2
0

CPL486.txt 33 KB

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