Changeset 171 for branches/virtualcpu4
- Timestamp:
- Apr 10, 2019, 4:00:46 PM (6 years ago)
- Location:
- branches/virtualcpu4
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/virtualcpu4/UCpu.pas
r170 r171 13 13 opCall, opRet, opAdd, opAddc, opSub, opSubc, opInc, opDec, opIn, opOut, opShl, 14 14 opShr, opDataPrefix8, opDataPrefix16, opDataPrefix32, opDataPrefix64, 15 opDataSize, opAddrSize );15 opDataSize, opAddrSize, opTest); 16 16 TAddress = QWord; 17 17 PAddress = ^TAddress; … … 53 53 procedure InstJumpNotZero; 54 54 procedure InstJumpRel; 55 procedure InstTest; 55 56 procedure InstNeg; 56 57 procedure InstClear; … … 77 78 procedure InstDataSize; 78 79 procedure InstAddrSize; 80 procedure InitInstructions; 79 81 public 80 82 Memory: array of Byte; … … 93 95 function Read32: DWord; inline; 94 96 function Read64: QWord; inline; 97 function ReadAddress: TAddress; inline; 95 98 constructor Create; 96 99 property Ticks: Integer read FTicks; … … 167 170 end; 168 171 172 procedure TCpu.InstTest; 173 var 174 Reg: Byte; 175 begin 176 Reg := Read8; 177 case DataSize of 178 bw8: Z := Registers[Reg].B = 0; 179 bw16: Z := Registers[Reg].W = 0; 180 bw32: Z := Registers[Reg].D = 0; 181 bw64: Z := Registers[Reg].Q = 0; 182 end; 183 end; 184 169 185 procedure TCpu.InstNeg; 170 186 var 171 Reg: Integer;187 Reg: Byte; 172 188 begin 173 189 Reg := Read8; … … 428 444 procedure TCpu.InstIn; 429 445 var 430 R: Integer;431 Port: Integer;446 R: Byte; 447 Port: TAddress; 432 448 begin 433 449 R := Read8; 434 Port := Read 8;450 Port := ReadAddress; 435 451 case DataSize of 436 452 bw8: begin … … 455 471 procedure TCpu.InstOut; 456 472 var 457 R: Integer;473 R: Byte; 458 474 Port: TAddress; 459 475 Value: TRegister; 460 476 begin 477 Port := ReadAddress; 461 478 R := Read8; 462 Port := Read8;463 479 case DataSize of 464 480 bw8: begin … … 541 557 end; 542 558 543 procedure TCpu.Run; 544 begin 545 Terminated := False; 546 FTicks := 0; 547 DataSizeLast := bwNone; 548 IP := 0; 549 SP := Length(Memory); 550 while not Terminated do 551 Step; 552 end; 553 554 procedure TCpu.Step; 555 var 556 Opcode: Byte; 557 begin 558 if DataSizePrefix <> bwNone then begin 559 DataSizeLast := DataSize; 560 DataSize := DataSizePrefix; 561 DataSizePrefix := bwNone; 562 end; 563 Opcode := Read8; 564 if Opcode < Length(Instructions) then Instructions[TOpcode(Opcode)] 565 else raise Exception.Create('Unsupported opcode ' + IntToStr(Opcode) + ' at address ' + IntToHex(IP, 8) + '.'); 566 if DataSizeLast <> bwNone then begin 567 DataSize := DataSizeLast; 568 DataSizeLast := bwNone; 569 end; 570 IP := IP mod Length(Memory); 571 Inc(FTicks); 572 end; 573 574 procedure TCpu.Start; 575 begin 576 if not Running then begin 577 Terminated := False; 578 Thread := TCpuThread.Create(True); 579 Thread.Cpu := Self; 580 Thread.Start; 581 FRunning := True; 582 end; 583 end; 584 585 procedure TCpu.Stop; 586 begin 587 if Running then begin 588 Terminated := True; 589 Thread.Terminate; 590 Thread.WaitFor; 591 FreeAndNil(Thread); 592 FRunning := False; 593 end; 594 end; 595 596 function TCpu.Read8: Byte; 597 begin 598 Result := Memory[IP]; 599 Inc(IP); 600 end; 601 602 function TCpu.Read16: Word; 603 begin 604 Result := PWord(@Memory[IP])^; 605 Inc(IP, SizeOf(Word)); 606 end; 607 608 function TCpu.Read32: DWord; 609 begin 610 Result := PDWord(@Memory[IP])^; 611 Inc(IP, SizeOf(DWord)); 612 end; 613 614 function TCpu.Read64: QWord; 615 begin 616 Result := PQWord(@Memory[IP])^; 617 Inc(IP, SizeOf(QWord)); 618 end; 619 620 constructor TCpu.Create; 621 begin 622 DataSize := bw16; 623 AddressSize := bw16; 624 SetLength(Memory, 1000); 625 SetLength(Registers, 32); 559 procedure TCpu.InitInstructions; 560 begin 626 561 Instructions[opNop] := InstNop; 627 562 Instructions[opHalt] := InstHalt; … … 629 564 Instructions[opLoadConst] := InstLoadConst; 630 565 Instructions[opJump] := InstJump; 566 Instructions[opJumpNotZero] := InstJumpNotZero; 567 Instructions[opJumpZero] := InstJumpZero; 631 568 Instructions[opJumpRel] := InstJumpRel; 632 569 Instructions[opLoadMem] := InstLoadMem; … … 654 591 Instructions[opDataPrefix32] := InstDataPrefix64; 655 592 Instructions[opAddrSize] := InstAddrSize; 593 Instructions[opTest] := InstTest; 594 end; 595 596 procedure TCpu.Run; 597 begin 598 Terminated := False; 599 FTicks := 0; 600 DataSizeLast := bwNone; 601 IP := 0; 602 SP := Length(Memory); 603 while not Terminated do 604 Step; 605 end; 606 607 procedure TCpu.Step; 608 var 609 Opcode: Byte; 610 begin 611 if DataSizePrefix <> bwNone then begin 612 DataSizeLast := DataSize; 613 DataSize := DataSizePrefix; 614 DataSizePrefix := bwNone; 615 end; 616 Opcode := Read8; 617 if Opcode < Length(Instructions) then begin 618 if Assigned(Instructions[TOpcode(Opcode)]) then Instructions[TOpcode(Opcode)] 619 else raise Exception.Create('Missing instruction handler for opcode '+ IntToStr(Opcode)); 620 end else raise Exception.Create('Unsupported opcode ' + IntToStr(Opcode) + ' at address ' + IntToHex(IP, 8) + '.'); 621 if DataSizeLast <> bwNone then begin 622 DataSize := DataSizeLast; 623 DataSizeLast := bwNone; 624 end; 625 IP := IP mod Length(Memory); 626 Inc(FTicks); 627 end; 628 629 procedure TCpu.Start; 630 begin 631 if not Running then begin 632 Terminated := False; 633 Thread := TCpuThread.Create(True); 634 Thread.Cpu := Self; 635 Thread.Start; 636 FRunning := True; 637 end; 638 end; 639 640 procedure TCpu.Stop; 641 begin 642 if Running then begin 643 Terminated := True; 644 Thread.Terminate; 645 Thread.WaitFor; 646 FreeAndNil(Thread); 647 FRunning := False; 648 end; 649 end; 650 651 function TCpu.Read8: Byte; 652 begin 653 Result := Memory[IP]; 654 Inc(IP); 655 end; 656 657 function TCpu.Read16: Word; 658 begin 659 Result := PWord(@Memory[IP])^; 660 Inc(IP, SizeOf(Word)); 661 end; 662 663 function TCpu.Read32: DWord; 664 begin 665 Result := PDWord(@Memory[IP])^; 666 Inc(IP, SizeOf(DWord)); 667 end; 668 669 function TCpu.Read64: QWord; 670 begin 671 Result := PQWord(@Memory[IP])^; 672 Inc(IP, SizeOf(QWord)); 673 end; 674 675 function TCpu.ReadAddress: TAddress; 676 begin 677 case AddressSize of 678 bw8: Result := Read8; 679 bw16: Result := Read16; 680 bw32: Result := Read32; 681 bw64: Result := Read64; 682 end; 683 end; 684 685 constructor TCpu.Create; 686 begin 687 DataSize := bw16; 688 AddressSize := bw16; 689 SetLength(Memory, 1000); 690 SetLength(Registers, 32); 691 InitInstructions; 656 692 end; 657 693 -
branches/virtualcpu4/UFormMain.lfm
r170 r171 1 1 object FormMain: TFormMain 2 Left = 3843 Height = 6134 Top = 2195 Width = 1 1782 Left = 223 3 Height = 790 4 Top = 54 5 Width = 1432 6 6 Caption = 'VirtCpu4' 7 ClientHeight = 6138 ClientWidth = 1 1787 ClientHeight = 790 8 ClientWidth = 1432 9 9 DesignTimePPI = 120 10 10 OnCreate = FormCreate … … 40 40 object ListViewRegisters: TListView 41 41 Left = 8 42 Height = 59242 Height = 769 43 43 Top = 8 44 44 Width = 312 … … 62 62 object ListViewMemory: TListView 63 63 Left = 328 64 Height = 59264 Height = 769 65 65 Top = 8 66 66 Width = 648 … … 82 82 OnData = ListViewMemoryData 83 83 end 84 object Memo1: TMemo 85 Left = 984 86 Height = 619 87 Top = 160 88 Width = 432 89 OnKeyPress = Memo1KeyPress 90 ReadOnly = True 91 TabOrder = 4 92 end 93 object Label2: TLabel 94 Left = 984 95 Height = 20 96 Top = 136 97 Width = 56 98 Caption = 'Console:' 99 ParentColor = False 100 end 84 101 object Timer1: TTimer 85 102 Interval = 200 -
branches/virtualcpu4/UFormMain.pas
r170 r171 1 1 unit UFormMain; 2 2 3 {$mode objfpc}{$H+}3 {$mode delphi}{$H+} 4 4 5 5 interface … … 17 17 ButtonStop: TButton; 18 18 Label1: TLabel; 19 Label2: TLabel; 19 20 ListViewMemory: TListView; 20 21 ListViewRegisters: TListView; 22 Memo1: TMemo; 21 23 Timer1: TTimer; 22 24 procedure ButtonStartClick(Sender: TObject); … … 27 29 procedure ListViewMemoryData(Sender: TObject; Item: TListItem); 28 30 procedure ListViewRegistersData(Sender: TObject; Item: TListItem); 31 procedure Memo1KeyPress(Sender: TObject; var Key: char); 29 32 procedure Timer1Timer(Sender: TObject); 30 33 private 34 KeyInputBuffer: array of Char; 35 function CpuInput(Port: TAddress): TRegister; 36 procedure CpuOutput(Port: TAddress; Value: TRegister); 31 37 procedure ReloadMemoryDump; 32 38 procedure ReloadRegisterDump; … … 62 68 begin 63 69 Cpu := TCpu.Create; 70 Cpu.OnInput := CpuInput; 71 Cpu.OnOutput := CpuOutput; 64 72 Cpu.DataSize := bw16; 65 73 Cpu.AddressSize := bw16; … … 110 118 end; 111 119 120 procedure TFormMain.Memo1KeyPress(Sender: TObject; var Key: char); 121 begin 122 SetLength(KeyInputBuffer, Length(KeyInputBuffer) + 1); 123 KeyInputBuffer[High(KeyInputBuffer)] := Key; 124 end; 125 112 126 procedure TFormMain.Timer1Timer(Sender: TObject); 113 127 begin … … 133 147 R1: Byte; 134 148 R2: Byte; 149 R3: Byte; 135 150 LabelStart: Integer; 151 LabelText: Integer; 152 LabelPrint: Integer; 136 153 begin 137 154 R1 := 1; 138 155 R2 := 2; 156 R3 := 3; 139 157 with InstructionWriter do begin 158 LabelText := 200; 159 LoadConst(R1, LabelText); 160 LoadConst(R2, 12); 161 LabelPrint := IP; 162 DataPrefix8; LoadMem(R3, R1); 163 DataPrefix8; Output(0, R3); 164 Increment(R1); 165 Decrement(R2); 166 Test(R2); 167 JumpNotZero(LabelPrint); 168 140 169 LoadConst(R1, 100); 170 LabelStart := IP; 171 Increment(R1); 141 172 LoadConst(R2, 100); 142 LabelStart := IP;143 Increment(R1);144 173 DataPrefix8; StoreMem(R2, R1); 174 DataPrefix8; Input(R2, 0); 175 DataPrefix8; Output(0, R2); 145 176 Jump(LabelStart); 146 177 Halt; 147 end; 148 end; 178 IP := LabelText; 179 WriteString('Hello World!'); 180 end; 181 end; 182 183 function TFormMain.CpuInput(Port: TAddress): TRegister; 184 begin 185 Result.Q := 0; 186 case Port of 187 0: begin 188 while (Length(KeyInputBuffer) = 0) and not Cpu.Terminated do begin 189 Sleep(100); 190 end; 191 if Length(KeyInputBuffer) > 0 then begin 192 Result.B := Ord(KeyInputBuffer[0]); 193 if Length(KeyInputBuffer) > 1 then 194 Move(KeyInputBuffer[1], KeyInputBuffer[0], Length(KeyInputBuffer) - 1); 195 SetLength(KeyInputBuffer, Length(KeyInputBuffer) - 1); 196 end else Result.B := 0; 197 end; 198 end; 199 end; 200 201 procedure TFormMain.CpuOutput(Port: TAddress; Value: TRegister); 202 begin 203 case Port of 204 0: Memo1.Lines.Text := Memo1.Lines.Text + Char(Value.B); 205 end; 206 end; 207 149 208 150 209 -
branches/virtualcpu4/UInstructionWriter.pas
r170 r171 19 19 procedure Write32(Value: DWord); 20 20 procedure Write64(Value: QWord); 21 procedure WriteAddress(Value: TAddress); 22 procedure WriteData(Value: QWord); 23 procedure WriteString(Text: string); 21 24 procedure Nop; 22 25 procedure Halt; 23 26 procedure LoadConst(Reg: Byte; Value: QWord); 24 27 procedure Increment(Reg: Byte); 28 procedure Decrement(Reg: Byte); 25 29 procedure Jump(Value: QWord); 30 procedure JumpNotZero(Value: QWord); 26 31 procedure DataPrefix8; 27 32 procedure StoreMem(RegAddr, RegSrc: Byte); 33 procedure LoadMem(RegDst, RegAddr: Byte); 34 procedure Output(Port: TAddress; Reg: Byte); 35 procedure Input(Reg: Byte; Port: TAddress); 36 procedure Test(Reg: Byte); 28 37 end; 29 38 … … 47 56 Write8(Byte(opLoadConst)); 48 57 Write8(Reg); 49 case Cpu.DataSize of 50 bw8: Write8(Value); 51 bw16: Write16(Value); 52 bw32: Write32(Value); 53 bw64: Write64(Value); 54 end; 58 WriteData(Value); 55 59 end; 56 60 … … 61 65 end; 62 66 67 procedure TInstructionWriter.Decrement(Reg: Byte); 68 begin 69 Write8(Byte(opDec)); 70 Write8(Reg); 71 end; 72 63 73 procedure TInstructionWriter.Jump(Value: QWord); 64 74 begin 65 75 Write8(Byte(opJump)); 66 case Cpu.AddressSize of 67 bw8: Write8(Value); 68 bw16: Write16(Value); 69 bw32: Write32(Value); 70 bw64: Write64(Value); 71 end; 76 WriteAddress(Value); 77 end; 78 79 procedure TInstructionWriter.JumpNotZero(Value: QWord); 80 begin 81 Write8(Byte(opJumpNotZero)); 82 WriteAddress(Value); 72 83 end; 73 84 … … 82 93 Write8(RegAddr); 83 94 Write8(RegSrc); 95 end; 96 97 procedure TInstructionWriter.LoadMem(RegDst, RegAddr: Byte); 98 begin 99 Write8(Byte(opLoadMem)); 100 Write8(RegDst); 101 Write8(RegAddr); 102 end; 103 104 procedure TInstructionWriter.Output(Port: TAddress; Reg: Byte); 105 begin 106 Write8(Byte(opOut)); 107 WriteAddress(Port); 108 Write8(Reg); 109 end; 110 111 procedure TInstructionWriter.Input(Reg: Byte; Port: TAddress); 112 begin 113 Write8(Byte(opIn)); 114 Write8(Reg); 115 WriteAddress(Port); 116 end; 117 118 procedure TInstructionWriter.Test(Reg: Byte); 119 begin 120 Write8(Byte(opTest)); 121 Write8(Reg); 122 end; 123 124 procedure TInstructionWriter.WriteString(Text: string); 125 var 126 I: Integer; 127 begin 128 for I := 1 to Length(Text) do 129 Write8(Ord(Text[I])); 84 130 end; 85 131 … … 108 154 end; 109 155 156 procedure TInstructionWriter.WriteAddress(Value: TAddress); 157 begin 158 case Cpu.AddressSize of 159 bw8: Write8(Value); 160 bw16: Write16(Value); 161 bw32: Write32(Value); 162 bw64: Write64(Value); 163 end; 164 end; 165 166 procedure TInstructionWriter.WriteData(Value: QWord); 167 begin 168 case Cpu.DataSize of 169 bw8: Write8(Value); 170 bw16: Write16(Value); 171 bw32: Write32(Value); 172 bw64: Write64(Value); 173 end; 174 end; 175 110 176 end. 111 177
Note:
See TracChangeset
for help on using the changeset viewer.