Ignore:
Timestamp:
Jul 12, 2022, 11:51:47 PM (22 months ago)
Author:
chronos
Message:
  • Modified: Execute instructions as array of instruction handlers.
  • Modified: Optimized some methods call with inline directive.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/UltimatOS/UCpu.pas

    r32 r34  
    2121
    2222  TCpu = class;
     23  TInstructionHandler = procedure of object;
    2324
    2425  { TCpuThread }
     
    4041    InterruptVector: Integer;
    4142    InterruptEnabled: Boolean;
     43    FInstructionHandlers: array[TInstruction] of TInstructionHandler;
    4244    function GetRunning: Boolean;
    43     function ReadByte: Byte;
    44     function ReadAddress: TAddress;
    45     function ReadData: TData;
    46     procedure Push(Value: Integer);
    47     function Pop: Integer;
     45    function ReadByte: Byte; inline;
     46    function ReadAddress: TAddress; inline;
     47    function ReadData: TData; inline;
     48    procedure Push(Value: Integer); inline;
     49    function Pop: Integer; inline;
    4850    procedure SetRunning(AValue: Boolean);
     51    procedure InitInstructions;
     52    procedure InstructionNop;
     53    procedure InstructionHalt;
     54    procedure InstructionSet;
     55    procedure InstructionInput;
     56    procedure InstructionOutput;
     57    procedure InstructionInc;
     58    procedure InstructionDec;
     59    procedure InstructionJp;
     60    procedure InstructionJpnz;
     61    procedure InstructionJpz;
     62    procedure InstructionAdd;
     63    procedure InstructionSub;
     64    procedure InstructionCall;
     65    procedure InstructionRet;
     66    procedure InstructionPush;
     67    procedure InstructionPop;
     68    procedure InstructionCopy;
     69    procedure InstructionShl;
     70    procedure InstructionShr;
     71    procedure InstructionLoad;
     72    procedure InstructionLoadi;
     73    procedure InstructionStore;
     74    procedure InstructionMul;
     75    procedure InstructionAnd;
     76    procedure InstructionAndi;
     77    procedure InstructionOr;
     78    procedure InstructionXor;
     79    procedure InstructionInt;
     80    procedure InstructionReti;
     81    procedure InstructionEnableInt;
     82    procedure InstructionDisableInt;
    4983  public
    5084    ExecutedCount: Integer;
     
    135169end;
    136170
     171procedure TCpu.InitInstructions;
     172begin
     173  FInstructionHandlers[inNop] := InstructionNop;
     174  FInstructionHandlers[inHalt] := InstructionHalt;
     175  FInstructionHandlers[inSet] := InstructionSet;
     176  FInstructionHandlers[inInput] := InstructionInput;
     177  FInstructionHandlers[inOutput] := InstructionOutput;
     178  FInstructionHandlers[inInc] := InstructionInc;
     179  FInstructionHandlers[inDec] := InstructionDec;
     180  FInstructionHandlers[inJp] := InstructionJp;
     181  FInstructionHandlers[inJpz] := InstructionJpz;
     182  FInstructionHandlers[inJpnz] := InstructionJpnz;
     183  FInstructionHandlers[inAdd] := InstructionAdd;
     184  FInstructionHandlers[inSub] := InstructionSub;
     185  FInstructionHandlers[inCall] := InstructionCall;
     186  FInstructionHandlers[inRet] := InstructionRet;
     187  FInstructionHandlers[inPush] := InstructionPush;
     188  FInstructionHandlers[inPop] := InstructionPop;
     189  FInstructionHandlers[inCopy] := InstructionCopy;
     190  FInstructionHandlers[inShl] := InstructionShl;
     191  FInstructionHandlers[inShr] := InstructionShr;
     192  FInstructionHandlers[inLoad] := InstructionLoad;
     193  FInstructionHandlers[inLoadi] := InstructionLoadi;
     194  FInstructionHandlers[inStore] := InstructionStore;
     195  FInstructionHandlers[inMul] := InstructionMul;
     196  FInstructionHandlers[inAnd] := InstructionAnd;
     197  FInstructionHandlers[inAndi] := InstructionAndi;
     198  FInstructionHandlers[inOr] := InstructionOr;
     199  FInstructionHandlers[inXor] := InstructionXor;
     200  FInstructionHandlers[inInt] := InstructionInt;
     201  FInstructionHandlers[inReti] := InstructionReti;
     202  FInstructionHandlers[inEnableInt] := InstructionEnableInt;
     203  FInstructionHandlers[inDisableInt] := InstructionDisableInt;
     204end;
     205
     206procedure TCpu.InstructionNop;
     207begin
     208  // No operation
     209end;
     210
     211procedure TCpu.InstructionHalt;
     212begin
     213  Terminated := True;
     214end;
     215
     216procedure TCpu.InstructionSet;
     217var
     218  RegIndex: Byte;
     219begin
     220  RegIndex := ReadByte;
     221  R[RegIndex] := ReadData;
     222end;
     223
     224procedure TCpu.InstructionInput;
     225var
     226  RegIndex: Byte;
     227  Address: TAddress;
     228begin
     229  RegIndex := ReadByte;
     230  Address := ReadAddress;
     231  if Assigned(FOnInput) then R[RegIndex] := FOnInput(Address)
     232    else R[RegIndex] := 0;
     233end;
     234
     235procedure TCpu.InstructionOutput;
     236var
     237  RegIndex: Byte;
     238  Address: TAddress;
     239begin
     240  Address := ReadAddress;
     241  RegIndex := ReadByte;
     242  if Assigned(FOnOutput) then FOnOutput(Address, R[RegIndex]);
     243end;
     244
     245procedure TCpu.InstructionInc;
     246var
     247  RegIndex: Byte;
     248begin
     249  RegIndex := ReadByte;
     250  R[RegIndex] := R[RegIndex] + 1;
     251end;
     252
     253procedure TCpu.InstructionDec;
     254var
     255  RegIndex: Byte;
     256begin
     257  RegIndex := ReadByte;
     258  R[RegIndex] := R[RegIndex] - 1;
     259end;
     260
     261procedure TCpu.InstructionJp;
     262begin
     263  IP := ReadAddress;
     264end;
     265
     266procedure TCpu.InstructionJpnz;
     267var
     268  RegIndex: Byte;
     269  Address: TAddress;
     270begin
     271  RegIndex := ReadByte;
     272  Address := ReadAddress;
     273  if R[RegIndex] <> 0 then IP := Address;
     274end;
     275
     276procedure TCpu.InstructionJpz;
     277var
     278  RegIndex: Byte;
     279  Address: TAddress;
     280begin
     281  RegIndex := ReadByte;
     282  Address := ReadAddress;
     283  if R[RegIndex] = 0 then IP := Address;
     284end;
     285
     286procedure TCpu.InstructionAdd;
     287var
     288  RegIndex: Byte;
     289  RegIndex2: Byte;
     290begin
     291  RegIndex := ReadByte;
     292  RegIndex2 := ReadByte;
     293  R[RegIndex] := R[RegIndex] + R[RegIndex2];
     294end;
     295
     296procedure TCpu.InstructionSub;
     297var
     298  RegIndex: Byte;
     299  RegIndex2: Byte;
     300begin
     301  RegIndex := ReadByte;
     302  RegIndex2 := ReadByte;
     303  R[RegIndex] := R[RegIndex] - R[RegIndex2];
     304end;
     305
     306procedure TCpu.InstructionCall;
     307var
     308  Address: TAddress;
     309begin
     310  Address := ReadAddress;
     311  Push(IP);
     312  IP := Address;
     313end;
     314
     315procedure TCpu.InstructionRet;
     316begin
     317  IP := Pop;
     318end;
     319
     320procedure TCpu.InstructionPush;
     321begin
     322  Push(R[ReadByte]);
     323end;
     324
     325procedure TCpu.InstructionPop;
     326begin
     327  R[ReadByte] := Pop;
     328end;
     329
     330procedure TCpu.InstructionCopy;
     331var
     332  RegIndex: Byte;
     333  RegIndex2: Byte;
     334begin
     335  RegIndex := ReadByte;
     336  RegIndex2 := ReadByte;
     337  R[RegIndex] := R[RegIndex2];
     338end;
     339
     340procedure TCpu.InstructionShl;
     341var
     342  RegIndex: Byte;
     343  Num: Byte;
     344begin
     345  RegIndex := ReadByte;
     346  Num := ReadByte;
     347  R[RegIndex] := R[RegIndex] shl Num;
     348end;
     349
     350procedure TCpu.InstructionShr;
     351var
     352  RegIndex: Byte;
     353  Num: Byte;
     354begin
     355  RegIndex := ReadByte;
     356  Num := ReadByte;
     357  R[RegIndex] := R[RegIndex] shr Num;
     358end;
     359
     360procedure TCpu.InstructionLoad;
     361var
     362  RegIndex: Byte;
     363  RegIndex2: Byte;
     364begin
     365  RegIndex := ReadByte;
     366  RegIndex2 := ReadByte;
     367  R[RegIndex] := PData(@Memory.Data[R[RegIndex2]])^;
     368end;
     369
     370procedure TCpu.InstructionLoadi;
     371var
     372  RegIndex: Byte;
     373  Address: TAddress;
     374begin
     375  RegIndex := ReadByte;
     376  Address := ReadAddress;
     377  R[RegIndex] := PData(@Memory.Data[Address])^;
     378end;
     379
     380procedure TCpu.InstructionStore;
     381var
     382  RegIndex: Byte;
     383  RegIndex2: Byte;
     384begin
     385  RegIndex := ReadByte;
     386  RegIndex2 := ReadByte;
     387  PData(@Memory.Data[R[RegIndex2]])^ := R[RegIndex];
     388end;
     389
     390procedure TCpu.InstructionMul;
     391var
     392  RegIndex: Byte;
     393  RegIndex2: Byte;
     394begin
     395  RegIndex := ReadByte;
     396  RegIndex2 := ReadByte;
     397  R[RegIndex] := R[RegIndex] * R[RegIndex2];
     398end;
     399
     400procedure TCpu.InstructionAnd;
     401var
     402  RegIndex: Byte;
     403  RegIndex2: Byte;
     404begin
     405  RegIndex := ReadByte;
     406  RegIndex2 := ReadByte;
     407  R[RegIndex] := R[RegIndex] and R[RegIndex2];
     408end;
     409
     410procedure TCpu.InstructionAndi;
     411var
     412  RegIndex: Byte;
     413begin
     414  RegIndex := ReadByte;
     415  R[RegIndex] := R[RegIndex] and ReadData;
     416end;
     417
     418procedure TCpu.InstructionOr;
     419var
     420  RegIndex: Byte;
     421  RegIndex2: Byte;
     422begin
     423  RegIndex := ReadByte;
     424  RegIndex2 := ReadByte;
     425  R[RegIndex] := R[RegIndex] or R[RegIndex2];
     426end;
     427
     428procedure TCpu.InstructionXor;
     429var
     430  RegIndex: Byte;
     431  RegIndex2: Byte;
     432begin
     433  RegIndex := ReadByte;
     434  RegIndex2 := ReadByte;
     435  R[RegIndex] := R[RegIndex] xor R[RegIndex2];
     436end;
     437
     438procedure TCpu.InstructionInt;
     439begin
     440  Interrupt(ReadByte);
     441end;
     442
     443procedure TCpu.InstructionReti;
     444begin
     445  IP := Pop;
     446  InterruptEnabled := True;
     447end;
     448
     449procedure TCpu.InstructionEnableInt;
     450begin
     451  InterruptEnabled := True;
     452end;
     453
     454procedure TCpu.InstructionDisableInt;
     455begin
     456  InterruptEnabled := False;
     457end;
     458
    137459procedure TCpu.Run;
    138460begin
     
    161483var
    162484  Instruction: TInstruction;
    163   Address: Integer;
    164   RegIndex: Byte;
    165   RegIndex2: Byte;
    166   Num: Byte;
    167485begin
    168486  Instruction := TInstruction(ReadByte);
     487  if Assigned(FInstructionHandlers[Instruction]) then
     488    FInstructionHandlers[Instruction]
     489    else raise Exception.Create('Missing handler for instruction ' + IntToStr(Integer(Instruction)));
    169490  Inc(ExecutedCount);
    170   case Instruction of
    171     inNop: ;
    172     inHalt: Terminated := True;
    173     inSet: begin
    174       RegIndex := ReadByte;
    175       R[RegIndex] := ReadData;
    176     end;
    177     inLoad: begin
    178       RegIndex := ReadByte;
    179       RegIndex2 := ReadByte;
    180       R[RegIndex] := PData(@Memory.Data[R[RegIndex2]])^;
    181     end;
    182     inLoadi: begin
    183       RegIndex := ReadByte;
    184       Address := ReadAddress;
    185       R[RegIndex] := PData(@Memory.Data[Address])^;
    186     end;
    187     inStore: begin
    188       RegIndex := ReadByte;
    189       RegIndex2 := ReadByte;
    190       PData(@Memory.Data[R[RegIndex2]])^ := R[RegIndex];
    191     end;
    192     inInput: begin
    193       RegIndex := ReadByte;
    194       Address := ReadAddress;
    195       if Assigned(FOnInput) then R[RegIndex] := FOnInput(Address)
    196         else R[RegIndex] := 0;
    197     end;
    198     inOutput: begin
    199       Address := ReadAddress;
    200       RegIndex := ReadByte;
    201       if Assigned(FOnOutput) then FOnOutput(Address, R[RegIndex]);
    202     end;
    203     inInc: begin
    204       RegIndex := ReadByte;
    205       R[RegIndex] := R[RegIndex] + 1;
    206     end;
    207     inDec: begin
    208       RegIndex := ReadByte;
    209       R[RegIndex] := R[RegIndex] - 1;
    210     end;
    211     inJp: begin
    212       IP := ReadAddress;
    213     end;
    214     inJpz: begin
    215       RegIndex := ReadByte;
    216       Address := ReadAddress;
    217       if R[RegIndex] = 0 then IP := Address;
    218     end;
    219     inJpnz: begin
    220       RegIndex := ReadByte;
    221       Address := ReadAddress;
    222       if R[RegIndex] <> 0 then IP := Address;
    223     end;
    224     inAdd: begin
    225       RegIndex := ReadByte;
    226       RegIndex2 := ReadByte;
    227       R[RegIndex] := R[RegIndex] + R[RegIndex2];
    228     end;
    229     inSub: begin
    230       RegIndex := ReadByte;
    231       RegIndex2 := ReadByte;
    232       R[RegIndex] := R[RegIndex] - R[RegIndex2];
    233     end;
    234     inPush: begin
    235       RegIndex := ReadByte;
    236       Push(R[RegIndex]);
    237     end;
    238     inPop: begin
    239       RegIndex := ReadByte;
    240       R[RegIndex] := Pop;
    241     end;
    242     inCall: begin
    243       Address := ReadAddress;
    244       Push(IP);
    245       IP := Address;
    246     end;
    247     inRet: begin
    248       IP := Pop;
    249     end;
    250     inCopy: begin
    251       RegIndex := ReadByte;
    252       RegIndex2 := ReadByte;
    253       R[RegIndex] := R[RegIndex2];
    254     end;
    255     inShl: begin
    256       RegIndex := ReadByte;
    257       Num := ReadByte;
    258       R[RegIndex] := R[RegIndex] shl Num;
    259     end;
    260     inShr: begin
    261       RegIndex := ReadByte;
    262       Num := ReadByte;
    263       R[RegIndex] := R[RegIndex] shr Num;
    264     end;
    265     inMul: begin
    266       RegIndex := ReadByte;
    267       RegIndex2 := ReadByte;
    268       R[RegIndex] := R[RegIndex] * R[RegIndex2];
    269     end;
    270     inAnd: begin
    271       RegIndex := ReadByte;
    272       RegIndex2 := ReadByte;
    273       R[RegIndex] := R[RegIndex] and R[RegIndex2];
    274     end;
    275     inAndi: begin
    276       RegIndex := ReadByte;
    277       R[RegIndex] := R[RegIndex] and ReadData;
    278     end;
    279     inOr: begin
    280       RegIndex := ReadByte;
    281       RegIndex2 := ReadByte;
    282       R[RegIndex] := R[RegIndex] or R[RegIndex2];
    283     end;
    284     inXor: begin
    285       RegIndex := ReadByte;
    286       RegIndex2 := ReadByte;
    287       R[RegIndex] := R[RegIndex] xor R[RegIndex2];
    288     end;
    289     inInt: begin
    290       Interrupt(ReadByte);
    291     end;
    292     inReti: begin
    293       IP := Pop;
    294       InterruptEnabled := True;
    295     end;
    296     inEnableInt: InterruptEnabled := True;
    297     inDisableInt: InterruptEnabled := False;
    298   end;
    299491end;
    300492
     
    319511constructor TCpu.Create;
    320512begin
     513  InitInstructions;
    321514end;
    322515
Note: See TracChangeset for help on using the changeset viewer.