AssemblyGeneratorX86.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. Copyright (c) 2018 tevador
  3. This file is part of RandomX.
  4. RandomX is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. RandomX is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with RandomX. If not, see<http://www.gnu.org/licenses/>.
  14. */
  15. //#define TRACE
  16. #include "AssemblyGeneratorX86.hpp"
  17. #include "Pcg32.hpp"
  18. #include "common.hpp"
  19. #include "instructions.hpp"
  20. namespace RandomX {
  21. static const char* regR[8] = { "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" };
  22. static const char* regR32[8] = { "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" };
  23. static const char* regF[8] = { "xmm8", "xmm9", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" };
  24. static const char* regMx = "rbp";
  25. static const char* regIc = "ebx";
  26. static const char* regIc8 = "bl";
  27. static const char* regStackBeginAddr = "rdi";
  28. static const char* regScratchpadAddr = "rsi";
  29. void AssemblyGeneratorX86::generateProgram(const void* seed) {
  30. asmCode.str(std::string()); //clear
  31. Pcg32 gen(seed);
  32. for (unsigned i = 0; i < sizeof(RegisterFile) / sizeof(Pcg32::result_type); ++i) {
  33. gen();
  34. }
  35. Instruction instr;
  36. for (unsigned i = 0; i < ProgramLength; ++i) {
  37. for (unsigned j = 0; j < sizeof(instr) / sizeof(Pcg32::result_type); ++j) {
  38. *(((uint32_t*)&instr) + j) = gen();
  39. }
  40. generateCode(instr, i);
  41. asmCode << std::endl;
  42. }
  43. if(ProgramLength > 0)
  44. asmCode << "\tjmp rx_i_0" << std::endl;
  45. }
  46. void AssemblyGeneratorX86::generateCode(Instruction& instr, int i) {
  47. asmCode << "rx_i_" << i << ": ;" << instr.getName() << std::endl;
  48. asmCode << "\tdec " << regIc << std::endl;
  49. asmCode << "\tjz rx_finish" << std::endl;
  50. auto generator = engine[instr.opcode];
  51. (this->*generator)(instr, i);
  52. }
  53. void AssemblyGeneratorX86::genar(Instruction& instr, int i) {
  54. asmCode << "\txor " << regR[instr.rega % RegistersCount] << ", 0" << std::hex << instr.addra << "h" << std::dec << std::endl;
  55. asmCode << "\tmov ecx, " << regR32[instr.rega % RegistersCount] << std::endl;
  56. asmCode << "\ttest " << regIc8 << ", 63" << std::endl;
  57. asmCode << "\tjnz short rx_body_" << i << std::endl;
  58. switch (instr.loca & 3)
  59. {
  60. case 0:
  61. case 1:
  62. case 2:
  63. asmCode << "\tcall rx_read_l1" << std::endl;
  64. asmCode << "rx_body_" << i << ":" << std::endl;
  65. if ((instr.loca & 192) == 0)
  66. asmCode << "\txor " << regMx << ", rcx" << std::endl;
  67. asmCode << "\tand ecx, " << (ScratchpadL1 - 1) << std::endl;
  68. break;
  69. default: //3
  70. asmCode << "\tcall rx_read_l2" << std::endl;
  71. asmCode << "rx_body_" << i << ":" << std::endl;
  72. if ((instr.loca & 192) == 0)
  73. asmCode << "\txor " << regMx << ", rcx" << std::endl;
  74. asmCode << "\tand ecx, " << (ScratchpadL2 - 1) << std::endl;
  75. break;
  76. }
  77. asmCode << "\tmov rax, qword ptr [" << regScratchpadAddr << "+rcx*8]" << std::endl;
  78. }
  79. void AssemblyGeneratorX86::genaf(Instruction& instr, int i) {
  80. asmCode << "\txor " << regR[instr.rega % RegistersCount] << ", 0" << std::hex << instr.addra << "h" << std::dec << std::endl;
  81. asmCode << "\tmov ecx, " << regR32[instr.rega % RegistersCount] << std::endl;
  82. asmCode << "\ttest " << regIc8 << ", 63" << std::endl;
  83. asmCode << "\tjnz short rx_body_" << i << std::endl;
  84. switch (instr.loca & 3)
  85. {
  86. case 0:
  87. case 1:
  88. case 2:
  89. asmCode << "\tcall rx_read_l1" << std::endl;
  90. asmCode << "rx_body_" << i << ":" << std::endl;
  91. if((instr.loca & 192) == 0)
  92. asmCode << "\txor " << regMx << ", rcx" << std::endl;
  93. asmCode << "\tand ecx, " << (ScratchpadL1 - 1) << std::endl;
  94. break;
  95. default: //3
  96. asmCode << "\tcall rx_read_l2" << std::endl;
  97. asmCode << "rx_body_" << i << ":" << std::endl;
  98. if ((instr.loca & 192) == 0)
  99. asmCode << "\txor " << regMx << ", rcx" << std::endl;
  100. asmCode << "\tand ecx, " << (ScratchpadL2 - 1) << std::endl;
  101. break;
  102. }
  103. asmCode << "\tcvtdq2pd xmm0, qword ptr [" << regScratchpadAddr << "+rcx*8]" << std::endl;
  104. }
  105. void AssemblyGeneratorX86::genbr0(Instruction& instr, const char* instrx86) {
  106. switch (instr.locb & 7)
  107. {
  108. case 0:
  109. case 1:
  110. case 2:
  111. case 3:
  112. asmCode << "\tmov rcx, " << regR[instr.regb % RegistersCount] << std::endl;
  113. asmCode << "\t" << instrx86 << " rax, cl" << std::endl;
  114. return;
  115. default:
  116. asmCode << "\t" << instrx86 << " rax, " << (instr.imm8 & 63) << std::endl;;
  117. return;
  118. }
  119. }
  120. void AssemblyGeneratorX86::genbr1(Instruction& instr) {
  121. switch (instr.locb & 7)
  122. {
  123. case 0:
  124. case 1:
  125. case 2:
  126. case 3:
  127. case 4:
  128. case 5:
  129. asmCode << regR[instr.regb % RegistersCount] << std::endl;
  130. return;
  131. default:
  132. asmCode << instr.imm32 << std::endl;;
  133. return;
  134. }
  135. }
  136. void AssemblyGeneratorX86::genbr132(Instruction& instr) {
  137. switch (instr.locb & 7)
  138. {
  139. case 0:
  140. case 1:
  141. case 2:
  142. case 3:
  143. case 4:
  144. case 5:
  145. asmCode << regR32[instr.regb % RegistersCount] << std::endl;
  146. return;
  147. default:
  148. asmCode << instr.imm32 << std::endl;;
  149. return;
  150. }
  151. }
  152. void AssemblyGeneratorX86::genbf(Instruction& instr, const char* instrx86) {
  153. asmCode << "\t" << instrx86 << " xmm0, " << regF[instr.regb % RegistersCount] << std::endl;
  154. }
  155. void AssemblyGeneratorX86::gencr(Instruction& instr) {
  156. switch (instr.locc & 7)
  157. {
  158. case 0:
  159. asmCode << "\tmov rcx, rax" << std::endl;
  160. asmCode << "\tmov eax, " << regR32[instr.regc % RegistersCount] << std::endl;
  161. asmCode << "\txor eax, 0" << std::hex << instr.addrc << "h" << std::dec << std::endl;
  162. asmCode << "\tand eax, " << (ScratchpadL2 - 1) << std::endl;
  163. asmCode << "\tmov qword ptr [" << regScratchpadAddr << " + rax * 8], rcx" << std::endl;
  164. if (trace) {
  165. asmCode << "\tmov qword ptr [" << regScratchpadAddr << " + " << regIc << " * 8 + 262136], rcx" << std::endl;
  166. }
  167. return;
  168. case 1:
  169. case 2:
  170. case 3:
  171. asmCode << "\tmov rcx, rax" << std::endl;
  172. asmCode << "\tmov eax, " << regR32[instr.regc % RegistersCount] << std::endl;
  173. asmCode << "\txor eax, 0" << std::hex << instr.addrc << "h" << std::dec << std::endl;
  174. asmCode << "\tand eax, " << (ScratchpadL1 - 1) << std::endl;
  175. asmCode << "\tmov qword ptr [" << regScratchpadAddr << " + rax * 8], rcx" << std::endl;
  176. if (trace) {
  177. asmCode << "\tmov qword ptr [" << regScratchpadAddr << " + " << regIc << " * 8 + 262136], rcx" << std::endl;
  178. }
  179. return;
  180. default:
  181. asmCode << "\tmov " << regR[instr.regc % RegistersCount] << ", rax" << std::endl;
  182. if (trace) {
  183. asmCode << "\tmov qword ptr [" << regScratchpadAddr << " + " << regIc << " * 8 + 262136], rax" << std::endl;
  184. }
  185. return;
  186. }
  187. }
  188. void AssemblyGeneratorX86::gencf(Instruction& instr, bool move = true) {
  189. if(move)
  190. asmCode << "\tmovaps " << regF[instr.regc % RegistersCount] << ", xmm0" << std::endl;
  191. const char* store = (instr.locc & 8) ? "movhpd" : "movlpd";
  192. switch (instr.locc & 7)
  193. {
  194. case 4:
  195. asmCode << "\tmov eax, " << regR32[instr.regc % RegistersCount] << std::endl;
  196. asmCode << "\txor eax, 0" << std::hex << instr.addrc << "h" << std::dec << std::endl;
  197. asmCode << "\tand eax, " << (ScratchpadL2 - 1) << std::endl;
  198. asmCode << "\t" << store << " qword ptr [" << regScratchpadAddr << " + rax * 8], " << regF[instr.regc % RegistersCount] << std::endl;
  199. break;
  200. case 5:
  201. case 6:
  202. case 7:
  203. asmCode << "\tmov eax, " << regR32[instr.regc % RegistersCount] << std::endl;
  204. asmCode << "\txor eax, 0" << std::hex << instr.addrc << "h" << std::dec << std::endl;
  205. asmCode << "\tand eax, " << (ScratchpadL1 - 1) << std::endl;
  206. asmCode << "\t" << store << " qword ptr [" << regScratchpadAddr << " + rax * 8], " << regF[instr.regc % RegistersCount] << std::endl;
  207. break;
  208. }
  209. if (trace) {
  210. asmCode << "\t" << store << " qword ptr [" << regScratchpadAddr << " + " << regIc << " * 8 + 262136], " << regF[instr.regc % RegistersCount] << std::endl;
  211. }
  212. }
  213. void AssemblyGeneratorX86::h_ADD_64(Instruction& instr, int i) {
  214. genar(instr, i);
  215. asmCode << "\tadd rax, ";
  216. genbr1(instr);
  217. gencr(instr);
  218. }
  219. void AssemblyGeneratorX86::h_ADD_32(Instruction& instr, int i) {
  220. genar(instr, i);
  221. asmCode << "\tadd eax, ";
  222. genbr132(instr);
  223. gencr(instr);
  224. }
  225. void AssemblyGeneratorX86::h_SUB_64(Instruction& instr, int i) {
  226. genar(instr, i);
  227. asmCode << "\tsub rax, ";
  228. genbr1(instr);
  229. gencr(instr);
  230. }
  231. void AssemblyGeneratorX86::h_SUB_32(Instruction& instr, int i) {
  232. genar(instr, i);
  233. asmCode << "\tsub eax, ";
  234. genbr132(instr);
  235. gencr(instr);
  236. }
  237. void AssemblyGeneratorX86::h_MUL_64(Instruction& instr, int i) {
  238. genar(instr, i);
  239. asmCode << "\timul rax, ";
  240. if ((instr.locb & 7) >= 6) {
  241. asmCode << "rax, ";
  242. }
  243. genbr1(instr);
  244. gencr(instr);
  245. }
  246. void AssemblyGeneratorX86::h_MULH_64(Instruction& instr, int i) {
  247. genar(instr, i);
  248. asmCode << "\tmov rcx, ";
  249. genbr1(instr);
  250. asmCode << "\tmul rcx" << std::endl;
  251. asmCode << "\tmov rax, rdx" << std::endl;
  252. gencr(instr);
  253. }
  254. void AssemblyGeneratorX86::h_MUL_32(Instruction& instr, int i) {
  255. genar(instr, i);
  256. asmCode << "\tmov ecx, eax" << std::endl;
  257. asmCode << "\tmov eax, ";
  258. genbr132(instr);
  259. asmCode << "\timul rax, rcx" << std::endl;
  260. gencr(instr);
  261. }
  262. void AssemblyGeneratorX86::h_IMUL_32(Instruction& instr, int i) {
  263. genar(instr, i);
  264. asmCode << "\tmovsxd rcx, eax" << std::endl;
  265. if ((instr.locb & 7) >= 6) {
  266. asmCode << "\tmov rax, " << instr.imm32 << std::endl;
  267. }
  268. else {
  269. asmCode << "\tmovsxd rax, " << regR32[instr.regb % RegistersCount] << std::endl;
  270. }
  271. asmCode << "\timul rax, rcx" << std::endl;
  272. gencr(instr);
  273. }
  274. void AssemblyGeneratorX86::h_IMULH_64(Instruction& instr, int i) {
  275. genar(instr, i);
  276. asmCode << "\tmov rcx, ";
  277. genbr1(instr);
  278. asmCode << "\timul rcx" << std::endl;
  279. asmCode << "\tmov rax, rdx" << std::endl;
  280. gencr(instr);
  281. }
  282. void AssemblyGeneratorX86::h_DIV_64(Instruction& instr, int i) {
  283. genar(instr, i);
  284. if ((instr.locb & 7) >= 6) {
  285. if (instr.imm32 == 0) {
  286. asmCode << "\tmov ecx, 1" << std::endl;
  287. }
  288. else {
  289. asmCode << "\tmov ecx, " << instr.imm32 << std::endl;
  290. }
  291. }
  292. else {
  293. asmCode << "\tmov ecx, 1" << std::endl;
  294. asmCode << "\tmov edx, " << regR32[instr.regb % RegistersCount] << std::endl;
  295. asmCode << "\ttest edx, edx" << std::endl;
  296. asmCode << "\tcmovne ecx, edx" << std::endl;
  297. }
  298. asmCode << "\txor edx, edx" << std::endl;
  299. asmCode << "\tdiv rcx" << std::endl;
  300. gencr(instr);
  301. }
  302. void AssemblyGeneratorX86::h_IDIV_64(Instruction& instr, int i) {
  303. genar(instr, i);
  304. asmCode << "\tmov edx, ";
  305. genbr132(instr);
  306. asmCode << "\tcmp edx, -1" << std::endl;
  307. asmCode << "\tjne short safe_idiv_" << i << std::endl;
  308. asmCode << "\tmov rcx, rax" << std::endl;
  309. asmCode << "\trol rcx, 1" << std::endl;
  310. asmCode << "\tdec rcx" << std::endl;
  311. asmCode << "\tjz short result_idiv_" << i << std::endl;
  312. asmCode << "safe_idiv_" << i << ":" << std::endl;
  313. asmCode << "\tmov ecx, 1" << std::endl;
  314. asmCode << "\ttest edx, edx" << std::endl;
  315. asmCode << "\tcmovne ecx, edx" << std::endl;
  316. asmCode << "\tmovsxd rcx, ecx" << std::endl;
  317. asmCode << "\tcqo" << std::endl;
  318. asmCode << "\tidiv rcx" << std::endl;
  319. asmCode << "result_idiv_" << i << ":" << std::endl;
  320. gencr(instr);
  321. }
  322. void AssemblyGeneratorX86::h_AND_64(Instruction& instr, int i) {
  323. genar(instr, i);
  324. asmCode << "\tand rax, ";
  325. genbr1(instr);
  326. gencr(instr);
  327. }
  328. void AssemblyGeneratorX86::h_AND_32(Instruction& instr, int i) {
  329. genar(instr, i);
  330. asmCode << "\tand eax, ";
  331. genbr132(instr);
  332. gencr(instr);
  333. }
  334. void AssemblyGeneratorX86::h_OR_64(Instruction& instr, int i) {
  335. genar(instr, i);
  336. asmCode << "\tor rax, ";
  337. genbr1(instr);
  338. gencr(instr);
  339. }
  340. void AssemblyGeneratorX86::h_OR_32(Instruction& instr, int i) {
  341. genar(instr, i);
  342. asmCode << "\tor eax, ";
  343. genbr132(instr);
  344. gencr(instr);
  345. }
  346. void AssemblyGeneratorX86::h_XOR_64(Instruction& instr, int i) {
  347. genar(instr, i);
  348. asmCode << "\txor rax, ";
  349. genbr1(instr);
  350. gencr(instr);
  351. }
  352. void AssemblyGeneratorX86::h_XOR_32(Instruction& instr, int i) {
  353. genar(instr, i);
  354. asmCode << "\txor eax, ";
  355. genbr132(instr);
  356. gencr(instr);
  357. }
  358. void AssemblyGeneratorX86::h_SHL_64(Instruction& instr, int i) {
  359. genar(instr, i);
  360. genbr0(instr, "shl");
  361. gencr(instr);
  362. }
  363. void AssemblyGeneratorX86::h_SHR_64(Instruction& instr, int i) {
  364. genar(instr, i);
  365. genbr0(instr, "shr");
  366. gencr(instr);
  367. }
  368. void AssemblyGeneratorX86::h_SAR_64(Instruction& instr, int i) {
  369. genar(instr, i);
  370. genbr0(instr, "sar");
  371. gencr(instr);
  372. }
  373. void AssemblyGeneratorX86::h_ROL_64(Instruction& instr, int i) {
  374. genar(instr, i);
  375. genbr0(instr, "rol");
  376. gencr(instr);
  377. }
  378. void AssemblyGeneratorX86::h_ROR_64(Instruction& instr, int i) {
  379. genar(instr, i);
  380. genbr0(instr, "ror");
  381. gencr(instr);
  382. }
  383. void AssemblyGeneratorX86::h_FPADD(Instruction& instr, int i) {
  384. genaf(instr, i);
  385. genbf(instr, "addpd");
  386. gencf(instr);
  387. }
  388. void AssemblyGeneratorX86::h_FPSUB(Instruction& instr, int i) {
  389. genaf(instr, i);
  390. genbf(instr, "subpd");
  391. gencf(instr);
  392. }
  393. void AssemblyGeneratorX86::h_FPMUL(Instruction& instr, int i) {
  394. genaf(instr, i);
  395. genbf(instr, "mulpd");
  396. asmCode << "\tmovaps xmm1, xmm0" << std::endl;
  397. asmCode << "\tcmpeqpd xmm1, xmm1" << std::endl;
  398. asmCode << "\tandps xmm0, xmm1" << std::endl;
  399. gencf(instr);
  400. }
  401. void AssemblyGeneratorX86::h_FPDIV(Instruction& instr, int i) {
  402. genaf(instr, i);
  403. genbf(instr, "divpd");
  404. asmCode << "\tmovaps xmm1, xmm0" << std::endl;
  405. asmCode << "\tcmpeqpd xmm1, xmm1" << std::endl;
  406. asmCode << "\tandps xmm0, xmm1" << std::endl;
  407. gencf(instr);
  408. }
  409. void AssemblyGeneratorX86::h_FPSQRT(Instruction& instr, int i) {
  410. genaf(instr, i);
  411. asmCode << "\tandps xmm0, xmm10" << std::endl;
  412. asmCode << "\tsqrtpd " << regF[instr.regc % RegistersCount] << ", xmm0" << std::endl;
  413. gencf(instr, false);
  414. }
  415. void AssemblyGeneratorX86::h_FPROUND(Instruction& instr, int i) {
  416. genar(instr, i);
  417. //asmCode << "\tmov rcx, rax" << std::endl;
  418. asmCode << "\tshl eax, 13" << std::endl;
  419. //asmCode << "\tand rcx, -2048" << std::endl;
  420. asmCode << "\tand eax, 24576" << std::endl;
  421. //asmCode << "\tmovaps " << regF[instr.regc % RegistersCount] << ", xmm0" << std::endl;
  422. asmCode << "\tor eax, 40896" << std::endl;
  423. asmCode << "\tmov dword ptr [rsp - 8], eax" << std::endl;
  424. asmCode << "\tldmxcsr dword ptr [rsp - 8]" << std::endl;
  425. }
  426. static inline const char* jumpCondition(Instruction& instr, bool invert = false) {
  427. switch ((instr.locb & 7) ^ invert)
  428. {
  429. case 0:
  430. return "jbe";
  431. case 1:
  432. return "ja";
  433. case 2:
  434. return "js";
  435. case 3:
  436. return "jns";
  437. case 4:
  438. return "jo";
  439. case 5:
  440. return "jno";
  441. case 6:
  442. return "jl";
  443. case 7:
  444. return "jge";
  445. }
  446. }
  447. void AssemblyGeneratorX86::h_CALL(Instruction& instr, int i) {
  448. genar(instr, i);
  449. asmCode << "\tcmp " << regR32[instr.regb % RegistersCount] << ", " << instr.imm32 << std::endl;
  450. asmCode << "\t" << jumpCondition(instr);
  451. asmCode << " short taken_call_" << i << std::endl;
  452. gencr(instr);
  453. asmCode << "\tjmp rx_i_" << wrapInstr(i + 1) << std::endl;
  454. asmCode << "taken_call_" << i << ":" << std::endl;
  455. if (trace) {
  456. asmCode << "\tmov qword ptr [" << regScratchpadAddr << " + " << regIc << " * 8 + 262136], rax" << std::endl;
  457. }
  458. asmCode << "\tpush rax" << std::endl;
  459. asmCode << "\tcall rx_i_" << wrapInstr(i + (instr.imm8 & 127) + 2) << std::endl;
  460. }
  461. void AssemblyGeneratorX86::h_RET(Instruction& instr, int i) {
  462. genar(instr, i);
  463. asmCode << "\tcmp rsp, " << regStackBeginAddr << std::endl;
  464. asmCode << "\tje short not_taken_ret_" << i << std::endl;
  465. asmCode << "\txor rax, qword ptr [rsp + 8]" << std::endl;
  466. gencr(instr);
  467. asmCode << "\tret 8" << std::endl;
  468. asmCode << "not_taken_ret_" << i << ":" << std::endl;
  469. gencr(instr);
  470. }
  471. #include "instructionWeights.hpp"
  472. #define INST_HANDLE(x) REPN(&AssemblyGeneratorX86::h_##x, WT(x))
  473. InstructionGenerator AssemblyGeneratorX86::engine[256] = {
  474. INST_HANDLE(ADD_64)
  475. INST_HANDLE(ADD_32)
  476. INST_HANDLE(SUB_64)
  477. INST_HANDLE(SUB_32)
  478. INST_HANDLE(MUL_64)
  479. INST_HANDLE(MULH_64)
  480. INST_HANDLE(MUL_32)
  481. INST_HANDLE(IMUL_32)
  482. INST_HANDLE(IMULH_64)
  483. INST_HANDLE(DIV_64)
  484. INST_HANDLE(IDIV_64)
  485. INST_HANDLE(AND_64)
  486. INST_HANDLE(AND_32)
  487. INST_HANDLE(OR_64)
  488. INST_HANDLE(OR_32)
  489. INST_HANDLE(XOR_64)
  490. INST_HANDLE(XOR_32)
  491. INST_HANDLE(SHL_64)
  492. INST_HANDLE(SHR_64)
  493. INST_HANDLE(SAR_64)
  494. INST_HANDLE(ROL_64)
  495. INST_HANDLE(ROR_64)
  496. INST_HANDLE(FPADD)
  497. INST_HANDLE(FPSUB)
  498. INST_HANDLE(FPMUL)
  499. INST_HANDLE(FPDIV)
  500. INST_HANDLE(FPSQRT)
  501. INST_HANDLE(FPROUND)
  502. INST_HANDLE(CALL)
  503. INST_HANDLE(RET)
  504. };
  505. }