Changeset 177


Ignore:
Timestamp:
Apr 12, 2019, 2:03:51 PM (5 years ago)
Author:
chronos
Message:
  • Modified: Better use data and address prefix opcodes.
  • Added: More instructions.
Location:
branches/virtualcpu4
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/virtualcpu4/UCpu.pas

    r175 r177  
    1010type
    1111  TOpcode = (opNop, opHalt, opLoad, opLoadi, opJump, opJumpZero, opJumpNotZero,
    12     opJumpRel, opNeg, opClear, opLoadMem, opStoreMem, opExchg, opPush, opPop,
    13     opCall, opRet, opAdd, opAddi, opSub, opSubi, opInc, opDec, opIn, opOut, opShl,
    14     opShr, opDataPrefix8, opDataPrefix16, opDataPrefix32, opDataPrefix64,
    15     opDataSize, opAddrSize, opTest, opAnd, opOr, opXor, opLddr, opLdir);
     12    opJumpRel, opJumpRelZero, opJumpRelNotZero, opNeg, opClear, opLoadMem,
     13    opStoreMem, opExchg, opPush, opPop, opCall, opRet, opAdd, opAddi, opSub,
     14    opSubi, opInc, opDec, opIn, opOut, opShl, opShr, opDataPrefix8, opDataPrefix16,
     15    opDataPrefix32, opDataPrefix64, opDataSize, opAddrSize, opTest, opAnd, opOr,
     16    opXor, opLddr, opLdir, opMul, opDiv, opMod, opAddrPrefix8, opAddrPrefix16,
     17    opAddrPrefix32, opAddrPrefix64);
     18
     19  TAddressSigned = Int64;
    1620  TAddress = QWord;
    1721  PAddress = ^TAddress;
     
    4448    DataSizeLast: TBitWidth;
    4549    DataSizePrefix: TBitWidth;
     50    AddrSizeLast: TBitWidth;
     51    AddrSizePrefix: TBitWidth;
    4652    Z: Boolean;
    4753    Thread: TCpuThread;
     
    5460    procedure InstJumpNotZero;
    5561    procedure InstJumpRel;
     62    procedure InstJumpRelZero;
     63    procedure InstJumpRelNotZero;
    5664    procedure InstTest;
    5765    procedure InstNeg;
     
    6876    procedure InstSub;
    6977    procedure InstSubi;
     78    procedure InstMul;
     79    procedure InstDiv;
     80    procedure InstMod;
    7081    procedure InstInc;
    7182    procedure InstDec;
     
    8495    procedure InstDataPrefix64;
    8596    procedure InstDataSize;
     97    procedure InstAddrPrefix8;
     98    procedure InstAddrPrefix16;
     99    procedure InstAddrPrefix32;
     100    procedure InstAddrPrefix64;
    86101    procedure InstAddrSize;
    87102    procedure InitInstructions;
     
    92107    IP: TAddress;
    93108    SP: TAddress;
    94     AddressSize: TBitWidth;
     109    AddrSize: TBitWidth;
    95110    DataSize: TBitWidth;
    96111    procedure Run;
     
    103118    function Read64: QWord; inline;
    104119    function ReadAddress: TAddress; inline;
     120    function ReadAddressSigned: TAddressSigned; inline;
    105121    constructor Create;
    106122    destructor Destroy; override;
     
    118134  end;
    119135
     136const
     137  BitWidthBytes: array[TBitWidth] of Byte = (0, 1, 2, 4, 8);
     138
    120139implementation
    121140
     
    167186procedure TCpu.InstJump;
    168187begin
    169   case AddressSize of
    170     bw8: IP := Read8;
    171     bw16: IP := Read16;
    172     bw32: IP := Read32;
    173     bw64: IP := Read64;
    174   end;
     188  IP := ReadAddress;
     189end;
     190
     191procedure TCpu.InstJumpZero;
     192var
     193  Addr: TAddress;
     194begin
     195  Addr := ReadAddress;
     196  if Z then IP := Addr;
     197end;
     198
     199procedure TCpu.InstJumpNotZero;
     200var
     201  Addr: TAddress;
     202begin
     203  Addr := ReadAddress;
     204  if not Z then IP := Addr;
    175205end;
    176206
    177207procedure TCpu.InstJumpRel;
    178208begin
    179   case AddressSize of
    180     bw8: PByte(@IP)^ := Byte(IP) + Read8;
    181     bw16: PWord(@IP)^ := Word(IP) + Read16;
    182     bw32: PDWord(@IP)^ := DWord(IP) + Read32;
    183     bw64: PQWord(@IP)^ := QWord(IP) + Read64;
    184   end;
     209  IP := IP + ReadAddressSigned;
     210end;
     211
     212procedure TCpu.InstJumpRelZero;
     213var
     214  Addr: TAddressSigned;
     215begin
     216  Addr := ReadAddressSigned;
     217  if Z then IP := IP + Addr;
     218end;
     219
     220procedure TCpu.InstJumpRelNotZero;
     221var
     222  Addr: TAddressSigned;
     223begin
     224  Addr := ReadAddressSigned;
     225  if not Z then IP := IP + Addr;
    185226end;
    186227
     
    227268  R1 := Read8;
    228269  R2 := Read8;
    229   case AddressSize of
     270  case AddrSize of
    230271    bw8: case DataSize of
    231272      bw8: Registers[R1].B := PByte(Memory + PByte(@Registers[R2])^)^;
     
    261302  R1 := Read8;
    262303  R2 := Read8;
    263   case AddressSize of
     304  case AddrSize of
    264305    bw8: case DataSize of
    265306      bw8: PByte(Memory + PByte(@Registers[R1])^)^ := Registers[R2].B;
     
    368409  Dest: TRegister;
    369410begin
    370   case AddressSize of
     411  case AddrSize of
    371412    bw8: begin
    372413      Dest.B := Read8;
     
    398439procedure TCpu.InstRet;
    399440begin
    400   case AddressSize of
     441  case AddrSize of
    401442    bw8: begin
    402443      IP := PByte(Memory + SP)^;
     
    472513end;
    473514
     515procedure TCpu.InstMul;
     516var
     517  R1, R2: TRegIndex;
     518begin
     519  R1 := Read8;
     520  R2 := Read8;
     521  case DataSize of
     522    bw8: Registers[R1].B := Registers[R1].B * Registers[R2].B;
     523    bw16: Registers[R1].W := Registers[R1].W * Registers[R2].W;
     524    bw32: Registers[R1].D := Registers[R1].D * Registers[R2].D;
     525    bw64: Registers[R1].Q := Registers[R1].Q * Registers[R2].Q;
     526  end;
     527end;
     528
     529procedure TCpu.InstDiv;
     530var
     531  R1, R2: TRegIndex;
     532begin
     533  R1 := Read8;
     534  R2 := Read8;
     535  case DataSize of
     536    bw8: Registers[R1].B := Registers[R1].B div Registers[R2].B;
     537    bw16: Registers[R1].W := Registers[R1].W div Registers[R2].W;
     538    bw32: Registers[R1].D := Registers[R1].D div Registers[R2].D;
     539    bw64: Registers[R1].Q := Registers[R1].Q div Registers[R2].Q;
     540  end;
     541end;
     542
     543procedure TCpu.InstMod;
     544var
     545  R1, R2: TRegIndex;
     546begin
     547  R1 := Read8;
     548  R2 := Read8;
     549  case DataSize of
     550    bw8: Registers[R1].B := Registers[R1].B mod Registers[R2].B;
     551    bw16: Registers[R1].W := Registers[R1].W mod Registers[R2].W;
     552    bw32: Registers[R1].D := Registers[R1].D mod Registers[R2].D;
     553    bw64: Registers[R1].Q := Registers[R1].Q mod Registers[R2].Q;
     554  end;
     555end;
     556
    474557procedure TCpu.InstInc;
    475558var
     
    498581end;
    499582
    500 procedure TCpu.InstJumpZero;
    501 begin
    502   case AddressSize of
    503     bw8: if Z then IP := Read8 else Read8;
    504     bw16: if Z then IP := Read16 else Read16;
    505     bw32: if Z then IP := Read32 else Read32;
    506     bw64: if Z then IP := Read64 else Read64;
    507   end;
    508 end;
    509 
    510 procedure TCpu.InstJumpNotZero;
    511 begin
    512   case AddressSize of
    513     bw8: if not Z then IP := Read8 else Read8;
    514     bw16: if not Z then IP := Read16 else Read16;
    515     bw32: if not Z then IP := Read32 else Read32;
    516     bw64: if not Z then IP := Read64 else Read64;
    517   end;
    518 end;
    519 
    520583procedure TCpu.InstIn;
    521584var
     
    652715  Dest := Read8;
    653716  Count := Read8;
    654   case AddressSize of
     717  case AddrSize of
    655718    bw8: while Registers[Count].B > 0 do begin
    656719      case DataSize of
     
    763826  Dest := Read8;
    764827  Count := Read8;
    765   case AddressSize of
     828  case AddrSize of
    766829    bw8: while Registers[Count].B > 0 do begin
    767830      case DataSize of
     
    892955end;
    893956
     957procedure TCpu.InstAddrPrefix8;
     958begin
     959  AddrSizePrefix := bw8;
     960end;
     961
     962procedure TCpu.InstAddrPrefix16;
     963begin
     964  AddrSizePrefix := bw16;
     965end;
     966
     967procedure TCpu.InstAddrPrefix32;
     968begin
     969  AddrSizePrefix := bw32;
     970end;
     971
     972procedure TCpu.InstAddrPrefix64;
     973begin
     974  AddrSizePrefix := bw64;
     975end;
     976
    894977procedure TCpu.InstAddrSize;
    895978begin
    896   AddressSize := TBitWidth(Read8);
     979  AddrSize := TBitWidth(Read8);
    897980end;
    898981
     
    907990  Instructions[opJumpZero] := InstJumpZero;
    908991  Instructions[opJumpRel] := InstJumpRel;
     992  Instructions[opJumpRelNotZero] := InstJumpRelNotZero;
     993  Instructions[opJumpRelZero] := InstJumpRelZero;
    909994  Instructions[opLoadMem] := InstLoadMem;
    910995  Instructions[opStoreMem] := InstStoreMem;
     
    9321017  Instructions[opDataPrefix32] := InstDataPrefix64;
    9331018  Instructions[opAddrSize] := InstAddrSize;
     1019  Instructions[opAddrPrefix8] := InstAddrPrefix8;
     1020  Instructions[opAddrPrefix16] := InstAddrPrefix16;
     1021  Instructions[opAddrPrefix32] := InstAddrPrefix32;
     1022  Instructions[opAddrPrefix32] := InstAddrPrefix64;
    9341023  Instructions[opTest] := InstTest;
    9351024  Instructions[opAnd] := InstAnd;
     
    9381027  Instructions[opLdir] := InstLdir;
    9391028  Instructions[opLddr] := InstLddr;
     1029  Instructions[opMul] := InstMul;
     1030  Instructions[opDiv] := InstDiv;
     1031  Instructions[opMod] := InstMod;
    9401032end;
    9411033
     
    9591051    DataSize := DataSizePrefix;
    9601052    DataSizePrefix := bwNone;
     1053  end;
     1054  if AddrSizePrefix <> bwNone then begin
     1055    AddrSizeLast := AddrSize;
     1056    AddrSize := AddrSizePrefix;
     1057    AddrSizePrefix := bwNone;
    9611058  end;
    9621059  Opcode := Read8;
     
    9691066    DataSizeLast := bwNone;
    9701067  end;
     1068  if AddrSizeLast <> bwNone then begin
     1069    AddrSize := AddrSizeLast;
     1070    AddrSizeLast := bwNone;
     1071  end;
    9711072  IP := IP mod MemSize(Memory);
    9721073  Inc(FTicks);
     
    10211122function TCpu.ReadAddress: TAddress;
    10221123begin
    1023   case AddressSize of
     1124  case AddrSize of
    10241125    bw8: Result := Read8;
    10251126    bw16: Result := Read16;
     
    10291130end;
    10301131
     1132function TCpu.ReadAddressSigned: TAddressSigned;
     1133begin
     1134  case AddrSize of
     1135    bw8: Result := ShortInt(Read8);
     1136    bw16: Result := SmallInt(Read16);
     1137    bw32: Result := Integer(Read32);
     1138    bw64: Result := Int64(Read64);
     1139  end;
     1140end;
     1141
    10311142constructor TCpu.Create;
    10321143begin
    10331144  DataSize := bw16;
    1034   AddressSize := bw16;
     1145  AddrSize := bw16;
    10351146  SetLength(Registers, 32);
    10361147  InitInstructions;
  • branches/virtualcpu4/UFormMain.pas

    r176 r177  
    197197  R4 := 4;
    198198  with InstructionWriter do begin
     199    Init;
    199200    // Print Hello world text
    200201    LabelText := 200;
     
    218219    Decrement(R2);
    219220    Test(R2);
    220     JumpNotZero(LabelClearScreen);
     221    AddrPrefix8; JumpRelNotZero(LabelClearScreen);
    221222
    222223    // Update screen area
  • branches/virtualcpu4/UInstructionWriter.pas

    r174 r177  
    1313
    1414  TInstructionWriter = class
     15  private
     16    DataSizeLast: TBitWidth;
     17    DataSizePrefix: TBitWidth;
     18    AddrSizeLast: TBitWidth;
     19    AddrSizePrefix: TBitWidth;
     20    procedure PrefixBegin;
     21    procedure PrefixEnd;
     22  public
    1523    Cpu: TCpu;
    1624    IP: Integer;
     25    DataSize: TBitWidth;
     26    AddrSize: TBitWidth;
     27    procedure Init;
    1728    procedure Write8(Value: Byte);
    1829    procedure Write16(Value: Word);
     
    2031    procedure Write64(Value: QWord);
    2132    procedure WriteAddress(Value: TAddress);
     33    procedure WriteAddressSigned(Value: TAddressSigned);
    2234    procedure WriteData(Value: QWord);
    2335    procedure WriteString(Text: string);
     
    2739    procedure Increment(Reg: TRegIndex);
    2840    procedure Decrement(Reg: TRegIndex);
    29     procedure Jump(Value: QWord);
    30     procedure JumpNotZero(Value: QWord);
     41    procedure Jump(Addr: QWord);
     42    procedure JumpNotZero(Addr: QWord);
     43    procedure JumpZero(Addr: QWord);
     44    procedure JumpRel(Addr: QWord);
     45    procedure JumpRelNotZero(Addr: QWord);
     46    procedure JumpRelZero(Addr: QWord);
    3147    procedure DataPrefix8;
    3248    procedure DataPrefix16;
    3349    procedure DataPrefix32;
    3450    procedure DataPrefix64;
     51    procedure AddrPrefix8;
     52    procedure AddrPrefix16;
     53    procedure AddrPrefix32;
     54    procedure AddrPrefix64;
    3555    procedure StoreMem(RegAddr, RegSrc: TRegIndex);
    3656    procedure LoadMem(RegDst, RegAddr: TRegIndex);
     
    4060  end;
    4161
     62  { TAssembler }
     63
     64  TAssembler = class
     65    Source: TStringList;
     66    Dest: array of Byte;
     67    procedure Compile;
     68  end;
     69
     70  TDisassembler = class
     71
     72  end;
     73
     74const
     75  OpcodeName: array[TOpcode] of string = ('NOP', 'HALT', 'LD', 'LDI', 'JP', 'JPZ',
     76    'JPNZ', 'JR', 'JRZ', 'JRNZ', 'NEG', 'CLR', 'LDM', 'STM', 'EX', 'PUSH', 'POP',
     77    'CALL', 'RET', 'ADD', 'ADDI', 'SUB', 'SUBI', 'INC', 'DEC', 'IN', 'OUT',
     78    'SHL', 'SHR', 'DP8', 'DP16', 'DP32', 'DP64', 'DS', 'AS', 'TEST', 'AND', 'OR',
     79    'XOR', 'LDDR', 'LDIR', 'MUL', 'DIV', 'MOD', 'AP8', 'AP16', 'AP32', 'AP64');
    4280
    4381implementation
    4482
     83{ TAssembler }
     84
     85procedure TAssembler.Compile;
     86begin
     87
     88end;
     89
    4590{ TInstructionWriter }
    4691
    4792procedure TInstructionWriter.Nop;
    4893begin
     94  PrefixBegin;
    4995  Write8(Byte(opNop));
     96  PrefixEnd;
    5097end;
    5198
    5299procedure TInstructionWriter.Halt;
    53100begin
     101  PrefixBegin;
    54102  Write8(Byte(opHalt));
     103  PrefixEnd;
    55104end;
    56105
    57106procedure TInstructionWriter.Loadi(Reg: TRegIndex; Value: QWord);
    58107begin
     108  PrefixBegin;
    59109  Write8(Byte(opLoadi));
    60110  Write8(Reg);
    61111  WriteData(Value);
     112  PrefixEnd;
    62113end;
    63114
    64115procedure TInstructionWriter.Increment(Reg: TRegIndex);
    65116begin
     117  PrefixBegin;
    66118  Write8(Byte(opInc));
    67119  Write8(Reg);
     120  PrefixEnd;
    68121end;
    69122
    70123procedure TInstructionWriter.Decrement(Reg: TRegIndex);
    71124begin
     125  PrefixBegin;
    72126  Write8(Byte(opDec));
    73127  Write8(Reg);
    74 end;
    75 
    76 procedure TInstructionWriter.Jump(Value: QWord);
    77 begin
     128  PrefixEnd;
     129end;
     130
     131procedure TInstructionWriter.Jump(Addr: QWord);
     132begin
     133  PrefixBegin;
    78134  Write8(Byte(opJump));
    79   WriteAddress(Value);
    80 end;
    81 
    82 procedure TInstructionWriter.JumpNotZero(Value: QWord);
    83 begin
     135  WriteAddress(Addr);
     136  PrefixEnd;
     137end;
     138
     139procedure TInstructionWriter.JumpNotZero(Addr: QWord);
     140begin
     141  PrefixBegin;
    84142  Write8(Byte(opJumpNotZero));
    85   WriteAddress(Value);
     143  WriteAddress(Addr);
     144  PrefixEnd;
     145end;
     146
     147procedure TInstructionWriter.JumpZero(Addr: QWord);
     148begin
     149  PrefixBegin;
     150  Write8(Byte(opJumpZero));
     151  WriteAddress(Addr);
     152  PrefixEnd;
     153end;
     154
     155procedure TInstructionWriter.JumpRel(Addr: QWord);
     156var
     157  NextIP: QWord;
     158begin
     159  PrefixBegin;
     160  NextIP := IP + 1 + BitWidthBytes[Cpu.AddrSize];
     161  Write8(Byte(opJumpRel));
     162  WriteAddressSigned(Int64(Addr) - Int64(NextIP));
     163  PrefixEnd;
     164end;
     165
     166procedure TInstructionWriter.JumpRelNotZero(Addr: QWord);
     167var
     168  NextIP: QWord;
     169begin
     170  PrefixBegin;
     171  NextIP := IP + 1 + BitWidthBytes[Cpu.AddrSize];
     172  Write8(Byte(opJumpRelNotZero));
     173  WriteAddressSigned(Int64(Addr) - Int64(NextIP));
     174  PrefixEnd;
     175end;
     176
     177procedure TInstructionWriter.JumpRelZero(Addr: QWord);
     178var
     179  NextIP: QWord;
     180begin
     181  PrefixBegin;
     182  NextIP := IP + 1 + BitWidthBytes[Cpu.AddrSize];
     183  Write8(Byte(opJumpRelZero));
     184  WriteAddressSigned(Int64(Addr) - Int64(NextIP));
     185  if AddrSizeLast <> bwNone then AddrSize := AddrSizeLast;
     186  PrefixEnd;
    86187end;
    87188
    88189procedure TInstructionWriter.DataPrefix8;
    89190begin
     191  DataSizePrefix := bw8;
    90192  Write8(Byte(opDataPrefix8));
    91193end;
     
    93195procedure TInstructionWriter.DataPrefix16;
    94196begin
     197  DataSizePrefix := bw16;
    95198  Write8(Byte(opDataPrefix16));
    96199end;
     
    98201procedure TInstructionWriter.DataPrefix32;
    99202begin
     203  DataSizePrefix := bw32;
    100204  Write8(Byte(opDataPrefix32));
    101205end;
     
    103207procedure TInstructionWriter.DataPrefix64;
    104208begin
     209  DataSizePrefix := bw64;
    105210  Write8(Byte(opDataPrefix64));
     211end;
     212
     213procedure TInstructionWriter.AddrPrefix8;
     214begin
     215  AddrSizePrefix := bw8;
     216  Write8(Byte(opAddrPrefix8));
     217end;
     218
     219procedure TInstructionWriter.AddrPrefix16;
     220begin
     221  AddrSizePrefix := bw16;
     222  Write8(Byte(opAddrPrefix16));
     223end;
     224
     225procedure TInstructionWriter.AddrPrefix32;
     226begin
     227  AddrSizePrefix := bw32;
     228  Write8(Byte(opAddrPrefix32));
     229end;
     230
     231procedure TInstructionWriter.AddrPrefix64;
     232begin
     233  AddrSizePrefix := bw64;
     234  Write8(Byte(opAddrPrefix64));
    106235end;
    107236
     
    115244procedure TInstructionWriter.LoadMem(RegDst, RegAddr: TRegIndex);
    116245begin
     246  PrefixBegin;
    117247  Write8(Byte(opLoadMem));
    118248  Write8(RegDst);
    119249  Write8(RegAddr);
     250  PrefixEnd;
    120251end;
    121252
    122253procedure TInstructionWriter.Output(Port: TAddress; Reg: TRegIndex);
    123254begin
     255  PrefixBegin;
    124256  Write8(Byte(opOut));
    125257  WriteAddress(Port);
    126258  Write8(Reg);
     259  PrefixEnd;
    127260end;
    128261
    129262procedure TInstructionWriter.Input(Reg: TRegIndex; Port: TAddress);
    130263begin
     264  PrefixBegin;
    131265  Write8(Byte(opIn));
    132266  Write8(Reg);
    133267  WriteAddress(Port);
     268  PrefixEnd;
    134269end;
    135270
    136271procedure TInstructionWriter.Test(Reg: TRegIndex);
    137272begin
     273  PrefixBegin;
    138274  Write8(Byte(opTest));
    139275  Write8(Reg);
     276  Prefixend;
    140277end;
    141278
     
    148285end;
    149286
     287procedure TInstructionWriter.PrefixBegin;
     288begin
     289  if DataSizePrefix <> bwNone then begin
     290    DataSizeLast := DataSize;
     291    DataSize := DataSizePrefix;
     292    DataSizePrefix := bwNone;
     293  end;
     294  if AddrSizePrefix <> bwNone then begin
     295    AddrSizeLast := AddrSize;
     296    AddrSize := AddrSizePrefix;
     297    AddrSizePrefix := bwNone;
     298  end;
     299end;
     300
     301procedure TInstructionWriter.PrefixEnd;
     302begin
     303  if DataSizeLast <> bwNone then begin
     304    DataSize := DataSizeLast;
     305    DataSizeLast := bwNone;
     306  end;
     307  if AddrSizeLast <> bwNone then begin
     308    AddrSize := AddrSizeLast;
     309    AddrSizeLast := bwNone;
     310  end;
     311end;
     312
     313procedure TInstructionWriter.Init;
     314begin
     315  DataSize := Cpu.DataSize;
     316  AddrSize := Cpu.AddrSize;
     317end;
     318
    150319procedure TInstructionWriter.Write8(Value: Byte);
    151320begin
     
    174343procedure TInstructionWriter.WriteAddress(Value: TAddress);
    175344begin
    176   case Cpu.AddressSize of
     345  case AddrSize of
    177346    bw8: Write8(Value);
    178347    bw16: Write16(Value);
     
    182351end;
    183352
     353procedure TInstructionWriter.WriteAddressSigned(Value: TAddressSigned);
     354begin
     355  case AddrSize of
     356    bw8: Write8(Byte(Value));
     357    bw16: Write16(Word(Value));
     358    bw32: Write32(DWord(Value));
     359    bw64: Write64(QWord(Value));
     360  end;
     361end;
     362
    184363procedure TInstructionWriter.WriteData(Value: QWord);
    185364begin
    186   case Cpu.DataSize of
     365  case DataSize of
    187366    bw8: Write8(Value);
    188367    bw16: Write16(Value);
  • branches/virtualcpu4/UMachine.pas

    r176 r177  
    5151  Cpu.OnOutput := CpuOutput;
    5252  Cpu.DataSize := bw32;
    53   Cpu.AddressSize := bw32;
     53  Cpu.AddrSize := bw32;
    5454  Screen := TScreen.Create;
    5555  Screen.Size := Point(320, 240);
Note: See TracChangeset for help on using the changeset viewer.