X86.ob07 72 KB

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