source: branches/virtualcpu/UMachine.pas

Last change on this file was 87, checked in by chronos, 9 years ago

Another experimental virtual CPU implementation.

File size: 4.2 KB
Line 
1unit UMachine;
2
3{$mode delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, Math;
9
10type
11 //TAddrInt = Int8;
12 TAddrInt = Int16;
13 //TAddrInt = Int32;
14 //TAddrInt = Int64;
15 TDataInt = Int16;
16 //TDataInt = Int16;
17 //TDataInt = Int32;
18 //TDataInt = Int64;
19
20 TRegIndex = TAddrInt;
21 TRegSize = Int8;
22
23 TOpcode = (opNop, opHalt, opCopy, opCopyFromMem, opCopyToMem, opCopyConst,
24 opSetRegSize, opGetDataSize, opInc, opDec, opJumpRelNotZero);
25
26 TOpcodeHandler = procedure of object;
27
28 { TMachine }
29
30 TMachine = class
31 private
32 OpcodeTable: array[TOpcode] of TOpcodeHandler;
33 procedure OpcodeNop;
34 procedure OpcodeHalt;
35 procedure OpcodeCopy;
36 procedure OpcodeCopyFromMem;
37 procedure OpcodeCopyToMem;
38 procedure OpcodeCopyConst;
39 procedure OpcodeSetRegSize;
40 procedure OpcodeGetDataSize;
41 procedure OpcodeInc;
42 procedure OpcodeDec;
43 procedure OpcodeJumpRelNotZero;
44 function ReadNext: Integer;
45 public
46 Registers: array of TDataInt;
47 RegisterSize: array of TRegSize;
48 Memory: array of Byte;
49 IP: TAddrInt;
50 Terminated: Boolean;
51 procedure Run;
52 constructor Create;
53 end;
54
55implementation
56
57{ TMachine }
58
59procedure TMachine.Run;
60var
61 Opcode: TOpcode;
62begin
63 IP := 0;
64 Terminated := False;
65 while not Terminated do begin
66 if IP >= Length(Memory) then IP := 0;
67 Opcode := TOpcode(ReadNext);
68 if Opcode <= High(Opcode) then OpcodeTable[Opcode]
69 else raise Exception.Create('Unknown opcode: ' + IntToHex(Integer(Opcode), 2));
70 end;
71end;
72
73constructor TMachine.Create;
74var
75 I: Integer;
76begin
77 SetLength(Registers, 16);
78 SetLength(RegisterSize, 16);
79 for I := 0 to High(RegisterSize) do
80 RegisterSize[I] := SizeOf(TDataInt);;
81
82 // Opcode table initialization
83 OpcodeTable[opNop] := OpcodeNop;
84 OpcodeTable[opHalt] := OpcodeHalt;
85 OpcodeTable[opCopy] := OpcodeCopy;
86 OpcodeTable[opCopyFromMem] := OpcodeCopyFromMem;
87 OpcodeTable[opCopyToMem] := OpcodeCopyToMem;
88 OpcodeTable[opCopyConst] := OpcodeCopyConst;
89 OpcodeTable[opSetRegSize] := OpcodeSetRegSize;
90 OpcodeTable[opGetDataSize] := OpcodeGetDataSize;
91 OpcodeTable[opInc] := OpcodeInc;
92 OpcodeTable[opDec] := OpcodeDec;
93 OpcodeTable[opJumpRelNotZero] := OpcodeJumpRelNotZero;
94end;
95
96procedure TMachine.OpcodeNop;
97begin
98
99end;
100
101procedure TMachine.OpcodeHalt;
102begin
103 Terminated := True;
104end;
105
106procedure TMachine.OpcodeCopy;
107var
108 Source: TRegIndex;
109 Dest: TRegIndex;
110 Size: TRegSize;
111begin
112 Dest := ReadNext;
113 Source := ReadNext;
114 Size := Min(RegisterSize[Dest], RegisterSize[Source]);
115 Move(Registers[Source], Registers[Dest], Size);
116end;
117
118procedure TMachine.OpcodeCopyFromMem;
119var
120 Source: TRegIndex;
121 Dest: TRegIndex;
122begin
123 Dest := ReadNext;
124 Source := ReadNext;
125 Move(Memory[Registers[Source]], Registers[Dest], RegisterSize[Dest]);
126end;
127
128procedure TMachine.OpcodeCopyToMem;
129var
130 Source: TRegIndex;
131 Dest: TRegIndex;
132begin
133 Source := ReadNext;
134 Dest := ReadNext;
135 Move(Registers[Source], Memory[Registers[Dest]], RegisterSize[Source]);
136end;
137
138procedure TMachine.OpcodeCopyConst;
139var
140 Source: TRegIndex;
141 Dest: TRegIndex;
142begin
143 Dest := ReadNext;
144 Source := ReadNext;
145 Move(Source, Registers[Dest], RegisterSize[Dest]);
146end;
147
148procedure TMachine.OpcodeSetRegSize;
149var
150 Reg: TRegIndex;
151 Size: TRegSize;
152begin
153 Reg := ReadNext;
154 Size := Registers[ReadNext];
155 if Size <= SizeOf(TDataInt) then
156 RegisterSize[Reg] := Size
157 else raise Exception.Create('Can''t set register size ' + IntToStr(Size) + '. Max is ' + IntToStr(SizeOf(TDataInt)) + '.');
158end;
159
160procedure TMachine.OpcodeGetDataSize;
161var
162 Dest: TRegIndex;
163begin
164 Dest := ReadNext;
165 Registers[Dest] := SizeOf(TDataInt);
166end;
167
168procedure TMachine.OpcodeInc;
169var
170 Reg: TRegIndex;
171begin
172 Reg := ReadNext;
173 Registers[Reg] := Registers[Reg] + 1;
174end;
175
176procedure TMachine.OpcodeDec;
177var
178 Reg: TRegIndex;
179begin
180 Reg := ReadNext;
181 Registers[Reg] := Registers[Reg] - 1;
182end;
183
184procedure TMachine.OpcodeJumpRelNotZero;
185var
186 RelAddr: TAddrInt;
187 Reg: TRegIndex;
188begin
189 Reg := ReadNext;
190 RelAddr := ReadNext;
191 if Registers[Reg] <> 0 then
192 IP := IP - RelAddr;
193end;
194
195function TMachine.ReadNext: Integer;
196begin
197 if (IP >= 0) and (IP < Length(Memory)) then Result := Memory[IP]
198 else raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8));
199 Inc(IP);
200end;
201
202end.
203
Note: See TracBrowser for help on using the repository browser.