X86.ob07 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2023, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE X86;
  7. IMPORT IL, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, PROG,
  8. CHL := CHUNKLISTS, PATHS, TARGETS, ERRORS;
  9. CONST
  10. eax = REG.R0; ecx = REG.R1; edx = REG.R2;
  11. al = eax; cl = ecx; dl = edx; ah = 4;
  12. ax = eax; cx = ecx; dx = edx;
  13. esp = 4;
  14. ebp = 5;
  15. MAX_FR = 7;
  16. sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H;
  17. je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; jnb = 83H;
  18. CODECHUNK = 8;
  19. FPR_ERR = 41;
  20. TYPE
  21. COMMAND = IL.COMMAND;
  22. ANYCODE = POINTER TO RECORD (LISTS.ITEM)
  23. offset: INTEGER
  24. END;
  25. CODE = POINTER TO RECORD (ANYCODE)
  26. code: ARRAY CODECHUNK OF BYTE;
  27. length: INTEGER
  28. END;
  29. LABEL = POINTER TO RECORD (ANYCODE)
  30. label: INTEGER
  31. END;
  32. JUMP = POINTER TO RECORD (ANYCODE)
  33. label, diff: INTEGER;
  34. short: BOOLEAN
  35. END;
  36. JMP = POINTER TO RECORD (JUMP)
  37. END;
  38. JCC = POINTER TO RECORD (JUMP)
  39. jmp: INTEGER
  40. END;
  41. CALL = POINTER TO RECORD (JUMP)
  42. END;
  43. RELOC = POINTER TO RECORD (ANYCODE)
  44. op, value: INTEGER
  45. END;
  46. VAR
  47. R: REG.REGS;
  48. program: BIN.PROGRAM;
  49. CodeList: LISTS.LIST;
  50. tcount, LocVarSize, mainLocVarSize: INTEGER;
  51. FR: ARRAY 1000 OF INTEGER;
  52. fname: PATHS.PATH;
  53. FltConstLabel, mainFltConstLabel: LABEL;
  54. PROCEDURE OutByte* (n: BYTE);
  55. VAR
  56. c: CODE;
  57. last: ANYCODE;
  58. BEGIN
  59. last := CodeList.last(ANYCODE);
  60. IF (last IS CODE) & (last(CODE).length < CODECHUNK) THEN
  61. c := last(CODE);
  62. c.code[c.length] := n;
  63. INC(c.length)
  64. ELSE
  65. NEW(c);
  66. c.code[0] := n;
  67. c.length := 1;
  68. LISTS.push(CodeList, c)
  69. END
  70. END OutByte;
  71. PROCEDURE OutInt (n: INTEGER);
  72. BEGIN
  73. OutByte(n MOD 256);
  74. OutByte(UTILS.Byte(n, 1));
  75. OutByte(UTILS.Byte(n, 2));
  76. OutByte(UTILS.Byte(n, 3))
  77. END OutInt;
  78. PROCEDURE OutByte2 (a, b: BYTE);
  79. BEGIN
  80. OutByte(a);
  81. OutByte(b)
  82. END OutByte2;
  83. PROCEDURE OutByte3 (a, b, c: BYTE);
  84. BEGIN
  85. OutByte(a);
  86. OutByte(b);
  87. OutByte(c)
  88. END OutByte3;
  89. PROCEDURE OutWord (n: INTEGER);
  90. BEGIN
  91. ASSERT((0 <= n) & (n <= 65535));
  92. OutByte2(n MOD 256, n DIV 256)
  93. END OutWord;
  94. PROCEDURE isByte* (n: INTEGER): BOOLEAN;
  95. RETURN (-128 <= n) & (n <= 127)
  96. END isByte;
  97. PROCEDURE short (n: INTEGER): INTEGER;
  98. RETURN 2 * ORD(isByte(n))
  99. END short;
  100. PROCEDURE long (n: INTEGER): INTEGER;
  101. RETURN 40H * ORD(~isByte(n))
  102. END long;
  103. PROCEDURE OutIntByte (n: INTEGER);
  104. BEGIN
  105. IF isByte(n) THEN
  106. OutByte(n MOD 256)
  107. ELSE
  108. OutInt(n)
  109. END
  110. END OutIntByte;
  111. PROCEDURE shift* (op, reg: INTEGER);
  112. BEGIN
  113. CASE op OF
  114. |IL.opASR, IL.opASR1, IL.opASR2: OutByte(0F8H + reg)
  115. |IL.opROR, IL.opROR1, IL.opROR2: OutByte(0C8H + reg)
  116. |IL.opLSL, IL.opLSL1, IL.opLSL2: OutByte(0E0H + reg)
  117. |IL.opLSR, IL.opLSR1, IL.opLSR2: OutByte(0E8H + reg)
  118. END
  119. END shift;
  120. PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *)
  121. BEGIN
  122. OutByte2(op, 0C0H + 8 * reg2 + reg1)
  123. END oprr;
  124. PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *)
  125. BEGIN
  126. oprr(89H, reg1, reg2)
  127. END mov;
  128. PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *)
  129. BEGIN
  130. IF eax IN {reg1, reg2} THEN
  131. OutByte(90H + reg1 + reg2)
  132. ELSE
  133. oprr(87H, reg1, reg2)
  134. END
  135. END xchg;
  136. PROCEDURE pop (reg: INTEGER);
  137. BEGIN
  138. OutByte(58H + reg) (* pop reg *)
  139. END pop;
  140. PROCEDURE push (reg: INTEGER);
  141. BEGIN
  142. OutByte(50H + reg) (* push reg *)
  143. END push;
  144. PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *)
  145. BEGIN
  146. oprr(31H, reg1, reg2)
  147. END xor;
  148. PROCEDURE movrc (reg, n: INTEGER);
  149. BEGIN
  150. IF n = 0 THEN
  151. xor(reg, reg)
  152. ELSE
  153. OutByte(0B8H + reg); (* mov reg, n *)
  154. OutInt(n)
  155. END
  156. END movrc;
  157. PROCEDURE pushc* (n: INTEGER);
  158. BEGIN
  159. OutByte(68H + short(n)); (* push n *)
  160. OutIntByte(n)
  161. END pushc;
  162. PROCEDURE test (reg: INTEGER);
  163. BEGIN
  164. OutByte2(85H, 0C0H + reg * 9) (* test reg, reg *)
  165. END test;
  166. PROCEDURE neg (reg: INTEGER);
  167. BEGIN
  168. OutByte2(0F7H, 0D8H + reg) (* neg reg *)
  169. END neg;
  170. PROCEDURE not (reg: INTEGER);
  171. BEGIN
  172. OutByte2(0F7H, 0D0H + reg) (* not reg *)
  173. END not;
  174. PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *)
  175. BEGIN
  176. oprr(01H, reg1, reg2)
  177. END add;
  178. PROCEDURE oprc* (op, reg, n: INTEGER);
  179. BEGIN
  180. IF (reg = eax) & ~isByte(n) THEN
  181. CASE op OF
  182. |0C0H: op := 05H (* add *)
  183. |0E8H: op := 2DH (* sub *)
  184. |0F8H: op := 3DH (* cmp *)
  185. |0E0H: op := 25H (* and *)
  186. |0C8H: op := 0DH (* or *)
  187. |0F0H: op := 35H (* xor *)
  188. END;
  189. OutByte(op);
  190. OutInt(n)
  191. ELSE
  192. OutByte2(81H + short(n), op + reg MOD 8);
  193. OutIntByte(n)
  194. END
  195. END oprc;
  196. PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *)
  197. BEGIN
  198. oprc(0E0H, reg, n)
  199. END andrc;
  200. PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *)
  201. BEGIN
  202. oprc(0C8H, reg, n)
  203. END orrc;
  204. PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *)
  205. BEGIN
  206. oprc(0F0H, reg, n)
  207. END xorrc;
  208. PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *)
  209. BEGIN
  210. oprc(0C0H, reg, n)
  211. END addrc;
  212. PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *)
  213. BEGIN
  214. oprc(0E8H, reg, n)
  215. END subrc;
  216. PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *)
  217. BEGIN
  218. IF n = 0 THEN
  219. test(reg)
  220. ELSE
  221. oprc(0F8H, reg, n)
  222. END
  223. END cmprc;
  224. PROCEDURE cmprr (reg1, reg2: INTEGER); (* cmp reg1, reg2 *)
  225. BEGIN
  226. oprr(39H, reg1, reg2)
  227. END cmprr;
  228. PROCEDURE setcc* (cc, reg: INTEGER); (* setcc reg *)
  229. BEGIN
  230. IF reg >= 8 THEN
  231. OutByte(41H)
  232. END;
  233. OutByte3(0FH, cc, 0C0H + reg MOD 8)
  234. END setcc;
  235. PROCEDURE ret*;
  236. BEGIN
  237. OutByte(0C3H)
  238. END ret;
  239. PROCEDURE drop;
  240. BEGIN
  241. REG.Drop(R)
  242. END drop;
  243. PROCEDURE GetAnyReg (): INTEGER;
  244. RETURN REG.GetAnyReg(R)
  245. END GetAnyReg;
  246. PROCEDURE cond* (op: INTEGER): INTEGER;
  247. VAR
  248. res: INTEGER;
  249. BEGIN
  250. CASE op OF
  251. |IL.opGT, IL.opGTC: res := jg
  252. |IL.opGE, IL.opGEC: res := jge
  253. |IL.opLT, IL.opLTC: res := jl
  254. |IL.opLE, IL.opLEC: res := jle
  255. |IL.opEQ, IL.opEQC: res := je
  256. |IL.opNE, IL.opNEC: res := jne
  257. END
  258. RETURN res
  259. END cond;
  260. PROCEDURE inv0* (op: INTEGER): INTEGER;
  261. RETURN ORD(BITS(op) / {0})
  262. END inv0;
  263. PROCEDURE Reloc* (op, value: INTEGER);
  264. VAR
  265. reloc: RELOC;
  266. BEGIN
  267. NEW(reloc);
  268. reloc.op := op;
  269. reloc.value := value;
  270. LISTS.push(CodeList, reloc)
  271. END Reloc;
  272. PROCEDURE PushFlt (label: LABEL; value: REAL);
  273. VAR
  274. a, b, n: INTEGER;
  275. PROCEDURE pushImm (label: LABEL; value: INTEGER);
  276. VAR
  277. c: CODE;
  278. i: INTEGER;
  279. BEGIN
  280. NEW(c);
  281. IF isByte(value) THEN
  282. c.code[0] := 6AH;
  283. c.code[1] := value MOD 256;
  284. c.length := 2
  285. ELSE
  286. c.code[0] := 68H;
  287. FOR i := 1 TO 4 DO
  288. c.code[i] := UTILS.Byte(value, i - 1)
  289. END;
  290. c.length := 5
  291. END;
  292. LISTS.insertL(CodeList, label, c)
  293. END pushImm;
  294. BEGIN
  295. n := UTILS.splitf(value, a, b);
  296. pushImm(label, b);
  297. pushImm(label, a)
  298. END PushFlt;
  299. PROCEDURE jcc* (cc, label: INTEGER);
  300. VAR
  301. j: JCC;
  302. BEGIN
  303. NEW(j);
  304. j.label := label;
  305. j.jmp := cc;
  306. j.short := FALSE;
  307. LISTS.push(CodeList, j)
  308. END jcc;
  309. PROCEDURE jmp* (label: INTEGER);
  310. VAR
  311. j: JMP;
  312. BEGIN
  313. NEW(j);
  314. j.label := label;
  315. j.short := FALSE;
  316. LISTS.push(CodeList, j)
  317. END jmp;
  318. PROCEDURE call* (label: INTEGER);
  319. VAR
  320. c: CALL;
  321. BEGIN
  322. NEW(c);
  323. c.label := label;
  324. c.short := TRUE;
  325. LISTS.push(CodeList, c)
  326. END call;
  327. PROCEDURE Pic (reg, opcode, value: INTEGER);
  328. BEGIN
  329. OutByte(0E8H); OutInt(0); (* call L
  330. L: *)
  331. pop(reg);
  332. OutByte2(081H, 0C0H + reg); (* add reg, ... *)
  333. Reloc(opcode, value)
  334. END Pic;
  335. PROCEDURE CallRTL (pic: BOOLEAN; proc: INTEGER);
  336. VAR
  337. label: INTEGER;
  338. reg1: INTEGER;
  339. BEGIN
  340. label := IL.codes.rtl[proc];
  341. IF label < 0 THEN
  342. label := -label;
  343. IF pic THEN
  344. reg1 := GetAnyReg();
  345. Pic(reg1, BIN.PICIMP, label);
  346. OutByte2(0FFH, 010H + reg1); (* call dword[reg1] *)
  347. drop
  348. ELSE
  349. OutByte2(0FFH, 015H); (* call dword[label] *)
  350. Reloc(BIN.RIMP, label)
  351. END
  352. ELSE
  353. call(label)
  354. END
  355. END CallRTL;
  356. PROCEDURE SetLabel* (label: INTEGER);
  357. VAR
  358. L: LABEL;
  359. BEGIN
  360. NEW(L);
  361. L.label := label;
  362. LISTS.push(CodeList, L)
  363. END SetLabel;
  364. PROCEDURE fixup*;
  365. VAR
  366. code: ANYCODE;
  367. count, i: INTEGER;
  368. shorted: BOOLEAN;
  369. jump: JUMP;
  370. BEGIN
  371. REPEAT
  372. shorted := FALSE;
  373. count := 0;
  374. code := CodeList.first(ANYCODE);
  375. WHILE code # NIL DO
  376. code.offset := count;
  377. CASE code OF
  378. |CODE: INC(count, code.length)
  379. |LABEL: BIN.SetLabel(program, code.label, count)
  380. |JMP: IF code.short THEN INC(count, 2) ELSE INC(count, 5) END; code.offset := count
  381. |JCC: IF code.short THEN INC(count, 2) ELSE INC(count, 6) END; code.offset := count
  382. |CALL: INC(count, 5); code.offset := count
  383. |RELOC: INC(count, 4)
  384. END;
  385. code := code.next(ANYCODE)
  386. END;
  387. code := CodeList.first(ANYCODE);
  388. WHILE code # NIL DO
  389. IF code IS JUMP THEN
  390. jump := code(JUMP);
  391. jump.diff := BIN.GetLabel(program, jump.label) - code.offset;
  392. IF ~jump.short & isByte(jump.diff) THEN
  393. jump.short := TRUE;
  394. shorted := TRUE
  395. END
  396. END;
  397. code := code.next(ANYCODE)
  398. END
  399. UNTIL ~shorted;
  400. code := CodeList.first(ANYCODE);
  401. WHILE code # NIL DO
  402. CASE code OF
  403. |CODE:
  404. FOR i := 0 TO code.length - 1 DO
  405. BIN.PutCode(program, code.code[i])
  406. END
  407. |LABEL:
  408. |JMP:
  409. IF code.short THEN
  410. BIN.PutCode(program, 0EBH);
  411. BIN.PutCode(program, code.diff MOD 256)
  412. ELSE
  413. BIN.PutCode(program, 0E9H);
  414. BIN.PutCode32LE(program, code.diff)
  415. END
  416. |JCC:
  417. IF code.short THEN
  418. BIN.PutCode(program, code.jmp - 16);
  419. BIN.PutCode(program, code.diff MOD 256)
  420. ELSE
  421. BIN.PutCode(program, 0FH);
  422. BIN.PutCode(program, code.jmp);
  423. BIN.PutCode32LE(program, code.diff)
  424. END
  425. |CALL:
  426. BIN.PutCode(program, 0E8H);
  427. BIN.PutCode32LE(program, code.diff)
  428. |RELOC:
  429. BIN.PutReloc(program, code.op);
  430. BIN.PutCode32LE(program, code.value)
  431. END;
  432. code := code.next(ANYCODE)
  433. END
  434. END fixup;
  435. PROCEDURE UnOp (VAR reg: INTEGER);
  436. BEGIN
  437. REG.UnOp(R, reg)
  438. END UnOp;
  439. PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
  440. BEGIN
  441. REG.BinOp(R, reg1, reg2)
  442. END BinOp;
  443. PROCEDURE PushAll (NumberOfParameters: INTEGER);
  444. BEGIN
  445. REG.PushAll(R);
  446. DEC(R.pushed, NumberOfParameters)
  447. END PushAll;
  448. PROCEDURE NewLabel (): INTEGER;
  449. BEGIN
  450. BIN.NewLabel(program)
  451. RETURN IL.NewLabel()
  452. END NewLabel;
  453. PROCEDURE GetRegA;
  454. BEGIN
  455. ASSERT(REG.GetReg(R, eax))
  456. END GetRegA;
  457. PROCEDURE fcmp;
  458. BEGIN
  459. GetRegA;
  460. OutByte2(0DAH, 0E9H); (* fucompp *)
  461. OutByte3(09BH, 0DFH, 0E0H); (* fstsw ax *)
  462. OutByte(09EH); (* sahf *)
  463. OutByte(0B8H); OutInt(0) (* mov eax, 0 *)
  464. END fcmp;
  465. PROCEDURE movzx* (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *)
  466. VAR
  467. b: BYTE;
  468. BEGIN
  469. OutByte2(0FH, 0B6H + ORD(word));
  470. IF (offs = 0) & (reg2 # ebp) THEN
  471. b := 0
  472. ELSE
  473. b := 40H + long(offs)
  474. END;
  475. OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8);
  476. IF reg2 = esp THEN
  477. OutByte(24H)
  478. END;
  479. IF b # 0 THEN
  480. OutIntByte(offs)
  481. END
  482. END movzx;
  483. PROCEDURE _movrm* (reg1, reg2, offs, size: INTEGER; mr: BOOLEAN);
  484. VAR
  485. b: BYTE;
  486. BEGIN
  487. IF size = 16 THEN
  488. OutByte(66H)
  489. END;
  490. IF (reg1 >= 8) OR (reg2 >= 8) OR (size = 64) THEN
  491. OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8) + 8 * ORD(size = 64))
  492. END;
  493. OutByte(8BH - 2 * ORD(mr) - ORD(size = 8));
  494. IF (offs = 0) & (reg2 # ebp) THEN
  495. b := 0
  496. ELSE
  497. b := 40H + long(offs)
  498. END;
  499. OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8);
  500. IF reg2 = esp THEN
  501. OutByte(24H)
  502. END;
  503. IF b # 0 THEN
  504. OutIntByte(offs)
  505. END
  506. END _movrm;
  507. PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2 *)
  508. BEGIN
  509. _movrm(reg2, reg1, offs, 32, TRUE)
  510. END movmr;
  511. PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, dword[reg2 + offs] *)
  512. BEGIN
  513. _movrm(reg1, reg2, offs, 32, FALSE)
  514. END movrm;
  515. PROCEDURE movmr8* (reg1, offs, reg2: INTEGER); (* mov byte[reg1+offs], reg2_8 *)
  516. BEGIN
  517. _movrm(reg2, reg1, offs, 8, TRUE)
  518. END movmr8;
  519. PROCEDURE movrm8* (reg1, reg2, offs: INTEGER); (* mov reg1_8, byte[reg2+offs] *)
  520. BEGIN
  521. _movrm(reg1, reg2, offs, 8, FALSE)
  522. END movrm8;
  523. PROCEDURE movmr16* (reg1, offs, reg2: INTEGER); (* mov word[reg1+offs], reg2_16 *)
  524. BEGIN
  525. _movrm(reg2, reg1, offs, 16, TRUE)
  526. END movmr16;
  527. PROCEDURE movrm16* (reg1, reg2, offs: INTEGER); (* mov reg1_16, word[reg2+offs] *)
  528. BEGIN
  529. _movrm(reg1, reg2, offs, 16, FALSE)
  530. END movrm16;
  531. PROCEDURE pushm* (reg, offs: INTEGER); (* push qword[reg+offs] *)
  532. VAR
  533. b: BYTE;
  534. BEGIN
  535. IF reg >= 8 THEN
  536. OutByte(41H)
  537. END;
  538. OutByte(0FFH);
  539. IF (offs = 0) & (reg # ebp) THEN
  540. b := 30H
  541. ELSE
  542. b := 70H + long(offs)
  543. END;
  544. OutByte(b + reg MOD 8);
  545. IF reg = esp THEN
  546. OutByte(24H)
  547. END;
  548. IF b # 30H THEN
  549. OutIntByte(offs)
  550. END
  551. END pushm;
  552. PROCEDURE LoadFltConst (value: REAL);
  553. BEGIN
  554. PushFlt(FltConstLabel, value);
  555. INC(LocVarSize, 8);
  556. IF FltConstLabel = mainFltConstLabel THEN
  557. mainLocVarSize := LocVarSize
  558. END;
  559. OutByte2(0DDH, 045H + long(-LocVarSize)); (* fld qword[ebp - LocVarSize] *)
  560. OutIntByte(-LocVarSize)
  561. END LoadFltConst;
  562. PROCEDURE translate (pic: BOOLEAN; stroffs, target: INTEGER);
  563. VAR
  564. cmd, next: COMMAND;
  565. reg1, reg2, reg3, fr: INTEGER;
  566. n, a, label, cc: INTEGER;
  567. opcode, param1, param2: INTEGER;
  568. float: REAL;
  569. BEGIN
  570. cmd := IL.codes.commands.first(COMMAND);
  571. fr := -1;
  572. WHILE cmd # NIL DO
  573. param1 := cmd.param1;
  574. param2 := cmd.param2;
  575. opcode := cmd.opcode;
  576. CASE opcode OF
  577. |IL.opJMP:
  578. jmp(param1)
  579. |IL.opCALL:
  580. call(param1)
  581. |IL.opCALLI:
  582. IF pic THEN
  583. reg1 := GetAnyReg();
  584. Pic(reg1, BIN.PICIMP, param1);
  585. OutByte2(0FFH, 010H + reg1); (* call dword[reg1] *)
  586. drop
  587. ELSE
  588. OutByte2(0FFH, 015H); (* call dword[L] *)
  589. Reloc(BIN.RIMP, param1)
  590. END
  591. |IL.opCALLP:
  592. UnOp(reg1);
  593. OutByte2(0FFH, 0D0H + reg1); (* call reg1 *)
  594. drop;
  595. ASSERT(R.top = -1)
  596. |IL.opFASTCALL:
  597. IF param2 = 1 THEN
  598. pop(ecx)
  599. ELSIF param2 = 2 THEN
  600. pop(ecx);
  601. pop(edx)
  602. END
  603. |IL.opPRECALL:
  604. PushAll(0);
  605. IF (param2 # 0) & (fr >= 0) THEN
  606. subrc(esp, 8)
  607. END;
  608. INC(FR[0]);
  609. FR[FR[0]] := fr + 1;
  610. WHILE fr >= 0 DO
  611. subrc(esp, 8);
  612. OutByte3(0DDH, 01CH, 024H); (* fstp qword[esp] *)
  613. DEC(fr)
  614. END;
  615. ASSERT(fr = -1)
  616. |IL.opALIGN16:
  617. ASSERT(eax IN R.regs);
  618. mov(eax, esp);
  619. andrc(esp, -16);
  620. n := (3 - param2 MOD 4) * 4;
  621. IF n > 0 THEN
  622. subrc(esp, n)
  623. END;
  624. push(eax)
  625. |IL.opRESF, IL.opRES:
  626. ASSERT(R.top = -1);
  627. ASSERT(fr = -1);
  628. n := FR[FR[0]]; DEC(FR[0]);
  629. IF opcode = IL.opRESF THEN
  630. INC(fr);
  631. IF n > 0 THEN
  632. OutByte3(0DDH, 5CH + long(n * 8), 24H);
  633. OutIntByte(n * 8); (* fstp qword[esp + n*8] *)
  634. DEC(fr);
  635. INC(n)
  636. END;
  637. IF fr + n > MAX_FR THEN
  638. ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
  639. END
  640. ELSE
  641. GetRegA
  642. END;
  643. WHILE n > 0 DO
  644. OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *)
  645. addrc(esp, 8);
  646. INC(fr);
  647. DEC(n)
  648. END
  649. |IL.opENTER:
  650. ASSERT(R.top = -1);
  651. SetLabel(param1);
  652. IF cmd.param3 > 0 THEN
  653. pop(eax);
  654. IF cmd.param3 >= 2 THEN
  655. push(edx)
  656. END;
  657. push(ecx);
  658. push(eax)
  659. END;
  660. push(ebp);
  661. mov(ebp, esp);
  662. n := param2;
  663. IF n > 4 THEN
  664. movrc(ecx, n);
  665. pushc(0); (* L: push 0 *)
  666. OutByte2(0E2H, 0FCH) (* loop L *)
  667. ELSE
  668. WHILE n > 0 DO
  669. pushc(0);
  670. DEC(n)
  671. END
  672. END;
  673. SetLabel(NewLabel());
  674. FltConstLabel := CodeList.last(LABEL);
  675. LocVarSize := param2 * 4
  676. |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
  677. IF opcode = IL.opLEAVER THEN
  678. UnOp(reg1);
  679. IF reg1 # eax THEN
  680. mov(eax, reg1)
  681. END;
  682. drop
  683. END;
  684. ASSERT(R.top = -1);
  685. IF opcode = IL.opLEAVEF THEN
  686. DEC(fr)
  687. END;
  688. ASSERT(fr = -1);
  689. IF LocVarSize > 0 THEN
  690. mov(esp, ebp)
  691. END;
  692. pop(ebp);
  693. IF param2 > 0 THEN
  694. OutByte(0C2H); OutWord(param2 * 4 MOD 65536) (* ret param2*4 *)
  695. ELSE
  696. ret
  697. END;
  698. FltConstLabel := mainFltConstLabel;
  699. LocVarSize := mainLocVarSize
  700. |IL.opPUSHC:
  701. pushc(param2)
  702. |IL.opONERR:
  703. pushc(param2);
  704. jmp(param1)
  705. |IL.opPARAM:
  706. IF param2 = 1 THEN
  707. UnOp(reg1);
  708. push(reg1);
  709. drop
  710. ELSE
  711. ASSERT(R.top + 1 <= param2);
  712. PushAll(param2)
  713. END
  714. |IL.opCLEANUP:
  715. IF param2 # 0 THEN
  716. addrc(esp, param2 * 4)
  717. END
  718. |IL.opPOPSP:
  719. pop(esp)
  720. |IL.opCONST:
  721. movrc(GetAnyReg(), param2)
  722. |IL.opLABEL:
  723. SetLabel(param1) (* L: *)
  724. |IL.opNOP, IL.opAND, IL.opOR:
  725. |IL.opGADR:
  726. next := cmd.next(COMMAND);
  727. IF next.opcode = IL.opADDC THEN
  728. INC(param2, next.param2);
  729. cmd := next
  730. END;
  731. reg1 := GetAnyReg();
  732. IF pic THEN
  733. Pic(reg1, BIN.PICBSS, param2)
  734. ELSE
  735. OutByte(0B8H + reg1); (* mov reg1, _bss + param2 *)
  736. Reloc(BIN.RBSS, param2)
  737. END
  738. |IL.opLADR:
  739. next := cmd.next(COMMAND);
  740. n := param2 * 4;
  741. IF next.opcode = IL.opADDC THEN
  742. INC(n, next.param2);
  743. cmd := next
  744. END;
  745. OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n)); (* lea reg1, dword[ebp + n] *)
  746. OutIntByte(n)
  747. |IL.opVADR, IL.opLLOAD32:
  748. movrm(GetAnyReg(), ebp, param2 * 4)
  749. |IL.opSADR:
  750. reg1 := GetAnyReg();
  751. IF pic THEN
  752. Pic(reg1, BIN.PICDATA, stroffs + param2);
  753. ELSE
  754. OutByte(0B8H + reg1); (* mov reg1, _data + stroffs + param2 *)
  755. Reloc(BIN.RDATA, stroffs + param2)
  756. END
  757. |IL.opSAVEC:
  758. UnOp(reg1);
  759. OutByte2(0C7H, reg1); OutInt(param2); (* mov dword[reg1], param2 *)
  760. drop
  761. |IL.opSAVE8C:
  762. UnOp(reg1);
  763. OutByte3(0C6H, reg1, param2 MOD 256); (* mov byte[reg1], param2 *)
  764. drop
  765. |IL.opSAVE16C:
  766. UnOp(reg1);
  767. OutByte3(66H, 0C7H, reg1); OutWord(param2 MOD 65536); (* mov word[reg1], param2 *)
  768. drop
  769. |IL.opVLOAD32:
  770. reg1 := GetAnyReg();
  771. movrm(reg1, ebp, param2 * 4);
  772. movrm(reg1, reg1, 0)
  773. |IL.opGLOAD32:
  774. reg1 := GetAnyReg();
  775. IF pic THEN
  776. Pic(reg1, BIN.PICBSS, param2);
  777. movrm(reg1, reg1, 0)
  778. ELSE
  779. OutByte2(08BH, 05H + reg1 * 8); (* mov reg1, dword[_bss + param2] *)
  780. Reloc(BIN.RBSS, param2)
  781. END
  782. |IL.opLOAD32:
  783. UnOp(reg1);
  784. movrm(reg1, reg1, 0)
  785. |IL.opVLOAD8:
  786. reg1 := GetAnyReg();
  787. movrm(reg1, ebp, param2 * 4);
  788. movzx(reg1, reg1, 0, FALSE)
  789. |IL.opGLOAD8:
  790. reg1 := GetAnyReg();
  791. IF pic THEN
  792. Pic(reg1, BIN.PICBSS, param2);
  793. movzx(reg1, reg1, 0, FALSE)
  794. ELSE
  795. OutByte3(00FH, 0B6H, 05H + reg1 * 8); (* movzx reg1, byte[_bss + param2] *)
  796. Reloc(BIN.RBSS, param2)
  797. END
  798. |IL.opLLOAD8:
  799. movzx(GetAnyReg(), ebp, param2 * 4, FALSE)
  800. |IL.opLOAD8:
  801. UnOp(reg1);
  802. movzx(reg1, reg1, 0, FALSE)
  803. |IL.opVLOAD16:
  804. reg1 := GetAnyReg();
  805. movrm(reg1, ebp, param2 * 4);
  806. movzx(reg1, reg1, 0, TRUE)
  807. |IL.opGLOAD16:
  808. reg1 := GetAnyReg();
  809. IF pic THEN
  810. Pic(reg1, BIN.PICBSS, param2);
  811. movzx(reg1, reg1, 0, TRUE)
  812. ELSE
  813. OutByte3(00FH, 0B7H, 05H + reg1 * 8); (* movzx reg1, word[_bss + param2] *)
  814. Reloc(BIN.RBSS, param2)
  815. END
  816. |IL.opLLOAD16:
  817. movzx(GetAnyReg(), ebp, param2 * 4, TRUE)
  818. |IL.opLOAD16:
  819. UnOp(reg1);
  820. movzx(reg1, reg1, 0, TRUE)
  821. |IL.opUMINUS:
  822. UnOp(reg1);
  823. neg(reg1)
  824. |IL.opADD:
  825. BinOp(reg1, reg2);
  826. add(reg1, reg2);
  827. drop
  828. |IL.opADDC:
  829. IF param2 # 0 THEN
  830. UnOp(reg1);
  831. next := cmd.next(COMMAND);
  832. CASE next.opcode OF
  833. |IL.opLOAD32:
  834. movrm(reg1, reg1, param2);
  835. cmd := next
  836. |IL.opLOAD16:
  837. movzx(reg1, reg1, param2, TRUE);
  838. cmd := next
  839. |IL.opLOAD8:
  840. movzx(reg1, reg1, param2, FALSE);
  841. cmd := next
  842. |IL.opLOAD32_PARAM:
  843. pushm(reg1, param2);
  844. drop;
  845. cmd := next
  846. ELSE
  847. IF param2 = 1 THEN
  848. OutByte(40H + reg1) (* inc reg1 *)
  849. ELSIF param2 = -1 THEN
  850. OutByte(48H + reg1) (* dec reg1 *)
  851. ELSE
  852. addrc(reg1, param2)
  853. END
  854. END
  855. END
  856. |IL.opSUB:
  857. BinOp(reg1, reg2);
  858. oprr(29H, reg1, reg2); (* sub reg1, reg2 *)
  859. drop
  860. |IL.opSUBR, IL.opSUBL:
  861. UnOp(reg1);
  862. IF param2 = 1 THEN
  863. OutByte(48H + reg1) (* dec reg1 *)
  864. ELSIF param2 = -1 THEN
  865. OutByte(40H + reg1) (* inc reg1 *)
  866. ELSIF param2 # 0 THEN
  867. subrc(reg1, param2)
  868. END;
  869. IF opcode = IL.opSUBL THEN
  870. neg(reg1)
  871. END
  872. |IL.opMULC:
  873. IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN
  874. BinOp(reg1, reg2);
  875. OutByte3(8DH, 04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2)); (* lea reg1, [reg1 + reg2 * param2] *)
  876. drop;
  877. cmd := cmd.next(COMMAND)
  878. ELSE
  879. UnOp(reg1);
  880. a := param2;
  881. IF a > 1 THEN
  882. n := UTILS.Log2(a)
  883. ELSIF a < -1 THEN
  884. n := UTILS.Log2(-a)
  885. ELSE
  886. n := -1
  887. END;
  888. IF a = 1 THEN
  889. ELSIF a = -1 THEN
  890. neg(reg1)
  891. ELSIF a = 0 THEN
  892. xor(reg1, reg1)
  893. ELSE
  894. IF n > 0 THEN
  895. IF a < 0 THEN
  896. neg(reg1)
  897. END;
  898. IF n # 1 THEN
  899. OutByte3(0C1H, 0E0H + reg1, n) (* shl reg1, n *)
  900. ELSE
  901. OutByte2(0D1H, 0E0H + reg1) (* shl reg1, 1 *)
  902. END
  903. ELSE
  904. OutByte2(69H + short(a), 0C0H + reg1 * 9); (* imul reg1, a *)
  905. OutIntByte(a)
  906. END
  907. END
  908. END
  909. |IL.opMUL:
  910. BinOp(reg1, reg2);
  911. OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); (* imul reg1, reg2 *)
  912. drop
  913. |IL.opSAVE, IL.opSAVE32:
  914. BinOp(reg2, reg1);
  915. movmr(reg1, 0, reg2);
  916. drop;
  917. drop
  918. |IL.opSAVE8:
  919. BinOp(reg2, reg1);
  920. movmr8(reg1, 0, reg2);
  921. drop;
  922. drop
  923. |IL.opSAVE16:
  924. BinOp(reg2, reg1);
  925. movmr16(reg1, 0, reg2);
  926. drop;
  927. drop
  928. |IL.opSAVEP:
  929. UnOp(reg1);
  930. IF pic THEN
  931. reg2 := GetAnyReg();
  932. Pic(reg2, BIN.PICCODE, param2);
  933. movmr(reg1, 0, reg2);
  934. drop
  935. ELSE
  936. OutByte2(0C7H, reg1); (* mov dword[reg1], L *)
  937. Reloc(BIN.RCODE, param2)
  938. END;
  939. drop
  940. |IL.opSAVEIP:
  941. UnOp(reg1);
  942. IF pic THEN
  943. reg2 := GetAnyReg();
  944. Pic(reg2, BIN.PICIMP, param2);
  945. pushm(reg2, 0);
  946. OutByte2(08FH, reg1); (* pop dword[reg1] *)
  947. drop
  948. ELSE
  949. OutByte2(0FFH, 035H); (* push dword[L] *)
  950. Reloc(BIN.RIMP, param2);
  951. OutByte2(08FH, reg1) (* pop dword[reg1] *)
  952. END;
  953. drop
  954. |IL.opPUSHP:
  955. reg1 := GetAnyReg();
  956. IF pic THEN
  957. Pic(reg1, BIN.PICCODE, param2)
  958. ELSE
  959. OutByte(0B8H + reg1); (* mov reg1, L *)
  960. Reloc(BIN.RCODE, param2)
  961. END
  962. |IL.opPUSHIP:
  963. reg1 := GetAnyReg();
  964. IF pic THEN
  965. Pic(reg1, BIN.PICIMP, param2);
  966. movrm(reg1, reg1, 0)
  967. ELSE
  968. OutByte2(08BH, 05H + reg1 * 8); (* mov reg1, dword[L] *)
  969. Reloc(BIN.RIMP, param2)
  970. END
  971. |IL.opNOT:
  972. UnOp(reg1);
  973. test(reg1);
  974. setcc(sete, reg1);
  975. andrc(reg1, 1)
  976. |IL.opORD:
  977. UnOp(reg1);
  978. test(reg1);
  979. setcc(setne, reg1);
  980. andrc(reg1, 1)
  981. |IL.opSBOOL:
  982. BinOp(reg2, reg1);
  983. test(reg2);
  984. OutByte3(0FH, 95H, reg1); (* setne byte[reg1] *)
  985. drop;
  986. drop
  987. |IL.opSBOOLC:
  988. UnOp(reg1);
  989. OutByte3(0C6H, reg1, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *)
  990. drop
  991. |IL.opEQ..IL.opGE,
  992. IL.opEQC..IL.opGEC:
  993. IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
  994. BinOp(reg1, reg2);
  995. cmprr(reg1, reg2);
  996. drop
  997. ELSE
  998. UnOp(reg1);
  999. cmprc(reg1, param2)
  1000. END;
  1001. drop;
  1002. cc := cond(opcode);
  1003. next := cmd.next(COMMAND);
  1004. IF next.opcode = IL.opJNZ THEN
  1005. jcc(cc, next.param1);
  1006. cmd := next
  1007. ELSIF next.opcode = IL.opJZ THEN
  1008. jcc(inv0(cc), next.param1);
  1009. cmd := next
  1010. ELSE
  1011. reg1 := GetAnyReg();
  1012. setcc(cc + 16, reg1);
  1013. andrc(reg1, 1)
  1014. END
  1015. |IL.opEQB, IL.opNEB:
  1016. BinOp(reg1, reg2);
  1017. drop;
  1018. test(reg1);
  1019. OutByte2(74H, 5); (* je @f *)
  1020. movrc(reg1, 1); (* mov reg1, 1
  1021. @@: *)
  1022. test(reg2);
  1023. OutByte2(74H, 5); (* je @f *)
  1024. movrc(reg2, 1); (* mov reg2, 1
  1025. @@: *)
  1026. cmprr(reg1, reg2);
  1027. IF opcode = IL.opEQB THEN
  1028. setcc(sete, reg1)
  1029. ELSE
  1030. setcc(setne, reg1)
  1031. END;
  1032. andrc(reg1, 1)
  1033. |IL.opDROP:
  1034. UnOp(reg1);
  1035. drop
  1036. |IL.opJNZ1:
  1037. UnOp(reg1);
  1038. test(reg1);
  1039. jcc(jne, param1)
  1040. |IL.opJG:
  1041. UnOp(reg1);
  1042. test(reg1);
  1043. jcc(jg, param1)
  1044. |IL.opJNZ:
  1045. UnOp(reg1);
  1046. test(reg1);
  1047. jcc(jne, param1);
  1048. drop
  1049. |IL.opJZ:
  1050. UnOp(reg1);
  1051. test(reg1);
  1052. jcc(je, param1);
  1053. drop
  1054. |IL.opSWITCH:
  1055. UnOp(reg1);
  1056. IF param2 = 0 THEN
  1057. reg2 := eax
  1058. ELSE
  1059. reg2 := ecx
  1060. END;
  1061. IF reg1 # reg2 THEN
  1062. ASSERT(REG.GetReg(R, reg2));
  1063. ASSERT(REG.Exchange(R, reg1, reg2));
  1064. drop
  1065. END;
  1066. drop
  1067. |IL.opENDSW:
  1068. |IL.opCASEL:
  1069. cmprc(eax, param1);
  1070. jcc(jl, param2)
  1071. |IL.opCASER:
  1072. cmprc(eax, param1);
  1073. jcc(jg, param2)
  1074. |IL.opCASELR:
  1075. cmprc(eax, param1);
  1076. IF param2 = cmd.param3 THEN
  1077. jcc(jne, param2)
  1078. ELSE
  1079. jcc(jl, param2);
  1080. jcc(jg, cmd.param3)
  1081. END
  1082. |IL.opCODE:
  1083. OutByte(param2)
  1084. |IL.opGET, IL.opGETC:
  1085. IF opcode = IL.opGET THEN
  1086. BinOp(reg1, reg2)
  1087. ELSIF opcode = IL.opGETC THEN
  1088. UnOp(reg2);
  1089. reg1 := GetAnyReg();
  1090. movrc(reg1, param1)
  1091. END;
  1092. drop;
  1093. drop;
  1094. IF param2 # 8 THEN
  1095. _movrm(reg1, reg1, 0, param2 * 8, FALSE);
  1096. _movrm(reg1, reg2, 0, param2 * 8, TRUE)
  1097. ELSE
  1098. PushAll(0);
  1099. push(reg1);
  1100. push(reg2);
  1101. pushc(8);
  1102. CallRTL(pic, IL._move)
  1103. END
  1104. |IL.opSAVES:
  1105. UnOp(reg2);
  1106. REG.PushAll_1(R);
  1107. IF pic THEN
  1108. reg1 := GetAnyReg();
  1109. Pic(reg1, BIN.PICDATA, stroffs + param2);
  1110. push(reg1);
  1111. drop
  1112. ELSE
  1113. OutByte(068H); (* push _data + stroffs + param2 *)
  1114. Reloc(BIN.RDATA, stroffs + param2);
  1115. END;
  1116. push(reg2);
  1117. drop;
  1118. pushc(param1);
  1119. CallRTL(pic, IL._move)
  1120. |IL.opCHKIDX:
  1121. UnOp(reg1);
  1122. cmprc(reg1, param2);
  1123. jcc(jb, param1)
  1124. |IL.opCHKIDX2:
  1125. BinOp(reg1, reg2);
  1126. IF param2 # -1 THEN
  1127. cmprr(reg2, reg1);
  1128. jcc(jb, param1)
  1129. END;
  1130. INCL(R.regs, reg1);
  1131. DEC(R.top);
  1132. R.stk[R.top] := reg2
  1133. |IL.opLEN:
  1134. n := param2;
  1135. UnOp(reg1);
  1136. drop;
  1137. EXCL(R.regs, reg1);
  1138. WHILE n > 0 DO
  1139. UnOp(reg2);
  1140. drop;
  1141. DEC(n)
  1142. END;
  1143. INCL(R.regs, reg1);
  1144. ASSERT(REG.GetReg(R, reg1))
  1145. |IL.opINCC:
  1146. UnOp(reg1);
  1147. IF param2 = 1 THEN
  1148. OutByte2(0FFH, reg1) (* inc dword[reg1] *)
  1149. ELSIF param2 = -1 THEN
  1150. OutByte2(0FFH, reg1 + 8) (* dec dword[reg1] *)
  1151. ELSE
  1152. OutByte2(81H + short(param2), reg1); OutIntByte(param2) (* add dword[reg1], param2 *)
  1153. END;
  1154. drop
  1155. |IL.opINC, IL.opDEC:
  1156. BinOp(reg1, reg2);
  1157. OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); (* add/sub dword[reg2], reg1 *)
  1158. drop;
  1159. drop
  1160. |IL.opINCCB, IL.opDECCB:
  1161. UnOp(reg1);
  1162. OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, param2 MOD 256); (* add/sub byte[reg1], n *)
  1163. drop
  1164. |IL.opINCB, IL.opDECB:
  1165. BinOp(reg1, reg2);
  1166. OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); (* add/sub byte[reg2], reg1 *)
  1167. drop;
  1168. drop
  1169. |IL.opMULS:
  1170. BinOp(reg1, reg2);
  1171. oprr(21H, reg1, reg2); (* and reg1, reg2 *)
  1172. drop
  1173. |IL.opMULSC:
  1174. UnOp(reg1);
  1175. andrc(reg1, param2)
  1176. |IL.opDIVS:
  1177. BinOp(reg1, reg2);
  1178. xor(reg1, reg2);
  1179. drop
  1180. |IL.opDIVSC:
  1181. UnOp(reg1);
  1182. xorrc(reg1, param2)
  1183. |IL.opADDS:
  1184. BinOp(reg1, reg2);
  1185. oprr(9H, reg1, reg2); (* or reg1, reg2 *)
  1186. drop
  1187. |IL.opSUBS:
  1188. BinOp(reg1, reg2);
  1189. not(reg2);
  1190. oprr(21H, reg1, reg2); (* and reg1, reg2 *)
  1191. drop
  1192. |IL.opADDSC:
  1193. UnOp(reg1);
  1194. orrc(reg1, param2)
  1195. |IL.opSUBSL:
  1196. UnOp(reg1);
  1197. not(reg1);
  1198. andrc(reg1, param2)
  1199. |IL.opSUBSR:
  1200. UnOp(reg1);
  1201. andrc(reg1, ORD(-BITS(param2)))
  1202. |IL.opUMINS:
  1203. UnOp(reg1);
  1204. not(reg1)
  1205. |IL.opLENGTH:
  1206. PushAll(2);
  1207. CallRTL(pic, IL._length);
  1208. GetRegA
  1209. |IL.opLENGTHW:
  1210. PushAll(2);
  1211. CallRTL(pic, IL._lengthw);
  1212. GetRegA
  1213. |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
  1214. UnOp(reg1);
  1215. IF reg1 # ecx THEN
  1216. ASSERT(REG.GetReg(R, ecx));
  1217. ASSERT(REG.Exchange(R, reg1, ecx));
  1218. drop
  1219. END;
  1220. BinOp(reg1, reg2);
  1221. ASSERT(reg2 = ecx);
  1222. OutByte(0D3H);
  1223. shift(opcode, reg1); (* shift reg1, cl *)
  1224. drop
  1225. |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
  1226. UnOp(reg1);
  1227. IF reg1 # ecx THEN
  1228. ASSERT(REG.GetReg(R, ecx));
  1229. ASSERT(REG.Exchange(R, reg1, ecx));
  1230. drop
  1231. END;
  1232. reg1 := GetAnyReg();
  1233. movrc(reg1, param2);
  1234. BinOp(reg1, reg2);
  1235. ASSERT(reg1 = ecx);
  1236. OutByte(0D3H);
  1237. shift(opcode, reg2); (* shift reg2, cl *)
  1238. drop;
  1239. drop;
  1240. ASSERT(REG.GetReg(R, reg2))
  1241. |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
  1242. UnOp(reg1);
  1243. n := param2 MOD 32;
  1244. IF n # 1 THEN
  1245. OutByte(0C1H)
  1246. ELSE
  1247. OutByte(0D1H)
  1248. END;
  1249. shift(opcode, reg1); (* shift reg1, n *)
  1250. IF n # 1 THEN
  1251. OutByte(n)
  1252. END
  1253. |IL.opMAX, IL.opMIN:
  1254. BinOp(reg1, reg2);
  1255. cmprr(reg1, reg2);
  1256. OutByte2(07DH + ORD(opcode = IL.opMIN), 2); (* jge/jle L *)
  1257. mov(reg1, reg2);
  1258. (* L: *)
  1259. drop
  1260. |IL.opMAXC, IL.opMINC:
  1261. UnOp(reg1);
  1262. cmprc(reg1, param2);
  1263. label := NewLabel();
  1264. IF opcode = IL.opMINC THEN
  1265. cc := jle
  1266. ELSE
  1267. cc := jge
  1268. END;
  1269. jcc(cc, label);
  1270. movrc(reg1, param2);
  1271. SetLabel(label)
  1272. |IL.opIN, IL.opINR:
  1273. IF opcode = IL.opINR THEN
  1274. reg2 := GetAnyReg();
  1275. movrc(reg2, param2)
  1276. END;
  1277. label := NewLabel();
  1278. BinOp(reg1, reg2);
  1279. cmprc(reg1, 32);
  1280. OutByte2(72H, 4); (* jb L *)
  1281. xor(reg1, reg1);
  1282. jmp(label);
  1283. (* L: *)
  1284. OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); (* bt reg2, reg1 *)
  1285. setcc(setc, reg1);
  1286. andrc(reg1, 1);
  1287. SetLabel(label);
  1288. drop
  1289. |IL.opINL:
  1290. UnOp(reg1);
  1291. OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); (* bt reg1, param2 *)
  1292. setcc(setc, reg1);
  1293. andrc(reg1, 1)
  1294. |IL.opRSET:
  1295. PushAll(2);
  1296. CallRTL(pic, IL._set);
  1297. GetRegA
  1298. |IL.opRSETR:
  1299. PushAll(1);
  1300. pushc(param2);
  1301. CallRTL(pic, IL._set);
  1302. GetRegA
  1303. |IL.opRSETL:
  1304. UnOp(reg1);
  1305. REG.PushAll_1(R);
  1306. pushc(param2);
  1307. push(reg1);
  1308. drop;
  1309. CallRTL(pic, IL._set);
  1310. GetRegA
  1311. |IL.opRSET1:
  1312. PushAll(1);
  1313. CallRTL(pic, IL._set1);
  1314. GetRegA
  1315. |IL.opINCL, IL.opEXCL:
  1316. BinOp(reg1, reg2);
  1317. cmprc(reg1, 32);
  1318. OutByte2(73H, 03H); (* jnb L *)
  1319. OutByte(0FH);
  1320. IF opcode = IL.opINCL THEN
  1321. OutByte(0ABH) (* bts dword[reg2], reg1 *)
  1322. ELSE
  1323. OutByte(0B3H) (* btr dword[reg2], reg1 *)
  1324. END;
  1325. OutByte(reg2 + 8 * reg1);
  1326. (* L: *)
  1327. drop;
  1328. drop
  1329. |IL.opINCLC:
  1330. UnOp(reg1);
  1331. OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); (* bts dword[reg1], param2 *)
  1332. drop
  1333. |IL.opEXCLC:
  1334. UnOp(reg1);
  1335. OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); (* btr dword[reg1], param2 *)
  1336. drop
  1337. |IL.opDIV:
  1338. PushAll(2);
  1339. CallRTL(pic, IL._divmod);
  1340. GetRegA
  1341. |IL.opDIVR:
  1342. n := UTILS.Log2(param2);
  1343. IF n > 0 THEN
  1344. UnOp(reg1);
  1345. IF n # 1 THEN
  1346. OutByte3(0C1H, 0F8H + reg1, n) (* sar reg1, n *)
  1347. ELSE
  1348. OutByte2(0D1H, 0F8H + reg1) (* sar reg1, 1 *)
  1349. END
  1350. ELSIF n < 0 THEN
  1351. PushAll(1);
  1352. pushc(param2);
  1353. CallRTL(pic, IL._divmod);
  1354. GetRegA
  1355. END
  1356. |IL.opDIVL:
  1357. UnOp(reg1);
  1358. REG.PushAll_1(R);
  1359. pushc(param2);
  1360. push(reg1);
  1361. drop;
  1362. CallRTL(pic, IL._divmod);
  1363. GetRegA
  1364. |IL.opMOD:
  1365. PushAll(2);
  1366. CallRTL(pic, IL._divmod);
  1367. mov(eax, edx);
  1368. GetRegA
  1369. |IL.opMODR:
  1370. n := UTILS.Log2(param2);
  1371. IF n > 0 THEN
  1372. UnOp(reg1);
  1373. andrc(reg1, param2 - 1);
  1374. ELSIF n < 0 THEN
  1375. PushAll(1);
  1376. pushc(param2);
  1377. CallRTL(pic, IL._divmod);
  1378. mov(eax, edx);
  1379. GetRegA
  1380. ELSE
  1381. UnOp(reg1);
  1382. xor(reg1, reg1)
  1383. END
  1384. |IL.opMODL:
  1385. UnOp(reg1);
  1386. REG.PushAll_1(R);
  1387. pushc(param2);
  1388. push(reg1);
  1389. drop;
  1390. CallRTL(pic, IL._divmod);
  1391. mov(eax, edx);
  1392. GetRegA
  1393. |IL.opERR:
  1394. CallRTL(pic, IL._error)
  1395. |IL.opABS:
  1396. UnOp(reg1);
  1397. test(reg1);
  1398. OutByte2(07DH, 002H); (* jge L *)
  1399. neg(reg1) (* neg reg1
  1400. L: *)
  1401. |IL.opCOPY:
  1402. IF (0 < param2) & (param2 <= 64) THEN
  1403. BinOp(reg1, reg2);
  1404. reg3 := GetAnyReg();
  1405. FOR n := 0 TO param2 - param2 MOD 4 - 1 BY 4 DO
  1406. movrm(reg3, reg1, n);
  1407. movmr(reg2, n, reg3)
  1408. END;
  1409. n := param2 - param2 MOD 4;
  1410. IF param2 MOD 4 >= 2 THEN
  1411. movrm16(reg3, reg1, n);
  1412. movmr16(reg2, n, reg3);
  1413. INC(n, 2);
  1414. DEC(param2, 2)
  1415. END;
  1416. IF param2 MOD 4 = 1 THEN
  1417. movrm8(reg3, reg1, n);
  1418. movmr8(reg2, n, reg3);
  1419. END;
  1420. drop;
  1421. drop;
  1422. drop
  1423. ELSE
  1424. PushAll(2);
  1425. pushc(param2);
  1426. CallRTL(pic, IL._move)
  1427. END
  1428. |IL.opMOVE:
  1429. PushAll(3);
  1430. CallRTL(pic, IL._move)
  1431. |IL.opCOPYA:
  1432. PushAll(4);
  1433. pushc(param2);
  1434. CallRTL(pic, IL._arrcpy);
  1435. GetRegA
  1436. |IL.opCOPYS:
  1437. PushAll(4);
  1438. pushc(param2);
  1439. CallRTL(pic, IL._strcpy)
  1440. |IL.opROT:
  1441. PushAll(0);
  1442. push(esp);
  1443. pushc(param2);
  1444. CallRTL(pic, IL._rot)
  1445. |IL.opNEW:
  1446. PushAll(1);
  1447. CASE TARGETS.OS OF
  1448. |TARGETS.osWIN32:
  1449. n := param2 + 4;
  1450. ASSERT(UTILS.Align(n, 4))
  1451. |TARGETS.osLINUX32:
  1452. n := param2 + 16;
  1453. ASSERT(UTILS.Align(n, 16))
  1454. |TARGETS.osKOS:
  1455. n := param2 + 8;
  1456. ASSERT(UTILS.Align(n, 32))
  1457. END;
  1458. pushc(n);
  1459. pushc(param1);
  1460. CallRTL(pic, IL._new)
  1461. |IL.opDISP:
  1462. PushAll(1);
  1463. CallRTL(pic, IL._dispose)
  1464. |IL.opEQS .. IL.opGES:
  1465. PushAll(4);
  1466. pushc(opcode - IL.opEQS);
  1467. CallRTL(pic, IL._strcmp);
  1468. GetRegA
  1469. |IL.opEQSW .. IL.opGESW:
  1470. PushAll(4);
  1471. pushc(opcode - IL.opEQSW);
  1472. CallRTL(pic, IL._strcmpw);
  1473. GetRegA
  1474. |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
  1475. UnOp(reg1);
  1476. CASE opcode OF
  1477. |IL.opEQP, IL.opNEP:
  1478. IF pic THEN
  1479. reg2 := GetAnyReg();
  1480. Pic(reg2, BIN.PICCODE, param1);
  1481. cmprr(reg1, reg2);
  1482. drop
  1483. ELSE
  1484. OutByte2(081H, 0F8H + reg1); (* cmp reg1, L *)
  1485. Reloc(BIN.RCODE, param1)
  1486. END
  1487. |IL.opEQIP, IL.opNEIP:
  1488. IF pic THEN
  1489. reg2 := GetAnyReg();
  1490. Pic(reg2, BIN.PICIMP, param1);
  1491. OutByte2(03BH, reg1 * 8 + reg2); (* cmp reg1, dword [reg2] *)
  1492. drop
  1493. ELSE
  1494. OutByte2(3BH, 05H + reg1 * 8); (* cmp reg1, dword[L] *)
  1495. Reloc(BIN.RIMP, param1)
  1496. END
  1497. END;
  1498. drop;
  1499. reg1 := GetAnyReg();
  1500. CASE opcode OF
  1501. |IL.opEQP, IL.opEQIP: setcc(sete, reg1)
  1502. |IL.opNEP, IL.opNEIP: setcc(setne, reg1)
  1503. END;
  1504. andrc(reg1, 1)
  1505. |IL.opPUSHT:
  1506. UnOp(reg1);
  1507. movrm(GetAnyReg(), reg1, -4)
  1508. |IL.opISREC:
  1509. PushAll(2);
  1510. IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
  1511. param2 := param2*tcount
  1512. END;
  1513. pushc(param2);
  1514. CallRTL(pic, IL._isrec);
  1515. GetRegA
  1516. |IL.opIS:
  1517. PushAll(1);
  1518. IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
  1519. param2 := param2*tcount
  1520. END;
  1521. pushc(param2);
  1522. CallRTL(pic, IL._is);
  1523. GetRegA
  1524. |IL.opTYPEGR:
  1525. PushAll(1);
  1526. IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
  1527. param2 := param2*tcount
  1528. END;
  1529. pushc(param2);
  1530. CallRTL(pic, IL._guardrec);
  1531. GetRegA
  1532. |IL.opTYPEGP:
  1533. UnOp(reg1);
  1534. PushAll(0);
  1535. push(reg1);
  1536. IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
  1537. param2 := param2*tcount
  1538. END;
  1539. pushc(param2);
  1540. CallRTL(pic, IL._guard);
  1541. GetRegA
  1542. |IL.opTYPEGD:
  1543. UnOp(reg1);
  1544. PushAll(0);
  1545. pushm(reg1, -4);
  1546. IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
  1547. param2 := param2*tcount
  1548. END;
  1549. pushc(param2);
  1550. CallRTL(pic, IL._guardrec);
  1551. GetRegA
  1552. |IL.opCASET:
  1553. push(ecx);
  1554. push(ecx);
  1555. IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
  1556. param2 := param2*tcount
  1557. END;
  1558. pushc(param2);
  1559. CallRTL(pic, IL._guardrec);
  1560. pop(ecx);
  1561. test(eax);
  1562. jcc(jne, param1)
  1563. |IL.opPACK:
  1564. BinOp(reg1, reg2);
  1565. push(reg2);
  1566. OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *)
  1567. OutByte2(0DDH, reg1); (* fld qword[reg1] *)
  1568. OutByte2(0D9H, 0FDH); (* fscale *)
  1569. OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
  1570. OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *)
  1571. pop(reg2);
  1572. drop;
  1573. drop
  1574. |IL.opPACKC:
  1575. UnOp(reg1);
  1576. pushc(param2);
  1577. OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *)
  1578. OutByte2(0DDH, reg1); (* fld qword[reg1] *)
  1579. OutByte2(0D9H, 0FDH); (* fscale *)
  1580. OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
  1581. OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *)
  1582. pop(reg1);
  1583. drop
  1584. |IL.opUNPK:
  1585. BinOp(reg1, reg2);
  1586. OutByte2(0DDH, reg1); (* fld qword[reg1] *)
  1587. OutByte2(0D9H, 0F4H); (* fxtract *)
  1588. OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
  1589. OutByte2(0DBH, 018H + reg2); (* fistp dword[reg2] *)
  1590. drop;
  1591. drop
  1592. |IL.opPUSHF:
  1593. ASSERT(fr >= 0);
  1594. DEC(fr);
  1595. subrc(esp, 8);
  1596. OutByte3(0DDH, 01CH, 024H) (* fstp qword[esp] *)
  1597. |IL.opLOADF:
  1598. INC(fr);
  1599. IF fr > MAX_FR THEN
  1600. ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
  1601. END;
  1602. UnOp(reg1);
  1603. OutByte2(0DDH, reg1); (* fld qword[reg1] *)
  1604. drop
  1605. |IL.opCONSTF:
  1606. INC(fr);
  1607. IF fr > MAX_FR THEN
  1608. ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
  1609. END;
  1610. float := cmd.float;
  1611. IF float = 0.0 THEN
  1612. OutByte2(0D9H, 0EEH) (* fldz *)
  1613. ELSIF float = 1.0 THEN
  1614. OutByte2(0D9H, 0E8H) (* fld1 *)
  1615. ELSIF float = -1.0 THEN
  1616. OutByte2(0D9H, 0E8H); (* fld1 *)
  1617. OutByte2(0D9H, 0E0H) (* fchs *)
  1618. ELSE
  1619. LoadFltConst(float)
  1620. END
  1621. |IL.opSAVEF, IL.opSAVEFI:
  1622. ASSERT(fr >= 0);
  1623. DEC(fr);
  1624. UnOp(reg1);
  1625. OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
  1626. drop
  1627. |IL.opADDF:
  1628. ASSERT(fr >= 1);
  1629. DEC(fr);
  1630. OutByte2(0DEH, 0C1H) (* faddp st1, st *)
  1631. |IL.opSUBF:
  1632. ASSERT(fr >= 1);
  1633. DEC(fr);
  1634. OutByte2(0DEH, 0E9H) (* fsubp st1, st *)
  1635. |IL.opSUBFI:
  1636. ASSERT(fr >= 1);
  1637. DEC(fr);
  1638. OutByte2(0DEH, 0E1H) (* fsubrp st1, st *)
  1639. |IL.opMULF:
  1640. ASSERT(fr >= 1);
  1641. DEC(fr);
  1642. OutByte2(0DEH, 0C9H) (* fmulp st1, st *)
  1643. |IL.opDIVF:
  1644. ASSERT(fr >= 1);
  1645. DEC(fr);
  1646. OutByte2(0DEH, 0F9H) (* fdivp st1, st *)
  1647. |IL.opDIVFI:
  1648. ASSERT(fr >= 1);
  1649. DEC(fr);
  1650. OutByte2(0DEH, 0F1H) (* fdivrp st1, st *)
  1651. |IL.opUMINF:
  1652. ASSERT(fr >= 0);
  1653. OutByte2(0D9H, 0E0H) (* fchs *)
  1654. |IL.opFABS:
  1655. ASSERT(fr >= 0);
  1656. OutByte2(0D9H, 0E1H) (* fabs *)
  1657. |IL.opFLT:
  1658. INC(fr);
  1659. IF fr > MAX_FR THEN
  1660. ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
  1661. END;
  1662. UnOp(reg1);
  1663. push(reg1);
  1664. OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *)
  1665. pop(reg1);
  1666. drop
  1667. |IL.opFLOOR:
  1668. ASSERT(fr >= 0);
  1669. DEC(fr);
  1670. subrc(esp, 8);
  1671. OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H); (* fstcw word[esp+4] *)
  1672. OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H); (* fstcw word[esp+6] *)
  1673. OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH); (* and word[esp+4], 1111001111111111b *)
  1674. OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H); (* or word[esp+4], 0000010000000000b *)
  1675. OutByte2(0D9H, 06CH); OutByte2(024H, 004H); (* fldcw word[esp+4] *)
  1676. OutByte2(0D9H, 0FCH); (* frndint *)
  1677. OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *)
  1678. pop(GetAnyReg());
  1679. OutByte2(0D9H, 06CH); OutByte2(024H, 002H); (* fldcw word[esp+2] *)
  1680. addrc(esp, 4)
  1681. |IL.opEQF:
  1682. ASSERT(fr >= 1);
  1683. DEC(fr, 2);
  1684. fcmp;
  1685. OutByte2(07AH, 003H); (* jp L *)
  1686. setcc(sete, al)
  1687. (* L: *)
  1688. |IL.opNEF:
  1689. ASSERT(fr >= 1);
  1690. DEC(fr, 2);
  1691. fcmp;
  1692. OutByte2(07AH, 003H); (* jp L *)
  1693. setcc(setne, al)
  1694. (* L: *)
  1695. |IL.opLTF:
  1696. ASSERT(fr >= 1);
  1697. DEC(fr, 2);
  1698. fcmp;
  1699. OutByte2(07AH, 00EH); (* jp L *)
  1700. setcc(setc, al);
  1701. setcc(sete, ah);
  1702. test(eax);
  1703. setcc(sete, al);
  1704. andrc(eax, 1)
  1705. (* L: *)
  1706. |IL.opGTF:
  1707. ASSERT(fr >= 1);
  1708. DEC(fr, 2);
  1709. fcmp;
  1710. OutByte2(07AH, 00FH); (* jp L *)
  1711. setcc(setc, al);
  1712. setcc(sete, ah);
  1713. cmprc(eax, 1);
  1714. setcc(sete, al);
  1715. andrc(eax, 1)
  1716. (* L: *)
  1717. |IL.opLEF:
  1718. ASSERT(fr >= 1);
  1719. DEC(fr, 2);
  1720. fcmp;
  1721. OutByte2(07AH, 003H); (* jp L *)
  1722. setcc(setnc, al)
  1723. (* L: *)
  1724. |IL.opGEF:
  1725. ASSERT(fr >= 1);
  1726. DEC(fr, 2);
  1727. fcmp;
  1728. OutByte2(07AH, 010H); (* jp L *)
  1729. setcc(setc, al);
  1730. setcc(sete, ah);
  1731. OutByte2(000H, 0E0H); (* add al, ah *)
  1732. OutByte2(03CH, 001H); (* cmp al, 1 *)
  1733. setcc(sete, al);
  1734. andrc(eax, 1)
  1735. (* L: *)
  1736. |IL.opINF:
  1737. INC(fr);
  1738. IF fr > MAX_FR THEN
  1739. ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
  1740. END;
  1741. LoadFltConst(UTILS.inf)
  1742. |IL.opLADR_UNPK:
  1743. n := param2 * 4;
  1744. reg1 := GetAnyReg();
  1745. OutByte2(8DH, 45H + reg1 * 8 + long(n)); (* lea reg1, dword[ebp + n] *)
  1746. OutIntByte(n);
  1747. BinOp(reg1, reg2);
  1748. OutByte2(0DDH, reg1); (* fld qword[reg1] *)
  1749. OutByte2(0D9H, 0F4H); (* fxtract *)
  1750. OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
  1751. OutByte2(0DBH, 018H + reg2); (* fistp dword[reg2] *)
  1752. drop;
  1753. drop
  1754. |IL.opSADR_PARAM:
  1755. IF pic THEN
  1756. reg1 := GetAnyReg();
  1757. Pic(reg1, BIN.PICDATA, stroffs + param2);
  1758. push(reg1);
  1759. drop
  1760. ELSE
  1761. OutByte(068H); (* push _data + stroffs + param2 *)
  1762. Reloc(BIN.RDATA, stroffs + param2)
  1763. END
  1764. |IL.opVADR_PARAM, IL.opLLOAD32_PARAM:
  1765. pushm(ebp, param2 * 4)
  1766. |IL.opCONST_PARAM:
  1767. pushc(param2)
  1768. |IL.opGLOAD32_PARAM:
  1769. IF pic THEN
  1770. reg1 := GetAnyReg();
  1771. Pic(reg1, BIN.PICBSS, param2);
  1772. pushm(reg1, 0);
  1773. drop
  1774. ELSE
  1775. OutByte2(0FFH, 035H); (* push dword[_bss + param2] *)
  1776. Reloc(BIN.RBSS, param2)
  1777. END
  1778. |IL.opLOAD32_PARAM:
  1779. UnOp(reg1);
  1780. pushm(reg1, 0);
  1781. drop
  1782. |IL.opGADR_SAVEC:
  1783. IF pic THEN
  1784. reg1 := GetAnyReg();
  1785. Pic(reg1, BIN.PICBSS, param1);
  1786. OutByte2(0C7H, reg1); (* mov dword[reg1], param2 *)
  1787. OutInt(param2);
  1788. drop
  1789. ELSE
  1790. OutByte2(0C7H, 05H); (* mov dword[_bss + param1], param2 *)
  1791. Reloc(BIN.RBSS, param1);
  1792. OutInt(param2)
  1793. END
  1794. |IL.opLADR_SAVEC:
  1795. n := param1 * 4;
  1796. OutByte2(0C7H, 45H + long(n)); (* mov dword[ebp + n], param2 *)
  1797. OutIntByte(n);
  1798. OutInt(param2)
  1799. |IL.opLADR_SAVE:
  1800. UnOp(reg1);
  1801. movmr(ebp, param2 * 4, reg1);
  1802. drop
  1803. |IL.opLADR_INCC:
  1804. n := param1 * 4;
  1805. IF ABS(param2) = 1 THEN
  1806. OutByte2(0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec dword[ebp + n] *)
  1807. OutIntByte(n)
  1808. ELSE
  1809. OutByte2(81H + short(param2), 45H + long(n)); (* add dword[ebp + n], param2 *)
  1810. OutIntByte(n);
  1811. OutIntByte(param2)
  1812. END
  1813. |IL.opLADR_INCCB, IL.opLADR_DECCB:
  1814. n := param1 * 4;
  1815. IF param2 = 1 THEN
  1816. OutByte2(0FEH, 45H + 8 * ORD(opcode = IL.opLADR_DECCB) + long(n)); (* inc/dec byte[ebp + n] *)
  1817. OutIntByte(n)
  1818. ELSE
  1819. OutByte2(80H, 45H + 28H * ORD(opcode = IL.opLADR_DECCB) + long(n)); (* add/sub byte[ebp + n], param2 *)
  1820. OutIntByte(n);
  1821. OutByte(param2 MOD 256)
  1822. END
  1823. |IL.opLADR_INC, IL.opLADR_DEC:
  1824. n := param2 * 4;
  1825. UnOp(reg1);
  1826. OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); (* add/sub dword[ebp + n], reg1 *)
  1827. OutIntByte(n);
  1828. drop
  1829. |IL.opLADR_INCB, IL.opLADR_DECB:
  1830. n := param2 * 4;
  1831. UnOp(reg1);
  1832. OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); (* add/sub byte[ebp + n], reg1 *)
  1833. OutIntByte(n);
  1834. drop
  1835. |IL.opLADR_INCL, IL.opLADR_EXCL:
  1836. n := param2 * 4;
  1837. UnOp(reg1);
  1838. cmprc(reg1, 32);
  1839. label := NewLabel();
  1840. jcc(jnb, label);
  1841. OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); (* bts(r) dword[ebp + n], reg1 *)
  1842. OutIntByte(n);
  1843. SetLabel(label);
  1844. drop
  1845. |IL.opLADR_INCLC, IL.opLADR_EXCLC:
  1846. n := param1 * 4;
  1847. OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); (* bts(r) dword[ebp + n], param2 *)
  1848. OutIntByte(n);
  1849. OutByte(param2)
  1850. |IL.opFNAME:
  1851. fname := cmd(IL.FNAMECMD).fname
  1852. END;
  1853. cmd := cmd.next(COMMAND)
  1854. END;
  1855. ASSERT(R.pushed = 0);
  1856. ASSERT(R.top = -1);
  1857. ASSERT(fr = -1)
  1858. END translate;
  1859. PROCEDURE prolog (pic: BOOLEAN; target, stack, dllret: INTEGER): INTEGER;
  1860. VAR
  1861. reg1, entry, L, dcount: INTEGER;
  1862. BEGIN
  1863. entry := NewLabel();
  1864. SetLabel(entry);
  1865. dcount := CHL.Length(IL.codes.data);
  1866. push(ebp);
  1867. mov(ebp, esp);
  1868. SetLabel(NewLabel());
  1869. mainFltConstLabel := CodeList.last(LABEL);
  1870. FltConstLabel := mainFltConstLabel;
  1871. mainLocVarSize := 0;
  1872. LocVarSize := 0;
  1873. IF target IN {TARGETS.Win32DLL, TARGETS.KolibriOSDrv} THEN
  1874. IF target = TARGETS.Win32DLL THEN
  1875. pushm(ebp, 16)
  1876. ELSE
  1877. pushc(0)
  1878. END;
  1879. pushm(ebp, 12);
  1880. pushm(ebp, 8);
  1881. CallRTL(pic, IL._dllentry);
  1882. test(eax);
  1883. jcc(je, dllret);
  1884. pushc(0)
  1885. ELSIF target = TARGETS.KolibriOSDLL THEN
  1886. OutByte(68H); (* push IMPORT *)
  1887. Reloc(BIN.IMPTAB, 0)
  1888. ELSIF target = TARGETS.KolibriOS THEN
  1889. reg1 := GetAnyReg();
  1890. Pic(reg1, BIN.IMPTAB, 0);
  1891. push(reg1); (* push IMPORT *)
  1892. drop
  1893. ELSIF target = TARGETS.Linux32 THEN
  1894. mov(eax, ebp);
  1895. addrc(eax, 4);
  1896. push(eax)
  1897. ELSE
  1898. pushc(0)
  1899. END;
  1900. IF pic THEN
  1901. reg1 := GetAnyReg();
  1902. Pic(reg1, BIN.PICCODE, entry);
  1903. push(reg1); (* push CODE *)
  1904. Pic(reg1, BIN.PICDATA, 0);
  1905. push(reg1); (* push _data *)
  1906. pushc(tcount);
  1907. Pic(reg1, BIN.PICDATA, tcount * 4 + dcount);
  1908. push(reg1); (* push _data + tcount * 4 + dcount *)
  1909. drop
  1910. ELSE
  1911. OutByte(68H); (* push CODE *)
  1912. Reloc(BIN.RCODE, entry);
  1913. OutByte(68H); (* push _data *)
  1914. Reloc(BIN.RDATA, 0);
  1915. pushc(tcount);
  1916. OutByte(68H); (* push _data + tcount * 4 + dcount *)
  1917. Reloc(BIN.RDATA, tcount * 4 + dcount)
  1918. END;
  1919. CallRTL(pic, IL._init);
  1920. IF target IN {TARGETS.Win32C, TARGETS.Win32GUI, TARGETS.Linux32} THEN
  1921. L := NewLabel();
  1922. pushc(0);
  1923. push(esp);
  1924. pushc(1024 * 1024 * stack);
  1925. pushc(0);
  1926. CallRTL(pic, IL._new);
  1927. pop(eax);
  1928. test(eax);
  1929. jcc(je, L);
  1930. addrc(eax, 1024 * 1024 * stack - 4);
  1931. mov(esp, eax);
  1932. SetLabel(L)
  1933. END
  1934. RETURN entry
  1935. END prolog;
  1936. PROCEDURE epilog (pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret, sofinit: INTEGER);
  1937. VAR
  1938. exp: IL.EXPORT_PROC;
  1939. path, name, ext: PATHS.PATH;
  1940. dcount, i: INTEGER;
  1941. PROCEDURE _import (imp: LISTS.LIST);
  1942. VAR
  1943. lib: IL.IMPORT_LIB;
  1944. proc: IL.IMPORT_PROC;
  1945. BEGIN
  1946. lib := imp.first(IL.IMPORT_LIB);
  1947. WHILE lib # NIL DO
  1948. BIN.Import(program, lib.name, 0);
  1949. proc := lib.procs.first(IL.IMPORT_PROC);
  1950. WHILE proc # NIL DO
  1951. BIN.Import(program, proc.name, proc.label);
  1952. proc := proc.next(IL.IMPORT_PROC)
  1953. END;
  1954. lib := lib.next(IL.IMPORT_LIB)
  1955. END
  1956. END _import;
  1957. BEGIN
  1958. IF target IN {TARGETS.Win32C, TARGETS.Win32GUI, TARGETS.KolibriOS, TARGETS.Linux32} THEN
  1959. pushc(0);
  1960. CallRTL(pic, IL._exit);
  1961. ELSIF target = TARGETS.Win32DLL THEN
  1962. SetLabel(dllret);
  1963. movrc(eax, 1);
  1964. OutByte(0C9H); (* leave *)
  1965. OutByte3(0C2H, 0CH, 0) (* ret 12 *)
  1966. ELSIF target = TARGETS.KolibriOSDrv THEN
  1967. OutByte(0C9H); (* leave *)
  1968. ret;
  1969. SetLabel(dllret);
  1970. movrc(eax, 0);
  1971. OutByte(0C9H); (* leave *)
  1972. ret
  1973. ELSIF target = TARGETS.KolibriOSDLL THEN
  1974. movrc(eax, 1);
  1975. OutByte(0C9H); (* leave *)
  1976. ret
  1977. ELSIF target = TARGETS.KolibriOSKer THEN
  1978. OutByte(0C9H); (* leave *)
  1979. ret;
  1980. ELSIF target = TARGETS.Linux32SO THEN
  1981. OutByte(0C9H); (* leave *)
  1982. ret;
  1983. SetLabel(sofinit);
  1984. CallRTL(pic, IL._sofinit);
  1985. ret
  1986. END;
  1987. fixup;
  1988. dcount := CHL.Length(IL.codes.data);
  1989. FOR i := 0 TO tcount - 1 DO
  1990. BIN.PutData32LE(program, CHL.GetInt(IL.codes.types, i))
  1991. END;
  1992. FOR i := 0 TO dcount - 1 DO
  1993. BIN.PutData(program, CHL.GetByte(IL.codes.data, i))
  1994. END;
  1995. program.modname := CHL.Length(program.data);
  1996. PATHS.split(modname, path, name, ext);
  1997. BIN.PutDataStr(program, name);
  1998. BIN.PutDataStr(program, ext);
  1999. BIN.PutData(program, 0);
  2000. IF target = TARGETS.KolibriOSDLL THEN
  2001. BIN.Export(program, "lib_init", dllinit);
  2002. END;
  2003. exp := IL.codes.export.first(IL.EXPORT_PROC);
  2004. WHILE exp # NIL DO
  2005. BIN.Export(program, exp.name, exp.label);
  2006. exp := exp.next(IL.EXPORT_PROC)
  2007. END;
  2008. _import(IL.codes._import);
  2009. IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4)));
  2010. BIN.SetParams(program, IL.codes.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536))
  2011. END epilog;
  2012. PROCEDURE align16* (bit64: BOOLEAN);
  2013. BEGIN
  2014. IF TARGETS.WinLin THEN
  2015. WHILE CHL.Length(IL.codes.data) MOD 16 # 0 DO
  2016. CHL.PushByte(IL.codes.data, 0)
  2017. END;
  2018. WHILE CHL.Length(IL.codes.types) MOD (4 - 2*ORD(bit64)) # 0 DO
  2019. CHL.PushInt(IL.codes.types, 0)
  2020. END
  2021. END
  2022. END align16;
  2023. PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
  2024. VAR
  2025. dllret, dllinit, sofinit: INTEGER;
  2026. opt: PROG.OPTIONS;
  2027. BEGIN
  2028. FR[0] := 0;
  2029. align16(FALSE);
  2030. tcount := CHL.Length(IL.codes.types);
  2031. opt := options;
  2032. CodeList := LISTS.create(NIL);
  2033. program := BIN.create(IL.codes.lcount);
  2034. dllret := NewLabel();
  2035. sofinit := NewLabel();
  2036. IF target = TARGETS.KolibriOSDLL THEN
  2037. opt.pic := FALSE
  2038. END;
  2039. IF target IN {TARGETS.KolibriOSKer, TARGETS.KolibriOSDrv} THEN
  2040. opt.pic := TRUE
  2041. END;
  2042. IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32} THEN
  2043. opt.pic := TRUE
  2044. END;
  2045. REG.Init(R, push, pop, mov, xchg, {eax, ecx, edx});
  2046. dllinit := prolog(opt.pic, target, opt.stack, dllret);
  2047. translate(opt.pic, tcount * 4, target);
  2048. epilog(opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit);
  2049. BIN.fixup(program);
  2050. IF TARGETS.OS = TARGETS.osWIN32 THEN
  2051. PE32.write(program, outname, target = TARGETS.Win32C, target = TARGETS.Win32DLL, FALSE, opt.PE32FileAlignment)
  2052. ELSIF target = TARGETS.KolibriOSDrv THEN
  2053. PE32.write(program, outname, FALSE, TRUE, FALSE, 512)
  2054. ELSIF target IN {TARGETS.KolibriOS, TARGETS.KolibriOSKer} THEN
  2055. KOS.write(program, outname, target = TARGETS.KolibriOSKer)
  2056. ELSIF target = TARGETS.KolibriOSDLL THEN
  2057. MSCOFF.write(program, outname, opt.version)
  2058. ELSIF TARGETS.OS = TARGETS.osLINUX32 THEN
  2059. ELF.write(program, outname, sofinit, target = TARGETS.Linux32SO, FALSE)
  2060. END
  2061. END CodeGen;
  2062. PROCEDURE SetProgram* (prog: BIN.PROGRAM);
  2063. BEGIN
  2064. program := prog;
  2065. CodeList := LISTS.create(NIL)
  2066. END SetProgram;
  2067. END X86.