1 | unit Cpu;
|
---|
2 |
|
---|
3 | interface
|
---|
4 |
|
---|
5 | uses
|
---|
6 | Classes, SysUtils, Channel;
|
---|
7 |
|
---|
8 | type
|
---|
9 | TOpcode = (opNop, opHalt, opLoad, opLoadMem, opStoreMem,
|
---|
10 | opInput, opOutput, opJump,
|
---|
11 | opWidth8, opWidth16, opWidth24, opWidth32, opWidth64, opWidth128,
|
---|
12 | opLoadSys, opStoreSys);
|
---|
13 |
|
---|
14 | { TCpu }
|
---|
15 |
|
---|
16 | TCpu = class
|
---|
17 | private
|
---|
18 | FDataWidth: TBitWidth;
|
---|
19 | FAddressWidth: TBitWidth;
|
---|
20 | FPrefixDataWidth: TBitWidth;
|
---|
21 | public
|
---|
22 | Memory: TChannel;
|
---|
23 | IO: TChannel;
|
---|
24 | Terminated: Boolean;
|
---|
25 | PC: QWord;
|
---|
26 | A: QWord;
|
---|
27 | procedure ReadData(var Data: QWord); overload;
|
---|
28 | procedure ReadData(Address: QWord; var Data: QWord); overload;
|
---|
29 | procedure ReadAddress(var Address: QWord);
|
---|
30 | function Read8: Byte;
|
---|
31 | function Read16: Word;
|
---|
32 | function Read24: DWord;
|
---|
33 | function Read32: DWord;
|
---|
34 | function Read64: QWord;
|
---|
35 | function ReadOpcode: TOpcode;
|
---|
36 | procedure WriteData(Data: QWord); overload;
|
---|
37 | procedure WriteData(Address: QWord; Data: QWord); overload;
|
---|
38 | procedure WriteAddress(Address: QWord);
|
---|
39 | procedure Write8(Data: Byte);
|
---|
40 | procedure Write16(Data: Word);
|
---|
41 | procedure Write24(Data: DWord);
|
---|
42 | procedure Write32(Data: DWord);
|
---|
43 | procedure Write64(Data: QWord);
|
---|
44 | procedure WriteOpcode(Opcode: TOpcode);
|
---|
45 | procedure Reset;
|
---|
46 | procedure Run;
|
---|
47 | procedure Step;
|
---|
48 | constructor Create;
|
---|
49 | destructor Destroy; override;
|
---|
50 | property AddressWidth: TBitWidth read FAddressWidth write FAddressWidth;
|
---|
51 | end;
|
---|
52 |
|
---|
53 |
|
---|
54 | implementation
|
---|
55 |
|
---|
56 | { TCpu }
|
---|
57 |
|
---|
58 | function TCpu.Read8: Byte;
|
---|
59 | begin
|
---|
60 | Result := Memory.Read8(PC);
|
---|
61 | Inc(PC);
|
---|
62 | end;
|
---|
63 |
|
---|
64 | function TCpu.Read16: Word;
|
---|
65 | begin
|
---|
66 | Result := Memory.Read16(PC);
|
---|
67 | Inc(PC, SizeOf(Word));
|
---|
68 | end;
|
---|
69 |
|
---|
70 | function TCpu.Read24: DWord;
|
---|
71 | begin
|
---|
72 | Result := Memory.Read24(PC);
|
---|
73 | Inc(PC, 3);
|
---|
74 | end;
|
---|
75 |
|
---|
76 | function TCpu.Read32: DWord;
|
---|
77 | begin
|
---|
78 | Result := Memory.Read32(PC);
|
---|
79 | Inc(PC, SizeOf(DWord));
|
---|
80 | end;
|
---|
81 |
|
---|
82 | function TCpu.Read64: QWord;
|
---|
83 | begin
|
---|
84 | Result := Memory.Read64(PC);
|
---|
85 | Inc(PC, SizeOf(QWord));
|
---|
86 | end;
|
---|
87 |
|
---|
88 | procedure TCpu.ReadData(var Data: QWord);
|
---|
89 | begin
|
---|
90 | ReadData(PC, Data);
|
---|
91 | Inc(PC, Integer(FDataWidth));
|
---|
92 | end;
|
---|
93 |
|
---|
94 | procedure TCpu.ReadData(Address: QWord; var Data: QWord);
|
---|
95 | begin
|
---|
96 | Memory.Read(FDataWidth, Address, Data);
|
---|
97 | end;
|
---|
98 |
|
---|
99 | procedure TCpu.ReadAddress(var Address: QWord);
|
---|
100 | begin
|
---|
101 | Memory.Read(FAddressWidth, PC, Address);
|
---|
102 | Inc(PC, Integer(FAddressWidth));
|
---|
103 | end;
|
---|
104 |
|
---|
105 | function TCpu.ReadOpcode: TOpcode;
|
---|
106 | begin
|
---|
107 | Result := TOpcode(Memory.Read8(PC));
|
---|
108 | Inc(PC);
|
---|
109 | end;
|
---|
110 |
|
---|
111 | procedure TCpu.WriteData(Data: QWord);
|
---|
112 | begin
|
---|
113 | WriteData(PC, Data);
|
---|
114 | Inc(PC, Integer(FDataWidth));
|
---|
115 | end;
|
---|
116 |
|
---|
117 | procedure TCpu.WriteData(Address: QWord; Data: QWord);
|
---|
118 | begin
|
---|
119 | Memory.Write(FDataWidth, Address, Data);
|
---|
120 | end;
|
---|
121 |
|
---|
122 | procedure TCpu.WriteAddress(Address: QWord);
|
---|
123 | begin
|
---|
124 | Memory.Write(FAddressWidth, PC, Address);
|
---|
125 | Inc(PC, Integer(FAddressWidth));
|
---|
126 | end;
|
---|
127 |
|
---|
128 | procedure TCpu.Write8(Data: Byte);
|
---|
129 | begin
|
---|
130 | Memory.Write8(PC, Data);
|
---|
131 | Inc(PC);
|
---|
132 | end;
|
---|
133 |
|
---|
134 | procedure TCpu.Write16(Data: Word);
|
---|
135 | begin
|
---|
136 | Memory.Write16(PC, Data);
|
---|
137 | Inc(PC, SizeOf(Word));
|
---|
138 | end;
|
---|
139 |
|
---|
140 | procedure TCpu.Write24(Data: DWord);
|
---|
141 | begin
|
---|
142 | Memory.Write24(PC, Data);
|
---|
143 | Inc(PC, 3);
|
---|
144 | end;
|
---|
145 |
|
---|
146 | procedure TCpu.Write32(Data: DWord);
|
---|
147 | begin
|
---|
148 | Memory.Write32(PC, Data);
|
---|
149 | Inc(PC, SizeOf(DWord));
|
---|
150 | end;
|
---|
151 |
|
---|
152 | procedure TCpu.Write64(Data: QWord);
|
---|
153 | begin
|
---|
154 | Memory.Write64(PC, Data);
|
---|
155 | Inc(PC, SizeOf(QWord));
|
---|
156 | end;
|
---|
157 |
|
---|
158 | procedure TCpu.WriteOpcode(Opcode: TOpcode);
|
---|
159 | begin
|
---|
160 | Memory.Write8(PC, Byte(Opcode));
|
---|
161 | Inc(PC);
|
---|
162 | end;
|
---|
163 |
|
---|
164 | procedure TCpu.Reset;
|
---|
165 | begin
|
---|
166 | Terminated := False;
|
---|
167 | PC := 0;
|
---|
168 | FPrefixDataWidth := bwNone;
|
---|
169 | FDataWidth := FAddressWidth;
|
---|
170 | end;
|
---|
171 |
|
---|
172 | procedure TCpu.Run;
|
---|
173 | begin
|
---|
174 | Reset;
|
---|
175 | while not Terminated do
|
---|
176 | Step;
|
---|
177 | end;
|
---|
178 |
|
---|
179 | procedure TCpu.Step;
|
---|
180 | var
|
---|
181 | Opcode: TOpcode;
|
---|
182 | Address: QWord;
|
---|
183 | begin
|
---|
184 | if FPrefixDataWidth <> bwNone then begin
|
---|
185 | FDataWidth := FPrefixDataWidth;
|
---|
186 | FPrefixDataWidth := bwNone;
|
---|
187 | end;
|
---|
188 | Opcode := TOpcode(Read8);
|
---|
189 | case Opcode of
|
---|
190 | opNop: ;
|
---|
191 | opHalt: Terminated := True;
|
---|
192 | opLoad: ReadData(A);
|
---|
193 | opLoadMem: begin
|
---|
194 | Address := 0;
|
---|
195 | ReadAddress(Address);
|
---|
196 | ReadData(Address, A);
|
---|
197 | end;
|
---|
198 | opStoreMem: begin
|
---|
199 | Address := 0;
|
---|
200 | ReadAddress(Address);
|
---|
201 | WriteData(Address, A);
|
---|
202 | end;
|
---|
203 | opInput: begin
|
---|
204 | Address := 0;
|
---|
205 | ReadAddress(Address);
|
---|
206 | IO.Read(FDataWidth, Address, A);
|
---|
207 | end;
|
---|
208 | opOutput: begin
|
---|
209 | Address := 0;
|
---|
210 | ReadAddress(Address);
|
---|
211 | IO.Write(FDataWidth, Address, A);
|
---|
212 | end;
|
---|
213 | opJump: begin
|
---|
214 | PC := 0;
|
---|
215 | ReadData(PC);
|
---|
216 | end;
|
---|
217 | opWidth8: if FAddressWidth <= bw8 then FPrefixDataWidth := bw8;
|
---|
218 | opWidth16: if FAddressWidth <= bw16 then FPrefixDataWidth := bw16;
|
---|
219 | opWidth24: if FAddressWidth <= bw24 then FPrefixDataWidth := bw24;
|
---|
220 | opWidth32: if FAddressWidth <= bw32 then FPrefixDataWidth := bw32;
|
---|
221 | opWidth64: if FAddressWidth <= bw64 then FPrefixDataWidth := bw64;
|
---|
222 | opWidth128: if FAddressWidth <= bw128 then FPrefixDataWidth := bw128;
|
---|
223 | end;
|
---|
224 | FDataWidth := FAddressWidth;
|
---|
225 | end;
|
---|
226 |
|
---|
227 | constructor TCpu.Create;
|
---|
228 | begin
|
---|
229 | Memory := TChannel.Create;
|
---|
230 | IO := TChannel.Create;
|
---|
231 | FAddressWidth := bw8;
|
---|
232 | Reset;
|
---|
233 | end;
|
---|
234 |
|
---|
235 | destructor TCpu.Destroy;
|
---|
236 | begin
|
---|
237 | FreeAndNil(Memory);
|
---|
238 | FreeAndNil(IO);
|
---|
239 | inherited;
|
---|
240 | end;
|
---|
241 |
|
---|
242 | end.
|
---|
243 |
|
---|