JitCompilerX86.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  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 MAGIC_DIVISION
  16. #include "JitCompilerX86.hpp"
  17. #include "Pcg32.hpp"
  18. #include <cstring>
  19. #include <stdexcept>
  20. #ifdef MAGIC_DIVISION
  21. #include "divideByConstantCodegen.h"
  22. #endif
  23. #ifdef _WIN32
  24. #include <windows.h>
  25. #else
  26. #include <sys/types.h>
  27. #include <sys/mman.h>
  28. #ifndef MAP_ANONYMOUS
  29. #define MAP_ANONYMOUS MAP_ANON
  30. #endif
  31. #endif
  32. namespace RandomX {
  33. #if !defined(_M_X64) && !defined(__x86_64__)
  34. JitCompilerX86::JitCompilerX86() {
  35. throw std::runtime_error("JIT compiler only supports x86-64 CPUs");
  36. }
  37. void JitCompilerX86::generateProgram(Pcg32& gen) {
  38. }
  39. size_t JitCompilerX86::getCodeSize() {
  40. return 0;
  41. }
  42. #else
  43. /*
  44. REGISTER ALLOCATION:
  45. rax -> temporary
  46. rbx -> "ic"
  47. rcx -> temporary
  48. rdx -> temporary
  49. rsi -> convertible_t* scratchpad
  50. rdi -> beginning of VM stack
  51. rbp -> "ma", "mx"
  52. rsp -> end of VM stack
  53. r8 -> "r0"
  54. r9 -> "r1"
  55. r10 -> "r2"
  56. r11 -> "r3"
  57. r12 -> "r4"
  58. r13 -> "r5"
  59. r14 -> "r6"
  60. r15 -> "r7"
  61. xmm0 -> temporary
  62. xmm1 -> temporary
  63. xmm2 -> "f2"
  64. xmm3 -> "f3"
  65. xmm4 -> "f4"
  66. xmm5 -> "f5"
  67. xmm6 -> "f6"
  68. xmm7 -> "f7"
  69. xmm8 -> "f0"
  70. xmm9 -> "f1"
  71. xmm10 -> absolute value mask 0x7fffffffffffffff7fffffffffffffff
  72. STACK STRUCTURE:
  73. |
  74. |
  75. | saved registers
  76. |
  77. v
  78. [rdi+8] RegisterFile& registerFile
  79. [rdi] uint8_t* dataset
  80. |
  81. |
  82. | VM stack
  83. |
  84. v
  85. [rsp] last element of VM stack
  86. */
  87. #include "JitCompilerX86-static.hpp"
  88. const uint8_t* codePrologue = (uint8_t*)&randomx_program_prologue;
  89. const uint8_t* codeProgramBegin = (uint8_t*)&randomx_program_begin;
  90. const uint8_t* codeEpilogue = (uint8_t*)&randomx_program_epilogue;
  91. const uint8_t* codeReadDataset = (uint8_t*)&randomx_program_read;
  92. const uint8_t* codeProgramEnd = (uint8_t*)&randomx_program_end;
  93. const uint32_t* addressTransformations = (uint32_t*)&randomx_program_transform;
  94. const int32_t prologueSize = codeProgramBegin - codePrologue;
  95. const int32_t epilogueSize = codeReadDataset - codeEpilogue;
  96. const int32_t readDatasetSize = codeProgramEnd - codeReadDataset;
  97. const int32_t readDatasetOffset = CodeSize - readDatasetSize;
  98. const int32_t epilogueOffset = readDatasetOffset - epilogueSize;
  99. size_t JitCompilerX86::getCodeSize() {
  100. return codePos - prologueSize + readDatasetSize;
  101. }
  102. JitCompilerX86::JitCompilerX86() {
  103. #ifdef _WIN32
  104. code = (uint8_t*)VirtualAlloc(nullptr, CodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  105. if (code == nullptr)
  106. throw std::runtime_error("VirtualAlloc failed");
  107. #else
  108. code = (uint8_t*)mmap(nullptr, CodeSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  109. if (code == (uint8_t*)-1)
  110. throw std::runtime_error("mmap failed");
  111. #endif
  112. memcpy(code, codePrologue, prologueSize);
  113. memcpy(code + CodeSize - epilogueSize - readDatasetSize, codeEpilogue, epilogueSize);
  114. memcpy(code + CodeSize - readDatasetSize, codeReadDataset, readDatasetSize);
  115. }
  116. void JitCompilerX86::generateProgram(Pcg32& gen) {
  117. instructionOffsets.clear();
  118. callOffsets.clear();
  119. codePos = prologueSize;
  120. Instruction instr;
  121. for (unsigned i = 0; i < ProgramLength; ++i) {
  122. for (unsigned j = 0; j < sizeof(instr) / sizeof(Pcg32::result_type); ++j) {
  123. *(((uint32_t*)&instr) + j) = gen();
  124. }
  125. generateCode(instr, i);
  126. }
  127. emitByte(0xe9);
  128. emit(instructionOffsets[0] - (codePos + 4));
  129. fixCallOffsets();
  130. uint32_t transform = addressTransformations[gen.getUniform(0, TransformationCount - 1)];
  131. *reinterpret_cast<uint32_t*>(code + readDatasetOffset) = transform;
  132. }
  133. void JitCompilerX86::generateCode(Instruction& instr, int i) {
  134. instructionOffsets.push_back(codePos);
  135. emit(0x840fcbff); //dec ebx; jz <epilogue>
  136. emit(epilogueOffset - (codePos + 4)); //jump offset (RIP-relative)
  137. auto generator = engine[instr.opcode];
  138. (this->*generator)(instr, i);
  139. }
  140. void JitCompilerX86::fixCallOffsets() {
  141. for (CallOffset& co : callOffsets) {
  142. *reinterpret_cast<int32_t*>(code + co.pos) = instructionOffsets[co.index] - (co.pos + 4);
  143. }
  144. }
  145. void JitCompilerX86::gena(Instruction& instr) {
  146. emit(uint16_t(0x8149)); //xor
  147. emitByte(0xf0 + (instr.rega % RegistersCount));
  148. emit(instr.addra);
  149. emit(uint16_t(0x8b41)); //mov
  150. emitByte(0xc0 + (instr.rega % RegistersCount)); //eax, rega
  151. emit(0x753fc3f6); //test bl,0x3f; jne
  152. emit(uint16_t(0xe805));
  153. emit(readDatasetOffset - (codePos + 4));
  154. if ((instr.loca & 192) == 0) { //A.LOC.X
  155. emit(uint16_t(0x3348));
  156. emitByte(0xe8); //xor rbp, rax
  157. }
  158. emitByte(0x25); //and eax,
  159. if (instr.loca & 15) {
  160. if (instr.loca & 3) {
  161. emit(ScratchpadL1 - 1); //first 16 KiB of scratchpad
  162. }
  163. else {
  164. emit(ScratchpadL2 - 1); //first 256 KiB of scratchpad
  165. }
  166. }
  167. else {
  168. emit(ScratchpadL3 - 1); //whole scratchpad
  169. }
  170. }
  171. void JitCompilerX86::genar(Instruction& instr) {
  172. gena(instr);
  173. emit(0xc6048b48); //mov rax,QWORD PTR [rsi+rax*8]
  174. }
  175. void JitCompilerX86::genaf(Instruction& instr) {
  176. gena(instr);
  177. emitByte(0xf3);
  178. emit(0xc604e60f); //cvtdq2pd xmm0,QWORD PTR [rsi+rax*8]
  179. }
  180. void JitCompilerX86::genbiashift(Instruction& instr, uint16_t opcodeReg, uint16_t opcodeImm) {
  181. if (instr.locb & 1) {
  182. emit(uint16_t(0x8b49)); //mov
  183. emitByte(0xc8 + (instr.regb % RegistersCount)); //rcx, regb
  184. emitByte(0x48); //REX.W
  185. emit(opcodeReg); //xxx rax, cl
  186. }
  187. else {
  188. emitByte(0x48); //REX.W
  189. emit(opcodeImm); //xxx rax, imm8
  190. emitByte((instr.imm8 & 63));
  191. }
  192. }
  193. void JitCompilerX86::genbia(Instruction& instr, uint16_t opcodeReg, uint16_t opcodeImm) {
  194. if (instr.locb & 3) {
  195. emit(opcodeReg); // xxx rax, r64
  196. emitByte(0xc0 + (instr.regb % RegistersCount));
  197. }
  198. else {
  199. emit(opcodeImm); // xxx rax, imm32
  200. emit(instr.imm32);
  201. }
  202. }
  203. void JitCompilerX86::genbia32(Instruction& instr, uint16_t opcodeReg, uint8_t opcodeImm) {
  204. if (instr.locb & 3) {
  205. emit(opcodeReg); // xxx eax, r32
  206. emitByte(0xc0 + (instr.regb % RegistersCount));
  207. }
  208. else {
  209. emitByte(opcodeImm); // xxx eax, imm32
  210. emit(instr.imm32);
  211. }
  212. }
  213. void JitCompilerX86::genbf(Instruction& instr, uint8_t opcode) {
  214. int regb = (instr.regb % RegistersCount);
  215. emitByte(0x66); //xxxpd xmm0,regb
  216. if (regb <= 1) {
  217. emitByte(0x41); //REX
  218. }
  219. emitByte(0x0f);
  220. emitByte(opcode);
  221. emitByte(0xc0 + regb);
  222. }
  223. void JitCompilerX86::scratchpadStoreR(Instruction& instr, uint32_t scratchpadSize, bool rax) {
  224. if (rax) {
  225. emit(0x41c88b48); //mov rcx, rax; REX
  226. }
  227. else {
  228. emitByte(0x41);
  229. }
  230. emitByte(0x8b); // mov
  231. emitByte(0xc0 + (instr.regc % RegistersCount)); //eax, regc
  232. emitByte(0x35); // xor eax
  233. emit(instr.addrc);
  234. emitByte(0x25); //and
  235. emit(scratchpadSize - 1);
  236. emit(0xc60c8948); // mov QWORD PTR [rsi+rax*8],rcx
  237. }
  238. void JitCompilerX86::gencr(Instruction& instr, bool rax = true) {
  239. if (instr.locc & 16) { //write to register
  240. emit(uint16_t(0x8b4c)); //mov
  241. if (rax) {
  242. emitByte(0xc0 + 8 * (instr.regc % RegistersCount)); //regc, rax
  243. }
  244. else {
  245. emitByte(0xc1 + 8 * (instr.regc % RegistersCount)); //regc, rcx
  246. }
  247. }
  248. else {
  249. if (instr.locc & 15) {
  250. if (instr.locc & 3) {
  251. scratchpadStoreR(instr, ScratchpadL1, rax);
  252. }
  253. else {
  254. scratchpadStoreR(instr, ScratchpadL2, rax);
  255. }
  256. }
  257. else {
  258. scratchpadStoreR(instr, ScratchpadL3, rax);
  259. }
  260. }
  261. }
  262. void JitCompilerX86::scratchpadStoreF(Instruction& instr, int regc, uint32_t scratchpadSize, bool storeHigh) {
  263. emit(uint16_t(0x8b41)); //mov
  264. emitByte(0xc0 + regc); //eax, regc
  265. emitByte(0x35); // xor eax
  266. emit(instr.addrc);
  267. emitByte(0x25); //and
  268. emit(scratchpadSize - 1);
  269. emitByte(0x66); //movhpd/movlpd QWORD PTR [rsi+rax*8], regc
  270. if (regc <= 1) {
  271. emitByte(0x44); //REX
  272. }
  273. emitByte(0x0f);
  274. emitByte(storeHigh ? 0x17 : 0x13);
  275. emitByte(4 + 8 * regc);
  276. emitByte(0xc6);
  277. }
  278. void JitCompilerX86::gencf(Instruction& instr) {
  279. int regc = (instr.regc % RegistersCount);
  280. if (regc <= 1) {
  281. emitByte(0x44); //REX
  282. }
  283. emit(uint16_t(0x280f)); //movaps
  284. emitByte(0xc0 + 8 * regc); // regc, xmm0
  285. if (instr.locc & 16) { //write to scratchpad
  286. if (instr.locc & 15) {
  287. if (instr.locc & 3) { //C.LOC.W
  288. scratchpadStoreF(instr, regc, ScratchpadL1, (instr.locc & 128)); //first 16 KiB of scratchpad
  289. }
  290. else {
  291. scratchpadStoreF(instr, regc, ScratchpadL2, (instr.locc & 128)); //first 256 KiB of scratchpad
  292. }
  293. }
  294. else {
  295. scratchpadStoreF(instr, regc, ScratchpadL3, (instr.locc & 128)); //whole scratchpad
  296. }
  297. }
  298. }
  299. void JitCompilerX86::h_ADD_64(Instruction& instr, int i) {
  300. genar(instr);
  301. genbia(instr, 0x0349, 0x0548);
  302. gencr(instr);
  303. }
  304. void JitCompilerX86::h_ADD_32(Instruction& instr, int i) {
  305. genar(instr);
  306. genbia32(instr, 0x0341, 0x05);
  307. gencr(instr);
  308. }
  309. void JitCompilerX86::h_SUB_64(Instruction& instr, int i) {
  310. genar(instr);
  311. genbia(instr, 0x2b49, 0x2d48);
  312. gencr(instr);
  313. }
  314. void JitCompilerX86::h_SUB_32(Instruction& instr, int i) {
  315. genar(instr);
  316. genbia32(instr, 0x2b41, 0x2d);
  317. gencr(instr);
  318. }
  319. void JitCompilerX86::h_MUL_64(Instruction& instr, int i) {
  320. genar(instr);
  321. if ((instr.locb & 7) <= 5) {
  322. emitByte(0x49); //REX
  323. emit(uint16_t(0xaf0f)); // imul rax, r64
  324. emitByte(0xc0 + (instr.regb % RegistersCount));
  325. }
  326. else {
  327. emitByte(0x48); //REX
  328. emit(uint16_t(0xc069)); // imul rax, rax, imm32
  329. emit(instr.imm32);
  330. }
  331. gencr(instr);
  332. }
  333. void JitCompilerX86::h_MULH_64(Instruction& instr, int i) {
  334. genar(instr);
  335. if ((instr.locb & 7) <= 5) {
  336. emit(uint16_t(0x8b49)); //mov rcx, r64
  337. emitByte(0xc8 + (instr.regb % RegistersCount));
  338. }
  339. else {
  340. emitByte(0x48);
  341. emit(uint16_t(0xc1c7)); // mov rcx, imm32
  342. emit(instr.imm32);
  343. }
  344. emitByte(0x48);
  345. emit(uint16_t(0xe1f7)); // mul rcx
  346. emitByte(0x48);
  347. emit(uint16_t(0xc28b)); // mov rax,rdx
  348. gencr(instr);
  349. }
  350. void JitCompilerX86::h_MUL_32(Instruction& instr, int i) {
  351. genar(instr);
  352. emit(uint16_t(0xc88b)); //mov ecx, eax
  353. if ((instr.locb & 7) <= 5) {
  354. emit(uint16_t(0x8b41)); // mov eax, r32
  355. emitByte(0xc0 + (instr.regb % RegistersCount));
  356. }
  357. else {
  358. emitByte(0xb8); // mov eax, imm32
  359. emit(instr.imm32);
  360. }
  361. emit(0xc1af0f48); //imul rax,rcx
  362. gencr(instr);
  363. }
  364. void JitCompilerX86::h_IMUL_32(Instruction& instr, int i) {
  365. genar(instr);
  366. emitByte(0x48);
  367. emit(uint16_t(0xc863)); //movsxd rcx,eax
  368. if ((instr.locb & 7) <= 5) {
  369. emit(uint16_t(0x6349)); //movsxd rax,r32
  370. emitByte(0xc0 + (instr.regb % RegistersCount));
  371. }
  372. else {
  373. emitByte(0x48);
  374. emit(uint16_t(0xc0c7)); // mov rax, imm32
  375. emit(instr.imm32);
  376. }
  377. emit(0xc1af0f48); //imul rax,rcx
  378. gencr(instr);
  379. }
  380. void JitCompilerX86::h_IMULH_64(Instruction& instr, int i) {
  381. genar(instr);
  382. if ((instr.locb & 7) <= 5) {
  383. emit(uint16_t(0x8b49)); //mov rcx, r64
  384. emitByte(0xc8 + (instr.regb % RegistersCount));
  385. }
  386. else {
  387. emitByte(0x48);
  388. emit(uint16_t(0xc1c7)); // mov rcx, imm32
  389. emit(instr.imm32);
  390. }
  391. emitByte(0x48);
  392. emit(uint16_t(0xe9f7)); // imul rcx
  393. emitByte(0x48);
  394. emit(uint16_t(0xc28b)); // mov rax,rdx
  395. gencr(instr);
  396. }
  397. void JitCompilerX86::h_DIV_64(Instruction& instr, int i) {
  398. genar(instr);
  399. if (instr.locb & 7) {
  400. #ifdef MAGIC_DIVISION
  401. if (instr.imm32 != 0) {
  402. uint32_t divisor = instr.imm32;
  403. if (divisor & (divisor - 1)) {
  404. magicu_info mi = compute_unsigned_magic_info(divisor, sizeof(uint64_t) * 8);
  405. if (mi.pre_shift > 0) {
  406. if (mi.pre_shift == 1) {
  407. emitByte(0x48);
  408. emit(uint16_t(0xe8d1)); //shr rax,1
  409. }
  410. else {
  411. emit(0x00e8c148 | (mi.pre_shift << 24)); //shr rax, pre_shift
  412. }
  413. }
  414. if (mi.increment) {
  415. emit(0x00d8834801c08348); //add rax,1; sbb rax,0
  416. }
  417. emit(uint16_t(0xb948)); //movabs rcx, multiplier
  418. emit(mi.multiplier);
  419. emit(0x48e1f748); //mul rcx; REX
  420. emit(uint16_t(0xc28b)); //mov rax,rdx
  421. if (mi.post_shift > 0)
  422. emit(0x00e8c148 | (mi.post_shift << 24)); //shr rax, post_shift
  423. }
  424. else { //divisor is a power of two
  425. int shift = 0;
  426. while (divisor >>= 1)
  427. ++shift;
  428. if (shift > 0)
  429. emit(0x00e8c148 | (shift << 24)); //shr rax, shift
  430. }
  431. }
  432. #else
  433. emitByte(0xb9); //mov ecx, imm32
  434. emit(instr.imm32 != 0 ? instr.imm32 : 1);
  435. #endif
  436. }
  437. else {
  438. emitByte(0xb9); //mov ecx, 1
  439. emit(1);
  440. emit(uint16_t(0x8b41)); //mov edx, r32
  441. emitByte(0xd0 + (instr.regb % RegistersCount));
  442. emit(0x450fd285); //test edx, edx; cmovne ecx,edx
  443. emitByte(0xca);
  444. #ifdef MAGIC_DIVISION
  445. emit(0xf748d233); //xor edx,edx; div rcx
  446. emitByte(0xf1);
  447. #endif
  448. }
  449. #ifndef MAGIC_DIVISION
  450. emit(0xf748d233); //xor edx,edx; div rcx
  451. emitByte(0xf1);
  452. #endif
  453. gencr(instr);
  454. }
  455. void JitCompilerX86::h_IDIV_64(Instruction& instr, int i) {
  456. genar(instr);
  457. if (instr.locb & 7) {
  458. #ifdef MAGIC_DIVISION
  459. int64_t divisor = instr.imm32;
  460. if ((divisor & -divisor) == divisor || (divisor & -divisor) == -divisor) {
  461. // +/- power of two
  462. bool negative = divisor < 0;
  463. if (negative)
  464. divisor = -divisor;
  465. int shift = 0;
  466. uint64_t unsignedDivisor = divisor;
  467. while (unsignedDivisor >>= 1)
  468. ++shift;
  469. if (shift > 0) {
  470. emitByte(0x48);
  471. emit(uint16_t(0xc88b)); //mov rcx, rax
  472. emit(0x3ff9c148); //sar rcx, 63
  473. uint32_t mask = (1ULL << shift) - 1;
  474. emit(uint16_t(0xe181)); //and ecx, mask
  475. emit(mask);
  476. emitByte(0x48);
  477. emit(uint16_t(0xc103)); //add rax, rcx
  478. emit(0x00f8c148 | (shift << 24)); //sar rax, shift
  479. }
  480. if (negative) {
  481. emitByte(0x48);
  482. emit(uint16_t(0xd8f7)); //neg rax
  483. }
  484. }
  485. else if (divisor != 0) {
  486. magics_info mi = compute_signed_magic_info(divisor);
  487. if ((divisor >= 0) != (mi.multiplier >= 0)) {
  488. emitByte(0x48);
  489. emit(uint16_t(0xc88b)); //mov rcx, rax
  490. }
  491. emit(uint16_t(0xba48)); //movabs rdx, multiplier
  492. emit(mi.multiplier);
  493. emit(0xd233c28b48eaf748); //imul rdx; mov rax,rdx; xor edx,edx
  494. bool haveSF = false;
  495. if (divisor > 0 && mi.multiplier < 0) {
  496. emitByte(0x48);
  497. emit(uint16_t(0xc103)); //add rax, rcx
  498. haveSF = true;
  499. }
  500. if (divisor < 0 && mi.multiplier > 0) {
  501. emitByte(0x48);
  502. emit(uint16_t(0xc12b)); //sub rax, rcx
  503. haveSF = true;
  504. }
  505. if (mi.shift > 0) {
  506. emit(0x00f8c148 | (mi.shift << 24)); //sar rax, shift
  507. haveSF = true;
  508. }
  509. if (!haveSF) {
  510. emitByte(0x48);
  511. emit(uint16_t(0x85c0));
  512. }
  513. emit(0x48c2980f); //sets dl; add rax, rdx
  514. emit(uint16_t(0xc203));
  515. }
  516. #else
  517. emitByte(0xba); // mov edx, imm32
  518. emit(instr.imm32);
  519. #endif
  520. }
  521. else {
  522. emit(uint16_t(0x8b41)); //mov edx, r32
  523. emitByte(0xd0 + (instr.regb % RegistersCount));
  524. #ifndef MAGIC_DIVISION
  525. }
  526. #endif
  527. emit(0xd8f7480575fffa83); //cmp edx,-1
  528. emit(uint16_t(0x12eb)); //jmp result
  529. emit(0x0fd28500000001b9);
  530. emit(0x489948c96348ca45);
  531. emit(uint16_t(0xf9f7)); //idiv rcx
  532. #ifdef MAGIC_DIVISION
  533. }
  534. #endif
  535. gencr(instr);
  536. }
  537. void JitCompilerX86::h_AND_64(Instruction& instr, int i) {
  538. genar(instr);
  539. genbia(instr, 0x2349, 0x2548);
  540. gencr(instr);
  541. }
  542. void JitCompilerX86::h_AND_32(Instruction& instr, int i) {
  543. genar(instr);
  544. genbia32(instr, 0x2341, 0x25);
  545. gencr(instr);
  546. }
  547. void JitCompilerX86::h_OR_64(Instruction& instr, int i) {
  548. genar(instr);
  549. genbia(instr, 0x0b49, 0x0d48);
  550. gencr(instr);
  551. }
  552. void JitCompilerX86::h_OR_32(Instruction& instr, int i) {
  553. genar(instr);
  554. genbia32(instr, 0x0b41, 0x0d);
  555. gencr(instr);
  556. }
  557. void JitCompilerX86::h_XOR_64(Instruction& instr, int i) {
  558. genar(instr);
  559. genbia(instr, 0x3349, 0x3548);
  560. gencr(instr);
  561. }
  562. void JitCompilerX86::h_XOR_32(Instruction& instr, int i) {
  563. genar(instr);
  564. genbia32(instr, 0x3341, 0x35);
  565. gencr(instr);
  566. }
  567. void JitCompilerX86::h_SHL_64(Instruction& instr, int i) {
  568. genar(instr);
  569. genbiashift(instr, 0xe0d3, 0xe0c1);
  570. gencr(instr);
  571. }
  572. void JitCompilerX86::h_SHR_64(Instruction& instr, int i) {
  573. genar(instr);
  574. genbiashift(instr, 0xe8d3, 0xe8c1);
  575. gencr(instr);
  576. }
  577. void JitCompilerX86::h_SAR_64(Instruction& instr, int i) {
  578. genar(instr);
  579. genbiashift(instr, 0xf8d3, 0xf8c1);
  580. gencr(instr);
  581. }
  582. void JitCompilerX86::h_ROL_64(Instruction& instr, int i) {
  583. genar(instr);
  584. genbiashift(instr, 0xc0d3, 0xc0c1);
  585. gencr(instr);
  586. }
  587. void JitCompilerX86::h_ROR_64(Instruction& instr, int i) {
  588. genar(instr);
  589. genbiashift(instr, 0xc8d3, 0xc8c1);
  590. gencr(instr);
  591. }
  592. void JitCompilerX86::h_FPADD(Instruction& instr, int i) {
  593. genaf(instr);
  594. genbf(instr, 0x58);
  595. gencf(instr);
  596. }
  597. void JitCompilerX86::h_FPSUB(Instruction& instr, int i) {
  598. genaf(instr);
  599. genbf(instr, 0x5c);
  600. gencf(instr);
  601. }
  602. void JitCompilerX86::h_FPMUL(Instruction& instr, int i) {
  603. genaf(instr);
  604. genbf(instr, 0x59);
  605. emit(0x00c9c20f66c8280f); //movaps xmm1,xmm0; cmpeqpd xmm1,xmm1
  606. emit(uint16_t(0x540f)); //andps xmm0,xmm1
  607. emitByte(0xc1);
  608. gencf(instr);
  609. }
  610. void JitCompilerX86::h_FPDIV(Instruction& instr, int i) {
  611. genaf(instr);
  612. genbf(instr, 0x5e);
  613. emit(0x00c9c20f66c8280f); //movaps xmm1,xmm0; cmpeqpd xmm1,xmm1
  614. emit(uint16_t(0x540f)); //andps xmm0,xmm1
  615. emitByte(0xc1);
  616. gencf(instr);
  617. }
  618. void JitCompilerX86::h_FPSQRT(Instruction& instr, int i) {
  619. genaf(instr);
  620. emit(0xc0510f66c2540f41); //andps xmm0,xmm10; sqrtpd xmm0,xmm0
  621. gencf(instr);
  622. }
  623. void JitCompilerX86::h_FPROUND(Instruction& instr, int i) {
  624. genar(instr);
  625. emitByte(0x48);
  626. emit(uint16_t(0xc88b)); //mov rcx,rax
  627. int rotate = (13 - (instr.imm8 & 63)) & 63;
  628. if (rotate != 0) {
  629. emitByte(0x48);
  630. emit(uint16_t(0xc0c1)); //rol rax
  631. emitByte(rotate);
  632. }
  633. emit(uint16_t(0x0025));
  634. emit(0x00009fc00d000060); //and eax,0x6000; or eax,0x9fc0
  635. emit(0x2454ae0ff8244489); //ldmxcsr DWORD PTR [rsp-0x8]
  636. emitByte(0xf8);
  637. gencr(instr, false); //result in rcx
  638. }
  639. static inline uint8_t jumpCondition(Instruction& instr, bool invert = false) {
  640. switch ((instr.locb & 7) ^ invert)
  641. {
  642. case 0:
  643. return 0x76; //jbe
  644. case 1:
  645. return 0x77; //ja
  646. case 2:
  647. return 0x78; //js
  648. case 3:
  649. return 0x79; //jns
  650. case 4:
  651. return 0x70; //jo
  652. case 5:
  653. return 0x71; //jno
  654. case 6:
  655. return 0x7c; //jl
  656. case 7:
  657. return 0x7d; //jge
  658. }
  659. }
  660. void JitCompilerX86::h_JUMP(Instruction& instr, int i) {
  661. genar(instr);
  662. gencr(instr);
  663. emit(uint16_t(0x8141)); //cmp regb, imm32
  664. emitByte(0xf8 + (instr.regb % RegistersCount));
  665. emit(instr.imm32);
  666. emitByte(0x0f); //near jump
  667. emitByte(jumpCondition(instr) + 0x10);
  668. i = wrapInstr(i + (instr.imm8 & 127) + 2);
  669. if (i < instructionOffsets.size()) {
  670. emit(instructionOffsets[i] - (codePos + 4));
  671. }
  672. else {
  673. callOffsets.push_back(CallOffset(codePos, i));
  674. codePos += 4;
  675. }
  676. }
  677. void JitCompilerX86::h_CALL(Instruction& instr, int i) {
  678. genar(instr);
  679. gencr(instr);
  680. emit(uint16_t(0x8141)); //cmp regb, imm32
  681. emitByte(0xf8 + (instr.regb % RegistersCount));
  682. emit(instr.imm32);
  683. emitByte(jumpCondition(instr, true));
  684. emitByte(0x05);
  685. emitByte(0xe8); //call
  686. i = wrapInstr(i + (instr.imm8 & 127) + 2);
  687. if (i < instructionOffsets.size()) {
  688. emit(instructionOffsets[i] - (codePos + 4));
  689. }
  690. else {
  691. callOffsets.push_back(CallOffset(codePos, i));
  692. codePos += 4;
  693. }
  694. }
  695. void JitCompilerX86::h_RET(Instruction& instr, int i) {
  696. genar(instr);
  697. int crlen = 0;
  698. if ((instr.locc & 7) <= 3) {
  699. crlen = 17;
  700. }
  701. emit(0x74e73b48); //cmp rsp, rdi; je
  702. emitByte(0x01);
  703. emitByte(0xc3); //ret
  704. }
  705. void JitCompilerX86::h_NOP(Instruction& instr, int i) {
  706. genar(instr);
  707. }
  708. #include "instructionWeights.hpp"
  709. #define INST_HANDLE(x) REPN(&JitCompilerX86::h_##x, WT(x))
  710. InstructionGeneratorX86 JitCompilerX86::engine[256] = {
  711. INST_HANDLE(ADD_64)
  712. INST_HANDLE(ADD_32)
  713. INST_HANDLE(SUB_64)
  714. INST_HANDLE(SUB_32)
  715. INST_HANDLE(MUL_64)
  716. INST_HANDLE(MULH_64)
  717. INST_HANDLE(MUL_32)
  718. INST_HANDLE(IMUL_32)
  719. INST_HANDLE(IMULH_64)
  720. INST_HANDLE(DIV_64)
  721. INST_HANDLE(IDIV_64)
  722. INST_HANDLE(AND_64)
  723. INST_HANDLE(AND_32)
  724. INST_HANDLE(OR_64)
  725. INST_HANDLE(OR_32)
  726. INST_HANDLE(XOR_64)
  727. INST_HANDLE(XOR_32)
  728. INST_HANDLE(SHL_64)
  729. INST_HANDLE(SHR_64)
  730. INST_HANDLE(SAR_64)
  731. INST_HANDLE(ROL_64)
  732. INST_HANDLE(ROR_64)
  733. INST_HANDLE(FPADD)
  734. INST_HANDLE(FPSUB)
  735. INST_HANDLE(FPMUL)
  736. INST_HANDLE(FPDIV)
  737. INST_HANDLE(FPSQRT)
  738. INST_HANDLE(FPROUND)
  739. INST_HANDLE(JUMP)
  740. INST_HANDLE(CALL)
  741. INST_HANDLE(RET)
  742. INST_HANDLE(NOP)
  743. };
  744. #endif
  745. }