1 | unit Cpu;
|
---|
2 |
|
---|
3 | interface
|
---|
4 |
|
---|
5 | uses
|
---|
6 | Classes, SysUtils, Int;
|
---|
7 |
|
---|
8 | type
|
---|
9 | TInstructionEvent = procedure of object;
|
---|
10 |
|
---|
11 | TInstruction = (inNop, inHalt, inLoad, inLoadConst, inInput, inOutput,
|
---|
12 | inJump, inJumpZero, inJumpNotZero, inIncrement, inDecrement, inLoadIndex,
|
---|
13 | inPush, inPop, inCall, inReturn, inLoadMem, inStoreMem, inAdd, inSubtract,
|
---|
14 | inAnd, inOr, inXor, inShiftLeft, inShiftRight, inJumpRel, inJumpRelZero,
|
---|
15 | inJumpRelNotZero, inBitSet, inBitReset, inBitTest, inGetMaxInt, inGetMinInt);
|
---|
16 |
|
---|
17 | { TCpu }
|
---|
18 |
|
---|
19 | TCpu = class
|
---|
20 | private
|
---|
21 | FOnReadIo: TReadAddrEvent;
|
---|
22 | FOnReadMem: TReadAddrEvent;
|
---|
23 | FOnWriteIo: TWriteAddrEvent;
|
---|
24 | FOnWriteMem: TWriteAddrEvent;
|
---|
25 | Instructions: array[TInstruction] of TInstructionEvent;
|
---|
26 | procedure InstructionNop;
|
---|
27 | procedure InstructionHalt;
|
---|
28 | procedure InstructionLoad;
|
---|
29 | procedure InstructionLoadConst;
|
---|
30 | procedure InstructionLoadIndex;
|
---|
31 | procedure InstructionLoadMem;
|
---|
32 | procedure InstructionStoreMem;
|
---|
33 | procedure InstructionInput;
|
---|
34 | procedure InstructionOutput;
|
---|
35 | procedure InstructionInc;
|
---|
36 | procedure InstructionDec;
|
---|
37 | procedure InstructionJump;
|
---|
38 | procedure InstructionJumpZero;
|
---|
39 | procedure InstructionJumpNotZero;
|
---|
40 | procedure InstructionJumpRel;
|
---|
41 | procedure InstructionJumpRelZero;
|
---|
42 | procedure InstructionJumpRelNotZero;
|
---|
43 | procedure InstructionPush;
|
---|
44 | procedure InstructionPop;
|
---|
45 | procedure InstructionCall;
|
---|
46 | procedure InstructionRet;
|
---|
47 | procedure InstructionAdd;
|
---|
48 | procedure InstructionSub;
|
---|
49 | procedure InstructionAnd;
|
---|
50 | procedure InstructionOr;
|
---|
51 | procedure InstructionXor;
|
---|
52 | procedure InstructionShl;
|
---|
53 | procedure InstructionShr;
|
---|
54 | procedure InstructionBitSet;
|
---|
55 | procedure InstructionBitReset;
|
---|
56 | procedure InstructionBitTest;
|
---|
57 | procedure InstructionGetMaxInt;
|
---|
58 | procedure InstructionGetMinInt;
|
---|
59 | procedure WriteMem(Address, Data: TInt);
|
---|
60 | function ReadMem(Address: TInt): TInt;
|
---|
61 | function ReadMemPc: TInt;
|
---|
62 | procedure WriteIo(Address, Data: TInt);
|
---|
63 | function ReadIo(Address: TInt): TInt;
|
---|
64 | procedure Push(Data: TInt);
|
---|
65 | function Pop: TInt;
|
---|
66 | public
|
---|
67 | Halted: Boolean;
|
---|
68 | PC: TInt;
|
---|
69 | SP: TInt;
|
---|
70 | procedure Reset;
|
---|
71 | procedure Run;
|
---|
72 | procedure Step;
|
---|
73 | constructor Create;
|
---|
74 | property OnReadMem: TReadAddrEvent read FOnReadMem write FOnReadMem;
|
---|
75 | property OnWriteMem: TWriteAddrEvent read FOnWriteMem write FOnWriteMem;
|
---|
76 | property OnReadIo: TReadAddrEvent read FOnReadIo write FOnReadIo;
|
---|
77 | property OnWriteIo: TWriteAddrEvent read FOnWriteIo write FOnWriteIo;
|
---|
78 | end;
|
---|
79 |
|
---|
80 | implementation
|
---|
81 |
|
---|
82 | { TCpu }
|
---|
83 |
|
---|
84 | procedure TCpu.InstructionNop;
|
---|
85 | begin
|
---|
86 | // No operation
|
---|
87 | end;
|
---|
88 |
|
---|
89 | procedure TCpu.InstructionHalt;
|
---|
90 | begin
|
---|
91 | Halted := True;
|
---|
92 | end;
|
---|
93 |
|
---|
94 | procedure TCpu.InstructionLoad;
|
---|
95 | var
|
---|
96 | Dst, Src: TInt;
|
---|
97 | begin
|
---|
98 | Dst := ReadMemPc;
|
---|
99 | Src := ReadMemPc;
|
---|
100 | WriteMem(Dst, ReadMem(Src));
|
---|
101 | end;
|
---|
102 |
|
---|
103 | procedure TCpu.InstructionLoadConst;
|
---|
104 | var
|
---|
105 | Dst, Data: TInt;
|
---|
106 | begin
|
---|
107 | Dst := ReadMemPc;
|
---|
108 | Data := ReadMemPc;
|
---|
109 | WriteMem(Dst, Data);
|
---|
110 | end;
|
---|
111 |
|
---|
112 | procedure TCpu.InstructionLoadIndex;
|
---|
113 | var
|
---|
114 | Dst, Src, Index: TInt;
|
---|
115 | begin
|
---|
116 | Dst := ReadMemPc;
|
---|
117 | Src := ReadMemPc;
|
---|
118 | Index := ReadMemPc;
|
---|
119 | WriteMem(Dst, ReadMem(Src + Index));
|
---|
120 | end;
|
---|
121 |
|
---|
122 | procedure TCpu.InstructionLoadMem;
|
---|
123 | var
|
---|
124 | Dst, Src: TInt;
|
---|
125 | begin
|
---|
126 | Dst := ReadMemPc;
|
---|
127 | Src := ReadMemPc;
|
---|
128 | WriteMem(Dst, ReadMem(ReadMem(Src)));
|
---|
129 | end;
|
---|
130 |
|
---|
131 | procedure TCpu.InstructionStoreMem;
|
---|
132 | var
|
---|
133 | Dst, Src: TInt;
|
---|
134 | begin
|
---|
135 | Dst := ReadMemPc;
|
---|
136 | Src := ReadMemPc;
|
---|
137 | WriteMem(ReadMem(Dst), ReadMem(Src));
|
---|
138 | end;
|
---|
139 |
|
---|
140 | procedure TCpu.InstructionInput;
|
---|
141 | var
|
---|
142 | Dst, Src: TInt;
|
---|
143 | begin
|
---|
144 | Dst := ReadMemPc;
|
---|
145 | Src := ReadMemPc;
|
---|
146 | WriteMem(Dst, ReadIo(Src));
|
---|
147 | end;
|
---|
148 |
|
---|
149 | procedure TCpu.InstructionOutput;
|
---|
150 | var
|
---|
151 | Dst, Src: TInt;
|
---|
152 | begin
|
---|
153 | Dst := ReadMemPc;
|
---|
154 | Src := ReadMemPc;
|
---|
155 | WriteIo(Dst, ReadMem(Src));
|
---|
156 | end;
|
---|
157 |
|
---|
158 | procedure TCpu.InstructionInc;
|
---|
159 | var
|
---|
160 | Addr: TInt;
|
---|
161 | begin
|
---|
162 | Addr := ReadMemPc;
|
---|
163 | WriteMem(Addr, ReadMem(Addr) + 1);
|
---|
164 | end;
|
---|
165 |
|
---|
166 | procedure TCpu.InstructionDec;
|
---|
167 | var
|
---|
168 | Addr: TInt;
|
---|
169 | begin
|
---|
170 | Addr := ReadMemPc;
|
---|
171 | WriteMem(Addr, ReadMem(Addr) - 1);
|
---|
172 | end;
|
---|
173 |
|
---|
174 | procedure TCpu.InstructionJump;
|
---|
175 | begin
|
---|
176 | PC := ReadMemPc;
|
---|
177 | end;
|
---|
178 |
|
---|
179 | procedure TCpu.InstructionJumpZero;
|
---|
180 | var
|
---|
181 | Condition: TInt;
|
---|
182 | Addr: TInt;
|
---|
183 | begin
|
---|
184 | Condition := ReadMemPc;
|
---|
185 | Addr := ReadMemPc;
|
---|
186 | if ReadMem(Condition) = 0 then PC := Addr;
|
---|
187 | end;
|
---|
188 |
|
---|
189 | procedure TCpu.InstructionJumpNotZero;
|
---|
190 | var
|
---|
191 | Condition: TInt;
|
---|
192 | Addr: TInt;
|
---|
193 | begin
|
---|
194 | Condition := ReadMemPc;
|
---|
195 | Addr := ReadMemPc;
|
---|
196 | if ReadMem(Condition) <> 0 then PC := Addr;
|
---|
197 | end;
|
---|
198 |
|
---|
199 | procedure TCpu.InstructionJumpRel;
|
---|
200 | var
|
---|
201 | Addr: TInt;
|
---|
202 | begin
|
---|
203 | Addr := ReadMemPc;
|
---|
204 | PC := PC + Addr;
|
---|
205 | end;
|
---|
206 |
|
---|
207 | procedure TCpu.InstructionJumpRelZero;
|
---|
208 | var
|
---|
209 | Condition: TInt;
|
---|
210 | Addr: TInt;
|
---|
211 | begin
|
---|
212 | Condition := ReadMemPc;
|
---|
213 | Addr := ReadMemPc;
|
---|
214 | if ReadMem(Condition) = 0 then PC := PC + Addr;
|
---|
215 | end;
|
---|
216 |
|
---|
217 | procedure TCpu.InstructionJumpRelNotZero;
|
---|
218 | var
|
---|
219 | Condition: TInt;
|
---|
220 | Addr: TInt;
|
---|
221 | begin
|
---|
222 | Condition := ReadMemPc;
|
---|
223 | Addr := ReadMemPc;
|
---|
224 | if ReadMem(Condition) <> 0 then PC := PC + Addr;
|
---|
225 | end;
|
---|
226 |
|
---|
227 | procedure TCpu.InstructionPush;
|
---|
228 | begin
|
---|
229 | Push(ReadMem(ReadMemPc));
|
---|
230 | end;
|
---|
231 |
|
---|
232 | procedure TCpu.InstructionPop;
|
---|
233 | begin
|
---|
234 | WriteMem(ReadMemPc, Pop);
|
---|
235 | end;
|
---|
236 |
|
---|
237 | procedure TCpu.InstructionCall;
|
---|
238 | var
|
---|
239 | Addr: TInt;
|
---|
240 | begin
|
---|
241 | Addr := ReadMemPc;
|
---|
242 | Push(PC);
|
---|
243 | PC := Addr;
|
---|
244 | end;
|
---|
245 |
|
---|
246 | procedure TCpu.InstructionRet;
|
---|
247 | begin
|
---|
248 | PC := Pop;
|
---|
249 | end;
|
---|
250 |
|
---|
251 | procedure TCpu.InstructionAdd;
|
---|
252 | var
|
---|
253 | Dst, Src1, Src2: TInt;
|
---|
254 | begin
|
---|
255 | Dst := ReadMemPc;
|
---|
256 | Src1 := ReadMemPc;
|
---|
257 | Src2 := ReadMemPc;
|
---|
258 | WriteMem(Dst, ReadMem(Src1) + ReadMem(Src2));
|
---|
259 | end;
|
---|
260 |
|
---|
261 | procedure TCpu.InstructionSub;
|
---|
262 | var
|
---|
263 | Dst, Src1, Src2: TInt;
|
---|
264 | begin
|
---|
265 | Dst := ReadMemPc;
|
---|
266 | Src1 := ReadMemPc;
|
---|
267 | Src2 := ReadMemPc;
|
---|
268 | WriteMem(Dst, ReadMem(Src1) - ReadMem(Src2));
|
---|
269 | end;
|
---|
270 |
|
---|
271 | procedure TCpu.InstructionAnd;
|
---|
272 | var
|
---|
273 | Dst, Src1, Src2: TInt;
|
---|
274 | begin
|
---|
275 | Dst := ReadMemPc;
|
---|
276 | Src1 := ReadMemPc;
|
---|
277 | Src2 := ReadMemPc;
|
---|
278 | WriteMem(Dst, ReadMem(Src1) and ReadMem(Src2));
|
---|
279 | end;
|
---|
280 |
|
---|
281 | procedure TCpu.InstructionOr;
|
---|
282 | var
|
---|
283 | Dst, Src1, Src2: TInt;
|
---|
284 | begin
|
---|
285 | Dst := ReadMemPc;
|
---|
286 | Src1 := ReadMemPc;
|
---|
287 | Src2 := ReadMemPc;
|
---|
288 | WriteMem(Dst, ReadMem(Src1) or ReadMem(Src2));
|
---|
289 | end;
|
---|
290 |
|
---|
291 | procedure TCpu.InstructionXor;
|
---|
292 | var
|
---|
293 | Dst, Src1, Src2: TInt;
|
---|
294 | begin
|
---|
295 | Dst := ReadMemPc;
|
---|
296 | Src1 := ReadMemPc;
|
---|
297 | Src2 := ReadMemPc;
|
---|
298 | WriteMem(Dst, ReadMem(Src1) xor ReadMem(Src2));
|
---|
299 | end;
|
---|
300 |
|
---|
301 | procedure TCpu.InstructionShl;
|
---|
302 | var
|
---|
303 | Dst, Src, Shift: TInt;
|
---|
304 | begin
|
---|
305 | Dst := ReadMemPc;
|
---|
306 | Src := ReadMemPc;
|
---|
307 | Shift := ReadMemPc;
|
---|
308 | WriteMem(Dst, ReadMem(Src) shl ReadMem(Shift));
|
---|
309 | end;
|
---|
310 |
|
---|
311 | procedure TCpu.InstructionShr;
|
---|
312 | var
|
---|
313 | Dst, Src, Shift: TInt;
|
---|
314 | begin
|
---|
315 | Dst := ReadMemPc;
|
---|
316 | Src := ReadMemPc;
|
---|
317 | Shift := ReadMemPc;
|
---|
318 | WriteMem(Dst, ReadMem(Src) shr ReadMem(Shift));
|
---|
319 | end;
|
---|
320 |
|
---|
321 | procedure TCpu.InstructionBitSet;
|
---|
322 | var
|
---|
323 | Dst, Src, Bit: TInt;
|
---|
324 | begin
|
---|
325 | Dst := ReadMemPc;
|
---|
326 | Src := ReadMemPc;
|
---|
327 | Bit := ReadMemPc;
|
---|
328 | WriteMem(Dst, ReadMem(Src) or (1 << ReadMem(Bit)));
|
---|
329 | end;
|
---|
330 |
|
---|
331 | procedure TCpu.InstructionBitReset;
|
---|
332 | var
|
---|
333 | Dst, Src, Bit: TInt;
|
---|
334 | begin
|
---|
335 | Dst := ReadMemPc;
|
---|
336 | Src := ReadMemPc;
|
---|
337 | Bit := ReadMemPc;
|
---|
338 | WriteMem(Dst, ReadMem(Src) and (-1 xor (1 << ReadMem(Bit))));
|
---|
339 | end;
|
---|
340 |
|
---|
341 | procedure TCpu.InstructionBitTest;
|
---|
342 | var
|
---|
343 | Dst, Src, Bit: TInt;
|
---|
344 | begin
|
---|
345 | Dst := ReadMemPc;
|
---|
346 | Src := ReadMemPc;
|
---|
347 | Bit := ReadMemPc;
|
---|
348 | WriteMem(Dst, (ReadMem(Src) >> ReadMem(Bit)) and 1);
|
---|
349 | end;
|
---|
350 |
|
---|
351 | procedure TCpu.InstructionGetMaxInt;
|
---|
352 | var
|
---|
353 | Dst: TInt;
|
---|
354 | begin
|
---|
355 | Dst := ReadMemPc;
|
---|
356 | WriteMem(Dst, SizeOf(TInt) * 8);
|
---|
357 | end;
|
---|
358 |
|
---|
359 | procedure TCpu.InstructionGetMinInt;
|
---|
360 | var
|
---|
361 | Dst: TInt;
|
---|
362 | begin
|
---|
363 | Dst := ReadMemPc;
|
---|
364 | // WriteMem(Dst, SizeOf(TInt) * 8);
|
---|
365 | end;
|
---|
366 |
|
---|
367 | procedure TCpu.WriteMem(Address, Data: TInt);
|
---|
368 | begin
|
---|
369 | if Assigned(FOnWriteMem) then FOnWriteMem(Address, Data);
|
---|
370 | end;
|
---|
371 |
|
---|
372 | function TCpu.ReadMem(Address: TInt): TInt;
|
---|
373 | begin
|
---|
374 | if Assigned(FOnReadMem) then Result := FOnReadMem(Address)
|
---|
375 | else Result := 0;
|
---|
376 | end;
|
---|
377 |
|
---|
378 | function TCpu.ReadMemPc: TInt;
|
---|
379 | begin
|
---|
380 | Result := ReadMem(PC);
|
---|
381 | Inc(PC);
|
---|
382 | end;
|
---|
383 |
|
---|
384 | procedure TCpu.WriteIo(Address, Data: TInt);
|
---|
385 | begin
|
---|
386 | if Assigned(FOnWriteIo) then FOnWriteIo(Address, Data);
|
---|
387 | end;
|
---|
388 |
|
---|
389 | function TCpu.ReadIo(Address: TInt): TInt;
|
---|
390 | begin
|
---|
391 | if Assigned(FOnReadIo) then Result := FOnReadIo(Address)
|
---|
392 | else Result := 0;
|
---|
393 | end;
|
---|
394 |
|
---|
395 | procedure TCpu.Push(Data: TInt);
|
---|
396 | begin
|
---|
397 | Dec(SP);
|
---|
398 | WriteMem(SP, Data);
|
---|
399 | end;
|
---|
400 |
|
---|
401 | function TCpu.Pop: TInt;
|
---|
402 | begin
|
---|
403 | Result := ReadMem(SP);
|
---|
404 | Inc(SP);
|
---|
405 | end;
|
---|
406 |
|
---|
407 | procedure TCpu.Reset;
|
---|
408 | begin
|
---|
409 | PC := 0;
|
---|
410 | SP := 1000;
|
---|
411 | Halted := False;
|
---|
412 | end;
|
---|
413 |
|
---|
414 | procedure TCpu.Run;
|
---|
415 | begin
|
---|
416 | Reset;
|
---|
417 | while not Halted do
|
---|
418 | Step;
|
---|
419 | end;
|
---|
420 |
|
---|
421 | procedure TCpu.Step;
|
---|
422 | var
|
---|
423 | Opcode: TInstruction;
|
---|
424 | begin
|
---|
425 | Opcode := TInstruction(FOnReadMem(PC));
|
---|
426 | Inc(PC);
|
---|
427 | Instructions[Opcode];
|
---|
428 | end;
|
---|
429 |
|
---|
430 | constructor TCpu.Create;
|
---|
431 | begin
|
---|
432 | Instructions[inNop] := InstructionNop;
|
---|
433 | Instructions[inHalt] := InstructionHalt;
|
---|
434 | Instructions[inLoad] := InstructionLoad;
|
---|
435 | Instructions[inLoadIndex] := InstructionLoadIndex;
|
---|
436 | Instructions[inLoadConst] := InstructionLoadConst;
|
---|
437 | Instructions[inLoadMem] := InstructionLoadMem;
|
---|
438 | Instructions[inStoreMem] := InstructionStoreMem;
|
---|
439 | Instructions[inInput] := InstructionInput;
|
---|
440 | Instructions[inOutput] := InstructionOutput;
|
---|
441 | Instructions[inJump] := InstructionJump;
|
---|
442 | Instructions[inJumpZero] := InstructionJumpZero;
|
---|
443 | Instructions[inJumpNotZero] := InstructionJumpNotZero;
|
---|
444 | Instructions[inJumpRel] := InstructionJumpRel;
|
---|
445 | Instructions[inJumpRelZero] := InstructionJumpRelZero;
|
---|
446 | Instructions[inJumpRelNotZero] := InstructionJumpRelNotZero;
|
---|
447 | Instructions[inIncrement] := InstructionInc;
|
---|
448 | Instructions[inDecrement] := InstructionDec;
|
---|
449 | Instructions[inPush] := InstructionPush;
|
---|
450 | Instructions[inPop] := InstructionPop;
|
---|
451 | Instructions[inCall] := InstructionCall;
|
---|
452 | Instructions[inReturn] := InstructionRet;
|
---|
453 | Instructions[inAdd] := InstructionAdd;
|
---|
454 | Instructions[inSubtract] := InstructionSub;
|
---|
455 | Instructions[inAnd] := InstructionAnd;
|
---|
456 | Instructions[inOr] := InstructionOr;
|
---|
457 | Instructions[inXor] := InstructionXor;
|
---|
458 | Instructions[inShiftLeft] := InstructionShl;
|
---|
459 | Instructions[inShiftRight] := InstructionShr;
|
---|
460 | Instructions[inBitSet] := InstructionBitSet;
|
---|
461 | Instructions[inBitReset] := InstructionBitReset;
|
---|
462 | Instructions[inBitTest] := InstructionBitTest;
|
---|
463 | Instructions[inGetMaxInt] := InstructionGetMaxInt;
|
---|
464 | Instructions[inGetMinInt] := InstructionGetMinInt;
|
---|
465 | end;
|
---|
466 |
|
---|
467 | end.
|
---|
468 |
|
---|