Changeset 184


Ignore:
Timestamp:
Apr 25, 2019, 4:20:43 PM (5 years ago)
Author:
chronos
Message:
  • Added: Basic assembler window.
Location:
branches/virtualcpu4
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • branches/virtualcpu4/Forms/UFormDisassembler.lfm

    r181 r184  
    11object FormDisassembler: TFormDisassembler
    2   Left = 687
    3   Height = 691
    4   Top = 416
    5   Width = 721
     2  Left = 587
     3  Height = 576
     4  Top = 248
     5  Width = 601
    66  Caption = 'Disassembler'
    7   ClientHeight = 691
    8   ClientWidth = 721
    9   DesignTimePPI = 144
     7  ClientHeight = 576
     8  ClientWidth = 601
     9  DesignTimePPI = 120
    1010  OnCreate = FormCreate
    1111  OnDestroy = FormDestroy
    12   LCLVersion = '2.0.0.4'
     12  OnShow = FormShow
     13  LCLVersion = '2.0.2.0'
    1314  object ListView1: TListView
    14     Left = 8
    15     Height = 675
    16     Top = 8
    17     Width = 705
    18     Align = alClient
    19     BorderSpacing.Around = 8
     15    Left = 7
     16    Height = 521
     17    Top = 7
     18    Width = 587
     19    Align = alCustom
     20    Anchors = [akTop, akLeft, akRight, akBottom]
     21    BorderSpacing.Around = 7
    2022    Columns = <   
    2123      item
    2224        Caption = 'Address'
    23         Width = 100
     25        Width = 83
    2426      end   
    2527      item
    2628        Caption = 'Opcode'
    27         Width = 150
     29        Width = 125
    2830      end   
    2931      item
    3032        Caption = 'Assembly'
    31         Width = 440
     33        Width = 367
    3234      end>
    3335    OwnerData = True
     36    ParentFont = False
    3437    ReadOnly = True
    3538    RowSelect = True
     
    3841    OnData = ListView1Data
    3942  end
     43  object ButtonReload: TButton
     44    Left = 7
     45    Height = 31
     46    Top = 536
     47    Width = 94
     48    Anchors = [akLeft, akBottom]
     49    Caption = 'Reload'
     50    OnClick = ButtonReloadClick
     51    TabOrder = 1
     52  end
    4053end
  • branches/virtualcpu4/Forms/UFormDisassembler.pas

    r181 r184  
    66
    77uses
    8   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls,
     8  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls,
    99  UDisassembler;
    1010
     
    1414
    1515  TFormDisassembler = class(TForm)
     16    ButtonReload: TButton;
    1617    ListView1: TListView;
     18    procedure ButtonReloadClick(Sender: TObject);
    1719    procedure FormCreate(Sender: TObject);
    1820    procedure FormDestroy(Sender: TObject);
     21    procedure FormShow(Sender: TObject);
    1922    procedure ListView1Data(Sender: TObject; Item: TListItem);
    2023  private
     
    3942end;
    4043
     44procedure TFormDisassembler.ButtonReloadClick(Sender: TObject);
     45begin
     46  Disassembler.Process;
     47  Reload;
     48end;
     49
    4150procedure TFormDisassembler.FormDestroy(Sender: TObject);
    4251begin
    4352  Disassembler.Free;
     53end;
     54
     55procedure TFormDisassembler.FormShow(Sender: TObject);
     56begin
     57  ButtonReload.Click;
    4458end;
    4559
  • branches/virtualcpu4/Forms/UFormMain.lfm

    r183 r184  
    8282    TabOrder = 6
    8383  end
     84  object ButtonAssembler: TButton
     85    Left = 309
     86    Height = 32
     87    Top = 128
     88    Width = 154
     89    Caption = 'Assembler'
     90    OnClick = ButtonAssemblerClick
     91    ParentFont = False
     92    TabOrder = 7
     93  end
    8494end
  • branches/virtualcpu4/Forms/UFormMain.pas

    r183 r184  
    1414
    1515  TFormMain = class(TForm)
     16    ButtonAssembler: TButton;
    1617    ButtonScreen: TButton;
    1718    ButtonDisassembler: TButton;
     
    2122    ButtonStart: TButton;
    2223    ButtonStop: TButton;
     24    procedure ButtonAssemblerClick(Sender: TObject);
    2325    procedure ButtonConsoleClick(Sender: TObject);
    2426    procedure ButtonCpuStateClick(Sender: TObject);
     
    4749
    4850uses
    49   UFormDisassembler, UFormMemory, UFormCpuState, UFormScreen, UFormConsole;
     51  UFormDisassembler, UFormMemory, UFormCpuState, UFormScreen, UFormConsole,
     52  UFormAssembler;
    5053
    5154{ TFormMain }
     
    6164    FormDisassembler := TFormDisassembler.Create(Self);
    6265  FormDisassembler.Disassembler.Cpu := Machine.Cpu;
    63   FormDisassembler.Disassembler.Process;
    6466  FormDisassembler.Show;
    6567  FormDisassembler.Reload;
     
    99101  FormConsole.Machine := Machine;
    100102  FormConsole.Show;
     103end;
     104
     105procedure TFormMain.ButtonAssemblerClick(Sender: TObject);
     106begin
     107  if not Assigned(FormAssembler) then
     108    FormAssembler := TFormAssembler.Create(Self);
     109  FormAssembler.Assembler.InstructionWriter.Cpu := Machine.Cpu;
     110  FormAssembler.Show;
    101111end;
    102112
  • branches/virtualcpu4/UAssembler.pas

    r181 r184  
    66
    77uses
    8   Classes, SysUtils;
     8  Classes, SysUtils, fgl, UCpu, UOpcode, UInstructionWriter;
    99
    1010type
     11  TErrorEvent = procedure (Text: string) of object;
     12
     13  { TParser }
     14
     15  TParser = class
     16  private
     17    FOnError: TErrorEvent;
     18    procedure Error(Text: string);
     19  public
     20    Text: string;
     21    procedure Expect(Text: string);
     22    function ReadNext: string;
     23    function EndOfText: Boolean;
     24    property OnError: TErrorEvent read FOnError write FOnError;
     25  end;
     26
     27  TLabel = class
     28    Name: string;
     29    Address: QWord;
     30  end;
     31
     32  TLabels = class(TFPGObjecTList<TLabel>)
     33
     34  end;
     35
    1136  { TAssembler }
    1237
    1338  TAssembler = class
     39  private
     40    FOnError: TErrorEvent;
     41    OpcodeDefs: TOpcodeDefs;
     42    procedure Error(Text: string);
     43    procedure ParseParam(Param: TOpcodeParam);
     44  public
     45    Parser: TParser;
     46    Labels: TLabels;
    1447    Source: TStringList;
    15     Dest: array of Byte;
     48    InstructionWriter: TInstructionWriter;
    1649    procedure Compile;
     50    constructor Create;
     51    destructor Destroy; override;
     52    property OnError: TErrorEvent read FOnError write FOnError;
    1753  end;
    1854
     
    2056implementation
    2157
     58{ TParser }
     59
     60procedure TParser.Error(Text: string);
     61begin
     62  if Assigned(FOnError) then FOnError(Text);
     63end;
     64
     65procedure TParser.Expect(Text: string);
     66var
     67  Next: string;
     68begin
     69  Next := ReadNext;
     70  if Next <> Text then
     71    Error('Expected ' + Text + ' but ' + Next + ' found');
     72end;
     73
     74function TParser.ReadNext: string;
     75var
     76  P: Integer;
     77begin
     78  Text := Trim(Text);
     79  P := 1;
     80  if (Length(Text) > 0) and (Text[P] = ',') then begin
     81    Result := Text[P];
     82    Delete(Text, 1, 1);
     83  end else begin
     84    while (P <= Length(Text)) and (Text[P] <> ' ') and (Text[P] <> ',') do Inc(P);
     85    Result := Copy(Text, 1, P - 1);
     86    Delete(Text, 1, P - 1);
     87  end;
     88end;
     89
     90function TParser.EndOfText: Boolean;
     91begin
     92  Result := Text = '';
     93end;
     94
    2295{ TAssembler }
    2396
     97procedure TAssembler.Error(Text: string);
     98begin
     99  if Assigned(FOnError) then FOnError(Text);
     100end;
     101
     102procedure TAssembler.ParseParam(Param: TOpcodeParam);
     103var
     104  Reg: TRegIndex;
     105  Addr: QWord;
     106  Next: string;
     107begin
     108  if Param = prReg then begin
     109    Next := Parser.ReadNext;
     110    if (Length(Next) > 1) and (Next[1] = 'R') then
     111      Reg := StrToInt(Copy(Next, 2, Length(Next)))
     112    else Error('Expected register name but found ' + Next);
     113    InstructionWriter.Write8(Reg);
     114  end else
     115  if Param = prData then begin
     116    Next := Parser.ReadNext;
     117    InstructionWriter.WriteData(StrToInt(Next));
     118  end else
     119  if Param = prAddr then begin
     120    Next := Parser.ReadNext;
     121    InstructionWriter.WriteAddress(StrToInt(Next));
     122  end else
     123  if Param = prAddrRel then begin
     124    Next := Parser.ReadNext;
     125    InstructionWriter.WriteAddress(StrToInt(Next));
     126  end;
     127end;
     128
    24129procedure TAssembler.Compile;
     130var
     131  I: Integer;
     132  NewLabel: TLabel;
     133  Next: string;
     134  OpcodeDef: TOpcodeDef;
    25135begin
     136  InstructionWriter.Init;
     137  Labels.Clear;
     138  for I := 0 to Source.Count - 1 do begin
     139    Parser.Text := Source[I];
     140    Next := Parser.ReadNext;
     141    if (Length(Next) > 0) and (Next[Length(Next)] = ':') then begin
     142      NewLabel := TLabel.Create;
     143      NewLabel.Name := Copy(Next, 1, Length(Next) - 1);
     144      //NewLabel.Address := ;
     145      Labels.Add(NewLabel);
     146      Next := Parser.ReadNext;
     147    end;
     148    OpcodeDef := OpcodeDefs.SearchByName(Next);
     149    if Assigned(OpcodeDef) then begin
     150      InstructionWriter.Write8(Byte(OpcodeDef.Opcode));
     151      ParseParam(OpcodeDef.Param1);
     152      if OpcodeDef.Param2 <> prNone then begin
     153        Parser.Expect(',');
     154        ParseParam(OpcodeDef.Param2);
     155        if OpcodeDef.Param3 <> prNone then begin
     156          Parser.Expect(',');
     157          ParseParam(OpcodeDef.Param3);
     158        end;
     159      end;
     160    end else Error('Unknown instruction ' + Next);
     161  end;
     162end;
    26163
     164constructor TAssembler.Create;
     165begin
     166  OpcodeDefs := TOpcodeDefs.Create;
     167  Source := TStringList.Create;
     168  Labels := TLabels.Create;
     169  Parser := TParser.Create;
     170  Parser.OnError := Error;
     171  InstructionWriter := TInstructionWriter.Create;
     172end;
     173
     174destructor TAssembler.Destroy;
     175begin
     176  FreeAndNil(InstructionWriter);
     177  FreeAndNil(Parser);
     178  FreeAndNil(Labels);
     179  FreeAndNil(Source);
     180  FreeAndNil(OpcodeDefs);
     181  inherited Destroy;
    27182end;
    28183
  • branches/virtualcpu4/UCpu.pas

    r183 r184  
    138138  end;
    139139
    140   TOpcodeParam = (prNone, prReg, prData, prAddr, prAddrRel);
    141   TOpcodeDef = record
    142     Name: string;
    143     Param1: TOpcodeParam;
    144     Param2: TOpcodeParam;
    145     Param3: TOpcodeParam;
    146     Prefix: Boolean;
    147   end;
    148 
    149140const
    150141  BitWidthBytes: array[TBitWidth] of Byte = (0, 1, 2, 4, 8);
    151142  BitWidthText: array[TBitWidth] of string = ('None', '8-bit', '16-bit', '32-bit', '64-bit');
    152   OpcodeDef: array[TOpcode] of TOpcodeDef = (
    153     (Name: 'NOP'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: False),
    154     (Name: 'HALT'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: False),
    155     (Name: 'LD'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    156     (Name: 'LDI'; Param1: prReg; Param2: prData; Param3: prNone; Prefix: False),
    157     (Name: 'JP'; Param1: prAddr; Param2: prNone; Param3: prNone; Prefix: False),
    158     (Name: 'JPZ'; Param1: prAddr; Param2: prNone; Param3: prNone; Prefix: False),
    159     (Name: 'JPNZ'; Param1: prAddr; Param2: prNone; Param3: prNone; Prefix: False),
    160     (Name: 'JR'; Param1: prAddrRel; Param2: prNone; Param3: prNone; Prefix: False),
    161     (Name: 'JRZ'; Param1: prAddrRel; Param2: prNone; Param3: prNone; Prefix: False),
    162     (Name: 'JRNZ'; Param1: prAddrRel; Param2: prNone; Param3: prNone; Prefix: False),
    163     (Name: 'NEG'; Param1: prReg; Param2: prNone; Param3: prNone; Prefix: False),
    164     (Name: 'CLR'; Param1: prReg; Param2: prNone; Param3: prNone; Prefix: False),
    165     (Name: 'LDM'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    166     (Name: 'STM'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    167     (Name: 'EX'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    168     (Name: 'PUSH'; Param1: prReg; Param2: prNone; Param3: prNone; Prefix: False),
    169     (Name: 'POP'; Param1: prReg; Param2: prNone; Param3: prNone; Prefix: False),
    170     (Name: 'CALL'; Param1: prAddr; Param2: prNone; Param3: prNone; Prefix: False),
    171     (Name: 'RET'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: False),
    172     (Name: 'ADD'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    173     (Name: 'ADDI'; Param1: prReg; Param2: prData; Param3: prNone; Prefix: False),
    174     (Name: 'SUB'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    175     (Name: 'SUBI'; Param1: prReg; Param2: prData; Param3: prNone; Prefix: False),
    176     (Name: 'INC'; Param1: prReg; Param2: prNone; Param3: prNone; Prefix: False),
    177     (Name: 'DEC'; Param1: prReg; Param2: prNone; Param3: prNone; Prefix: False),
    178     (Name: 'IN'; Param1: prReg; Param2: prAddr; Param3: prNone; Prefix: False),
    179     (Name: 'OUT'; Param1: prAddr; Param2: prReg; Param3: prNone; Prefix: False),
    180     (Name: 'SHL'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    181     (Name: 'SHR'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    182     (Name: 'DP8'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: True),
    183     (Name: 'DP16'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: False),
    184     (Name: 'DP32'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: True),
    185     (Name: 'DP64'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: True),
    186     (Name: 'DS'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: False),
    187     (Name: 'AS'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: False),
    188     (Name: 'TEST'; Param1: prReg; Param2: prNone; Param3: prNone; Prefix: False),
    189     (Name: 'AND'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    190     (Name: 'OR'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    191     (Name: 'XOR'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    192     (Name: 'LDDR'; Param1: prReg; Param2: prReg; Param3: prReg; Prefix: False),
    193     (Name: 'LDDR'; Param1: prReg; Param2: prReg; Param3: prReg; Prefix: False),
    194     (Name: 'MUL'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    195     (Name: 'DIV'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    196     (Name: 'MOD'; Param1: prReg; Param2: prReg; Param3: prNone; Prefix: False),
    197     (Name: 'AP8'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: True),
    198     (Name: 'AP16'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: True),
    199     (Name: 'AP32'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: True),
    200     (Name: 'AP64'; Param1: prNone; Param2: prNone; Param3: prNone; Prefix: True),
    201     (Name: 'CON'; Param1: prReg; Param2: prNone; Param3: prNone; Prefix: True)
    202   );
    203143
    204144implementation
  • branches/virtualcpu4/UDisassembler.pas

    r183 r184  
    66
    77uses
    8   Classes, SysUtils, UMemory, fgl, UCpu, UInstructionReader, Math;
     8  Classes, SysUtils, UMemory, fgl, UCpu, UInstructionReader, Math, UOpcode;
    99
    1010type
     
    1919  TDisassembler = class(TInstructionReader)
    2020  private
     21    OpcodeDefs: TOpcodeDefs;
    2122  public
    2223    Output: TFPGObjectList<TDisassemblerLine>;
     
    4849  AddressRel: TAddressSigned;
    4950  Reg: TRegIndex;
     51  OpcodeDef: TOpcodeDef;
    5052begin
    5153  Init;
     
    5759    Opcode := Read8;
    5860    if Opcode <= Integer(High(TOpcode)) then begin
    59       Prefix := OpcodeDef[TOpcode(Opcode)].Prefix;
     61      OpcodeDef := OpcodeDefs.SearchByOpcode(TOpcode(Opcode));
     62      Prefix := OpcodeDef.Prefix;
    6063      case TOpcode(Opcode) of
    6164        opDataPrefix8: DataSize := bw8;
     
    7174      Line.Address := IP - 1;
    7275      Line.Opcode := IntToHex(Opcode, 2);
    73       Line.Instruction := OpcodeDef[TOpcode(Opcode)].Name;
    74       case OpcodeDef[TOpcode(Opcode)].Param1 of
     76      Line.Instruction := OpcodeDef.Name;
     77      case OpcodeDef.Param1 of
    7578        prReg: begin
    7679          Reg := Read8;
     
    9497        end;
    9598      end;
    96       case OpcodeDef[TOpcode(Opcode)].Param2 of
     99      case OpcodeDef.Param2 of
    97100        prReg: begin
    98101          Reg := Read8;
     
    116119        end;
    117120      end;
    118       case OpcodeDef[TOpcode(Opcode)].Param3 of
     121      case OpcodeDef.Param3 of
    119122        prReg: begin
    120123          Reg := Read8;
     
    156159constructor TDisassembler.Create;
    157160begin
     161  OpcodeDefs := TOpcodeDefs.Create;
    158162  Output := TFPGObjectList<TDisassemblerLine>.Create;
    159163end;
     
    161165destructor TDisassembler.Destroy;
    162166begin
    163   Output.Free;
     167  FreeAndNil(Output);
     168  FreeAndNil(OpcodeDefs);
    164169  inherited Destroy;
    165170end;
  • branches/virtualcpu4/UInstructionReader.pas

    r182 r184  
    4242  AddrSizeBase := Cpu.AddrSizeBase;
    4343  AddrSize := AddrSizeBase;
     44  IP := 0;
     45  Prefix := False;
    4446end;
    4547
  • branches/virtualcpu4/UInstructionWriter.pas

    r183 r184  
    329329  AddrSizeBase := Cpu.AddrSizeBase;
    330330  AddrSize := AddrSizeBase;
     331  IP := 0;
     332  Prefix := False;
    331333end;
    332334
  • branches/virtualcpu4/virtucpu4.lpi

    r183 r184  
    7171      </Item1>
    7272    </RequiredPackages>
    73     <Units Count="14">
     73    <Units Count="16">
    7474      <Unit0>
    7575        <Filename Value="virtucpu4.lpr"/>
     
    146146        <IsPartOfProject Value="True"/>
    147147      </Unit13>
     148      <Unit14>
     149        <Filename Value="UOpcode.pas"/>
     150        <IsPartOfProject Value="True"/>
     151      </Unit14>
     152      <Unit15>
     153        <Filename Value="Forms\UFormAssembler.pas"/>
     154        <IsPartOfProject Value="True"/>
     155        <ComponentName Value="FormAssembler"/>
     156        <ResourceBaseClass Value="Form"/>
     157      </Unit15>
    148158    </Units>
    149159  </ProjectOptions>
  • branches/virtualcpu4/virtucpu4.lpr

    r181 r184  
    1010  SysUtils, Forms, UFormMain, UCpu, UMachine, UMemory, UFormDisassembler,
    1111  UFormMemory, UFormCpuState, UFormScreen, UFormConsole, UDisassembler,
    12   UAssembler, UInstructionReader
     12  UAssembler, UInstructionReader, UOpcode, UFormAssembler
    1313  { you can add units after this };
    1414
Note: See TracChangeset for help on using the changeset viewer.