Changeset 152
- Timestamp:
- Apr 20, 2018, 5:42:48 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/virtualcpu2/UMachine.pas
r151 r152 22 22 TRegSize = Int8; 23 23 24 TOpcode = (opNop, opHalt, opCopy, opCopy8, opCopy16, opCopy32, opCopy64, 25 opCopyFromMem, opCopyToMem, opCopyConst, 26 opGetDataSize, opInc, opInc8, opInc16, opInc32, opInc64, opDec, 27 opJumpRelNotZero); 24 TOpcode = ( 25 // Data move 26 opCopy, 27 opCopyFromMem, 28 opCopyToMem, 29 opCopyConst, 30 opXchg, 31 // Arithmetic 32 opInc, 33 opDec, 34 opAdd, 35 opSub, 36 opMul, 37 opDiv, 38 // Stack 39 opPush, 40 opPop, 41 // Skip 42 opSkipZero, 43 opSkipNotZero, 44 opSkipCarry, 45 opSkipNotCarray, 46 // Subroutine 47 opCallRel, 48 opCallAbs, 49 opRet, 50 // Jump 51 opJumpRel, 52 opJumpAbs, 53 // Logical operations 54 opAnd, 55 opOr, 56 opXor, 57 // Bit shift 58 opShr, 59 opShl, 60 // I/O access 61 opIn, 62 opOut, 63 // Block operations 64 opLdir, 65 opLddr, 66 // Special 67 opNop, 68 opHalt, 69 opGetSize, 70 opSetSize, opSetSize8, opSetSize16, opSetSize32, opSetSize64 71 ); 28 72 29 73 TOpcodeHandler = procedure of object; 74 TDataSize = (dsNative, ds8, ds16, ds32, ds64); 30 75 31 76 { TMachine } … … 33 78 TMachine = class 34 79 private 35 OpcodeTable: array[TOpcode] of TOpcodeHandler; 80 OpcodeTable: array[TOpcode, TDataSize] of TOpcodeHandler; 81 procedure CheckIP; 36 82 procedure OpcodeNop; 37 83 procedure OpcodeHalt; … … 44 90 procedure OpcodeCopyToMem; 45 91 procedure OpcodeCopyConst; 92 procedure OpcodeCopyConst8; 93 procedure OpcodeCopyConst16; 94 procedure OpcodeCopyConst32; 95 procedure OpcodeCopyConst64; 46 96 procedure OpcodeGetDataSize; 97 procedure OpcodeXchg; 98 procedure OpcodeAdd; 99 procedure OpcodeSub; 100 procedure OpcodeAnd; 101 procedure OpcodeOr; 102 procedure OpcodeXor; 103 procedure OpcodePop; 104 procedure OpcodePush; 105 procedure OpcodeLdir; 47 106 procedure OpcodeInc; 48 107 procedure OpcodeInc8; … … 51 110 procedure OpcodeInc64; 52 111 procedure OpcodeDec; 53 procedure OpcodeJumpRelNotZero; 112 procedure OpcodeSkipNotZero; 113 procedure OpcodeSkipZero; 114 procedure OpcodeJumpRel; 115 procedure OpcodeJumpAbs; 54 116 procedure OpcodeUnsupported; 55 117 function ReadNext: TDataInt; … … 59 121 function ReadNext32: Cardinal; 60 122 function ReadNext64: QWord; 123 procedure SetOpcode(Opcode: TOpcode; Handler: TOpcodeHandler; DataSize: TDataSize = dsNative); 124 procedure InitOpcode; 125 procedure Step; 61 126 public 62 127 Registers: array of TDataInt; … … 64 129 Memory: array of Byte; 65 130 IP: TAddrInt; 131 SP: TAddrInt; 132 DataSize: TDataSize; 66 133 Terminated: Boolean; 134 SkipNext: Boolean; 67 135 procedure Run; 68 136 constructor Create; … … 88 156 end; 89 157 158 const 159 DataSizeValue: array[TDataSize] of Byte = (SizeOf(TDataInt), SizeOf(Byte), 160 SizeOf(Word), SizeOf(Cardinal), SizeOf(QWord)); 161 90 162 implementation 91 163 … … 93 165 94 166 procedure TMachine.Run; 95 var96 Opcode: TOpcode;97 167 begin 98 168 IP := 0; 99 169 Terminated := False; 100 170 while not Terminated do begin 101 if IP >= Length(Memory) then IP := 0; 102 Opcode := TOpcode(ReadNext8); 103 if (Opcode <= High(Opcode)) and Assigned(OpcodeTable[Opcode]) then 104 OpcodeTable[Opcode] 105 else raise Exception.Create('Unknown opcode: ' + IntToHex(Integer(Opcode), 2)); 171 Step; 106 172 end; 107 173 end; 108 174 175 procedure TMachine.SetOpcode(Opcode: TOpcode; Handler: TOpcodeHandler; DataSize: TDataSize); 176 begin 177 if SizeOf(TDataInt) >= DataSizeValue[DataSize] then OpcodeTable[Opcode, DataSize] := Handler 178 else OpcodeTable[Opcode, DataSize] := OpcodeUnsupported; 179 end; 180 181 procedure TMachine.InitOpcode; 182 begin 183 SetOpcode(opNop, OpcodeNop); 184 SetOpcode(opHalt, OpcodeHalt); 185 SetOpcode(opCopy, OpcodeCopy); 186 SetOpcode(opCopy, OpcodeCopy8, ds8); 187 SetOpcode(opCopy, OpcodeCopy16, ds16); 188 SetOpcode(opCopy, OpcodeCopy32, ds32); 189 SetOpcode(opCopy, OpcodeCopy64, ds64); 190 SetOpcode(opCopyFromMem, OpcodeCopyFromMem); 191 SetOpcode(opCopyToMem, OpcodeCopyToMem); 192 SetOpcode(opCopyConst, OpcodeCopyConst); 193 SetOpcode(opCopyConst, OpcodeCopyConst8, ds8); 194 SetOpcode(opCopyConst, OpcodeCopyConst16, ds16); 195 SetOpcode(opCopyConst, OpcodeCopyConst32, ds32); 196 SetOpcode(opCopyConst, OpcodeCopyConst64, ds64); 197 SetOpcode(opXchg, OpcodeXchg); 198 SetOpcode(opGetSize, OpcodeGetDataSize); 199 SetOpcode(opInc, OpcodeInc); 200 SetOpcode(opInc, OpcodeInc8, ds8); 201 SetOpcode(opInc, OpcodeInc16, ds16); 202 SetOpcode(opInc, OpcodeInc32, ds32); 203 SetOpcode(opInc, OpcodeInc64, ds64); 204 SetOpcode(opDec, OpcodeDec); 205 SetOpcode(opSkipZero, OpcodeSkipZero); 206 SetOpcode(opSkipNotZero, OpcodeSkipNotZero); 207 SetOpcode(opJumpRel, OpcodeJumpRel); 208 SetOpcode(opJumpAbs, OpcodeJumpAbs); 209 SetOpcode(opAdd, OpcodeAdd); 210 SetOpcode(opSub, OpcodeSub); 211 SetOpcode(opLdir, OpcodeLdir); 212 SetOpcode(opAnd, OpcodeAnd); 213 SetOpcode(opOr, OpcodeOr); 214 SetOpcode(opXor, OpcodeXor); 215 SetOpcode(opPush, OpcodePush); 216 SetOpcode(opPop, OpcodePop); 217 end; 218 219 procedure TMachine.Step; 220 var 221 Opcode: TOpcode; 222 OpcodeHandler: TOpcodeHandler; 223 begin 224 if IP >= Length(Memory) then IP := 0; 225 Opcode := TOpcode(ReadNext8); 226 if (Opcode <= High(Opcode)) then begin 227 OpcodeHandler := OpcodeTable[Opcode, DataSize]; 228 if not Assigned(OpcodeHandler) then OpcodeHandler 229 else raise Exception.Create('Opcode without handler: ' + IntToHex(Integer(Opcode), 2)); 230 end else raise Exception.Create('Unknown opcode: ' + IntToHex(Integer(Opcode), 2)); 231 end; 232 109 233 constructor TMachine.Create; 110 234 begin 111 235 SetLength(Registers, 16); 112 113 // Opcode table initialization 114 OpcodeTable[opNop] := OpcodeNop; 115 OpcodeTable[opHalt] := OpcodeHalt; 116 OpcodeTable[opCopy] := OpcodeCopy; 117 OpcodeTable[opCopy8] := OpcodeCopy8; 118 if SizeOf(TDataInt) >= SizeOf(Word) then 119 OpcodeTable[opCopy16] := OpcodeCopy16 120 else OpcodeTable[opCopy16] := OpcodeUnsupported; 121 if SizeOf(TDataInt) >= SizeOf(Cardinal) then 122 OpcodeTable[opCopy32] := OpcodeCopy32 123 else OpcodeTable[opCopy32] := OpcodeUnsupported; 124 if SizeOf(TDataInt) >= SizeOf(QWord) then 125 OpcodeTable[opCopy64] := OpcodeCopy64 126 else OpcodeTable[opCopy64] := OpcodeUnsupported; 127 OpcodeTable[opCopyFromMem] := OpcodeCopyFromMem; 128 OpcodeTable[opCopyToMem] := OpcodeCopyToMem; 129 OpcodeTable[opCopyConst] := OpcodeCopyConst; 130 OpcodeTable[opGetDataSize] := OpcodeGetDataSize; 131 OpcodeTable[opInc] := OpcodeInc; 132 OpcodeTable[opInc8] := OpcodeInc8; 133 if SizeOf(TDataInt) >= SizeOf(Word) then OpcodeTable[opInc16] := OpcodeInc16 134 else OpcodeTable[opInc16] := OpcodeUnsupported; 135 if SizeOf(TDataInt) >= SizeOf(Cardinal) then OpcodeTable[opInc32] := OpcodeInc32 136 else OpcodeTable[opInc32] := OpcodeUnsupported; 137 if SizeOf(TDataInt) >= SizeOf(QWord) then OpcodeTable[opInc64] := OpcodeInc64 138 else OpcodeTable[opInc64] := OpcodeUnsupported; 139 OpcodeTable[opDec] := OpcodeDec; 140 OpcodeTable[opJumpRelNotZero] := OpcodeJumpRelNotZero; 236 InitOpcode; 141 237 end; 142 238 143 239 procedure TMachine.OpcodeNop; 144 240 begin 145 146 241 end; 147 242 … … 231 326 end; 232 327 328 procedure TMachine.OpcodeCopyConst8; 329 var 330 Source: Byte; 331 Dest: TRegIndex; 332 begin 333 Dest := ReadNext8; 334 Source := ReadNext8; 335 PByte(@Registers[Dest])^ := Source; 336 end; 337 338 procedure TMachine.OpcodeCopyConst16; 339 var 340 Source: Word; 341 Dest: TRegIndex; 342 begin 343 Dest := ReadNext8; 344 Source := ReadNext16; 345 PWord(@Registers[Dest])^ := Source; 346 end; 347 348 procedure TMachine.OpcodeCopyConst32; 349 var 350 Source: Cardinal; 351 Dest: TRegIndex; 352 begin 353 Dest := ReadNext8; 354 Source := ReadNext32; 355 PCardinal(@Registers[Dest])^ := Source; 356 end; 357 358 procedure TMachine.OpcodeCopyConst64; 359 var 360 Source: QWord; 361 Dest: TRegIndex; 362 begin 363 Dest := ReadNext8; 364 Source := ReadNext64; 365 PQWord(@Registers[Dest])^ := Source; 366 end; 367 233 368 procedure TMachine.OpcodeGetDataSize; 234 369 var … … 239 374 end; 240 375 376 procedure TMachine.OpcodeXchg; 377 var 378 Source: TRegIndex; 379 Dest: TRegIndex; 380 Temp: TDataInt; 381 begin 382 Dest := ReadNext8; 383 Source := ReadNext8; 384 Temp := PDataInt(@Registers[Dest])^; 385 PDataInt(@Registers[Dest])^ := PDataInt(@Registers[Source])^; 386 PDataInt(@Registers[Source])^ := Temp; 387 end; 388 389 procedure TMachine.OpcodeAdd; 390 var 391 Op1: TRegIndex; 392 Op2: TRegIndex; 393 begin 394 Op1 := ReadNext8; 395 Op2 := ReadNext8; 396 PDataInt(@Registers[Op1])^ := PDataInt(@Registers[Op1])^ + PDataInt(@Registers[Op2])^; 397 end; 398 399 procedure TMachine.OpcodeSub; 400 var 401 Op1: TRegIndex; 402 Op2: TRegIndex; 403 begin 404 Op1 := ReadNext8; 405 Op2 := ReadNext8; 406 PDataInt(@Registers[Op1])^ := PDataInt(@Registers[Op1])^ - PDataInt(@Registers[Op2])^; 407 end; 408 409 procedure TMachine.OpcodeAnd; 410 var 411 Op1: TRegIndex; 412 Op2: TRegIndex; 413 begin 414 Op1 := ReadNext8; 415 Op2 := ReadNext8; 416 PDataInt(@Registers[Op1])^ := PDataInt(@Registers[Op1])^ and PDataInt(@Registers[Op2])^; 417 end; 418 419 procedure TMachine.OpcodeOr; 420 var 421 Op1: TRegIndex; 422 Op2: TRegIndex; 423 begin 424 Op1 := ReadNext8; 425 Op2 := ReadNext8; 426 PDataInt(@Registers[Op1])^ := PDataInt(@Registers[Op1])^ or PDataInt(@Registers[Op2])^; 427 end; 428 429 procedure TMachine.OpcodeXor; 430 var 431 Op1: TRegIndex; 432 Op2: TRegIndex; 433 begin 434 Op1 := ReadNext8; 435 Op2 := ReadNext8; 436 PDataInt(@Registers[Op1])^ := PDataInt(@Registers[Op1])^ xor PDataInt(@Registers[Op2])^; 437 end; 438 439 procedure TMachine.OpcodePop; 440 var 441 Dest: TRegIndex; 442 begin 443 Dest := ReadNext8; 444 PDataInt(@Registers[Dest])^ := PDataInt(@Memory[SP])^; 445 Inc(SP, SizeOf(TDataInt)); 446 end; 447 448 procedure TMachine.OpcodePush; 449 var 450 Source: TRegIndex; 451 begin 452 Source := ReadNext8; 453 Dec(SP, SizeOf(TDataInt)); 454 PDataInt(@Memory[SP])^ := PDataInt(@Registers[Source])^; 455 end; 456 457 procedure TMachine.OpcodeLdir; 458 var 459 Src: TRegIndex; 460 Dst: TRegIndex; 461 Count: TRegIndex; 462 begin 463 Src := ReadNext8; 464 Dst := ReadNext8; 465 Count := ReadNext8; 466 while Count > 0 do begin 467 PDataInt(@Registers[Dst])^ := PDataInt(@Registers[Src])^; 468 Inc(Src); 469 Inc(Dst); 470 Dec(Count); 471 end; 472 end; 473 241 474 procedure TMachine.OpcodeInc; 242 475 var … … 287 520 end; 288 521 289 procedure TMachine.OpcodeJumpRelNotZero; 522 procedure TMachine.OpcodeSkipNotZero; 523 var 524 Reg: TRegIndex; 525 begin 526 Reg := ReadNext8; 527 SkipNext := Registers[Reg] <> 0; 528 end; 529 530 procedure TMachine.OpcodeSkipZero; 531 var 532 Reg: TRegIndex; 533 begin 534 Reg := ReadNext8; 535 SkipNext := Registers[Reg] = 0; 536 end; 537 538 procedure TMachine.OpcodeJumpRel; 290 539 var 291 540 RelAddr: TAddrInt; 292 Reg: TRegIndex; 293 begin 294 Reg := ReadNext8; 541 begin 542 OpcodeSkipNotZero; 295 543 RelAddr := ReadNextS8; 296 if Registers[Reg] <> 0 then 297 IP := IP + RelAddr; 544 if not SkipNext then IP := IP + RelAddr; 545 end; 546 547 procedure TMachine.OpcodeJumpAbs; 548 var 549 Addr: TAddrInt; 550 begin 551 OpcodeSkipNotZero; 552 Addr := ReadNext; 553 if not SkipNext then IP := Addr; 298 554 end; 299 555 … … 303 559 end; 304 560 561 procedure TMachine.CheckIP; 562 begin 563 if (IP < 0) and (IP >= Length(Memory)) then 564 raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8)); 565 end; 566 305 567 function TMachine.ReadNext: TDataInt; 306 568 begin 307 if (IP >= 0) and (IP < Length(Memory)) then Result := PDataInt(@Memory[IP])^308 else raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8));569 CheckIP; 570 Result := PDataInt(@Memory[IP])^; 309 571 Inc(IP, SizeOf(TDataInt)); 310 572 end; … … 312 574 function TMachine.ReadNext8: Byte; 313 575 begin 314 if (IP >= 0) and (IP < Length(Memory)) then Result := Memory[IP]315 else raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8));576 CheckIP; 577 Result := Memory[IP]; 316 578 Inc(IP); 317 579 end; … … 319 581 function TMachine.ReadNextS8: ShortInt; 320 582 begin 321 if (IP >= 0) and (IP < Length(Memory)) then Result := Memory[IP]322 else raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8));583 CheckIP; 584 Result := Memory[IP]; 323 585 Inc(IP); 324 586 end; … … 326 588 function TMachine.ReadNext16: Word; 327 589 begin 328 if (IP >= 0) and (IP < Length(Memory)) then Result := PWord(@Memory[IP])^329 else raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8));590 CheckIP; 591 Result := PWord(@Memory[IP])^; 330 592 Inc(IP, SizeOf(Word)); 331 593 end; … … 333 595 function TMachine.ReadNext32: Cardinal; 334 596 begin 335 if (IP >= 0) and (IP < Length(Memory)) then Result := PCardinal(@Memory[IP])^336 else raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8));597 CheckIP; 598 Result := PCardinal(@Memory[IP])^; 337 599 Inc(IP, SizeOf(Cardinal)); 338 600 end; … … 340 602 function TMachine.ReadNext64: QWord; 341 603 begin 342 if (IP >= 0) and (IP < Length(Memory)) then Result := PQWord(@Memory[IP])^343 else raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8));604 CheckIP; 605 Result := PQWord(@Memory[IP])^; 344 606 Inc(IP, SizeOf(QWord)); 345 607 end; … … 374 636 procedure TInstructionWriter.AddGetDataSize(Reg: TRegIndex); 375 637 begin 376 AddData8(Integer(opGet DataSize));638 AddData8(Integer(opGetSize)); 377 639 AddData8(Reg); 378 640 end; … … 412 674 ); 413 675 begin 414 AddData8(Integer(opJumpRel NotZero));676 AddData8(Integer(opJumpRel)); 415 677 AddData8(Reg); 416 678 AddDataS8(RelAddr - 3);
Note:
See TracChangeset
for help on using the changeset viewer.