source: branches/virtualcpu4/UInstructionWriter.pas

Last change on this file was 185, checked in by chronos, 5 years ago
  • Added: Assembler labels reference address calculation.
  • Fixed: Displaying address/data hex numbers in opcode and instruction.
File size: 8.2 KB
Line 
1unit UInstructionWriter;
2
3{$mode delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, UCpu;
9
10type
11
12 { TInstructionWriter }
13
14 TInstructionWriter = class
15 private
16 procedure PrefixBegin;
17 procedure PrefixEnd;
18 public
19 Cpu: TCpu;
20 IP: Integer;
21 DataSize: TBitWidth;
22 DataSizeBase: TBitWidth;
23 AddrSize: TBitWidth;
24 AddrSizeBase: TBitWidth;
25 Prefix: Boolean;
26 procedure Init;
27 function GetRelativeAddr(BitWidth: TBitWidth; BaseIP, TargetAddr: QWord): Int64;
28 procedure Write8(Value: Byte);
29 procedure Write16(Value: Word);
30 procedure Write32(Value: DWord);
31 procedure Write64(Value: QWord);
32 procedure WriteAddress(Value: TAddress);
33 procedure WriteAddressSigned(Value: TAddressSigned); inline;
34 procedure WriteData(Value: QWord);
35 procedure WriteString(Text: string);
36 procedure Nop;
37 procedure Halt;
38 procedure Loadi(Reg: TRegIndex; Value: QWord);
39 procedure Increment(Reg: TRegIndex);
40 procedure Decrement(Reg: TRegIndex);
41 procedure Jump(Addr: QWord);
42 procedure JumpNotZero(Addr: QWord);
43 procedure JumpZero(Addr: QWord);
44 procedure JumpRel(Addr: QWord);
45 procedure JumpRelNotZero(Addr: QWord);
46 procedure JumpRelZero(Addr: QWord);
47 procedure Push(Reg: TRegIndex);
48 procedure Pop(Reg: TRegIndex);
49 procedure Call(Addr: QWord);
50 procedure Return;
51 procedure Convert(Reg: TRegIndex);
52 procedure DataPrefix8;
53 procedure DataPrefix16;
54 procedure DataPrefix32;
55 procedure DataPrefix64;
56 procedure AddrPrefix8;
57 procedure AddrPrefix16;
58 procedure AddrPrefix32;
59 procedure AddrPrefix64;
60 procedure StoreMem(RegAddr, RegSrc: TRegIndex);
61 procedure LoadMem(RegDst, RegAddr: TRegIndex);
62 procedure Output(Port: TAddress; Reg: TRegIndex);
63 procedure Input(Reg: TRegIndex; Port: TAddress);
64 procedure Test(Reg: TRegIndex);
65 end;
66
67
68implementation
69
70{ TInstructionWriter }
71
72procedure TInstructionWriter.Nop;
73begin
74 PrefixBegin;
75 Write8(Byte(opNop));
76 PrefixEnd;
77end;
78
79procedure TInstructionWriter.Halt;
80begin
81 PrefixBegin;
82 Write8(Byte(opHalt));
83 PrefixEnd;
84end;
85
86procedure TInstructionWriter.Loadi(Reg: TRegIndex; Value: QWord);
87begin
88 PrefixBegin;
89 Write8(Byte(opLoadi));
90 Write8(Reg);
91 WriteData(Value);
92 PrefixEnd;
93end;
94
95procedure TInstructionWriter.Increment(Reg: TRegIndex);
96begin
97 PrefixBegin;
98 Write8(Byte(opInc));
99 Write8(Reg);
100 PrefixEnd;
101end;
102
103procedure TInstructionWriter.Decrement(Reg: TRegIndex);
104begin
105 PrefixBegin;
106 Write8(Byte(opDec));
107 Write8(Reg);
108 PrefixEnd;
109end;
110
111procedure TInstructionWriter.Jump(Addr: QWord);
112begin
113 PrefixBegin;
114 Write8(Byte(opJump));
115 WriteAddress(Addr);
116 PrefixEnd;
117end;
118
119procedure TInstructionWriter.JumpNotZero(Addr: QWord);
120begin
121 PrefixBegin;
122 Write8(Byte(opJumpNotZero));
123 WriteAddress(Addr);
124 PrefixEnd;
125end;
126
127procedure TInstructionWriter.JumpZero(Addr: QWord);
128begin
129 PrefixBegin;
130 Write8(Byte(opJumpZero));
131 WriteAddress(Addr);
132 PrefixEnd;
133end;
134
135function TInstructionWriter.GetRelativeAddr(BitWidth: TBitWidth; BaseIP, TargetAddr: QWord): Int64;
136begin
137 Result := Int64(TargetAddr) - (BaseIP + 1 + BitWidthBytes[BitWidth]);
138end;
139
140procedure TInstructionWriter.JumpRel(Addr: QWord);
141var
142 RelAddr: Int64;
143begin
144 PrefixBegin;
145 RelAddr := GetRelativeAddr(AddrSize, IP, Addr);
146 Write8(Byte(opJumpRel));
147 WriteAddressSigned(RelAddr);
148 PrefixEnd;
149end;
150
151procedure TInstructionWriter.JumpRelNotZero(Addr: QWord);
152var
153 RelAddr: Int64;
154begin
155 PrefixBegin;
156 RelAddr := GetRelativeAddr(AddrSize, IP, Addr);
157 Write8(Byte(opJumpRelNotZero));
158 WriteAddressSigned(RelAddr);
159 PrefixEnd;
160end;
161
162procedure TInstructionWriter.JumpRelZero(Addr: QWord);
163var
164 RelAddr: Int64;
165begin
166 PrefixBegin;
167 RelAddr := GetRelativeAddr(AddrSize, IP, Addr);
168 Write8(Byte(opJumpRelZero));
169 WriteAddressSigned(RelAddr);
170 PrefixEnd;
171end;
172
173procedure TInstructionWriter.Push(Reg: TRegIndex);
174begin
175 PrefixBegin;
176 Write8(Byte(opPush));
177 Write8(Reg);
178 PrefixEnd;
179end;
180
181procedure TInstructionWriter.Pop(Reg: TRegIndex);
182begin
183 PrefixBegin;
184 Write8(Byte(opPop));
185 Write8(Reg);
186 PrefixEnd;
187end;
188
189procedure TInstructionWriter.Call(Addr: QWord);
190begin
191 PrefixBegin;
192 Write8(Byte(opCall));
193 WriteAddress(Addr);
194 PrefixEnd;
195end;
196
197procedure TInstructionWriter.Return;
198begin
199 PrefixBegin;
200 Write8(Byte(opRet));
201 PrefixEnd;
202end;
203
204procedure TInstructionWriter.Convert(Reg: TRegIndex);
205begin
206 PrefixBegin;
207 Write8(Byte(opConvert));
208 Write8(Reg);
209 PrefixEnd;
210end;
211
212procedure TInstructionWriter.DataPrefix8;
213begin
214 Prefix := True;
215 DataSize := bw8;
216 Write8(Byte(opDataPrefix8));
217end;
218
219procedure TInstructionWriter.DataPrefix16;
220begin
221 Prefix := True;
222 DataSize := bw16;
223 Write8(Byte(opDataPrefix16));
224end;
225
226procedure TInstructionWriter.DataPrefix32;
227begin
228 Prefix := True;
229 DataSize := bw32;
230 Write8(Byte(opDataPrefix32));
231end;
232
233procedure TInstructionWriter.DataPrefix64;
234begin
235 Prefix := True;
236 DataSize := bw64;
237 Write8(Byte(opDataPrefix64));
238end;
239
240procedure TInstructionWriter.AddrPrefix8;
241begin
242 Prefix := True;
243 AddrSize := bw8;
244 Write8(Byte(opAddrPrefix8));
245end;
246
247procedure TInstructionWriter.AddrPrefix16;
248begin
249 Prefix := True;
250 AddrSize := bw16;
251 Write8(Byte(opAddrPrefix16));
252end;
253
254procedure TInstructionWriter.AddrPrefix32;
255begin
256 Prefix := True;
257 AddrSize := bw32;
258 Write8(Byte(opAddrPrefix32));
259end;
260
261procedure TInstructionWriter.AddrPrefix64;
262begin
263 Prefix := True;
264 AddrSize := bw64;
265 Write8(Byte(opAddrPrefix64));
266end;
267
268procedure TInstructionWriter.StoreMem(RegAddr, RegSrc: TRegIndex);
269begin
270 Write8(Byte(opStoreMem));
271 Write8(RegAddr);
272 Write8(RegSrc);
273end;
274
275procedure TInstructionWriter.LoadMem(RegDst, RegAddr: TRegIndex);
276begin
277 PrefixBegin;
278 Write8(Byte(opLoadMem));
279 Write8(RegDst);
280 Write8(RegAddr);
281 PrefixEnd;
282end;
283
284procedure TInstructionWriter.Output(Port: TAddress; Reg: TRegIndex);
285begin
286 PrefixBegin;
287 Write8(Byte(opOut));
288 WriteAddress(Port);
289 Write8(Reg);
290 PrefixEnd;
291end;
292
293procedure TInstructionWriter.Input(Reg: TRegIndex; Port: TAddress);
294begin
295 PrefixBegin;
296 Write8(Byte(opIn));
297 Write8(Reg);
298 WriteAddress(Port);
299 PrefixEnd;
300end;
301
302procedure TInstructionWriter.Test(Reg: TRegIndex);
303begin
304 PrefixBegin;
305 Write8(Byte(opTest));
306 Write8(Reg);
307 Prefixend;
308end;
309
310procedure TInstructionWriter.WriteString(Text: string);
311var
312 I: Integer;
313begin
314 for I := 1 to Length(Text) do
315 Write8(Ord(Text[I]));
316end;
317
318procedure TInstructionWriter.PrefixBegin;
319begin
320 Prefix := False;
321end;
322
323procedure TInstructionWriter.PrefixEnd;
324begin
325 if not Prefix then begin
326 DataSize := DataSizeBase;
327 AddrSize := AddrSizeBase;
328 end;
329end;
330
331procedure TInstructionWriter.Init;
332begin
333 DataSizeBase := Cpu.DataSizeBase;
334 DataSize := DataSizeBase;
335 AddrSizeBase := Cpu.AddrSizeBase;
336 AddrSize := AddrSizeBase;
337 IP := 0;
338 Prefix := False;
339end;
340
341procedure TInstructionWriter.Write8(Value: Byte);
342begin
343 PByte(Cpu.Memory + IP)^ := Value;
344 Inc(IP, SizeOf(Byte));
345end;
346
347procedure TInstructionWriter.Write16(Value: Word);
348begin
349 PWord(Cpu.Memory + IP)^ := Value;
350 Inc(IP, SizeOf(Word));
351end;
352
353procedure TInstructionWriter.Write32(Value: DWord);
354begin
355 PDWord(Cpu.Memory + IP)^ := Value;
356 Inc(IP, SizeOf(DWord));
357end;
358
359procedure TInstructionWriter.Write64(Value: QWord);
360begin
361 PQWord(Cpu.Memory + IP)^ := Value;
362 Inc(IP, SizeOf(QWord));
363end;
364
365procedure TInstructionWriter.WriteAddress(Value: TAddress);
366begin
367 case AddrSize of
368 bw8: Write8(Value and $ff);
369 bw16: Write16(Value and $ffff);
370 bw32: Write32(Value and $ffffffff);
371 bw64: Write64(Value);
372 end;
373end;
374
375procedure TInstructionWriter.WriteAddressSigned(Value: TAddressSigned);
376begin
377 case AddrSize of
378 bw8: Write8(Byte(Value and $ff));
379 bw16: Write16(Word(Value and $ffff));
380 bw32: Write32(DWord(Value and $ffffffff));
381 bw64: Write64(QWord(Value));
382 end;
383end;
384
385procedure TInstructionWriter.WriteData(Value: QWord);
386begin
387 case DataSize of
388 bw8: Write8(Value and $ff);
389 bw16: Write16(Value and $ffff);
390 bw32: Write32(Value and $ffffffff);
391 bw64: Write64(Value);
392 end;
393end;
394
395end.
396
Note: See TracBrowser for help on using the repository browser.