AMD64.ob07 68 KB

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