/Src/Dependencies/AsmJit/AsmJit/AssemblerX86X64.cpp

http://hadesmem.googlecode.com/ · C++ · 2297 lines · 1750 code · 345 blank · 202 comment · 495 complexity · 075f732bded64c785e6ed494783f2917 MD5 · raw file

Large files are truncated click here to view the full file

  1. // AsmJit - Complete JIT Assembler for C++ Language.
  2. // Copyright (c) 2008-2010, Petr Kobalicek <kobalicek.petr@gmail.com>
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. // We are using sprintf() here.
  25. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
  26. #define _CRT_SECURE_NO_WARNINGS
  27. #endif // _MSC_VER
  28. // [Dependencies]
  29. #include "Assembler.h"
  30. #include "CodeGenerator.h"
  31. #include "CpuInfo.h"
  32. #include "Defs.h"
  33. #include "Logger.h"
  34. #include "MemoryManager.h"
  35. #include "Platform.h"
  36. #include "Util_p.h"
  37. #include <stdarg.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. // A little bit C++.
  41. #include <new>
  42. // [Api-Begin]
  43. #include "ApiBegin.h"
  44. namespace AsmJit {
  45. #if defined(ASMJIT_X64)
  46. // ============================================================================
  47. // [AsmJit::TrampolineWriter]
  48. // ============================================================================
  49. //! @brief Class used to determine size of trampoline and as trampoline writer.
  50. struct ASMJIT_HIDDEN TrampolineWriter
  51. {
  52. // Size of trampoline
  53. enum {
  54. TRAMPOLINE_JMP = 6,
  55. TRAMPOLINE_ADDR = sizeof(sysint_t),
  56. TRAMPOLINE_SIZE = TRAMPOLINE_JMP + TRAMPOLINE_ADDR
  57. };
  58. // Write trampoline into code at address @a code that will jump to @a target.
  59. static void writeTrampoline(uint8_t* code, void* target)
  60. {
  61. // Jmp.
  62. code[0] = 0xFF;
  63. // ModM (RIP addressing).
  64. code[1] = 0x25;
  65. // Offset (zero).
  66. ((uint32_t*)(code + 2))[0] = 0;
  67. // Absolute address.
  68. ((sysuint_t*)(code + TRAMPOLINE_JMP))[0] = (sysuint_t)target;
  69. }
  70. };
  71. #endif // ASMJIT_X64
  72. // ============================================================================
  73. // [AsmJit::AssemblerCore - Construction / Destruction]
  74. // ============================================================================
  75. AssemblerCore::AssemblerCore(CodeGenerator* codeGenerator) ASMJIT_NOTHROW :
  76. _codeGenerator(codeGenerator != NULL ? codeGenerator : CodeGenerator::getGlobal()),
  77. _zone(16384 - sizeof(Zone::Chunk) - 32),
  78. _logger(NULL),
  79. _error(0),
  80. _properties((1 << PROPERTY_OPTIMIZE_ALIGN)),
  81. _emitOptions(0),
  82. _buffer(32), // Max instruction length is 15, but we can align up to 32 bytes.
  83. _trampolineSize(0),
  84. _unusedLinks(NULL),
  85. _comment(NULL)
  86. {
  87. }
  88. AssemblerCore::~AssemblerCore() ASMJIT_NOTHROW
  89. {
  90. }
  91. // ============================================================================
  92. // [AsmJit::AssemblerCore - Logging]
  93. // ============================================================================
  94. void AssemblerCore::setLogger(Logger* logger) ASMJIT_NOTHROW
  95. {
  96. _logger = logger;
  97. }
  98. // ============================================================================
  99. // [AsmJit::AssemblerCore - Error Handling]
  100. // ============================================================================
  101. void AssemblerCore::setError(uint32_t error) ASMJIT_NOTHROW
  102. {
  103. _error = error;
  104. if (_error == ERROR_NONE) return;
  105. if (_logger)
  106. {
  107. _logger->logFormat("*** ASSEMBLER ERROR: %s (%u).\n",
  108. getErrorString(error),
  109. (unsigned int)error);
  110. }
  111. }
  112. // ============================================================================
  113. // [AsmJit::AssemblerCore - Properties]
  114. // ============================================================================
  115. uint32_t AssemblerCore::getProperty(uint32_t propertyId)
  116. {
  117. return (_properties & (1 << propertyId)) != 0;
  118. }
  119. void AssemblerCore::setProperty(uint32_t propertyId, uint32_t value)
  120. {
  121. if (value)
  122. _properties |= (1 << propertyId);
  123. else
  124. _properties &= ~(1 << propertyId);
  125. }
  126. // ============================================================================
  127. // [AsmJit::AssemblerCore - Buffer]
  128. // ============================================================================
  129. void AssemblerCore::clear() ASMJIT_NOTHROW
  130. {
  131. _buffer.clear();
  132. _relocData.clear();
  133. _zone.clear();
  134. if (_error) setError(ERROR_NONE);
  135. }
  136. void AssemblerCore::free() ASMJIT_NOTHROW
  137. {
  138. _zone.freeAll();
  139. _buffer.free();
  140. _relocData.free();
  141. if (_error) setError(ERROR_NONE);
  142. }
  143. uint8_t* AssemblerCore::takeCode() ASMJIT_NOTHROW
  144. {
  145. uint8_t* code = _buffer.take();
  146. _relocData.clear();
  147. _zone.clear();
  148. if (_error) setError(ERROR_NONE);
  149. return code;
  150. }
  151. // ============================================================================
  152. // [AsmJit::AssemblerCore - Stream Setters / Getters]
  153. // ============================================================================
  154. void AssemblerCore::setVarAt(sysint_t pos, sysint_t i, uint8_t isUnsigned, uint32_t size) ASMJIT_NOTHROW
  155. {
  156. if (size == 1 && !isUnsigned) setByteAt (pos, (int8_t )i);
  157. else if (size == 1 && isUnsigned) setByteAt (pos, (uint8_t )i);
  158. else if (size == 2 && !isUnsigned) setWordAt (pos, (int16_t )i);
  159. else if (size == 2 && isUnsigned) setWordAt (pos, (uint16_t)i);
  160. else if (size == 4 && !isUnsigned) setDWordAt(pos, (int32_t )i);
  161. else if (size == 4 && isUnsigned) setDWordAt(pos, (uint32_t)i);
  162. #if defined(ASMJIT_X64)
  163. else if (size == 8 && !isUnsigned) setQWordAt(pos, (int64_t )i);
  164. else if (size == 8 && isUnsigned) setQWordAt(pos, (uint64_t)i);
  165. #endif // ASMJIT_X64
  166. else
  167. ASMJIT_ASSERT(0);
  168. }
  169. // ============================================================================
  170. // [AsmJit::AssemblerCore - Assembler Emitters]
  171. // ============================================================================
  172. bool AssemblerCore::canEmit() ASMJIT_NOTHROW
  173. {
  174. // If there is an error, we can't emit another instruction until last error
  175. // is cleared by calling @c setError(ERROR_NONE). If something caused an error
  176. // while generating code it's probably fatal in all cases. You can't use
  177. // generated code, because you are not sure about its status.
  178. if (_error) return false;
  179. // The ensureSpace() method returns true on success and false on failure. We
  180. // are catching return value and setting error code here.
  181. if (ensureSpace()) return true;
  182. // If we are here, there is memory allocation error. Note that this is HEAP
  183. // allocation error, virtual allocation error can be caused only by
  184. // AsmJit::VirtualMemory class!
  185. setError(ERROR_NO_HEAP_MEMORY);
  186. return false;
  187. }
  188. void AssemblerCore::_emitSegmentPrefix(const Operand& rm) ASMJIT_NOTHROW
  189. {
  190. static const uint8_t segmentPrefixCode[6] =
  191. {
  192. 0x26, // ES
  193. 0x2E, // SS
  194. 0x36, // SS
  195. 0x3E, // DS
  196. 0x64, // FS
  197. 0x65 // GS
  198. };
  199. uint32_t segmentPrefix;
  200. if (!rm.isMem())
  201. return;
  202. if ((segmentPrefix = reinterpret_cast<const Mem&>(rm).getSegmentPrefix()) >= REG_NUM_SEGMENT)
  203. return;
  204. _emitByte(segmentPrefixCode[segmentPrefix]);
  205. }
  206. void AssemblerCore::_emitModM(
  207. uint8_t opReg, const Mem& mem, sysint_t immSize) ASMJIT_NOTHROW
  208. {
  209. ASMJIT_ASSERT(mem.getType() == OPERAND_MEM);
  210. uint8_t baseReg = mem.getBase() & 0x7;
  211. uint8_t indexReg = mem.getIndex() & 0x7;
  212. sysint_t disp = mem.getDisplacement();
  213. uint32_t shift = mem.getShift();
  214. if (mem.getMemType() == OPERAND_MEM_NATIVE)
  215. {
  216. // [base + displacemnt]
  217. if (!mem.hasIndex())
  218. {
  219. // ESP/RSP/R12 == 4
  220. if (baseReg == 4)
  221. {
  222. uint8_t mod = 0;
  223. if (disp)
  224. {
  225. mod = Util::isInt8(disp) ? 1 : 2;
  226. }
  227. _emitMod(mod, opReg, 4);
  228. _emitSib(0, 4, 4);
  229. if (disp)
  230. {
  231. if (Util::isInt8(disp))
  232. _emitByte((int8_t)disp);
  233. else
  234. _emitInt32((int32_t)disp);
  235. }
  236. }
  237. // EBP/RBP/R13 == 5
  238. else if (baseReg != 5 && disp == 0)
  239. {
  240. _emitMod(0, opReg, baseReg);
  241. }
  242. else if (Util::isInt8(disp))
  243. {
  244. _emitMod(1, opReg, baseReg);
  245. _emitByte((int8_t)disp);
  246. }
  247. else
  248. {
  249. _emitMod(2, opReg, baseReg);
  250. _emitInt32((int32_t)disp);
  251. }
  252. }
  253. // [base + index * scale + displacemnt]
  254. else
  255. {
  256. // ASMJIT_ASSERT(indexReg != RID_ESP);
  257. // EBP/RBP/R13 == 5
  258. if (baseReg != 5 && disp == 0)
  259. {
  260. _emitMod(0, opReg, 4);
  261. _emitSib(shift, indexReg, baseReg);
  262. }
  263. else if (Util::isInt8(disp))
  264. {
  265. _emitMod(1, opReg, 4);
  266. _emitSib(shift, indexReg, baseReg);
  267. _emitByte((int8_t)disp);
  268. }
  269. else
  270. {
  271. _emitMod(2, opReg, 4);
  272. _emitSib(shift, indexReg, baseReg);
  273. _emitInt32((int32_t)disp);
  274. }
  275. }
  276. }
  277. // Address | 32-bit mode | 64-bit mode
  278. // ------------------------------+-------------+---------------
  279. // [displacement] | ABSOLUTE | RELATIVE (RIP)
  280. // [index * scale + displacemnt] | ABSOLUTE | ABSOLUTE (ZERO EXTENDED)
  281. else
  282. {
  283. // - In 32-bit mode the absolute addressing model is used.
  284. // - In 64-bit mode the relative addressing model is used together with
  285. // the absolute addressing. Main problem is that if instruction
  286. // contains SIB then relative addressing (RIP) is not possible.
  287. #if defined(ASMJIT_X86)
  288. if (mem.hasIndex())
  289. {
  290. // ASMJIT_ASSERT(mem.getMemIndex() != 4); // ESP/RSP == 4
  291. _emitMod(0, opReg, 4);
  292. _emitSib(shift, indexReg, 5);
  293. }
  294. else
  295. {
  296. _emitMod(0, opReg, 5);
  297. }
  298. // X86 uses absolute addressing model, all relative addresses will be
  299. // relocated to absolute ones.
  300. if (mem.getMemType() == OPERAND_MEM_LABEL)
  301. {
  302. LabelData& l_data = _labelData[mem._mem.base & OPERAND_ID_VALUE_MASK];
  303. RelocData r_data;
  304. uint32_t relocId = _relocData.getLength();
  305. // Relative addressing will be relocated to absolute address.
  306. r_data.type = RelocData::RELATIVE_TO_ABSOLUTE;
  307. r_data.size = 4;
  308. r_data.offset = getOffset();
  309. r_data.destination = disp;
  310. if (l_data.offset != -1)
  311. {
  312. // Bound label.
  313. r_data.destination += l_data.offset;
  314. // Add a dummy DWORD.
  315. _emitInt32(0);
  316. }
  317. else
  318. {
  319. // Non-bound label.
  320. _emitDisplacement(l_data, -4 - immSize, 4)->relocId = relocId;
  321. }
  322. _relocData.append(r_data);
  323. }
  324. else
  325. {
  326. // Absolute address
  327. _emitInt32( (int32_t)((uint8_t*)mem._mem.target + disp) );
  328. }
  329. #else
  330. // X64 uses relative addressing model
  331. if (mem.getMemType() == OPERAND_MEM_LABEL)
  332. {
  333. LabelData& l_data = _labelData[mem._mem.base & OPERAND_ID_VALUE_MASK];
  334. if (mem.hasIndex())
  335. {
  336. // Indexing is not possible.
  337. setError(ERROR_ILLEGAL_ADDRESING);
  338. return;
  339. }
  340. // Relative address (RIP +/- displacement).
  341. _emitMod(0, opReg, 5);
  342. disp -= (4 + immSize);
  343. if (l_data.offset != -1)
  344. {
  345. // Bound label.
  346. disp += getOffset() - l_data.offset;
  347. // Add a dummy DWORD.
  348. _emitInt32((int32_t)disp);
  349. }
  350. else
  351. {
  352. // Non-bound label.
  353. _emitDisplacement(l_data, disp, 4);
  354. }
  355. }
  356. else
  357. {
  358. // Absolute address (truncated to 32-bits), this kind of address requires
  359. // SIB byte (4).
  360. _emitMod(0, opReg, 4);
  361. if (mem.hasIndex())
  362. {
  363. // ASMJIT_ASSERT(mem.getMemIndex() != 4); // ESP/RSP == 4
  364. _emitSib(shift, indexReg, 5);
  365. }
  366. else
  367. {
  368. _emitSib(0, 4, 5);
  369. }
  370. // Truncate to 32-bits.
  371. sysuint_t target = (sysuint_t)((uint8_t*)mem._mem.target + disp);
  372. if (target > (sysuint_t)0xFFFFFFFF)
  373. {
  374. if (_logger)
  375. {
  376. _logger->logString("*** ASSEMBER WARNING - Absolute address truncated to 32-bits.\n");
  377. }
  378. target &= 0xFFFFFFFF;
  379. }
  380. _emitInt32( (int32_t)((uint32_t)target) );
  381. }
  382. #endif // ASMJIT_X64
  383. }
  384. }
  385. void AssemblerCore::_emitModRM(
  386. uint8_t opReg, const Operand& op, sysint_t immSize) ASMJIT_NOTHROW
  387. {
  388. ASMJIT_ASSERT(op.getType() == OPERAND_REG || op.getType() == OPERAND_MEM);
  389. if (op.getType() == OPERAND_REG)
  390. _emitModR(opReg, reinterpret_cast<const BaseReg&>(op).getRegCode());
  391. else
  392. _emitModM(opReg, reinterpret_cast<const Mem&>(op), immSize);
  393. }
  394. void AssemblerCore::_emitX86Inl(
  395. uint32_t opCode, uint8_t i16bit, uint8_t rexw, uint8_t reg, bool forceRexPrefix) ASMJIT_NOTHROW
  396. {
  397. // 16-bit prefix.
  398. if (i16bit) _emitByte(0x66);
  399. // Instruction prefix.
  400. if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24));
  401. // REX prefix.
  402. #if defined(ASMJIT_X64)
  403. _emitRexR(rexw, 0, reg, forceRexPrefix);
  404. #endif // ASMJIT_X64
  405. // Instruction opcodes.
  406. if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16));
  407. if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8));
  408. _emitByte((uint8_t)(opCode & 0x000000FF) + (reg & 0x7));
  409. }
  410. void AssemblerCore::_emitX86RM(
  411. uint32_t opCode, uint8_t i16bit, uint8_t rexw, uint8_t o,
  412. const Operand& op, sysint_t immSize, bool forceRexPrefix) ASMJIT_NOTHROW
  413. {
  414. // 16-bit prefix.
  415. if (i16bit) _emitByte(0x66);
  416. // Segment prefix.
  417. _emitSegmentPrefix(op);
  418. // Instruction prefix.
  419. if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24));
  420. // REX prefix.
  421. #if defined(ASMJIT_X64)
  422. _emitRexRM(rexw, o, op, forceRexPrefix);
  423. #endif // ASMJIT_X64
  424. // Instruction opcodes.
  425. if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16));
  426. if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8));
  427. _emitByte((uint8_t)(opCode & 0x000000FF));
  428. // Mod R/M.
  429. _emitModRM(o, op, immSize);
  430. }
  431. void AssemblerCore::_emitFpu(uint32_t opCode) ASMJIT_NOTHROW
  432. {
  433. _emitOpCode(opCode);
  434. }
  435. void AssemblerCore::_emitFpuSTI(uint32_t opCode, uint32_t sti) ASMJIT_NOTHROW
  436. {
  437. // Illegal stack offset.
  438. ASMJIT_ASSERT(0 <= sti && sti < 8);
  439. _emitOpCode(opCode + sti);
  440. }
  441. void AssemblerCore::_emitFpuMEM(uint32_t opCode, uint8_t opReg, const Mem& mem) ASMJIT_NOTHROW
  442. {
  443. // Segment prefix.
  444. _emitSegmentPrefix(mem);
  445. // Instruction prefix.
  446. if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24));
  447. // REX prefix.
  448. #if defined(ASMJIT_X64)
  449. _emitRexRM(0, opReg, mem, false);
  450. #endif // ASMJIT_X64
  451. // Instruction opcodes.
  452. if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16));
  453. if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8));
  454. _emitByte((uint8_t)((opCode & 0x000000FF)));
  455. _emitModM(opReg, mem, 0);
  456. }
  457. void AssemblerCore::_emitMmu(uint32_t opCode, uint8_t rexw, uint8_t opReg,
  458. const Operand& src, sysint_t immSize) ASMJIT_NOTHROW
  459. {
  460. // Segment prefix.
  461. _emitSegmentPrefix(src);
  462. // Instruction prefix.
  463. if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24));
  464. // REX prefix.
  465. #if defined(ASMJIT_X64)
  466. _emitRexRM(rexw, opReg, src, false);
  467. #endif // ASMJIT_X64
  468. // Instruction opcodes.
  469. if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16));
  470. // No checking, MMX/SSE instructions have always two opcodes or more.
  471. _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8));
  472. _emitByte((uint8_t)((opCode & 0x000000FF)));
  473. if (src.isReg())
  474. _emitModR(opReg, reinterpret_cast<const BaseReg&>(src).getRegCode());
  475. else
  476. _emitModM(opReg, reinterpret_cast<const Mem&>(src), immSize);
  477. }
  478. AssemblerCore::LabelLink* AssemblerCore::_emitDisplacement(
  479. LabelData& l_data, sysint_t inlinedDisplacement, int size) ASMJIT_NOTHROW
  480. {
  481. ASMJIT_ASSERT(l_data.offset == -1);
  482. ASMJIT_ASSERT(size == 1 || size == 4);
  483. // Chain with label.
  484. LabelLink* link = _newLabelLink();
  485. link->prev = l_data.links;
  486. link->offset = getOffset();
  487. link->displacement = inlinedDisplacement;
  488. l_data.links = link;
  489. // Emit label size as dummy data.
  490. if (size == 1)
  491. _emitByte(0x01);
  492. else // if (size == 4)
  493. _emitDWord(0x04040404);
  494. return link;
  495. }
  496. void AssemblerCore::_emitJmpOrCallReloc(uint32_t instruction, void* target) ASMJIT_NOTHROW
  497. {
  498. RelocData rd;
  499. rd.type = RelocData::ABSOLUTE_TO_RELATIVE_TRAMPOLINE;
  500. #if defined(ASMJIT_X64)
  501. // If we are compiling in 64-bit mode, we can use trampoline if relative jump
  502. // is not possible.
  503. _trampolineSize += TrampolineWriter::TRAMPOLINE_SIZE;
  504. #endif // ARCHITECTURE_SPECIFIC
  505. rd.size = 4;
  506. rd.offset = getOffset();
  507. rd.address = target;
  508. _relocData.append(rd);
  509. // Emit dummy 32-bit integer (will be overwritten by relocCode()).
  510. _emitInt32(0);
  511. }
  512. // Logging helpers.
  513. static const char* operandSize[] =
  514. {
  515. NULL,
  516. "byte ptr ",
  517. "word ptr ",
  518. NULL,
  519. "dword ptr ",
  520. NULL,
  521. NULL,
  522. NULL,
  523. "qword ptr ",
  524. NULL,
  525. "tword ptr ",
  526. NULL,
  527. NULL,
  528. NULL,
  529. NULL,
  530. NULL,
  531. "dqword ptr "
  532. };
  533. static const char segmentPrefixName[] =
  534. "es:\0"
  535. "cs:\0"
  536. "ss:\0"
  537. "ds:\0"
  538. "fs:\0"
  539. "gs:\0"
  540. "\0\0\0\0";
  541. ASMJIT_HIDDEN char* dumpInstructionName(char* buf, uint32_t code) ASMJIT_NOTHROW
  542. {
  543. ASMJIT_ASSERT(code < _INST_COUNT);
  544. return Util::mycpy(buf, instructionDescription[code].getName());
  545. }
  546. ASMJIT_HIDDEN char* dumpRegister(char* buf, uint32_t type, uint32_t index) ASMJIT_NOTHROW
  547. {
  548. // NE == Not-Encodable.
  549. const char reg8l[] = "al\0\0" "cl\0\0" "dl\0\0" "bl\0\0" "spl\0" "bpl\0" "sil\0" "dil\0" ;
  550. const char reg8h[] = "ah\0\0" "ch\0\0" "dh\0\0" "bh\0\0" "NE\0\0" "NE\0\0" "NE\0\0" "NE\0\0";
  551. const char reg16[] = "ax\0\0" "cx\0\0" "dx\0\0" "bx\0\0" "sp\0\0" "bp\0\0" "si\0\0" "di\0\0";
  552. switch (type)
  553. {
  554. case REG_TYPE_GPB_LO:
  555. if (index < 8)
  556. return Util::mycpy(buf, &reg8l[index*4]);
  557. *buf++ = 'r';
  558. goto _EmitID;
  559. case REG_TYPE_GPB_HI:
  560. if (index < 4)
  561. return Util::mycpy(buf, &reg8h[index*4]);
  562. _EmitNE:
  563. return Util::mycpy(buf, "NE");
  564. case REG_TYPE_GPW:
  565. if (index < 8)
  566. return Util::mycpy(buf, &reg16[index*4]);
  567. *buf++ = 'r';
  568. buf = Util::myutoa(buf, index);
  569. *buf++ = 'w';
  570. return buf;
  571. case REG_TYPE_GPD:
  572. if (index < 8)
  573. {
  574. *buf++ = 'e';
  575. return Util::mycpy(buf, &reg16[index*4]);
  576. }
  577. *buf++ = 'r';
  578. buf = Util::myutoa(buf, index);
  579. *buf++ = 'd';
  580. return buf;
  581. case REG_TYPE_GPQ:
  582. *buf++ = 'r';
  583. if (index < 8)
  584. return Util::mycpy(buf, &reg16[index*4]);
  585. _EmitID:
  586. return Util::myutoa(buf, index);
  587. case REG_TYPE_X87:
  588. *buf++ = 's';
  589. *buf++ = 't';
  590. goto _EmitID;
  591. case REG_TYPE_MM:
  592. *buf++ = 'm';
  593. *buf++ = 'm';
  594. goto _EmitID;
  595. case REG_TYPE_XMM:
  596. *buf++ = 'x';
  597. *buf++ = 'm';
  598. *buf++ = 'm';
  599. goto _EmitID;
  600. case REG_TYPE_YMM:
  601. *buf++ = 'y';
  602. *buf++ = 'm';
  603. *buf++ = 'm';
  604. goto _EmitID;
  605. case REG_TYPE_SEGMENT:
  606. if (index < REG_NUM_SEGMENT)
  607. return Util::mycpy(buf, &segmentPrefixName[index*4], 2);
  608. goto _EmitNE;
  609. default:
  610. return buf;
  611. }
  612. }
  613. ASMJIT_HIDDEN char* dumpOperand(char* buf, const Operand* op, uint32_t memRegType) ASMJIT_NOTHROW
  614. {
  615. if (op->isReg())
  616. {
  617. const BaseReg& reg = reinterpret_cast<const BaseReg&>(*op);
  618. return dumpRegister(buf, reg.getRegType(), reg.getRegIndex());
  619. }
  620. else if (op->isMem())
  621. {
  622. const Mem& mem = reinterpret_cast<const Mem&>(*op);
  623. uint32_t segmentPrefix = mem.getSegmentPrefix();
  624. bool isAbsolute = false;
  625. if (op->getSize() <= 16)
  626. {
  627. buf = Util::mycpy(buf, operandSize[op->getSize()]);
  628. }
  629. if (segmentPrefix < REG_NUM_SEGMENT)
  630. {
  631. buf = Util::mycpy(buf, &segmentPrefixName[segmentPrefix * 4]);
  632. }
  633. *buf++ = '[';
  634. switch (mem.getMemType())
  635. {
  636. case OPERAND_MEM_NATIVE:
  637. {
  638. // [base + index*scale + displacement]
  639. buf = dumpRegister(buf, memRegType, mem.getBase());
  640. break;
  641. }
  642. case OPERAND_MEM_LABEL:
  643. {
  644. // [label + index*scale + displacement]
  645. buf += sprintf(buf, "L.%u", mem.getBase() & OPERAND_ID_VALUE_MASK);
  646. break;
  647. }
  648. case OPERAND_MEM_ABSOLUTE:
  649. {
  650. // [absolute]
  651. isAbsolute = true;
  652. buf = Util::myutoa(buf, (sysuint_t)mem.getTarget(), 16);
  653. break;
  654. }
  655. }
  656. if (mem.hasIndex())
  657. {
  658. buf = Util::mycpy(buf, " + ");
  659. buf = dumpRegister(buf, memRegType, mem.getIndex());
  660. if (mem.getShift())
  661. {
  662. buf = Util::mycpy(buf, " * ");
  663. *buf++ = "1248"[mem.getShift() & 3];
  664. }
  665. }
  666. if (mem.getDisplacement() && !isAbsolute)
  667. {
  668. sysint_t d = mem.getDisplacement();
  669. *buf++ = ' ';
  670. *buf++ = (d < 0) ? '-' : '+';
  671. *buf++ = ' ';
  672. buf = Util::myutoa(buf, d < 0 ? -d : d);
  673. }
  674. *buf++ = ']';
  675. return buf;
  676. }
  677. else if (op->isImm())
  678. {
  679. const Imm& i = reinterpret_cast<const Imm&>(*op);
  680. return Util::myitoa(buf, (sysint_t)i.getValue());
  681. }
  682. else if (op->isLabel())
  683. {
  684. return buf + sprintf(buf, "L.%u", op->getId() & OPERAND_ID_VALUE_MASK);
  685. }
  686. else
  687. {
  688. return Util::mycpy(buf, "None");
  689. }
  690. }
  691. static char* dumpInstruction(char* buf,
  692. uint32_t code,
  693. uint32_t emitOptions,
  694. const Operand* o0,
  695. const Operand* o1,
  696. const Operand* o2,
  697. uint32_t memRegType) ASMJIT_NOTHROW
  698. {
  699. if (emitOptions & EMIT_OPTION_REX_PREFIX ) buf = Util::mycpy(buf, "rex ", 4);
  700. if (emitOptions & EMIT_OPTION_LOCK_PREFIX) buf = Util::mycpy(buf, "lock ", 5);
  701. if (emitOptions & EMIT_OPTION_SHORT_JUMP ) buf = Util::mycpy(buf, "short ", 6);
  702. // Dump instruction.
  703. buf = dumpInstructionName(buf, code);
  704. // Dump operands.
  705. if (!o0->isNone()) { *buf++ = ' '; buf = dumpOperand(buf, o0, memRegType); }
  706. if (!o1->isNone()) { *buf++ = ','; *buf++ = ' '; buf = dumpOperand(buf, o1, memRegType); }
  707. if (!o2->isNone()) { *buf++ = ','; *buf++ = ' '; buf = dumpOperand(buf, o2, memRegType); }
  708. return buf;
  709. }
  710. static char* dumpComment(char* buf, sysuint_t len, const uint8_t* binaryData, sysuint_t binaryLen, const char* comment)
  711. {
  712. sysuint_t currentLength = len;
  713. sysuint_t commentLength = comment ? strlen(comment) : 0;
  714. if (binaryLen || commentLength)
  715. {
  716. sysuint_t align = 32;
  717. char sep = ';';
  718. // Truncate if comment is too long (it shouldn't be, larger than 80 seems to
  719. // be an exploit).
  720. if (commentLength > 80) commentLength = 80;
  721. for (sysuint_t i = (binaryLen == 0); i < 2; i++)
  722. {
  723. char* bufBegin = buf;
  724. // Append align.
  725. if (currentLength < align)
  726. {
  727. buf = Util::myfill(buf, ' ', align - currentLength);
  728. }
  729. // Append separator.
  730. if (sep)
  731. {
  732. *buf++ = sep;
  733. *buf++ = ' ';
  734. }
  735. // Append binary data or comment.
  736. if (i == 0)
  737. {
  738. buf = Util::myhex(buf, binaryData, binaryLen);
  739. if (commentLength == 0) break;
  740. }
  741. else
  742. {
  743. buf = Util::mycpy(buf, comment, commentLength);
  744. }
  745. currentLength += (sysuint_t)(buf - bufBegin);
  746. align += 18;
  747. sep = '|';
  748. }
  749. }
  750. *buf++ = '\n';
  751. return buf;
  752. }
  753. // Used for NULL operands to translate them to OPERAND_NONE.
  754. static const uint8_t _none[sizeof(Operand)] =
  755. {
  756. 0
  757. };
  758. static const Operand::RegData _patchedHiRegs[4] =
  759. {// op , size, { reserved0, reserved1 }, id , code
  760. { OPERAND_REG, 1 , { 0 , 0 }, INVALID_VALUE, REG_TYPE_GPB_LO | 4 },
  761. { OPERAND_REG, 1 , { 0 , 0 }, INVALID_VALUE, REG_TYPE_GPB_LO | 5 },
  762. { OPERAND_REG, 1 , { 0 , 0 }, INVALID_VALUE, REG_TYPE_GPB_LO | 6 },
  763. { OPERAND_REG, 1 , { 0 , 0 }, INVALID_VALUE, REG_TYPE_GPB_LO | 7 }
  764. };
  765. void AssemblerCore::_emitInstruction(uint32_t code) ASMJIT_NOTHROW
  766. {
  767. _emitInstruction(code, NULL, NULL, NULL);
  768. }
  769. void AssemblerCore::_emitInstruction(uint32_t code, const Operand* o0) ASMJIT_NOTHROW
  770. {
  771. _emitInstruction(code, o0, NULL, NULL);
  772. }
  773. void AssemblerCore::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1) ASMJIT_NOTHROW
  774. {
  775. _emitInstruction(code, o0, o1, NULL);
  776. }
  777. void AssemblerCore::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2) ASMJIT_NOTHROW
  778. {
  779. const Operand* _loggerOperands[3];
  780. uint32_t bLoHiUsed = 0;
  781. #if defined(ASMJIT_X86)
  782. uint32_t forceRexPrefix = false;
  783. #else
  784. uint32_t forceRexPrefix = _emitOptions & EMIT_OPTION_REX_PREFIX;
  785. #endif
  786. uint32_t memRegType = REG_TYPE_GPN;
  787. #if defined(ASMJIT_DEBUG)
  788. bool assertIllegal = false;
  789. #endif // ASMJIT_DEBUG
  790. const Imm* immOperand = NULL;
  791. uint32_t immSize;
  792. #define _FINISHED() \
  793. goto end
  794. #define _FINISHED_IMMEDIATE(_Operand_, _Size_) \
  795. do { \
  796. immOperand = reinterpret_cast<const Imm*>(_Operand_); \
  797. immSize = (_Size_); \
  798. goto emitImmediate; \
  799. } while (0)
  800. // Convert operands to OPERAND_NONE if needed.
  801. if (o0 == NULL) { o0 = reinterpret_cast<const Operand*>(_none); } else if (o0->isReg()) { bLoHiUsed |= o0->_reg.code & (REG_TYPE_GPB_LO | REG_TYPE_GPB_HI); }
  802. if (o1 == NULL) { o1 = reinterpret_cast<const Operand*>(_none); } else if (o1->isReg()) { bLoHiUsed |= o1->_reg.code & (REG_TYPE_GPB_LO | REG_TYPE_GPB_HI); }
  803. if (o2 == NULL) { o2 = reinterpret_cast<const Operand*>(_none); } else if (o2->isReg()) { bLoHiUsed |= o2->_reg.code & (REG_TYPE_GPB_LO | REG_TYPE_GPB_HI); }
  804. sysuint_t beginOffset = getOffset();
  805. const InstructionDescription* id = &instructionDescription[code];
  806. if (code >= _INST_COUNT)
  807. {
  808. setError(ERROR_UNKNOWN_INSTRUCTION);
  809. goto cleanup;
  810. }
  811. // Check if register operand is BPL, SPL, SIL, DIL and do action that depends
  812. // to current mode:
  813. // - 64-bit: - Force REX prefix.
  814. //
  815. // Check if register operand is AH, BH, CH or DH and do action that depends
  816. // to current mode:
  817. // - 32-bit: - Patch operand index (index += 4), because we are using
  818. // different index what is used in opcode.
  819. // - 64-bit: - Check whether there is REX prefix and raise error if it is.
  820. // - Do the same as in 32-bit mode - patch register index.
  821. //
  822. // NOTE: This is a hit hacky, but I added this to older code-base and I have
  823. // no energy to rewrite it. Maybe in future all of this can be cleaned up!
  824. if (bLoHiUsed | forceRexPrefix)
  825. {
  826. _loggerOperands[0] = o0;
  827. _loggerOperands[1] = o1;
  828. _loggerOperands[2] = o2;
  829. #if defined(ASMJIT_X64)
  830. // Check if there is register that makes this instruction un-encodable.
  831. forceRexPrefix |= (uint32_t)o0->isExtendedRegisterUsed();
  832. forceRexPrefix |= (uint32_t)o1->isExtendedRegisterUsed();
  833. forceRexPrefix |= (uint32_t)o2->isExtendedRegisterUsed();
  834. if (o0->isRegType(REG_TYPE_GPB_LO) && (o0->_reg.code & REG_INDEX_MASK) >= 4) forceRexPrefix = true;
  835. else if (o1->isRegType(REG_TYPE_GPB_LO) && (o1->_reg.code & REG_INDEX_MASK) >= 4) forceRexPrefix = true;
  836. else if (o2->isRegType(REG_TYPE_GPB_LO) && (o2->_reg.code & REG_INDEX_MASK) >= 4) forceRexPrefix = true;
  837. if ((bLoHiUsed & REG_TYPE_GPB_HI) != 0 && forceRexPrefix)
  838. {
  839. goto illegalInstruction;
  840. }
  841. #endif // ASMJIT_X64
  842. // Patch GPB.HI operand index.
  843. if ((bLoHiUsed & REG_TYPE_GPB_HI) != 0)
  844. {
  845. if (o0->isRegType(REG_TYPE_GPB_HI)) o0 = reinterpret_cast<const Operand*>(&_patchedHiRegs[o0->_reg.code & REG_INDEX_MASK]);
  846. if (o1->isRegType(REG_TYPE_GPB_HI)) o1 = reinterpret_cast<const Operand*>(&_patchedHiRegs[o1->_reg.code & REG_INDEX_MASK]);
  847. if (o2->isRegType(REG_TYPE_GPB_HI)) o2 = reinterpret_cast<const Operand*>(&_patchedHiRegs[o2->_reg.code & REG_INDEX_MASK]);
  848. }
  849. }
  850. // Check for buffer space (and grow if needed).
  851. if (!canEmit()) goto cleanup;
  852. if (_emitOptions & EMIT_OPTION_LOCK_PREFIX)
  853. {
  854. if (!id->isLockable()) goto illegalInstruction;
  855. _emitByte(0xF0);
  856. }
  857. switch (id->group)
  858. {
  859. case InstructionDescription::G_EMIT:
  860. {
  861. _emitOpCode(id->opCode[0]);
  862. _FINISHED();
  863. }
  864. case InstructionDescription::G_ALU:
  865. {
  866. uint32_t opCode = id->opCode[0];
  867. uint8_t opReg = (uint8_t)id->opCodeR;
  868. // Mem <- Reg
  869. if (o0->isMem() && o1->isReg())
  870. {
  871. _emitX86RM(opCode + (o1->getSize() != 1),
  872. o1->getSize() == 2,
  873. o1->getSize() == 8,
  874. reinterpret_cast<const GPReg&>(*o1).getRegCode(),
  875. reinterpret_cast<const Operand&>(*o0),
  876. 0, forceRexPrefix);
  877. _FINISHED();
  878. }
  879. // Reg <- Reg|Mem
  880. if (o0->isReg() && o1->isRegMem())
  881. {
  882. _emitX86RM(opCode + 2 + (o0->getSize() != 1),
  883. o0->getSize() == 2,
  884. o0->getSize() == 8,
  885. reinterpret_cast<const GPReg&>(*o0).getRegCode(),
  886. reinterpret_cast<const Operand&>(*o1),
  887. 0, forceRexPrefix);
  888. _FINISHED();
  889. }
  890. // AL, AX, EAX, RAX register shortcuts
  891. if (o0->isRegIndex(0) && o1->isImm())
  892. {
  893. if (o0->getSize() == 2)
  894. _emitByte(0x66); // 16-bit.
  895. else if (o0->getSize() == 8)
  896. _emitByte(0x48); // REX.W.
  897. _emitByte((opReg << 3) | (0x04 + (o0->getSize() != 1)));
  898. _FINISHED_IMMEDIATE(o1, o0->getSize() <= 4 ? o0->getSize() : 4);
  899. }
  900. if (o0->isRegMem() && o1->isImm())
  901. {
  902. const Imm& imm = reinterpret_cast<const Imm&>(*o1);
  903. immSize = Util::isInt8(imm.getValue()) ? 1 : (o0->getSize() <= 4 ? o0->getSize() : 4);
  904. _emitX86RM(id->opCode[1] + (o0->getSize() != 1 ? (immSize != 1 ? 1 : 3) : 0),
  905. o0->getSize() == 2,
  906. o0->getSize() == 8,
  907. opReg, reinterpret_cast<const Operand&>(*o0),
  908. immSize, forceRexPrefix);
  909. _FINISHED_IMMEDIATE(&imm, immSize);
  910. }
  911. break;
  912. }
  913. case InstructionDescription::G_BSWAP:
  914. {
  915. if (o0->isReg())
  916. {
  917. const GPReg& dst = reinterpret_cast<const GPReg&>(*o0);
  918. #if defined(ASMJIT_X64)
  919. _emitRexR(dst.getRegType() == REG_TYPE_GPQ, 1, dst.getRegCode(), forceRexPrefix);
  920. #endif // ASMJIT_X64
  921. _emitByte(0x0F);
  922. _emitModR(1, dst.getRegCode());
  923. _FINISHED();
  924. }
  925. break;
  926. }
  927. case InstructionDescription::G_BT:
  928. {
  929. if (o0->isRegMem() && o1->isReg())
  930. {
  931. const Operand& dst = reinterpret_cast<const Operand&>(*o0);
  932. const GPReg& src = reinterpret_cast<const GPReg&>(*o1);
  933. _emitX86RM(id->opCode[0],
  934. src.isRegType(REG_TYPE_GPW),
  935. src.isRegType(REG_TYPE_GPQ),
  936. src.getRegCode(),
  937. dst,
  938. 0, forceRexPrefix);
  939. _FINISHED();
  940. }
  941. if (o0->isRegMem() && o1->isImm())
  942. {
  943. const Operand& dst = reinterpret_cast<const Operand&>(*o0);
  944. const Imm& src = reinterpret_cast<const Imm&>(*o1);
  945. _emitX86RM(id->opCode[1],
  946. dst.getSize() == 2,
  947. dst.getSize() == 8,
  948. (uint8_t)id->opCodeR,
  949. dst,
  950. 1, forceRexPrefix);
  951. _FINISHED_IMMEDIATE(o1, 1);
  952. }
  953. break;
  954. }
  955. case InstructionDescription::G_CALL:
  956. {
  957. if (o0->isRegTypeMem(REG_TYPE_GPN))
  958. {
  959. const Operand& dst = reinterpret_cast<const Operand&>(*o0);
  960. _emitX86RM(0xFF,
  961. 0,
  962. 0, 2, dst,
  963. 0, forceRexPrefix);
  964. _FINISHED();
  965. }
  966. if (o0->isImm())
  967. {
  968. const Imm& imm = reinterpret_cast<const Imm&>(*o0);
  969. _emitByte(0xE8);
  970. _emitJmpOrCallReloc(InstructionDescription::G_CALL, (void*)imm.getValue());
  971. _FINISHED();
  972. }
  973. if (o0->isLabel())
  974. {
  975. LabelData& l_data = _labelData[reinterpret_cast<const Label*>(o0)->getId() & OPERAND_ID_VALUE_MASK];
  976. if (l_data.offset != -1)
  977. {
  978. // Bound label.
  979. static const sysint_t rel32_size = 5;
  980. sysint_t offs = l_data.offset - getOffset();
  981. ASMJIT_ASSERT(offs <= 0);
  982. _emitByte(0xE8);
  983. _emitInt32((int32_t)(offs - rel32_size));
  984. }
  985. else
  986. {
  987. // Non-bound label.
  988. _emitByte(0xE8);
  989. _emitDisplacement(l_data, -4, 4);
  990. }
  991. _FINISHED();
  992. }
  993. break;
  994. }
  995. case InstructionDescription::G_CRC32:
  996. {
  997. if (o0->isReg() && o1->isRegMem())
  998. {
  999. const GPReg& dst = reinterpret_cast<const GPReg&>(*o0);
  1000. const Operand& src = reinterpret_cast<const Operand&>(*o1);
  1001. ASMJIT_ASSERT(dst.getRegType() == REG_TYPE_GPD || dst.getRegType() == REG_TYPE_GPQ);
  1002. _emitX86RM(id->opCode[0] + (src.getSize() != 1),
  1003. src.getSize() == 2,
  1004. dst.getRegType() == 8, dst.getRegCode(), src,
  1005. 0, forceRexPrefix);
  1006. _FINISHED();
  1007. }
  1008. break;
  1009. }
  1010. case InstructionDescription::G_ENTER:
  1011. {
  1012. if (o0->isImm() && o1->isImm())
  1013. {
  1014. _emitByte(0xC8);
  1015. _emitWord((uint16_t)(sysuint_t)reinterpret_cast<const Imm&>(*o2).getValue());
  1016. _emitByte((uint8_t )(sysuint_t)reinterpret_cast<const Imm&>(*o1).getValue());
  1017. _FINISHED();
  1018. }
  1019. break;
  1020. }
  1021. case InstructionDescription::G_IMUL:
  1022. {
  1023. // 1 operand
  1024. if (o0->isRegMem() && o1->isNone() && o2->isNone())
  1025. {
  1026. const Operand& src = reinterpret_cast<const Operand&>(*o0);
  1027. _emitX86RM(0xF6 + (src.getSize() != 1),
  1028. src.getSize() == 2,
  1029. src.getSize() == 8, 5, src,
  1030. 0, forceRexPrefix);
  1031. _FINISHED();
  1032. }
  1033. // 2 operands
  1034. else if (o0->isReg() && !o1->isNone() && o2->isNone())
  1035. {
  1036. const GPReg& dst = reinterpret_cast<const GPReg&>(*o0);
  1037. ASMJIT_ASSERT(!dst.isRegType(REG_TYPE_GPW));
  1038. if (o1->isRegMem())
  1039. {
  1040. const Operand& src = reinterpret_cast<const Operand&>(*o1);
  1041. _emitX86RM(0x0FAF,
  1042. dst.isRegType(REG_TYPE_GPW),
  1043. dst.isRegType(REG_TYPE_GPQ), dst.getRegCode(), src,
  1044. 0, forceRexPrefix);
  1045. _FINISHED();
  1046. }
  1047. else if (o1->isImm())
  1048. {
  1049. const Imm& imm = reinterpret_cast<const Imm&>(*o1);
  1050. if (Util::isInt8(imm.getValue()))
  1051. {
  1052. _emitX86RM(0x6B,
  1053. dst.isRegType(REG_TYPE_GPW),
  1054. dst.isRegType(REG_TYPE_GPQ), dst.getRegCode(), dst,
  1055. 1, forceRexPrefix);
  1056. _FINISHED_IMMEDIATE(&imm, 1);
  1057. }
  1058. else
  1059. {
  1060. immSize = dst.isRegType(REG_TYPE_GPW) ? 2 : 4;
  1061. _emitX86RM(0x69,
  1062. dst.isRegType(REG_TYPE_GPW),
  1063. dst.isRegType(REG_TYPE_GPQ), dst.getRegCode(), dst,
  1064. immSize, forceRexPrefix);
  1065. _FINISHED_IMMEDIATE(&imm, immSize);
  1066. }
  1067. }
  1068. }
  1069. // 3 operands
  1070. else if (o0->isReg() && o1->isRegMem() && o2->isImm())
  1071. {
  1072. const GPReg& dst = reinterpret_cast<const GPReg&>(*o0);
  1073. const Operand& src = reinterpret_cast<const Operand&>(*o1);
  1074. const Imm& imm = reinterpret_cast<const Imm&>(*o2);
  1075. if (Util::isInt8(imm.getValue()))
  1076. {
  1077. _emitX86RM(0x6B,
  1078. dst.isRegType(REG_TYPE_GPW),
  1079. dst.isRegType(REG_TYPE_GPQ), dst.getRegCode(), src,
  1080. 1, forceRexPrefix);
  1081. _FINISHED_IMMEDIATE(&imm, 1);
  1082. }
  1083. else
  1084. {
  1085. immSize = dst.isRegType(REG_TYPE_GPW) ? 2 : 4;
  1086. _emitX86RM(0x69,
  1087. dst.isRegType(REG_TYPE_GPW),
  1088. dst.isRegType(REG_TYPE_GPQ), dst.getRegCode(), src,
  1089. immSize, forceRexPrefix);
  1090. _FINISHED_IMMEDIATE(&imm, immSize);
  1091. }
  1092. }
  1093. break;
  1094. }
  1095. case InstructionDescription::G_INC_DEC:
  1096. {
  1097. if (o0->isRegMem())
  1098. {
  1099. const Operand& dst = reinterpret_cast<const Operand&>(*o0);
  1100. // INC [r16|r32] in 64-bit mode is not encodable.
  1101. #if defined(ASMJIT_X86)
  1102. if ((dst.isReg()) && (dst.isRegType(REG_TYPE_GPW) || dst.isRegType(REG_TYPE_GPD)))
  1103. {
  1104. _emitX86Inl(id->opCode[0],
  1105. dst.isRegType(REG_TYPE_GPW),
  1106. 0, reinterpret_cast<const BaseReg&>(dst).getRegCode(),
  1107. false);
  1108. _FINISHED();
  1109. }
  1110. #endif // ASMJIT_X86
  1111. _emitX86RM(id->opCode[1] + (dst.getSize() != 1),
  1112. dst.getSize() == 2,
  1113. dst.getSize() == 8, (uint8_t)id->opCodeR, dst,
  1114. 0, forceRexPrefix);
  1115. _FINISHED();
  1116. }
  1117. break;
  1118. }
  1119. case InstructionDescription::G_J:
  1120. {
  1121. if (o0->isLabel())
  1122. {
  1123. LabelData& l_data = _labelData[reinterpret_cast<const Label*>(o0)->getId() & OPERAND_ID_VALUE_MASK];
  1124. uint32_t hint = (uint32_t)(o1->isImm() ? reinterpret_cast<const Imm&>(*o1).getValue() : 0);
  1125. bool isShortJump = (_emitOptions & EMIT_OPTION_SHORT_JUMP) != 0;
  1126. // Emit jump hint if configured for that.
  1127. if ((hint & (HINT_TAKEN | HINT_NOT_TAKEN)) && (_properties & (1 << PROPERTY_JUMP_HINTS)))
  1128. {
  1129. if (hint & HINT_TAKEN)
  1130. _emitByte(HINT_BYTE_VALUE_TAKEN);
  1131. else if (hint & HINT_NOT_TAKEN)
  1132. _emitByte(HINT_BYTE_VALUE_NOT_TAKEN);
  1133. }
  1134. if (l_data.offset != -1)
  1135. {
  1136. // Bound label.
  1137. static const sysint_t rel8_size = 2;
  1138. static const sysint_t rel32_size = 6;
  1139. sysint_t offs = l_data.offset - getOffset();
  1140. ASMJIT_ASSERT(offs <= 0);
  1141. if (Util::isInt8(offs - rel8_size))
  1142. {
  1143. _emitByte(0x70 | (uint8_t)id->opCode[0]);
  1144. _emitByte((uint8_t)(int8_t)(offs - rel8_size));
  1145. // Change the emit options so logger can log instruction correctly.
  1146. _emitOptions |= EMIT_OPTION_SHORT_JUMP;
  1147. }
  1148. else
  1149. {
  1150. if (isShortJump && _logger)
  1151. {
  1152. _logger->logString("*** ASSEMBLER WARNING: Emitting long conditional jump, but short jump instruction forced!\n");
  1153. _emitOptions &= ~EMIT_OPTION_SHORT_JUMP;
  1154. }
  1155. _emitByte(0x0F);
  1156. _emitByte(0x80 | (uint8_t)id->opCode[0]);
  1157. _emitInt32((int32_t)(offs - rel32_size));
  1158. }
  1159. }
  1160. else
  1161. {
  1162. // Non-bound label.
  1163. if (isShortJump)
  1164. {
  1165. _emitByte(0x70 | (uint8_t)id->opCode[0]);
  1166. _emitDisplacement(l_data, -1, 1);
  1167. }
  1168. else
  1169. {
  1170. _emitByte(0x0F);
  1171. _emitByte(0x80 | (uint8_t)id->opCode[0]);
  1172. _emitDisplacement(l_data, -4, 4);
  1173. }
  1174. }
  1175. _FINISHED();
  1176. }
  1177. break;
  1178. }
  1179. case InstructionDescription::G_JMP:
  1180. {
  1181. if (o0->isRegMem())
  1182. {
  1183. const Operand& dst = reinterpret_cast<const Operand&>(*o0);
  1184. _emitX86RM(0xFF,
  1185. 0,
  1186. 0, 4, dst,
  1187. 0, forceRexPrefix);
  1188. _FINISHED();
  1189. }
  1190. if (o0->isImm())
  1191. {
  1192. const Imm& imm = reinterpret_cast<const Imm&>(*o0);
  1193. _emitByte(0xE9);
  1194. _emitJmpOrCallReloc(InstructionDescription::G_JMP, (void*)imm.getValue());
  1195. _FINISHED();
  1196. }
  1197. if (o0->isLabel())
  1198. {
  1199. LabelData& l_data = _labelData[reinterpret_cast<const Label*>(o0)->getId() & OPERAND_ID_VALUE_MASK];
  1200. bool isShortJump = (_emitOptions & EMIT_OPTION_SHORT_JUMP) != 0;
  1201. if (l_data.offset != -1)
  1202. {
  1203. // Bound label.
  1204. const sysint_t rel8_size = 2;
  1205. const sysint_t rel32_size = 5;
  1206. sysint_t offs = l_data.offset - getOffset();
  1207. if (Util::isInt8(offs - rel8_size))
  1208. {
  1209. _emitByte(0xEB);
  1210. _emitByte((uint8_t)(int8_t)(offs - rel8_size));
  1211. // Change the emit options so logger can log instruction correctly.
  1212. _emitOptions |= EMIT_OPTION_SHORT_JUMP;
  1213. }
  1214. else
  1215. {
  1216. if (isShortJump)
  1217. {
  1218. if (_logger)
  1219. {
  1220. _logger->logString("*** ASSEMBLER WARNING: Emitting long jump, but short jump instruction forced!\n");
  1221. _emitOptions &= ~EMIT_OPTION_SHORT_JUMP;
  1222. }
  1223. }
  1224. _emitByte(0xE9);
  1225. _emitInt32((int32_t)(offs - rel32_size));
  1226. }
  1227. }
  1228. else
  1229. {
  1230. // Non-bound label.
  1231. if (isShortJump)
  1232. {
  1233. _emitByte(0xEB);
  1234. _emitDisplacement(l_data, -1, 1);
  1235. }
  1236. else
  1237. {
  1238. _emitByte(0xE9);
  1239. _emitDisplacement(l_data, -4, 4);
  1240. }
  1241. }
  1242. _FINISHED();
  1243. }
  1244. break;
  1245. }
  1246. case InstructionDescription::G_LEA:
  1247. {
  1248. if (o0->isReg() && o1->isMem())
  1249. {
  1250. const GPReg& dst = reinterpret_cast<const GPReg&>(*o0);
  1251. const Mem& src = reinterpret_cast<const Mem&>(*o1);
  1252. // Size override prefix support.
  1253. if (src.getSizePrefix())
  1254. {
  1255. _emitByte(0x67);
  1256. #if defined(ASMJIT_X86)
  1257. memRegType = REG_TYPE_GPW;
  1258. #else
  1259. memRegType = REG_TYPE_GPD;
  1260. #endif
  1261. }
  1262. _emitX86RM(0x8D,
  1263. dst.isRegType(REG_TYPE_GPW),
  1264. dst.isRegType(REG_TYPE_GPQ), dst.getRegCode(), src,
  1265. 0, forceRexPrefix);
  1266. _FINISHED();
  1267. }
  1268. break;
  1269. }
  1270. case InstructionDescription::G_M:
  1271. {
  1272. if (o0->isMem())
  1273. {
  1274. _emitX86RM(id->opCode[0], 0, (uint8_t)id->opCode[1], (uint8_t)id->opCodeR, reinterpret_cast<const Mem&>(*o0), 0, forceRexPrefix);
  1275. _FINISHED();
  1276. }
  1277. break;
  1278. }
  1279. case InstructionDescription::G_MOV:
  1280. {
  1281. const Operand& dst = *o0;
  1282. const Operand& src = *o1;
  1283. switch (dst.getType() << 4 | src.getType())
  1284. {
  1285. // Reg <- Reg/Mem
  1286. case (OPERAND_REG << 4) | OPERAND_REG:
  1287. {
  1288. // Reg <- Sreg
  1289. if (src.isRegType(REG_TYPE_SEGMENT))
  1290. {
  1291. ASMJIT_ASSERT(dst.isRegType(REG_TYPE_GPW) ||
  1292. dst.isRegType(REG_TYPE_GPD) ||
  1293. dst.isRegType(REG_TYPE_GPQ) );
  1294. _emitX86RM(0x8C,
  1295. dst.getSize() == 2,
  1296. dst.getSize() == 8,
  1297. reinterpret_cast<const SegmentReg&>(src).getRegCode(),
  1298. reinterpret_cast<const Operand&>(dst),
  1299. 0, forceRexPrefix);
  1300. _FINISHED();
  1301. }
  1302. // Sreg <- Reg/Mem
  1303. if (dst.isRegType(REG_TYPE_SEGMENT))
  1304. {
  1305. ASMJIT_ASSERT(src.isRegType(REG_TYPE_GPW ) ||
  1306. src.isRegType(REG_TYPE_GPD ) ||
  1307. src.isRegType(REG_TYPE_GPQ ) );
  1308. _Emit_Mov_Sreg_RM:
  1309. _emitX86RM(0x8E,
  1310. src.getSize() == 2,
  1311. src.getSize() == 8,
  1312. reinterpret_cast<const SegmentReg&>(dst).getRegCode(),
  1313. reinterpret_cast<const Operand&>(src),
  1314. 0, forceRexPrefix);
  1315. _FINISHED();
  1316. }
  1317. ASMJIT_ASSERT(src.isRegType(REG_TYPE_GPB_LO) ||
  1318. src.isRegType(REG_TYPE_GPB_HI) ||
  1319. src.isRegType(REG_TYPE_GPW ) ||
  1320. src.isRegType(REG_TYPE_GPD ) ||
  1321. src.isRegType(REG_TYPE_GPQ ) );
  1322. // ... fall through ...
  1323. }
  1324. case (OPERAND_REG << 4) | OPERAND_MEM:
  1325. {
  1326. // Sreg <- Mem
  1327. if (dst.isRegType(REG_TYPE_SEGMENT))
  1328. {
  1329. goto _Emit_Mov_Sreg_RM;
  1330. }
  1331. ASMJIT_ASSERT(dst.isRegType(REG_TYPE_GPB_LO) ||
  1332. dst.isRegType(REG_TYPE_GPB_HI) ||
  1333. dst.isRegType(REG_TYPE_GPW ) ||
  1334. dst.isRegType(REG_TYPE_GPD ) ||
  1335. dst.isRegType(REG_TYPE_GPQ ) );
  1336. _emitX86RM(0x0000008A + (dst.getSize() != 1),
  1337. dst.isRegType(REG_TYPE_GPW),
  1338. dst.isRegType(REG_TYPE_GPQ),
  1339. reinterpret_cast<const GPReg&>(dst).getRegCode(),
  1340. reinterpret_cast<const Operand&>(src),
  1341. 0, forceRexPrefix);
  1342. _FINISHED();
  1343. }
  1344. // Reg <- Imm
  1345. case (OPERAND_REG << 4) | OPERAND_IMM:
  1346. {
  1347. const GPReg& dst = reinterpret_cast<const GPReg&>(*o0);
  1348. const Imm& src = reinterpret_cast<const Imm&>(*o1);
  1349. // In 64-bit mode the immediate can be 64-bits long if the
  1350. // destination operand type is register (otherwise 32-bits).
  1351. immSize = dst.getSize();
  1352. #if defined(ASMJIT_X64)
  1353. // Optimize instruction size by using 32-bit immediate if value can
  1354. // fit into it.
  1355. if (immSize == 8 && Util::isInt32(src.getValue()))
  1356. {
  1357. _emitX86RM(0xC7,
  1358. 0, // 16BIT
  1359. 1, // REX.W
  1360. 0, // O
  1361. dst,
  1362. 0, forceRexPrefix);
  1363. immSize = 4;
  1364. }
  1365. else
  1366. {
  1367. #endif // ASMJIT_X64
  1368. _emitX86Inl((dst.getSize() == 1 ? 0xB0 : 0xB8),
  1369. dst.isRegType(REG_TYPE_GPW),
  1370. dst.isRegType(REG_TYPE_GPQ),
  1371. dst.getRegCode(), forceRexPrefix);
  1372. #if defined(ASMJIT_X64)
  1373. }
  1374. #endif // ASMJIT_X64
  1375. _FINISHED_IMMEDIATE(&src, immSize);
  1376. }
  1377. // Mem <- Reg/Sreg
  1378. case (OPERAND_MEM << 4) | OPERAND_REG:
  1379. {
  1380. if (src.isRegType(REG_TYPE_SEGMENT))
  1381. {
  1382. // Mem <- Sreg
  1383. _emitX86RM(0x8C,
  1384. dst.getSize() == 2,
  1385. dst.getSize() == 8,
  1386. reinterpret_cast<const SegmentReg&>(src).getRegCode(),
  1387. reinterpret_cast<const Operand&>(dst),
  1388. 0, forceRexPrefix);
  1389. _FINISHED();
  1390. }
  1391. else
  1392. {
  1393. // Mem <- Reg
  1394. ASMJIT_ASSERT(src.isRegType(REG_TYPE_GPB_LO) ||
  1395. src.isRegType(REG_TYPE_GPB_HI) ||
  1396. src.isRegType(REG_TYPE_GPW ) ||
  1397. src.isRegType(REG_TYPE_GPD ) ||
  1398. src.isRegType(REG_TYPE_GPQ ) );
  1399. _emitX86RM(0x88 + (src.getSize() != 1),
  1400. src.isRegType(REG_TYPE_GPW),
  1401. src.isRegType(REG_TYPE_GPQ),
  1402. reinterpret_cast<const GPReg&>(src).getRegCode(),
  1403. reinterpret_cast<const Operand&>(dst),
  1404. 0, forceRexPrefix);
  1405. _FINISHED();
  1406. }
  1407. }
  1408. // Mem <- Imm
  1409. case (OPERAND_MEM << 4) | OPERAND_IMM:
  1410. {
  1411. immSize = dst.getSize() <= 4 ? dst.getSize() : 4;
  1412. _emitX86RM(0xC6 + (dst.getSize() != 1),
  1413. dst.getSize() == 2,
  1414. dst.getSize() == 8,
  1415. 0,
  1416. reinterpret_cast<const Operand&>(dst),
  1417. immSize, forceRexPrefix);
  1418. _FINISHED_IMMEDIATE(&src, immSize);
  1419. }
  1420. }
  1421. break;
  1422. }
  1423. case InstructionDescription::G_MOV_PTR:
  1424. {
  1425. if ((o0->isReg() && o1->isImm()) || (o0->isImm() && o1->isReg()))
  1426. {
  1427. bool reverse = o1->getType() == OPERAND_REG;
  1428. uint8_t opCode = !reverse ? 0xA0 : 0xA2;
  1429. const GPReg& reg = reinterpret_cast<const GPReg&>(!reverse ? *o0 : *o1);
  1430. const Imm& imm = reinterpret_cast<const Imm&>(!reverse ? *o1 : *o0);
  1431. if (reg.getRegIndex() != 0) goto illegalInstruction;
  1432. if (reg.isRegType(REG_TYPE_GPW)) _emitByte(0x66);
  1433. #if defined(ASMJIT_X64)
  1434. _emitRexR(reg.getSize() == 8, 0, 0, forceRexPrefix);
  1435. #endif // ASMJIT_X64
  1436. _emitByte(opCode + (reg.getSize() != 1));
  1437. _FINISHED_IMMEDIATE(&imm, sizeof(sysint_t));
  1438. }
  1439. break;
  1440. }
  1441. case InstructionDescription::G_MOVSX_MOVZX:
  1442. {
  1443. if (o0->isReg() && o1->isRegMem())
  1444. {
  1445. const GPReg& dst = reinterpret_cast<const GPReg&>(*o0);
  1446. const Operand& src = reinterpret_cast<const Operand&>(*o1);
  1447. if (dst.getSize() == 1) goto illegalInstruction;
  1448. if (src.getSize() != 1 && src.getSize() != 2) goto illegalInstruction;
  1449. if (src.getSize() == 2 && dst.getSize() == 2) goto illegalInstruction;
  1450. _emitX86RM(id->opCode[0] + (src.getSize() != 1),
  1451. dst.isRegType(REG_TYPE_GPW),
  1452. dst.isRegType(REG_TYPE_GPQ),
  1453. dst.getRegCode(),
  1454. src,
  1455. 0, forceRexPrefix);
  1456. _FINISHED();
  1457. }
  1458. break;
  1459. }
  1460. #if defined(ASMJIT_X64)
  1461. case InstructionDescription::G_MOVSXD:
  1462. {
  1463. if (o0->isReg() && o1->isRegMem())
  1464. {
  1465. const GPReg& dst = reinterpret_cast<const GPReg&>(*o0);
  1466. const Operand& src = reinterpret_cast<const Operand&>(*o1);
  1467. _emitX86RM(0x00000063,
  1468. 0,
  1469. 1, dst.getRegCode(), src,
  1470. 0, forceRexPrefix);
  1471. _FINISHED();
  1472. }
  1473. break;
  1474. }
  1475. #endif // ASMJIT_X64
  1476. case InstructionDescription::G_PUSH:
  1477. {
  1478. // This section is only for immediates, memory/register operands are handled in G_POP.
  1479. if (o0->isImm())
  1480. {
  1481. const Imm& imm = reinterpret_cast<const Imm&>(*o0);
  1482. if (Util::isInt8(imm.getValue()))
  1483. {
  1484. _emitByte(0x6A);
  1485. _FINISHED_IMMEDIATE(&imm, 1);
  1486. }
  1487. else
  1488. {
  1489. _emitByte(0x68);
  1490. _FINISHED_IMMEDIATE(&imm, 4);
  1491. }
  1492. }
  1493. // ... goto G_POP ...
  1494. }
  1495. case InstructionDescription::G_POP:
  1496. {
  1497. if (o0->isReg())
  1498. {
  1499. ASMJIT_ASSERT(o0->isRegType(REG_TYPE_GPW) || o0->isRegType(REG_TYPE_GPN));
  1500. _emitX86Inl(id->opCode[0], o0->isRegType(REG_TYPE_GPW), 0, reinterpret_cast<const GPReg&>(*o0).getRegCode(), forceRexPrefix);
  1501. _FINISHED();
  1502. }
  1503. if (o0->isMem())
  1504. {
  1505. _emitX86RM(id->opCode[1], o0->getSize() == 2, 0, (uint8_t)id->opCodeR, reinterpret_cast<const Operand&>(*o0), 0, forceRexPrefix);
  1506. _FINISHED();
  1507. }
  1508. break;
  1509. }
  1510. case InstructionDescript