Changeset 196


Ignore:
Timestamp:
Sep 22, 2019, 7:13:15 PM (5 years ago)
Author:
chronos
Message:
  • Modified: Address CPU memory as pointer instead array of bytes.
  • Added: TMachine class to represent virtual machine itself.
Location:
branches/virtcpu varint
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • branches/virtcpu varint

    • Property svn:ignore set to
      lib
      virtcpu
      virtcpu.lps
  • branches/virtcpu varint/UFormMain.lfm

    r195 r196  
    1 object Form1: TForm1
     1object FormMain: TFormMain
    22  Left = 385
    33  Height = 914
    44  Top = 208
    55  Width = 1543
    6   Caption = 'Form1'
     6  Caption = 'VarInt machine'
    77  ClientHeight = 914
    88  ClientWidth = 1543
  • branches/virtcpu varint/UFormMain.pas

    r195 r196  
    1111type
    1212
    13   { TForm1 }
    14 
    15   TForm1 = class(TForm)
     13  { TFormMain }
     14
     15  TFormMain = class(TForm)
    1616    Button1: TButton;
    1717    Button2: TButton;
     
    3838    procedure CpuOutput(Port, Value: T);
    3939  public
    40     Cpu: TCPU;
     40    Machine: TMachine;
    4141    InstructionWriter: TInstructionWriter;
    4242  end;
    4343
    4444var
    45   Form1: TForm1;
     45  FormMain: TFormMain;
    4646
    4747const
     
    5353{$R *.lfm}
    5454
    55 { TForm1 }
    56 
    57 procedure TForm1.FormShow(Sender: TObject);
     55{ TFormMain }
     56
     57procedure TFormMain.FormShow(Sender: TObject);
    5858var
    5959  LabelStart: Integer;
     
    104104end;
    105105
    106 procedure TForm1.FormDestroy(Sender: TObject);
    107 begin
    108   InstructionWriter.Free;
    109   Cpu.Free;
    110 end;
    111 
    112 procedure TForm1.FormKeyPress(Sender: TObject; var Key: char);
    113 begin
    114 end;
    115 
    116 procedure TForm1.FormCreate(Sender: TObject);
    117 begin
    118   Cpu := TCPU.Create(nil);
    119   Cpu.OnInput := CpuInput;
    120   Cpu.OnOutput := CpuOutput;
     106procedure TFormMain.FormDestroy(Sender: TObject);
     107begin
     108  FreeAndNil(InstructionWriter);
     109  FreeAndNil(Machine);
     110end;
     111
     112procedure TFormMain.FormKeyPress(Sender: TObject; var Key: char);
     113begin
     114end;
     115
     116procedure TFormMain.FormCreate(Sender: TObject);
     117begin
     118  Machine := TMachine.Create(nil);
     119  Machine.Cpu.OnInput := CpuInput;
     120  Machine.Cpu.OnOutput := CpuOutput;
    121121  InstructionWriter := TInstructionWriter.Create;
    122   InstructionWriter.Cpu := Cpu;
    123 end;
    124 
    125 procedure TForm1.Button1Click(Sender: TObject);
    126 begin
    127   Cpu.Start;
    128 end;
    129 
    130 procedure TForm1.Button2Click(Sender: TObject);
    131 begin
    132   Cpu.Stop;
    133 end;
    134 
    135 procedure TForm1.ListViewMemoryData(Sender: TObject; Item: TListItem);
     122  InstructionWriter.Cpu := Machine.Cpu;
     123end;
     124
     125procedure TFormMain.Button1Click(Sender: TObject);
     126begin
     127  Machine.Cpu.Start;
     128end;
     129
     130procedure TFormMain.Button2Click(Sender: TObject);
     131begin
     132  Machine.Cpu.Stop;
     133end;
     134
     135procedure TFormMain.ListViewMemoryData(Sender: TObject; Item: TListItem);
    136136var
    137137  Line: string;
    138138  I: Integer;
    139139begin
    140   if Item.Index < Length(Cpu.Memory) div ItemsPerLine then begin
     140  if Item.Index < Machine.MemorySize div ItemsPerLine then begin
    141141    Line := '';
    142142    for I := 0 to ItemsPerLine - 1 do
    143       Line := Line + IntToHex(Cpu.Memory[Item.Index * ItemsPerLine + I], 2) + ' ';
     143      Line := Line + IntToHex(PByte(NativeUInt(Machine.Memory) + Item.Index * ItemsPerLine + I)^, 2) + ' ';
    144144    Item.Caption := IntToHex(Item.Index * ItemsPerLine, 8);
    145145    Item.SubItems.Add(Line);
     
    147147end;
    148148
    149 procedure TForm1.ListViewRegistersData(Sender: TObject; Item: TListItem);
    150 begin
    151   if Item.Index < Length(Cpu.Registers) + 1 then begin
     149procedure TFormMain.ListViewRegistersData(Sender: TObject; Item: TListItem);
     150begin
     151  if Item.Index < Length(Machine.Cpu.Registers) + 1 then begin
    152152    if Item.Index = 0 then begin
    153153      Item.Caption := 'IP';
    154       Item.SubItems.Add(IntToHex(Int64(Cpu.IP), 8));
     154      Item.SubItems.Add(IntToHex(Int64(Machine.Cpu.IP), 8));
    155155    end else
    156156    if Item.Index = 1 then begin
    157157      Item.Caption := 'SP';
    158       Item.SubItems.Add(IntToHex(Int64(Cpu.SP), 8));
     158      Item.SubItems.Add(IntToHex(Int64(Machine.Cpu.SP), 8));
    159159    end else begin
    160160      Item.Caption := 'R' + IntToStr(Item.Index - 2);
    161       Item.SubItems.Add(IntToHex(Int64(Cpu.Registers[Item.Index - 2]), 8));
     161      Item.SubItems.Add(IntToHex(Int64(Machine.Cpu.Registers[Item.Index - 2]), 8));
    162162    end;
    163163  end;
    164164end;
    165165
    166 procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: char);
     166procedure TFormMain.Memo1KeyPress(Sender: TObject; var Key: char);
    167167begin
    168168  SetLength(KeyInputBuffer, Length(KeyInputBuffer) + 1);
     
    170170end;
    171171
    172 procedure TForm1.Timer1Timer(Sender: TObject);
     172procedure TFormMain.Timer1Timer(Sender: TObject);
    173173begin
    174174  ReloadMemoryDump;
    175175  ReloadRegisterDump;
    176   LabelTicks.Caption := 'Ticks: ' + IntToStr(Cpu.Ticks);
    177 end;
    178 
    179 procedure TForm1.ReloadMemoryDump;
    180 begin
    181   ListViewMemory.Items.Count := Length(Cpu.Memory) div ItemsPerLine;
     176  LabelTicks.Caption := 'Ticks: ' + IntToStr(Machine.Cpu.Ticks);
     177end;
     178
     179procedure TFormMain.ReloadMemoryDump;
     180begin
     181  ListViewMemory.Items.Count := Machine.MemorySize div ItemsPerLine;
    182182  ListViewMemory.Refresh;
    183183end;
    184184
    185 procedure TForm1.ReloadRegisterDump;
    186 begin
    187   ListViewRegisters.Items.Count := Length(Cpu.Registers);
     185procedure TFormMain.ReloadRegisterDump;
     186begin
     187  ListViewRegisters.Items.Count := Length(Machine.Cpu.Registers);
    188188  ListViewRegisters.Refresh;
    189189end;
    190190
    191 function TForm1.CpuInput(Port: T): T;
     191function TFormMain.CpuInput(Port: T): T;
    192192begin
    193193  Result := 0;
    194194  case Integer(Port) of
    195195    0: begin
    196       while (Length(KeyInputBuffer) = 0) and not Cpu.Terminated do begin
     196      while (Length(KeyInputBuffer) = 0) and not Machine.Cpu.Terminated do begin
    197197        Sleep(100);
    198198        Application.ProcessMessages;
     
    208208end;
    209209
    210 procedure TForm1.CpuOutput(Port, Value: T);
     210procedure TFormMain.CpuOutput(Port, Value: T);
    211211begin
    212212  case Integer(Port) of
  • branches/virtcpu varint/UInstructionWriter.pas

    r195 r196  
    166166  C: Integer;
    167167begin
    168   C := Value.WriteToAddr(@Cpu.Memory[IP]);
     168  C := Value.WriteToAddr(Pointer(NativeInt(Cpu.Memory) + IP));
    169169  Inc(IP, C);
    170170end;
  • branches/virtcpu varint/UMachine.pas

    r195 r196  
    11unit UMachine;
    2 
    32
    43{$mode delphi}{$H+}
     
    8584    procedure OpcodeLddr;
    8685  public
     86    Memory: Pointer;
    8787    Registers: array of T;
    8888    IP: T;
     89    SP: T;
    8990    Condition: Boolean;
    90     SP: T;
    91     Memory: array of Byte;
    9291    Terminated: Boolean;
    9392    Ticks: Integer;
    9493    procedure Start;
    9594    procedure Stop;
     95    procedure Step; inline;
    9696    constructor Create(AOwner: TComponent); override;
    9797  published
     
    100100  end;
    101101
     102  { TMachine }
     103
     104  TMachine = class(TComponent)
     105  private
     106    FMemorySize: Integer;
     107    procedure SetMemorySize(AValue: Integer);
     108  public
     109    Cpu: TCpu;
     110    Memory: Pointer;
     111    property MemorySize: Integer read FMemorySize write SetMemorySize;
     112    constructor Create(AOwner: TComponent); override;
     113    destructor Destroy; override;
     114  end;
     115
    102116
    103117implementation
    104118
     119{ TMachine }
     120
     121procedure TMachine.SetMemorySize(AValue: Integer);
     122begin
     123  if FMemorySize = AValue then Exit;
     124  FMemorySize := AValue;
     125  Memory := ReAllocMem(Memory, FMemorySize);
     126  Cpu.Memory := Memory;
     127end;
     128
     129constructor TMachine.Create(AOwner: TComponent);
     130begin
     131  inherited;
     132  Cpu := TCpu.Create(nil);
     133  MemorySize := 1000;
     134end;
     135
     136destructor TMachine.Destroy;
     137begin
     138  MemorySize := 0;
     139  FreeAndNil(Cpu);
     140  inherited Destroy;
     141end;
     142
    105143{ TCPU }
    106144
    107145function TCPU.ReadNext: T;
    108146begin
    109   IP := IP + Result.ReadFromAddr(@Memory[IP]);
     147  IP := IP + Result.ReadFromAddr(Pointer(NativeUInt(Memory) + IP));
    110148end;
    111149
     
    147185  P1 := ReadNext;
    148186  P2 := ReadNext;
    149   Registers[P1] := Memory[Registers[P2]];
     187  Registers[P1].ReadFromAddr(Pointer(NativeUInt(Memory) + Integer(Registers[P2])));
    150188end;
    151189
     
    157195  P1 := ReadNext;
    158196  P2 := ReadNext;
    159   Memory[Registers[P1]] := Registers[P2];
     197  Registers[P2].WriteToAddr(Pointer(NativeUInt(Memory) + Registers[P1]));
    160198end;
    161199
     
    307345  P1 := ReadNext;
    308346  SP := SP - Registers[P1].GetByteSize;
    309   Registers[P1].WriteToAddr(@Memory[SP]);
     347  Registers[P1].WriteToAddr(Pointer(NativeUInt(Memory) + Integer(SP)));
    310348end;
    311349
    312350procedure TCPU.OpcodePop;
    313351begin
    314   SP := SP + Registers[ReadNext].ReadFromAddr(@Memory[SP]);
     352  SP := SP + Registers[ReadNext].ReadFromAddr(Pointer(NativeUInt(Memory) + Integer(SP)));
    315353end;
    316354
     
    321359  Addr := ReadNext;
    322360  SP := SP - IP.GetByteSize;
    323   IP.WriteToAddr(@Memory[SP]);
     361  IP.WriteToAddr(Pointer(NativeUInt(Memory) + SP));
    324362  IP := Addr;
    325363end;
     
    331369  Addr := ReadNext;
    332370  SP := SP - IP.GetByteSize;
    333   IP.WriteToAddr(@Memory[SP]);
     371  IP.WriteToAddr(Pointer(NativeUInt(Memory) + SP));
    334372  IP := IP + Addr;
    335373end;
    336374
    337375procedure TCPU.OpcodeReturn;
    338 var
    339   S: Integer;
    340 begin
    341   SP := SP + IP.ReadFromAddr(@Memory[SP]);
     376begin
     377  SP := SP + IP.ReadFromAddr(Pointer(NativeUInt(Memory) + SP));
    342378end;
    343379
     
    424460  Src: T;
    425461  Dst: T;
    426   Size: T;
     462  Count: T;
     463  Bytes: T;
    427464begin
    428465  Src := ReadNext;
    429466  Dst := ReadNext;
    430   Size := ReadNext;
    431   while Registers[Size] > 0 do begin
    432     Memory[Registers[Dst]] := Memory[Registers[Src]];
    433     Inc(Registers[Src]);
    434     Inc(Registers[Dst]);
    435     Dec(Registers[Size]);
     467  Count := ReadNext;
     468  Bytes := ReadNext;
     469  while Registers[Count] > 0 do begin
     470    Move(Pointer(NativeUInt(Memory) + Registers[Src])^,
     471      Pointer(NativeUInt(Memory) + Registers[Dst])^, Bytes);
     472    Inc(Registers[Src], Bytes);
     473    Inc(Registers[Dst], Bytes);
     474    Dec(Registers[Count]);
    436475  end;
    437476end;
     
    441480  Src: T;
    442481  Dst: T;
    443   Size: T;
     482  Count: T;
     483  Bytes: T;
    444484begin
    445485  Src := ReadNext;
    446486  Dst := ReadNext;
    447   Size := ReadNext;
    448   while Registers[Size] > 0 do begin
    449     Memory[Registers[Dst]] := Memory[Registers[Src]];
    450     Dec(Registers[Src]);
    451     Dec(Registers[Dst]);
    452     Dec(Registers[Size]);
     487  Count := ReadNext;
     488  Bytes := ReadNext;
     489  while Registers[Count] > 0 do begin
     490    Move(Pointer(NativeUInt(Memory) + Registers[Src])^,
     491      Pointer(NativeUInt(Memory) + Registers[Dst])^, Bytes);
     492    Dec(Registers[Src], Bytes);
     493    Dec(Registers[Dst], Bytes);
     494    Dec(Registers[Count]);
    453495  end;
    454496end;
    455497
    456498procedure TCPU.Start;
    457 var
    458   Opcode: T;
    459499begin
    460500  Terminated := False;
    461501  Ticks := 0;
    462502  IP := 0;
    463   SP := Length(Memory);
    464   while not Terminated do begin
    465     Opcode := ReadNext;
    466     if (Opcode >= 0) and (Opcode <= T(Integer(High(TOpcode)))) then
    467       OpcodeHandlers[TOpcode(Byte(Opcode))]
    468       else raise Exception.Create(Format('Unsupported instruction %d', [Int64(Opcode)]));
    469     Inc(Ticks);
    470   end;
     503  SP := MemSize(Memory);
     504  while not Terminated do
     505    Step;
    471506end;
    472507
     
    474509begin
    475510  Terminated := True;
     511end;
     512
     513procedure TCPU.Step;
     514var
     515  Opcode: T;
     516begin
     517  Opcode := ReadNext;
     518  if (Opcode >= 0) and (Opcode <= T(Integer(High(TOpcode)))) then
     519    OpcodeHandlers[TOpcode(Byte(Opcode))]
     520    else raise Exception.Create(Format('Unsupported instruction %d on address %x', [Int64(Opcode), Int64(IP)]));
     521  Inc(Ticks);
    476522end;
    477523
     
    480526  inherited;
    481527  SetLength(Registers, 16);
    482   SetLength(Memory, 1024);
    483528  OpcodeHandlers[opNop] := OpcodeNop;
    484529  OpcodeHandlers[opHalt] := OpcodeHalt;
  • branches/virtcpu varint/UVarInt.pas

    r195 r196  
    3232    class operator Explicit(A: TVarInt): Int64;
    3333    class operator Inc(A: TVarInt): TVarInt;
    34     class operator Inc(A: TVarInt; B: Integer): TVarInt;
     34    class operator Inc(A: TVarInt; B: TVarInt): TVarInt;
    3535    class operator Dec(A: TVarInt): TVarInt;
     36    class operator Dec(A: TVarInt; B: TVarInt): TVarInt;
    3637    class operator Negative(A: TVarInt): TVarInt;
    3738    class operator Add(A: TVarInt; B: TVarInt): TVarInt;
     
    7576    class operator Explicit(A: TVarUInt): Int64;
    7677    class operator Inc(A: TVarUInt): TVarUInt;
    77     class operator Inc(A: TVarUInt; B: Integer): TVarUInt;
     78    class operator Inc(A: TVarUInt; B: TVarInt): TVarUInt;
    7879    class operator Dec(A: TVarUInt): TVarUInt;
     80    class operator Dec(A: TVarUInt; B: TVarUInt): TVarUInt;
    7981    class operator Negative(A: TVarUInt): TVarUInt;
    8082    class operator Add(A: TVarUInt; B: TVarUInt): TVarUInt;
     
    191193end;
    192194
    193 class operator TVarUInt.Inc(A: TVarUInt; B: Integer): TVarUInt;
    194 begin
    195   Result.Value := A.Value + B;
     195class operator TVarUInt.Inc(A: TVarUInt; B: TVarInt): TVarUInt;
     196begin
     197  Result.Value := A.Value + B.Value;
    196198end;
    197199
     
    199201begin
    200202  Result.Value := A.Value - 1;
     203end;
     204
     205class operator TVarUInt.Dec(A: TVarUInt; B: TVarUInt): TVarUInt;
     206begin
     207  Result.Value := A.Value - B.Value;
    201208end;
    202209
     
    424431end;
    425432
    426 class operator TVarInt.Inc(A: TVarInt; B: Integer): TVarInt;
    427 begin
    428   Result := A.Value + B;
     433class operator TVarInt.Inc(A: TVarInt; B: TVarInt): TVarInt;
     434begin
     435  Result := A.Value + B.Value;
    429436end;
    430437
     
    432439begin
    433440  Result.Value := A.Value - 1;
     441end;
     442
     443class operator TVarInt.Dec(A: TVarInt; B: TVarInt): TVarInt;
     444begin
     445  Result.Value := A.Value - B.Value;
    434446end;
    435447
  • branches/virtcpu varint/virtcpu.lpi

    r195 r196  
    7272        <Filename Value="UFormMain.pas"/>
    7373        <IsPartOfProject Value="True"/>
    74         <ComponentName Value="Form1"/>
     74        <ComponentName Value="FormMain"/>
    7575        <HasResources Value="True"/>
    7676        <ResourceBaseClass Value="Form"/>
  • branches/virtcpu varint/virtcpu.lpr

    r195 r196  
    1616  RequireDerivedFormResource:=True;
    1717  Application.Initialize;
    18   Application.CreateForm(TForm1, Form1);
     18  Application.CreateForm(TFormMain, FormMain);
    1919  Application.Run;
    2020end.
Note: See TracChangeset for help on using the changeset viewer.