source: branches/virtualcpu3/UMachine.pas

Last change on this file was 160, checked in by chronos, 6 years ago
  • Added: Unfinished unit for Int128 type.
File size: 19.3 KB
Line 
1unit UMachine;
2
3
4{$DEFINE EXT_IO}
5{$DEFINE EXT_ADDRESSING_MODES}
6{$DEFINE EXT_ARITHMETIC}
7{$DEFINE EXT_LOGICAL}
8{$DEFINE EXT_STACK}
9{$DEFINE EXT_SUBROUTINE}
10{$DEFINE EXT_SHIFT}
11{$DEFINE EXT_BLOCK}
12{$DEFINE EXT_GENERAL}
13{$DEFINE EXT_BIT}
14//{$DEFINE EXT_LOWER_WIDTH}
15
16// Extension dependencies
17{$IFDEF EXT_SUBROUTINE}
18{$DEFINE EXT_STACK}
19{$ENDIF}
20
21{$mode objfpc}{$H+}
22
23interface
24
25uses
26 Classes, SysUtils;
27
28type
29 TOpcode = (opNop, opHalt, opLD, opLDC, opLDM, opSTM, opInc, opDec, opJP, opJr,
30 opPush, opPop, opCall, opRet, opAdd, opSub, opMul, opDiv, opShr, opShl,
31 opIn, opOut, opXchg, opXor, opOr, opAnd, opJpc, opJrc,
32 opTstZ, opTstNZ, opTstC, opTstNC, opLDMD, opSTMD, opLdir, opLddr,
33 opBitSet, opBitRes, opBitGet, opBitPut,
34 opPrefix8, opPrefix16, opPrefix32, opPrefix64, opPrefix128);
35
36 TOpcodeHandler = procedure of object;
37
38 TDataWidth = (dwNative, dw8, dw16, dw32, dw64, dw128);
39
40 // Goals: Simple to implement, fast execution
41 // Address and data have same bit width
42 // Memory access with lower bit width?
43 // Related instructions grouped as extensions
44
45 { TCPU }
46
47 generic TCPU<T> = class
48 type
49 TOutputEvent = procedure (Port: T; Value: T) of object;
50 TInputEvent = function (Port: T): T of object;
51 PT = ^T;
52 TOpcodeIndex = Byte;
53 POpcodeIndex = ^TOpcodeIndex;
54 TRegIndex = Byte;
55 PRegIndex = ^TRegIndex;
56 var
57 Terminated: Boolean;
58 OpcodeHandlers: array[TOpcode] of TOpcodeHandler;
59 function ReadNext: T;
60 {$IFDEF EXT_LOWER_WIDTH}
61 function ReadNext8: ShortInt;
62 function ReadNext16: SmallInt;
63 function ReadNext32: Integer;
64 function ReadNext64: Int64;
65 {$ENDIF}
66 function ReadOpcode: TOpcodeIndex;
67 function ReadReg: TRegIndex;
68 procedure Step;
69 procedure AddOpcode(Opcode: TOpcode; Handler: TOpcodeHandler);
70 procedure InitOpcodes;
71 private
72 FOnInput: TInputEvent;
73 FOnOutput: TOutputEvent;
74 Condition: Boolean;
75 procedure OpcodeNoOperation;
76 procedure OpcodeHalt;
77 procedure OpcodeIncrement;
78 procedure OpcodeDecrement;
79 procedure OpcodeJump;
80 procedure OpcodeJumpConditional;
81 procedure OpcodeJumpRelative;
82 procedure OpcodeJumpRelativeConditional;
83 procedure OpcodeLoad;
84 procedure OpcodeLoadConst;
85 procedure OpcodeLoadMemory;
86 procedure OpcodeStoreMemory;
87 procedure OpcodeTestNotZero;
88 procedure OpcodeTestZero;
89 procedure OpcodeTestNotCarry;
90 procedure OpcodeTestCarry;
91 {$IFDEF EXT_LOWER_WIDTH}
92 procedure OpcodePrefix8;
93 procedure OpcodePrefix16;
94 procedure OpcodePrefix32;
95 procedure OpcodePrefix64;
96 {$ENDIF}
97 {$IFDEF EXT_GENERAL}
98 procedure OpcodeExchange;
99 {$ENDIF}
100 {$IFDEF EXT_IO}
101 procedure OpcodeInput;
102 procedure OpcodeOutput;
103 {$ENDIF}
104 {$IFDEF EXT_ADDRESSING_MODES}
105 procedure OpcodeLoadMemoryDisplacement;
106 procedure OpcodeStoreMemoryDisplacement;
107 {$ENDIF}
108 {$IFDEF EXT_ARITHMETIC}
109 procedure OpcodeAddition;
110 procedure OpcodeSubtraction;
111 procedure OpcodeDivision;
112 procedure OpcodeMultiplication;
113 {$ENDIF}
114 {$IFDEF EXT_LOGICAL}
115 procedure OpcodeAnd;
116 procedure OpcodeOr;
117 procedure OpcodeXor;
118 {$ENDIF}
119 {$IFDEF EXT_STACK}
120 procedure OpcodePop;
121 procedure OpcodePush;
122 {$ENDIF}
123 {$IFDEF EXT_SUBROUTINE}
124 procedure OpcodeCall;
125 procedure OpcodeReturn;
126 {$ENDIF}
127 {$IFDEF EXT_SHIFT}
128 procedure OpcodeShiftLeft;
129 procedure OpcodeShiftRight;
130 {$ENDIF}
131 {$IFDEF EXT_BLOCK}
132 procedure OpcodeLdir;
133 procedure OpcodeLddr;
134 {$ENDIF}
135 {$IFDEF EXT_BIT}
136 procedure OpcodeBitSet;
137 procedure OpcodeBitReset;
138 procedure OpcodeBitGet;
139 procedure OpcodeBitPut;
140 {$ENDIF}
141 public
142 Registers: array of T;
143 Memory: array of Byte;
144 IP: T;
145 DataWidth: TDataWidth;
146 {$IFDEF EXT_STACK}
147 SP: T;
148 {$ENDIF}
149 procedure Run;
150 constructor Create;
151 property OnInput: TInputEvent read FOnInput write FOnInput;
152 property OnOutput: TOutputEvent read FOnOutput write FOnOutput;
153 end;
154
155 { TInstructionWriter }
156
157 generic TInstructionWriter<T> = class
158 type
159 PT = ^T;
160 TOpcodeIndex = Byte;
161 POpcodeIndex = ^TOpcodeIndex;
162 TRegIndex = Byte;
163 PRegIndex = ^TRegIndex;
164 var
165 Addr: Integer;
166 Machine: specialize TCPU<T>;
167 procedure AddLoadConst(Reg: TRegIndex; Value: T);
168 {$IFDEF EXT_LOWER_WIDTH}
169 procedure AddLoadConst8(Reg: TRegIndex; Value: ShortInt);
170 procedure AddLoadConst16(Reg: TRegIndex; Value: SmallInt);
171 procedure AddLoadConst32(Reg: TRegIndex; Value: Integer);
172 procedure AddLoadConst64(Reg: TRegIndex; Value: Int64);
173 {$ENDIF}
174 procedure AddNop;
175 procedure AddHalt;
176 procedure AddReg(Reg: TRegIndex);
177 procedure AddOpcode(Opcode: TOpcode);
178 procedure AddData(Value: T);
179 {$IFDEF EXT_LOWER_WIDTH}
180 procedure AddData8(Value: ShortInt);
181 procedure AddData16(Value: SmallInt);
182 procedure AddData32(Value: Integer);
183 procedure AddData64(Value: Int64);
184 {$ENDIF}
185 end;
186
187
188implementation
189
190{ TInstructionWriter }
191
192procedure TInstructionWriter.AddLoadConst(Reg: TRegIndex; Value: T);
193begin
194 AddOpcode(opLDC);
195 AddReg(Reg);
196 AddData(Value);
197end;
198
199{$IFDEF EXT_LOWER_WIDTH}
200procedure TInstructionWriter.AddLoadConst8(Reg: TRegIndex; Value: ShortInt);
201begin
202 AddOpcode(opPrefix8);
203 AddOpcode(opLDC);
204 AddData8(Reg);
205 AddData8(Value);
206end;
207
208procedure TInstructionWriter.AddLoadConst16(Reg: TRegIndex; Value: SmallInt);
209begin
210 AddOpcode(opPrefix16);
211 AddOpcode(opLDC);
212 AddReg(Reg);
213 AddData16(Value);
214end;
215
216procedure TInstructionWriter.AddLoadConst32(Reg: TRegIndex; Value: Integer);
217begin
218 AddOpcode(opPrefix32);
219 AddOpcode(opLDC);
220 AddReg(Reg);
221 AddData32(Value);
222end;
223
224procedure TInstructionWriter.AddLoadConst64(Reg: TRegIndex; Value: Int64);
225begin
226 AddOpcode(opPrefix64);
227 AddOpcode(opLDC);
228 AddReg(Reg);
229 AddData64(Value);
230end;
231{$ENDIF}
232
233procedure TInstructionWriter.AddNop;
234begin
235 AddOpcode(opNop);
236end;
237
238procedure TInstructionWriter.AddHalt;
239begin
240 AddOpcode(opHalt);
241end;
242
243procedure TInstructionWriter.AddReg(Reg: TRegIndex);
244begin
245 PRegIndex(@(Machine.Memory[Addr]))^ := Reg;
246 Inc(Addr, SizeOf(TRegIndex));
247end;
248
249procedure TInstructionWriter.AddOpcode(Opcode: TOpcode);
250begin
251 POpcodeIndex(@(Machine.Memory[Addr]))^ := TOpcodeIndex(Opcode);
252 Inc(Addr, SizeOf(TOpcodeIndex));
253end;
254
255procedure TInstructionWriter.AddData(Value: T);
256begin
257 PT(@(Machine.Memory[Addr]))^ := Value;
258 Inc(Addr, SizeOf(T));
259end;
260
261{$IFDEF EXT_LOWER_WIDTH}
262procedure TInstructionWriter.AddData8(Value: ShortInt);
263begin
264 PShortInt(@(Machine.Memory[Addr]))^ := Value;
265 Inc(Addr, SizeOf(ShortInt));
266end;
267
268procedure TInstructionWriter.AddData16(Value: SmallInt);
269begin
270 PSmallInt(@(Machine.Memory[Addr]))^ := Value;
271 Inc(Addr, SizeOf(SmallInt));
272end;
273
274procedure TInstructionWriter.AddData32(Value: Integer);
275begin
276 PInteger(@(Machine.Memory[Addr]))^ := Value;
277 Inc(Addr, SizeOf(Integer));
278end;
279
280procedure TInstructionWriter.AddData64(Value: Int64);
281begin
282 PInt64(@(Machine.Memory[Addr]))^ := Value;
283 Inc(Addr, SizeOf(Int64));
284end;
285{$ENDIF}
286
287{ TCPU }
288
289function TCPU.ReadNext: T;
290begin
291 Result := PT(@Memory[IP])^;
292 Inc(IP, SizeOf(T));
293end;
294
295{$IFDEF EXT_LOWER_WIDTH}
296function TCPU.ReadNext8: ShortInt;
297begin
298 Result := PShortInt(@Memory[IP])^;
299 Inc(IP, SizeOf(ShortInt));
300end;
301
302function TCPU.ReadNext16: SmallInt;
303begin
304 Result := PSmallInt(@Memory[IP])^;
305 Inc(IP, SizeOf(SmallInt));
306end;
307
308function TCPU.ReadNext32: Integer;
309begin
310 Result := PInteger(@Memory[IP])^;
311 Inc(IP, SizeOf(Integer));
312end;
313
314function TCPU.ReadNext64: Int64;
315begin
316 Result := PInt64(@Memory[IP])^;
317 Inc(IP, SizeOf(Int64));
318end;
319{$ENDIF}
320
321function TCPU.ReadOpcode: TOpcodeIndex;
322begin
323 Result := POpcodeIndex(@Memory[IP])^;
324 Inc(IP, SizeOf(TOpcodeIndex));
325end;
326
327function TCPU.ReadReg: TRegIndex;
328begin
329 Result := PRegIndex(@Memory[IP])^;
330 Inc(IP, SizeOf(TRegIndex));
331end;
332
333procedure TCPU.Run;
334begin
335 IP := 0;
336 {$IFDEF EXT_STACK}
337 SP := Length(Memory);
338 {$ENDIF}
339 {$IFDEF EXT_LOWER_WIDTH}
340 DataWidth := dwNative;
341 {$ENDIF}
342 Terminated := False;
343 while not Terminated do
344 Step;
345end;
346
347constructor TCPU.Create;
348begin
349 SetLength(Registers, 32);
350 SetLength(Memory, 100);
351 InitOpcodes;
352end;
353
354procedure TCPU.OpcodeNoOperation;
355begin
356end;
357
358procedure TCPU.OpcodeHalt;
359begin
360 Terminated := True;
361end;
362
363procedure TCPU.OpcodeLoad;
364var
365 Src, Dest: TRegIndex;
366begin
367 Dest := ReadReg;
368 Src := ReadReg;
369 Registers[Dest] := Registers[Src];
370end;
371
372procedure TCPU.OpcodeLoadConst;
373var
374 Reg: TRegIndex;
375begin
376 Reg := ReadReg;
377 {$IFDEF EXT_LOWER_WIDTH}
378 case DataWidth of
379 dwNative: Registers[Reg] := ReadNext;
380 dw8: Registers[Reg] := ReadNext8;
381 dw16: Registers[Reg] := ReadNext16;
382 dw32: Registers[Reg] := ReadNext32;
383 dw64: Registers[Reg] := ReadNext64;
384 end;
385 {$ELSE}
386 Registers[Reg] := ReadNext;
387 {$ENDIF}
388end;
389
390procedure TCPU.OpcodeLoadMemory;
391var
392 Src, Dest: TRegIndex;
393begin
394 Dest := ReadReg;
395 Src := ReadReg;
396 {$IFDEF EXT_LOWER_WIDTH}
397 case DataWidth of
398 dwNative: Registers[Dest] := PT(@Memory[Registers[Src]])^;
399 dw8: Registers[Dest] := PShortInt(@Memory[Registers[Src]])^;
400 dw16: Registers[Dest] := PSmallInt(@Memory[Registers[Src]])^;
401 dw32: Registers[Dest] := PInteger(@Memory[Registers[Src]])^;
402 dw64: Registers[Dest] := PInt64(@Memory[Registers[Src]])^;
403 end;
404 {$ELSE}
405 Registers[Dest] := PT(@Memory[Registers[Src]])^;
406 {$ENDIF}
407end;
408
409procedure TCPU.OpcodeStoreMemory;
410var
411 Src, Dest: TRegIndex;
412begin
413 Dest := ReadReg;
414 Src := ReadReg;
415 {$IFDEF EXT_LOWER_WIDTH}
416 case DataWidth of
417 dwNative: PT(@Memory[Registers[Dest]])^ := Registers[Src];
418 dw8: PShortInt(@Memory[Registers[Dest]])^ := Registers[Src];
419 dw16: PSmallInt(@Memory[Registers[Dest]])^ := Registers[Src];
420 dw32: PInteger(@Memory[Registers[Dest]])^ := Registers[Src];
421 dw64: PInt64(@Memory[Registers[Dest]])^ := Registers[Src];
422 end;
423 {$ELSE}
424 PT(@Memory[Registers[Dest]])^ := Registers[Src];
425 {$ENDIF}
426end;
427
428{$IFDEF EXT_ADDRESSING_MODES}
429procedure TCPU.OpcodeLoadMemoryDisplacement;
430var
431 Disp, Src, Dest: TRegIndex;
432begin
433 Dest := ReadReg;
434 Src := ReadReg;
435 Disp := ReadReg;
436 Registers[Dest] := PT(@Memory[Registers[Src] + Registers[Disp]])^;
437end;
438
439procedure TCPU.OpcodeStoreMemoryDisplacement;
440var
441 Disp, Src, Dest: TRegIndex;
442begin
443 Dest := ReadReg;
444 Disp := ReadReg;
445 Src := ReadReg;
446 PT(@Memory[Registers[Dest] + Registers[Disp]])^ := Registers[Src];
447end;
448{$ENDIF}
449
450procedure TCPU.OpcodeIncrement;
451var
452 Reg: TRegIndex;
453begin
454 Reg := ReadReg;
455 Registers[Reg] := Registers[Reg] + 1;
456end;
457
458procedure TCPU.OpcodeDecrement;
459var
460 Reg: TRegIndex;
461begin
462 Reg := ReadReg;
463 Registers[Reg] := Registers[Reg] - 1;
464end;
465
466{$IFDEF EXT_ARITHMETIC}
467procedure TCPU.OpcodeAddition;
468var
469 Dest, Src: TRegIndex;
470begin
471 Dest := ReadReg;
472 Src := ReadReg;
473 Registers[Dest] := Registers[Dest] + Registers[Src];
474end;
475
476procedure TCPU.OpcodeSubtraction;
477var
478 Dest, Src: TRegIndex;
479begin
480 Dest := ReadReg;
481 Src := ReadReg;
482 Registers[Dest] := Registers[Dest] - Registers[Src];
483end;
484
485procedure TCPU.OpcodeMultiplication;
486var
487 Dest, Src: TRegIndex;
488begin
489 Dest := ReadReg;
490 Src := ReadReg;
491 Registers[Dest] := Registers[Dest] * Registers[Src];
492end;
493
494procedure TCPU.OpcodeDivision;
495var
496 Dest, Src: TRegIndex;
497begin
498 Dest := ReadReg;
499 Src := ReadReg;
500 Registers[Dest] := Registers[Dest] div Registers[Src];
501end;
502{$ENDIF}
503
504{$IFDEF EXT_SHIFT}
505procedure TCPU.OpcodeShiftLeft;
506var
507 Dest, Src: TRegIndex;
508begin
509 Dest := ReadReg;
510 Src := ReadReg;
511 Registers[Dest] := Registers[Dest] shl Registers[Src];
512end;
513
514procedure TCPU.OpcodeShiftRight;
515var
516 Src, Dest: TRegIndex;
517begin
518 Dest := ReadReg;
519 Src := ReadReg;
520 Registers[Dest] := Registers[Dest] shr Registers[Src];
521end;
522{$ENDIF}
523
524{$IFDEF EXT_LOGICAL}
525procedure TCPU.OpcodeAnd;
526var
527 Src, Dest: TRegIndex;
528begin
529 Dest := ReadReg;
530 Src := ReadReg;
531 Registers[Dest] := Registers[Dest] and Registers[Src];
532end;
533
534procedure TCPU.OpcodeOr;
535var
536 Src, Dest: TRegIndex;
537begin
538 Dest := ReadReg;
539 Src := ReadReg;
540 Registers[Dest] := Registers[Dest] or Registers[Src];
541end;
542
543procedure TCPU.OpcodeXor;
544var
545 Src, Dest: TRegIndex;
546begin
547 Dest := ReadReg;
548 Src := ReadReg;
549 Registers[Dest] := Registers[Dest] xor Registers[Src];
550end;
551{$ENDIF}
552
553procedure TCPU.OpcodeJump;
554var
555 Reg: TRegIndex;
556begin
557 Reg := ReadReg;
558 IP := Registers[Reg];
559end;
560
561procedure TCPU.OpcodeJumpConditional;
562var
563 Reg: TRegIndex;
564begin
565 Reg := ReadReg;
566 if Condition then
567 IP := Registers[Reg];
568end;
569
570procedure TCPU.OpcodeJumpRelative;
571var
572 Reg: TRegIndex;
573begin
574 Reg := ReadReg;
575 IP := IP + Registers[Reg];
576end;
577
578procedure TCPU.OpcodeJumpRelativeConditional;
579var
580 Reg: TRegIndex;
581begin
582 Reg := ReadReg;
583 if Condition then
584 IP := IP + Registers[Reg];
585end;
586
587{$IFDEF EXT_STACK}
588procedure TCPU.OpcodePush;
589var
590 Reg: TRegIndex;
591begin
592 SP := SP - SizeOf(T);
593 Reg := ReadReg;
594 PT(@Memory[SP])^ := Registers[Reg];
595end;
596
597procedure TCPU.OpcodePop;
598var
599 Reg: TRegIndex;
600begin
601 Reg := ReadReg;
602 Registers[Reg] := PT(@Memory[SP])^;
603 SP := SP + SizeOf(T);
604end;
605{$ENDIF}
606
607{$IFDEF EXT_SUBROUTINE}
608procedure TCPU.OpcodeCall;
609var
610 Reg: TRegIndex;
611begin
612 SP := SP - SizeOf(T);
613 Reg := ReadReg;
614 PT(@Memory[SP])^ := IP;
615 IP := Registers[Reg];
616end;
617
618procedure TCPU.OpcodeReturn;
619begin
620 IP := PT(@Memory[SP])^;
621 SP := SP + SizeOf(T);
622end;
623{$ENDIF}
624
625{$IFDEF EXT_IO}
626procedure TCPU.OpcodeInput;
627var
628 Src, Dest: TRegIndex;
629begin
630 Dest := ReadReg;
631 Src := ReadReg;
632 if Assigned(FOnInput) then
633 Registers[Dest] := FOnInput(Registers[Src]);
634end;
635
636procedure TCPU.OpcodeOutput;
637var
638 Dest, Src: TRegIndex;
639begin
640 Dest := ReadReg;
641 Src := ReadReg;
642 if Assigned(FOnOutput) then
643 FOnOutput(Registers[Dest], Registers[Src]);
644end;
645{$ENDIF}
646
647procedure TCPU.OpcodeTestZero;
648var
649 Reg: TRegIndex;
650begin
651 Reg := ReadReg;
652 Condition := Registers[Reg] = 0;
653end;
654
655procedure TCPU.OpcodeTestNotCarry;
656var
657 Reg1: TRegIndex;
658 Reg2: TRegIndex;
659begin
660 Reg1 := ReadReg;
661 Reg2 := ReadReg;
662 Condition := Registers[Reg2] <= Registers[Reg1];
663end;
664
665procedure TCPU.OpcodeTestCarry;
666var
667 Reg1: TRegIndex;
668 Reg2: TRegIndex;
669begin
670 Reg1 := ReadReg;
671 Reg2 := ReadReg;
672 Condition := Registers[Reg2] > Registers[Reg1];
673end;
674
675{$IFDEF EXT_LOWER_WIDTH}
676procedure TCPU.OpcodePrefix8;
677begin
678 DataWidth := dw8;
679end;
680
681procedure TCPU.OpcodePrefix16;
682begin
683 DataWidth := dw16;
684end;
685
686procedure TCPU.OpcodePrefix32;
687begin
688 DataWidth := dw32;
689end;
690
691procedure TCPU.OpcodePrefix64;
692begin
693 DataWidth := dw64;
694end;
695{$ENDIF}
696
697procedure TCPU.OpcodeTestNotZero;
698var
699 Reg: TRegIndex;
700begin
701 Reg := ReadReg;
702 Condition := Registers[Reg] <> 0;
703end;
704
705{$IFDEF EXT_GENERAL}
706procedure TCPU.OpcodeExchange;
707var
708 Dest, Src: TRegIndex;
709 Temp: T;
710begin
711 Dest := ReadReg;
712 Src := ReadReg;
713 Temp := Registers[Dest];
714 Registers[Dest] := Registers[Src];
715 Registers[Src] := Temp;
716end;
717{$ENDIF}
718
719{$IFDEF EXT_BLOCK}
720procedure TCPU.OpcodeLdir;
721var
722 Dest, Src, Count: TRegIndex;
723begin
724 Dest := ReadReg;
725 Src := ReadReg;
726 Count := ReadReg;
727 while Count > 0 do begin
728 Memory[Registers[Dest]] := Memory[Registers[Src]];
729 Inc(Registers[Dest]);
730 Inc(Registers[Src]);
731 Dec(Registers[Count]);
732 end;
733end;
734
735procedure TCPU.OpcodeLddr;
736var
737 Dest, Src, Count: TRegIndex;
738begin
739 Dest := ReadReg;
740 Src := ReadReg;
741 Count := ReadReg;
742 while Count > 0 do begin
743 Memory[Registers[Dest]] := Memory[Registers[Src]];
744 Dec(Registers[Dest]);
745 Dec(Registers[Src]);
746 Dec(Registers[Count]);
747 end;
748end;
749{$ENDIF}
750
751{$IFDEF EXT_BIT}
752procedure TCPU.OpcodeBitSet;
753var
754 Reg: TRegIndex;
755 Bit: TRegIndex;
756begin
757 Reg := ReadReg;
758 Bit := ReadReg;
759 Registers[Reg] := Registers[Reg] or (1 shl Registers[Bit]);
760end;
761
762procedure TCPU.OpcodeBitReset;
763var
764 Reg: TRegIndex;
765 Bit: TRegIndex;
766begin
767 Reg := ReadReg;
768 Bit := ReadReg;
769 Registers[Reg] := Registers[Reg] and ((1 shl Registers[Bit]) xor -1);
770end;
771
772procedure TCPU.OpcodeBitGet;
773var
774 Reg: TRegIndex;
775 Bit: TRegIndex;
776begin
777 Reg := ReadReg;
778 Bit := ReadReg;
779 Condition := ((Registers[Reg] shr Registers[Bit]) and 1) = 1;
780end;
781
782procedure TCPU.OpcodeBitPut;
783var
784 Reg: TRegIndex;
785 Bit: TRegIndex;
786begin
787 Reg := ReadReg;
788 Bit := ReadReg;
789 if Condition then
790 Registers[Reg] := Registers[Reg] or (1 shl Registers[Bit]);
791end;
792{$ENDIF}
793
794procedure TCPU.Step;
795var
796 Opcode: TOpcode;
797 Handler: TOpcodeHandler;
798begin
799 Opcode := TOpcode(ReadOpcode);
800 if Opcode <= High(TOpcode) then begin
801 Handler := OpcodeHandlers[Opcode];
802 if Assigned(Handler) then Handler
803 else raise Exception.Create('Missing handler for opcode + ' + IntToStr(Integer(Opcode)));
804 end else raise Exception.Create('Unknown opcode: ' + IntToStr(Integer(Opcode)));
805 {$IFDEF EXT_LOWER_WIDTH}
806 if (Opcode <> opPrefix8) and (Opcode <> opPrefix16) and (Opcode <> opPrefix32) and
807 (Opcode <> opPrefix64) then
808 DataWidth := dwNative;
809 {$ENDIF}
810end;
811
812procedure TCPU.AddOpcode(Opcode: TOpcode; Handler: TOpcodeHandler);
813begin
814 OpcodeHandlers[Opcode] := Handler;
815end;
816
817procedure TCPU.InitOpcodes;
818begin
819 AddOpcode(opNop, @OpcodeNoOperation);
820 AddOpcode(opHalt, @OpcodeHalt);
821 AddOpcode(opLD, @OpcodeLoad);
822 AddOpcode(opLDC, @OpcodeLoadConst);
823 AddOpcode(opLDM, @OpcodeLoadMemory);
824 AddOpcode(opSTM, @OpcodeStoreMemory);
825 AddOpcode(opInc, @OpcodeIncrement);
826 AddOpcode(opDec, @OpcodeDecrement);
827 AddOpcode(opTstNZ, @OpcodeTestNotZero);
828 AddOpcode(opTstZ, @OpcodeTestZero);
829 AddOpcode(opTstNC, @OpcodeTestNotCarry);
830 AddOpcode(opTstC, @OpcodeTestCarry);
831 AddOpcode(opJP, @OpcodeJump);
832 AddOpcode(opJpc, @OpcodeJumpConditional);
833 AddOpcode(opJR, @OpcodeJumpRelative);
834 AddOpcode(opJRC, @OpcodeJumpRelativeConditional);
835 {$IFDEF EXT_BIT}
836 AddOpcode(opBitSet, @OpcodeBitSet);
837 AddOpcode(opBitRes, @OpcodeBitReset);
838 AddOpcode(opBitPut, @OpcodeBitPut);
839 AddOpcode(opBitGet, @OpcodeBitGet);
840 {$ENDIF}
841 {$IFDEF EXT_LOGICAL}
842 AddOpcode(opAnd, @OpcodeAnd);
843 AddOpcode(opOr, @OpcodeOr);
844 AddOpcode(opXor, @OpcodeXor);
845 {$ENDIF}
846 {$IFDEF EXT_ADDRESSING_MODES}
847 AddOpcode(opLDMD, @OpcodeLoadMemoryDisplacement);
848 AddOpcode(opSTMD, @OpcodeStoreMemoryDisplacement);
849 {$ENDIF}
850 {$IFDEF EXT_SUBROUTINE}
851 AddOpcode(opCall, @OpcodeCall);
852 AddOpcode(opRet, @OpcodeReturn);
853 {$ENDIF}
854 {$IFDEF EXT_STACK}
855 AddOpcode(opPush, @OpcodePush);
856 AddOpcode(opPop, @OpcodePop);
857 {$ENDIF}
858 {$IFDEF EXT_ARITHMETIC}
859 AddOpcode(opAdd, @OpcodeAddition);
860 AddOpcode(opSub, @OpcodeSubtraction);
861 AddOpcode(opMul, @OpcodeMultiplication);
862 AddOpcode(opDiv, @OpcodeDivision);
863 {$ENDIF}
864 {$IFDEF EXT_GENERAL}
865 AddOpcode(opXchg, @OpcodeExchange);
866 {$ENDIF}
867 {$IFDEF EXT_SHIFT}
868 AddOpcode(opShl, @OpcodeShiftLeft);
869 AddOpcode(opShr, @OpcodeShiftRight);
870 {$ENDIF}
871 {$IFDEF EXT_IO}
872 AddOpcode(opIn, @OpcodeInput);
873 AddOpcode(opOut, @OpcodeOutput);
874 {$ENDIF}
875 {$IFDEF EXT_BLOCK}
876 AddOpcode(opLdir, @OpcodeLdir);
877 AddOpcode(opLddr, @OpcodeLddr);
878 {$ENDIF}
879end;
880
881end.
882
Note: See TracBrowser for help on using the repository browser.