コード例 #1
0
ファイル: ParseEQUALS.c プロジェクト: avtobiff/virtualagc
int
FetchSymbolPlusOffset (Address_t *pc, char *Operand, char *Mod1,
                       Address_t *Value)
{
    Symbol_t *Symbol;
    int i, Offset;

    i = GetOctOrDec (Operand, &Offset);
    if (!i)
    {
        IncPc (pc, Offset, Value);
        return (0);
    }
    Value->Invalid = 1;
    Symbol = GetSymbol (Operand);
    if (Symbol == NULL)
        return (1);
    *Value = Symbol->Value;
    i = GetOctOrDec (Mod1, &Offset);
    if (!i)
    {
        //IncPc (&Symbol->Value, Offset, Value);
        OpcodeOffset = Offset;
        // I'm not sure how to treat very big offsets.  Empirically, this works.
        if (OpcodeOffset >= 0)
            OpcodeOffset &= 07777;
        else
            OpcodeOffset = -(07777 & -OpcodeOffset);
    }
    return (0);
}
コード例 #2
0
ファイル: ParseBLOCK.c プロジェクト: Bhagita/virtualagc
int 
ParseBLOCK(ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
  int Value, i;
  
  if (InRecord->Extend && !InRecord->IndexValid)
    {
      strcpy(OutRecord->ErrorMessage, "Illegally preceded by EXTEND.");
      OutRecord->Fatal = 1;
      OutRecord->Extend = 0;
    }

  if (InRecord->IndexValid)
    {
      strcpy(OutRecord->ErrorMessage, "Illegally preceded by INDEX.");
      OutRecord->Fatal = 1;
      OutRecord->Index = 0;
    }

  i = GetOctOrDec(InRecord->Operand, &Value);
  if (!i)
    {
      if (Value == 0 || Value == 2 || Value == 3)
        {
          Value = GetBankCount(Value) + Value * 02000;
          OutRecord->ProgramCounter = (const Address_t) { 0 };
          OutRecord->ProgramCounter.Address = 1;
          OutRecord->ProgramCounter.SReg = Value;

          if (Value == 0)
              OutRecord->ProgramCounter.Erasable = 1;
          else
              OutRecord->ProgramCounter.Fixed = 1;  

          OutRecord->ProgramCounter.Unbanked = 1;
          OutRecord->ProgramCounter.Value = Value;

          if (Value == 0)
              OutRecord->EBank.current = OutRecord->ProgramCounter;
        }
      else
        {
          strcpy(OutRecord->ErrorMessage, "BLOCK operand must be 0, 2, or 3.");
          OutRecord->ProgramCounter = (const Address_t) { 0 };
          OutRecord->ProgramCounter.Invalid = 1;
        }
    } 
  else 
    {  
コード例 #3
0
ファイル: ParseINDEX.c プロジェクト: Bhagita/virtualagc
//------------------------------------------------------------------------
// Return non-zero on unrecoverable error.
int ParseINDEX(ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
  Address_t Offset;
  int Value, i;
  //extern int KeepExtend;
  
  //KeepExtend = 1;
  OutRecord->Extend = InRecord->Extend;
  IncPc(&InRecord->ProgramCounter, 1, &OutRecord->ProgramCounter);
  if (!OutRecord->ProgramCounter.Invalid && OutRecord->ProgramCounter.Overflow)
    {
      strcpy(OutRecord->ErrorMessage, "Next code may overflow storage.");
      OutRecord->Warning = 1;
    }

  OutRecord->EBank = InRecord->EBank;
  OutRecord->SBank = InRecord->SBank;
  OutRecord->NumWords = 1;
  OutRecord->IndexValid = 1;

  i = GetOctOrDec(InRecord->Operand, &Value);
  if (!i)
    {
      if (*InRecord->Operand == '+' || *InRecord->Operand == '-')
	  IncPc(&InRecord->ProgramCounter, Value, &Offset);
      else
          PseudoToStruct(Value, &Offset);
	
       if (*InRecord->Mod1 != 0)
         {
	   i = GetOctOrDec(InRecord->Mod1, &Value);
	   if (!i)
	     OpcodeOffset = Value;
	 }
      
    DoIt:  
      if (!Offset.Address && !Offset.Constant)
        {
	  strcpy(OutRecord->ErrorMessage, "Index is not an address.");
	  Offset.SReg = 0;
	  OutRecord->Fatal = 1;
	}

      if ((InRecord->Extend && (Offset.SReg & ~07777)) || (!InRecord->Extend && (Offset.SReg & ~01777)))
        {
	  strcpy(OutRecord->ErrorMessage, "Index is out of range.");
	  Offset.SReg = 0;
	  OutRecord->Fatal = 1;
	}

      if (Offset.Constant)
        OutRecord->Words[0] = OPCODE + Offset.Value;
      else
        OutRecord->Words[0] = OPCODE + Offset.SReg;
    }
  else
    {
      // The operand is NOT a number.  Presumably, it's a symbol.
      i = FetchSymbolPlusOffset(&InRecord->ProgramCounter, InRecord->Operand, InRecord->Mod1, &Offset);
      if (!i)
        goto DoIt;
      sprintf(OutRecord->ErrorMessage, "Symbol \"%s\" undefined or offset bad", InRecord->Operand);
      OutRecord->Fatal = 1;
      OutRecord->Words[0] = OPCODE;
    }

  if (OutRecord->Words[0] == 050017)
    OutRecord->IndexValid = 0;

  return (0);  
}
コード例 #4
0
ファイル: ParseERASE.c プロジェクト: ayhanozemre/virtualagc
int 
ParseERASE (ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
  int Value, i;
  IncPc (&InRecord->ProgramCounter, 1, &OutRecord->ProgramCounter);
  if (!OutRecord->ProgramCounter.Invalid && OutRecord->ProgramCounter.Overflow)
    {
      strcpy (OutRecord->ErrorMessage, "Next code may overflow storage.");
      OutRecord->Warning = 1;
    }
  OutRecord->Bank = InRecord->Bank;
  if (InRecord->Extend && !InRecord->IndexValid)
    {
      strcpy (OutRecord->ErrorMessage, "Illegally preceded by EXTEND.");
      OutRecord->Fatal = 1;
      OutRecord->Extend = 0;
    }
  if (InRecord->IndexValid)
    {
      strcpy (OutRecord->ErrorMessage, "Illegally preceded by INDEX.");
      OutRecord->Fatal = 1;
      OutRecord->IndexValid = 0;
    }
  i = GetOctOrDec (InRecord->Operand, &Value);
  if (!i)
    {
      if (Value < 0)
        {
	  strcpy (OutRecord->ErrorMessage, "Address increment is negative.");
	  OutRecord->Warning = 1;
	}	
      else
        {
	  // There are really two cases here.  Normally, the operand is
	  // simply a number, and that's the end of it.  But it's also
	  // possible that Mod1 is "-", and Mod2 is another number, in 
	  // which case we want to allocate a range.
	  if (!strcmp (InRecord->Mod1, "-"))
	    {
#if 0
	      // This is the range case, "ERASE n - m".
	      i = GetOctOrDec (InRecord->Mod2, &Value2);
	      Value2++;
	      if (i)
	        {
		  strcpy (OutRecord->ErrorMessage, "End of range missing or illegal.");
		  OutRecord->Fatal = 1;
		}
	      else if (Value2 <= Value)
	        {
		  strcpy (OutRecord->ErrorMessage, "Ending address precedes starting address.");
		  OutRecord->Fatal = 1;
		}	
	      else
	        {
		  ParseOutput_t Dummy = { { 0 } }, Dummy2 = { { 0 } };
		  PseudoToSegmented (Value, &Dummy);
		  PseudoToSegmented (Value2, &Dummy2);
		  if (Dummy.Fatal || Dummy.Warning || Dummy2.Fatal || Dummy2.Warning
		      || Dummy.ProgramCounter.Invalid || !Dummy.ProgramCounter.Erasable
		      || Dummy2.ProgramCounter.Invalid || !Dummy2.ProgramCounter.Erasable
		      || Dummy.ProgramCounter.Banked != Dummy2.ProgramCounter.Banked
		      || Dummy.ProgramCounter.EB != Dummy2.ProgramCounter.EB)
		    {
		      strcpy (OutRecord->ErrorMessage, "May span bank boundary.");
		      OutRecord->Warning = 1;
		    }
		  InRecord->ProgramCounter = Dummy.ProgramCounter;
		  OutRecord->ProgramCounter = Dummy2.ProgramCounter;
		}
#else // 0
  		  char Mod1[1 + MAX_LINE_LENGTH], Mod2[1 + MAX_LINE_LENGTH];
		  strcpy (Mod1, InRecord->Mod1);
		  strcpy (Mod2, InRecord->Mod2);
		  strcpy (InRecord->Mod1, "");
		  strcpy (InRecord->Mod2, "");  
		  strcpy (InRecord->Operator, "EQUALS");            
		  ParseEQUALS (InRecord, OutRecord);
		  strcpy (InRecord->Mod1, Mod1);
		  strcpy (InRecord->Mod2, Mod2);
		  strcpy (InRecord->Operator, "ERASE");
#endif // 0
	    }
	  else
	    {  
	      // This is the normal case, "ERASE n".
	      if (0 != *InRecord->Mod1 && !OutRecord->Fatal)
	        {
		  strcpy (OutRecord->ErrorMessage, "Extra fields are present.");
		  OutRecord->Warning = 1;
		}
	      IncPc (&InRecord->ProgramCounter, 1 + Value, &OutRecord->ProgramCounter);
	      if (!OutRecord->ProgramCounter.Invalid)
		{
		  if (!OutRecord->ProgramCounter.Erasable)
		    {
		      strcpy (OutRecord->ErrorMessage, "Not in erasable memory.");
		      OutRecord->Fatal = 1;
		    }
		  else if (OutRecord->ProgramCounter.Overflow)
		    {
		      strcpy (OutRecord->ErrorMessage, "May overflow memory bank.");
		      OutRecord->Warning = 1;
		    }
		}
	    }
	}
    }
  else if (0 != *InRecord->Operand)
    {
      // Note that if the Operand field is simply missing, it's legal.
      strcpy (OutRecord->ErrorMessage, "Illegal number.");
      OutRecord->Fatal = 1;
    }  
  return (0);  
}
コード例 #5
0
ファイル: ParseBBCON.c プロジェクト: ayhanozemre/virtualagc
int
ParseBBCON (ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
  Address_t Address, EBank;
  int Value, i;
  IncPc (&InRecord->ProgramCounter, 1, &OutRecord->ProgramCounter);
  if (!OutRecord->ProgramCounter.Invalid && OutRecord->ProgramCounter.Overflow)
    {
      strcpy (OutRecord->ErrorMessage, "Next code may overflow storage.");
      OutRecord->Warning = 1;
    }
  OutRecord->Bank = InRecord->Bank;
  OutRecord->NumWords = 1;
  OutRecord->Words[0] = 0;
  if (InRecord->Extend && !InRecord->IndexValid)
    {
      strcpy (OutRecord->ErrorMessage, "Illegally preceded by EXTEND.");
      OutRecord->Fatal = 1;
      OutRecord->Extend = 0;
    }
  if (InRecord->IndexValid)
    {
      strcpy (OutRecord->ErrorMessage, "Illegally preceded by INDEX.");
      OutRecord->Fatal = 1;
      OutRecord->IndexValid = 0;
    }
  #ifdef ORIGINAL_SBANK_SURMISE
  if (!strcmp (InRecord->Operator, "BBCON*"))
    {
      OutRecord->Words[0] = 066100;
      OutRecord->Bank.CurrentSBank.Super = 1;
      return (0);
    }
  #endif
  i = GetOctOrDec (InRecord->Operand, &Value);
  if (!i && *InRecord->Mod1 == 0)
    {
      IncPc (&InRecord->ProgramCounter, Value, &Address);
    DoIt:  
      if (Address.Invalid)
        {
	  strcpy (OutRecord->ErrorMessage, "Destination address not resolved.");
	  OutRecord->Fatal = 1;
	  return (0);
	}
      if (!Address.Address)
        {
	  strcpy (OutRecord->ErrorMessage, "Destination is not a memory address.");
	  OutRecord->Fatal = 1;
	  return (0);
	}
      if (!Address.Fixed)
        {
	  strcpy (OutRecord->ErrorMessage, "Destination is not in fixed memory.");
	  OutRecord->Fatal = 1;
	  return (0);
	}	
      if (Address.SReg < 02000 || Address.SReg > 07777)
        {
	  strcpy (OutRecord->ErrorMessage, "Destination address out of range.");
	  OutRecord->Fatal = 1;
	  return (0);
	}	
      //printf ("PC=%o EB=%o,%o FB=%o SReg=%o Super=%o,%o ", 
      //        InRecord->ProgramCounter.SReg, Address.EB, InRecord->Bank.CurrentEBank.EB,
      //      Address.FB, Address.SReg,
      //      Address.Super, InRecord->Bank.CurrentSBank.Super);
      if (!Address.Banked)
        Address.Value = Address.SReg / 02000;
      else 
        Address.Value = Address.FB;
      EBank = InRecord->Bank.CurrentEBank;
      if (EBank.SReg >= 0 && EBank.SReg < 01400)
        EBank.EB = EBank.SReg / 0400;
      Address.Value = (Address.Value << 10) | EBank.EB;
      // Superbank processing.
      FixSuperbankBits (InRecord, &Address, &Address.Value);
      OutRecord->Words[0] = Address.Value;	
    }
  else
    {
      // The operand is NOT a number.  Presumably, it's a symbol.
      i = FetchSymbolPlusOffset (&InRecord->ProgramCounter, 
                                 InRecord->Operand, 
				 InRecord->Mod1, &Address);
      if (!i)
        goto DoIt;
      sprintf(OutRecord->ErrorMessage, "Symbol \"%s\" undefined or offset bad", InRecord->Operand);
      OutRecord->Fatal = 1;
    }
  return (0);  
}
コード例 #6
0
ファイル: ParseEQUALS.c プロジェクト: avtobiff/virtualagc
int
ParseEQUALS (ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
    Address_t LabelValue = { 1 };
    int Value, i;
    OutRecord->ProgramCounter = InRecord->ProgramCounter;
    OutRecord->Bank = InRecord->Bank;
    OutRecord->LabelValue.Invalid = 1;
    OutRecord->NumWords = 0;
    OutRecord->Equals = 1;
    // As a special case, it sometimes happens that the label is empty.
    // I *believe* that this is done only for documentation purposes, and
    // has no other effect.
    if (*InRecord->Label == 0)
    {
        OutRecord->LabelValueValid = 0;
        return (0);
    }
    // As another special case, there is sometimes no operand.  *That* means
    // that the current program counter is the value.
    if (*InRecord->Operand == 0 && *InRecord->Mod1 == 0)
    {
        // JMS: Even though it is assigned the program counter as the current
        // value, it is still just a constant
        //EditSymbol (InRecord->Label, &InRecord->ProgramCounter);
        EditSymbolNew (InRecord->Label, &InRecord->ProgramCounter, SYMBOL_CONSTANT,
                       CurrentFilename, CurrentLineInFile);
        OutRecord->LabelValue = InRecord->ProgramCounter;
        return (0);
    }
    // Next, it may be that the operand is simply a number.  If so, then
    // we're talking about a simple constant.
    i = GetOctOrDec (InRecord->Operand, &Value);
    if (i)
    {
        // The operand is NOT a number.  Presumably, it's a symbol.
        i = FetchSymbolPlusOffset (&InRecord->ProgramCounter,
                                   InRecord->Operand,
                                   InRecord->Mod1, &LabelValue);
        if (i)
        {
            sprintf(OutRecord->ErrorMessage, "Symbol \"%s\" undefined or offset bad", InRecord->Operand);
            OutRecord->Fatal = 1;
            return (0);
        }
#if 0
        if (!i)
        {
            LabelValue = CONSTANT (0);
            LabelValue.Value = Value;
            EditSymbol (InRecord->Label, &LabelValue);
        }
#endif
        if (OpcodeOffset)
        {
            if (LabelValue.Constant)
            {
                LabelValue.Value += OpcodeOffset;
            }
            else
                IncPc (&LabelValue, OpcodeOffset, &LabelValue);
        }

        // JMS: This is just a constant to add to the symbol table
        //EditSymbol (InRecord->Label, &LabelValue);
        EditSymbolNew (InRecord->Label, &LabelValue, SYMBOL_CONSTANT,
                       CurrentFilename, CurrentLineInFile);
        OutRecord->LabelValueValid = 1;
    }
    else
    {
        ParseOutput_t TempOutput;
        if (*InRecord->Operand == '+' || *InRecord->Operand == '-')
        {
            IncPc (&InRecord->ProgramCounter, Value, &LabelValue);
        }
        else
        {
            if (Value < -16383 || Value > 32767)
            {
                strcpy (OutRecord->ErrorMessage, "Value out of range---truncating");
                OutRecord->Warning = 1;
                if (Value < -16383)
                    Value = -16383;
                else if (Value > 32767)
                    Value = 32767;
            }
            LabelValue.Invalid = 0;
            LabelValue.Constant = 1;
            LabelValue.Value = Value;
            PseudoToSegmented (Value, &TempOutput);
        }

        // JMS: This is just a constant to add to the symbol table
        //EditSymbol (InRecord->Label, &LabelValue /*&TempOutput.ProgramCounter*/);
        EditSymbolNew (InRecord->Label, &LabelValue, SYMBOL_CONSTANT,
                       CurrentFilename, CurrentLineInFile);
    }
    OutRecord->LabelValue = LabelValue;
    return (0);
}
コード例 #7
0
ファイル: ParseEBANKEquals.c プロジェクト: Bhagita/virtualagc
//-------------------------------------------------------------------------
// Returns non-zero on unrecoverable error.
int ParseEBANKEquals(ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
    ParseOutput_t Dummy;
    Address_t Address;
    int Value, i;

    OutRecord->Extend = InRecord->Extend;
    OutRecord->IndexValid = InRecord->IndexValid;
    OutRecord->EBank = InRecord->EBank;
    OutRecord->SBank = InRecord->SBank;
    OutRecord->NumWords = 0;
    OutRecord->ProgramCounter = InRecord->ProgramCounter;

    if (*InRecord->Mod1) {
        strcpy(OutRecord->ErrorMessage, "Extra fields.");
        OutRecord->Warning = 1;
    }

    i = GetOctOrDec(InRecord->Operand, &Value);
    if (!i) {
        PseudoToSegmented(Value, &Dummy);
        Address = Dummy.ProgramCounter;

        DoIt:
        if (Address.Invalid) {
            strcpy(OutRecord->ErrorMessage, "Destination address not resolved.");
            OutRecord->Fatal = 1;
            return (0);
        }

        if (!Address.Erasable) {
            strcpy(OutRecord->ErrorMessage, "Destination not erasable.");
            OutRecord->Fatal = 1;
            return (0);
        }

        if (Address.SReg < 0 || Address.SReg > 01777) {
            strcpy(OutRecord->ErrorMessage, "Destination address out of range.");
            OutRecord->Fatal = 1;
            return (0);
        }

        OutRecord->EBank.last = OutRecord->EBank.current;
        OutRecord->EBank.current = Address;
        OutRecord->EBank.oneshotPending = 1;
        OutRecord->LabelValue = Address;
        OutRecord->LabelValueValid = 1;
    } else {
        // The operand is NOT a number.  Presumably, it's a symbol.
        i = FetchSymbolPlusOffset(&InRecord->ProgramCounter, InRecord->Operand, "", &Address);
        if (!i) {
            IncPc(&Address, OpcodeOffset, &Address);
            goto DoIt;
        }

        sprintf(OutRecord->ErrorMessage, "Symbol \"%s\" undefined or offset bad", InRecord->Operand);
        OutRecord->Fatal = 1;
    }

#ifdef YAYUL_TRACE
    PrintTrace(InRecord, OutRecord);
#endif

    return (0);
}
コード例 #8
0
ファイル: ParseCADR.c プロジェクト: ayhanozemre/virtualagc
int
ParseCADR (ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
  Address_t Address;
  int Value, i;
  IncPc (&InRecord->ProgramCounter, 1, &OutRecord->ProgramCounter);
  if (!OutRecord->ProgramCounter.Invalid && OutRecord->ProgramCounter.Overflow)
    {
      strcpy (OutRecord->ErrorMessage, "Next code may overflow storage.");
      OutRecord->Warning = 1;
    }
  OutRecord->Bank = InRecord->Bank;
  OutRecord->NumWords = 1;
  OutRecord->Words[0] = 0;
  if (InRecord->Extend && !InRecord->IndexValid)
    {
      strcpy (OutRecord->ErrorMessage, "Illegally preceded by EXTEND.");
      OutRecord->Fatal = 1;
      OutRecord->Extend = 0;
    }
  if (InRecord->IndexValid)
    {
      strcpy (OutRecord->ErrorMessage, "Illegally preceded by INDEX.");
      OutRecord->Fatal = 1;
      OutRecord->IndexValid = 0;
    }
  i = GetOctOrDec (InRecord->Operand, &Value);
  if (!i && *InRecord->Mod1 == 0)
    {
      IncPc (&InRecord->ProgramCounter, Value, &Address);
    DoIt:  
      if (Address.Invalid)
        {
	  strcpy (OutRecord->ErrorMessage, "Destination address not resolved.");
	  OutRecord->Fatal = 1;
	  return (0);
	}
      if (!Address.Address)
        {
	  strcpy (OutRecord->ErrorMessage, "Destination is not a memory address.");
	  OutRecord->Fatal = 1;
	  return (0);
	}
      if (!Address.Fixed || !Address.Banked)
        {
	  strcpy (OutRecord->ErrorMessage, "Destination not in an F-bank.");
	  OutRecord->Fatal = 1;
	  return (0);
	}	
      // If this is a superbank, we massage a little more to get into the 15-bit
      // address range.
      if (Address.Super && Address.FB >= 030)
        Address.Value -= 010 * 02000;
      if (Address.Value < 010000 || Address.Value > 0107777)
        {
	  strcpy (OutRecord->ErrorMessage, "Destination address out of range.");
	  OutRecord->Fatal = 1;
	  return (0);
	}	
      OutRecord->Words[0] = Address.Value - 010000;	
    }
  else
    {
      // The operand is NOT a number.  Presumably, it's a symbol.
      i = FetchSymbolPlusOffset (&InRecord->ProgramCounter, 
                                 InRecord->Operand, 
				 InRecord->Mod1, &Address);
      if (!i)
        goto DoIt;
      sprintf(OutRecord->ErrorMessage, "Symbol \"%s\" undefined or offset bad", InRecord->Operand);
      OutRecord->Fatal = 1;
    }
  return (0);  
}
コード例 #9
0
ファイル: ParseEQUALS.c プロジェクト: Bhagita/virtualagc
int ParseEQUALS(ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
  Address_t LabelValue = { 1 };
  int Value, i;

  OutRecord->ProgramCounter = InRecord->ProgramCounter;
  OutRecord->EBank = InRecord->EBank;
  OutRecord->SBank = InRecord->SBank;
  OutRecord->LabelValue.Invalid = 1;
  OutRecord->NumWords = 0;
  OutRecord->Equals = 1;

  // As a special case, it sometimes happens that the label is empty.
  // I *believe* that this is done only for documentation purposes, and
  // has no other effect.
  if (*InRecord->Label == 0)
    {
      OutRecord->LabelValueValid = 0;
      return (0);
    }

  // As another special case, there is sometimes no operand.  *That* means
  // that the current program counter is the value.  
  if (*InRecord->Operand == 0 && *InRecord->Mod1 == 0)
    {
      EditSymbolNew(InRecord->Label, &InRecord->ProgramCounter, SYMBOL_CONSTANT,
                    CurrentFilename, CurrentLineInFile);
      OutRecord->LabelValue = InRecord->ProgramCounter;
      return (0);
    }

  i = GetOctOrDec(InRecord->Operand, &Value);
  if (i)
    {
      // The operand is NOT a number.  Presumably, it's a symbol.
      if (!strcmp(InRecord->Mod1, "+") || !strcmp(InRecord->Mod1, "-"))
      {
          // Handle the case of whitespace between +/- and the actual offset. 
          if (*InRecord->Mod2 != 0)
          {
              char mod[1 + MAX_LINE_LENGTH];

              strcpy(mod, InRecord->Mod1);
              strcat(mod, InRecord->Mod2);
              i = FetchSymbolPlusOffset(&InRecord->ProgramCounter, 
                                        InRecord->Operand, 
                                        mod, 
                                        &LabelValue);
          }
          else
          {
              sprintf(OutRecord->ErrorMessage, "Syntax error, invalid offset specified");
              OutRecord->Fatal = 1;
              return(0);
          }
      }
      else
      {
          i = FetchSymbolPlusOffset(&InRecord->ProgramCounter, 
                                    InRecord->Operand, 
                                    InRecord->Mod1, 
                                    &LabelValue);
      }

      if (i)
      {
          sprintf(OutRecord->ErrorMessage, "Symbol \"%s\" undefined or offset bad", InRecord->Operand);
          OutRecord->Fatal = 1;
          return(0);
      }

      if (OpcodeOffset)
        {
          if (LabelValue.Constant)
            {
              LabelValue.Value += OpcodeOffset;
            }
          else
            IncPc(&LabelValue, OpcodeOffset, &LabelValue);
        }

      EditSymbolNew(InRecord->Label, &LabelValue, SYMBOL_CONSTANT, CurrentFilename, CurrentLineInFile);
      OutRecord->LabelValueValid = 1;
    }
  else
    {
      // Next, it may be that the operand is simply a number.  If so, then
      // we're talking about a simple constant.  

      ParseOutput_t TempOutput;

      if (*InRecord->Operand == '+' || *InRecord->Operand == '-')
        {
          IncPc(&InRecord->ProgramCounter, Value, &LabelValue);
        }
      else
        {
          if (Value < -16383 || Value > 32767)
            {
              strcpy(OutRecord->ErrorMessage, "Value out of range---truncating");
              OutRecord->Warning = 1;
              if (Value < -16383)
                Value = -16383;
              else if (Value > 32767)
                Value = 32767;  
            }

          LabelValue.Invalid = 0;
          LabelValue.Constant = 1;
          LabelValue.Value = Value;

          PseudoToSegmented(Value, &TempOutput);

          if (!TempOutput.ProgramCounter.Invalid)
            {
              LabelValue = TempOutput.ProgramCounter;
              if (!strcmp(InRecord->Operator, "ERASE"))
                {
                  // Special case. This is to handle "ERASE start - end" constructs, 
                  // which should not be tagged as constants.
                  LabelValue.Constant = 0;
                }
              else
                {
                  // Otherwise mark it as a constant as well.
                  LabelValue.Constant = 1;
                }
            }
        }

      EditSymbolNew(InRecord->Label, &LabelValue, SYMBOL_CONSTANT, CurrentFilename, CurrentLineInFile);
    }

  OutRecord->LabelValue = LabelValue;

  return (0);  
}
コード例 #10
0
ファイル: ParseBANK.c プロジェクト: jimlawton/virtualagc-1
int 
ParseBANK(ParseInput_t *InRecord, ParseOutput_t *OutRecord)
{
    int Value, i;

    // Pass EXTEND through.
    OutRecord->Extend = InRecord->Extend;

    if (InRecord->IndexValid) {
        strcpy(OutRecord->ErrorMessage, "Illegally preceded by INDEX.");
        OutRecord->Fatal = 1;
        OutRecord->Index = 0;
    }

    // The case of no Operand has a special meaning.  It means simply to
    // advance the program counter by however many words have already
    // been used in the current bank.  It would be used after a SETLOC.
    if (!*InRecord->Operand) {
        OutRecord->ProgramCounter = InRecord->ProgramCounter;

        if (OutRecord->ProgramCounter.Invalid)
            return (0);

        if (!OutRecord->ProgramCounter.Address || !OutRecord->ProgramCounter.Fixed) {
            strcpy(OutRecord->ErrorMessage, "Works only for fixed-memory.");
            OutRecord->Fatal = 1;
            return (0);
        }

        if (OutRecord->ProgramCounter.Banked) {
            i = OutRecord->ProgramCounter.FB + 010 * OutRecord->ProgramCounter.Super;
            OutRecord->ProgramCounter.SReg = 02000 + UsedInBank[i];
            OutRecord->ProgramCounter.Value = 010000 + i * 02000 + UsedInBank[i];
        } else if (OutRecord->ProgramCounter.Value >= 04000 && OutRecord->ProgramCounter.Value <= 05777) {
            OutRecord->ProgramCounter.SReg = 04000 + UsedInBank[2];
            OutRecord->ProgramCounter.Value = OutRecord->ProgramCounter.SReg;
        } else if (OutRecord->ProgramCounter.Value >= 06000 && OutRecord->ProgramCounter.Value <= 07777) {
            OutRecord->ProgramCounter.SReg = 06000 + UsedInBank[3];
            OutRecord->ProgramCounter.Value = OutRecord->ProgramCounter.SReg;
        }

#ifdef YAYUL_TRACE
        PrintTrace(InRecord, OutRecord);
#endif

        return (0);
    }

    // Here's where we assume that an Operand field exists.
    i = GetOctOrDec(InRecord->Operand, &Value);
    if (!i) {
        if (Value >= 0 && Value <= 043) {
            OutRecord->ProgramCounter = (const Address_t) { 0 };
            OutRecord->ProgramCounter.Address = 1;
            OutRecord->ProgramCounter.SReg = 02000;
            OutRecord->ProgramCounter.Fixed = 1;
            OutRecord->ProgramCounter.Banked = 1;

            if (Value >= 040) {
                OutRecord->ProgramCounter.Super = 1;
                OutRecord->ProgramCounter.FB = Value - 010;
            } else {
                OutRecord->ProgramCounter.Super = 0;
                OutRecord->ProgramCounter.FB = Value;
            }

            if (Block1 && Value >= 0 && Value <= 2)
              {
                OutRecord->ProgramCounter.Value = 02000 * Value;
                OutRecord->ProgramCounter.SReg = 02000 * Value;
                OutRecord->ProgramCounter.Banked = 0;
                OutRecord->ProgramCounter.Unbanked = 1;
              }
            else if (Block1)
              {
                OutRecord->ProgramCounter.Value = 06000;
                OutRecord->ProgramCounter.SReg = 06000;
              }
            else if (Value == 2 || Value == 3)
                OutRecord->ProgramCounter.Value = Value * 02000;
            else
                OutRecord->ProgramCounter.Value = 010000 + Value * 02000;

            OutRecord->ProgramCounter.Value += UsedInBank[Value];
            OutRecord->ProgramCounter.SReg += UsedInBank[Value];
        } else {
            strcpy(OutRecord->ErrorMessage, "BANK operand range is 00 to 43.");
            OutRecord->Fatal = 1;
            OutRecord->ProgramCounter = (const Address_t) { 0 };
            OutRecord->ProgramCounter.Invalid = 1;
        }
    } else {