DEADSOFTWARE

Port, TODO
[bbcp.git] / Trurl-based / Dev / Mod / CPL486.txt
1 MODULE DevCPL486;
3 (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 Dev/Mod/CPL486.odc *)
4 (* DO NOT EDIT *)
6 IMPORT DevCPM, DevCPT, DevCPE;
8 TYPE
9 Item* = RECORD
10 mode*, tmode*, form*: BYTE;
11 offset*, index*, reg*, scale*: INTEGER; (* adr = offset + index * scale *)
12 typ*: DevCPT.Struct;
13 obj*: DevCPT.Object
14 END ;
16 (* Items:
18 mode | offset index scale reg obj
19 ------------------------------------------------
20 1 Var | adr xreg scale obj (ea = FP + adr + xreg * scale)
21 2 VarPar| off xreg scale obj (ea = [FP + obj.adr] + off + xreg * scale)
22 3 Con | val (val2) NIL
23 Con | off obj (val = adr(obj) + off)
24 Con | id NIL (for predefined reals)
25 6 LProc | obj
26 7 XProc | obj
27 9 CProc | obj
28 10 IProc | obj
29 13 TProc | mthno 0/1 obj (0 = normal / 1 = super call)
30 14 Ind | off xreg scale Reg (ea = Reg + off + xreg * scale)
31 15 Abs | adr xreg scale NIL (ea = adr + xreg * scale)
32 Abs | off xreg scale obj (ea = adr(obj) + off + xreg * scale)
33 Abs | off len 0 obj (for constant strings and reals)
34 16 Stk | (ea = ESP)
35 17 Cond | CC
36 18 Reg | (Reg2) Reg
37 19 DInd | off xreg scale Reg (ea = [Reg + off + xreg * scale])
39 tmode | record tag array desc
40 -------------------------------------
41 VarPar | [FP + obj.adr + 4] [FP + obj.adr]
42 Ind | [Reg - 4] [Reg + 8]
43 Con | Adr(typ.strobj)
45 *)
47 CONST
48 processor* = 10; (* for i386 *)
49 NewLbl* = 0;
51 TYPE
52 Label* = INTEGER; (* 0: unassigned, > 0: address, < 0: - (linkadr + linktype * 2^24) *)
54 VAR
55 level*: BYTE;
56 one*: DevCPT.Const;
58 CONST
59 (* item base modes (=object modes) *)
60 Var = 1; VarPar = 2; Con = 3; LProc = 6; XProc = 7; CProc = 9; IProc = 10; TProc = 13;
62 (* item modes for i386 (must not overlap item basemodes, > 13) *)
63 Ind = 14; Abs = 15; Stk = 16; Cond = 17; Reg = 18; DInd = 19;
65 (* structure forms *)
66 Undef = 0; Byte = 1; Bool = 2; Char8 = 3; Int8 = 4; Int16 = 5; Int32 = 6;
67 Real32 = 7; Real64 = 8; Set = 9; String8 = 10; NilTyp = 11; NoTyp = 12;
68 Pointer = 13; ProcTyp = 14; Comp = 15;
69 Char16 = 16; String16 = 17; Int64 = 18; Guid = 23;
71 (* composite structure forms *)
72 Basic = 1; Array = 2; DynArr = 3; Record = 4;
74 (* condition codes *)
75 ccB = 2; ccAE = 3; ccBE = 6; ccA = 7; (* unsigned *)
76 ccL = 12; ccGE = 13; ccLE = 14; ccG = 15; (* signed *)
77 ccE = 4; ccNE = 5; ccS = 8; ccNS = 9; ccO = 0; ccNO = 1;
78 ccAlways = -1; ccNever = -2; ccCall = -3;
80 (* registers *)
81 AX = 0; CX = 1; DX = 2; BX = 3; SP = 4; BP = 5; SI = 6; DI = 7; AH = 4; CH = 5; DH = 6; BH = 7;
83 (* fixup types *)
84 absolute = 100; relative = 101; copy = 102; table = 103; tableend = 104; short = 105;
86 (* system trap numbers *)
87 withTrap = -1; caseTrap = -2; funcTrap = -3; typTrap = -4;
88 recTrap = -5; ranTrap = -6; inxTrap = -7; copyTrap = -8;
91 VAR
92 Size: ARRAY 32 OF INTEGER; (* Size[typ.form] == +/- typ.size *)
93 a1, a2: Item;
96 PROCEDURE MakeReg* (VAR x: Item; reg: INTEGER; form: BYTE);
97 BEGIN
98 ASSERT((reg >= 0) & (reg < 8));
99 x.mode := Reg; x.reg := reg; x.form := form
100 END MakeReg;
102 PROCEDURE MakeConst* (VAR x: Item; val: INTEGER; form: BYTE);
103 BEGIN
104 x.mode := Con; x.offset := val; x.form := form; x.obj := NIL;
105 END MakeConst;
107 PROCEDURE AllocConst* (VAR x: Item; con: DevCPT.Const; form: BYTE);
108 VAR r: REAL; short: SHORTREAL; c: DevCPT.Const; i: INTEGER;
109 BEGIN
110 IF form IN {Real32, Real64} THEN
111 r := con.realval;
112 IF ABS(r) <= MAX(SHORTREAL) THEN
113 short := SHORT(r);
114 IF short = r THEN form := Real32 (* a shortreal can represent the exact value *)
115 ELSE form := Real64 (* use a real *)
116 END
117 ELSE form := Real64 (* use a real *)
118 END
119 ELSIF form IN {String8, String16, Guid} THEN
120 x.index := con.intval2 (* string length *)
121 END;
122 DevCPE.AllocConst(con, form, x.obj, x.offset);
123 x.form := form; x.mode := Abs; x.scale := 0
124 END AllocConst;
126 (*******************************************************)
128 PROCEDURE BegStat*; (* general-purpose procedure which is called before each statement *)
129 BEGIN
130 END BegStat;
132 PROCEDURE EndStat*; (* general-purpose procedure which is called after each statement *)
133 BEGIN
134 END EndStat;
136 (*******************************************************)
138 PROCEDURE SetLabel* (VAR L: Label);
139 VAR link, typ, disp, x: INTEGER; c: SHORTCHAR;
140 BEGIN
141 ASSERT(L <= 0); link := -L;
142 WHILE link # 0 DO
143 typ := link DIV 1000000H; link := link MOD 1000000H;
144 IF typ = short THEN
145 disp := DevCPE.pc - link - 1; ASSERT(disp < 128);
146 DevCPE.PutByte(link, disp); link := 0
147 ELSIF typ = relative THEN
148 x := DevCPE.ThisWord(link); DevCPE.PutWord(link, DevCPE.pc - link - 4); link := x
149 ELSE
150 x := DevCPE.ThisWord(link); DevCPE.PutWord(link, DevCPE.pc + typ * 1000000H); link := x
151 END
152 END;
153 L := DevCPE.pc;
154 a1.mode := 0; a2.mode := 0
155 END SetLabel;
158 (*******************************************************)
160 PROCEDURE GenWord (x: INTEGER);
161 BEGIN
162 DevCPE.GenByte(x); DevCPE.GenByte(x DIV 256)
163 END GenWord;
165 PROCEDURE GenDbl (x: INTEGER);
166 BEGIN
167 DevCPE.GenByte(x); DevCPE.GenByte(x DIV 256); DevCPE.GenByte(x DIV 10000H); DevCPE.GenByte(x DIV 1000000H)
168 END GenDbl;
170 PROCEDURE CaseEntry* (tab, from, to: INTEGER);
171 VAR a, e: INTEGER;
172 BEGIN
173 a := tab + 4 * from; e := tab + 4 * to;
174 WHILE a <= e DO
175 DevCPE.PutByte(a, DevCPE.pc);
176 DevCPE.PutByte(a + 1, DevCPE.pc DIV 256);
177 DevCPE.PutByte(a + 2, DevCPE.pc DIV 65536);
178 INC(a, 4)
179 END;
180 a1.mode := 0; a2.mode := 0
181 END CaseEntry;
183 PROCEDURE GenLinked (VAR x: Item; type: BYTE);
184 VAR link: DevCPT.LinkList;
185 BEGIN
186 IF x.obj = NIL THEN GenDbl(x.offset)
187 ELSE
188 link := DevCPE.OffsetLink(x.obj, x.offset);
189 IF link # NIL THEN
190 GenDbl(type * 1000000H + link.linkadr MOD 1000000H);
191 link.linkadr := DevCPE.pc - 4
192 ELSE GenDbl(0)
193 END
194 END
195 END GenLinked;
197 PROCEDURE CheckSize (form: BYTE; VAR w: INTEGER);
198 BEGIN
199 IF form IN {Int16, Char16} THEN DevCPE.GenByte(66H); w := 1
200 ELSIF form >= Int32 THEN ASSERT(form IN {Int32, Set, NilTyp, Pointer, ProcTyp}); w := 1
201 ELSE w := 0
202 END
203 END CheckSize;
205 PROCEDURE CheckForm (form: BYTE; VAR mf: INTEGER);
206 BEGIN
207 IF form = Real32 THEN mf := 0
208 ELSIF form = Real64 THEN mf := 4
209 ELSIF form = Int32 THEN mf := 2
210 ELSE ASSERT(form = Int16); mf := 6
211 END
212 END CheckForm;
214 PROCEDURE CheckConst (VAR x: Item; VAR s: INTEGER);
215 BEGIN
216 IF (x.form > Int8) & (x.offset >= -128) & (x.offset < 128) & (x.obj = NIL) THEN s := 2
217 ELSE s := 0
218 END
219 END CheckConst;
221 PROCEDURE GenConst (VAR x: Item; short: BOOLEAN);
222 BEGIN
223 IF x.obj # NIL THEN GenLinked(x, absolute)
224 ELSIF x.form <= Int8 THEN DevCPE.GenByte(x.offset)
225 ELSIF short & (x.offset >= -128) & (x.offset < 128) THEN DevCPE.GenByte(x.offset)
226 ELSIF x.form IN {Int16, Char16} THEN GenWord(x.offset)
227 ELSE GenDbl(x.offset)
228 END
229 END GenConst;
231 PROCEDURE GenCExt (code: INTEGER; VAR x: Item);
232 VAR disp, mod, base, scale: INTEGER;
233 BEGIN
234 ASSERT(x.mode IN {Reg, Ind, Abs, Stk});
235 ASSERT((code MOD 8 = 0) & (code < 64));
236 disp := x.offset; base := x.reg; scale := x.scale;
237 IF x.mode = Reg THEN mod := 0C0H; scale := 0
238 ELSIF x.mode = Stk THEN base := SP; mod := 0; disp := 0; scale := 0
239 ELSIF x.mode = Abs THEN
240 IF scale = 1 THEN base := x.index; mod := 80H; scale := 0
241 ELSE base := BP; mod := 0
242 END
243 ELSIF (disp = 0) & (base # BP) THEN mod := 0
244 ELSIF (disp >= -128) & (disp < 128) THEN mod := 40H
245 ELSE mod := 80H
246 END;
247 IF scale # 0 THEN
248 DevCPE.GenByte(mod + code + 4); base := base + x.index * 8;
249 IF scale = 8 THEN DevCPE.GenByte(0C0H + base);
250 ELSIF scale = 4 THEN DevCPE.GenByte(80H + base);
251 ELSIF scale = 2 THEN DevCPE.GenByte(40H + base);
252 ELSE ASSERT(scale = 1); DevCPE.GenByte(base);
253 END;
254 ELSE
255 DevCPE.GenByte(mod + code + base);
256 IF (base = SP) & (mod <= 80H) THEN DevCPE.GenByte(24H) END
257 END;
258 IF x.mode = Abs THEN GenLinked(x, absolute)
259 ELSIF mod = 80H THEN GenDbl(disp)
260 ELSIF mod = 40H THEN DevCPE.GenByte(disp)
261 END
262 END GenCExt;
264 PROCEDURE GenDExt (VAR r, x: Item);
265 BEGIN
266 ASSERT(r.mode = Reg);
267 GenCExt(r.reg * 8, x)
268 END GenDExt;
270 (*******************************************************)
272 PROCEDURE GenMove* (VAR from, to: Item);
273 VAR w: INTEGER;
274 BEGIN
275 ASSERT(Size[from.form] = Size[to.form]);
276 IF to.mode = Reg THEN
277 IF from.mode = Con THEN
278 IF to.reg = AX THEN
280 IF (a1.mode = Con) & (from.offset = a1.offset) & (from.obj = a1.obj) & (from.form = a1.form) THEN
281 RETURN
282 END;
284 a1 := from; a2.mode := 0
285 END;
286 CheckSize(from.form, w);
287 IF (from.offset = 0) & (from.obj = NIL) THEN
288 DevCPE.GenByte(30H + w); DevCPE.GenByte(0C0H + 9 * to.reg) (* XOR r,r *)
289 ELSE
290 DevCPE.GenByte(0B0H + w * 8 + to.reg); GenConst(from, FALSE)
291 END;
292 ELSIF (to.reg = AX) & (from.mode = Abs) & (from.scale = 0) THEN
294 IF (a1.mode = Abs) & (from.offset = a1.offset) & (from.obj = a1.obj) & (from.form = a1.form)
295 OR (a2.mode = Abs) & (from.offset = a2.offset) & (from.obj = a2.obj) & (from.form = a2.form) THEN
296 RETURN
297 END;
299 a1 := from; a2.mode := 0;
300 CheckSize(from.form, w);
301 DevCPE.GenByte(0A0H + w); GenLinked(from, absolute);
302 ELSIF (from.mode # Reg) OR (from.reg # to.reg) THEN
303 IF to.reg = AX THEN
304 IF (from.mode = Ind) & (from.scale = 0) & ((from.reg = BP) OR (from.reg = BX)) THEN
306 IF (a1.mode = Ind) & (from.offset = a1.offset) & (from.reg = a1.reg) & (from.form = a1.form)
307 OR (a2.mode = Ind) & (from.offset = a2.offset) & (from.reg = a2.reg) & (from.form = a2.form) THEN
308 RETURN
309 END;
311 a1 := from
312 ELSE a1.mode := 0
313 END;
314 a2.mode := 0
315 END;
316 CheckSize(from.form, w);
317 DevCPE.GenByte(8AH + w); GenDExt(to, from)
318 END
319 ELSE
320 CheckSize(from.form, w);
321 IF from.mode = Con THEN
322 DevCPE.GenByte(0C6H + w); GenCExt(0, to); GenConst(from, FALSE);
323 a1.mode := 0; a2.mode := 0
324 ELSIF (from.reg = AX) & (to.mode = Abs) & (to.scale = 0) THEN
325 DevCPE.GenByte(0A2H + w); GenLinked(to, absolute);
326 a2 := to
327 ELSE
328 DevCPE.GenByte(88H + w); GenDExt(from, to);
329 IF from.reg = AX THEN
330 IF (to.mode = Ind) & (to.scale = 0) & ((to.reg = BP) OR (to.reg = BX)) THEN a2 := to END
331 ELSE a1.mode := 0; a2.mode := 0
332 END
333 END
334 END
335 END GenMove;
337 PROCEDURE GenExtMove* (VAR from, to: Item);
338 VAR w, op: INTEGER;
339 BEGIN
340 ASSERT(from.mode # Con);
341 IF from.form IN {Byte, Char8, Char16} THEN op := 0B6H (* MOVZX *)
342 ELSE op := 0BEH (* MOVSX *)
343 END;
344 IF from.form IN {Int16, Char16} THEN INC(op) END;
345 DevCPE.GenByte(0FH); DevCPE.GenByte(op); GenDExt(to, from);
346 IF to.reg = AX THEN a1.mode := 0; a2.mode := 0 END
347 END GenExtMove;
349 PROCEDURE GenSignExt* (VAR from, to: Item);
350 BEGIN
351 ASSERT(to.mode = Reg);
352 IF (from.mode = Reg) & (from.reg = AX) & (to.reg = DX) THEN
353 DevCPE.GenByte(99H) (* cdq *)
354 ELSE
355 GenMove(from, to); (* mov to, from *)
356 DevCPE.GenByte(0C1H); GenCExt(38H, to); DevCPE.GenByte(31) (* sar to, 31 *)
357 END
358 END GenSignExt;
360 PROCEDURE GenLoadAdr* (VAR from, to: Item);
361 BEGIN
362 ASSERT(to.form IN {Int32, Pointer, ProcTyp});
363 IF (from.mode = Abs) & (from.scale = 0) THEN
364 DevCPE.GenByte(0B8H + to.reg); GenLinked(from, absolute)
365 ELSIF from.mode = Stk THEN
366 DevCPE.GenByte(89H); GenCExt(SP * 8, to)
367 ELSIF (from.mode # Ind) OR (from.offset # 0) OR (from.scale # 0) THEN
368 DevCPE.GenByte(8DH); GenDExt(to, from)
369 ELSIF from.reg # to.reg THEN
370 DevCPE.GenByte(89H); GenCExt(from.reg * 8, to)
371 ELSE RETURN
372 END;
373 IF to.reg = AX THEN a1.mode := 0; a2.mode := 0 END
374 END GenLoadAdr;
376 PROCEDURE GenPush* (VAR src: Item);
377 VAR s: INTEGER;
378 BEGIN
379 IF src.mode = Con THEN
380 ASSERT(src.form >= Int32);
381 CheckConst(src, s); DevCPE.GenByte(68H + s); GenConst(src, TRUE)
382 ELSIF src.mode = Reg THEN
383 ASSERT((src.form >= Int16) OR (src.reg < 4));
384 DevCPE.GenByte(50H + src.reg)
385 ELSE
386 ASSERT(src.form >= Int32);
387 DevCPE.GenByte(0FFH); GenCExt(30H, src)
388 END
389 END GenPush;
391 PROCEDURE GenPop* (VAR dst: Item);
392 BEGIN
393 IF dst.mode = Reg THEN
394 ASSERT((dst.form >= Int16) OR (dst.reg < 4));
395 DevCPE.GenByte(58H + dst.reg);
396 IF dst.reg = AX THEN a1.mode := 0; a2.mode := 0 END
397 ELSE
398 DevCPE.GenByte(08FH); GenCExt(0, dst)
399 END
400 END GenPop;
402 PROCEDURE GenConOp (op: INTEGER; VAR src, dst: Item);
403 VAR w, s: INTEGER;
404 BEGIN
405 ASSERT(Size[src.form] = Size[dst.form]);
406 CheckSize(src.form, w);
407 CheckConst(src, s);
408 IF (dst.mode = Reg) & (dst.reg = AX) & (s = 0) THEN
409 DevCPE.GenByte(op + 4 + w); GenConst(src, FALSE)
410 ELSE
411 DevCPE.GenByte(80H + s + w); GenCExt(op, dst); GenConst(src, TRUE)
412 END
413 END GenConOp;
415 PROCEDURE GenDirOp (op: INTEGER; VAR src, dst: Item);
416 VAR w: INTEGER;
417 BEGIN
418 ASSERT(Size[src.form] = Size[dst.form]);
419 CheckSize(src.form, w);
420 IF dst.mode = Reg THEN
421 DevCPE.GenByte(op + 2 + w); GenDExt(dst, src)
422 ELSE
423 DevCPE.GenByte(op + w); GenDExt(src, dst)
424 END
425 END GenDirOp;
427 PROCEDURE GenAdd* (VAR src, dst: Item; ovflchk: BOOLEAN);
428 VAR w: INTEGER;
429 BEGIN
430 ASSERT(Size[src.form] = Size[dst.form]);
431 IF src.mode = Con THEN
432 IF src.obj = NIL THEN
433 IF src.offset = 1 THEN
434 IF (dst.mode = Reg) & (dst.form >= Int32) THEN DevCPE.GenByte(40H + dst.reg) (* inc *)
435 ELSE CheckSize(dst.form, w); DevCPE.GenByte(0FEH + w); GenCExt(0, dst)
436 END
437 ELSIF src.offset = -1 THEN
438 IF (dst.mode = Reg) & (dst.form >= Int32) THEN DevCPE.GenByte(48H + dst.reg) (* dec *)
439 ELSE CheckSize(dst.form, w); DevCPE.GenByte(0FEH + w); GenCExt(8, dst)
440 END
441 ELSIF src.offset # 0 THEN
442 GenConOp(0, src, dst)
443 ELSE RETURN
444 END
445 ELSE
446 GenConOp(0, src, dst)
447 END
448 ELSE
449 GenDirOp(0, src, dst)
450 END;
451 IF ovflchk THEN DevCPE.GenByte(0CEH) END;
452 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
453 END GenAdd;
455 PROCEDURE GenAddC* (VAR src, dst: Item; first, ovflchk: BOOLEAN);
456 VAR op: INTEGER;
457 BEGIN
458 ASSERT(Size[src.form] = Size[dst.form]);
459 IF first THEN op := 0 ELSE op := 10H END;
460 IF src.mode = Con THEN GenConOp(op, src, dst)
461 ELSE GenDirOp(op, src, dst)
462 END;
463 IF ovflchk THEN DevCPE.GenByte(0CEH) END;
464 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
465 END GenAddC;
467 PROCEDURE GenSub* (VAR src, dst: Item; ovflchk: BOOLEAN);
468 VAR w: INTEGER;
469 BEGIN
470 ASSERT(Size[src.form] = Size[dst.form]);
471 IF src.mode = Con THEN
472 IF src.obj = NIL THEN
473 IF src.offset = 1 THEN
474 IF (dst.mode = Reg) & (dst.form >= Int32) THEN DevCPE.GenByte(48H + dst.reg) (* dec *)
475 ELSE CheckSize(dst.form, w); DevCPE.GenByte(0FEH + w); GenCExt(8, dst)
476 END
477 ELSIF src.offset = -1 THEN
478 IF (dst.mode = Reg) & (dst.form >= Int32) THEN DevCPE.GenByte(40H + dst.reg) (* inc *)
479 ELSE CheckSize(dst.form, w); DevCPE.GenByte(0FEH + w); GenCExt(0, dst)
480 END
481 ELSIF src.offset # 0 THEN
482 GenConOp(28H, src, dst)
483 ELSE RETURN
484 END
485 ELSE
486 GenConOp(28H, src, dst)
487 END
488 ELSE
489 GenDirOp(28H, src, dst)
490 END;
491 IF ovflchk THEN DevCPE.GenByte(0CEH) END;
492 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
493 END GenSub;
495 PROCEDURE GenSubC* (VAR src, dst: Item; first, ovflchk: BOOLEAN);
496 VAR op: INTEGER;
497 BEGIN
498 ASSERT(Size[src.form] = Size[dst.form]);
499 IF first THEN op := 28H ELSE op := 18H END;
500 IF src.mode = Con THEN GenConOp(op, src, dst)
501 ELSE GenDirOp(op, src, dst)
502 END;
503 IF ovflchk THEN DevCPE.GenByte(0CEH) END;
504 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
505 END GenSubC;
507 PROCEDURE GenComp* (VAR src, dst: Item);
508 VAR w: INTEGER;
509 BEGIN
510 IF src.mode = Con THEN
511 IF (src.offset = 0) & (src.obj = NIL) & (dst.mode = Reg) THEN
512 CheckSize(dst.form, w); DevCPE.GenByte(8 + w); DevCPE.GenByte(0C0H + 9 * dst.reg) (* or r,r *)
513 ELSE GenConOp(38H, src, dst)
514 END
515 ELSE
516 GenDirOp(38H, src, dst)
517 END
518 END GenComp;
520 PROCEDURE GenAnd* (VAR src, dst: Item);
521 BEGIN
522 IF src.mode = Con THEN
523 IF (src.obj # NIL) OR (src.offset # -1) THEN GenConOp(20H, src, dst) END
524 ELSE GenDirOp(20H, src, dst)
525 END;
526 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
527 END GenAnd;
529 PROCEDURE GenOr* (VAR src, dst: Item);
530 BEGIN
531 IF src.mode = Con THEN
532 IF (src.obj # NIL) OR (src.offset # 0) THEN GenConOp(8H, src, dst) END
533 ELSE GenDirOp(8H, src, dst)
534 END;
535 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
536 END GenOr;
538 PROCEDURE GenXor* (VAR src, dst: Item);
539 BEGIN
540 IF src.mode = Con THEN
541 IF (src.obj # NIL) OR (src.offset # 0) THEN GenConOp(30H, src, dst) END
542 ELSE GenDirOp(30H, src, dst)
543 END;
544 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
545 END GenXor;
547 PROCEDURE GenTest* (VAR x, y: Item);
548 VAR w: INTEGER;
549 BEGIN
550 ASSERT(Size[x.form] = Size[y.form]);
551 CheckSize(x.form, w);
552 IF x.mode = Con THEN
553 IF (x.mode = Reg) & (x.reg = AX) THEN
554 DevCPE.GenByte(0A8H + w); GenConst(x, FALSE)
555 ELSE
556 DevCPE.GenByte(0F6H + w); GenCExt(0, y); GenConst(x, FALSE)
557 END
558 ELSE
559 DevCPE.GenByte(84H + w);
560 IF y.mode = Reg THEN GenDExt(y, x) ELSE GenDExt(x, y) END
561 END
562 END GenTest;
564 PROCEDURE GenNeg* (VAR dst: Item; ovflchk: BOOLEAN);
565 VAR w: INTEGER;
566 BEGIN
567 CheckSize(dst.form, w); DevCPE.GenByte(0F6H + w); GenCExt(18H, dst);
568 IF ovflchk THEN DevCPE.GenByte(0CEH) END;
569 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
570 END GenNeg;
572 PROCEDURE GenNot* (VAR dst: Item);
573 VAR w: INTEGER;
574 BEGIN
575 CheckSize(dst.form, w); DevCPE.GenByte(0F6H + w); GenCExt(10H, dst);
576 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
577 END GenNot;
579 PROCEDURE GenMul* (VAR src, dst: Item; ovflchk: BOOLEAN);
580 VAR w, s, val, f2, f5, f9: INTEGER;
581 BEGIN
582 ASSERT((dst.mode = Reg) & (Size[src.form] = Size[dst.form]));
583 IF (src.mode = Con) & (src.offset = 1) THEN RETURN END;
584 IF src.form <= Int8 THEN
585 ASSERT(dst.reg = 0);
586 DevCPE.GenByte(0F6H); GenCExt(28H, src)
587 ELSIF src.mode = Con THEN
588 val := src.offset;
589 IF (src.obj = NIL) & (val # 0) & ~ovflchk THEN
590 f2 := 0; f5 := 0; f9 := 0;
591 WHILE ~ODD(val) DO val := val DIV 2; INC(f2) END;
592 WHILE val MOD 9 = 0 DO val := val DIV 9; INC(f9) END;
593 WHILE val MOD 5 = 0 DO val := val DIV 5; INC(f5) END;
594 IF ABS(val) <= 3 THEN
595 WHILE f9 > 0 DO
596 DevCPE.GenByte(8DH);
597 DevCPE.GenByte(dst.reg * 8 + 4);
598 DevCPE.GenByte(0C0H + dst.reg * 9);
599 DEC(f9)
600 END;
601 WHILE f5 > 0 DO
602 DevCPE.GenByte(8DH);
603 DevCPE.GenByte(dst.reg * 8 + 4);
604 DevCPE.GenByte(80H + dst.reg * 9);
605 DEC(f5)
606 END;
607 IF ABS(val) = 3 THEN
608 DevCPE.GenByte(8DH); DevCPE.GenByte(dst.reg * 8 + 4); DevCPE.GenByte(40H + dst.reg * 9)
609 END;
610 IF f2 > 1 THEN DevCPE.GenByte(0C1H); DevCPE.GenByte(0E0H + dst.reg); DevCPE.GenByte(f2)
611 ELSIF f2 = 1 THEN DevCPE.GenByte(1); DevCPE.GenByte(0C0H + dst.reg * 9)
612 END;
613 IF val < 0 THEN DevCPE.GenByte(0F7H); GenCExt(18H, dst) END;
614 IF dst.reg = AX THEN a1.mode := 0; a2.mode := 0 END;
615 RETURN
616 END
617 END;
618 CheckSize(src.form, w); CheckConst(src, s);
619 DevCPE.GenByte(69H + s); GenDExt(dst, dst); GenConst(src, TRUE)
620 ELSE
621 CheckSize(src.form, w);
622 DevCPE.GenByte(0FH); DevCPE.GenByte(0AFH); GenDExt(dst, src)
623 END;
624 IF ovflchk THEN DevCPE.GenByte(0CEH) END;
625 IF dst.reg = AX THEN a1.mode := 0; a2.mode := 0 END
626 END GenMul;
628 PROCEDURE GenDiv* (VAR src: Item; mod, pos: BOOLEAN);
629 VAR w, rem: INTEGER;
630 BEGIN
631 ASSERT(src.mode = Reg);
632 IF src.form >= Int32 THEN DevCPE.GenByte(99H) (* cdq *)
633 ELSIF src.form = Int16 THEN DevCPE.GenByte(66H); DevCPE.GenByte(99H) (* cwd *)
634 ELSE DevCPE.GenByte(66H); DevCPE.GenByte(98H) (* cbw *)
635 END;
636 CheckSize(src.form, w); DevCPE.GenByte(0F6H + w); GenCExt(38H, src); (* idiv src *)
637 IF src.form > Int8 THEN rem := 2 (* edx *) ELSE rem := 4 (* ah *) END;
638 IF pos THEN (* src > 0 *)
639 CheckSize(src.form, w); DevCPE.GenByte(8 + w); DevCPE.GenByte(0C0H + 9 * rem); (* or rem,rem *)
640 IF mod THEN
641 DevCPE.GenByte(79H); DevCPE.GenByte(2); (* jns end *)
642 DevCPE.GenByte(2 + w); GenCExt(8 * rem, src); (* add rem,src *)
643 ELSE
644 DevCPE.GenByte(79H); DevCPE.GenByte(1); (* jns end *)
645 DevCPE.GenByte(48H); (* dec eax *)
646 END
647 ELSE
648 CheckSize(src.form, w); DevCPE.GenByte(30H + w); GenCExt(8 * rem, src); (* xor src,rem *)
649 IF mod THEN
650 DevCPE.GenByte(79H); (* jns end *)
651 IF src.form = Int16 THEN DevCPE.GenByte(9); DevCPE.GenByte(66H) ELSE DevCPE.GenByte(8) END;
652 DevCPE.GenByte(8 + w); DevCPE.GenByte(0C0H + 9 * rem); (* or rem,rem *)
653 DevCPE.GenByte(74H); DevCPE.GenByte(4); (* je end *)
654 DevCPE.GenByte(30H + w); GenCExt(8 * rem, src); (* xor src,rem *)
655 DevCPE.GenByte(2 + w); GenCExt(8 * rem, src); (* add rem,src *)
656 ELSE
657 DevCPE.GenByte(79H); (* jns end *)
658 IF src.form = Int16 THEN DevCPE.GenByte(6); DevCPE.GenByte(66H) ELSE DevCPE.GenByte(5) END;
659 DevCPE.GenByte(8 + w); DevCPE.GenByte(0C0H + 9 * rem); (* or rem,rem *)
660 DevCPE.GenByte(74H); DevCPE.GenByte(1); (* je end *)
661 DevCPE.GenByte(48H); (* dec eax *)
662 END
663 (*
664 CheckSize(src.form, w); DevCPE.GenByte(3AH + w); GenCExt(8 * rem, src); (* cmp rem,src *)
665 IF mod THEN
666 DevCPE.GenByte(72H); DevCPE.GenByte(4); (* jb end *)
667 DevCPE.GenByte(7FH); DevCPE.GenByte(2); (* jg end *)
668 DevCPE.GenByte(2 + w); GenCExt(8 * rem, src); (* add rem,src *)
669 ELSE
670 DevCPE.GenByte(72H); DevCPE.GenByte(3); (* jb end *)
671 DevCPE.GenByte(7FH); DevCPE.GenByte(1); (* jg end *)
672 DevCPE.GenByte(48H); (* dec eax *)
673 END
674 *)
675 END;
676 a1.mode := 0; a2.mode := 0
677 END GenDiv;
679 PROCEDURE GenShiftOp* (op: INTEGER; VAR cnt, dst: Item);
680 VAR w: INTEGER;
681 BEGIN
682 CheckSize(dst.form, w);
683 IF cnt.mode = Con THEN
684 ASSERT(cnt.offset >= 0); ASSERT(cnt.obj = NIL);
685 IF cnt.offset = 1 THEN
686 IF (op = 10H) & (dst.mode = Reg) THEN (* shl r *)
687 DevCPE.GenByte(w); GenDExt(dst, dst) (* add r, r *)
688 ELSE
689 DevCPE.GenByte(0D0H + w); GenCExt(op, dst)
690 END
691 ELSIF cnt.offset > 1 THEN
692 DevCPE.GenByte(0C0H + w); GenCExt(op, dst); DevCPE.GenByte(cnt.offset)
693 END
694 ELSE
695 ASSERT((cnt.mode = Reg) & (cnt.reg = CX));
696 DevCPE.GenByte(0D2H + w); GenCExt(op, dst)
697 END;
698 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
699 END GenShiftOp;
701 PROCEDURE GenBitOp* (op: INTEGER; VAR num, dst: Item);
702 BEGIN
703 DevCPE.GenByte(0FH);
704 IF num.mode = Con THEN
705 ASSERT(num.obj = NIL);
706 DevCPE.GenByte(0BAH); GenCExt(op, dst); DevCPE.GenByte(num.offset)
707 ELSE
708 ASSERT((num.mode = Reg) & (num.form = Int32));
709 DevCPE.GenByte(83H + op); GenDExt(num, dst)
710 END;
711 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
712 END GenBitOp;
714 PROCEDURE GenSetCC* (cc: INTEGER; VAR dst: Item);
715 BEGIN
716 ASSERT((dst.form = Bool) & (cc >= 0));
717 DevCPE.GenByte(0FH); DevCPE.GenByte(90H + cc); GenCExt(0, dst);
718 IF (dst.mode # Reg) OR (dst.reg = AX) THEN a1.mode := 0; a2.mode := 0 END
719 END GenSetCC;
721 PROCEDURE GenFLoad* (VAR src: Item);
722 VAR mf: INTEGER;
723 BEGIN
724 IF src.mode = Con THEN (* predefined constants *)
725 DevCPE.GenByte(0D9H); DevCPE.GenByte(0E8H + src.offset)
726 ELSIF src.form = Int64 THEN
727 DevCPE.GenByte(0DFH); GenCExt(28H, src)
728 ELSE
729 CheckForm(src.form, mf);
730 DevCPE.GenByte(0D9H + mf); GenCExt(0, src)
731 END
732 END GenFLoad;
734 PROCEDURE GenFStore* (VAR dst: Item; pop: BOOLEAN);
735 VAR mf: INTEGER;
736 BEGIN
737 IF dst.form = Int64 THEN ASSERT(pop);
738 DevCPE.GenByte(0DFH); GenCExt(38H, dst); DevCPE.GenByte(9BH) (* wait *)
739 ELSE
740 CheckForm(dst.form, mf); DevCPE.GenByte(0D9H + mf);
741 IF pop THEN GenCExt(18H, dst); DevCPE.GenByte(9BH) (* wait *)
742 ELSE GenCExt(10H, dst)
743 END
744 END;
745 a1.mode := 0; a2.mode := 0
746 END GenFStore;
748 PROCEDURE GenFDOp* (op: INTEGER; VAR src: Item);
749 VAR mf: INTEGER;
750 BEGIN
751 IF src.mode = Reg THEN
752 DevCPE.GenByte(0DEH); DevCPE.GenByte(0C1H + op)
753 ELSE
754 CheckForm(src.form, mf);
755 DevCPE.GenByte(0D8H + mf); GenCExt(op, src)
756 END
757 END GenFDOp;
759 PROCEDURE GenFMOp* (op: INTEGER);
760 BEGIN
761 DevCPE.GenByte(0D8H + op DIV 256);
762 DevCPE.GenByte(op MOD 256);
763 IF op = 07E0H THEN a1.mode := 0; a2.mode := 0 END (* FSTSW AX *)
764 END GenFMOp;
766 PROCEDURE GenJump* (cc: INTEGER; VAR L: Label; shortjmp: BOOLEAN);
767 BEGIN
768 IF cc # ccNever THEN
769 IF shortjmp OR (L > 0) & (DevCPE.pc + 2 - L <= 128) & (cc # ccCall) THEN
770 IF cc = ccAlways THEN DevCPE.GenByte(0EBH)
771 ELSE DevCPE.GenByte(70H + cc)
772 END;
773 IF L > 0 THEN DevCPE.GenByte(L - DevCPE.pc - 1)
774 ELSE ASSERT(L = 0); L := -(DevCPE.pc + short * 1000000H); DevCPE.GenByte(0)
775 END
776 ELSE
777 IF cc = ccAlways THEN DevCPE.GenByte(0E9H)
778 ELSIF cc = ccCall THEN DevCPE.GenByte(0E8H)
779 ELSE DevCPE.GenByte(0FH); DevCPE.GenByte(80H + cc)
780 END;
781 IF L > 0 THEN GenDbl(L - DevCPE.pc - 4)
782 ELSE GenDbl(-L); L := -(DevCPE.pc - 4 + relative * 1000000H)
783 END
784 END
785 END
786 END GenJump;
788 PROCEDURE GenExtJump* (cc: INTEGER; VAR dst: Item);
789 BEGIN
790 IF cc = ccAlways THEN DevCPE.GenByte(0E9H)
791 ELSE DevCPE.GenByte(0FH); DevCPE.GenByte(80H + cc)
792 END;
793 dst.offset := 0; GenLinked(dst, relative)
794 END GenExtJump;
796 PROCEDURE GenIndJump* (VAR dst: Item);
797 BEGIN
798 DevCPE.GenByte(0FFH); GenCExt(20H, dst)
799 END GenIndJump;
801 PROCEDURE GenCaseJump* (VAR src: Item);
802 VAR link: DevCPT.LinkList; tab: INTEGER;
803 BEGIN
804 ASSERT((src.form = Int32) & (src.mode = Reg));
805 DevCPE.GenByte(0FFH); DevCPE.GenByte(24H); DevCPE.GenByte(85H + 8 * src.reg);
806 tab := (DevCPE.pc + 7) DIV 4 * 4;
807 NEW(link); link.offset := tab; link.linkadr := DevCPE.pc;
808 link.next := DevCPE.CaseLinks; DevCPE.CaseLinks := link;
809 GenDbl(absolute * 1000000H + tab);
810 WHILE DevCPE.pc < tab DO DevCPE.GenByte(90H) END;
811 END GenCaseJump;
812 (*
813 PROCEDURE GenCaseJump* (VAR src: Item; num: LONGINT; VAR tab: LONGINT);
814 VAR link: DevCPT.LinkList; else, last: LONGINT;
815 BEGIN
816 ASSERT((src.form = Int32) & (src.mode = Reg));
817 DevCPE.GenByte(0FFH); DevCPE.GenByte(24H); DevCPE.GenByte(85H + 8 * src.reg);
818 tab := (DevCPE.pc + 7) DIV 4 * 4;
819 else := tab + num * 4; last := else - 4;
820 NEW(link); link.offset := tab; link.linkadr := DevCPE.pc;
821 link.next := CaseLinks; CaseLinks := link;
822 GenDbl(absolute * 1000000H + tab);
823 WHILE DevCPE.pc < tab DO DevCPE.GenByte(90H) END;
824 WHILE DevCPE.pc < last DO GenDbl(table * 1000000H + else) END;
825 GenDbl(tableend * 1000000H + else)
826 END GenCaseJump;
827 *)
828 PROCEDURE GenCaseEntry* (VAR L: Label; last: BOOLEAN);
829 VAR typ: INTEGER;
830 BEGIN
831 IF last THEN typ := tableend * 1000000H ELSE typ := table * 1000000H END;
832 IF L > 0 THEN GenDbl(L + typ) ELSE GenDbl(-L); L := -(DevCPE.pc - 4 + typ) END
833 END GenCaseEntry;
835 PROCEDURE GenCall* (VAR dst: Item);
836 BEGIN
837 IF dst.mode IN {LProc, XProc, IProc} THEN
838 DevCPE.GenByte(0E8H);
839 IF dst.obj.mnolev >= 0 THEN (* local *)
840 IF dst.obj.adr > 0 THEN GenDbl(dst.obj.adr - DevCPE.pc - 4)
841 ELSE GenDbl(-dst.obj.adr); dst.obj.adr := -(DevCPE.pc - 4 + relative * 1000000H)
842 END
843 ELSE (* imported *)
844 dst.offset := 0; GenLinked(dst, relative)
845 END
846 ELSE DevCPE.GenByte(0FFH); GenCExt(10H, dst)
847 END;
848 a1.mode := 0; a2.mode := 0
849 END GenCall;
851 PROCEDURE GenAssert* (cc, no: INTEGER);
852 BEGIN
853 IF cc # ccAlways THEN
854 IF cc >= 0 THEN
855 DevCPE.GenByte(70H + cc); (* jcc end *)
856 IF no < 0 THEN DevCPE.GenByte(2) ELSE DevCPE.GenByte(3) END
857 END;
858 IF no < 0 THEN
859 DevCPE.GenByte(8DH); DevCPE.GenByte(0E0H - no)
860 ELSE
861 DevCPE.GenByte(8DH); DevCPE.GenByte(0F0H); DevCPE.GenByte(no)
862 END
863 END
864 END GenAssert;
866 PROCEDURE GenReturn* (val: INTEGER);
867 BEGIN
868 IF val = 0 THEN DevCPE.GenByte(0C3H)
869 ELSE DevCPE.GenByte(0C2H); GenWord(val)
870 END;
871 a1.mode := 0; a2.mode := 0
872 END GenReturn;
874 PROCEDURE LoadStr (size: INTEGER);
875 BEGIN
876 IF size = 2 THEN DevCPE.GenByte(66H) END;
877 IF size <= 1 THEN DevCPE.GenByte(0ACH) ELSE DevCPE.GenByte(0ADH) END (* lods *)
878 END LoadStr;
880 PROCEDURE StoreStr (size: INTEGER);
881 BEGIN
882 IF size = 2 THEN DevCPE.GenByte(66H) END;
883 IF size <= 1 THEN DevCPE.GenByte(0AAH) ELSE DevCPE.GenByte(0ABH) END (* stos *)
884 END StoreStr;
886 PROCEDURE ScanStr (size: INTEGER; rep: BOOLEAN);
887 BEGIN
888 IF size = 2 THEN DevCPE.GenByte(66H) END;
889 IF rep THEN DevCPE.GenByte(0F2H) END;
890 IF size <= 1 THEN DevCPE.GenByte(0AEH) ELSE DevCPE.GenByte(0AFH) END (* scas *)
891 END ScanStr;
893 PROCEDURE TestNull (size: INTEGER);
894 BEGIN
895 IF size = 2 THEN DevCPE.GenByte(66H) END;
896 IF size <= 1 THEN DevCPE.GenByte(8); DevCPE.GenByte(0C0H); (* or al,al *)
897 ELSE DevCPE.GenByte(9); DevCPE.GenByte(0C0H); (* or ax,ax *)
898 END
899 END TestNull;
901 PROCEDURE GenBlockMove* (wsize, len: INTEGER); (* len = 0: len in ECX *)
902 VAR w: INTEGER;
903 BEGIN
904 IF len = 0 THEN (* variable size move *)
905 IF wsize = 4 THEN w := 1 ELSIF wsize = 2 THEN w := 1; DevCPE.GenByte(66H) ELSE w := 0 END;
906 DevCPE.GenByte(0F3H); DevCPE.GenByte(0A4H + w); (* rep:movs *)
907 ELSE (* fixed size move *)
908 len := len * wsize;
909 IF len >= 16 THEN
910 DevCPE.GenByte(0B9H); GenDbl(len DIV 4); (* ld ecx,len/4 *)
911 DevCPE.GenByte(0F3H); DevCPE.GenByte(0A5H); (* rep:movs long*)
912 len := len MOD 4
913 END;
914 WHILE len >= 4 DO DevCPE.GenByte(0A5H); DEC(len, 4) END; (* movs long *);
915 IF len >= 2 THEN DevCPE.GenByte(66H); DevCPE.GenByte(0A5H) END; (* movs word *);
916 IF ODD(len) THEN DevCPE.GenByte(0A4H) END; (* movs byte *)
917 END
918 END GenBlockMove;
920 PROCEDURE GenBlockStore* (wsize, len: INTEGER); (* len = 0: len in ECX *)
921 VAR w: INTEGER;
922 BEGIN
923 IF len = 0 THEN (* variable size move *)
924 IF wsize = 4 THEN w := 1 ELSIF wsize = 2 THEN w := 1; DevCPE.GenByte(66H) ELSE w := 0 END;
925 DevCPE.GenByte(0F3H); DevCPE.GenByte(0AAH + w); (* rep:stos *)
926 ELSE (* fixed size move *)
927 len := len * wsize;
928 IF len >= 16 THEN
929 DevCPE.GenByte(0B9H); GenDbl(len DIV 4); (* ld ecx,len/4 *)
930 DevCPE.GenByte(0F3H); DevCPE.GenByte(0ABH); (* rep:stos long*)
931 len := len MOD 4
932 END;
933 WHILE len >= 4 DO DevCPE.GenByte(0ABH); DEC(len, 4) END; (* stos long *);
934 IF len >= 2 THEN DevCPE.GenByte(66H); DevCPE.GenByte(0ABH) END; (* stos word *);
935 IF ODD(len) THEN DevCPE.GenByte(0ABH) END; (* stos byte *)
936 END
937 END GenBlockStore;
939 PROCEDURE GenBlockComp* (wsize, len: INTEGER); (* len = 0: len in ECX *)
940 VAR w: INTEGER;
941 BEGIN
942 ASSERT(len >= 0);
943 IF len > 0 THEN DevCPE.GenByte(0B9H); GenDbl(len) END; (* ld ecx,len *)
944 IF wsize = 4 THEN w := 1 ELSIF wsize = 2 THEN w := 1; DevCPE.GenByte(66H) ELSE w := 0 END;
945 DevCPE.GenByte(0F3H); DevCPE.GenByte(0A6H + w) (* repe:cmps *)
946 END GenBlockComp;
948 PROCEDURE GenStringMove* (excl: BOOLEAN; wsize, dsize, len: INTEGER);
949 (*
950 len = 0: len in ECX, len = -1: len undefined; wsize # dsize -> convert; size = 0: opsize = 1, incsize = 2; excl: don't move 0X
951 *)
952 VAR loop, end: Label;
953 BEGIN
954 IF len > 0 THEN DevCPE.GenByte(0B9H); GenDbl(len) END; (* ld ecx,len *)
955 (* len >= 0: len IN ECX *)
956 IF (dsize = 2) & (wsize < 2) THEN DevCPE.GenByte(31H); DevCPE.GenByte(0C0H) END; (* xor eax,eax *)
957 loop := NewLbl; end := NewLbl;
958 SetLabel(loop); LoadStr(wsize);
959 IF wsize = 0 THEN DevCPE.GenByte(46H) END; (* inc esi *)
960 IF len < 0 THEN (* no limit *)
961 StoreStr(dsize); TestNull(wsize); GenJump(ccNE, loop, TRUE);
962 IF excl THEN (* dec edi *)
963 DevCPE.GenByte(4FH);
964 IF dsize # 1 THEN DevCPE.GenByte(4FH) END
965 END;
966 ELSE (* cx limit *)
967 IF excl THEN TestNull(wsize); GenJump(ccE, end, TRUE); StoreStr(dsize)
968 ELSE StoreStr(dsize); TestNull(wsize); GenJump(ccE, end, TRUE)
969 END;
970 DevCPE.GenByte(49H); (* dec ecx *)
971 GenJump(ccNE, loop, TRUE);
972 GenAssert(ccNever, copyTrap); (* trap *)
973 SetLabel(end)
974 END;
975 a1.mode := 0; a2.mode := 0
976 END GenStringMove;
978 PROCEDURE GenStringComp* (wsize, dsize: INTEGER);
979 (* wsize # dsize -> convert; size = 0: opsize = 1, incsize = 2; *)
980 VAR loop, end: Label;
981 BEGIN
982 IF (dsize = 2) & (wsize < 2) THEN DevCPE.GenByte(31H); DevCPE.GenByte(0C0H); (* xor eax,eax *) END;
983 loop := NewLbl; end := NewLbl;
984 SetLabel(loop); LoadStr(wsize);
985 IF wsize = 0 THEN DevCPE.GenByte(46H) END; (* inc esi *)
986 ScanStr(dsize, FALSE); GenJump(ccNE, end, TRUE);
987 IF dsize = 0 THEN DevCPE.GenByte(47H) END; (* inc edi *)
988 TestNull(wsize); GenJump(ccNE, loop, TRUE);
989 SetLabel(end);
990 a1.mode := 0; a2.mode := 0
991 END GenStringComp;
993 PROCEDURE GenStringLength* (wsize, len: INTEGER); (* len = 0: len in ECX, len = -1: len undefined *)
994 BEGIN
995 DevCPE.GenByte(31H); DevCPE.GenByte(0C0H); (* xor eax,eax *)
996 IF len # 0 THEN DevCPE.GenByte(0B9H); GenDbl(len) END; (* ld ecx,len *)
997 ScanStr(wsize, TRUE);
998 a1.mode := 0; a2.mode := 0
999 END GenStringLength;
1001 PROCEDURE GenStrStore* (size: INTEGER);
1002 VAR w: INTEGER;
1003 BEGIN
1004 IF size # 0 THEN
1005 IF size MOD 4 = 0 THEN w := 1; size := size DIV 4
1006 ELSIF size MOD 2 = 0 THEN w := 2; size := size DIV 2
1007 ELSE w := 0
1008 END;
1009 DevCPE.GenByte(0B9H); GenDbl(size); (* ld ecx,size *)
1010 IF w = 2 THEN DevCPE.GenByte(66H); w := 1 END
1011 ELSE w := 0
1012 END;
1013 DevCPE.GenByte(0F3H); DevCPE.GenByte(0AAH + w); (* rep:stos *)
1014 a1.mode := 0; a2.mode := 0
1015 END GenStrStore;
1017 PROCEDURE GenCode* (op: INTEGER);
1018 BEGIN
1019 DevCPE.GenByte(op);
1020 a1.mode := 0; a2.mode := 0
1021 END GenCode;
1024 PROCEDURE Init*(opt: SET);
1025 BEGIN
1026 DevCPE.Init(processor, opt);
1027 level := 0;
1028 NEW(one); one.realval := 1.0; one.intval := DevCPM.ConstNotAlloc;
1029 END Init;
1031 PROCEDURE Close*;
1032 BEGIN
1033 a1.obj := NIL; a1.typ := NIL; a2.obj := NIL; a2.typ := NIL; one := NIL;
1034 DevCPE.Close
1035 END Close;
1037 BEGIN
1038 Size[Undef] := 0;
1039 Size[Byte] := 1;
1040 Size[Bool] := 1;
1041 Size[Char8] := 1;
1042 Size[Int8] := 1;
1043 Size[Int16] := 2;
1044 Size[Int32] := 4;
1045 Size[Real32] := -4;
1046 Size[Real64] := -8;
1047 Size[Set] := 4;
1048 Size[String8] := 0;
1049 Size[NilTyp] := 4;
1050 Size[NoTyp] := 0;
1051 Size[Pointer] := 4;
1052 Size[ProcTyp] := 4;
1053 Size[Comp] := 0;
1054 Size[Char16] := 2;
1055 Size[Int64] := 8;
1056 Size[String16] := 0
1057 END DevCPL486.