Changeset 177
- Timestamp:
- Apr 12, 2019, 2:03:51 PM (6 years ago)
- Location:
- branches/virtualcpu4
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/virtualcpu4/UCpu.pas
r175 r177 10 10 type 11 11 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; 16 20 TAddress = QWord; 17 21 PAddress = ^TAddress; … … 44 48 DataSizeLast: TBitWidth; 45 49 DataSizePrefix: TBitWidth; 50 AddrSizeLast: TBitWidth; 51 AddrSizePrefix: TBitWidth; 46 52 Z: Boolean; 47 53 Thread: TCpuThread; … … 54 60 procedure InstJumpNotZero; 55 61 procedure InstJumpRel; 62 procedure InstJumpRelZero; 63 procedure InstJumpRelNotZero; 56 64 procedure InstTest; 57 65 procedure InstNeg; … … 68 76 procedure InstSub; 69 77 procedure InstSubi; 78 procedure InstMul; 79 procedure InstDiv; 80 procedure InstMod; 70 81 procedure InstInc; 71 82 procedure InstDec; … … 84 95 procedure InstDataPrefix64; 85 96 procedure InstDataSize; 97 procedure InstAddrPrefix8; 98 procedure InstAddrPrefix16; 99 procedure InstAddrPrefix32; 100 procedure InstAddrPrefix64; 86 101 procedure InstAddrSize; 87 102 procedure InitInstructions; … … 92 107 IP: TAddress; 93 108 SP: TAddress; 94 Addr essSize: TBitWidth;109 AddrSize: TBitWidth; 95 110 DataSize: TBitWidth; 96 111 procedure Run; … … 103 118 function Read64: QWord; inline; 104 119 function ReadAddress: TAddress; inline; 120 function ReadAddressSigned: TAddressSigned; inline; 105 121 constructor Create; 106 122 destructor Destroy; override; … … 118 134 end; 119 135 136 const 137 BitWidthBytes: array[TBitWidth] of Byte = (0, 1, 2, 4, 8); 138 120 139 implementation 121 140 … … 167 186 procedure TCpu.InstJump; 168 187 begin 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; 189 end; 190 191 procedure TCpu.InstJumpZero; 192 var 193 Addr: TAddress; 194 begin 195 Addr := ReadAddress; 196 if Z then IP := Addr; 197 end; 198 199 procedure TCpu.InstJumpNotZero; 200 var 201 Addr: TAddress; 202 begin 203 Addr := ReadAddress; 204 if not Z then IP := Addr; 175 205 end; 176 206 177 207 procedure TCpu.InstJumpRel; 178 208 begin 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; 210 end; 211 212 procedure TCpu.InstJumpRelZero; 213 var 214 Addr: TAddressSigned; 215 begin 216 Addr := ReadAddressSigned; 217 if Z then IP := IP + Addr; 218 end; 219 220 procedure TCpu.InstJumpRelNotZero; 221 var 222 Addr: TAddressSigned; 223 begin 224 Addr := ReadAddressSigned; 225 if not Z then IP := IP + Addr; 185 226 end; 186 227 … … 227 268 R1 := Read8; 228 269 R2 := Read8; 229 case Addr essSize of270 case AddrSize of 230 271 bw8: case DataSize of 231 272 bw8: Registers[R1].B := PByte(Memory + PByte(@Registers[R2])^)^; … … 261 302 R1 := Read8; 262 303 R2 := Read8; 263 case Addr essSize of304 case AddrSize of 264 305 bw8: case DataSize of 265 306 bw8: PByte(Memory + PByte(@Registers[R1])^)^ := Registers[R2].B; … … 368 409 Dest: TRegister; 369 410 begin 370 case Addr essSize of411 case AddrSize of 371 412 bw8: begin 372 413 Dest.B := Read8; … … 398 439 procedure TCpu.InstRet; 399 440 begin 400 case Addr essSize of441 case AddrSize of 401 442 bw8: begin 402 443 IP := PByte(Memory + SP)^; … … 472 513 end; 473 514 515 procedure TCpu.InstMul; 516 var 517 R1, R2: TRegIndex; 518 begin 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; 527 end; 528 529 procedure TCpu.InstDiv; 530 var 531 R1, R2: TRegIndex; 532 begin 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; 541 end; 542 543 procedure TCpu.InstMod; 544 var 545 R1, R2: TRegIndex; 546 begin 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; 555 end; 556 474 557 procedure TCpu.InstInc; 475 558 var … … 498 581 end; 499 582 500 procedure TCpu.InstJumpZero;501 begin502 case AddressSize of503 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 begin512 case AddressSize of513 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 520 583 procedure TCpu.InstIn; 521 584 var … … 652 715 Dest := Read8; 653 716 Count := Read8; 654 case Addr essSize of717 case AddrSize of 655 718 bw8: while Registers[Count].B > 0 do begin 656 719 case DataSize of … … 763 826 Dest := Read8; 764 827 Count := Read8; 765 case Addr essSize of828 case AddrSize of 766 829 bw8: while Registers[Count].B > 0 do begin 767 830 case DataSize of … … 892 955 end; 893 956 957 procedure TCpu.InstAddrPrefix8; 958 begin 959 AddrSizePrefix := bw8; 960 end; 961 962 procedure TCpu.InstAddrPrefix16; 963 begin 964 AddrSizePrefix := bw16; 965 end; 966 967 procedure TCpu.InstAddrPrefix32; 968 begin 969 AddrSizePrefix := bw32; 970 end; 971 972 procedure TCpu.InstAddrPrefix64; 973 begin 974 AddrSizePrefix := bw64; 975 end; 976 894 977 procedure TCpu.InstAddrSize; 895 978 begin 896 Addr essSize := TBitWidth(Read8);979 AddrSize := TBitWidth(Read8); 897 980 end; 898 981 … … 907 990 Instructions[opJumpZero] := InstJumpZero; 908 991 Instructions[opJumpRel] := InstJumpRel; 992 Instructions[opJumpRelNotZero] := InstJumpRelNotZero; 993 Instructions[opJumpRelZero] := InstJumpRelZero; 909 994 Instructions[opLoadMem] := InstLoadMem; 910 995 Instructions[opStoreMem] := InstStoreMem; … … 932 1017 Instructions[opDataPrefix32] := InstDataPrefix64; 933 1018 Instructions[opAddrSize] := InstAddrSize; 1019 Instructions[opAddrPrefix8] := InstAddrPrefix8; 1020 Instructions[opAddrPrefix16] := InstAddrPrefix16; 1021 Instructions[opAddrPrefix32] := InstAddrPrefix32; 1022 Instructions[opAddrPrefix32] := InstAddrPrefix64; 934 1023 Instructions[opTest] := InstTest; 935 1024 Instructions[opAnd] := InstAnd; … … 938 1027 Instructions[opLdir] := InstLdir; 939 1028 Instructions[opLddr] := InstLddr; 1029 Instructions[opMul] := InstMul; 1030 Instructions[opDiv] := InstDiv; 1031 Instructions[opMod] := InstMod; 940 1032 end; 941 1033 … … 959 1051 DataSize := DataSizePrefix; 960 1052 DataSizePrefix := bwNone; 1053 end; 1054 if AddrSizePrefix <> bwNone then begin 1055 AddrSizeLast := AddrSize; 1056 AddrSize := AddrSizePrefix; 1057 AddrSizePrefix := bwNone; 961 1058 end; 962 1059 Opcode := Read8; … … 969 1066 DataSizeLast := bwNone; 970 1067 end; 1068 if AddrSizeLast <> bwNone then begin 1069 AddrSize := AddrSizeLast; 1070 AddrSizeLast := bwNone; 1071 end; 971 1072 IP := IP mod MemSize(Memory); 972 1073 Inc(FTicks); … … 1021 1122 function TCpu.ReadAddress: TAddress; 1022 1123 begin 1023 case Addr essSize of1124 case AddrSize of 1024 1125 bw8: Result := Read8; 1025 1126 bw16: Result := Read16; … … 1029 1130 end; 1030 1131 1132 function TCpu.ReadAddressSigned: TAddressSigned; 1133 begin 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; 1140 end; 1141 1031 1142 constructor TCpu.Create; 1032 1143 begin 1033 1144 DataSize := bw16; 1034 Addr essSize := bw16;1145 AddrSize := bw16; 1035 1146 SetLength(Registers, 32); 1036 1147 InitInstructions; -
branches/virtualcpu4/UFormMain.pas
r176 r177 197 197 R4 := 4; 198 198 with InstructionWriter do begin 199 Init; 199 200 // Print Hello world text 200 201 LabelText := 200; … … 218 219 Decrement(R2); 219 220 Test(R2); 220 JumpNotZero(LabelClearScreen);221 AddrPrefix8; JumpRelNotZero(LabelClearScreen); 221 222 222 223 // Update screen area -
branches/virtualcpu4/UInstructionWriter.pas
r174 r177 13 13 14 14 TInstructionWriter = class 15 private 16 DataSizeLast: TBitWidth; 17 DataSizePrefix: TBitWidth; 18 AddrSizeLast: TBitWidth; 19 AddrSizePrefix: TBitWidth; 20 procedure PrefixBegin; 21 procedure PrefixEnd; 22 public 15 23 Cpu: TCpu; 16 24 IP: Integer; 25 DataSize: TBitWidth; 26 AddrSize: TBitWidth; 27 procedure Init; 17 28 procedure Write8(Value: Byte); 18 29 procedure Write16(Value: Word); … … 20 31 procedure Write64(Value: QWord); 21 32 procedure WriteAddress(Value: TAddress); 33 procedure WriteAddressSigned(Value: TAddressSigned); 22 34 procedure WriteData(Value: QWord); 23 35 procedure WriteString(Text: string); … … 27 39 procedure Increment(Reg: TRegIndex); 28 40 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); 31 47 procedure DataPrefix8; 32 48 procedure DataPrefix16; 33 49 procedure DataPrefix32; 34 50 procedure DataPrefix64; 51 procedure AddrPrefix8; 52 procedure AddrPrefix16; 53 procedure AddrPrefix32; 54 procedure AddrPrefix64; 35 55 procedure StoreMem(RegAddr, RegSrc: TRegIndex); 36 56 procedure LoadMem(RegDst, RegAddr: TRegIndex); … … 40 60 end; 41 61 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 74 const 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'); 42 80 43 81 implementation 44 82 83 { TAssembler } 84 85 procedure TAssembler.Compile; 86 begin 87 88 end; 89 45 90 { TInstructionWriter } 46 91 47 92 procedure TInstructionWriter.Nop; 48 93 begin 94 PrefixBegin; 49 95 Write8(Byte(opNop)); 96 PrefixEnd; 50 97 end; 51 98 52 99 procedure TInstructionWriter.Halt; 53 100 begin 101 PrefixBegin; 54 102 Write8(Byte(opHalt)); 103 PrefixEnd; 55 104 end; 56 105 57 106 procedure TInstructionWriter.Loadi(Reg: TRegIndex; Value: QWord); 58 107 begin 108 PrefixBegin; 59 109 Write8(Byte(opLoadi)); 60 110 Write8(Reg); 61 111 WriteData(Value); 112 PrefixEnd; 62 113 end; 63 114 64 115 procedure TInstructionWriter.Increment(Reg: TRegIndex); 65 116 begin 117 PrefixBegin; 66 118 Write8(Byte(opInc)); 67 119 Write8(Reg); 120 PrefixEnd; 68 121 end; 69 122 70 123 procedure TInstructionWriter.Decrement(Reg: TRegIndex); 71 124 begin 125 PrefixBegin; 72 126 Write8(Byte(opDec)); 73 127 Write8(Reg); 74 end; 75 76 procedure TInstructionWriter.Jump(Value: QWord); 77 begin 128 PrefixEnd; 129 end; 130 131 procedure TInstructionWriter.Jump(Addr: QWord); 132 begin 133 PrefixBegin; 78 134 Write8(Byte(opJump)); 79 WriteAddress(Value); 80 end; 81 82 procedure TInstructionWriter.JumpNotZero(Value: QWord); 83 begin 135 WriteAddress(Addr); 136 PrefixEnd; 137 end; 138 139 procedure TInstructionWriter.JumpNotZero(Addr: QWord); 140 begin 141 PrefixBegin; 84 142 Write8(Byte(opJumpNotZero)); 85 WriteAddress(Value); 143 WriteAddress(Addr); 144 PrefixEnd; 145 end; 146 147 procedure TInstructionWriter.JumpZero(Addr: QWord); 148 begin 149 PrefixBegin; 150 Write8(Byte(opJumpZero)); 151 WriteAddress(Addr); 152 PrefixEnd; 153 end; 154 155 procedure TInstructionWriter.JumpRel(Addr: QWord); 156 var 157 NextIP: QWord; 158 begin 159 PrefixBegin; 160 NextIP := IP + 1 + BitWidthBytes[Cpu.AddrSize]; 161 Write8(Byte(opJumpRel)); 162 WriteAddressSigned(Int64(Addr) - Int64(NextIP)); 163 PrefixEnd; 164 end; 165 166 procedure TInstructionWriter.JumpRelNotZero(Addr: QWord); 167 var 168 NextIP: QWord; 169 begin 170 PrefixBegin; 171 NextIP := IP + 1 + BitWidthBytes[Cpu.AddrSize]; 172 Write8(Byte(opJumpRelNotZero)); 173 WriteAddressSigned(Int64(Addr) - Int64(NextIP)); 174 PrefixEnd; 175 end; 176 177 procedure TInstructionWriter.JumpRelZero(Addr: QWord); 178 var 179 NextIP: QWord; 180 begin 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; 86 187 end; 87 188 88 189 procedure TInstructionWriter.DataPrefix8; 89 190 begin 191 DataSizePrefix := bw8; 90 192 Write8(Byte(opDataPrefix8)); 91 193 end; … … 93 195 procedure TInstructionWriter.DataPrefix16; 94 196 begin 197 DataSizePrefix := bw16; 95 198 Write8(Byte(opDataPrefix16)); 96 199 end; … … 98 201 procedure TInstructionWriter.DataPrefix32; 99 202 begin 203 DataSizePrefix := bw32; 100 204 Write8(Byte(opDataPrefix32)); 101 205 end; … … 103 207 procedure TInstructionWriter.DataPrefix64; 104 208 begin 209 DataSizePrefix := bw64; 105 210 Write8(Byte(opDataPrefix64)); 211 end; 212 213 procedure TInstructionWriter.AddrPrefix8; 214 begin 215 AddrSizePrefix := bw8; 216 Write8(Byte(opAddrPrefix8)); 217 end; 218 219 procedure TInstructionWriter.AddrPrefix16; 220 begin 221 AddrSizePrefix := bw16; 222 Write8(Byte(opAddrPrefix16)); 223 end; 224 225 procedure TInstructionWriter.AddrPrefix32; 226 begin 227 AddrSizePrefix := bw32; 228 Write8(Byte(opAddrPrefix32)); 229 end; 230 231 procedure TInstructionWriter.AddrPrefix64; 232 begin 233 AddrSizePrefix := bw64; 234 Write8(Byte(opAddrPrefix64)); 106 235 end; 107 236 … … 115 244 procedure TInstructionWriter.LoadMem(RegDst, RegAddr: TRegIndex); 116 245 begin 246 PrefixBegin; 117 247 Write8(Byte(opLoadMem)); 118 248 Write8(RegDst); 119 249 Write8(RegAddr); 250 PrefixEnd; 120 251 end; 121 252 122 253 procedure TInstructionWriter.Output(Port: TAddress; Reg: TRegIndex); 123 254 begin 255 PrefixBegin; 124 256 Write8(Byte(opOut)); 125 257 WriteAddress(Port); 126 258 Write8(Reg); 259 PrefixEnd; 127 260 end; 128 261 129 262 procedure TInstructionWriter.Input(Reg: TRegIndex; Port: TAddress); 130 263 begin 264 PrefixBegin; 131 265 Write8(Byte(opIn)); 132 266 Write8(Reg); 133 267 WriteAddress(Port); 268 PrefixEnd; 134 269 end; 135 270 136 271 procedure TInstructionWriter.Test(Reg: TRegIndex); 137 272 begin 273 PrefixBegin; 138 274 Write8(Byte(opTest)); 139 275 Write8(Reg); 276 Prefixend; 140 277 end; 141 278 … … 148 285 end; 149 286 287 procedure TInstructionWriter.PrefixBegin; 288 begin 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; 299 end; 300 301 procedure TInstructionWriter.PrefixEnd; 302 begin 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; 311 end; 312 313 procedure TInstructionWriter.Init; 314 begin 315 DataSize := Cpu.DataSize; 316 AddrSize := Cpu.AddrSize; 317 end; 318 150 319 procedure TInstructionWriter.Write8(Value: Byte); 151 320 begin … … 174 343 procedure TInstructionWriter.WriteAddress(Value: TAddress); 175 344 begin 176 case Cpu.AddressSize of345 case AddrSize of 177 346 bw8: Write8(Value); 178 347 bw16: Write16(Value); … … 182 351 end; 183 352 353 procedure TInstructionWriter.WriteAddressSigned(Value: TAddressSigned); 354 begin 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; 361 end; 362 184 363 procedure TInstructionWriter.WriteData(Value: QWord); 185 364 begin 186 case Cpu.DataSize of365 case DataSize of 187 366 bw8: Write8(Value); 188 367 bw16: Write16(Value); -
branches/virtualcpu4/UMachine.pas
r176 r177 51 51 Cpu.OnOutput := CpuOutput; 52 52 Cpu.DataSize := bw32; 53 Cpu.Addr essSize := bw32;53 Cpu.AddrSize := bw32; 54 54 Screen := TScreen.Create; 55 55 Screen.Size := Point(320, 240);
Note:
See TracChangeset
for help on using the changeset viewer.