source: branches/test3/Cpu.pas

Last change on this file was 16, checked in by chronos, 2 weeks ago
  • Added: Test virtual machine implemented with generics to specify custom data and address bit width.
File size: 8.0 KB
Line 
1unit Cpu;
2
3interface
4
5uses
6 Classes, SysUtils;
7
8type
9 TInstruction = (inNop, inHalt,
10 inConstD, inConstA, inConstN,
11 inLoadD, inLoadA, inLoadN,
12 inStoreD, inStoreA, inStoreN,
13 inInputD, inInputA, inInputN,
14 inOutputD, inOutputA, inOutputN,
15 inAdd, inSub);
16
17 { TCpu }
18
19 TCpu<TData,TAddr,TMax> = class
20 type
21 PData = ^TData;
22 PAddr = ^TAddr;
23 PMax = ^TMax;
24 TRegIndex = 0..255;
25 TOnInput = function (Addr: TAddr; Count: Byte): TData of object;
26 TOnOutput = procedure (Addr: TAddr; Data: TData; Count: Byte) of object;
27 private
28 FOnInput: TOnInput;
29 FOnOutput: TOnOutput;
30 public
31 Memory: array[0..$ffff] of Byte;
32 PC: TAddr;
33 SP: TAddr;
34 R: array[TRegIndex] of TMax;
35 Terminated: Boolean;
36 procedure Run;
37 procedure Step;
38 procedure Reset;
39 procedure AddConstD(Reg: TRegIndex; Value: TData);
40 procedure AddConstA(Reg: TRegIndex; Value: TAddr);
41 procedure AddConstN(Count: Byte; Reg: TRegIndex; Value: TMax);
42 procedure AddOutputD(Addr: TAddr; Reg: TRegIndex);
43 procedure AddOutputA(Addr: TAddr; Reg: TRegIndex);
44 procedure AddOutputN(Count: Byte; Addr: TAddr; Reg: TRegIndex);
45 procedure AddHalt;
46 function ReadBytePC: Byte;
47 function ReadDataPC: TData;
48 function ReadAddrPC: TAddr;
49 function ReadPC(Count: Byte): TMax;
50 function ReadData(Addr: TAddr): TData;
51 function ReadAddr(Addr: TAddr): TAddr;
52 function Read(Addr: TAddr; Count: Byte): TMax;
53 function ReadRegData(Reg: TRegIndex): TData;
54 function ReadRegAddr(Reg: TRegIndex): TAddr;
55 function ReadReg(Reg: TRegIndex; Count: Byte): TMax;
56 procedure WriteBytePC(Data: Byte);
57 procedure WriteRegPC(Reg: TRegIndex);
58 procedure WriteDataPC(Data: TData);
59 procedure WriteAddrPC(Addr: TAddr);
60 procedure WritePC(Value: TMax; Count: Byte);
61 procedure WriteData(Addr: TAddr; Value: TData);
62 procedure WriteAddr(Addr, Value: TAddr);
63 procedure WriteRegData(Reg: TRegIndex; Value: TData);
64 procedure WriteRegAddr(Reg: TRegIndex; Value: TAddr);
65 procedure WriteReg(Reg: TRegIndex; Value: TMax; Count: Byte);
66 constructor Create;
67 destructor Destroy; override;
68 property OnInput: TOnInput read FOnInput write FOnInput;
69 property OnOutput: TOnOutput read FOnOutput write FOnOutput;
70 end;
71
72
73implementation
74
75{ TCpu }
76
77procedure TCpu<TData,TAddr,TMax>.Run;
78begin
79 Reset;
80 while not Terminated do
81 Step;
82end;
83
84procedure TCpu<TData,TAddr,TMax>.Step;
85var
86 Instruction: TInstruction;
87 I: TRegIndex;
88 Addr: TAddr;
89 N: Byte;
90 M: TMax;
91begin
92 Instruction := TInstruction(ReadBytePC);
93 case Instruction of
94 inNop: ;
95 inHalt: Terminated := True;
96 inConstD: PData(@R[ReadBytePC])^ := ReadDataPC;
97 inConstA: PAddr(@R[ReadBytePC])^ := ReadAddrPC;
98 inConstN: begin
99 N := ReadBytePC;
100 I := ReadBytePC;
101 WriteReg(I, ReadPC(N), N);
102 end;
103 inLoadD: PData(@R[ReadBytePC])^ := ReadData(ReadAddrPC);
104 inLoadA: PAddr(@R[ReadBytePC])^ := ReadAddr(ReadAddrPC);
105 inLoadN: begin
106 N := ReadBytePC;
107 WriteReg(ReadBytePC, Read(ReadAddrPC, N), N);
108 end;
109 inStoreD: WriteData(ReadAddrPC, R[ReadBytePC]);
110 inStoreA: WriteAddr(ReadAddrPC, R[ReadBytePC]);
111 inStoreN: begin
112 N := ReadBytePC;
113 Write(ReadAddrPC, ReadReg(ReadBytePC, N), N);
114 end;
115 inInputD: begin
116 I := ReadBytePC;
117 Addr := ReadAddrPC;
118 if Assigned(FOnInput) then PData(@R[I])^ := FOnInput(Addr, SizeOf(TData))
119 else R[I] := 0;
120 end;
121 inInputA: begin
122 I := ReadBytePC;
123 Addr := ReadAddrPC;
124 if Assigned(FOnInput) then PAddr(@R[I])^ := FOnInput(Addr, SizeOf(TAddr))
125 else R[I] := 0;
126 end;
127 inInputN: begin
128 N := ReadBytePC;
129 I := ReadBytePC;
130 Addr := ReadAddrPC;
131 if Assigned(FOnInput) then begin
132 M := FOnInput(Addr, N);
133 Move(M, R[I], N);
134 end else R[I] := 0;
135 end;
136 inOutputD: begin
137 Addr := ReadAddrPC;
138 I := ReadBytePC;
139 if Assigned(FOnOutput) then FOnOutput(Addr, PData(@R[I])^, SizeOf(TData));
140 end;
141 inOutputA: begin
142 Addr := ReadAddrPC;
143 I := ReadBytePC;
144 if Assigned(FOnOutput) then FOnOutput(Addr, PAddr(@R[I])^, SizeOf(TAddr));
145 end;
146 inOutputN: begin
147 N := ReadBytePC;
148 Addr := ReadAddrPC;
149 I := ReadBytePC;
150 M := 0;
151 Move(R[I], M, N);
152 if Assigned(FOnOutput) then FOnOutput(Addr, M, N);
153 end;
154 end;
155end;
156
157procedure TCpu<TData,TAddr,TMax>.Reset;
158begin
159 SP := 0;
160 PC := 0;
161 Terminated := False;
162end;
163
164procedure TCpu<TData,TAddr,TMax>.AddConstD(Reg: TRegIndex; Value: TData);
165begin
166 WriteBytePC(Byte(inConstD));
167 WriteRegPC(Reg);
168 WriteDataPC(Value);
169end;
170
171procedure TCpu<TData, TAddr, TMax>.AddConstA(Reg: TRegIndex; Value: TAddr);
172begin
173 WriteBytePC(Byte(inConstA));
174 WriteRegPC(Reg);
175 WriteAddrPC(Value);
176end;
177
178procedure TCpu<TData, TAddr, TMax>.AddConstN(Count: Byte; Reg: TRegIndex;
179 Value: TMax);
180begin
181 WriteBytePC(Byte(inConstN));
182 WriteBytePc(Count);
183 WriteRegPC(Reg);
184 WritePC(Value, Count);
185end;
186
187procedure TCpu<TData, TAddr, TMax>.AddOutputD(Addr: TAddr; Reg: TRegIndex);
188begin
189 WriteBytePC(Byte(inOutputD));
190 WriteAddrPC(Addr);
191 WriteRegPC(Reg);
192end;
193
194procedure TCpu<TData, TAddr, TMax>.AddOutputA(Addr: TAddr; Reg: TRegIndex);
195begin
196 WriteBytePC(Byte(inOutputA));
197 WriteAddrPC(Addr);
198 WriteRegPC(Reg);
199end;
200
201procedure TCpu<TData, TAddr, TMax>.AddOutputN(Count: Byte; Addr: TAddr;
202 Reg: TRegIndex);
203begin
204 WriteBytePC(Byte(inOutputN));
205 WriteBytePC(Count);
206 WriteAddrPC(Addr);
207 WriteRegPC(Reg);
208end;
209
210procedure TCpu<TData,TAddr,TMax>.AddHalt;
211begin
212 WriteBytePC(Byte(inHalt));
213end;
214
215function TCpu<TData,TAddr,TMax>.ReadBytePC: Byte;
216begin
217 Result := Memory[PC];
218 Inc(PC);
219end;
220
221function TCpu<TData,TAddr,TMax>.ReadDataPC: TData;
222begin
223 Result := PData(@Memory[PC])^;
224 Inc(PC, SizeOf(TData));
225end;
226
227function TCpu<TData,TAddr,TMax>.ReadAddrPC: TAddr;
228begin
229 Result := PAddr(@Memory[PC])^;
230 Inc(PC, SizeOf(TAddr));
231end;
232
233function TCpu<TData, TAddr, TMax>.ReadPC(Count: Byte): TMax;
234begin
235 Move(PMax(@Memory[PC])^, Result, Count);
236 Inc(PC, SizeOf(Count));
237end;
238
239function TCpu<TData,TAddr,TMax>.ReadData(Addr: TAddr): TData;
240begin
241 Result := PData(@Memory[Addr])^;
242end;
243
244function TCpu<TData, TAddr, TMax>.ReadAddr(Addr: TAddr): TAddr;
245begin
246 Result := PAddr(@Memory[Addr])^;
247end;
248
249function TCpu<TData, TAddr, TMax>.Read(Addr: TAddr; Count: Byte): TMax;
250begin
251 Move(PMax(@Memory[Addr])^, Result, Count);
252end;
253
254function TCpu<TData, TAddr, TMax>.ReadRegData(Reg: TRegIndex): TData;
255begin
256 Result := PData(@R[Reg])^;
257end;
258
259function TCpu<TData, TAddr, TMax>.ReadRegAddr(Reg: TRegIndex): TAddr;
260begin
261 Result := PAddr(@R[Reg])^;
262end;
263
264function TCpu<TData, TAddr, TMax>.ReadReg(Reg: TRegIndex; Count: Byte): TMax;
265begin
266 Move(PMax(@R[Reg])^, Result, Count);
267end;
268
269procedure TCpu<TData,TAddr,TMax>.WriteBytePC(Data: Byte);
270begin
271 Memory[PC] := Data;
272 Inc(PC);
273end;
274
275procedure TCpu<TData,TAddr,TMax>.WriteRegPC(Reg: TRegIndex);
276begin
277 Memory[PC] := Reg;
278 Inc(PC, SizeOf(Reg));
279end;
280
281procedure TCpu<TData,TAddr,TMax>.WriteDataPC(Data: TData);
282begin
283 WriteData(PC, Data);
284 Inc(PC, SizeOf(TData));
285end;
286
287procedure TCpu<TData,TAddr,TMax>.WriteAddrPC(Addr: TAddr);
288begin
289 WriteAddr(PC, Addr);
290 Inc(PC, SizeOf(TAddr));
291end;
292
293procedure TCpu<TData, TAddr, TMax>.WritePC(Value: TMax; Count: Byte);
294begin
295 Move(Value, PMax(@Memory[PC])^, Count);
296 Inc(PC, Count);
297end;
298
299procedure TCpu<TData,TAddr,TMax>.WriteData(Addr: TAddr; Value: TData);
300begin
301 PData(@Memory[Addr])^ := Value;
302end;
303
304procedure TCpu<TData,TAddr,TMax>.WriteAddr(Addr, Value: TAddr);
305begin
306 PAddr(@Memory[Addr])^ := Value;
307end;
308
309procedure TCpu<TData, TAddr, TMax>.WriteRegData(Reg: TRegIndex; Value: TData);
310begin
311 PData(@R[Reg])^ := Value;
312end;
313
314procedure TCpu<TData, TAddr, TMax>.WriteRegAddr(Reg: TRegIndex; Value: TAddr);
315begin
316 PAddr(@R[Reg])^ := Value;
317end;
318
319procedure TCpu<TData, TAddr, TMax>.WriteReg(Reg: TRegIndex; Value: TMax;
320 Count: Byte);
321begin
322 R[Reg] := 0;
323 Move(Value, PMax(@R[Reg])^, Count);
324end;
325
326constructor TCpu<TData,TAddr,TMax>.Create;
327begin
328end;
329
330destructor TCpu<TData,TAddr,TMax>.Destroy;
331begin
332 inherited;
333end;
334
335end.
336
Note: See TracBrowser for help on using the repository browser.