Ignore:
Timestamp:
Nov 25, 2023, 11:47:52 PM (6 months ago)
Author:
chronos
Message:
  • Fixed: Assembler and disassembler to work correctly with supported instructions.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/ByteArray/Assembler.pas

    r56 r59  
    1414    RefPos: Integer;
    1515    TextPos: TPoint;
    16     class function Create(LabelName: string; RefPos: Integer): TLabelRef; static;
     16    class function Create(LabelName: string; RefPos: Integer; TextPos: TPoint): TLabelRef; static;
    1717  end;
    1818
     
    2323    FOnError: TErrorEvent;
    2424    Parser: TParser;
     25    InstDataWidth: TBigIntSize;
     26    InstAddressWidth: TBigIntSize;
    2527    function ParseVar: Boolean;
    2628    function ParseDb: Boolean;
    2729    function ParseOrg: Boolean;
    2830    function ParseInstruction: Boolean;
     31    function ParseInstructionParameter(ParamType: TParamType; Memory: TMemory): Boolean;
    2932    function ParseLabel: Boolean;
    3033    procedure UpdateLabelRefs;
    3134    function ParseNumParam(out Number: TBigInt): Boolean;
    3235    function ParseReg(out RegIndex: TRegIndex): Boolean;
     36    function ParseDataWidth(out Size: TBigIntSize): Boolean;
     37    function ParseAddressWidth(out Size: TBigIntSize): Boolean;
    3338  public
    34     InstructionSet: TInstructionSet;
     39    InstructionSet: TInstructionInfos;
    3540    Memory: TMemory;
    3641    Labels: TDictionary<string, TBigInt>;
     
    3843    Variables: TDictionary<string, TBigInt>;
    3944    Messages: TMessages;
     45    DataWidth: TBigIntSize;
     46    AddressWidth: TBigIntSize;
    4047    procedure Error(Text: string; Pos: TPoint);
    4148    procedure Compile(Source: string);
     
    5865  SExpectedVariableValue = 'Expected variable value.';
    5966  SUnsupportedParameterType = 'Unsupported parameter type';
     67  SDuplicateLabel = 'Duplicate label %s.';
     68  SLabelReferencedButNotDefined = 'Label %s referenced but not defined.';
     69  SDuplicateVariableName = 'Duplicate variable name %s';
     70  SExpectedParameter = 'Expected parameter';
     71  SExpectedParameterType = 'Expected parameter type [%s]';
     72  SExpectedNumberButFound = 'Expected number but %s found.';
    6073
    6174{ TLabelRef }
    6275
    63 class function TLabelRef.Create(LabelName: string; RefPos: Integer): TLabelRef;
     76class function TLabelRef.Create(LabelName: string; RefPos: Integer; TextPos: TPoint): TLabelRef;
    6477begin
    6578  Result.LabelName := LabelName;
    6679  Result.RefPos := RefPos;
     80  Result.TextPos := TextPos;
    6781end;
    6882
     
    7791    if Labels.TryGetValue(LabelRefs[I].LabelName, Addr) then
    7892      Memory.Write(LabelRefs[I].RefPos, 1, Addr)
    79       else Error('Label ' + LabelRefs[I].LabelName + ' referenced but not defined.', LabelRefs[I].TextPos);
     93      else Error(Format(SLabelReferencedButNotDefined, [LabelRefs[I].LabelName]),
     94        LabelRefs[I].TextPos);
    8095  end;
    8196end;
     
    8499var
    85100  Token: TToken;
    86 begin
     101  LastPos: TParserPos;
     102begin
     103  LastPos := Parser.Pos;
    87104  Result := False;
    88105  Token := Parser.ReadNext;
     
    99116      Result := True;
    100117    end else begin
    101       LabelRefs.Add(TLabelRef.Create(Token.Value, Memory.Position));
     118      LabelRefs.Add(TLabelRef.Create(Token.Value, Memory.Position + 1, Parser.Pos.Pos));
    102119      Number := 0;
    103120      Result := True;
    104121    end;
    105   end else Error('Unexpected token ' + Token.Value + '.', Token.Pos);
     122  end;
     123  if not Result then Parser.Pos := LastPos;
    106124end;
    107125
     
    110128  LastPos: TParserPos;
    111129  Token: TToken;
     130  Index: Integer;
    112131begin
    113132  Result := False;
    114133  LastPos := Parser.Pos;
    115134  Token := Parser.ReadNext;
    116   if (Length(Token.Value) = 1) and (Token.Value[1] in ['A'..'H']) then begin
    117     RegIndex := TRegIndex(Ord(Token.Value[1]) - Ord('A'));
    118     Result := True;
    119   end else Parser.Pos := LastPos;
     135  if (Length(Token.Value) >= 2) and (Token.Value[1] = 'R') then begin
     136    if TryStrToInt(Copy(Token.Value, 2, MaxInt), Index) then begin
     137      RegIndex := Index;
     138      Result := True;
     139    end;
     140  end;
     141  if not Result then Parser.Pos := LastPos;
     142end;
     143
     144function TAssembler.ParseDataWidth(out Size: TBigIntSize): Boolean;
     145var
     146  LastPos: TParserPos;
     147  Token: TToken;
     148  Index: Integer;
     149begin
     150  Result := False;
     151  LastPos := Parser.Pos;
     152  Token := Parser.ReadNext;
     153  if (Length(Token.Value) >= 2) and (Token.Value[1] = 'D') then begin
     154    if TryStrToInt(Copy(Token.Value, 2, MaxInt), Index) then begin
     155      Size := Index;
     156      Result := True;
     157    end;
     158  end;
     159  if not Result then Parser.Pos := LastPos;
     160end;
     161
     162function TAssembler.ParseAddressWidth(out Size: TBigIntSize): Boolean;
     163var
     164  LastPos: TParserPos;
     165  Token: TToken;
     166  Index: Integer;
     167begin
     168  Result := False;
     169  LastPos := Parser.Pos;
     170  Token := Parser.ReadNext;
     171  if (Length(Token.Value) >= 2) and (Token.Value[1] = 'A') then begin
     172    if TryStrToInt(Copy(Token.Value, 2, MaxInt), Index) then begin
     173      Size := Index;
     174      Result := True;
     175    end;
     176  end;
     177  if not Result then Parser.Pos := LastPos;
    120178end;
    121179
     
    134192  Labels.Clear;
    135193  LabelRefs.Clear;
     194  Variables.Clear;
    136195  Parser.Reset;
    137196  Parser.Source := Source;
     
    172231            if TryStrToBigInt(TokenValue.Value, Number) then
    173232              Variables.Add(TokenName.Value, Number)
    174             else Error('Expected number', TokenValue.Pos);
    175           end else Error('Duplicate variable name ' + TokenName.Value, TokenName.Pos);
     233            else Error(SExpectedNumber, TokenValue.Pos);
     234          end else Error(Format(SDuplicateVariableName, [TokenName.Value]), TokenName.Pos);
    176235        end else Error(SExpectedVariableValue, TokenValue.Pos);
    177236      end else Error(SExpectedVariableName, TokenName.Pos);
     
    199258        if Token.Kind = tkString then begin
    200259          Memory.WriteStringPos(Token.Value);
    201         end else raise Exception.Create('Expected parameter');
     260        end else
     261        if Token.Kind = tkEof then
     262        else if Token.Kind = tkEol then
     263        else raise Exception.Create(SExpectedParameter);
    202264      end;
    203265      if Parser.CheckNextAndRead(tkSpecialSymbol, ',') then begin
     
    219281    if Token.Kind = tkNumber then begin
    220282      Memory.Position := StrToInt(Token.Value);
    221     end else Error('Expected number but ' + Token.Value + ' found.', Token.Pos);
     283    end else Error(Format(SExpectedNumberButFound, [Token.Value]), Token.Pos);
    222284  end;
    223285end;
     
    225287function TAssembler.ParseInstruction: Boolean;
    226288var
    227   InstructionInfo: TInstructionInfo;
     289  InstructionInfos: TInstructionInfos;
    228290  I: Integer;
    229291  Token: TToken;
    230292  LastPos: TParserPos;
     293  J: Integer;
     294  AllowedParams: set of TParamType;
     295  ParamType: TParamType;
     296  ParamOk: Boolean;
     297  LastMessagesCount: Integer;
     298  Text: string;
     299  EmptyParam: Boolean;
     300  InstructionMemory: TMemory;
     301  ParamMemory: TMemory;
     302begin
     303  Result := False;
     304  LastPos := Parser.Pos;
     305  Token := Parser.ReadNext;
     306  InstructionInfos := InstructionSet.SearchByNameMultiple(Token.Value);
     307  InstDataWidth := DataWidth;
     308  InstAddressWidth := AddressWidth;
     309  InstructionMemory := TMemory.Create;
     310  InstructionMemory.Grow := True;
     311  ParamMemory := TMemory.Create;
     312  ParamMemory.Grow := True;
     313  J := 0;
     314  if InstructionInfos.Count > 0 then
     315  repeat
     316    EmptyParam := False;
     317
     318    if J > 0 then
     319      Parser.Expect(tkSpecialSymbol, ',');
     320
     321    // Get allowed parameters
     322    AllowedParams := [];
     323    for I := 0 to InstructionInfos.Count - 1 do begin
     324      if Length(InstructionInfos[I].Params) > J then
     325        AllowedParams := AllowedParams + [InstructionInfos[I].Params[J]]
     326        else EmptyParam := True;
     327    end;
     328
     329    if AllowedParams <> [] then begin
     330      ParamOk := False;
     331      for ParamType := Low(TParamType) to High(TParamType) do begin
     332        if ParamType in AllowedParams then begin
     333          LastMessagesCount := Messages.Count;
     334          ParamMemory.Clear;
     335          if ParseInstructionParameter(ParamType, ParamMemory) and
     336            (LastMessagesCount = Messages.Count) then begin
     337            ParamOk := True;
     338            InstructionMemory.WriteMemoryPos(ParamMemory);
     339            Break;
     340          end else Messages.Count := LastMessagesCount;
     341        end;
     342      end;
     343      if not ParamOk then begin
     344        if EmptyParam then begin
     345          ParamType := ptNone;
     346        end else begin
     347          Text := '';
     348          for ParamType := Low(TParamType) to High(TParamType) do begin
     349            if ParamType in AllowedParams then begin
     350              if Text <> '' then Text := Text + ' or ';
     351              Text := Text + ParamTypeString[ParamType]
     352            end;
     353          end;
     354
     355          Error(Format(SExpectedParameterType, [Text]), Parser.Pos.Pos);
     356          Break;
     357        end;
     358      end;
     359    end;
     360
     361    // Remove not matching instruction infos
     362    for I := InstructionInfos.Count - 1 downto 0 do
     363      if (Length(InstructionInfos[I].Params) > J) and
     364        (InstructionInfos[I].Params[J] <> ParamType) then InstructionInfos.Delete(I);
     365
     366    if (InstructionInfos.Count = 1) and (J >= (Length(InstructionInfos[0].Params) - 1)) then begin
     367      Memory.WritePos(1, Byte(InstructionInfos[0].Instruction));
     368      Memory.WriteMemoryPos(InstructionMemory);
     369      Result := True;
     370      Break;
     371    end;
     372
     373    Inc(J);
     374  until False;
     375
     376  if not Result then Parser.Pos := LastPos;
     377  FreeAndNil(ParamMemory);
     378  FreeAndNil(InstructionMemory);
     379end;
     380
     381function TAssembler.ParseInstructionParameter(ParamType: TParamType; Memory: TMemory): Boolean;
     382var
     383  LastPos: TParserPos;
     384  I: Integer;
    231385  RegIndex: TRegIndex;
    232386  Number: TBigInt;
    233 begin
    234   Result := False;
    235   LastPos := Parser.Pos;
    236   Token := Parser.ReadNext;
    237   InstructionInfo := InstructionSet.SearchName(Token.Value);
    238   if Assigned(InstructionInfo) then begin
    239     Result := True;
    240     Memory.WritePos(1, Integer(InstructionInfo.Instruction));
    241     for I := 0 to Length(InstructionInfo.Params) - 1 do begin
    242       if I > 0 then
    243         Parser.Expect(tkSpecialSymbol, ',');
    244       if InstructionInfo.Params[I] = ptNumber then begin
    245         if ParseNumParam(Number) then Memory.WritePos(1, Number)
    246           else Error(SExpectedNumber, Token.Pos);
    247       end else
    248       if InstructionInfo.Params[I] = ptReg then begin
    249         if ParseReg(RegIndex) then Memory.WritePos(1, Byte(RegIndex))
    250           else Error(SExpectedRegisterName, Token.Pos);
    251       end else
    252       if InstructionInfo.Params[I] = ptRegIndirect then begin
    253         Parser.Expect(tkSpecialSymbol, '(');
    254         if ParseReg(RegIndex) then Memory.WritePos(1, Byte(RegIndex))
    255           else Error(SExpectedRegisterName, Token.Pos);
    256         Parser.Expect(tkSpecialSymbol, ')');
    257       end else
    258       if InstructionInfo.Params[I] = ptRegIndirectIndex then begin
    259         Parser.Expect(tkSpecialSymbol, '(');
    260         if ParseReg(RegIndex) then begin
    261           Memory.WritePos(1, Byte(RegIndex));
    262           Parser.Expect(tkSpecialSymbol, '+');
    263           Token := Parser.ReadNext;
    264           if ParseNumParam(Number) then Memory.WritePos(1, Number)
    265             else Error(SExpectedNumericIndex, Token.Pos);
    266         end else Error(SExpectedRegisterName, Token.Pos);
    267         Parser.Expect(tkSpecialSymbol, ')');
    268       end else Error(SUnsupportedParameterType, Token.Pos);
     387  Token: TToken;
     388begin
     389  LastPos := Parser.Pos;
     390  Result := True;
     391  case ParamType of
     392    ptData: begin
     393      if ParseNumParam(Number) then Memory.WritePos(InstDataWidth, Number)
     394        else begin
     395          Error(SExpectedNumber, Parser.Pos.Pos);
     396          Result := False;
     397        end;
     398    end;
     399    ptAddress: begin
     400      if ParseNumParam(Number) then Memory.WritePos(InstAddressWidth, Number)
     401        else begin
     402          Error(SExpectedNumber, Parser.Pos.Pos);
     403          Result := False;
     404        end;
     405    end;
     406    ptReg: begin
     407      if ParseReg(RegIndex) then Memory.WritePos(1, Byte(RegIndex))
     408        else begin
     409          Error(SExpectedRegisterName, Parser.Pos.Pos);
     410          Result := False;
     411        end;
     412    end;
     413    ptRegIndirect: begin
     414      if not Parser.Expect(tkSpecialSymbol, '(') then Result := False;
     415      if ParseReg(RegIndex) then Memory.WritePos(1, Byte(RegIndex))
     416        else begin
     417          Error(SExpectedRegisterName, Parser.Pos.Pos);
     418          Result := False;
     419        end;
     420      if not Parser.Expect(tkSpecialSymbol, ')') then Result := False;;
     421    end;
     422    ptRegIndirectIndex: begin
     423      if not Parser.Expect(tkSpecialSymbol, '(') then Result := False;
     424      if ParseReg(RegIndex) then begin
     425        Memory.WritePos(1, Byte(RegIndex));
     426        if not Parser.Expect(tkSpecialSymbol, '+') then Result := False;
     427        if ParseNumParam(Number) then Memory.WritePos(InstAddressWidth, Number)
     428          else begin
     429            Error(SExpectedNumericIndex, Parser.Pos.Pos);
     430            Result := False;
     431          end;
     432      end else begin
     433        Error(SExpectedRegisterName, Parser.Pos.Pos);
     434        Result := False;
     435      end;
     436      if not Parser.Expect(tkSpecialSymbol, ')') then Result := False;
     437    end;
     438    ptDataWidth: begin
     439      if ParseDataWidth(InstDataWidth) then begin
     440        Memory.WritePos(1, InstDataWidth)
     441      end else begin
     442        Error(SExpectedRegisterName, Parser.Pos.Pos);
     443        Result := False;
     444      end;
     445    end;
     446    ptAddressWidth: begin
     447      if ParseAddressWidth(InstAddressWidth) then begin
     448        Memory.WritePos(1, InstAddressWidth)
     449      end else begin
     450        Error(SExpectedRegisterName, Parser.Pos.Pos);
     451        Result := False;
     452      end;
     453    end;
     454    else begin
     455      Result := False;
     456      Error(SUnsupportedParameterType, Parser.Pos.Pos);
    269457    end;
    270458  end;
     
    285473    if not Labels.TryGetValue(Token.Value, Addr) then begin
    286474      Labels.Add(Token.Value, Memory.Position);
    287     end else Error('Duplicate label ' + Token.Value + '.', Token.Pos);
     475    end else Error(Format(SDuplicateLabel, [Token.Value]), Token.Pos);
    288476  end;
    289477  if not Result then Parser.Pos := LastPos;
     
    323511  Messages := TMessages.Create;
    324512  Memory := TMemory.Create;
    325   InstructionSet := TInstructionSet.Create;
     513  InstructionSet := TInstructionInfos.Create;
     514  InstructionSet.Init;
    326515  Labels := TDictionary<string, TBigInt>.Create;
    327516  LabelRefs := TList<TLabelRef>.Create;
Note: See TracChangeset for help on using the changeset viewer.