source: branches/Machine/UMachine.pas

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

Another experimental virtual CPU implementation.

File size: 8.4 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 TOpcode = (opNop, opHalt, opCopy, opAdd, opSub, opMul, opDiv, opSet,
21 opParamClearAll, opParamSelect, opParamSet, opParamIndirect, opParamNext,
22 opSkip, opSign, opParamSize);
23
24 TAreaType = (atAddress, atMemory, atIOPort, atRegister, atSysRegister);
25
26 TSysAddr = (saInstructionPointer, saAddrWidth, saDataWidth, saRegisterCount);
27
28 TParameter = record
29 Number: TAddrInt;
30 Area: Integer;
31 Size: Integer;
32 Defined: Boolean;
33 end;
34
35 TOpcodeHandler = procedure of object;
36
37 { TMachine }
38
39 TMachine = class
40 private
41 OpcodeTable: array[TOpcode] of TOpcodeHandler;
42 SkipNextInstruction: Boolean;
43 CurrentParam: Integer;
44 procedure OpcodeNop;
45 procedure OpcodeHalt;
46 procedure OpcodeCopy;
47 procedure OpcodeAdd;
48 procedure OpcodeSub;
49 procedure OpcodeMul;
50 procedure OpcodeDiv;
51 procedure OpcodeParamNext;
52 procedure OpcodeParamSelect;
53 procedure OpcodeParamSet;
54 procedure OpcodeParamIndirect;
55 procedure OpcodeParamClearAll;
56 procedure OpcodeParamSize;
57 procedure OpcodeSkip;
58 procedure OpcodeSign;
59 function ReadNext: Integer;
60 public
61 Memory: array of Byte;
62 Registers: array of TAddrInt;
63 IP: TAddrInt;
64 Params: array of TParameter;
65 Terminated: Boolean;
66 function ReadPort(Address: Integer): TDataInt;
67 procedure WritePort(Address: TAddrInt; Value: TDataInt);
68 function ReadArea(AreaIndex: Integer; Address: TAddrInt): TDataInt;
69 procedure WriteArea(AreaIndex: Integer; Address: TAddrInt; Value: TDataInt);
70 function ReadSys(Address: TAddrInt): TDataInt;
71 procedure Run;
72 constructor Create;
73 end;
74
75implementation
76
77{ TMachine }
78
79procedure TMachine.OpcodeNop;
80begin
81end;
82
83procedure TMachine.OpcodeHalt;
84begin
85 Terminated := True;
86end;
87
88procedure TMachine.OpcodeCopy;
89begin
90// for I := 0 to Params[0].Size - 1 do begin
91 WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[1].Area, Params[1].Number));
92end;
93
94procedure TMachine.OpcodeAdd;
95begin
96 if Params[2].Defined then
97 WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[2].Area, Params[2].Number) + ReadArea(Params[1].Area, Params[1].Number))
98 else if Params[1].Defined then WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[0].Area, Params[0].Number) + ReadArea(Params[1].Area, Params[1].Number))
99 else WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[0].Area, Params[0].Number) + 1);
100end;
101
102procedure TMachine.OpcodeSub;
103begin
104 if Params[2].Defined then
105 WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[2].Area, Params[2].Number) - ReadArea(Params[1].Area, Params[1].Number))
106 else if Params[1].Defined then WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[0].Area, Params[0].Number) - ReadArea(Params[1].Area, Params[1].Number))
107 else WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[0].Area, Params[0].Number) - 1);
108end;
109
110procedure TMachine.OpcodeMul;
111begin
112 if Params[2].Defined then
113 WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[2].Area, Params[2].Number) * ReadArea(Params[1].Area, Params[1].Number))
114 else WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[0].Area, Params[0].Number) * ReadArea(Params[1].Area, Params[1].Number));
115end;
116
117procedure TMachine.OpcodeDiv;
118begin
119 if Params[2].Defined then
120 WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[2].Area, Params[2].Number) div ReadArea(Params[1].Area, Params[1].Number))
121 else WriteArea(Params[0].Area, Params[0].Number, ReadArea(Params[0].Area, Params[0].Number) div ReadArea(Params[1].Area, Params[1].Number));
122end;
123
124procedure TMachine.OpcodeParamNext;
125begin
126 Inc(CurrentParam);
127end;
128
129procedure TMachine.OpcodeParamSelect;
130begin
131 CurrentParam := ReadNext;
132end;
133
134procedure TMachine.OpcodeParamSet;
135begin
136 Params[CurrentParam].Number := ReadNext;
137 Params[CurrentParam].Area := Integer(atAddress);
138 Params[CurrentParam].Defined := True;
139end;
140
141procedure TMachine.OpcodeParamIndirect;
142begin
143 if not Params[CurrentParam].Defined then
144 raise Exception.Create('Undefined parameter ' + IntToStr(CurrentParam));
145 if Params[CurrentParam].Area = Integer(atAddress) then
146 Params[CurrentParam].Area := ReadNext
147 else begin
148 Params[CurrentParam].Number := ReadArea(Params[CurrentParam].Area, Params[CurrentParam].Number);
149 Params[CurrentParam].Area := ReadNext;
150 end;
151end;
152
153procedure TMachine.OpcodeParamClearAll;
154var
155 I: Integer;
156begin
157 for I := 0 to Length(Params) - 1 do begin
158 Params[I].Number := 0;
159 Params[I].Area := Integer(atAddress);
160 Params[I].Defined := False;
161 Params[I].Size := 1;
162 end;
163 CurrentParam := 0;
164end;
165
166procedure TMachine.OpcodeParamSize;
167begin
168 Params[CurrentParam].Size := ReadNext;
169end;
170
171procedure TMachine.OpcodeSkip;
172begin
173 if ReadArea(Params[0].Area, Params[0].Number) < 0 then begin
174 SkipNextInstruction := True;
175 end;
176end;
177
178procedure TMachine.OpcodeSign;
179begin
180 if not Params[1].Defined then
181 WriteArea(Params[0].Area, Params[0].Number, Sign(ReadArea(Params[1].Area, Params[1].Number)))
182 else WriteArea(Params[0].Area, Params[0].Number, Sign(ReadArea(Params[0].Area, Params[0].Number)));
183end;
184
185function TMachine.ReadNext: Integer;
186begin
187 if (IP >= 0) and (IP < Length(Memory)) then Result := Memory[IP]
188 else raise Exception.Create('Memory access out of range ' + IntToHex(IP, 8));
189 Inc(IP);
190end;
191
192function TMachine.ReadPort(Address: Integer): TDataInt;
193begin
194 Result := 0;
195end;
196
197procedure TMachine.WritePort(Address: TAddrInt; Value: TDataInt);
198begin
199
200end;
201
202function TMachine.ReadArea(AreaIndex: Integer; Address: TAddrInt): TDataInt;
203begin
204 if AreaIndex = Integer(atAddress) then Result := Address
205 else if AreaIndex = Integer(atMemory) then Result := Memory[Address]
206 else if AreaIndex = Integer(atIOPort) then Result := ReadPort(Address)
207 else if AreaIndex = Integer(atRegister) then Result := Registers[Address]
208 else if AreaIndex = Integer(atSysRegister) then Result := ReadSys(Address)
209 else raise Exception.Create('Unsupported area number ' + IntToStr(AreaIndex));
210end;
211
212procedure TMachine.WriteArea(AreaIndex: Integer; Address: TAddrInt;
213 Value: TDataInt);
214begin
215 if AreaIndex = Integer(atAddress) then
216 else if AreaIndex = Integer(atMemory) then Memory[Address] := Value
217 else if AreaIndex = Integer(atIOPort) then WritePort(Address, Value)
218 else if AreaIndex = Integer(atRegister) then Registers[Address] := Value
219 else if AreaIndex = Integer(atSysRegister) then begin
220 if Address = 0 then IP := Value
221 end else raise Exception.Create('Unsupported area number ' + IntToStr(AreaIndex));
222end;
223
224function TMachine.ReadSys(Address: TAddrInt): TDataInt;
225begin
226 if Address = Integer(saInstructionPointer) then Result := IP
227 else if Address = Integer(saAddrWidth) then Result := SizeOf(TAddrInt)
228 else if Address = Integer(saDataWidth) then Result := SizeOf(TDataInt)
229 else if Address = Integer(saRegisterCount) then Result := Length(Registers)
230 else Result := 0;
231end;
232
233procedure TMachine.Run;
234var
235 Opcode: TOpcode;
236 I: Integer;
237begin
238 IP := 0;
239 Terminated := False;
240 CurrentParam := 0;
241 while not Terminated do begin
242 Opcode := TOpcode(ReadNext);
243 if SkipNextInstruction and ((Opcode <> opParamIndirect) and (Opcode <> opParamSelect) and
244 (Opcode <> opParamClearAll) and (Opcode <> opParamSet) and (Opcode <> opParamNext)) then begin
245 SkipNextInstruction := False;
246 end else begin
247 if Assigned(OpcodeTable[Opcode]) then
248 OpcodeTable[Opcode]
249 else raise Exception.Create('Unknown opcode ' + IntToStr(Integer(Opcode)));
250 end;
251 end;
252end;
253
254constructor TMachine.Create;
255begin
256 SetLength(Registers, 16);
257 SetLength(Params, 4);
258
259 // Opcode table initialization
260 OpcodeTable[opNop] := OpcodeNop;
261 OpcodeTable[opHalt] := OpcodeHalt;
262 OpcodeTable[opCopy] := OpcodeCopy;
263 OpcodeTable[opAdd] := OpcodeAdd;
264 OpcodeTable[opSub] := OpcodeSub;
265 OpcodeTable[opMul] := OpcodeMul;
266 OpcodeTable[opDiv] := OpcodeDiv;
267 OpcodeTable[opParamSelect] := OpcodeParamSelect;
268 OpcodeTable[opParamSet] := OpcodeParamSet;
269 OpcodeTable[opParamIndirect] := OpcodeParamIndirect;
270 OpcodeTable[opParamClearAll] := OpcodeParamClearAll;
271 OpcodeTable[opSkip] := OpcodeSkip;
272 OpcodeTable[opSign] := OpcodeSign;
273 OpcodeTable[opParamNext] := OpcodeParamNext;
274 OpcodeTable[opParamSize] := OpcodeParamSize;
275end;
276
277end.
278
Note: See TracBrowser for help on using the repository browser.