source: branches/DataAddress/UCpu.pas

Last change on this file was 199, checked in by chronos, 4 years ago
  • Added: Virtual CPU with customizable bit width of data and address.
File size: 6.7 KB
Line 
1unit UCpu;
2
3{$mode delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils;
9
10type
11 TAddress = QWord;
12 TData = QWord;
13 TOpcode = (opNop, opHalt, opLda, opSta, opAdda, opSuba, opLdca, opBra, opInp,
14 opOut, opBrz, opBrnz, opInca, opDeca, opLdi, opSti, opAnd, opOr, opXor,
15 opLdp, opStp, opAddp, opSubp, opLdcp, opIncp, opDecp);
16
17 PAddress = ^TAddress;
18 PData = ^TData;
19 POpcode = ^TOpcode;
20
21 TOpcodeHandler = procedure of object;
22 TInputEvent = function (Address: TAddress): TData of object;
23 TOutputEvent = procedure (Address: TAddress; Data: TData) of object;
24
25 { TCpu }
26
27 TCpu = class
28 private
29 FOnInput: TInputEvent;
30 FOnOutput: TOutputEvent;
31 OpcodeHandlers: array[TOpcode] of TOpcodeHandler;
32 procedure OpcodeAddp;
33 procedure OpcodeLdcp;
34 procedure OpcodeLdp;
35 procedure OpcodeNop;
36 procedure OpcodeHalt;
37 procedure OpcodeLda;
38 procedure OpcodeSta;
39 procedure OpcodeAdda;
40 procedure OpcodeStp;
41 procedure OpcodeSuba;
42 procedure OpcodeBra;
43 procedure OpcodeBrz;
44 procedure OpcodeBrnz;
45 procedure OpcodeLdca;
46 procedure OpcodeInp;
47 procedure OpcodeOut;
48 procedure OpcodeInca;
49 procedure OpcodeDeca;
50 procedure OpcodeLdi;
51 procedure OpcodeSti;
52 procedure OpcodeAnd;
53 procedure OpcodeOr;
54 procedure OpcodeSubp;
55 procedure OpcodeXor;
56 procedure OpcodeIncp;
57 procedure OpcodeDecp;
58 public
59 Memory: array of Byte;
60 A: TData;
61 P: TAddress;
62 IP: TAddress;
63 Cycles: Integer;
64 Terminated: Boolean;
65 function ReadOpcode: TOpcode;
66 function ReadData: TData;
67 function ReadAddress: TAddress;
68 procedure WriteOpcode(Opcode: TOpcode);
69 procedure WriteData(Data: TData);
70 procedure WriteAddress(Address: TAddress);
71 procedure WriteString(Text: string);
72 procedure Step;
73 procedure Run;
74 procedure Reset;
75 constructor Create;
76 property OnInput: TInputEvent read FOnInput write FOnInput;
77 property OnOutput: TOutputEvent read FOnOutput write FOnOutput;
78 end;
79
80implementation
81
82{ TCpu }
83
84procedure TCpu.OpcodeNop;
85begin
86end;
87
88procedure TCpu.OpcodeHalt;
89begin
90 Terminated := True;
91end;
92
93procedure TCpu.OpcodeLda;
94var
95 Address: TAddress;
96begin
97 Address := ReadAddress;
98 A := PData(@Memory[Address])^;
99end;
100
101procedure TCpu.OpcodeSta;
102var
103 Address: TAddress;
104begin
105 Address := ReadAddress;
106 PData(@Memory[Address])^ := A;
107end;
108
109procedure TCpu.OpcodeAdda;
110var
111 Address: TAddress;
112begin
113 Address := ReadAddress;
114 A := A + PData(@Memory[Address])^;
115end;
116
117procedure TCpu.OpcodeSuba;
118var
119 Address: TAddress;
120begin
121 Address := ReadAddress;
122 A := A - PData(@Memory[Address])^;
123end;
124
125procedure TCpu.OpcodeBra;
126begin
127 IP := ReadAddress;
128end;
129
130procedure TCpu.OpcodeBrz;
131var
132 Address: TAddress;
133begin
134 Address := ReadAddress;
135 if A = 0 then IP := Address;
136end;
137
138procedure TCpu.OpcodeBrnz;
139var
140 Address: TAddress;
141begin
142 Address := ReadAddress;
143 if A <> 0 then IP := Address;
144end;
145
146procedure TCpu.OpcodeLdca;
147begin
148 A := ReadData;
149end;
150
151procedure TCpu.OpcodeInp;
152var
153 Address: TAddress;
154begin
155 Address := ReadAddress;
156 if Assigned(FOnInput) then
157 A := FOnInput(Address);
158end;
159
160procedure TCpu.OpcodeOut;
161var
162 Address: TAddress;
163begin
164 Address := ReadAddress;
165 if Assigned(FOnOutput) then
166 FOnOutput(Address, A);
167end;
168
169procedure TCpu.OpcodeInca;
170begin
171 A := A + 1;
172end;
173
174procedure TCpu.OpcodeDeca;
175begin
176 A := A - 1;
177end;
178
179procedure TCpu.OpcodeLdi;
180var
181 Address: TAddress;
182begin
183 Address := ReadAddress;
184 Address := PAddress(@Memory[Address])^;
185 A := PData(@Memory[Address])^;
186end;
187
188procedure TCpu.OpcodeSti;
189var
190 Address: TAddress;
191begin
192 Address := ReadAddress;
193 Address := PAddress(@Memory[Address])^;
194 PData(@Memory[Address])^ := A;
195end;
196
197procedure TCpu.OpcodeAnd;
198var
199 Address: TAddress;
200begin
201 Address := ReadAddress;
202 A := A and PData(@Memory[Address])^;
203end;
204
205procedure TCpu.OpcodeOr;
206begin
207 A := A or PData(@Memory[ReadAddress])^;
208end;
209
210procedure TCpu.OpcodeXor;
211begin
212 A := A xor PData(@Memory[ReadAddress])^;
213end;
214
215procedure TCpu.OpcodeIncp;
216begin
217 P := P + 1;
218end;
219
220procedure TCpu.OpcodeDecp;
221begin
222 P := P - 1;
223end;
224
225procedure TCpu.OpcodeLdp;
226var
227 Address: TAddress;
228begin
229 Address := ReadAddress;
230 P := PAddress(@Memory[Address])^;
231end;
232
233procedure TCpu.OpcodeStp;
234var
235 Address: TAddress;
236begin
237 Address := ReadAddress;
238 PAddress(@Memory[Address])^ := P;
239end;
240
241procedure TCpu.OpcodeAddp;
242var
243 Address: TAddress;
244begin
245 Address := ReadAddress;
246 P := P + PAddress(@Memory[Address])^;
247end;
248
249procedure TCpu.OpcodeSubp;
250var
251 Address: TAddress;
252begin
253 Address := ReadAddress;
254 P := P - PAddress(@Memory[Address])^;
255end;
256
257procedure TCpu.OpcodeLdcp;
258begin
259 P := ReadAddress;
260end;
261
262function TCpu.ReadOpcode: TOpcode;
263begin
264 Result := TOpcode(PByte(@Memory[IP])^);
265 Inc(IP, SizeOf(Byte));
266end;
267
268function TCpu.ReadAddress: TAddress;
269begin
270 Result := PAddress(@Memory[IP])^;
271 Inc(IP, SizeOf(TAddress));
272end;
273
274procedure TCpu.WriteOpcode(Opcode: TOpcode);
275begin
276 PByte(@Memory[IP])^ := Byte(Opcode);
277 Inc(IP, SizeOf(Byte));
278end;
279
280procedure TCpu.WriteData(Data: TData);
281begin
282 PData(@Memory[IP])^ := Data;
283 Inc(IP, SizeOf(TData));
284end;
285
286procedure TCpu.WriteAddress(Address: TAddress);
287begin
288 PAddress(@Memory[IP])^ := Address;
289 Inc(IP, SizeOf(TAddress));
290end;
291
292procedure TCpu.WriteString(Text: string);
293var
294 I: Integer;
295begin
296 for I := 1 to Length(Text) do
297 Memory[IP + I - 1] := Ord(Text[I]);
298 Inc(IP, Length(Text));
299end;
300
301function TCpu.ReadData: TData;
302begin
303 Result := PData(@Memory[IP])^;
304 Inc(IP, SizeOf(TData));
305end;
306
307procedure TCpu.Step;
308var
309 Opcode: TOpcode;
310begin
311 Opcode := ReadOpcode;
312 OpcodeHandlers[Opcode];
313 Inc(Cycles);
314end;
315
316procedure TCpu.Run;
317begin
318 while not Terminated do
319 Step;
320end;
321
322procedure TCpu.Reset;
323begin
324 IP := 0;
325 A := 0;
326 Cycles := 0;
327 Terminated := False;
328end;
329
330constructor TCpu.Create;
331begin
332 OpcodeHandlers[opNop] := OpcodeNop;
333 OpcodeHandlers[opHalt] := OpcodeHalt;
334 OpcodeHandlers[opLda] := OpcodeLda;
335 OpcodeHandlers[opSta] := OpcodeSta;
336 OpcodeHandlers[opAdda] := OpcodeAdda;
337 OpcodeHandlers[opSuba] := OpcodeSuba;
338 OpcodeHandlers[opLdca] := OpcodeLdca;
339 OpcodeHandlers[opBra] := OpcodeBra;
340 OpcodeHandlers[opBrz] := OpcodeBrz;
341 OpcodeHandlers[opBrnz] := OpcodeBrnz;
342 OpcodeHandlers[opInp] := OpcodeInp;
343 OpcodeHandlers[opOut] := OpcodeOut;
344 OpcodeHandlers[opInca] := OpcodeInca;
345 OpcodeHandlers[opDeca] := OpcodeDeca;
346 OpcodeHandlers[opLdi] := OpcodeLdi;
347 OpcodeHandlers[opSti] := OpcodeSti;
348 OpcodeHandlers[opAnd] := OpcodeAnd;
349 OpcodeHandlers[opOr] := OpcodeOr;
350 OpcodeHandlers[opXor] := OpcodeXor;
351
352 // Address
353 OpcodeHandlers[opLdp] := OpcodeLdp;
354 OpcodeHandlers[opStp] := OpcodeStp;
355 OpcodeHandlers[opAddp] := OpcodeAddp;
356 OpcodeHandlers[opSubp] := OpcodeSubp;
357 OpcodeHandlers[opLdcp] := OpcodeLdcp;
358 OpcodeHandlers[opIncp] := OpcodeIncp;
359 OpcodeHandlers[opDecp] := OpcodeDecp;
360end;
361
362end.
363
Note: See TracBrowser for help on using the repository browser.