source: branches/ByteArray/Cpu.pas

Last change on this file was 11, checked in by chronos, 2 months ago
  • Modified: Updated Common package.
  • Fixed: Wrong return address from CALL instruction.
File size: 18.2 KB
Line 
1unit Cpu;
2
3interface
4
5uses
6 Classes, SysUtils, Int, Channel;
7
8type
9 TInstruction = (inNop, inHalt,
10 inLoadConst, inLoadConstSize,
11 inLoad, inLoadSize,
12 inLoadMem, inLoadMemSize,
13 inStoreMem, inStoreMemSize,
14 inLoadMemIndex, inLoadMemIndexSize,
15 inStoreMemIndex, inStoreMemIndexSize,
16 inInput, inInputSize,
17 inOutput, inOutputSize,
18 inInc, inIncSize, inDec, inDecSize,
19 inAdd, inAddSize, inSub, inSubSize,
20 inShr, inShrSize, inShl, inShlSize,
21 inXor, inXorSize, inAnd, inAndSize, inOr, inOrSize,
22 inJump, inJumpSize,
23 inJumpNotZero, inJumpNotZeroSize,
24 inJumpZero, inJumpZeroSize,
25 inJumpRel, inJumpRelSize,
26 inCall, inCallSize,
27 inRet, inRetSize,
28 inPush, inPushSize,
29 inPop, inPopSize,
30 inSet, inSetSize,
31 inRes, inResSize,
32 inBit, inBitSize,
33 inMul, inMulSize,
34 inDiv, inDivSize,
35 inLdir, inLdi, inLddr, inLdd,
36 inInir, inIni, inIndr, inInd,
37 inOtir, inOti, inOtdr, inOtd,
38 inCpir, inCpi, inCpdr, inCpd,
39 inEx, inEnableInterrupts, inDisableInterrupts,
40 inCompare);
41
42 TRegIndex = Byte;
43
44 TInstructionEvent = procedure of object;
45 TCpuThread = class;
46
47 { TCpu }
48
49 TCpu = class
50 private
51 FHalted: Boolean;
52 FRunning: Boolean;
53 FThread: TCpuThread;
54 FInstructions: array[TInstruction] of TInstructionEvent;
55 FTicks: QWord;
56 procedure Push(Value: TInt; Size: TIntSize);
57 function Pop(Size: TIntSize): TInt;
58 procedure InstructionNop;
59 procedure InstructionHalt;
60 procedure InstructionLoadConst;
61 procedure InstructionLoadConstSize;
62 procedure InstructionLoad;
63 procedure InstructionLoadSize;
64 procedure InstructionLoadMem;
65 procedure InstructionLoadMemSize;
66 procedure InstructionStoreMem;
67 procedure InstructionStoreMemSize;
68 procedure InstructionLoadMemIndex;
69 procedure InstructionLoadMemIndexSize;
70 procedure InstructionStoreMemIndex;
71 procedure InstructionStoreMemIndexSize;
72 procedure InstructionJump;
73 procedure InstructionJumpSize;
74 procedure InstructionJumpNotZero;
75 procedure InstructionJumpNotZeroSize;
76 procedure InstructionJumpZero;
77 procedure InstructionJumpZeroSize;
78 procedure InstructionJumpRel;
79 procedure InstructionJumpRelSize;
80 procedure InstructionCall;
81 procedure InstructionCallSize;
82 procedure InstructionRet;
83 procedure InstructionRetSize;
84 procedure InstructionPush;
85 procedure InstructionPushSize;
86 procedure InstructionPop;
87 procedure InstructionPopSize;
88 procedure InstructionInput;
89 procedure InstructionInputSize;
90 procedure InstructionOutput;
91 procedure InstructionOutputSize;
92 procedure InstructionInc;
93 procedure InstructionIncSize;
94 procedure InstructionDec;
95 procedure InstructionDecSize;
96 procedure InstructionXor;
97 procedure InstructionXorSize;
98 procedure InstructionAnd;
99 procedure InstructionAndSize;
100 procedure InstructionOr;
101 procedure InstructionOrSize;
102 procedure InstructionAdd;
103 procedure InstructionAddSize;
104 procedure InstructionSub;
105 procedure InstructionSubSize;
106 procedure InitInstructions;
107 procedure SetRunning(AValue: Boolean);
108 procedure Run;
109 procedure Step;
110 public
111 Regs: array[TRegIndex] of TInt;
112 PC: TInt;
113 SP: TInt;
114 DataWidth: TIntSize;
115 AddressWidth: TIntSize;
116 Memory: TChannel;
117 IO: TChannel;
118 function Read(Size: TIntSize): TInt;
119 function ReadSize: TIntSize;
120 function ReadRegIndex: TRegIndex;
121 procedure Write(Size: TIntSize; Value: TInt);
122 procedure WriteInstruction(Instruction: TInstruction);
123 procedure WriteRegister(Reg: TRegIndex);
124 procedure Reset;
125 procedure Start;
126 procedure Stop;
127 constructor Create;
128 destructor Destroy; override;
129 property Ticks: QWord read FTicks;
130 property Running: Boolean read FRunning write SetRunning;
131 property Halted: Boolean read FHalted;
132 end;
133
134 { TCpuThread }
135
136 TCpuThread = class(TThread)
137 Cpu: TCpu;
138 procedure Execute; override;
139 end;
140
141
142implementation
143
144{ TCpuThread }
145
146procedure TCpuThread.Execute;
147begin
148 repeat
149 if not Cpu.Halted then Cpu.Step
150 else Sleep(1);
151 //Cpu.CheckInterreupts;
152 until Terminated;
153end;
154
155{ TCpu }
156
157procedure TCpu.Push(Value: TInt; Size: TIntSize);
158begin
159 SP := (SP - Size + Memory.GetSize) mod Memory.GetSize;
160 Memory.Write(SP, Size, Value);
161end;
162
163function TCpu.Pop(Size: TIntSize): TInt;
164begin
165 Result := Memory.Read(SP, Size);
166 SP := (SP + Size) mod Memory.GetSize;
167end;
168
169procedure TCpu.InstructionNop;
170begin
171 // Do nothing
172end;
173
174procedure TCpu.InstructionHalt;
175begin
176 FHalted := True;
177end;
178
179procedure TCpu.InstructionLoadConst;
180var
181 RegIndex: TRegIndex;
182begin
183 RegIndex := ReadRegIndex;
184 Regs[RegIndex] := Read(DataWidth);
185end;
186
187procedure TCpu.InstructionLoadConstSize;
188var
189 RegIndex: TRegIndex;
190 DataSize: TIntSize;
191begin
192 DataSize := ReadSize;
193 RegIndex := ReadRegIndex;
194 Regs[RegIndex] := Read(DataSize);
195end;
196
197procedure TCpu.InstructionLoad;
198var
199 RegIndex: TRegIndex;
200 RegIndex2: TRegIndex;
201begin
202 RegIndex := ReadRegIndex;
203 RegIndex2 := ReadRegIndex;
204 Regs[RegIndex] := Regs[RegIndex2];
205end;
206
207procedure TCpu.InstructionLoadSize;
208var
209 DataSize: TIntSize;
210 RegIndex: TRegIndex;
211 RegIndex2: TRegIndex;
212begin
213 DataSize := ReadSize;
214 RegIndex := ReadRegIndex;
215 RegIndex2 := ReadRegIndex;
216 Regs[RegIndex] := LimitSize(Regs[RegIndex2], DataSize);
217end;
218
219procedure TCpu.InstructionLoadMem;
220var
221 RegIndex1: TRegIndex;
222 RegIndex2: TRegIndex;
223begin
224 RegIndex1 := ReadRegIndex;
225 RegIndex2 := ReadRegIndex;
226 Regs[RegIndex1] := Memory.Read(Regs[RegIndex2], DataWidth);
227end;
228
229procedure TCpu.InstructionLoadMemSize;
230var
231 DataSize: TIntSize;
232 RegIndex1: TRegIndex;
233 RegIndex2: TRegIndex;
234begin
235 DataSize := ReadSize;
236 RegIndex1 := ReadRegIndex;
237 RegIndex2 := ReadRegIndex;
238 Regs[RegIndex1] := Memory.Read(Regs[RegIndex2], DataSize);
239end;
240
241procedure TCpu.InstructionStoreMem;
242var
243 RegIndex1: TRegIndex;
244 RegIndex2: TRegIndex;
245begin
246 RegIndex1 := ReadRegIndex;
247 RegIndex2 := ReadRegIndex;
248 Memory.Write(Regs[RegIndex1], DataWidth, Regs[RegIndex2]);
249end;
250
251procedure TCpu.InstructionStoreMemSize;
252var
253 DataSize: TIntSize;
254 RegIndex1: TRegIndex;
255 RegIndex2: TRegIndex;
256begin
257 DataSize := ReadSize;
258 RegIndex1 := ReadRegIndex;
259 RegIndex2 := ReadRegIndex;
260 Memory.Write(Regs[RegIndex1], DataSize, Regs[RegIndex2]);
261end;
262
263procedure TCpu.InstructionLoadMemIndex;
264var
265 RegIndex1: TRegIndex;
266 RegIndex2: TRegIndex;
267 RelativeAddress: TInt;
268begin
269 RegIndex1 := ReadRegIndex;
270 RegIndex2 := ReadRegIndex;
271 RelativeAddress := Read(AddressWidth);
272 Regs[RegIndex1] := Memory.Read(Regs[RegIndex2] + RelativeAddress, DataWidth);
273end;
274
275procedure TCpu.InstructionLoadMemIndexSize;
276var
277 DataSize: TIntSize;
278 RegIndex1: TRegIndex;
279 RegIndex2: TRegIndex;
280 RelativeAddress: TInt;
281begin
282 DataSize := ReadSize;
283 RegIndex1 := ReadRegIndex;
284 RegIndex2 := ReadRegIndex;
285 RelativeAddress := Read(AddressWidth);
286 Regs[RegIndex1] := Memory.Read(Regs[RegIndex2] + RelativeAddress, DataSize);
287end;
288
289procedure TCpu.InstructionStoreMemIndex;
290var
291 RegIndex1: TRegIndex;
292 RegIndex2: TRegIndex;
293 RelativeAddress: TInt;
294begin
295 RegIndex1 := ReadRegIndex;
296 RegIndex2 := ReadRegIndex;
297 RelativeAddress := Read(AddressWidth);
298 Memory.Write(Regs[RegIndex1] + RelativeAddress, DataWidth, Regs[RegIndex2]);
299end;
300
301procedure TCpu.InstructionStoreMemIndexSize;
302var
303 DataSize: TIntSize;
304 RegIndex1: TRegIndex;
305 RegIndex2: TRegIndex;
306 RelativeAddress: TInt;
307begin
308 DataSize := ReadSize;
309 RegIndex1 := ReadRegIndex;
310 RegIndex2 := ReadRegIndex;
311 RelativeAddress := Read(AddressWidth);
312 Memory.Write(Regs[RegIndex1] + RelativeAddress, DataSize, Regs[RegIndex2]);
313end;
314
315procedure TCpu.InstructionJump;
316begin
317 PC := Read(AddressWidth);
318end;
319
320procedure TCpu.InstructionJumpSize;
321var
322 AddressSize: TIntSize;
323begin
324 AddressSize := Read(SizeOf(TIntSize));
325 PC := Read(AddressSize);
326end;
327
328procedure TCpu.InstructionJumpNotZero;
329var
330 RegIndex: TRegIndex;
331 Address: TInt;
332begin
333 RegIndex := ReadRegIndex;
334 Address := Read(AddressWidth);
335 if Regs[RegIndex] <> 0 then
336 PC := Address;
337end;
338
339procedure TCpu.InstructionJumpNotZeroSize;
340var
341 RegIndex: TRegIndex;
342 Address: TInt;
343 DataSize: TIntSize;
344 AddressSize: TIntSize;
345begin
346 DataSize := ReadSize;
347 AddressSize := Read(SizeOf(TIntSize));
348 RegIndex := ReadRegIndex;
349 Address := Read(AddressSize);
350 if LimitSize(Regs[RegIndex], DataSize) <> 0 then
351 PC := Address;
352end;
353
354procedure TCpu.InstructionJumpZero;
355var
356 RegIndex: TRegIndex;
357 Address: TInt;
358begin
359 RegIndex := ReadRegIndex;
360 Address := Read(AddressWidth);
361 if Regs[RegIndex] = 0 then
362 PC := Address;
363end;
364
365procedure TCpu.InstructionJumpZeroSize;
366var
367 RegIndex: TRegIndex;
368 Address: TInt;
369 DataSize: TIntSize;
370 AddressSize: TIntSize;
371begin
372 DataSize := ReadSize;
373 AddressSize := Read(SizeOf(TIntSize));
374 RegIndex := ReadRegIndex;
375 Address := Read(AddressSize);
376 if LimitSize(Regs[RegIndex], DataSize) = 0 then
377 PC := Address;
378end;
379
380procedure TCpu.InstructionJumpRel;
381begin
382 PC := PC + Read(AddressWidth);
383end;
384
385procedure TCpu.InstructionJumpRelSize;
386var
387 AddressSize: TIntSize;
388begin
389 AddressSize := ReadSize;
390 PC := PC + Read(AddressSize);
391end;
392
393procedure TCpu.InstructionCall;
394var
395 NewAddress: TInt;
396begin
397 NewAddress := Read(AddressWidth);
398 Push(PC, AddressWidth);
399 PC := NewAddress;
400end;
401
402procedure TCpu.InstructionCallSize;
403var
404 AddressSize: TIntSize;
405begin
406 AddressSize := ReadSize;
407 Push(PC, AddressSize);
408 PC := Read(AddressSize);
409end;
410
411procedure TCpu.InstructionRet;
412begin
413 PC := Pop(AddressWidth);
414end;
415
416procedure TCpu.InstructionRetSize;
417var
418 AddressSize: TIntSize;
419begin
420 AddressSize := ReadSize;
421 PC := Pop(AddressSize);
422end;
423
424procedure TCpu.InstructionPush;
425var
426 RegIndex: TRegIndex;
427begin
428 RegIndex := ReadRegIndex;
429 Push(Regs[RegIndex], DataWidth);
430end;
431
432procedure TCpu.InstructionPushSize;
433var
434 DataSize: TIntSize;
435 RegIndex: TRegIndex;
436begin
437 DataSize := ReadSize;
438 RegIndex := ReadRegIndex;
439 Push(Regs[RegIndex], DataSize);
440end;
441
442procedure TCpu.InstructionPop;
443var
444 RegIndex: TRegIndex;
445begin
446 RegIndex := ReadRegIndex;
447 Regs[RegIndex] := Pop(DataWidth);
448end;
449
450procedure TCpu.InstructionPopSize;
451var
452 DataSize: TIntSize;
453 RegIndex: TRegIndex;
454begin
455 DataSize := ReadSize;
456 RegIndex := ReadRegIndex;
457 Regs[RegIndex] := Pop(DataSize);
458end;
459
460procedure TCpu.InstructionInput;
461var
462 RegIndex: TRegIndex;
463 RegIndex2: TRegIndex;
464begin
465 RegIndex := ReadRegIndex;
466 RegIndex2 := ReadRegIndex;
467 Regs[RegIndex] := IO.Read(Regs[RegIndex2], DataWidth);
468end;
469
470procedure TCpu.InstructionInputSize;
471var
472 RegIndex: TRegIndex;
473 RegIndex2: TRegIndex;
474 DataSize: TIntSize;
475begin
476 DataSize := ReadSize;
477 RegIndex := ReadRegIndex;
478 RegIndex2 := ReadRegIndex;
479 Regs[RegIndex] := IO.Read(Regs[RegIndex2], DataSize);
480end;
481
482procedure TCpu.InstructionOutput;
483var
484 RegIndex: TRegIndex;
485 RegIndex2: TRegIndex;
486begin
487 RegIndex := ReadRegIndex;
488 RegIndex2 := ReadRegIndex;
489 IO.Write(Regs[RegIndex], DataWidth, Regs[RegIndex2]);
490end;
491
492procedure TCpu.InstructionOutputSize;
493var
494 RegIndex: TRegIndex;
495 RegIndex2: TRegIndex;
496 DataSize: TIntSize;
497begin
498 DataSize := ReadSize;
499 RegIndex := ReadRegIndex;
500 RegIndex2 := ReadRegIndex;
501 IO.Write(Regs[RegIndex], DataSize, Regs[RegIndex2]);
502end;
503
504procedure TCpu.InstructionInc;
505var
506 RegIndex: TRegIndex;
507begin
508 RegIndex := ReadRegIndex;
509 Regs[RegIndex] := Regs[RegIndex] + 1;
510end;
511
512procedure TCpu.InstructionIncSize;
513var
514 RegIndex: TRegIndex;
515 DataSize: TIntSize;
516begin
517 DataSize := ReadSize;
518 RegIndex := ReadRegIndex;
519 Regs[RegIndex] := LimitSize(Regs[RegIndex], DataSize) + 1;
520end;
521
522procedure TCpu.InstructionDec;
523var
524 RegIndex: TRegIndex;
525begin
526 RegIndex := ReadRegIndex;
527 Regs[RegIndex] := Regs[RegIndex] - 1;
528end;
529
530procedure TCpu.InstructionDecSize;
531var
532 RegIndex: TRegIndex;
533 DataSize: TIntSize;
534begin
535 DataSize := ReadSize;
536 RegIndex := ReadRegIndex;
537 Regs[RegIndex] := LimitSize(Regs[RegIndex], DataSize) - 1;
538end;
539
540procedure TCpu.InstructionXor;
541var
542 RegIndex: TRegIndex;
543 RegIndex2: TRegIndex;
544begin
545 RegIndex := ReadRegIndex;
546 RegIndex2 := ReadRegIndex;
547 Regs[RegIndex] := Regs[RegIndex] xor Regs[RegIndex2];
548end;
549
550procedure TCpu.InstructionXorSize;
551var
552 DataSize: TIntSize;
553 RegIndex: TRegIndex;
554 RegIndex2: TRegIndex;
555begin
556 DataSize := ReadSize;
557 RegIndex := ReadRegIndex;
558 RegIndex2 := ReadRegIndex;
559 Regs[RegIndex] := LimitSize(Regs[RegIndex] xor Regs[RegIndex2], DataSize);
560end;
561
562procedure TCpu.InstructionAnd;
563var
564 RegIndex: TRegIndex;
565 RegIndex2: TRegIndex;
566begin
567 RegIndex := ReadRegIndex;
568 RegIndex2 := ReadRegIndex;
569 Regs[RegIndex] := Regs[RegIndex] and Regs[RegIndex2];
570end;
571
572procedure TCpu.InstructionAndSize;
573var
574 DataSize: TIntSize;
575 RegIndex: TRegIndex;
576 RegIndex2: TRegIndex;
577begin
578 DataSize := ReadSize;
579 RegIndex := ReadRegIndex;
580 RegIndex2 := ReadRegIndex;
581 Regs[RegIndex] := LimitSize(Regs[RegIndex] and Regs[RegIndex2], DataSize);
582end;
583
584procedure TCpu.InstructionOr;
585var
586 RegIndex: TRegIndex;
587 RegIndex2: TRegIndex;
588begin
589 RegIndex := ReadRegIndex;
590 RegIndex2 := ReadRegIndex;
591 Regs[RegIndex] := Regs[RegIndex] or Regs[RegIndex2];
592end;
593
594procedure TCpu.InstructionOrSize;
595var
596 DataSize: TIntSize;
597 RegIndex: TRegIndex;
598 RegIndex2: TRegIndex;
599begin
600 DataSize := ReadSize;
601 RegIndex := ReadRegIndex;
602 RegIndex2 := ReadRegIndex;
603 Regs[RegIndex] := LimitSize(Regs[RegIndex] or Regs[RegIndex2], DataSize);
604end;
605
606procedure TCpu.InstructionAdd;
607var
608 RegIndex: TRegIndex;
609 RegIndex2: TRegIndex;
610begin
611 RegIndex := ReadRegIndex;
612 RegIndex2 := ReadRegIndex;
613 Regs[RegIndex] := Regs[RegIndex] + Regs[RegIndex2];
614end;
615
616procedure TCpu.InstructionAddSize;
617var
618 DataSize: TIntSize;
619 RegIndex: TRegIndex;
620 RegIndex2: TRegIndex;
621begin
622 DataSize := ReadSize;
623 RegIndex := ReadRegIndex;
624 RegIndex2 := ReadRegIndex;
625 Regs[RegIndex] := LimitSize(Regs[RegIndex] + Regs[RegIndex2], DataSize);
626end;
627
628procedure TCpu.InstructionSub;
629var
630 RegIndex: TRegIndex;
631 RegIndex2: TRegIndex;
632begin
633 RegIndex := ReadRegIndex;
634 RegIndex2 := ReadRegIndex;
635 Regs[RegIndex] := Regs[RegIndex] - Regs[RegIndex2];
636end;
637
638procedure TCpu.InstructionSubSize;
639var
640 DataSize: TIntSize;
641 RegIndex: TRegIndex;
642 RegIndex2: TRegIndex;
643begin
644 DataSize := ReadSize;
645 RegIndex := ReadRegIndex;
646 RegIndex2 := ReadRegIndex;
647 Regs[RegIndex] := LimitSize(Regs[RegIndex] + Regs[RegIndex2], DataSize);
648end;
649
650procedure TCpu.InitInstructions;
651begin
652 FInstructions[inNop] := InstructionNop;
653 FInstructions[inHalt] := InstructionHalt;
654 FInstructions[inLoadConst] := InstructionLoadConst;
655 FInstructions[inLoadConstSize] := InstructionLoadConstSize;
656 FInstructions[inLoad] := InstructionLoad;
657 FInstructions[inLoadSize] := InstructionLoadSize;
658 FInstructions[inLoadMem] := InstructionLoadMem;
659 FInstructions[inLoadMemSize] := InstructionLoadMemSize;
660 FInstructions[inStoreMem] := InstructionStoreMem;
661 FInstructions[inStoreMemSize] := InstructionStoreMemSize;
662 FInstructions[inLoadMemIndex] := InstructionLoadMemIndex;
663 FInstructions[inLoadMemIndexSize] := InstructionLoadMemIndexSize;
664 FInstructions[inStoreMemIndex] := InstructionStoreMemIndex;
665 FInstructions[inStoreMemIndexSize] := InstructionStoreMemIndexSize;
666 FInstructions[inJump] := InstructionJump;
667 FInstructions[inJumpSize] := InstructionJumpSize;
668 FInstructions[inJumpNotZero] := InstructionJumpNotZero;
669 FInstructions[inJumpNotZeroSize] := InstructionJumpNotZeroSize;
670 FInstructions[inJumpZero] := InstructionJumpZero;
671 FInstructions[inJumpZeroSize] := InstructionJumpZeroSize;
672 FInstructions[inJumpRel] := InstructionJumpRel;
673 FInstructions[inJumpRelSize] := InstructionJumpRelSize;
674 FInstructions[inCall] := InstructionCall;
675 FInstructions[inCallSize] := InstructionCallSize;
676 FInstructions[inRet] := InstructionRet;
677 FInstructions[inRetSize] := InstructionRetSize;
678 FInstructions[inPush] := InstructionPush;
679 FInstructions[inPushSize] := InstructionPushSize;
680 FInstructions[inPop] := InstructionPop;
681 FInstructions[inPopSize] := InstructionPopSize;
682 FInstructions[inInput] := InstructionInput;
683 FInstructions[inInputSize] := InstructionInputSize;
684 FInstructions[inOutput] := InstructionOutput;
685 FInstructions[inOutputSize] := InstructionOutputSize;
686 FInstructions[inInc] := InstructionInc;
687 FInstructions[inIncSize] := InstructionIncSize;
688 FInstructions[inDec] := InstructionDec;
689 FInstructions[inDecSize] := InstructionDecSize;
690 FInstructions[inXor] := InstructionXor;
691 FInstructions[inXorSize] := InstructionXorSize;
692 FInstructions[inAnd] := InstructionAnd;
693 FInstructions[inAndSize] := InstructionAndSize;
694 FInstructions[inOr] := InstructionOr;
695 FInstructions[inOrSize] := InstructionOrSize;
696 FInstructions[inAdd] := InstructionAdd;
697 FInstructions[inAddSize] := InstructionAddSize;
698 FInstructions[inSub] := InstructionSub;
699 FInstructions[inSubSize] := InstructionSubSize;
700end;
701
702procedure TCpu.SetRunning(AValue: Boolean);
703begin
704 if FRunning = AValue then Exit;
705 if AValue then Start
706 else Stop;
707end;
708
709function TCpu.Read(Size: TIntSize): TInt;
710begin
711 Result := Memory.Read(PC, Size);
712 PC := PC + Size;
713end;
714
715function TCpu.ReadSize: TIntSize;
716begin
717 Result := Read(SizeOf(TIntSize));
718end;
719
720function TCpu.ReadRegIndex: TRegIndex;
721begin
722 Result := TRegIndex(Byte(Read(1)));
723end;
724
725procedure TCpu.Write(Size: TIntSize; Value: TInt);
726begin
727 Memory.Write(PC, Size, Value);
728 PC := PC + Size;
729end;
730
731procedure TCpu.WriteInstruction(Instruction: TInstruction);
732begin
733 Write(1, Byte(Instruction));
734end;
735
736procedure TCpu.WriteRegister(Reg: TRegIndex);
737begin
738 Write(1, Byte(Reg));
739end;
740
741procedure TCpu.Reset;
742var
743 I: TRegIndex;
744begin
745 DataWidth := 2;
746 AddressWidth := 2;
747 for I := Low(TRegIndex) to High(TRegIndex) do
748 Regs[I] := 0;
749 PC := 0;
750 SP := 0;
751 FHalted := False;
752 FTicks := 0;
753end;
754
755procedure TCpu.Run;
756begin
757 Reset;
758 while not FHalted do
759 Step;
760end;
761
762procedure TCpu.Step;
763var
764 Instruction: TInstruction;
765begin
766 Instruction := TInstruction(Byte(Read(1)));
767 FInstructions[Instruction];
768 Inc(FTicks);
769end;
770
771procedure TCpu.Start;
772begin
773 if not Running then begin
774 Reset;
775 FThread := TCpuThread.Create(True);
776 FThread.Cpu := Self;
777 FThread.Start;
778 FRunning := True;
779 end;
780end;
781
782procedure TCpu.Stop;
783begin
784 if Running then begin
785 FHalted := True;
786 FThread.Terminate;
787 FThread.WaitFor;
788 FreeAndNil(FThread);
789 FRunning := False;
790 end;
791end;
792
793constructor TCpu.Create;
794begin
795 Memory := TChannel.Create;
796 IO := TChannel.Create;
797 InitInstructions;
798 Reset;
799end;
800
801destructor TCpu.Destroy;
802begin
803 Stop;
804 FreeAndNil(Memory);
805 FreeAndNil(IO);
806 inherited;
807end;
808
809end.
810
Note: See TracBrowser for help on using the repository browser.