Ignore:
Timestamp:
Apr 24, 2018, 9:54:30 AM (7 years ago)
Author:
chronos
Message:
  • Modified: Made opcodes as separate methods and placed them to opcode handler array to avoid multiple condition checking in case-of statement.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/virtualcpu3/UMachine.pas

    r155 r156  
    1111  TOpcode = (opNop, opHalt, opLD, opLDC, opLDM, opSTM, opInc, opDec, opJP, opJr,
    1212    opPush, opPop, opCall, opRet, opAdd, opSub, opMul, opDiv, opShr, opShl,
    13     opIn, opOut, opXchg, opXor, opOr, opAnd, opJpc, opJrc, opTstZ, opTstNZ);
     13    opIn, opOut, opXchg, opXor, opOr, opAnd, opJpc, opJrc, opTstZ, opTstNZ,
     14    opLDMD, opSTMD);
     15
     16  TOpcodeHandler = procedure of object;
    1417
    1518  { TCPU }
     
    2124  var
    2225    Terminated: Boolean;
     26    OpcodeHandlers: array[TOpcode] of TOpcodeHandler;
    2327    function ReadNext: T;
    2428    procedure Step;
     29    procedure AddOpcode(Opcode: TOpcode; Handler: TOpcodeHandler);
     30    procedure InitOpcodes;
    2531  private
    2632    FOnInput: TInputEvent;
    2733    FOnOutput: TOutputEvent;
    2834    Condition: Boolean;
     35    procedure OpcodeAddition;
     36    procedure OpcodeAnd;
     37    procedure OpcodeCall;
     38    procedure OpcodeDecrement;
     39    procedure OpcodeDivision;
     40    procedure OpcodeExchange;
     41    procedure OpcodeHalt;
     42    procedure OpcodeIncrement;
     43    procedure OpcodeInput;
     44    procedure OpcodeJump;
     45    procedure OpcodeJumpConditional;
     46    procedure OpcodeJumpRelative;
     47    procedure OpcodeJumpRelativeConditional;
     48    procedure OpcodeLoad;
     49    procedure OpcodeLoadConst;
     50    procedure OpcodeLoadMemory;
     51    procedure OpcodeLoadMemoryDisplacement;
     52    procedure OpcodeMultiplication;
     53    procedure OpcodeNop;
     54    procedure OpcodeOr;
     55    procedure OpcodeOutput;
     56    procedure OpcodePop;
     57    procedure OpcodePush;
     58    procedure OpcodeReturn;
     59    procedure OpcodeShiftLeft;
     60    procedure OpcodeShiftRight;
     61    procedure OpcodeStoreMemory;
     62    procedure OpcodeStoreMemoryDisplacement;
     63    procedure OpcodeSubtraction;
     64    procedure OpcodeTestNotZero;
     65    procedure OpcodeTestZero;
     66    procedure OpcodeXor;
    2967  public
    3068    Registers: array of T;
     
    62100  SetLength(Registers, 32);
    63101  SetLength(Memory, 1000);
    64 end;
     102  InitOpcodes;
     103end;
     104
     105procedure TCPU.OpcodeNop;
     106begin
     107end;
     108
     109procedure TCPU.OpcodeHalt;
     110begin
     111  Terminated := True;
     112end;
     113
     114procedure TCPU.OpcodeLoad;
     115var
     116  Src, Dest: T;
     117begin
     118  Dest := ReadNext;
     119  Src := ReadNext;
     120  Registers[Dest] := Registers[Src];
     121end;
     122
     123procedure TCPU.OpcodeLoadConst;
     124var
     125  Reg: T;
     126begin
     127  Reg := ReadNext;
     128  Registers[Reg] := ReadNext;
     129end;
     130
     131procedure TCPU.OpcodeLoadMemory;
     132var
     133  Src, Dest: T;
     134begin
     135  Dest := ReadNext;
     136  Src := ReadNext;
     137  Registers[Dest] := Memory[Registers[Src]];
     138end;
     139
     140procedure TCPU.OpcodeStoreMemory;
     141var
     142  Src, Dest: T;
     143begin
     144  Dest := ReadNext;
     145  Src := ReadNext;
     146  Memory[Registers[Dest]] := Registers[Src];
     147end;
     148
     149procedure TCPU.OpcodeLoadMemoryDisplacement;
     150var
     151  Reg, Src, Dest: T;
     152begin
     153  Dest := ReadNext;
     154  Src := ReadNext;
     155  Reg := ReadNext;
     156  Registers[Dest] := Memory[Registers[Src] + Registers[Reg]];
     157end;
     158
     159procedure TCPU.OpcodeStoreMemoryDisplacement;
     160var
     161  Reg, Src, Dest: T;
     162begin
     163  Dest := ReadNext;
     164  Reg := ReadNext;
     165  Src := ReadNext;
     166  Memory[Registers[Dest] + Registers[Reg]] := Registers[Src];
     167end;
     168
     169procedure TCPU.OpcodeIncrement;
     170var
     171  Reg: T;
     172begin
     173  Reg := ReadNext;
     174  Registers[Reg] := Registers[Reg] + 1;
     175end;
     176
     177procedure TCPU.OpcodeDecrement;
     178var
     179  Reg: T;
     180begin
     181  Reg := ReadNext;
     182  Registers[Reg] := Registers[Reg] - 1;
     183end;
     184
     185procedure TCPU.OpcodeAddition;
     186var
     187  Dest, Src: T;
     188begin
     189  Dest := ReadNext;
     190  Src := ReadNext;
     191  Registers[Dest] := Registers[Dest] + Registers[Src];
     192end;
     193
     194procedure TCPU.OpcodeSubtraction;
     195var
     196  Dest, Src: T;
     197begin
     198  Dest := ReadNext;
     199  Src := ReadNext;
     200  Registers[Dest] := Registers[Dest] - Registers[Src];
     201end;
     202
     203procedure TCPU.OpcodeMultiplication;
     204var
     205  Dest, Src: T;
     206begin
     207  Dest := ReadNext;
     208  Src := ReadNext;
     209  Registers[Dest] := Registers[Dest] * Registers[Src];
     210end;
     211
     212procedure TCPU.OpcodeDivision;
     213var
     214  Dest, Src: T;
     215begin
     216  Dest := ReadNext;
     217  Src := ReadNext;
     218  Registers[Dest] := Registers[Dest] div Registers[Src];
     219end;
     220
     221procedure TCPU.OpcodeShiftLeft;
     222var
     223  Dest, Src: T;
     224begin
     225  Dest := ReadNext;
     226  Src := ReadNext;
     227  Registers[Dest] := Registers[Dest] shl Registers[Src];
     228end;
     229
     230procedure TCPU.OpcodeShiftRight;
     231var
     232  Src, Dest: T;
     233begin
     234  Dest := ReadNext;
     235  Src := ReadNext;
     236  Registers[Dest] := Registers[Dest] shr Registers[Src];
     237end;
     238
     239procedure TCPU.OpcodeAnd;
     240var
     241  Src, Dest: T;
     242begin
     243  Dest := ReadNext;
     244  Src := ReadNext;
     245  Registers[Dest] := Registers[Dest] and Registers[Src];
     246end;
     247
     248procedure TCPU.OpcodeOr;
     249var
     250  Src, Dest: T;
     251begin
     252  Dest := ReadNext;
     253  Src := ReadNext;
     254  Registers[Dest] := Registers[Dest] or Registers[Src];
     255end;
     256
     257procedure TCPU.OpcodeXor;
     258var
     259  Src, Dest: T;
     260begin
     261  Dest := ReadNext;
     262  Src := ReadNext;
     263  Registers[Dest] := Registers[Dest] xor Registers[Src];
     264end;
     265
     266procedure TCPU.OpcodeJump;
     267var
     268  Reg: T;
     269begin
     270  Reg := ReadNext;
     271  IP := Registers[Reg];
     272end;
     273
     274procedure TCPU.OpcodeJumpConditional;
     275var
     276  Reg: T;
     277begin
     278  Reg := ReadNext;
     279  if Condition then
     280    IP := Registers[Reg];
     281end;
     282
     283procedure TCPU.OpcodeJumpRelative;
     284var
     285  Reg: T;
     286begin
     287  Reg := ReadNext;
     288  IP := IP + Registers[Reg];
     289end;
     290
     291procedure TCPU.OpcodeJumpRelativeConditional;
     292var
     293  Reg: T;
     294begin
     295  Reg := ReadNext;
     296  if Condition then
     297    IP := IP + Registers[Reg];
     298end;
     299
     300procedure TCPU.OpcodePush;
     301var
     302  Reg: T;
     303begin
     304  SP := SP - 1;
     305  Reg := ReadNext;
     306  Memory[SP] := Registers[Reg];
     307end;
     308
     309procedure TCPU.OpcodePop;
     310var
     311  Reg: T;
     312begin
     313  Reg := ReadNext;
     314  Registers[Reg] := Memory[SP];
     315  SP := SP + 1;
     316end;
     317
     318procedure TCPU.OpcodeCall;
     319var
     320  Reg: T;
     321begin
     322  SP := SP - 1;
     323  Reg := ReadNext;
     324  Memory[SP] := IP;
     325  IP := Registers[Reg];
     326end;
     327
     328procedure TCPU.OpcodeReturn;
     329begin
     330  IP := Memory[SP];
     331  SP := SP + 1;
     332end;
     333
     334procedure TCPU.OpcodeInput;
     335var
     336  Src, Dest: T;
     337begin
     338  Dest := ReadNext;
     339  Src := ReadNext;
     340  if Assigned(FOnInput) then
     341    Registers[Dest] := FOnInput(Registers[Src]);
     342end;
     343
     344procedure TCPU.OpcodeOutput;
     345var
     346  Dest, Src: T;
     347begin
     348  Dest := ReadNext;
     349  Src := ReadNext;
     350  if Assigned(FOnOutput) then
     351    FOnOutput(Registers[Dest], Registers[Src]);
     352end;
     353
     354procedure TCPU.OpcodeTestZero;
     355var
     356  Reg: T;
     357begin
     358  Reg := ReadNext;
     359  Condition := Registers[Reg] = 0;
     360end;
     361
     362procedure TCPU.OpcodeTestNotZero;
     363var
     364  Reg: T;
     365begin
     366  Reg := ReadNext;
     367  Condition := Registers[Reg] <> 0;
     368end;
     369
     370procedure TCPU.OpcodeExchange;
     371var
     372  Dest, Src, Temp: T;
     373begin
     374  Dest := ReadNext;
     375  Src := ReadNext;
     376  Temp := Registers[Dest];
     377  Registers[Dest] := Registers[Src];
     378  Registers[Src] := Temp;
     379end;
     380
    65381
    66382procedure TCPU.Step;
    67383var
    68384  Opcode: TOpcode;
    69   Reg: T;
    70   Src: T;
    71   Dest: T;
    72   Temp: T;
     385  Handler: TOpcodeHandler;
    73386begin
    74387  Opcode := TOpcode(ReadNext);
    75   case Opcode of
    76     opNop: ;
    77     opHalt: Terminated := True;
    78     opLD: begin
    79       Dest := ReadNext;
    80       Src := ReadNext;
    81       Registers[Dest] := Registers[Src];
    82     end;
    83     opLDC: begin
    84       Reg := ReadNext;
    85       Registers[Reg] := ReadNext;
    86     end;
    87     opLDM: begin
    88       Dest := ReadNext;
    89       Src := ReadNext;
    90       Registers[Dest] := Memory[Registers[Src]];
    91     end;
    92     opSTM: begin
    93       Dest := ReadNext;
    94       Src := ReadNext;
    95       Memory[Registers[Dest]] := Registers[Src];
    96     end;
    97     opLDMD: begin
    98       Dest := ReadNext;
    99       Src := ReadNext;
    100       Reg := ReadNext;
    101       Registers[Dest] := Memory[Registers[Src] + Registers[Reg]];
    102     end;
    103     opSTMD: begin
    104       Dest := ReadNext;
    105       Reg := ReadNext;
    106       Src := ReadNext;
    107       Memory[Registers[Dest] + Registers[Reg]] := Registers[Src];
    108     end;
    109     opInc: begin
    110       Reg := ReadNext;
    111       Registers[Reg] := Registers[Reg] + 1;
    112     end;
    113     opDec: begin
    114       Reg := ReadNext;
    115       Registers[Reg] := Registers[Reg] - 1;
    116     end;
    117     opAdd: begin
    118       Dest := ReadNext;
    119       Src := ReadNext;
    120       Registers[Dest] := Registers[Dest] + Registers[Src];
    121     end;
    122     opSub: begin
    123       Dest := ReadNext;
    124       Src := ReadNext;
    125       Registers[Dest] := Registers[Dest] - Registers[Src];
    126     end;
    127     opMul: begin
    128       Dest := ReadNext;
    129       Src := ReadNext;
    130       Registers[Dest] := Registers[Dest] * Registers[Src];
    131     end;
    132     opDiv: begin
    133       Dest := ReadNext;
    134       Src := ReadNext;
    135       Registers[Dest] := Registers[Dest] div Registers[Src];
    136     end;
    137     opShl: begin
    138       Dest := ReadNext;
    139       Src := ReadNext;
    140       Registers[Dest] := Registers[Dest] shl Registers[Src];
    141     end;
    142     opShr: begin
    143       Dest := ReadNext;
    144       Src := ReadNext;
    145       Registers[Dest] := Registers[Dest] shr Registers[Src];
    146     end;
    147     opAnd: begin
    148       Dest := ReadNext;
    149       Src := ReadNext;
    150       Registers[Dest] := Registers[Dest] and Registers[Src];
    151     end;
    152     opOr: begin
    153       Dest := ReadNext;
    154       Src := ReadNext;
    155       Registers[Dest] := Registers[Dest] or Registers[Src];
    156     end;
    157     opXor: begin
    158       Dest := ReadNext;
    159       Src := ReadNext;
    160       Registers[Dest] := Registers[Dest] xor Registers[Src];
    161     end;
    162     opJp: begin
    163       Reg := ReadNext;
    164       IP := Registers[Reg];
    165     end;
    166     opJpc: begin
    167       Reg := ReadNext;
    168       if Condition then
    169         IP := Registers[Reg];
    170     end;
    171     opJr: begin
    172       Reg := ReadNext;
    173       IP := IP + Registers[Reg];
    174     end;
    175     opJrc: begin
    176       Reg := ReadNext;
    177       if Condition then
    178         IP := IP + Registers[Reg];
    179     end;
    180     opPush: begin
    181       SP := SP - 1;
    182       Reg := ReadNext;
    183       Memory[SP] := Registers[Reg];
    184     end;
    185     opPop: begin
    186       Reg := ReadNext;
    187       Registers[Reg] := Memory[SP];
    188       SP := SP + 1;
    189     end;
    190     opCall: begin
    191       SP := SP - 1;
    192       Reg := ReadNext;
    193       Memory[SP] := IP;
    194       IP := Registers[Reg];
    195     end;
    196     opRet: begin
    197       Reg := ReadNext;
    198       IP := Memory[SP];
    199       SP := SP + 1;
    200     end;
    201     opIn: begin
    202       Dest := ReadNext;
    203       Src := ReadNext;
    204       if Assigned(FOnInput) then
    205         Registers[Dest] := FOnInput(Registers[Src]);
    206     end;
    207     opOut: begin
    208       Dest := ReadNext;
    209       Src := ReadNext;
    210       if Assigned(FOnOutput) then
    211         FOnOutput(Registers[Dest], Registers[Src]);
    212     end;
    213     opTstZ: begin
    214       Reg := ReadNext;
    215       Condition := Registers[Reg] = 0;
    216     end;
    217     opTstNZ: begin
    218       Reg := ReadNext;
    219       Condition := Registers[Reg] <> 0;
    220     end;
    221     opXchg: begin
    222       Dest := ReadNext;
    223       Src := ReadNext;
    224       Temp := Registers[Dest];
    225       Registers[Dest] := Registers[Src];
    226       Registers[Src] := Temp;
    227     end;
    228     else raise Exception.Create('Unknown opcode: ' + IntToStr(Integer(Opcode)));
    229   end;
     388  if Opcode <= High(TOpcode) then begin
     389    Handler := OpcodeHandlers[Opcode];
     390    if Assigned(Handler) then Handler
     391    else raise Exception.Create('Missing handler for opcode + ' + IntToStr(Integer(Opcode)));
     392  end else raise Exception.Create('Unknown opcode: ' + IntToStr(Integer(Opcode)));
     393end;
     394
     395procedure TCPU.AddOpcode(Opcode: TOpcode; Handler: TOpcodeHandler);
     396begin
     397  OpcodeHandlers[Opcode] := Handler;
     398end;
     399
     400procedure TCPU.InitOpcodes;
     401begin
     402  AddOpcode(opNop, @OpcodeNop);
     403  AddOpcode(opHalt, @OpcodeHalt);
     404  AddOpcode(opAnd, @OpcodeAnd);
     405  AddOpcode(opOr, @OpcodeOr);
     406  AddOpcode(opXor, @OpcodeXor);
     407  AddOpcode(opLD, @OpcodeLoad);
     408  AddOpcode(opLDC, @OpcodeLoadConst);
     409  AddOpcode(opLDM, @OpcodeLoadMemory);
     410  AddOpcode(opSTM, @OpcodeStoreMemory);
     411  AddOpcode(opLDMD, @OpcodeLoadMemoryDisplacement);
     412  AddOpcode(opSTMD, @OpcodeStoreMemoryDisplacement);
     413  AddOpcode(opCall, @OpcodeCall);
     414  AddOpcode(opRet, @OpcodeReturn);
     415  AddOpcode(opPush, @OpcodePush);
     416  AddOpcode(opPop, @OpcodePop);
     417  AddOpcode(opJP, @OpcodeJump);
     418  AddOpcode(opJpc, @OpcodeJumpConditional);
     419  AddOpcode(opJR, @OpcodeJumpRelative);
     420  AddOpcode(opJRC, @OpcodeJumpRelativeConditional);
     421  AddOpcode(opAdd, @OpcodeAddition);
     422  AddOpcode(opSub, @OpcodeSubtraction);
     423  AddOpcode(opMul, @OpcodeMultiplication);
     424  AddOpcode(opDiv, @OpcodeDivision);
     425  AddOpcode(opXchg, @OpcodeExchange);
     426  AddOpcode(opShl, @OpcodeShiftLeft);
     427  AddOpcode(opShr, @OpcodeShiftRight);
     428  AddOpcode(opIn, @OpcodeInput);
     429  AddOpcode(opOut, @OpcodeOutput);
     430  AddOpcode(opInc, @OpcodeIncrement);
     431  AddOpcode(opDec, @OpcodeDecrement);
     432  AddOpcode(opTstNZ, @OpcodeTestNotZero);
     433  AddOpcode(opTstZ, @OpcodeTestZero);
    230434end;
    231435
Note: See TracChangeset for help on using the changeset viewer.