1 // [AsmJit]
2 // Complete JIT Assembler for C++ Language.
3 //
4 // [License]
5 // Zlib - See COPYING file in this package.
6 
7 #define ASMJIT_EXPORTS
8 
9 // [Dependencies - AsmJit]
10 #include "../core/assembler.h"
11 #include "../core/context.h"
12 #include "../core/cpuinfo.h"
13 #include "../core/defs.h"
14 #include "../core/intutil.h"
15 #include "../core/logger.h"
16 #include "../core/memorymanager.h"
17 #include "../core/memorymarker.h"
18 #include "../core/stringutil.h"
19 
20 #include "../x86/x86assembler.h"
21 #include "../x86/x86cpuinfo.h"
22 #include "../x86/x86defs.h"
23 #include "../x86/x86operand.h"
24 #include "../x86/x86util.h"
25 
26 // [Api-Begin]
27 #include "../core/apibegin.h"
28 
29 namespace AsmJit {
30 
31 // ============================================================================
32 // [Constants]
33 // ============================================================================
34 
35 enum { kMaxCommentLength = 80 };
36 
37 // ============================================================================
38 // [AsmJit::X64TrampolineWriter]
39 // ============================================================================
40 
41 #if defined(ASMJIT_X64)
42 //! @brief Class used to determine size of trampoline and as trampoline writer.
43 struct X64TrampolineWriter
44 {
45   // Size of trampoline
46   enum
47   {
48     kSizeJmp = 6,
49     kSizeAddr = 8,
50     kSizeTotal = kSizeJmp + kSizeAddr
51   };
52 
53   // Write trampoline into code at address @a code that will jump to @a target.
writeTrampolineAsmJit::X64TrampolineWriter54   static void writeTrampoline(uint8_t* code, uint64_t target)
55   {
56     code[0] = 0xFF;                                       // Jmp OpCode.
57     code[1] = 0x25;                                       // ModM (RIP addressing).
58     ((uint32_t*)(code + 2))[0] = 0;                       // Offset (zero).
59     ((uint64_t*)(code + kSizeJmp))[0] = (uint64_t)target; // Absolute address.
60   }
61 };
62 #endif // ASMJIT_X64
63 
64 // ============================================================================
65 // [AsmJit::X86Assembler - Construction / Destruction]
66 // ============================================================================
67 
X86Assembler(Context * context)68 X86Assembler::X86Assembler(Context* context) :
69   Assembler(context)
70 {
71   _properties = IntUtil::maskFromIndex(kX86PropertyOptimizedAlign);
72 }
73 
~X86Assembler()74 X86Assembler::~X86Assembler()
75 {
76 }
77 
78 // ============================================================================
79 // [AsmJit::X86Assembler - Buffer - Setters (X86-Extensions)]
80 // ============================================================================
81 
setVarAt(size_t pos,sysint_t i,uint8_t isUnsigned,uint32_t size)82 void X86Assembler::setVarAt(size_t pos, sysint_t i, uint8_t isUnsigned, uint32_t size)
83 {
84   if (size == 1 && !isUnsigned) setByteAt (pos, (int8_t  )i);
85   else if (size == 1 &&  isUnsigned) setByteAt (pos, (uint8_t )i);
86   else if (size == 2 && !isUnsigned) setWordAt (pos, (int16_t )i);
87   else if (size == 2 &&  isUnsigned) setWordAt (pos, (uint16_t)i);
88   else if (size == 4 && !isUnsigned) setDWordAt(pos, (int32_t )i);
89   else if (size == 4 &&  isUnsigned) setDWordAt(pos, (uint32_t)i);
90 
91 #if defined(ASMJIT_X64)
92   else if (size == 8 && !isUnsigned) setQWordAt(pos, (int64_t )i);
93   else if (size == 8 &&  isUnsigned) setQWordAt(pos, (uint64_t)i);
94 #endif // ASMJIT_X64
95 
96   else
97     ASMJIT_ASSERT(0);
98 }
99 
100 // ============================================================================
101 // [AsmJit::X86Assembler - Emit]
102 // ============================================================================
103 
_emitModM(uint8_t opReg,const Mem & mem,sysint_t immSize)104 void X86Assembler::_emitModM(
105   uint8_t opReg, const Mem& mem, sysint_t immSize)
106 {
107   ASMJIT_ASSERT(mem.getType() == kOperandMem);
108 
109   uint8_t baseReg = mem.getBase() & 0x7;
110   uint8_t indexReg = mem.getIndex() & 0x7;
111   sysint_t disp = mem.getDisplacement();
112   uint32_t shift = mem.getShift();
113 
114   if (mem.getMemType() == kOperandMemNative)
115   {
116     // [base + displacemnt]
117     if (!mem.hasIndex())
118     {
119       // ESP/RSP/R12 == 4
120       if (baseReg == 4)
121       {
122         uint8_t mod = 0;
123 
124         if (disp)
125           mod = IntUtil::isInt8(disp) ? 1 : 2;
126 
127         _emitMod(mod, opReg, 4);
128         _emitSib(0, 4, 4);
129 
130         if (disp)
131         {
132           if (IntUtil::isInt8(disp))
133             _emitByte((int8_t)disp);
134           else
135             _emitInt32((int32_t)disp);
136         }
137       }
138       // EBP/RBP/R13 == 5
139       else if (baseReg != 5 && disp == 0)
140       {
141         _emitMod(0, opReg, baseReg);
142       }
143       else if (IntUtil::isInt8(disp))
144       {
145         _emitMod(1, opReg, baseReg);
146         _emitByte((int8_t)disp);
147       }
148       else
149       {
150         _emitMod(2, opReg, baseReg);
151         _emitInt32((int32_t)disp);
152       }
153     }
154 
155     // [base + index * scale + displacemnt]
156     else
157     {
158       // ASMJIT_ASSERT(indexReg != RID_ESP);
159 
160       // EBP/RBP/R13 == 5
161       if (baseReg != 5 && disp == 0)
162       {
163         _emitMod(0, opReg, 4);
164         _emitSib(shift, indexReg, baseReg);
165       }
166       else if (IntUtil::isInt8(disp))
167       {
168         _emitMod(1, opReg, 4);
169         _emitSib(shift, indexReg, baseReg);
170         _emitByte((int8_t)disp);
171       }
172       else
173       {
174         _emitMod(2, opReg, 4);
175         _emitSib(shift, indexReg, baseReg);
176         _emitInt32((int32_t)disp);
177       }
178     }
179   }
180 
181   // Address                       | 32-bit mode | 64-bit mode
182   // ------------------------------+-------------+---------------
183   // [displacement]                |   ABSOLUTE  | RELATIVE (RIP)
184   // [index * scale + displacemnt] |   ABSOLUTE  | ABSOLUTE (ZERO EXTENDED)
185   else
186   {
187     // - In 32-bit mode the absolute addressing model is used.
188     // - In 64-bit mode the relative addressing model is used together with
189     //   the absolute addressing. Main problem is that if instruction
190     //   contains SIB then relative addressing (RIP) is not possible.
191 
192 #if defined(ASMJIT_X86)
193 
194     if (mem.hasIndex())
195     {
196       // ASMJIT_ASSERT(mem.getMemIndex() != 4); // ESP/RSP == 4
197       _emitMod(0, opReg, 4);
198       _emitSib(shift, indexReg, 5);
199     }
200     else
201     {
202       _emitMod(0, opReg, 5);
203     }
204 
205     // X86 uses absolute addressing model, all relative addresses will be
206     // relocated to absolute ones.
207     if (mem.getMemType() == kOperandMemLabel)
208     {
209       LabelData& l_data = _labels[mem._mem.base & kOperandIdValueMask];
210       RelocData r_data;
211       uint32_t relocId = _relocData.getLength();
212 
213       // Relative addressing will be relocated to absolute address.
214       r_data.type = kRelocRelToAbs;
215       r_data.size = 4;
216       r_data.offset = getOffset();
217       r_data.destination = disp;
218 
219       if (l_data.offset != -1)
220       {
221         // Bound label.
222         r_data.destination += l_data.offset;
223 
224         // Add a dummy DWORD.
225         _emitInt32(0);
226       }
227       else
228       {
229         // Non-bound label.
230         _emitDisplacement(l_data, -4 - immSize, 4)->relocId = relocId;
231       }
232 
233       _relocData.append(r_data);
234     }
235     else
236     {
237       // Absolute address
238       _emitInt32( (int32_t)((uint8_t*)mem._mem.target + disp) );
239     }
240 
241 #else
242 
243     // X64 uses relative addressing model
244     if (mem.getMemType() == kOperandMemLabel)
245     {
246       LabelData& l_data = _labels[mem._mem.base & kOperandIdValueMask];
247 
248       if (mem.hasIndex())
249       {
250         // Indexing is not possible.
251         setError(kErrorIllegalAddressing);
252         return;
253       }
254 
255       // Relative address (RIP +/- displacement).
256       _emitMod(0, opReg, 5);
257 
258       disp -= (4 + immSize);
259 
260       if (l_data.offset != -1)
261       {
262         // Bound label.
263         disp += getOffset() - l_data.offset;
264 
265         // Displacement is known.
266         _emitInt32((int32_t)disp);
267       }
268       else
269       {
270         // Non-bound label.
271         _emitDisplacement(l_data, disp, 4);
272       }
273     }
274     else
275     {
276       // Absolute address (truncated to 32-bits), this kind of address requires
277       // SIB byte (4).
278       _emitMod(0, opReg, 4);
279 
280       if (mem.hasIndex())
281       {
282         // ASMJIT_ASSERT(mem.getMemIndex() != 4); // ESP/RSP == 4
283         _emitSib(shift, indexReg, 5);
284       }
285       else
286       {
287         _emitSib(0, 4, 5);
288       }
289 
290       // Truncate to 32-bits.
291       sysuint_t target = (sysuint_t)((uint8_t*)mem._mem.target + disp);
292 
293       if (target > (sysuint_t)0xFFFFFFFF)
294       {
295         if (_logger)
296         {
297           _logger->logString("*** ASSEMBER WARNING - Absolute address truncated to 32-bits.\n");
298         }
299         target &= 0xFFFFFFFF;
300       }
301 
302       _emitInt32( (int32_t)((uint32_t)target) );
303     }
304 
305 #endif // ASMJIT_X64
306 
307   }
308 }
309 
_emitModRM(uint8_t opReg,const Operand & op,sysint_t immSize)310 void X86Assembler::_emitModRM(
311   uint8_t opReg, const Operand& op, sysint_t immSize)
312 {
313   ASMJIT_ASSERT(op.getType() == kOperandReg || op.getType() == kOperandMem);
314 
315   if (op.getType() == kOperandReg)
316     _emitModR(opReg, reinterpret_cast<const Reg&>(op).getRegCode());
317   else
318     _emitModM(opReg, reinterpret_cast<const Mem&>(op), immSize);
319 }
320 
_emitSegmentPrefix(const Operand & rm)321 void X86Assembler::_emitSegmentPrefix(const Operand& rm)
322 {
323   static const uint8_t segmentCode[6] =
324   {
325     0x26, // ES
326     0x2E, // SS
327     0x36, // SS
328     0x3E, // DS
329     0x64, // FS
330     0x65  // GS
331   };
332 
333   if (!rm.isMem())
334     return;
335 
336   uint32_t seg = reinterpret_cast<const Mem&>(rm).getSegment();
337   if (seg >= kX86RegNumSeg)
338     return;
339 
340   _emitByte(segmentCode[seg]);
341 }
342 
_emitX86Inl(uint32_t opCode,uint8_t i16bit,uint8_t rexw,uint8_t reg,bool forceRexPrefix)343 void X86Assembler::_emitX86Inl(
344   uint32_t opCode, uint8_t i16bit, uint8_t rexw, uint8_t reg, bool forceRexPrefix)
345 {
346   // 16-bit prefix.
347   if (i16bit) _emitByte(0x66);
348 
349   // Instruction prefix.
350   if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24));
351 
352   // REX prefix.
353 #if defined(ASMJIT_X64)
354   _emitRexR(rexw, 0, reg, forceRexPrefix);
355 #endif // ASMJIT_X64
356 
357   // Instruction opcodes.
358   if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16));
359   if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >>  8));
360 
361   _emitByte((uint8_t)(opCode & 0x000000FF) + (reg & 0x7));
362 }
363 
_emitX86RM(uint32_t opCode,uint8_t i16bit,uint8_t rexw,uint8_t o,const Operand & op,sysint_t immSize,bool forceRexPrefix)364 void X86Assembler::_emitX86RM(
365   uint32_t opCode, uint8_t i16bit, uint8_t rexw, uint8_t o,
366   const Operand& op, sysint_t immSize, bool forceRexPrefix)
367 {
368   // 16-bit prefix.
369   if (i16bit) _emitByte(0x66);
370 
371   // Segment prefix.
372   _emitSegmentPrefix(op);
373 
374   // Instruction prefix.
375   if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24));
376 
377   // REX prefix.
378 #if defined(ASMJIT_X64)
379   _emitRexRM(rexw, o, op, forceRexPrefix);
380 #endif // ASMJIT_X64
381 
382   // Instruction opcodes.
383   if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16));
384   if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >>  8));
385   _emitByte((uint8_t)(opCode & 0x000000FF));
386 
387   // Mod R/M.
388   _emitModRM(o, op, immSize);
389 }
390 
_emitFpu(uint32_t opCode)391 void X86Assembler::_emitFpu(uint32_t opCode)
392 {
393   _emitOpCode(opCode);
394 }
395 
_emitFpuSTI(uint32_t opCode,uint32_t sti)396 void X86Assembler::_emitFpuSTI(uint32_t opCode, uint32_t sti)
397 {
398   // Illegal stack offset.
399   ASMJIT_ASSERT(0 <= sti && sti < 8);
400   _emitOpCode(opCode + sti);
401 }
402 
_emitFpuMEM(uint32_t opCode,uint8_t opReg,const Mem & mem)403 void X86Assembler::_emitFpuMEM(uint32_t opCode, uint8_t opReg, const Mem& mem)
404 {
405   // Segment prefix.
406   _emitSegmentPrefix(mem);
407 
408   // Instruction prefix.
409   if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24));
410 
411   // REX prefix.
412 #if defined(ASMJIT_X64)
413   _emitRexRM(0, opReg, mem, false);
414 #endif // ASMJIT_X64
415 
416   // Instruction opcodes.
417   if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16));
418   if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >>  8));
419 
420   _emitByte((uint8_t)((opCode & 0x000000FF)));
421   _emitModM(opReg, mem, 0);
422 }
423 
_emitMmu(uint32_t opCode,uint8_t rexw,uint8_t opReg,const Operand & src,sysint_t immSize)424 void X86Assembler::_emitMmu(uint32_t opCode, uint8_t rexw, uint8_t opReg,
425   const Operand& src, sysint_t immSize)
426 {
427   // Segment prefix.
428   _emitSegmentPrefix(src);
429 
430   // Instruction prefix.
431   if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24));
432 
433   // REX prefix.
434 #if defined(ASMJIT_X64)
435   _emitRexRM(rexw, opReg, src, false);
436 #endif // ASMJIT_X64
437 
438   // Instruction opcodes.
439   if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16));
440 
441   // No checking, MMX/SSE instructions have always two opcodes or more.
442   _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8));
443   _emitByte((uint8_t)((opCode & 0x000000FF)));
444 
445   if (src.isReg())
446     _emitModR(opReg, reinterpret_cast<const Reg&>(src).getRegCode());
447   else
448     _emitModM(opReg, reinterpret_cast<const Mem&>(src), immSize);
449 }
450 
_emitDisplacement(LabelData & l_data,sysint_t inlinedDisplacement,int size)451 X86Assembler::LabelLink* X86Assembler::_emitDisplacement(
452   LabelData& l_data, sysint_t inlinedDisplacement, int size)
453 {
454   ASMJIT_ASSERT(l_data.offset == -1);
455   ASMJIT_ASSERT(size == 1 || size == 4);
456 
457   // Chain with label.
458   LabelLink* link = _newLabelLink();
459   link->prev = l_data.links;
460   link->offset = getOffset();
461   link->displacement = inlinedDisplacement;
462 
463   l_data.links = link;
464 
465   // Emit label size as dummy data.
466   if (size == 1)
467     _emitByte(0x01);
468   else // if (size == 4)
469     _emitDWord(0x04040404);
470 
471   return link;
472 }
473 
_emitJmpOrCallReloc(uint32_t instruction,void * target)474 void X86Assembler::_emitJmpOrCallReloc(uint32_t instruction, void* target)
475 {
476   RelocData rd;
477 
478   rd.type = kRelocTrampoline;
479 
480 #if defined(ASMJIT_X64)
481   // If we are compiling in 64-bit mode, we can use trampoline if relative jump
482   // is not possible.
483   _trampolineSize += X64TrampolineWriter::kSizeTotal;
484 #endif // ARCHITECTURE_SPECIFIC
485 
486   rd.size = 4;
487   rd.offset = getOffset();
488   rd.address = target;
489 
490   _relocData.append(rd);
491 
492   // Emit dummy 32-bit integer (will be overwritten by relocCode()).
493   _emitInt32(0);
494 }
495 
496 //! @internal
497 //!
498 //! @brief Get whether the extended register (additional eight registers
499 //! introduced by 64-bit mode) is used.
X86Assembler_isExtRegisterUsed(const Operand & op)500 static inline bool X86Assembler_isExtRegisterUsed(const Operand& op)
501 {
502   // Hacky, but correct.
503   // - If operand type is register then extended register is register with
504   //   index 8 and greater (8 to 15 inclusive).
505   // - If operand type is memory operand then we need to take care about
506   //   label (in _mem.base) and kInvalidValue, we just decrement the value
507   //   by 8 and check if it's at interval 0 to 7 inclusive (if it's there
508   //   then it's extended register.
509   return (op.isReg() && (op._reg.code & kRegIndexMask)  >= 8U) ||
510          (op.isMem() && ((((uint32_t)op._mem.base  - 8U) < 8U) ||
511                          (((uint32_t)op._mem.index - 8U) < 8U) ));
512 }
513 
514 // Logging helpers.
515 static const char* AssemblerX86_operandSize[] =
516 {
517   NULL,
518   "byte ptr ",
519   "word ptr ",
520   NULL,
521   "dword ptr ",
522   NULL,
523   NULL,
524   NULL,
525   "qword ptr ",
526   NULL,
527   "tword ptr ",
528   NULL,
529   NULL,
530   NULL,
531   NULL,
532   NULL,
533   "dqword ptr "
534 };
535 
536 static const char X86Assembler_segmentName[] =
537   "es:\0"
538   "cs:\0"
539   "ss:\0"
540   "ds:\0"
541   "fs:\0"
542   "gs:\0"
543   "\0\0\0\0";
544 
X86Assembler_dumpInstructionName(char * buf,uint32_t code)545 static char* X86Assembler_dumpInstructionName(char* buf, uint32_t code)
546 {
547   ASMJIT_ASSERT(code < _kX86InstCount);
548   return StringUtil::copy(buf, x86InstInfo[code].getName());
549 }
550 
X86Assembler_dumpRegister(char * buf,uint32_t type,uint32_t index)551 char* X86Assembler_dumpRegister(char* buf, uint32_t type, uint32_t index)
552 {
553   // NE == Not-Encodable.
554   const char reg8l[] = "al\0\0" "cl\0\0" "dl\0\0" "bl\0\0" "spl\0"  "bpl\0"  "sil\0"  "dil\0" ;
555   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";
556   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";
557 
558   switch (type)
559   {
560     case kX86RegTypeGpbLo:
561       if (index < 8)
562         return StringUtil::copy(buf, &reg8l[index*4]);
563 
564       *buf++ = 'r';
565       goto _EmitID;
566 
567     case kX86RegTypeGpbHi:
568       if (index < 4)
569         return StringUtil::copy(buf, &reg8h[index*4]);
570 
571 _EmitNE:
572       return StringUtil::copy(buf, "NE");
573 
574     case kX86RegTypeGpw:
575       if (index < 8)
576         return StringUtil::copy(buf, &reg16[index*4]);
577 
578       *buf++ = 'r';
579       buf = StringUtil::utoa(buf, index);
580       *buf++ = 'w';
581       return buf;
582 
583     case kX86RegTypeGpd:
584       if (index < 8)
585       {
586         *buf++ = 'e';
587         return StringUtil::copy(buf, &reg16[index*4]);
588       }
589 
590       *buf++ = 'r';
591       buf = StringUtil::utoa(buf, index);
592       *buf++ = 'd';
593       return buf;
594 
595     case kX86RegTypeGpq:
596       *buf++ = 'r';
597 
598       if (index < 8)
599         return StringUtil::copy(buf, &reg16[index*4]);
600 
601 _EmitID:
602       return StringUtil::utoa(buf, index);
603 
604     case kX86RegTypeX87:
605       *buf++ = 's';
606       *buf++ = 't';
607       goto _EmitID;
608 
609     case kX86RegTypeMm:
610       *buf++ = 'm';
611       *buf++ = 'm';
612       goto _EmitID;
613 
614     case kX86RegTypeXmm:
615       *buf++ = 'x';
616       *buf++ = 'm';
617       *buf++ = 'm';
618       goto _EmitID;
619 
620     case kX86RegTypeYmm:
621       *buf++ = 'y';
622       *buf++ = 'm';
623       *buf++ = 'm';
624       goto _EmitID;
625 
626     case kX86RegTypeSeg:
627       if (index < kX86RegNumSeg)
628         return StringUtil::copy(buf, &X86Assembler_segmentName[index*4], 2);
629 
630       goto _EmitNE;
631 
632     default:
633       return buf;
634   }
635 }
636 
X86Assembler_dumpOperand(char * buf,const Operand * op,uint32_t memRegType,uint32_t loggerFlags)637 char* X86Assembler_dumpOperand(char* buf, const Operand* op, uint32_t memRegType, uint32_t loggerFlags)
638 {
639   if (op->isReg())
640   {
641     const Reg& reg = reinterpret_cast<const Reg&>(*op);
642     return X86Assembler_dumpRegister(buf, reg.getRegType(), reg.getRegIndex());
643   }
644   else if (op->isMem())
645   {
646     const Mem& mem = reinterpret_cast<const Mem&>(*op);
647     uint32_t seg = mem.getSegment();
648 
649     bool isAbsolute = false;
650 
651     if (op->getSize() <= 16)
652       buf = StringUtil::copy(buf, AssemblerX86_operandSize[op->getSize()]);
653 
654     if (seg < kX86RegNumSeg)
655       buf = StringUtil::copy(buf, &X86Assembler_segmentName[seg * 4]);
656 
657     *buf++ = '[';
658 
659     switch (mem.getMemType())
660     {
661       case kOperandMemNative:
662       {
663         // [base + index << shift + displacement]
664         buf = X86Assembler_dumpRegister(buf, memRegType, mem.getBase());
665         break;
666       }
667       case kOperandMemLabel:
668       {
669         // [label + index << shift + displacement]
670         buf += sprintf(buf, "L.%u", mem.getBase() & kOperandIdValueMask);
671         break;
672       }
673       case kOperandMemAbsolute:
674       {
675         // [absolute]
676         isAbsolute = true;
677         buf = StringUtil::utoa(buf, (sysuint_t)mem.getTarget() + mem.getDisplacement(), 16);
678         break;
679       }
680     }
681 
682     if (mem.hasIndex())
683     {
684       buf = StringUtil::copy(buf, " + ");
685       buf = X86Assembler_dumpRegister(buf, memRegType, mem.getIndex());
686 
687       if (mem.getShift())
688       {
689         buf = StringUtil::copy(buf, " * ");
690         *buf++ = "1248"[mem.getShift() & 3];
691       }
692     }
693 
694     if (mem.getDisplacement() && !isAbsolute)
695     {
696       sysint_t d = mem.getDisplacement();
697       uint32_t base = 10;
698       char sign = '+';
699 
700       if (d < 0)
701       {
702         d = -d;
703         sign = '-';
704       }
705 
706       buf[0] = ' ';
707       buf[1] = sign;
708       buf[2] = ' ';
709       buf += 3;
710 
711       if ((loggerFlags & kLoggerOutputHexDisplacement) != 0 && d > 9)
712       {
713         buf[0] = '0';
714         buf[1] = 'x';
715         buf += 2;
716         base = 16;
717       }
718 
719       buf = StringUtil::utoa(buf, static_cast<uintptr_t>(d), base);
720     }
721 
722     *buf++ = ']';
723     return buf;
724   }
725   else if (op->isImm())
726   {
727     const Imm& i = reinterpret_cast<const Imm&>(*op);
728 
729     sysuint_t value = i.getUValue();
730     uint32_t base = 10;
731 
732     if ((loggerFlags & kLoggerOutputHexImmediate) && value > 9)
733       base = 16;
734 
735     if (i.isUnsigned() || base == 16)
736     {
737       return StringUtil::utoa(buf, value, base);
738     }
739     else
740     {
741       return StringUtil::itoa(buf, static_cast<sysint_t>(value), base);
742     }
743   }
744   else if (op->isLabel())
745   {
746     return buf + sprintf(buf, "L.%u", op->getId() & kOperandIdValueMask);
747   }
748   else
749   {
750     return StringUtil::copy(buf, "None");
751   }
752 }
753 
X86Assembler_dumpInstruction(char * buf,uint32_t code,uint32_t emitOptions,const Operand * o0,const Operand * o1,const Operand * o2,uint32_t memRegType,uint32_t loggerFlags)754 static char* X86Assembler_dumpInstruction(char* buf,
755   uint32_t code, uint32_t emitOptions,
756   const Operand* o0,
757   const Operand* o1,
758   const Operand* o2,
759   uint32_t memRegType,
760   uint32_t loggerFlags)
761 {
762   // Rex, lock, and short prefix.
763   if (emitOptions & kX86EmitOptionRex)
764     buf = StringUtil::copy(buf, "rex ", 4);
765 
766   if (emitOptions & kX86EmitOptionLock)
767     buf = StringUtil::copy(buf, "lock ", 5);
768 
769   if (emitOptions & kX86EmitOptionShortJump)
770     buf = StringUtil::copy(buf, "short ", 6);
771 
772   // Dump instruction name.
773   buf = X86Assembler_dumpInstructionName(buf, code);
774 
775   // Dump operands.
776   if (!o0->isNone()) { *buf++ = ' ';               buf = X86Assembler_dumpOperand(buf, o0, memRegType, loggerFlags); }
777   if (!o1->isNone()) { *buf++ = ','; *buf++ = ' '; buf = X86Assembler_dumpOperand(buf, o1, memRegType, loggerFlags); }
778   if (!o2->isNone()) { *buf++ = ','; *buf++ = ' '; buf = X86Assembler_dumpOperand(buf, o2, memRegType, loggerFlags); }
779 
780   return buf;
781 }
782 
X86Assembler_dumpComment(char * buf,size_t len,const uint8_t * binaryData,size_t binaryLen,const char * comment)783 static char* X86Assembler_dumpComment(char* buf, size_t len, const uint8_t* binaryData, size_t binaryLen, const char* comment)
784 {
785   size_t currentLength = len;
786   size_t commentLength = comment ? strnlen(comment, kMaxCommentLength) : 0;
787 
788   if (binaryLen || commentLength)
789   {
790     size_t align = 32;
791     char sep = ';';
792 
793     for (size_t i = (binaryLen == 0); i < 2; i++)
794     {
795       char* bufBegin = buf;
796 
797       // Append align.
798       if (currentLength < align)
799       {
800         buf = StringUtil::fill(buf, ' ', align - currentLength);
801       }
802 
803       // Append separator.
804       if (sep)
805       {
806         *buf++ = sep;
807         *buf++ = ' ';
808       }
809 
810       // Append binary data or comment.
811       if (i == 0)
812       {
813         buf = StringUtil::hex(buf, binaryData, binaryLen);
814         if (commentLength == 0)
815           break;
816       }
817       else
818       {
819         buf = StringUtil::copy(buf, comment, commentLength);
820       }
821 
822       currentLength += (size_t)(buf - bufBegin);
823       align += 18;
824       sep = '|';
825     }
826   }
827 
828   *buf++ = '\n';
829   return buf;
830 }
831 
832 static const _OpReg _patchedHiRegs[4] =
833 {
834   // Operand   |Size|Reserved0|Reserved1| OperandId    | RegisterCode          |
835   // ----------+----+---------+---------+--------------+-----------------------+
836   { kOperandReg, 1, {0        ,0       }, kInvalidValue, kX86RegTypeGpbLo | 4 },
837   { kOperandReg, 1, {0        ,0       }, kInvalidValue, kX86RegTypeGpbLo | 5 },
838   { kOperandReg, 1, {0        ,0       }, kInvalidValue, kX86RegTypeGpbLo | 6 },
839   { kOperandReg, 1, {0        ,0       }, kInvalidValue, kX86RegTypeGpbLo | 7 }
840 };
841 
_emitInstruction(uint32_t code)842 void X86Assembler::_emitInstruction(uint32_t code)
843 {
844   _emitInstruction(code, &noOperand, &noOperand, &noOperand);
845 }
846 
_emitInstruction(uint32_t code,const Operand * o0)847 void X86Assembler::_emitInstruction(uint32_t code, const Operand* o0)
848 {
849   _emitInstruction(code, o0, &noOperand, &noOperand);
850 }
851 
_emitInstruction(uint32_t code,const Operand * o0,const Operand * o1)852 void X86Assembler::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1)
853 {
854   _emitInstruction(code, o0, o1, &noOperand);
855 }
856 
_emitInstruction(uint32_t code,const Operand * o0,const Operand * o1,const Operand * o2)857 void X86Assembler::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2)
858 {
859   ASMJIT_ASSERT(o0 != NULL);
860   ASMJIT_ASSERT(o1 != NULL);
861   ASMJIT_ASSERT(o2 != NULL);
862 
863   const Operand* _loggerOperands[3];
864 
865   uint32_t bLoHiUsed = 0;
866 #if defined(ASMJIT_X86)
867   uint32_t forceRexPrefix = false;
868 #else
869   uint32_t forceRexPrefix = _emitOptions & kX86EmitOptionRex;
870 #endif
871   uint32_t memRegType = kX86RegTypeGpz;
872 
873 #if defined(ASMJIT_DEBUG)
874   bool assertIllegal = false;
875 #endif // ASMJIT_DEBUG
876 
877   const Imm* immOperand = NULL;
878   uint32_t immSize;
879 
880 #define _FINISHED() \
881   goto _End
882 
883 #define _FINISHED_IMMEDIATE(_Operand_, _Size_) \
884   do { \
885     immOperand = reinterpret_cast<const Imm*>(_Operand_); \
886     immSize = (_Size_); \
887     goto _EmitImmediate; \
888   } while (0)
889 
890   // Convert operands to kOperandNone if needed.
891   if (o0->isReg()) bLoHiUsed |= o0->_reg.code & (kX86RegTypeGpbLo | kX86RegTypeGpbHi);
892   if (o1->isReg()) bLoHiUsed |= o1->_reg.code & (kX86RegTypeGpbLo | kX86RegTypeGpbHi);
893   if (o2->isReg()) bLoHiUsed |= o2->_reg.code & (kX86RegTypeGpbLo | kX86RegTypeGpbHi);
894 
895   size_t beginOffset = getOffset();
896   const X86InstInfo* id = &x86InstInfo[code];
897 
898   if (code >= _kX86InstCount)
899   {
900     setError(kErrorUnknownInstruction);
901     goto _Cleanup;
902   }
903 
904   // Check if register operand is BPL, SPL, SIL, DIL and do action that depends
905   // to current mode:
906   //   - 64-bit: - Force REX prefix.
907   //
908   // Check if register operand is AH, BH, CH or DH and do action that depends
909   // to current mode:
910   //   - 32-bit: - Patch operand index (index += 4), because we are using
911   //               different index what is used in opcode.
912   //   - 64-bit: - Check whether there is REX prefix and raise error if it is.
913   //             - Do the same as in 32-bit mode - patch register index.
914   //
915   // NOTE: This is a hit hacky, but I added this to older code-base and I have
916   // no energy to rewrite it. Maybe in future all of this can be cleaned up!
917   if (bLoHiUsed | forceRexPrefix)
918   {
919     _loggerOperands[0] = o0;
920     _loggerOperands[1] = o1;
921     _loggerOperands[2] = o2;
922 
923 #if defined(ASMJIT_X64)
924     // Check if there is register that makes this instruction un-encodable.
925 
926     forceRexPrefix |= (uint32_t)X86Assembler_isExtRegisterUsed(*o0);
927     forceRexPrefix |= (uint32_t)X86Assembler_isExtRegisterUsed(*o1);
928     forceRexPrefix |= (uint32_t)X86Assembler_isExtRegisterUsed(*o2);
929 
930     if      (o0->isRegType(kX86RegTypeGpbLo) && (o0->_reg.code & kRegIndexMask) >= 4) forceRexPrefix = true;
931     else if (o1->isRegType(kX86RegTypeGpbLo) && (o1->_reg.code & kRegIndexMask) >= 4) forceRexPrefix = true;
932     else if (o2->isRegType(kX86RegTypeGpbLo) && (o2->_reg.code & kRegIndexMask) >= 4) forceRexPrefix = true;
933 
934     if ((bLoHiUsed & kX86RegTypeGpbHi) != 0 && forceRexPrefix)
935     {
936       goto _IllegalInstruction;
937     }
938 #endif // ASMJIT_X64
939 
940     // Patch GPB.HI operand index.
941     if ((bLoHiUsed & kX86RegTypeGpbHi) != 0)
942     {
943       if (o0->isRegType(kX86RegTypeGpbHi)) o0 = reinterpret_cast<const Operand*>(&_patchedHiRegs[o0->_reg.code & kRegIndexMask]);
944       if (o1->isRegType(kX86RegTypeGpbHi)) o1 = reinterpret_cast<const Operand*>(&_patchedHiRegs[o1->_reg.code & kRegIndexMask]);
945       if (o2->isRegType(kX86RegTypeGpbHi)) o2 = reinterpret_cast<const Operand*>(&_patchedHiRegs[o2->_reg.code & kRegIndexMask]);
946     }
947   }
948 
949   // Check for buffer space (and grow if needed).
950   if (!canEmit()) goto _Cleanup;
951 
952   if (_emitOptions & kX86EmitOptionLock)
953   {
954     if (!id->isLockable())
955       goto _IllegalInstruction;
956     _emitByte(0xF0);
957   }
958 
959   switch (id->getGroup())
960   {
961     case kX86InstGroupNone:
962     {
963       _FINISHED();
964     }
965 
966     case kX86InstGroupEmit:
967     {
968       _emitOpCode(id->_opCode[0]);
969       _FINISHED();
970     }
971 
972     case kX86InstGroupArith:
973     {
974       uint32_t opCode = id->_opCode[0];
975       uint8_t opReg = (uint8_t)id->_opCodeR;
976 
977       // Mem <- Reg
978       if (o0->isMem() && o1->isReg())
979       {
980         _emitX86RM(opCode + (o1->getSize() != 1),
981           o1->getSize() == 2,
982           o1->getSize() == 8,
983           reinterpret_cast<const GpReg&>(*o1).getRegCode(),
984           reinterpret_cast<const Operand&>(*o0),
985           0, forceRexPrefix);
986         _FINISHED();
987       }
988 
989       // Reg <- Reg|Mem
990       if (o0->isReg() && o1->isRegMem())
991       {
992         _emitX86RM(opCode + 2 + (o0->getSize() != 1),
993           o0->getSize() == 2,
994           o0->getSize() == 8,
995           reinterpret_cast<const GpReg&>(*o0).getRegCode(),
996           reinterpret_cast<const Operand&>(*o1),
997           0, forceRexPrefix);
998         _FINISHED();
999       }
1000 
1001       // Alternate Form - AL, AX, EAX, RAX.
1002       if (o0->isRegIndex(0) && o1->isImm())
1003       {
1004         if (o0->getSize() == 1 || !IntUtil::isInt8(static_cast<const Imm*>(o1)->getValue()))
1005         {
1006           if (o0->getSize() == 2)
1007             _emitByte(0x66); // 16-bit.
1008           else if (o0->getSize() == 8)
1009             _emitByte(0x48); // REX.W.
1010 
1011           _emitByte((opReg << 3) | (0x04 + (o0->getSize() != 1)));
1012           _FINISHED_IMMEDIATE(o1, IntUtil::_min<uint32_t>(o0->getSize(), 4));
1013         }
1014       }
1015 
1016       if (o0->isRegMem() && o1->isImm())
1017       {
1018         const Imm& imm = reinterpret_cast<const Imm&>(*o1);
1019         immSize = IntUtil::isInt8(imm.getValue()) ? 1 : IntUtil::_min<uint32_t>(o0->getSize(), 4);
1020 
1021         _emitX86RM(id->_opCode[1] + (o0->getSize() != 1 ? (immSize != 1 ? 1 : 3) : 0),
1022           o0->getSize() == 2,
1023           o0->getSize() == 8,
1024           opReg, reinterpret_cast<const Operand&>(*o0),
1025           immSize, forceRexPrefix);
1026         _FINISHED_IMMEDIATE(&imm, immSize);
1027       }
1028 
1029       break;
1030     }
1031 
1032     case kX86InstGroupBSwap:
1033     {
1034       if (o0->isReg())
1035       {
1036         const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1037 
1038 #if defined(ASMJIT_X64)
1039         _emitRexR(dst.getRegType() == kX86RegTypeGpq, 1, dst.getRegCode(), forceRexPrefix);
1040 #endif // ASMJIT_X64
1041         _emitByte(0x0F);
1042         _emitModR(1, dst.getRegCode());
1043         _FINISHED();
1044       }
1045 
1046       break;
1047     }
1048 
1049     case kX86InstGroupBTest:
1050     {
1051       if (o0->isRegMem() && o1->isReg())
1052       {
1053         const Operand& dst = reinterpret_cast<const Operand&>(*o0);
1054         const GpReg& src = reinterpret_cast<const GpReg&>(*o1);
1055 
1056         _emitX86RM(id->_opCode[0],
1057           src.isRegType(kX86RegTypeGpw),
1058           src.isRegType(kX86RegTypeGpq),
1059           src.getRegCode(),
1060           dst,
1061           0, forceRexPrefix);
1062         _FINISHED();
1063       }
1064 
1065       if (o0->isRegMem() && o1->isImm())
1066       {
1067         const Operand& dst = reinterpret_cast<const Operand&>(*o0);
1068         const Imm& src = reinterpret_cast<const Imm&>(*o1);
1069 
1070         _emitX86RM(id->_opCode[1],
1071           dst.getSize() == 2,
1072           dst.getSize() == 8,
1073           (uint8_t)id->_opCodeR,
1074           dst,
1075           1, forceRexPrefix);
1076         _FINISHED_IMMEDIATE(o1, 1);
1077       }
1078 
1079       break;
1080     }
1081 
1082     case kX86InstGroupCall:
1083     {
1084       if (o0->isRegTypeMem(kX86RegTypeGpz))
1085       {
1086         const Operand& dst = reinterpret_cast<const Operand&>(*o0);
1087         _emitX86RM(0xFF,
1088           0,
1089           0, 2, dst,
1090           0, forceRexPrefix);
1091         _FINISHED();
1092       }
1093 
1094       if (o0->isImm())
1095       {
1096         const Imm& imm = reinterpret_cast<const Imm&>(*o0);
1097         _emitByte(0xE8);
1098         _emitJmpOrCallReloc(kX86InstGroupCall, (void*)imm.getValue());
1099         _FINISHED();
1100       }
1101 
1102       if (o0->isLabel())
1103       {
1104         LabelData& l_data = _labels[reinterpret_cast<const Label*>(o0)->getId() & kOperandIdValueMask];
1105 
1106         if (l_data.offset != -1)
1107         {
1108           // Bound label.
1109           static const sysint_t rel32_size = 5;
1110           sysint_t offs = l_data.offset - getOffset();
1111 
1112           ASMJIT_ASSERT(offs <= 0);
1113 
1114           _emitByte(0xE8);
1115           _emitInt32((int32_t)(offs - rel32_size));
1116         }
1117         else
1118         {
1119           // Non-bound label.
1120           _emitByte(0xE8);
1121           _emitDisplacement(l_data, -4, 4);
1122         }
1123         _FINISHED();
1124       }
1125 
1126       break;
1127     }
1128 
1129     case kX86InstGroupCrc32:
1130     {
1131       if (o0->isReg() && o1->isRegMem())
1132       {
1133         const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1134         const Operand& src = reinterpret_cast<const Operand&>(*o1);
1135         ASMJIT_ASSERT(dst.getRegType() == kX86RegTypeGpd || dst.getRegType() == kX86RegTypeGpq);
1136 
1137         _emitX86RM(id->_opCode[0] + (src.getSize() != 1),
1138           src.getSize() == 2,
1139           dst.getRegType() == 8, dst.getRegCode(), src,
1140           0, forceRexPrefix);
1141         _FINISHED();
1142       }
1143 
1144       break;
1145     }
1146 
1147     case kX86InstGroupEnter:
1148     {
1149       if (o0->isImm() && o1->isImm())
1150       {
1151         _emitByte(0xC8);
1152         _emitWord((uint16_t)(uintptr_t)reinterpret_cast<const Imm&>(*o2).getValue());
1153         _emitByte((uint8_t )(uintptr_t)reinterpret_cast<const Imm&>(*o1).getValue());
1154         _FINISHED();
1155       }
1156       break;
1157     }
1158 
1159     case kX86InstGroupIMul:
1160     {
1161       // 1 operand
1162       if (o0->isRegMem() && o1->isNone() && o2->isNone())
1163       {
1164         const Operand& src = reinterpret_cast<const Operand&>(*o0);
1165         _emitX86RM(0xF6 + (src.getSize() != 1),
1166           src.getSize() == 2,
1167           src.getSize() == 8, 5, src,
1168           0, forceRexPrefix);
1169         _FINISHED();
1170       }
1171       // 2 operands
1172       else if (o0->isReg() && !o1->isNone() && o2->isNone())
1173       {
1174         const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1175         ASMJIT_ASSERT(!dst.isRegType(kX86RegTypeGpw));
1176 
1177         if (o1->isRegMem())
1178         {
1179           const Operand& src = reinterpret_cast<const Operand&>(*o1);
1180 
1181           _emitX86RM(0x0FAF,
1182             dst.isRegType(kX86RegTypeGpw),
1183             dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src,
1184             0, forceRexPrefix);
1185           _FINISHED();
1186         }
1187         else if (o1->isImm())
1188         {
1189           const Imm& imm = reinterpret_cast<const Imm&>(*o1);
1190 
1191           if (IntUtil::isInt8(imm.getValue()))
1192           {
1193             _emitX86RM(0x6B,
1194               dst.isRegType(kX86RegTypeGpw),
1195               dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), dst,
1196               1, forceRexPrefix);
1197             _FINISHED_IMMEDIATE(&imm, 1);
1198           }
1199           else
1200           {
1201             immSize = dst.isRegType(kX86RegTypeGpw) ? 2 : 4;
1202             _emitX86RM(0x69,
1203               dst.isRegType(kX86RegTypeGpw),
1204               dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), dst,
1205               immSize, forceRexPrefix);
1206             _FINISHED_IMMEDIATE(&imm, immSize);
1207           }
1208         }
1209       }
1210       // 3 operands
1211       else if (o0->isReg() && o1->isRegMem() && o2->isImm())
1212       {
1213         const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1214         const Operand& src = reinterpret_cast<const Operand&>(*o1);
1215         const Imm& imm = reinterpret_cast<const Imm&>(*o2);
1216 
1217         if (IntUtil::isInt8(imm.getValue()))
1218         {
1219           _emitX86RM(0x6B,
1220             dst.isRegType(kX86RegTypeGpw),
1221             dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src,
1222             1, forceRexPrefix);
1223           _FINISHED_IMMEDIATE(&imm, 1);
1224         }
1225         else
1226         {
1227           immSize = dst.isRegType(kX86RegTypeGpw) ? 2 : 4;
1228           _emitX86RM(0x69,
1229             dst.isRegType(kX86RegTypeGpw),
1230             dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src,
1231             immSize, forceRexPrefix);
1232           _FINISHED_IMMEDIATE(&imm, immSize);
1233         }
1234       }
1235 
1236       break;
1237     }
1238 
1239     case kX86InstGroupIncDec:
1240     {
1241       if (o0->isRegMem())
1242       {
1243         const Operand& dst = reinterpret_cast<const Operand&>(*o0);
1244 
1245         // INC [r16|r32] in 64-bit mode is not encodable.
1246 #if defined(ASMJIT_X86)
1247         if ((dst.isReg()) && (dst.isRegType(kX86RegTypeGpw) || dst.isRegType(kX86RegTypeGpd)))
1248         {
1249           _emitX86Inl(id->_opCode[0],
1250             dst.isRegType(kX86RegTypeGpw),
1251             0, reinterpret_cast<const Reg&>(dst).getRegCode(),
1252             false);
1253           _FINISHED();
1254         }
1255 #endif // ASMJIT_X86
1256 
1257         _emitX86RM(id->_opCode[1] + (dst.getSize() != 1),
1258           dst.getSize() == 2,
1259           dst.getSize() == 8, (uint8_t)id->_opCodeR, dst,
1260           0, forceRexPrefix);
1261         _FINISHED();
1262       }
1263 
1264       break;
1265     }
1266 
1267     case kX86InstGroupJcc:
1268     {
1269       if (o0->isLabel())
1270       {
1271         LabelData& l_data = _labels[reinterpret_cast<const Label*>(o0)->getId() & kOperandIdValueMask];
1272 
1273         uint32_t hint = (uint32_t)(o1->isImm() ? reinterpret_cast<const Imm&>(*o1).getValue() : 0);
1274         bool isShortJump = (_emitOptions & kX86EmitOptionShortJump) != 0;
1275 
1276         // Emit jump hint if configured for that.
1277         if ((hint & (kCondHintLikely | kCondHintUnlikely)) && (_properties & (1 << kX86PropertyJumpHints)))
1278         {
1279           if (hint & kCondHintLikely)
1280             _emitByte(kX86CondPrefixLikely);
1281           else if (hint & kCondHintUnlikely)
1282             _emitByte(kX86CondPrefixUnlikely);
1283         }
1284 
1285         if (l_data.offset != -1)
1286         {
1287           // Bound label.
1288           static const sysint_t rel8_size = 2;
1289           static const sysint_t rel32_size = 6;
1290           sysint_t offs = l_data.offset - getOffset();
1291 
1292           ASMJIT_ASSERT(offs <= 0);
1293 
1294           if (IntUtil::isInt8(offs - rel8_size))
1295           {
1296             _emitByte(0x70 | (uint8_t)id->_opCode[0]);
1297             _emitByte((uint8_t)(int8_t)(offs - rel8_size));
1298 
1299             // Change the emit options so logger can log instruction correctly.
1300             _emitOptions |= kX86EmitOptionShortJump;
1301           }
1302           else
1303           {
1304             if (isShortJump && _logger)
1305             {
1306               _logger->logString("*** ASSEMBLER WARNING: Emitting long conditional jump, but short jump instruction forced!\n");
1307               _emitOptions &= ~kX86EmitOptionShortJump;
1308             }
1309 
1310             _emitByte(0x0F);
1311             _emitByte(0x80 | (uint8_t)id->_opCode[0]);
1312             _emitInt32((int32_t)(offs - rel32_size));
1313           }
1314         }
1315         else
1316         {
1317           // Non-bound label.
1318           if (isShortJump)
1319           {
1320             _emitByte(0x70 | (uint8_t)id->_opCode[0]);
1321             _emitDisplacement(l_data, -1, 1);
1322           }
1323           else
1324           {
1325             _emitByte(0x0F);
1326             _emitByte(0x80 | (uint8_t)id->_opCode[0]);
1327             _emitDisplacement(l_data, -4, 4);
1328           }
1329         }
1330         _FINISHED();
1331       }
1332 
1333       break;
1334     }
1335 
1336     case kX86InstGroupJmp:
1337     {
1338       if (o0->isRegMem())
1339       {
1340         const Operand& dst = reinterpret_cast<const Operand&>(*o0);
1341 
1342         _emitX86RM(0xFF,
1343           0,
1344           0, 4, dst,
1345           0, forceRexPrefix);
1346         _FINISHED();
1347       }
1348 
1349       if (o0->isImm())
1350       {
1351         const Imm& imm = reinterpret_cast<const Imm&>(*o0);
1352         _emitByte(0xE9);
1353         _emitJmpOrCallReloc(kX86InstGroupJmp, (void*)imm.getValue());
1354         _FINISHED();
1355       }
1356 
1357       if (o0->isLabel())
1358       {
1359         LabelData& l_data = _labels[reinterpret_cast<const Label*>(o0)->getId() & kOperandIdValueMask];
1360         bool isShortJump = (_emitOptions & kX86EmitOptionShortJump) != 0;
1361 
1362         if (l_data.offset != -1)
1363         {
1364           // Bound label.
1365           const sysint_t rel8_size = 2;
1366           const sysint_t rel32_size = 5;
1367           sysint_t offs = l_data.offset - getOffset();
1368 
1369           if (IntUtil::isInt8(offs - rel8_size))
1370           {
1371             _emitByte(0xEB);
1372             _emitByte((uint8_t)(int8_t)(offs - rel8_size));
1373 
1374             // Change the emit options so logger can log instruction correctly.
1375             _emitOptions |= kX86EmitOptionShortJump;
1376           }
1377           else
1378           {
1379             if (isShortJump)
1380             {
1381               if (_logger)
1382               {
1383                 _logger->logString("*** ASSEMBLER WARNING: Emitting long jump, but short jump instruction forced!\n");
1384                 _emitOptions &= ~kX86EmitOptionShortJump;
1385               }
1386             }
1387 
1388             _emitByte(0xE9);
1389             _emitInt32((int32_t)(offs - rel32_size));
1390           }
1391         }
1392         else
1393         {
1394           // Non-bound label.
1395           if (isShortJump)
1396           {
1397             _emitByte(0xEB);
1398             _emitDisplacement(l_data, -1, 1);
1399           }
1400           else
1401           {
1402             _emitByte(0xE9);
1403             _emitDisplacement(l_data, -4, 4);
1404           }
1405         }
1406         _FINISHED();
1407       }
1408 
1409       break;
1410     }
1411 
1412     case kX86InstGroupLea:
1413     {
1414       if (o0->isReg() && o1->isMem())
1415       {
1416         const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1417         const Mem& src = reinterpret_cast<const Mem&>(*o1);
1418 
1419         // Size override prefix support.
1420         if (src.getSizePrefix())
1421         {
1422           _emitByte(0x67);
1423 #if defined(ASMJIT_X86)
1424           memRegType = kX86RegTypeGpw;
1425 #else
1426           memRegType = kX86RegTypeGpd;
1427 #endif
1428         }
1429 
1430         _emitX86RM(0x8D,
1431           dst.isRegType(kX86RegTypeGpw),
1432           dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src,
1433           0, forceRexPrefix);
1434         _FINISHED();
1435       }
1436 
1437       break;
1438     }
1439 
1440     case kX86InstGroupMem:
1441     {
1442       if (o0->isMem())
1443       {
1444         _emitX86RM(id->_opCode[0], 0, (uint8_t)id->_opCode[1], (uint8_t)id->_opCodeR, reinterpret_cast<const Mem&>(*o0), 0, forceRexPrefix);
1445         _FINISHED();
1446       }
1447       break;
1448     }
1449 
1450     case kX86InstGroupMov:
1451     {
1452       const Operand& dst = *o0;
1453       const Operand& src = *o1;
1454 
1455       switch (dst.getType() << 4 | src.getType())
1456       {
1457         // Reg <- Reg/Mem
1458         case (kOperandReg << 4) | kOperandReg:
1459         {
1460           // Reg <- Sreg
1461           if (src.isRegType(kX86RegTypeSeg))
1462           {
1463             ASMJIT_ASSERT(dst.isRegType(kX86RegTypeGpw) ||
1464                           dst.isRegType(kX86RegTypeGpd) ||
1465                           dst.isRegType(kX86RegTypeGpq) );
1466 
1467             _emitX86RM(0x8C,
1468               dst.getSize() == 2,
1469               dst.getSize() == 8,
1470               reinterpret_cast<const SegmentReg&>(src).getRegCode(),
1471               reinterpret_cast<const Operand&>(dst),
1472               0, forceRexPrefix);
1473             _FINISHED();
1474           }
1475 
1476           // Sreg <- Reg/Mem
1477           if (dst.isRegType(kX86RegTypeSeg))
1478           {
1479             ASMJIT_ASSERT(src.isRegType(kX86RegTypeGpw   ) ||
1480                           src.isRegType(kX86RegTypeGpd   ) ||
1481                           src.isRegType(kX86RegTypeGpq   ) );
1482 
1483 _Emit_Mov_Sreg_RM:
1484             _emitX86RM(0x8E,
1485               src.getSize() == 2,
1486               src.getSize() == 8,
1487               reinterpret_cast<const SegmentReg&>(dst).getRegCode(),
1488               reinterpret_cast<const Operand&>(src),
1489               0, forceRexPrefix);
1490             _FINISHED();
1491           }
1492 
1493           ASMJIT_ASSERT(src.isRegType(kX86RegTypeGpbLo) ||
1494                         src.isRegType(kX86RegTypeGpbHi) ||
1495                         src.isRegType(kX86RegTypeGpw   ) ||
1496                         src.isRegType(kX86RegTypeGpd   ) ||
1497                         src.isRegType(kX86RegTypeGpq   ) );
1498           // ... fall through ...
1499         }
1500         case (kOperandReg << 4) | kOperandMem:
1501         {
1502           // Sreg <- Mem
1503           if (dst.isRegType(kX86RegTypeSeg))
1504           {
1505             goto _Emit_Mov_Sreg_RM;
1506           }
1507 
1508           ASMJIT_ASSERT(dst.isRegType(kX86RegTypeGpbLo) ||
1509                         dst.isRegType(kX86RegTypeGpbHi) ||
1510                         dst.isRegType(kX86RegTypeGpw   ) ||
1511                         dst.isRegType(kX86RegTypeGpd   ) ||
1512                         dst.isRegType(kX86RegTypeGpq   ) );
1513 
1514           _emitX86RM(0x0000008A + (dst.getSize() != 1),
1515             dst.isRegType(kX86RegTypeGpw),
1516             dst.isRegType(kX86RegTypeGpq),
1517             reinterpret_cast<const GpReg&>(dst).getRegCode(),
1518             reinterpret_cast<const Operand&>(src),
1519             0, forceRexPrefix);
1520           _FINISHED();
1521         }
1522 
1523         // Reg <- Imm
1524         case (kOperandReg << 4) | kOperandImm:
1525         {
1526           const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1527           const Imm& src = reinterpret_cast<const Imm&>(*o1);
1528 
1529           // In 64-bit mode the immediate can be 64-bits long if the
1530           // destination operand type is register (otherwise 32-bits).
1531           immSize = dst.getSize();
1532 
1533 #if defined(ASMJIT_X64)
1534           // Optimize instruction size by using 32-bit immediate if value can
1535           // fit into it.
1536           if (immSize == 8 && IntUtil::isInt32(src.getValue()))
1537           {
1538             _emitX86RM(0xC7,
1539               0, // 16BIT
1540               1, // REX.W
1541               0, // O
1542               dst,
1543               0, forceRexPrefix);
1544             immSize = 4;
1545           }
1546           else
1547           {
1548 #endif // ASMJIT_X64
1549             _emitX86Inl((dst.getSize() == 1 ? 0xB0 : 0xB8),
1550               dst.isRegType(kX86RegTypeGpw),
1551               dst.isRegType(kX86RegTypeGpq),
1552               dst.getRegCode(), forceRexPrefix);
1553 #if defined(ASMJIT_X64)
1554           }
1555 #endif // ASMJIT_X64
1556 
1557           _FINISHED_IMMEDIATE(&src, immSize);
1558         }
1559 
1560         // Mem <- Reg/Sreg
1561         case (kOperandMem << 4) | kOperandReg:
1562         {
1563           if (src.isRegType(kX86RegTypeSeg))
1564           {
1565             // Mem <- Sreg
1566             _emitX86RM(0x8C,
1567               dst.getSize() == 2,
1568               dst.getSize() == 8,
1569               reinterpret_cast<const SegmentReg&>(src).getRegCode(),
1570               reinterpret_cast<const Operand&>(dst),
1571               0, forceRexPrefix);
1572             _FINISHED();
1573           }
1574           else
1575           {
1576             // Mem <- Reg
1577             ASMJIT_ASSERT(src.isRegType(kX86RegTypeGpbLo) ||
1578                           src.isRegType(kX86RegTypeGpbHi) ||
1579                           src.isRegType(kX86RegTypeGpw   ) ||
1580                           src.isRegType(kX86RegTypeGpd   ) ||
1581                           src.isRegType(kX86RegTypeGpq   ) );
1582 
1583             _emitX86RM(0x88 + (src.getSize() != 1),
1584               src.isRegType(kX86RegTypeGpw),
1585               src.isRegType(kX86RegTypeGpq),
1586               reinterpret_cast<const GpReg&>(src).getRegCode(),
1587               reinterpret_cast<const Operand&>(dst),
1588               0, forceRexPrefix);
1589             _FINISHED();
1590           }
1591         }
1592 
1593         // Mem <- Imm
1594         case (kOperandMem << 4) | kOperandImm:
1595         {
1596           immSize = IntUtil::_min<uint32_t>(dst.getSize(), 4);
1597 
1598           _emitX86RM(0xC6 + (dst.getSize() != 1),
1599             dst.getSize() == 2,
1600             dst.getSize() == 8,
1601             0,
1602             reinterpret_cast<const Operand&>(dst),
1603             immSize, forceRexPrefix);
1604           _FINISHED_IMMEDIATE(&src, immSize);
1605         }
1606       }
1607 
1608       break;
1609     }
1610 
1611     case kX86InstGroupMovPtr:
1612     {
1613       if ((o0->isReg() && o1->isImm()) || (o0->isImm() && o1->isReg()))
1614       {
1615         bool reverse = o1->getType() == kOperandReg;
1616         uint8_t opCode = !reverse ? 0xA0 : 0xA2;
1617         const GpReg& reg = reinterpret_cast<const GpReg&>(!reverse ? *o0 : *o1);
1618         const Imm& imm = reinterpret_cast<const Imm&>(!reverse ? *o1 : *o0);
1619 
1620         if (reg.getRegIndex() != 0)
1621           goto _IllegalInstruction;
1622 
1623         if (reg.isRegType(kX86RegTypeGpw)) _emitByte(0x66);
1624 #if defined(ASMJIT_X64)
1625         _emitRexR(reg.getSize() == 8, 0, 0, forceRexPrefix);
1626 #endif // ASMJIT_X64
1627         _emitByte(opCode + (reg.getSize() != 1));
1628         _FINISHED_IMMEDIATE(&imm, sizeof(sysint_t));
1629       }
1630 
1631       break;
1632     }
1633 
1634     case kX86InstGroupMovSxMovZx:
1635     {
1636       if (o0->isReg() && o1->isRegMem())
1637       {
1638         const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1639         const Operand& src = reinterpret_cast<const Operand&>(*o1);
1640 
1641         if (dst.getSize() == 1)
1642           goto _IllegalInstruction;
1643 
1644         if (src.getSize() != 1 && src.getSize() != 2)
1645           goto _IllegalInstruction;
1646 
1647         if (src.getSize() == 2 && dst.getSize() == 2)
1648           goto _IllegalInstruction;
1649 
1650         _emitX86RM(id->_opCode[0] + (src.getSize() != 1),
1651           dst.isRegType(kX86RegTypeGpw),
1652           dst.isRegType(kX86RegTypeGpq),
1653           dst.getRegCode(),
1654           src,
1655           0, forceRexPrefix);
1656         _FINISHED();
1657       }
1658 
1659       break;
1660     }
1661 
1662 #if defined(ASMJIT_X64)
1663     case kX86InstGroupMovSxD:
1664     {
1665       if (o0->isReg() && o1->isRegMem())
1666       {
1667         const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1668         const Operand& src = reinterpret_cast<const Operand&>(*o1);
1669         _emitX86RM(0x00000063,
1670           0,
1671           1, dst.getRegCode(), src,
1672           0, forceRexPrefix);
1673         _FINISHED();
1674       }
1675 
1676       break;
1677     }
1678 #endif // ASMJIT_X64
1679 
1680     case kX86InstGroupPush:
1681     {
1682       if (o0->isRegType(kX86RegTypeSeg))
1683       {
1684         static const uint32_t opcodeList[] =
1685         {
1686           0x06,   // ES.
1687           0x0E,   // CS.
1688           0x16,   // SS.
1689           0x1E,   // DS.
1690           0x0FA0, // FS.
1691           0x0FA8  // GS.
1692         };
1693 
1694         unsigned int segment = reinterpret_cast<const SegmentReg*>(o0)->getRegIndex();
1695         ASMJIT_ASSERT(segment < kX86SegCount);
1696 
1697         unsigned int opcode = opcodeList[segment];
1698 
1699         if (opcode > 0xFF)
1700           _emitByte(opcode >> 8);
1701         _emitByte(opcode & 0xFF);
1702 
1703         _FINISHED();
1704       }
1705 
1706       // This section is only for immediates, memory/register operands are handled in kX86InstGroupPop.
1707       if (o0->isImm())
1708       {
1709         const Imm& imm = reinterpret_cast<const Imm&>(*o0);
1710 
1711         if (IntUtil::isInt8(imm.getValue()))
1712         {
1713           _emitByte(0x6A);
1714           _FINISHED_IMMEDIATE(&imm, 1);
1715         }
1716         else
1717         {
1718           _emitByte(0x68);
1719           _FINISHED_IMMEDIATE(&imm, 4);
1720         }
1721       }
1722 
1723       // ... goto kX86InstGroupPop ...
1724     }
1725 
1726     case kX86InstGroupPop:
1727     {
1728       if (o0->isRegType(kX86RegTypeSeg))
1729       {
1730         static const uint32_t opcodeList[] =
1731         {
1732           0x07,   // ES.
1733           0,      // CS.
1734           0x17,   // SS.
1735           0x1F,   // DS.
1736           0x0FA1, // FS.
1737           0x0FA9  // GS.
1738         };
1739 
1740         unsigned int segment = reinterpret_cast<const SegmentReg*>(o0)->getRegIndex();
1741         ASMJIT_ASSERT(segment < kX86SegCount);
1742 
1743         unsigned int opcode = opcodeList[segment];
1744         ASMJIT_ASSERT(opcode != 0);
1745 
1746         if (opcode > 0xFF)
1747           _emitByte(opcode >> 8);
1748         _emitByte(opcode & 0xFF);
1749 
1750         _FINISHED();
1751       }
1752 
1753       if (o0->isReg())
1754       {
1755         ASMJIT_ASSERT(o0->isRegType(kX86RegTypeGpw) || o0->isRegType(kX86RegTypeGpz));
1756         _emitX86Inl(id->_opCode[0], o0->isRegType(kX86RegTypeGpw), 0, reinterpret_cast<const GpReg&>(*o0).getRegCode(), forceRexPrefix);
1757         _FINISHED();
1758       }
1759 
1760       if (o0->isMem())
1761       {
1762         _emitX86RM(id->_opCode[1], o0->getSize() == 2, 0, (uint8_t)id->_opCodeR, reinterpret_cast<const Operand&>(*o0), 0, forceRexPrefix);
1763         _FINISHED();
1764       }
1765 
1766       break;
1767     }
1768 
1769     case kX86InstGroupRegRm:
1770     {
1771       if (o0->isReg() && o1->isRegMem())
1772       {
1773         const GpReg& dst = reinterpret_cast<const GpReg&>(*o0);
1774         const Operand& src = reinterpret_cast<const Operand&>(*o1);
1775         ASMJIT_ASSERT(dst.getSize() != 1);
1776 
1777         _emitX86RM(id->_opCode[0],
1778           dst.getRegType() == kX86RegTypeGpw,
1779           dst.getRegType() == kX86RegTypeGpq, dst.getRegCode(), src,
1780           0, forceRexPrefix);
1781         _FINISHED();
1782       }
1783 
1784       break;
1785     }
1786 
1787     case kX86InstGroupRm:
1788     {
1789       if (o0->isRegMem())
1790       {
1791         const Operand& op = reinterpret_cast<const Operand&>(*o0);
1792         _emitX86RM(id->_opCode[0] + (op.getSize() != 1),
1793           op.getSize() == 2,
1794           op.getSize() == 8, (uint8_t)id->_opCodeR, op,
1795           0, forceRexPrefix);
1796         _FINISHED();
1797       }
1798 
1799       break;
1800     }
1801 
1802     case kX86InstGroupRmByte:
1803     {
1804       if (o0->isRegMem())
1805       {
1806         const Operand& op = reinterpret_cast<const Operand&>(*o0);
1807 
1808         // Only BYTE register or BYTE/TYPELESS memory location can be used.
1809         ASMJIT_ASSERT(op.getSize() <= 1);
1810 
1811         _emitX86RM(id->_opCode[0], false, false, 0, op, 0, forceRexPrefix);
1812         _FINISHED();
1813       }
1814 
1815       break;
1816     }
1817 
1818     case kX86InstGroupRmReg:
1819     {
1820       if (o0->isRegMem() && o1->isReg())
1821       {
1822         const Operand& dst = reinterpret_cast<const Operand&>(*o0);
1823         const GpReg& src = reinterpret_cast<const GpReg&>(*o1);
1824         _emitX86RM(id->_opCode[0] + (src.getSize() != 1),
1825           src.getRegType() == kX86RegTypeGpw,
1826           src.getRegType() == kX86RegTypeGpq, src.getRegCode(), dst,
1827           0, forceRexPrefix);
1828         _FINISHED();
1829       }
1830 
1831       break;
1832     }
1833 
1834     case kX86InstGroupRep:
1835     {
1836       uint32_t opCode = id->_opCode[0];
1837       uint32_t opSize = id->_opCode[1];
1838 
1839       // Emit REP prefix (1 BYTE).
1840       _emitByte(opCode >> 24);
1841 
1842       if (opSize != 1) opCode++; // D, Q and W form.
1843       if (opSize == 2) _emitByte(0x66); // 16-bit prefix.
1844 #if defined(ASMJIT_X64)
1845       else if (opSize == 8) _emitByte(0x48); // REX.W prefix.
1846 #endif // ASMJIT_X64
1847 
1848       // Emit opcode (1 BYTE).
1849       _emitByte(opCode & 0xFF);
1850       _FINISHED();
1851     }
1852 
1853     case kX86InstGroupRet:
1854     {
1855       if (o0->isNone())
1856       {
1857         _emitByte(0xC3);
1858         _FINISHED();
1859       }
1860       else if (o0->isImm())
1861       {
1862         const Imm& imm = reinterpret_cast<const Imm&>(*o0);
1863         ASMJIT_ASSERT(IntUtil::isUInt16(imm.getValue()));
1864 
1865         if (imm.getValue() == 0)
1866         {
1867           _emitByte(0xC3);
1868           _FINISHED();
1869         }
1870         else
1871         {
1872           _emitByte(0xC2);
1873           _FINISHED_IMMEDIATE(&imm, 2);
1874         }
1875       }
1876 
1877       break;
1878     }
1879 
1880     case kX86InstGroupRot:
1881     {
1882       if (o0->isRegMem() && (o1->isRegCode(kX86RegCl) || o1->isImm()))
1883       {
1884         // generate opcode. For these operations is base 0xC0 or 0xD0.
1885         bool useImm8 = o1->isImm() && reinterpret_cast<const Imm&>(*o1).getValue() != 1;
1886         uint32_t opCode = useImm8 ? 0xC0 : 0xD0;
1887 
1888         // size and operand type modifies the opcode
1889         if (o0->getSize() != 1) opCode |= 0x01;
1890         if (o1->getType() == kOperandReg) opCode |= 0x02;
1891 
1892         _emitX86RM(opCode,
1893           o0->getSize() == 2,
1894           o0->getSize() == 8,
1895           (uint8_t)id->_opCodeR, reinterpret_cast<const Operand&>(*o0),
1896           useImm8 ? 1 : 0, forceRexPrefix);
1897 
1898         if (useImm8)
1899           _FINISHED_IMMEDIATE(o1, 1);
1900         else
1901           _FINISHED();
1902       }
1903 
1904       break;
1905     }
1906 
1907     case kX86InstGroupShldShrd:
1908     {
1909       if (o0->isRegMem() && o1->isReg() && (o2->isImm() || (o2->isReg() && o2->isRegCode(kX86RegCl))))
1910       {
1911         const Operand& dst = reinterpret_cast<const Operand&>(*o0);
1912         const GpReg& src1 = reinterpret_cast<const GpReg&>(*o1);
1913         const Operand& src2 = reinterpret_cast<const Operand&>(*o2);
1914 
1915         ASMJIT_ASSERT(dst.getSize() == src1.getSize());
1916 
1917         _emitX86RM(id->_opCode[0] + src2.isReg(),
1918           src1.isRegType(kX86RegTypeGpw),
1919           src1.isRegType(kX86RegTypeGpq),
1920           src1.getRegCode(), dst,
1921           src2.isImm() ? 1 : 0, forceRexPrefix);
1922         if (src2.isImm())
1923           _FINISHED_IMMEDIATE(&src2, 1);
1924         else
1925           _FINISHED();
1926       }
1927 
1928       break;
1929     }
1930 
1931     case kX86InstGroupTest:
1932     {
1933       if (o0->isRegMem() && o1->isReg())
1934       {
1935         ASMJIT_ASSERT(o0->getSize() == o1->getSize());
1936         _emitX86RM(0x84 + (o1->getSize() != 1),
1937           o1->getSize() == 2, o1->getSize() == 8,
1938           reinterpret_cast<const Reg&>(*o1).getRegCode(),
1939           reinterpret_cast<const Operand&>(*o0),
1940           0, forceRexPrefix);
1941         _FINISHED();
1942       }
1943 
1944       // Alternate Form - AL, AX, EAX, RAX.
1945       if (o0->isRegIndex(0) && o1->isImm())
1946       {
1947         immSize = IntUtil::_min<uint32_t>(o0->getSize(), 4);
1948 
1949         if (o0->getSize() == 2) _emitByte(0x66); // 16-bit.
1950 #if defined(ASMJIT_X64)
1951         _emitRexRM(o0->getSize() == 8, 0, reinterpret_cast<const Operand&>(*o0), forceRexPrefix);
1952 #endif // ASMJIT_X64
1953         _emitByte(0xA8 + (o0->getSize() != 1));
1954         _FINISHED_IMMEDIATE(o1, immSize);
1955       }
1956 
1957       if (o0->isRegMem() && o1->isImm())
1958       {
1959         immSize = IntUtil::_min<uint32_t>(o0->getSize(), 4);
1960 
1961         if (o0->getSize() == 2) _emitByte(0x66); // 16-bit.
1962         _emitSegmentPrefix(reinterpret_cast<const Operand&>(*o0)); // Segment prefix.
1963 #if defined(ASMJIT_X64)
1964         _emitRexRM(o0->getSize() == 8, 0, reinterpret_cast<const Operand&>(*o0), forceRexPrefix);
1965 #endif // ASMJIT_X64
1966         _emitByte(0xF6 + (o0->getSize() != 1));
1967         _emitModRM(0, reinterpret_cast<const Operand&>(*o0), immSize);
1968         _FINISHED_IMMEDIATE(o1, immSize);
1969       }
1970 
1971       break;
1972     }
1973 
1974     case kX86InstGroupXchg:
1975     {
1976       if (o0->isRegMem() && o1->isReg())
1977       {
1978         const Operand& dst = reinterpret_cast<const Operand&>(*o0);
1979         const GpReg& src = reinterpret_cast<const GpReg&>(*o1);
1980 
1981         if (src.isRegType(kX86RegTypeGpw)) _emitByte(0x66); // 16-bit.
1982         _emitSegmentPrefix(dst); // segment prefix
1983 #if defined(ASMJIT_X64)
1984         _emitRexRM(src.isRegType(kX86RegTypeGpq), src.getRegCode(), dst, forceRexPrefix);
1985 #endif // ASMJIT_X64
1986 
1987         // Special opcode for index 0 registers (AX, EAX, RAX vs register).
1988         if ((dst.getType() == kOperandReg && dst.getSize() > 1) &&
1989             (reinterpret_cast<const GpReg&>(dst).getRegCode() == 0 ||
1990              reinterpret_cast<const GpReg&>(src).getRegCode() == 0 ))
1991         {
1992           uint8_t index = reinterpret_cast<const GpReg&>(dst).getRegCode() | src.getRegCode();
1993           _emitByte(0x90 + index);
1994           _FINISHED();
1995         }
1996 
1997         _emitByte(0x86 + (src.getSize() != 1));
1998         _emitModRM(src.getRegCode(), dst, 0);
1999         _FINISHED();
2000       }
2001 
2002       break;
2003     }
2004 
2005     case kX86InstGroupMovBE:
2006     {
2007       if (o0->isReg() && o1->isMem())
2008       {
2009         _emitX86RM(0x000F38F0,
2010           o0->isRegType(kX86RegTypeGpw),
2011           o0->isRegType(kX86RegTypeGpq),
2012           reinterpret_cast<const GpReg&>(*o0).getRegCode(),
2013           reinterpret_cast<const Mem&>(*o1),
2014           0, forceRexPrefix);
2015         _FINISHED();
2016       }
2017 
2018       if (o0->isMem() && o1->isReg())
2019       {
2020         _emitX86RM(0x000F38F1,
2021           o1->isRegType(kX86RegTypeGpw),
2022           o1->isRegType(kX86RegTypeGpq),
2023           reinterpret_cast<const GpReg&>(*o1).getRegCode(),
2024           reinterpret_cast<const Mem&>(*o0),
2025           0, forceRexPrefix);
2026         _FINISHED();
2027       }
2028 
2029       break;
2030     }
2031 
2032     case kX86InstGroupX87StM:
2033     {
2034       if (o0->isRegType(kX86RegTypeX87))
2035       {
2036         uint8_t i1 = reinterpret_cast<const X87Reg&>(*o0).getRegIndex();
2037         uint8_t i2 = 0;
2038 
2039         if (code != kX86InstFCom && code != kX86InstFComP)
2040         {
2041           if (!o1->isRegType(kX86RegTypeX87))
2042             goto _IllegalInstruction;
2043           i2 = reinterpret_cast<const X87Reg&>(*o1).getRegIndex();
2044         }
2045         else if (i1 != 0 && i2 != 0)
2046         {
2047           goto _IllegalInstruction;
2048         }
2049 
2050         _emitByte(i1 == 0
2051           ? ((id->_opCode[0] & 0xFF000000) >> 24)
2052           : ((id->_opCode[0] & 0x00FF0000) >> 16));
2053         _emitByte(i1 == 0
2054           ? ((id->_opCode[0] & 0x0000FF00) >>  8) + i2
2055           : ((id->_opCode[0] & 0x000000FF)      ) + i1);
2056         _FINISHED();
2057       }
2058 
2059       if (o0->isMem() && (o0->getSize() == 4 || o0->getSize() == 8) && o1->isNone())
2060       {
2061         const Mem& m = reinterpret_cast<const Mem&>(*o0);
2062 
2063         // Segment prefix.
2064         _emitSegmentPrefix(m);
2065 
2066         _emitByte(o0->getSize() == 4
2067           ? ((id->_opCode[0] & 0xFF000000) >> 24)
2068           : ((id->_opCode[0] & 0x00FF0000) >> 16));
2069         _emitModM((uint8_t)id->_opCodeR, m, 0);
2070         _FINISHED();
2071       }
2072 
2073       break;
2074     }
2075 
2076     case kX86InstGroupX87StI:
2077     {
2078       if (o0->isRegType(kX86RegTypeX87))
2079       {
2080         uint8_t i = reinterpret_cast<const X87Reg&>(*o0).getRegIndex();
2081         _emitByte((uint8_t)((id->_opCode[0] & 0x0000FF00) >> 8));
2082         _emitByte((uint8_t)((id->_opCode[0] & 0x000000FF) + i));
2083         _FINISHED();
2084       }
2085       break;
2086     }
2087 
2088     case kX86InstGroupX87Status:
2089     {
2090       if (o0->isReg() &&
2091           reinterpret_cast<const Reg&>(*o0).getRegType() <= kX86RegTypeGpq &&
2092           reinterpret_cast<const Reg&>(*o0).getRegIndex() == 0)
2093       {
2094         _emitOpCode(id->_opCode[1]);
2095         _FINISHED();
2096       }
2097 
2098       if (o0->isMem())
2099       {
2100         _emitX86RM(id->_opCode[0], 0, 0, (uint8_t)id->_opCodeR, reinterpret_cast<const Mem&>(*o0), 0, forceRexPrefix);
2101         _FINISHED();
2102       }
2103 
2104       break;
2105     }
2106 
2107     case kX86InstGroupX87FldFst:
2108     {
2109       if (o0->isRegType(kX86RegTypeX87))
2110       {
2111         _emitByte((uint8_t)((id->_opCode[1] & 0xFF000000) >> 24));
2112         _emitByte((uint8_t)((id->_opCode[1] & 0x00FF0000) >> 16) +
2113           reinterpret_cast<const X87Reg&>(*o0).getRegIndex());
2114         _FINISHED();
2115       }
2116 
2117       // ... fall through to kX86InstGroupX87Mem ...
2118     }
2119 
2120     case kX86InstGroupX87Mem:
2121     {
2122       if (!o0->isMem())
2123         goto _IllegalInstruction;
2124       const Mem& m = reinterpret_cast<const Mem&>(*o0);
2125 
2126       uint8_t opCode = 0x00, mod = 0;
2127 
2128       if (o0->getSize() == 2 && (id->_opFlags[0] & kX86InstOpStM2))
2129       {
2130         opCode = (uint8_t)((id->_opCode[0] & 0xFF000000) >> 24);
2131         mod    = (uint8_t)id->_opCodeR;
2132       }
2133       if (o0->getSize() == 4 && (id->_opFlags[0] & kX86InstOpStM4))
2134       {
2135         opCode = (uint8_t)((id->_opCode[0] & 0x00FF0000) >> 16);
2136         mod    = (uint8_t)id->_opCodeR;
2137       }
2138       if (o0->getSize() == 8 && (id->_opFlags[0] & kX86InstOpStM8))
2139       {
2140         opCode = (uint8_t)((id->_opCode[0] & 0x0000FF00) >>  8);
2141         mod    = (uint8_t)((id->_opCode[0] & 0x000000FF)      );
2142       }
2143 
2144       if (opCode)
2145       {
2146         _emitSegmentPrefix(m);
2147         _emitByte(opCode);
2148         _emitModM(mod, m, 0);
2149         _FINISHED();
2150       }
2151 
2152       break;
2153     }
2154 
2155     case kX86InstGroupMmuMov:
2156     {
2157       ASMJIT_ASSERT(id->_opFlags[0] != 0);
2158       ASMJIT_ASSERT(id->_opFlags[1] != 0);
2159 
2160       // Check parameters (X)MM|GP32_64 <- (X)MM|GP32_64|Mem|Imm
2161       if ((o0->isMem()                 && (id->_opFlags[0] & kX86InstOpMem) == 0) ||
2162           (o0->isRegType(kX86RegTypeMm ) && (id->_opFlags[0] & kX86InstOpMm ) == 0) ||
2163           (o0->isRegType(kX86RegTypeXmm) && (id->_opFlags[0] & kX86InstOpXmm) == 0) ||
2164           (o0->isRegType(kX86RegTypeGpd) && (id->_opFlags[0] & kX86InstOpGd ) == 0) ||
2165           (o0->isRegType(kX86RegTypeGpq) && (id->_opFlags[0] & kX86InstOpGq ) == 0) ||
2166           (o1->isRegType(kX86RegTypeMm ) && (id->_opFlags[1] & kX86InstOpMm ) == 0) ||
2167           (o1->isRegType(kX86RegTypeXmm) && (id->_opFlags[1] & kX86InstOpXmm) == 0) ||
2168           (o1->isRegType(kX86RegTypeGpd) && (id->_opFlags[1] & kX86InstOpGd ) == 0) ||
2169           (o1->isRegType(kX86RegTypeGpq) && (id->_opFlags[1] & kX86InstOpGq ) == 0) ||
2170           (o1->isMem()                 && (id->_opFlags[1] & kX86InstOpMem) == 0) )
2171       {
2172         goto _IllegalInstruction;
2173       }
2174 
2175       // Illegal.
2176       if (o0->isMem() && o1->isMem())
2177         goto _IllegalInstruction;
2178 
2179       uint8_t rexw = ((id->_opFlags[0] | id->_opFlags[1]) & kX86InstOpNoRex)
2180         ? 0
2181         : o0->isRegType(kX86RegTypeGpq) | o1->isRegType(kX86RegTypeGpq);
2182 
2183       // (X)MM|Reg <- (X)MM|Reg
2184       if (o0->isReg() && o1->isReg())
2185       {
2186         _emitMmu(id->_opCode[0], rexw,
2187           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2188           reinterpret_cast<const Reg&>(*o1),
2189           0);
2190         _FINISHED();
2191       }
2192 
2193       // (X)MM|Reg <- Mem
2194       if (o0->isReg() && o1->isMem())
2195       {
2196         _emitMmu(id->_opCode[0], rexw,
2197           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2198           reinterpret_cast<const Mem&>(*o1),
2199           0);
2200         _FINISHED();
2201       }
2202 
2203       // Mem <- (X)MM|Reg
2204       if (o0->isMem() && o1->isReg())
2205       {
2206         _emitMmu(id->_opCode[1], rexw,
2207           reinterpret_cast<const Reg&>(*o1).getRegCode(),
2208           reinterpret_cast<const Mem&>(*o0),
2209           0);
2210         _FINISHED();
2211       }
2212 
2213       break;
2214     }
2215 
2216     case kX86InstGroupMmuMovD:
2217     {
2218       if ((o0->isRegType(kX86RegTypeMm) || o0->isRegType(kX86RegTypeXmm)) && (o1->isRegType(kX86RegTypeGpd) || o1->isMem()))
2219       {
2220         _emitMmu(o0->isRegType(kX86RegTypeXmm) ? 0x66000F6E : 0x00000F6E, 0,
2221           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2222           reinterpret_cast<const Operand&>(*o1),
2223           0);
2224         _FINISHED();
2225       }
2226 
2227       if ((o0->isRegType(kX86RegTypeGpd) || o0->isMem()) && (o1->isRegType(kX86RegTypeMm) || o1->isRegType(kX86RegTypeXmm)))
2228       {
2229         _emitMmu(o1->isRegType(kX86RegTypeXmm) ? 0x66000F7E : 0x00000F7E, 0,
2230           reinterpret_cast<const Reg&>(*o1).getRegCode(),
2231           reinterpret_cast<const Operand&>(*o0),
2232           0);
2233         _FINISHED();
2234       }
2235 
2236       break;
2237     }
2238 
2239     case kX86InstGroupMmuMovQ:
2240     {
2241       if (o0->isRegType(kX86RegTypeMm) && o1->isRegType(kX86RegTypeMm))
2242       {
2243         _emitMmu(0x00000F6F, 0,
2244           reinterpret_cast<const MmReg&>(*o0).getRegCode(),
2245           reinterpret_cast<const MmReg&>(*o1),
2246           0);
2247         _FINISHED();
2248       }
2249 
2250       if (o0->isRegType(kX86RegTypeXmm) && o1->isRegType(kX86RegTypeXmm))
2251       {
2252         _emitMmu(0xF3000F7E, 0,
2253           reinterpret_cast<const XmmReg&>(*o0).getRegCode(),
2254           reinterpret_cast<const XmmReg&>(*o1),
2255           0);
2256         _FINISHED();
2257       }
2258 
2259       // Convenience - movdq2q
2260       if (o0->isRegType(kX86RegTypeMm) && o1->isRegType(kX86RegTypeXmm))
2261       {
2262         _emitMmu(0xF2000FD6, 0,
2263           reinterpret_cast<const MmReg&>(*o0).getRegCode(),
2264           reinterpret_cast<const XmmReg&>(*o1),
2265           0);
2266         _FINISHED();
2267       }
2268 
2269       // Convenience - movq2dq
2270       if (o0->isRegType(kX86RegTypeXmm) && o1->isRegType(kX86RegTypeMm))
2271       {
2272         _emitMmu(0xF3000FD6, 0,
2273           reinterpret_cast<const XmmReg&>(*o0).getRegCode(),
2274           reinterpret_cast<const MmReg&>(*o1),
2275           0);
2276         _FINISHED();
2277       }
2278 
2279       if (o0->isRegType(kX86RegTypeMm) && o1->isMem())
2280       {
2281         _emitMmu(0x00000F6F, 0,
2282           reinterpret_cast<const MmReg&>(*o0).getRegCode(),
2283           reinterpret_cast<const Mem&>(*o1),
2284           0);
2285         _FINISHED();
2286       }
2287 
2288       if (o0->isRegType(kX86RegTypeXmm) && o1->isMem())
2289       {
2290         _emitMmu(0xF3000F7E, 0,
2291           reinterpret_cast<const XmmReg&>(*o0).getRegCode(),
2292           reinterpret_cast<const Mem&>(*o1),
2293           0);
2294         _FINISHED();
2295       }
2296 
2297       if (o0->isMem() && o1->isRegType(kX86RegTypeMm))
2298       {
2299         _emitMmu(0x00000F7F, 0,
2300           reinterpret_cast<const MmReg&>(*o1).getRegCode(),
2301           reinterpret_cast<const Mem&>(*o0),
2302           0);
2303         _FINISHED();
2304       }
2305 
2306       if (o0->isMem() && o1->isRegType(kX86RegTypeXmm))
2307       {
2308         _emitMmu(0x66000FD6, 0,
2309           reinterpret_cast<const XmmReg&>(*o1).getRegCode(),
2310           reinterpret_cast<const Mem&>(*o0),
2311           0);
2312         _FINISHED();
2313       }
2314 
2315 #if defined(ASMJIT_X64)
2316       if ((o0->isRegType(kX86RegTypeMm) || o0->isRegType(kX86RegTypeXmm)) && (o1->isRegType(kX86RegTypeGpq) || o1->isMem()))
2317       {
2318         _emitMmu(o0->isRegType(kX86RegTypeXmm) ? 0x66000F6E : 0x00000F6E, 1,
2319           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2320           reinterpret_cast<const Operand&>(*o1),
2321           0);
2322         _FINISHED();
2323       }
2324 
2325       if ((o0->isRegType(kX86RegTypeGpq) || o0->isMem()) && (o1->isRegType(kX86RegTypeMm) || o1->isRegType(kX86RegTypeXmm)))
2326       {
2327         _emitMmu(o1->isRegType(kX86RegTypeXmm) ? 0x66000F7E : 0x00000F7E, 1,
2328           reinterpret_cast<const Reg&>(*o1).getRegCode(),
2329           reinterpret_cast<const Operand&>(*o0),
2330           0);
2331         _FINISHED();
2332       }
2333 #endif // ASMJIT_X64
2334 
2335       break;
2336     }
2337 
2338     case kX86InstGroupMmuExtract:
2339     {
2340       if (!(o0->isRegMem() &&
2341            (o1->isRegType(kX86RegTypeXmm) || (code == kX86InstPExtrW && o1->isRegType(kX86RegTypeMm))) &&
2342             o2->isImm()))
2343       {
2344         goto _IllegalInstruction;
2345       }
2346 
2347       uint32_t opCode = id->_opCode[0];
2348       uint8_t isGpdGpq = o0->isRegType(kX86RegTypeGpd) | o0->isRegType(kX86RegTypeGpq);
2349 
2350       if (code == kX86InstPExtrB && (o0->getSize() != 0 && o0->getSize() != 1) && !isGpdGpq)
2351         goto _IllegalInstruction;
2352       if (code == kX86InstPExtrW && (o0->getSize() != 0 && o0->getSize() != 2) && !isGpdGpq)
2353         goto _IllegalInstruction;
2354       if (code == kX86InstPExtrD && (o0->getSize() != 0 && o0->getSize() != 4) && !isGpdGpq)
2355         goto _IllegalInstruction;
2356       if (code == kX86InstPExtrQ && (o0->getSize() != 0 && o0->getSize() != 8) && !isGpdGpq)
2357         goto _IllegalInstruction;
2358 
2359       if (o1->isRegType(kX86RegTypeXmm)) opCode |= 0x66000000;
2360 
2361       if (o0->isReg())
2362       {
2363         _emitMmu(opCode, id->_opCodeR | (uint8_t)o0->isRegType(kX86RegTypeGpq),
2364           reinterpret_cast<const Reg&>(*o1).getRegCode(),
2365           reinterpret_cast<const Reg&>(*o0), 1);
2366         _FINISHED_IMMEDIATE(o2, 1);
2367       }
2368 
2369       if (o0->isMem())
2370       {
2371         _emitMmu(opCode, (uint8_t)id->_opCodeR,
2372           reinterpret_cast<const Reg&>(*o1).getRegCode(),
2373           reinterpret_cast<const Mem&>(*o0), 1);
2374         _FINISHED_IMMEDIATE(o2, 1);
2375       }
2376 
2377       break;
2378     }
2379 
2380     case kX86InstGroupMmuPrefetch:
2381     {
2382       if (o0->isMem() && o1->isImm())
2383       {
2384         const Mem& mem = reinterpret_cast<const Mem&>(*o0);
2385         const Imm& hint = reinterpret_cast<const Imm&>(*o1);
2386 
2387         _emitMmu(0x00000F18, 0, (uint8_t)hint.getValue(), mem, 0);
2388         _FINISHED();
2389       }
2390 
2391       break;
2392     }
2393 
2394     case kX86InstGroupMmuRmI:
2395     {
2396       ASMJIT_ASSERT(id->_opFlags[0] != 0);
2397       ASMJIT_ASSERT(id->_opFlags[1] != 0);
2398 
2399       // Check parameters (X)MM|GP32_64 <- (X)MM|GP32_64|Mem|Imm
2400       if (!o0->isReg() ||
2401           (o0->isRegType(kX86RegTypeMm ) && (id->_opFlags[0] & kX86InstOpMm ) == 0) ||
2402           (o0->isRegType(kX86RegTypeXmm) && (id->_opFlags[0] & kX86InstOpXmm) == 0) ||
2403           (o0->isRegType(kX86RegTypeGpd) && (id->_opFlags[0] & kX86InstOpGd ) == 0) ||
2404           (o0->isRegType(kX86RegTypeGpq) && (id->_opFlags[0] & kX86InstOpGq ) == 0) ||
2405           (o1->isRegType(kX86RegTypeMm ) && (id->_opFlags[1] & kX86InstOpMm ) == 0) ||
2406           (o1->isRegType(kX86RegTypeXmm) && (id->_opFlags[1] & kX86InstOpXmm) == 0) ||
2407           (o1->isRegType(kX86RegTypeGpd) && (id->_opFlags[1] & kX86InstOpGd ) == 0) ||
2408           (o1->isRegType(kX86RegTypeGpq) && (id->_opFlags[1] & kX86InstOpGq ) == 0) ||
2409           (o1->isMem()                   && (id->_opFlags[1] & kX86InstOpMem) == 0) ||
2410           (o1->isImm()                   && (id->_opFlags[1] & kX86InstOpImm) == 0))
2411       {
2412         goto _IllegalInstruction;
2413       }
2414 
2415       uint32_t prefix =
2416         ((id->_opFlags[0] & kX86InstOpMmXmm) == kX86InstOpMmXmm && o0->isRegType(kX86RegTypeXmm)) ||
2417         ((id->_opFlags[1] & kX86InstOpMmXmm) == kX86InstOpMmXmm && o1->isRegType(kX86RegTypeXmm))
2418           ? 0x66000000
2419           : 0x00000000;
2420 
2421       uint8_t rexw = ((id->_opFlags[0] | id->_opFlags[1]) & kX86InstOpNoRex)
2422         ? 0
2423         : o0->isRegType(kX86RegTypeGpq) | o1->isRegType(kX86RegTypeGpq);
2424 
2425       // (X)MM <- (X)MM (opcode0)
2426       if (o1->isReg())
2427       {
2428         if ((id->_opFlags[1] & (kX86InstOpMmXmm | kX86InstOpGqd)) == 0)
2429           goto _IllegalInstruction;
2430         _emitMmu(id->_opCode[0] | prefix, rexw,
2431           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2432           reinterpret_cast<const Reg&>(*o1), 0);
2433         _FINISHED();
2434       }
2435       // (X)MM <- Mem (opcode0)
2436       if (o1->isMem())
2437       {
2438         if ((id->_opFlags[1] & kX86InstOpMem) == 0)
2439           goto _IllegalInstruction;
2440         _emitMmu(id->_opCode[0] | prefix, rexw,
2441           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2442           reinterpret_cast<const Mem&>(*o1), 0);
2443         _FINISHED();
2444       }
2445       // (X)MM <- Imm (opcode1+opcodeR)
2446       if (o1->isImm())
2447       {
2448         if ((id->_opFlags[1] & kX86InstOpImm) == 0)
2449           goto _IllegalInstruction;
2450         _emitMmu(id->_opCode[1] | prefix, rexw,
2451           (uint8_t)id->_opCodeR,
2452           reinterpret_cast<const Reg&>(*o0), 1);
2453         _FINISHED_IMMEDIATE(o1, 1);
2454       }
2455 
2456       break;
2457     }
2458 
2459     case kX86InstGroupMmuRmImm8:
2460     {
2461       ASMJIT_ASSERT(id->_opFlags[0] != 0);
2462       ASMJIT_ASSERT(id->_opFlags[1] != 0);
2463 
2464       // Check parameters (X)MM|GP32_64 <- (X)MM|GP32_64|Mem|Imm
2465       if (!o0->isReg() ||
2466           (o0->isRegType(kX86RegTypeMm ) && (id->_opFlags[0] & kX86InstOpMm ) == 0) ||
2467           (o0->isRegType(kX86RegTypeXmm) && (id->_opFlags[0] & kX86InstOpXmm) == 0) ||
2468           (o0->isRegType(kX86RegTypeGpd) && (id->_opFlags[0] & kX86InstOpGd ) == 0) ||
2469           (o0->isRegType(kX86RegTypeGpq) && (id->_opFlags[0] & kX86InstOpGq ) == 0) ||
2470           (o1->isRegType(kX86RegTypeMm ) && (id->_opFlags[1] & kX86InstOpMm ) == 0) ||
2471           (o1->isRegType(kX86RegTypeXmm) && (id->_opFlags[1] & kX86InstOpXmm) == 0) ||
2472           (o1->isRegType(kX86RegTypeGpd) && (id->_opFlags[1] & kX86InstOpGd ) == 0) ||
2473           (o1->isRegType(kX86RegTypeGpq) && (id->_opFlags[1] & kX86InstOpGq ) == 0) ||
2474           (o1->isMem()                 && (id->_opFlags[1] & kX86InstOpMem) == 0) ||
2475           !o2->isImm())
2476       {
2477         goto _IllegalInstruction;
2478       }
2479 
2480       uint32_t prefix =
2481         ((id->_opFlags[0] & kX86InstOpMmXmm) == kX86InstOpMmXmm && o0->isRegType(kX86RegTypeXmm)) ||
2482         ((id->_opFlags[1] & kX86InstOpMmXmm) == kX86InstOpMmXmm && o1->isRegType(kX86RegTypeXmm))
2483           ? 0x66000000
2484           : 0x00000000;
2485 
2486       uint8_t rexw = ((id->_opFlags[0]|id->_opFlags[1]) & kX86InstOpNoRex)
2487         ? 0
2488         : o0->isRegType(kX86RegTypeGpq) | o1->isRegType(kX86RegTypeGpq);
2489 
2490       // (X)MM <- (X)MM (opcode0)
2491       if (o1->isReg())
2492       {
2493         if ((id->_opFlags[1] & (kX86InstOpMmXmm | kX86InstOpGqd)) == 0)
2494 goto _IllegalInstruction;
2495         _emitMmu(id->_opCode[0] | prefix, rexw,
2496           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2497           reinterpret_cast<const Reg&>(*o1), 1);
2498         _FINISHED_IMMEDIATE(o2, 1);
2499       }
2500       // (X)MM <- Mem (opcode0)
2501       if (o1->isMem())
2502       {
2503         if ((id->_opFlags[1] & kX86InstOpMem) == 0)
2504           goto _IllegalInstruction;
2505         _emitMmu(id->_opCode[0] | prefix, rexw,
2506           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2507           reinterpret_cast<const Mem&>(*o1), 1);
2508         _FINISHED_IMMEDIATE(o2, 1);
2509       }
2510 
2511       break;
2512     }
2513 
2514     case kX86InstGroupMmuRm3dNow:
2515     {
2516       if (o0->isRegType(kX86RegTypeMm) && (o1->isRegType(kX86RegTypeMm) || o1->isMem()))
2517       {
2518         _emitMmu(id->_opCode[0], 0,
2519           reinterpret_cast<const Reg&>(*o0).getRegCode(),
2520           reinterpret_cast<const Mem&>(*o1), 1);
2521         _emitByte((uint8_t)id->_opCode[1]);
2522         _FINISHED();
2523       }
2524 
2525       break;
2526     }
2527   }
2528 
2529 _IllegalInstruction:
2530   // Set an error. If we run in release mode assertion will be not used, so we
2531   // must inform about invalid state.
2532   setError(kErrorIllegalInstruction);
2533 
2534 #if defined(ASMJIT_DEBUG)
2535   assertIllegal = true;
2536 #endif // ASMJIT_DEBUG
2537   goto _End;
2538 
2539 _EmitImmediate:
2540   {
2541     sysint_t value = immOperand->getValue();
2542     switch (immSize)
2543     {
2544       case 1: _emitByte ((uint8_t )(sysuint_t)value); break;
2545       case 2: _emitWord ((uint16_t)(sysuint_t)value); break;
2546       case 4: _emitDWord((uint32_t)(sysuint_t)value); break;
2547 #if defined(ASMJIT_X64)
2548       case 8: _emitQWord((uint64_t)(sysuint_t)value); break;
2549 #endif // ASMJIT_X64
2550       default: ASMJIT_ASSERT(0);
2551     }
2552   }
2553 
2554 _End:
2555   if (_logger
2556 #if defined(ASMJIT_DEBUG)
2557       || assertIllegal
2558 #endif // ASMJIT_DEBUG
2559      )
2560   {
2561     char bufStorage[512];
2562     char* buf = bufStorage;
2563 
2564     // Detect truncated operand.
2565     Imm immTemporary(0);
2566     uint32_t loggerFlags = 0;
2567 
2568     // Use the original operands, because BYTE some of them were replaced.
2569     if (bLoHiUsed)
2570     {
2571       o0 = _loggerOperands[0];
2572       o1 = _loggerOperands[1];
2573       o2 = _loggerOperands[2];
2574     }
2575 
2576     if (immOperand)
2577     {
2578       sysint_t value = immOperand->getValue();
2579       bool isUnsigned = immOperand->isUnsigned();
2580 
2581       switch (immSize)
2582       {
2583         case 1: if ( isUnsigned && !IntUtil::isUInt8 (value)) { immTemporary.setValue((uint8_t)(sysuint_t)value, true ); break; }
2584                 if (!isUnsigned && !IntUtil::isInt8  (value)) { immTemporary.setValue((uint8_t)(sysuint_t)value, false); break; }
2585                 break;
2586         case 2: if ( isUnsigned && !IntUtil::isUInt16(value)) { immTemporary.setValue((uint16_t)(sysuint_t)value, true ); break; }
2587                 if (!isUnsigned && !IntUtil::isInt16 (value)) { immTemporary.setValue((uint16_t)(sysuint_t)value, false); break; }
2588                 break;
2589         case 4: if ( isUnsigned && !IntUtil::isUInt32(value)) { immTemporary.setValue((uint32_t)(sysuint_t)value, true ); break; }
2590                 if (!isUnsigned && !IntUtil::isInt32 (value)) { immTemporary.setValue((uint32_t)(sysuint_t)value, false); break; }
2591                 break;
2592       }
2593 
2594       if (immTemporary.getValue() != 0)
2595       {
2596         if (o0 == immOperand) o0 = &immTemporary;
2597         if (o1 == immOperand) o1 = &immTemporary;
2598         if (o2 == immOperand) o2 = &immTemporary;
2599       }
2600     }
2601 
2602     if (_logger)
2603     {
2604       buf = StringUtil::copy(buf, _logger->getInstructionPrefix());
2605       loggerFlags = _logger->getFlags();
2606     }
2607 
2608     buf = X86Assembler_dumpInstruction(buf, code, _emitOptions, o0, o1, o2, memRegType, loggerFlags);
2609 
2610     if ((loggerFlags & kLoggerOutputBinary) != 0)
2611       buf = X86Assembler_dumpComment(buf, (size_t)(buf - bufStorage), getCode() + beginOffset, getOffset() - beginOffset, _inlineComment);
2612     else
2613       buf = X86Assembler_dumpComment(buf, (size_t)(buf - bufStorage), NULL, 0, _inlineComment);
2614 
2615     // We don't need to NULL terminate the resulting string.
2616 #if defined(ASMJIT_DEBUG)
2617     if (_logger)
2618 #endif // ASMJIT_DEBUG
2619       _logger->logString(bufStorage, (size_t)(buf - bufStorage));
2620 
2621 #if defined(ASMJIT_DEBUG)
2622     if (assertIllegal)
2623     {
2624       // Here we need to NULL terminate.
2625       buf[0] = '\0';
2626 
2627       // Raise an assertion failure, because this situation shouldn't happen.
2628       assertionFailure(__FILE__, __LINE__, bufStorage);
2629     }
2630 #endif // ASMJIT_DEBUG
2631   }
2632 
2633 _Cleanup:
2634   _inlineComment = NULL;
2635   _emitOptions = 0;
2636 }
2637 
_emitJcc(uint32_t code,const Label * label,uint32_t hint)2638 void X86Assembler::_emitJcc(uint32_t code, const Label* label, uint32_t hint)
2639 {
2640   if (hint == kCondHintNone)
2641   {
2642     _emitInstruction(code, label);
2643   }
2644   else
2645   {
2646     Imm imm(hint);
2647     _emitInstruction(code, label, &imm);
2648   }
2649 }
2650 
2651 // ============================================================================
2652 // [AsmJit::Assembler - Relocation helpers]
2653 // ============================================================================
2654 
relocCode(void * _dst,sysuint_t addressBase) const2655 size_t X86Assembler::relocCode(void* _dst, sysuint_t addressBase) const
2656 {
2657   // Copy code to virtual memory (this is a given _dst pointer).
2658   uint8_t* dst = reinterpret_cast<uint8_t*>(_dst);
2659 
2660   size_t coff = _buffer.getOffset();
2661   size_t csize = getCodeSize();
2662 
2663   // We are copying the exact size of the generated code. Extra code for trampolines
2664   // is generated on-the-fly by relocator (this code doesn't exist at the moment).
2665   memcpy(dst, _buffer.getData(), coff);
2666 
2667 #if defined(ASMJIT_X64)
2668   // Trampoline pointer.
2669   uint8_t* tramp = dst + coff;
2670 #endif // ASMJIT_X64
2671 
2672   // Relocate all recorded locations.
2673   size_t i;
2674   size_t len = _relocData.getLength();
2675 
2676   for (i = 0; i < len; i++)
2677   {
2678     const RelocData& r = _relocData[i];
2679     sysint_t val;
2680 
2681 #if defined(ASMJIT_X64)
2682     // Whether to use trampoline, can be only used if relocation type is
2683     // kRelocAbsToRel.
2684     bool useTrampoline = false;
2685 #endif // ASMJIT_X64
2686 
2687     // Be sure that reloc data structure is correct.
2688     ASMJIT_ASSERT((size_t)(r.offset + r.size) <= csize);
2689 
2690     switch (r.type)
2691     {
2692       case kRelocAbsToAbs:
2693         val = (sysint_t)(r.address);
2694         break;
2695 
2696       case kRelocRelToAbs:
2697         val = (sysint_t)(addressBase + r.destination);
2698         break;
2699 
2700       case kRelocAbsToRel:
2701       case kRelocTrampoline:
2702         val = (sysint_t)( (sysuint_t)r.address - (addressBase + (sysuint_t)r.offset + 4) );
2703 
2704 #if defined(ASMJIT_X64)
2705         if (r.type == kRelocTrampoline && !IntUtil::isInt32(val))
2706         {
2707           val = (sysint_t)( (sysuint_t)tramp - ((sysuint_t)_dst + (sysuint_t)r.offset + 4) );
2708           useTrampoline = true;
2709         }
2710 #endif // ASMJIT_X64
2711         break;
2712 
2713       default:
2714         ASMJIT_ASSERT(0);
2715     }
2716 
2717     switch (r.size)
2718     {
2719       case 4:
2720         *reinterpret_cast<int32_t*>(dst + r.offset) = static_cast<int32_t>(val);
2721         break;
2722 
2723       case 8:
2724         *reinterpret_cast<int64_t*>(dst + r.offset) = static_cast<int64_t>(val);
2725         break;
2726 
2727       default:
2728         ASMJIT_ASSERT(0);
2729     }
2730 
2731 #if defined(ASMJIT_X64)
2732     if (useTrampoline)
2733     {
2734       if (getLogger())
2735       {
2736         getLogger()->logFormat("; Trampoline from %p -> %p\n", (int8_t*)addressBase + r.offset, r.address);
2737       }
2738 
2739       X64TrampolineWriter::writeTrampoline(tramp, (uint64_t)r.address);
2740       tramp += X64TrampolineWriter::kSizeTotal;
2741     }
2742 #endif // ASMJIT_X64
2743   }
2744 
2745 #if defined(ASMJIT_X64)
2746   return (size_t)(tramp - dst);
2747 #else
2748   return (size_t)(coff);
2749 #endif // ASMJIT_X64
2750 }
2751 
2752 // ============================================================================
2753 // [AsmJit::Assembler - EmbedLabel]
2754 // ============================================================================
2755 
embedLabel(const Label & label)2756 void X86Assembler::embedLabel(const Label& label)
2757 {
2758   ASMJIT_ASSERT(label.getId() != kInvalidValue);
2759   if (!canEmit()) return;
2760 
2761   LabelData& l_data = _labels[label.getId() & kOperandIdValueMask];
2762   RelocData r_data;
2763 
2764   if (_logger)
2765   {
2766     _logger->logFormat(sizeof(sysint_t) == 4 ? ".dd L.%u\n" : ".dq L.%u\n", (uint32_t)label.getId() & kOperandIdValueMask);
2767   }
2768 
2769   r_data.type = kRelocRelToAbs;
2770   r_data.size = sizeof(sysint_t);
2771   r_data.offset = getOffset();
2772   r_data.destination = 0;
2773 
2774   if (l_data.offset != -1)
2775   {
2776     // Bound label.
2777     r_data.destination = l_data.offset;
2778   }
2779   else
2780   {
2781     // Non-bound label. Need to chain.
2782     LabelLink* link = _newLabelLink();
2783 
2784     link->prev = (LabelLink*)l_data.links;
2785     link->offset = getOffset();
2786     link->displacement = 0;
2787     link->relocId = _relocData.getLength();
2788 
2789     l_data.links = link;
2790   }
2791 
2792   _relocData.append(r_data);
2793 
2794   // Emit dummy intptr_t (4 or 8 bytes that depends on address size).
2795   _emitIntPtrT(0);
2796 }
2797 
2798 // ============================================================================
2799 // [AsmJit::Assembler - Align]
2800 // ============================================================================
2801 
align(uint32_t m)2802 void X86Assembler::align(uint32_t m)
2803 {
2804   if (!canEmit())
2805     return;
2806 
2807   if (_logger)
2808     _logger->logFormat("%s.align %u\n", _logger->getInstructionPrefix(), (uint)m);
2809 
2810   if (!m) return;
2811 
2812   if (m > 64)
2813   {
2814     ASMJIT_ASSERT(0);
2815     return;
2816   }
2817 
2818   sysint_t i = m - (getOffset() % m);
2819   if (i == m) return;
2820 
2821   if (_properties & (1 << kX86PropertyOptimizedAlign))
2822   {
2823     const X86CpuInfo* ci = X86CpuInfo::getGlobal();
2824 
2825     // NOPs optimized for Intel:
2826     //   Intel 64 and IA-32 Architectures Software Developer's Manual
2827     //   - Volume 2B
2828     //   - Instruction Set Reference N-Z
2829     //     - NOP
2830 
2831     // NOPs optimized for AMD:
2832     //   Software Optimization Guide for AMD Family 10h Processors (Quad-Core)
2833     //   - 4.13 - Code Padding with Operand-Size Override and Multibyte NOP
2834 
2835     // Intel and AMD.
2836     static const uint8_t nop1[] = { 0x90 };
2837     static const uint8_t nop2[] = { 0x66, 0x90 };
2838     static const uint8_t nop3[] = { 0x0F, 0x1F, 0x00 };
2839     static const uint8_t nop4[] = { 0x0F, 0x1F, 0x40, 0x00 };
2840     static const uint8_t nop5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 };
2841     static const uint8_t nop6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 };
2842     static const uint8_t nop7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
2843     static const uint8_t nop8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
2844     static const uint8_t nop9[] = { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
2845 
2846     // AMD.
2847     static const uint8_t nop10[] = { 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
2848     static const uint8_t nop11[] = { 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
2849 
2850     const uint8_t* p;
2851     sysint_t n;
2852 
2853     if (ci->getVendorId() == kCpuIntel && ((ci->getFamily() & 0x0F) == 6 || (ci->getFamily() & 0x0F) == 15))
2854     {
2855       do {
2856         switch (i)
2857         {
2858           case  1: p = nop1; n = 1; break;
2859           case  2: p = nop2; n = 2; break;
2860           case  3: p = nop3; n = 3; break;
2861           case  4: p = nop4; n = 4; break;
2862           case  5: p = nop5; n = 5; break;
2863           case  6: p = nop6; n = 6; break;
2864           case  7: p = nop7; n = 7; break;
2865           case  8: p = nop8; n = 8; break;
2866           default: p = nop9; n = 9; break;
2867         }
2868 
2869         i -= n;
2870         do { _emitByte(*p++); } while(--n);
2871       } while (i);
2872 
2873       return;
2874     }
2875 
2876     if (ci->getVendorId() == kCpuAmd && ci->getFamily() >= 0x0F)
2877     {
2878       do {
2879         switch (i)
2880         {
2881           case  1: p = nop1 ; n =  1; break;
2882           case  2: p = nop2 ; n =  2; break;
2883           case  3: p = nop3 ; n =  3; break;
2884           case  4: p = nop4 ; n =  4; break;
2885           case  5: p = nop5 ; n =  5; break;
2886           case  6: p = nop6 ; n =  6; break;
2887           case  7: p = nop7 ; n =  7; break;
2888           case  8: p = nop8 ; n =  8; break;
2889           case  9: p = nop9 ; n =  9; break;
2890           case 10: p = nop10; n = 10; break;
2891           default: p = nop11; n = 11; break;
2892         }
2893 
2894         i -= n;
2895         do { _emitByte(*p++); } while(--n);
2896       } while (i);
2897 
2898       return;
2899     }
2900 #if defined(ASMJIT_X86)
2901     // Legacy NOPs, 0x90 with 0x66 prefix.
2902     do {
2903       switch (i)
2904       {
2905         default: _emitByte(0x66); i--;
2906         case  3: _emitByte(0x66); i--;
2907         case  2: _emitByte(0x66); i--;
2908         case  1: _emitByte(0x90); i--;
2909       }
2910     } while(i);
2911 #endif
2912   }
2913 
2914   // Legacy NOPs, only 0x90. In 64-bit mode, we can't use 0x66 prefix.
2915   do {
2916     _emitByte(0x90);
2917   } while(--i);
2918 }
2919 
2920 // ============================================================================
2921 // [AsmJit::Assembler - Label]
2922 // ============================================================================
2923 
newLabel()2924 Label X86Assembler::newLabel()
2925 {
2926   Label label;
2927   label._base.id = (uint32_t)_labels.getLength() | kOperandIdTypeLabel;
2928 
2929   LabelData l_data;
2930   l_data.offset = -1;
2931   l_data.links = NULL;
2932   _labels.append(l_data);
2933 
2934   return label;
2935 }
2936 
registerLabels(size_t count)2937 void X86Assembler::registerLabels(size_t count)
2938 {
2939   // Duplicated newLabel() code, but we are not creating Label instances.
2940   LabelData l_data;
2941   l_data.offset = -1;
2942   l_data.links = NULL;
2943 
2944   for (size_t i = 0; i < count; i++)
2945     _labels.append(l_data);
2946 }
2947 
bind(const Label & label)2948 void X86Assembler::bind(const Label& label)
2949 {
2950   // Only labels created by newLabel() can be used by Assembler.
2951   ASMJIT_ASSERT(label.getId() != kInvalidValue);
2952   // Never go out of bounds.
2953   ASMJIT_ASSERT((label.getId() & kOperandIdValueMask) < _labels.getLength());
2954 
2955   // Get label data based on label id.
2956   LabelData& l_data = _labels[label.getId() & kOperandIdValueMask];
2957 
2958   // Label can be bound only once.
2959   ASMJIT_ASSERT(l_data.offset == -1);
2960 
2961   // Log.
2962   if (_logger) _logger->logFormat("L.%u:\n", (uint32_t)label.getId() & kOperandIdValueMask);
2963 
2964   sysint_t pos = getOffset();
2965 
2966   LabelLink* link = l_data.links;
2967   LabelLink* prev = NULL;
2968 
2969   while (link)
2970   {
2971     sysint_t offset = link->offset;
2972 
2973     if (link->relocId != -1)
2974     {
2975       // If linked label points to RelocData then instead of writing relative
2976       // displacement to assembler stream, we will write it to RelocData.
2977       _relocData[link->relocId].destination += pos;
2978     }
2979     else
2980     {
2981       // Not using relocId, this means that we overwriting real displacement
2982       // in assembler stream.
2983       int32_t patchedValue = (int32_t)(pos - offset + link->displacement);
2984       uint32_t size = getByteAt(offset);
2985 
2986       // Only these size specifiers are allowed.
2987       ASMJIT_ASSERT(size == 1 || size == 4);
2988 
2989       if (size == 4)
2990       {
2991         setInt32At(offset, patchedValue);
2992       }
2993       else // if (size == 1)
2994       {
2995         if (IntUtil::isInt8(patchedValue))
2996         {
2997           setByteAt(offset, (uint8_t)(int8_t)patchedValue);
2998         }
2999         else
3000         {
3001           // Fatal error.
3002           setError(kErrorIllegalShortJump);
3003         }
3004       }
3005     }
3006 
3007     prev = link->prev;
3008     link = prev;
3009   }
3010 
3011   // Chain unused links.
3012   link = l_data.links;
3013   if (link)
3014   {
3015     if (prev == NULL) prev = link;
3016 
3017     prev->prev = _unusedLinks;
3018     _unusedLinks = link;
3019   }
3020 
3021   // Unlink label if it was linked.
3022   l_data.offset = pos;
3023   l_data.links = NULL;
3024 }
3025 
3026 // ============================================================================
3027 // [AsmJit::Assembler - Make]
3028 // ============================================================================
3029 
make()3030 void* X86Assembler::make()
3031 {
3032   // Do nothing on error state or when no instruction was emitted.
3033   if (_error || getCodeSize() == 0)
3034     return NULL;
3035 
3036   void* p;
3037   _error = _context->generate(&p, this);
3038   return p;
3039 }
3040 
3041 } // AsmJit namespace
3042 
3043 // [Api-End]
3044 #include "../core/apiend.h"
3045