AMD64.ob07 61 KB

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