Home | History | Annotate | Download | only in disassembler
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "disassembler_x86.h"
     18 
     19 #include <inttypes.h>
     20 
     21 #include <ostream>
     22 #include <sstream>
     23 
     24 #include "android-base/logging.h"
     25 #include "android-base/stringprintf.h"
     26 
     27 using android::base::StringPrintf;
     28 
     29 namespace art {
     30 namespace x86 {
     31 
     32 size_t DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin) {
     33   return DumpInstruction(os, begin);
     34 }
     35 
     36 void DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) {
     37   size_t length = 0;
     38   for (const uint8_t* cur = begin; cur < end; cur += length) {
     39     length = DumpInstruction(os, cur);
     40   }
     41 }
     42 
     43 static const char* gReg8Names[]  = {
     44   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
     45 };
     46 static const char* gExtReg8Names[] = {
     47   "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
     48   "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
     49 };
     50 static const char* gReg16Names[] = {
     51   "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
     52   "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
     53 };
     54 static const char* gReg32Names[] = {
     55   "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
     56   "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
     57 };
     58 static const char* gReg64Names[] = {
     59   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
     60   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
     61 };
     62 
     63 // 64-bit opcode REX modifier.
     64 constexpr uint8_t REX_W = 8U /* 0b1000 */;
     65 constexpr uint8_t REX_R = 4U /* 0b0100 */;
     66 constexpr uint8_t REX_X = 2U /* 0b0010 */;
     67 constexpr uint8_t REX_B = 1U /* 0b0001 */;
     68 
     69 static void DumpReg0(std::ostream& os, uint8_t rex, size_t reg,
     70                      bool byte_operand, uint8_t size_override) {
     71   DCHECK_LT(reg, (rex == 0) ? 8u : 16u);
     72   bool rex_w = (rex & REX_W) != 0;
     73   if (byte_operand) {
     74     os << ((rex == 0) ? gReg8Names[reg] : gExtReg8Names[reg]);
     75   } else if (rex_w) {
     76     os << gReg64Names[reg];
     77   } else if (size_override == 0x66) {
     78     os << gReg16Names[reg];
     79   } else {
     80     os << gReg32Names[reg];
     81   }
     82 }
     83 
     84 static void DumpAnyReg(std::ostream& os, uint8_t rex, size_t reg,
     85                        bool byte_operand, uint8_t size_override, RegFile reg_file) {
     86   if (reg_file == GPR) {
     87     DumpReg0(os, rex, reg, byte_operand, size_override);
     88   } else if (reg_file == SSE) {
     89     os << "xmm" << reg;
     90   } else {
     91     os << "mm" << reg;
     92   }
     93 }
     94 
     95 static void DumpReg(std::ostream& os, uint8_t rex, uint8_t reg,
     96                     bool byte_operand, uint8_t size_override, RegFile reg_file) {
     97   bool rex_r = (rex & REX_R) != 0;
     98   size_t reg_num = rex_r ? (reg + 8) : reg;
     99   DumpAnyReg(os, rex, reg_num, byte_operand, size_override, reg_file);
    100 }
    101 
    102 static void DumpRmReg(std::ostream& os, uint8_t rex, uint8_t reg,
    103                       bool byte_operand, uint8_t size_override, RegFile reg_file) {
    104   bool rex_b = (rex & REX_B) != 0;
    105   size_t reg_num = rex_b ? (reg + 8) : reg;
    106   DumpAnyReg(os, rex, reg_num, byte_operand, size_override, reg_file);
    107 }
    108 
    109 static void DumpAddrReg(std::ostream& os, uint8_t rex, uint8_t reg) {
    110   if (rex != 0) {
    111     os << gReg64Names[reg];
    112   } else {
    113     os << gReg32Names[reg];
    114   }
    115 }
    116 
    117 static void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg) {
    118   bool rex_b = (rex & REX_B) != 0;
    119   size_t reg_num = rex_b ? (reg + 8) : reg;
    120   DumpAddrReg(os, rex, reg_num);
    121 }
    122 
    123 static void DumpOpcodeReg(std::ostream& os, uint8_t rex, uint8_t reg,
    124                           bool byte_operand, uint8_t size_override) {
    125   bool rex_b = (rex & REX_B) != 0;
    126   size_t reg_num = rex_b ? (reg + 8) : reg;
    127   DumpReg0(os, rex, reg_num, byte_operand, size_override);
    128 }
    129 
    130 enum SegmentPrefix {
    131   kCs = 0x2e,
    132   kSs = 0x36,
    133   kDs = 0x3e,
    134   kEs = 0x26,
    135   kFs = 0x64,
    136   kGs = 0x65,
    137 };
    138 
    139 static void DumpSegmentOverride(std::ostream& os, uint8_t segment_prefix) {
    140   switch (segment_prefix) {
    141     case kCs: os << "cs:"; break;
    142     case kSs: os << "ss:"; break;
    143     case kDs: os << "ds:"; break;
    144     case kEs: os << "es:"; break;
    145     case kFs: os << "fs:"; break;
    146     case kGs: os << "gs:"; break;
    147     default: break;
    148   }
    149 }
    150 
    151 // Do not inline to avoid Clang stack frame problems. b/18733806
    152 NO_INLINE
    153 static std::string DumpCodeHex(const uint8_t* begin, const uint8_t* end) {
    154   std::stringstream hex;
    155   for (size_t i = 0; begin + i < end; ++i) {
    156     hex << StringPrintf("%02X", begin[i]);
    157   }
    158   return hex.str();
    159 }
    160 
    161 std::string DisassemblerX86::DumpAddress(uint8_t mod, uint8_t rm, uint8_t rex64, uint8_t rex_w,
    162                                          bool no_ops, bool byte_operand, bool byte_second_operand,
    163                                          uint8_t* prefix, bool load, RegFile src_reg_file,
    164                                          RegFile dst_reg_file, const uint8_t** instr,
    165                                          uint32_t* address_bits) {
    166   std::ostringstream address;
    167   if (mod == 0 && rm == 5) {
    168     if (!supports_rex_) {  // Absolute address.
    169       *address_bits = *reinterpret_cast<const uint32_t*>(*instr);
    170       address << StringPrintf("[0x%x]", *address_bits);
    171     } else {  // 64-bit RIP relative addressing.
    172       address << StringPrintf("[RIP + 0x%x]",  *reinterpret_cast<const uint32_t*>(*instr));
    173     }
    174     (*instr) += 4;
    175   } else if (rm == 4 && mod != 3) {  // SIB
    176     uint8_t sib = **instr;
    177     (*instr)++;
    178     uint8_t scale = (sib >> 6) & 3;
    179     uint8_t index = (sib >> 3) & 7;
    180     uint8_t base = sib & 7;
    181     address << "[";
    182 
    183     // REX.x is bit 3 of index.
    184     if ((rex64 & REX_X) != 0) {
    185       index += 8;
    186     }
    187 
    188     // Mod = 0 && base = 5 (ebp): no base (ignores REX.b).
    189     bool has_base = false;
    190     if (base != 5 || mod != 0) {
    191       has_base = true;
    192       DumpBaseReg(address, rex64, base);
    193     }
    194 
    195     // Index = 4 (esp/rsp) is disallowed.
    196     if (index != 4) {
    197       if (has_base) {
    198         address << " + ";
    199       }
    200       DumpAddrReg(address, rex64, index);
    201       if (scale != 0) {
    202         address << StringPrintf(" * %d", 1 << scale);
    203       }
    204     }
    205 
    206     if (mod == 0) {
    207       if (base == 5) {
    208         if (index != 4) {
    209           address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr));
    210         } else {
    211           // 64-bit low 32-bit absolute address, redundant absolute address encoding on 32-bit.
    212           *address_bits = *reinterpret_cast<const uint32_t*>(*instr);
    213           address << StringPrintf("%d", *address_bits);
    214         }
    215         (*instr) += 4;
    216       }
    217     } else if (mod == 1) {
    218       address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(*instr));
    219       (*instr)++;
    220     } else if (mod == 2) {
    221       address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr));
    222       (*instr) += 4;
    223     }
    224     address << "]";
    225   } else {
    226     if (mod == 3) {
    227       if (!no_ops) {
    228         DumpRmReg(address, rex_w, rm, byte_operand || byte_second_operand,
    229                   prefix[2], load ? src_reg_file : dst_reg_file);
    230       }
    231     } else {
    232       address << "[";
    233       DumpBaseReg(address, rex64, rm);
    234       if (mod == 1) {
    235         address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(*instr));
    236         (*instr)++;
    237       } else if (mod == 2) {
    238         address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr));
    239         (*instr) += 4;
    240       }
    241       address << "]";
    242     }
    243   }
    244   return address.str();
    245 }
    246 
    247 size_t DisassemblerX86::DumpNops(std::ostream& os, const uint8_t* instr) {
    248 static constexpr uint8_t kNops[][10] = {
    249       { },
    250       { 0x90 },
    251       { 0x66, 0x90 },
    252       { 0x0f, 0x1f, 0x00 },
    253       { 0x0f, 0x1f, 0x40, 0x00 },
    254       { 0x0f, 0x1f, 0x44, 0x00, 0x00 },
    255       { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 },
    256       { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 },
    257       { 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 },
    258       { 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 },
    259       { 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }
    260   };
    261 
    262   for (size_t i = 1; i < arraysize(kNops); ++i) {
    263     if (memcmp(instr, kNops[i], i) == 0) {
    264       os << FormatInstructionPointer(instr)
    265          << StringPrintf(": %22s    \t       nop \n", DumpCodeHex(instr, instr + i).c_str());
    266       return i;
    267     }
    268   }
    269 
    270   return 0;
    271 }
    272 
    273 size_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) {
    274   size_t nop_size = DumpNops(os, instr);
    275   if (nop_size != 0u) {
    276     return nop_size;
    277   }
    278 
    279   const uint8_t* begin_instr = instr;
    280   bool have_prefixes = true;
    281   uint8_t prefix[4] = {0, 0, 0, 0};
    282   do {
    283     switch (*instr) {
    284         // Group 1 - lock and repeat prefixes:
    285       case 0xF0:
    286       case 0xF2:
    287       case 0xF3:
    288         prefix[0] = *instr;
    289         break;
    290         // Group 2 - segment override prefixes:
    291       case kCs:
    292       case kSs:
    293       case kDs:
    294       case kEs:
    295       case kFs:
    296       case kGs:
    297         prefix[1] = *instr;
    298         break;
    299         // Group 3 - operand size override:
    300       case 0x66:
    301         prefix[2] = *instr;
    302         break;
    303         // Group 4 - address size override:
    304       case 0x67:
    305         prefix[3] = *instr;
    306         break;
    307       default:
    308         have_prefixes = false;
    309         break;
    310     }
    311     if (have_prefixes) {
    312       instr++;
    313     }
    314   } while (have_prefixes);
    315   uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0;
    316   if (rex != 0) {
    317     instr++;
    318   }
    319   const char** modrm_opcodes = nullptr;
    320   bool has_modrm = false;
    321   bool reg_is_opcode = false;
    322   size_t immediate_bytes = 0;
    323   size_t branch_bytes = 0;
    324   std::string opcode_tmp;    // Storage to keep StringPrintf result alive.
    325   const char* opcode0 = "";  // Prefix part.
    326   const char* opcode1 = "";  // Main opcode.
    327   const char* opcode2 = "";  // Sub-opcode. E.g., jump type.
    328   const char* opcode3 = "";  // Mod-rm part.
    329   const char* opcode4 = "";  // Suffix part.
    330   bool store = false;  // stores to memory (ie rm is on the left)
    331   bool load = false;  // loads from memory (ie rm is on the right)
    332   bool byte_operand = false;  // true when the opcode is dealing with byte operands
    333   // true when the source operand is a byte register but the target register isn't
    334   // (ie movsxb/movzxb).
    335   bool byte_second_operand = false;
    336   bool target_specific = false;  // register name depends on target (64 vs 32 bits).
    337   bool ax = false;  // implicit use of ax
    338   bool cx = false;  // implicit use of cx
    339   bool reg_in_opcode = false;  // low 3-bits of opcode encode register parameter
    340   bool no_ops = false;
    341   RegFile src_reg_file = GPR;
    342   RegFile dst_reg_file = GPR;
    343   switch (*instr) {
    344 #define DISASSEMBLER_ENTRY(opname, \
    345                      rm8_r8, rm32_r32, \
    346                      r8_rm8, r32_rm32, \
    347                      ax8_i8, ax32_i32) \
    348   case rm8_r8:   opcode1 = #opname; store = true; has_modrm = true; byte_operand = true; break; \
    349   case rm32_r32: opcode1 = #opname; store = true; has_modrm = true; break; \
    350   case r8_rm8:   opcode1 = #opname; load = true; has_modrm = true; byte_operand = true; break; \
    351   case r32_rm32: opcode1 = #opname; load = true; has_modrm = true; break; \
    352   case ax8_i8:   opcode1 = #opname; ax = true; immediate_bytes = 1; byte_operand = true; break; \
    353   case ax32_i32: opcode1 = #opname; ax = true; immediate_bytes = 4; break;
    354 
    355 DISASSEMBLER_ENTRY(add,
    356   0x00 /* RegMem8/Reg8 */,     0x01 /* RegMem32/Reg32 */,
    357   0x02 /* Reg8/RegMem8 */,     0x03 /* Reg32/RegMem32 */,
    358   0x04 /* Rax8/imm8 opcode */, 0x05 /* Rax32/imm32 */)
    359 DISASSEMBLER_ENTRY(or,
    360   0x08 /* RegMem8/Reg8 */,     0x09 /* RegMem32/Reg32 */,
    361   0x0A /* Reg8/RegMem8 */,     0x0B /* Reg32/RegMem32 */,
    362   0x0C /* Rax8/imm8 opcode */, 0x0D /* Rax32/imm32 */)
    363 DISASSEMBLER_ENTRY(adc,
    364   0x10 /* RegMem8/Reg8 */,     0x11 /* RegMem32/Reg32 */,
    365   0x12 /* Reg8/RegMem8 */,     0x13 /* Reg32/RegMem32 */,
    366   0x14 /* Rax8/imm8 opcode */, 0x15 /* Rax32/imm32 */)
    367 DISASSEMBLER_ENTRY(sbb,
    368   0x18 /* RegMem8/Reg8 */,     0x19 /* RegMem32/Reg32 */,
    369   0x1A /* Reg8/RegMem8 */,     0x1B /* Reg32/RegMem32 */,
    370   0x1C /* Rax8/imm8 opcode */, 0x1D /* Rax32/imm32 */)
    371 DISASSEMBLER_ENTRY(and,
    372   0x20 /* RegMem8/Reg8 */,     0x21 /* RegMem32/Reg32 */,
    373   0x22 /* Reg8/RegMem8 */,     0x23 /* Reg32/RegMem32 */,
    374   0x24 /* Rax8/imm8 opcode */, 0x25 /* Rax32/imm32 */)
    375 DISASSEMBLER_ENTRY(sub,
    376   0x28 /* RegMem8/Reg8 */,     0x29 /* RegMem32/Reg32 */,
    377   0x2A /* Reg8/RegMem8 */,     0x2B /* Reg32/RegMem32 */,
    378   0x2C /* Rax8/imm8 opcode */, 0x2D /* Rax32/imm32 */)
    379 DISASSEMBLER_ENTRY(xor,
    380   0x30 /* RegMem8/Reg8 */,     0x31 /* RegMem32/Reg32 */,
    381   0x32 /* Reg8/RegMem8 */,     0x33 /* Reg32/RegMem32 */,
    382   0x34 /* Rax8/imm8 opcode */, 0x35 /* Rax32/imm32 */)
    383 DISASSEMBLER_ENTRY(cmp,
    384   0x38 /* RegMem8/Reg8 */,     0x39 /* RegMem32/Reg32 */,
    385   0x3A /* Reg8/RegMem8 */,     0x3B /* Reg32/RegMem32 */,
    386   0x3C /* Rax8/imm8 opcode */, 0x3D /* Rax32/imm32 */)
    387 
    388 #undef DISASSEMBLER_ENTRY
    389   case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
    390     opcode1 = "push";
    391     reg_in_opcode = true;
    392     target_specific = true;
    393     break;
    394   case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F:
    395     opcode1 = "pop";
    396     reg_in_opcode = true;
    397     target_specific = true;
    398     break;
    399   case 0x63:
    400     if ((rex & REX_W) != 0) {
    401       opcode1 = "movsxd";
    402       has_modrm = true;
    403       load = true;
    404     } else {
    405       // In 32-bit mode (!supports_rex_) this is ARPL, with no REX prefix the functionality is the
    406       // same as 'mov' but the use of the instruction is discouraged.
    407       opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr);
    408       opcode1 = opcode_tmp.c_str();
    409     }
    410     break;
    411   case 0x68: opcode1 = "push"; immediate_bytes = 4; break;
    412   case 0x69: opcode1 = "imul"; load = true; has_modrm = true; immediate_bytes = 4; break;
    413   case 0x6A: opcode1 = "push"; immediate_bytes = 1; break;
    414   case 0x6B: opcode1 = "imul"; load = true; has_modrm = true; immediate_bytes = 1; break;
    415   case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
    416   case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
    417     static const char* condition_codes[] =
    418     {"o", "no", "b/nae/c", "nb/ae/nc", "z/eq",  "nz/ne", "be/na", "nbe/a",
    419      "s", "ns", "p/pe",    "np/po",    "l/nge", "nl/ge", "le/ng", "nle/g"
    420     };
    421     opcode1 = "j";
    422     opcode2 = condition_codes[*instr & 0xF];
    423     branch_bytes = 1;
    424     break;
    425   case 0x86: case 0x87:
    426     opcode1 = "xchg";
    427     store = true;
    428     has_modrm = true;
    429     byte_operand = (*instr == 0x86);
    430     break;
    431   case 0x88: opcode1 = "mov"; store = true; has_modrm = true; byte_operand = true; break;
    432   case 0x89: opcode1 = "mov"; store = true; has_modrm = true; break;
    433   case 0x8A: opcode1 = "mov"; load = true; has_modrm = true; byte_operand = true; break;
    434   case 0x8B: opcode1 = "mov"; load = true; has_modrm = true; break;
    435   case 0x9D: opcode1 = "popf"; break;
    436 
    437   case 0x0F:  // 2 byte extended opcode
    438     instr++;
    439     switch (*instr) {
    440       case 0x10: case 0x11:
    441         if (prefix[0] == 0xF2) {
    442           opcode1 = "movsd";
    443           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    444         } else if (prefix[0] == 0xF3) {
    445           opcode1 = "movss";
    446           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    447         } else if (prefix[2] == 0x66) {
    448           opcode1 = "movupd";
    449           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    450         } else {
    451           opcode1 = "movups";
    452         }
    453         has_modrm = true;
    454         src_reg_file = dst_reg_file = SSE;
    455         load = *instr == 0x10;
    456         store = !load;
    457         break;
    458       case 0x12: case 0x13:
    459         if (prefix[2] == 0x66) {
    460           opcode1 = "movlpd";
    461           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    462         } else if (prefix[0] == 0) {
    463           opcode1 = "movlps";
    464         }
    465         has_modrm = true;
    466         src_reg_file = dst_reg_file = SSE;
    467         load = *instr == 0x12;
    468         store = !load;
    469         break;
    470       case 0x16: case 0x17:
    471         if (prefix[2] == 0x66) {
    472           opcode1 = "movhpd";
    473           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    474         } else if (prefix[0] == 0) {
    475           opcode1 = "movhps";
    476         }
    477         has_modrm = true;
    478         src_reg_file = dst_reg_file = SSE;
    479         load = *instr == 0x16;
    480         store = !load;
    481         break;
    482       case 0x28: case 0x29:
    483         if (prefix[2] == 0x66) {
    484           opcode1 = "movapd";
    485           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    486         } else if (prefix[0] == 0) {
    487           opcode1 = "movaps";
    488         }
    489         has_modrm = true;
    490         src_reg_file = dst_reg_file = SSE;
    491         load = *instr == 0x28;
    492         store = !load;
    493         break;
    494       case 0x2A:
    495         if (prefix[2] == 0x66) {
    496           opcode1 = "cvtpi2pd";
    497           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    498         } else if (prefix[0] == 0xF2) {
    499           opcode1 = "cvtsi2sd";
    500           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    501         } else if (prefix[0] == 0xF3) {
    502           opcode1 = "cvtsi2ss";
    503           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    504         } else {
    505           opcode1 = "cvtpi2ps";
    506         }
    507         load = true;
    508         has_modrm = true;
    509         dst_reg_file = SSE;
    510         break;
    511       case 0x2C:
    512         if (prefix[2] == 0x66) {
    513           opcode1 = "cvttpd2pi";
    514           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    515         } else if (prefix[0] == 0xF2) {
    516           opcode1 = "cvttsd2si";
    517           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    518         } else if (prefix[0] == 0xF3) {
    519           opcode1 = "cvttss2si";
    520           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    521         } else {
    522           opcode1 = "cvttps2pi";
    523         }
    524         load = true;
    525         has_modrm = true;
    526         src_reg_file = SSE;
    527         break;
    528       case 0x2D:
    529         if (prefix[2] == 0x66) {
    530           opcode1 = "cvtpd2pi";
    531           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    532         } else if (prefix[0] == 0xF2) {
    533           opcode1 = "cvtsd2si";
    534           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    535         } else if (prefix[0] == 0xF3) {
    536           opcode1 = "cvtss2si";
    537           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    538         } else {
    539           opcode1 = "cvtps2pi";
    540         }
    541         load = true;
    542         has_modrm = true;
    543         src_reg_file = SSE;
    544         break;
    545       case 0x2E:
    546         opcode0 = "u";
    547         FALLTHROUGH_INTENDED;
    548       case 0x2F:
    549         if (prefix[2] == 0x66) {
    550           opcode1 = "comisd";
    551           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    552         } else {
    553           opcode1 = "comiss";
    554         }
    555         has_modrm = true;
    556         load = true;
    557         src_reg_file = dst_reg_file = SSE;
    558         break;
    559       case 0x38:  // 3 byte extended opcode
    560         instr++;
    561         if (prefix[2] == 0x66) {
    562           switch (*instr) {
    563             case 0x01:
    564               opcode1 = "phaddw";
    565               prefix[2] = 0;
    566               has_modrm = true;
    567               load = true;
    568               src_reg_file = dst_reg_file = SSE;
    569               break;
    570             case 0x02:
    571               opcode1 = "phaddd";
    572               prefix[2] = 0;
    573               has_modrm = true;
    574               load = true;
    575               src_reg_file = dst_reg_file = SSE;
    576               break;
    577             case 0x29:
    578               opcode1 = "pcmpeqq";
    579               prefix[2] = 0;
    580               has_modrm = true;
    581               load = true;
    582               src_reg_file = dst_reg_file = SSE;
    583               break;
    584             case 0x37:
    585               opcode1 = "pcmpgtq";
    586               prefix[2] = 0;
    587               has_modrm = true;
    588               load = true;
    589               src_reg_file = dst_reg_file = SSE;
    590               break;
    591             case 0x38:
    592               opcode1 = "pminsb";
    593               prefix[2] = 0;
    594               has_modrm = true;
    595               load = true;
    596               src_reg_file = dst_reg_file = SSE;
    597               break;
    598             case 0x39:
    599               opcode1 = "pminsd";
    600               prefix[2] = 0;
    601               has_modrm = true;
    602               load = true;
    603               src_reg_file = dst_reg_file = SSE;
    604               break;
    605             case 0x3A:
    606               opcode1 = "pminuw";
    607               prefix[2] = 0;
    608               has_modrm = true;
    609               load = true;
    610               src_reg_file = dst_reg_file = SSE;
    611               break;
    612             case 0x3B:
    613               opcode1 = "pminud";
    614               prefix[2] = 0;
    615               has_modrm = true;
    616               load = true;
    617               src_reg_file = dst_reg_file = SSE;
    618               break;
    619             case 0x3C:
    620               opcode1 = "pmaxsb";
    621               prefix[2] = 0;
    622               has_modrm = true;
    623               load = true;
    624               src_reg_file = dst_reg_file = SSE;
    625               break;
    626             case 0x3D:
    627               opcode1 = "pmaxsd";
    628               prefix[2] = 0;
    629               has_modrm = true;
    630               load = true;
    631               src_reg_file = dst_reg_file = SSE;
    632               break;
    633             case 0x3E:
    634               opcode1 = "pmaxuw";
    635               prefix[2] = 0;
    636               has_modrm = true;
    637               load = true;
    638               src_reg_file = dst_reg_file = SSE;
    639               break;
    640             case 0x3F:
    641               opcode1 = "pmaxud";
    642               prefix[2] = 0;
    643               has_modrm = true;
    644               load = true;
    645               src_reg_file = dst_reg_file = SSE;
    646               break;
    647             case 0x40:
    648               opcode1 = "pmulld";
    649               prefix[2] = 0;
    650               has_modrm = true;
    651               load = true;
    652               src_reg_file = dst_reg_file = SSE;
    653               break;
    654             default:
    655               opcode_tmp = StringPrintf("unknown opcode '0F 38 %02X'", *instr);
    656               opcode1 = opcode_tmp.c_str();
    657           }
    658         } else {
    659           opcode_tmp = StringPrintf("unknown opcode '0F 38 %02X'", *instr);
    660           opcode1 = opcode_tmp.c_str();
    661         }
    662         break;
    663       case 0x3A:  // 3 byte extended opcode
    664         instr++;
    665         if (prefix[2] == 0x66) {
    666           switch (*instr) {
    667             case 0x0A:
    668               opcode1 = "roundss";
    669               prefix[2] = 0;
    670               has_modrm = true;
    671               load = true;
    672               src_reg_file = SSE;
    673               dst_reg_file = SSE;
    674               immediate_bytes = 1;
    675               break;
    676             case 0x0B:
    677               opcode1 = "roundsd";
    678               prefix[2] = 0;
    679               has_modrm = true;
    680               load = true;
    681               src_reg_file = SSE;
    682               dst_reg_file = SSE;
    683               immediate_bytes = 1;
    684               break;
    685             case 0x14:
    686               opcode1 = "pextrb";
    687               prefix[2] = 0;
    688               has_modrm = true;
    689               store = true;
    690               src_reg_file = SSE;
    691               immediate_bytes = 1;
    692               break;
    693           case 0x15:
    694               opcode1 = "pextrw";
    695               prefix[2] = 0;
    696               has_modrm = true;
    697               store = true;
    698               src_reg_file = SSE;
    699               immediate_bytes = 1;
    700               break;
    701             case 0x16:
    702               opcode1 = "pextrd";
    703               prefix[2] = 0;
    704               has_modrm = true;
    705               store = true;
    706               src_reg_file = SSE;
    707               immediate_bytes = 1;
    708               break;
    709             default:
    710               opcode_tmp = StringPrintf("unknown opcode '0F 3A %02X'", *instr);
    711               opcode1 = opcode_tmp.c_str();
    712           }
    713         } else {
    714           opcode_tmp = StringPrintf("unknown opcode '0F 3A %02X'", *instr);
    715           opcode1 = opcode_tmp.c_str();
    716         }
    717         break;
    718       case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
    719       case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F:
    720         opcode1 = "cmov";
    721         opcode2 = condition_codes[*instr & 0xF];
    722         has_modrm = true;
    723         load = true;
    724         break;
    725       case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
    726       case 0x58: case 0x59: case 0x5C: case 0x5D: case 0x5E: case 0x5F: {
    727         switch (*instr) {
    728           case 0x50: opcode1 = "movmsk"; break;
    729           case 0x51: opcode1 = "sqrt"; break;
    730           case 0x52: opcode1 = "rsqrt"; break;
    731           case 0x53: opcode1 = "rcp"; break;
    732           case 0x54: opcode1 = "and"; break;
    733           case 0x55: opcode1 = "andn"; break;
    734           case 0x56: opcode1 = "or"; break;
    735           case 0x57: opcode1 = "xor"; break;
    736           case 0x58: opcode1 = "add"; break;
    737           case 0x59: opcode1 = "mul"; break;
    738           case 0x5C: opcode1 = "sub"; break;
    739           case 0x5D: opcode1 = "min"; break;
    740           case 0x5E: opcode1 = "div"; break;
    741           case 0x5F: opcode1 = "max"; break;
    742           default: LOG(FATAL) << "Unreachable"; UNREACHABLE();
    743         }
    744         if (prefix[2] == 0x66) {
    745           opcode2 = "pd";
    746           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    747         } else if (prefix[0] == 0xF2) {
    748           opcode2 = "sd";
    749           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    750         } else if (prefix[0] == 0xF3) {
    751           opcode2 = "ss";
    752           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    753         } else {
    754           opcode2 = "ps";
    755         }
    756         load = true;
    757         has_modrm = true;
    758         src_reg_file = dst_reg_file = SSE;
    759         break;
    760       }
    761       case 0x5A:
    762         if (prefix[2] == 0x66) {
    763           opcode1 = "cvtpd2ps";
    764           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    765         } else if (prefix[0] == 0xF2) {
    766           opcode1 = "cvtsd2ss";
    767           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    768         } else if (prefix[0] == 0xF3) {
    769           opcode1 = "cvtss2sd";
    770           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    771         } else {
    772           opcode1 = "cvtps2pd";
    773         }
    774         load = true;
    775         has_modrm = true;
    776         src_reg_file = dst_reg_file = SSE;
    777         break;
    778       case 0x5B:
    779         if (prefix[2] == 0x66) {
    780           opcode1 = "cvtps2dq";
    781           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    782         } else if (prefix[0] == 0xF2) {
    783           opcode1 = "bad opcode F2 0F 5B";
    784         } else if (prefix[0] == 0xF3) {
    785           opcode1 = "cvttps2dq";
    786           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    787         } else {
    788           opcode1 = "cvtdq2ps";
    789         }
    790         load = true;
    791         has_modrm = true;
    792         src_reg_file = dst_reg_file = SSE;
    793         break;
    794       case 0x60: case 0x61: case 0x62: case 0x6C:
    795         if (prefix[2] == 0x66) {
    796           src_reg_file = dst_reg_file = SSE;
    797           prefix[2] = 0;  // Clear prefix now. It has served its purpose as part of the opcode.
    798         } else {
    799           src_reg_file = dst_reg_file = MMX;
    800         }
    801         switch (*instr) {
    802           case 0x60: opcode1 = "punpcklbw"; break;
    803           case 0x61: opcode1 = "punpcklwd"; break;
    804           case 0x62: opcode1 = "punpckldq"; break;
    805           case 0x6c: opcode1 = "punpcklqdq"; break;
    806         }
    807         load = true;
    808         has_modrm = true;
    809         break;
    810       case 0x64:
    811       case 0x65:
    812       case 0x66:
    813         if (prefix[2] == 0x66) {
    814           src_reg_file = dst_reg_file = SSE;
    815           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    816         } else {
    817           src_reg_file = dst_reg_file = MMX;
    818         }
    819         switch (*instr) {
    820           case 0x64: opcode1 = "pcmpgtb"; break;
    821           case 0x65: opcode1 = "pcmpgtw"; break;
    822           case 0x66: opcode1 = "pcmpgtd"; break;
    823         }
    824         prefix[2] = 0;
    825         has_modrm = true;
    826         load = true;
    827         break;
    828       case 0x6E:
    829         if (prefix[2] == 0x66) {
    830           dst_reg_file = SSE;
    831           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    832         } else {
    833           dst_reg_file = MMX;
    834         }
    835         opcode1 = "movd";
    836         load = true;
    837         has_modrm = true;
    838         break;
    839       case 0x6F:
    840         if (prefix[2] == 0x66) {
    841           src_reg_file = dst_reg_file = SSE;
    842           opcode1 = "movdqa";
    843           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    844         } else if (prefix[0] == 0xF3) {
    845           src_reg_file = dst_reg_file = SSE;
    846           opcode1 = "movdqu";
    847           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    848         } else {
    849           dst_reg_file = MMX;
    850           opcode1 = "movq";
    851         }
    852         load = true;
    853         has_modrm = true;
    854         break;
    855       case 0x70:
    856         if (prefix[2] == 0x66) {
    857           opcode1 = "pshufd";
    858           prefix[2] = 0;
    859           has_modrm = true;
    860           store = true;
    861           src_reg_file = dst_reg_file = SSE;
    862           immediate_bytes = 1;
    863         } else if (prefix[0] == 0xF2) {
    864           opcode1 = "pshuflw";
    865           prefix[0] = 0;
    866           has_modrm = true;
    867           store = true;
    868           src_reg_file = dst_reg_file = SSE;
    869           immediate_bytes = 1;
    870         } else {
    871           opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr);
    872           opcode1 = opcode_tmp.c_str();
    873         }
    874         break;
    875       case 0x71:
    876         if (prefix[2] == 0x66) {
    877           dst_reg_file = SSE;
    878           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    879         } else {
    880           dst_reg_file = MMX;
    881         }
    882         static const char* x71_opcodes[] = {
    883             "unknown-71", "unknown-71", "psrlw", "unknown-71",
    884             "psraw",      "unknown-71", "psllw", "unknown-71"};
    885         modrm_opcodes = x71_opcodes;
    886         reg_is_opcode = true;
    887         has_modrm = true;
    888         store = true;
    889         immediate_bytes = 1;
    890         break;
    891       case 0x72:
    892         if (prefix[2] == 0x66) {
    893           dst_reg_file = SSE;
    894           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    895         } else {
    896           dst_reg_file = MMX;
    897         }
    898         static const char* x72_opcodes[] = {
    899             "unknown-72", "unknown-72", "psrld", "unknown-72",
    900             "psrad",      "unknown-72", "pslld", "unknown-72"};
    901         modrm_opcodes = x72_opcodes;
    902         reg_is_opcode = true;
    903         has_modrm = true;
    904         store = true;
    905         immediate_bytes = 1;
    906         break;
    907       case 0x73:
    908         if (prefix[2] == 0x66) {
    909           dst_reg_file = SSE;
    910           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    911         } else {
    912           dst_reg_file = MMX;
    913         }
    914         static const char* x73_opcodes[] = {
    915             "unknown-73", "unknown-73", "psrlq", "psrldq",
    916             "unknown-73", "unknown-73", "psllq", "unknown-73"};
    917         modrm_opcodes = x73_opcodes;
    918         reg_is_opcode = true;
    919         has_modrm = true;
    920         store = true;
    921         immediate_bytes = 1;
    922         break;
    923       case 0x74:
    924       case 0x75:
    925       case 0x76:
    926         if (prefix[2] == 0x66) {
    927           src_reg_file = dst_reg_file = SSE;
    928           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    929         } else {
    930           src_reg_file = dst_reg_file = MMX;
    931         }
    932         switch (*instr) {
    933           case 0x74: opcode1 = "pcmpeqb"; break;
    934           case 0x75: opcode1 = "pcmpeqw"; break;
    935           case 0x76: opcode1 = "pcmpeqd"; break;
    936         }
    937         prefix[2] = 0;
    938         has_modrm = true;
    939         load = true;
    940         break;
    941       case 0x7C:
    942         if (prefix[0] == 0xF2) {
    943           opcode1 = "haddps";
    944           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    945         } else if (prefix[2] == 0x66) {
    946           opcode1 = "haddpd";
    947           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    948         } else {
    949           opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr);
    950           opcode1 = opcode_tmp.c_str();
    951           break;
    952         }
    953         src_reg_file = dst_reg_file = SSE;
    954         has_modrm = true;
    955         load = true;
    956         break;
    957       case 0x7E:
    958         if (prefix[2] == 0x66) {
    959           src_reg_file = SSE;
    960           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    961         } else {
    962           src_reg_file = MMX;
    963         }
    964         opcode1 = "movd";
    965         has_modrm = true;
    966         store = true;
    967         break;
    968       case 0x7F:
    969         if (prefix[2] == 0x66) {
    970           src_reg_file = dst_reg_file = SSE;
    971           opcode1 = "movdqa";
    972           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
    973         } else if (prefix[0] == 0xF3) {
    974           src_reg_file = dst_reg_file = SSE;
    975           opcode1 = "movdqu";
    976           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
    977         } else {
    978           dst_reg_file = MMX;
    979           opcode1 = "movq";
    980         }
    981         store = true;
    982         has_modrm = true;
    983         break;
    984       case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
    985       case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F:
    986         opcode1 = "j";
    987         opcode2 = condition_codes[*instr & 0xF];
    988         branch_bytes = 4;
    989         break;
    990       case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
    991       case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F:
    992         opcode1 = "set";
    993         opcode2 = condition_codes[*instr & 0xF];
    994         modrm_opcodes = nullptr;
    995         reg_is_opcode = true;
    996         has_modrm = true;
    997         store = true;
    998         break;
    999       case 0xA4:
   1000         opcode1 = "shld";
   1001         has_modrm = true;
   1002         load = true;
   1003         immediate_bytes = 1;
   1004         break;
   1005       case 0xA5:
   1006         opcode1 = "shld";
   1007         has_modrm = true;
   1008         load = true;
   1009         cx = true;
   1010         break;
   1011       case 0xAC:
   1012         opcode1 = "shrd";
   1013         has_modrm = true;
   1014         load = true;
   1015         immediate_bytes = 1;
   1016         break;
   1017       case 0xAD:
   1018         opcode1 = "shrd";
   1019         has_modrm = true;
   1020         load = true;
   1021         cx = true;
   1022         break;
   1023       case 0xAE:
   1024         if (prefix[0] == 0xF3) {
   1025           prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
   1026           static const char* xAE_opcodes[] = {
   1027               "rdfsbase",   "rdgsbase",   "wrfsbase",   "wrgsbase",
   1028               "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"};
   1029           modrm_opcodes = xAE_opcodes;
   1030           reg_is_opcode = true;
   1031           has_modrm = true;
   1032           uint8_t reg_or_opcode = (instr[1] >> 3) & 7;
   1033           switch (reg_or_opcode) {
   1034             case 0:
   1035               prefix[1] = kFs;
   1036               load = true;
   1037               break;
   1038             case 1:
   1039               prefix[1] = kGs;
   1040               load = true;
   1041               break;
   1042             case 2:
   1043               prefix[1] = kFs;
   1044               store = true;
   1045               break;
   1046             case 3:
   1047               prefix[1] = kGs;
   1048               store = true;
   1049               break;
   1050             default:
   1051               load = true;
   1052               break;
   1053           }
   1054         } else {
   1055           static const char* xAE_opcodes[] = {
   1056               "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE",
   1057               "unknown-AE", "lfence",     "mfence",     "sfence"};
   1058           modrm_opcodes = xAE_opcodes;
   1059           reg_is_opcode = true;
   1060           has_modrm = true;
   1061           load = true;
   1062           no_ops = true;
   1063         }
   1064         break;
   1065       case 0xAF:
   1066         opcode1 = "imul";
   1067         has_modrm = true;
   1068         load = true;
   1069         break;
   1070       case 0xB1:
   1071         opcode1 = "cmpxchg";
   1072         has_modrm = true;
   1073         store = true;
   1074         break;
   1075       case 0xB6:
   1076         opcode1 = "movzxb";
   1077         has_modrm = true;
   1078         load = true;
   1079         byte_second_operand = true;
   1080         break;
   1081       case 0xB7:
   1082         opcode1 = "movzxw";
   1083         has_modrm = true;
   1084         load = true;
   1085         break;
   1086       case 0xBC:
   1087         opcode1 = "bsf";
   1088         has_modrm = true;
   1089         load = true;
   1090         break;
   1091       case 0xBD:
   1092         opcode1 = "bsr";
   1093         has_modrm = true;
   1094         load = true;
   1095         break;
   1096       case 0xB8:
   1097         opcode1 = "popcnt";
   1098         has_modrm = true;
   1099         load = true;
   1100         break;
   1101       case 0xBE:
   1102         opcode1 = "movsxb";
   1103         has_modrm = true;
   1104         load = true;
   1105         byte_second_operand = true;
   1106         rex |= (rex == 0 ? 0 : REX_W);
   1107         break;
   1108       case 0xBF:
   1109         opcode1 = "movsxw";
   1110         has_modrm = true;
   1111         load = true;
   1112         break;
   1113       case 0xC3:
   1114         opcode1 = "movnti";
   1115         store = true;
   1116         has_modrm = true;
   1117         break;
   1118       case 0xC5:
   1119         if (prefix[2] == 0x66) {
   1120           opcode1 = "pextrw";
   1121           prefix[2] = 0;
   1122           has_modrm = true;
   1123           load = true;
   1124           src_reg_file = SSE;
   1125           immediate_bytes = 1;
   1126         } else {
   1127           opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr);
   1128           opcode1 = opcode_tmp.c_str();
   1129         }
   1130         break;
   1131       case 0xC6:
   1132         if (prefix[2] == 0x66) {
   1133           opcode1 = "shufpd";
   1134           prefix[2] = 0;
   1135         } else {
   1136           opcode1 = "shufps";
   1137         }
   1138         has_modrm = true;
   1139         store = true;
   1140         src_reg_file = dst_reg_file = SSE;
   1141         immediate_bytes = 1;
   1142         break;
   1143       case 0xC7:
   1144         static const char* x0FxC7_opcodes[] = {
   1145             "unknown-0f-c7", "cmpxchg8b",     "unknown-0f-c7", "unknown-0f-c7",
   1146             "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7"};
   1147         modrm_opcodes = x0FxC7_opcodes;
   1148         has_modrm = true;
   1149         reg_is_opcode = true;
   1150         store = true;
   1151         break;
   1152       case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
   1153         opcode1 = "bswap";
   1154         reg_in_opcode = true;
   1155         break;
   1156       case 0xD4:
   1157         if (prefix[2] == 0x66) {
   1158           src_reg_file = dst_reg_file = SSE;
   1159           prefix[2] = 0;
   1160         } else {
   1161           src_reg_file = dst_reg_file = MMX;
   1162         }
   1163         opcode1 = "paddq";
   1164         prefix[2] = 0;
   1165         has_modrm = true;
   1166         load = true;
   1167         break;
   1168       case 0xDB:
   1169         if (prefix[2] == 0x66) {
   1170           src_reg_file = dst_reg_file = SSE;
   1171           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
   1172         } else {
   1173           src_reg_file = dst_reg_file = MMX;
   1174         }
   1175         opcode1 = "pand";
   1176         prefix[2] = 0;
   1177         has_modrm = true;
   1178         load = true;
   1179         break;
   1180       case 0xD5:
   1181         if (prefix[2] == 0x66) {
   1182           opcode1 = "pmullw";
   1183           prefix[2] = 0;
   1184           has_modrm = true;
   1185           load = true;
   1186           src_reg_file = dst_reg_file = SSE;
   1187         } else {
   1188           opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr);
   1189           opcode1 = opcode_tmp.c_str();
   1190         }
   1191         break;
   1192       case 0xDA:
   1193       case 0xDE:
   1194       case 0xE0:
   1195       case 0xE3:
   1196       case 0xEA:
   1197       case 0xEE:
   1198         if (prefix[2] == 0x66) {
   1199           src_reg_file = dst_reg_file = SSE;
   1200           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
   1201         } else {
   1202           src_reg_file = dst_reg_file = MMX;
   1203         }
   1204         switch (*instr) {
   1205           case 0xDA: opcode1 = "pminub"; break;
   1206           case 0xDE: opcode1 = "pmaxub"; break;
   1207           case 0xE0: opcode1 = "pavgb"; break;
   1208           case 0xE3: opcode1 = "pavgw"; break;
   1209           case 0xEA: opcode1 = "pminsw"; break;
   1210           case 0xEE: opcode1 = "pmaxsw"; break;
   1211         }
   1212         prefix[2] = 0;
   1213         has_modrm = true;
   1214         load = true;
   1215         break;
   1216       case 0xEB:
   1217         if (prefix[2] == 0x66) {
   1218           src_reg_file = dst_reg_file = SSE;
   1219           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
   1220         } else {
   1221           src_reg_file = dst_reg_file = MMX;
   1222         }
   1223         opcode1 = "por";
   1224         prefix[2] = 0;
   1225         has_modrm = true;
   1226         load = true;
   1227         break;
   1228       case 0xEF:
   1229         if (prefix[2] == 0x66) {
   1230           src_reg_file = dst_reg_file = SSE;
   1231           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
   1232         } else {
   1233           src_reg_file = dst_reg_file = MMX;
   1234         }
   1235         opcode1 = "pxor";
   1236         prefix[2] = 0;
   1237         has_modrm = true;
   1238         load = true;
   1239         break;
   1240       case 0xF4:
   1241       case 0xF6:
   1242       case 0xF8:
   1243       case 0xF9:
   1244       case 0xFA:
   1245       case 0xFB:
   1246       case 0xFC:
   1247       case 0xFD:
   1248       case 0xFE:
   1249         if (prefix[2] == 0x66) {
   1250           src_reg_file = dst_reg_file = SSE;
   1251           prefix[2] = 0;  // clear prefix now it's served its purpose as part of the opcode
   1252         } else {
   1253           src_reg_file = dst_reg_file = MMX;
   1254         }
   1255         switch (*instr) {
   1256           case 0xF4: opcode1 = "pmuludq"; break;
   1257           case 0xF6: opcode1 = "psadbw"; break;
   1258           case 0xF8: opcode1 = "psubb"; break;
   1259           case 0xF9: opcode1 = "psubw"; break;
   1260           case 0xFA: opcode1 = "psubd"; break;
   1261           case 0xFB: opcode1 = "psubq"; break;
   1262           case 0xFC: opcode1 = "paddb"; break;
   1263           case 0xFD: opcode1 = "paddw"; break;
   1264           case 0xFE: opcode1 = "paddd"; break;
   1265         }
   1266         prefix[2] = 0;
   1267         has_modrm = true;
   1268         load = true;
   1269         break;
   1270       default:
   1271         opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr);
   1272         opcode1 = opcode_tmp.c_str();
   1273         break;
   1274     }
   1275     break;
   1276   case 0x80: case 0x81: case 0x82: case 0x83:
   1277     static const char* x80_opcodes[] = {"add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"};
   1278     modrm_opcodes = x80_opcodes;
   1279     has_modrm = true;
   1280     reg_is_opcode = true;
   1281     store = true;
   1282     byte_operand = (*instr & 1) == 0;
   1283     immediate_bytes = *instr == 0x81 ? 4 : 1;
   1284     break;
   1285   case 0x84: case 0x85:
   1286     opcode1 = "test";
   1287     has_modrm = true;
   1288     load = true;
   1289     byte_operand = (*instr & 1) == 0;
   1290     break;
   1291   case 0x8D:
   1292     opcode1 = "lea";
   1293     has_modrm = true;
   1294     load = true;
   1295     break;
   1296   case 0x8F:
   1297     opcode1 = "pop";
   1298     has_modrm = true;
   1299     reg_is_opcode = true;
   1300     store = true;
   1301     break;
   1302   case 0x99:
   1303     opcode1 = "cdq";
   1304     break;
   1305   case 0x9B:
   1306     if (instr[1] == 0xDF && instr[2] == 0xE0) {
   1307       opcode1 = "fstsw\tax";
   1308       instr += 2;
   1309     } else {
   1310       opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr);
   1311       opcode1 = opcode_tmp.c_str();
   1312     }
   1313     break;
   1314   case 0xA5:
   1315     opcode1 = (prefix[2] == 0x66 ? "movsw" : "movsl");
   1316     break;
   1317   case 0xA7:
   1318     opcode1 = (prefix[2] == 0x66 ? "cmpsw" : "cmpsl");
   1319     break;
   1320   case 0xAF:
   1321     opcode1 = (prefix[2] == 0x66 ? "scasw" : "scasl");
   1322     break;
   1323   case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7:
   1324     opcode1 = "mov";
   1325     immediate_bytes = 1;
   1326     byte_operand = true;
   1327     reg_in_opcode = true;
   1328     byte_operand = true;
   1329     break;
   1330   case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF:
   1331     if ((rex & REX_W) != 0) {
   1332       opcode1 = "movabsq";
   1333       immediate_bytes = 8;
   1334       reg_in_opcode = true;
   1335       break;
   1336     }
   1337     opcode1 = "mov";
   1338     immediate_bytes = 4;
   1339     reg_in_opcode = true;
   1340     break;
   1341   case 0xC0: case 0xC1:
   1342   case 0xD0: case 0xD1: case 0xD2: case 0xD3:
   1343     static const char* shift_opcodes[] =
   1344         {"rol", "ror", "rcl", "rcr", "shl", "shr", "unknown-shift", "sar"};
   1345     modrm_opcodes = shift_opcodes;
   1346     has_modrm = true;
   1347     reg_is_opcode = true;
   1348     store = true;
   1349     immediate_bytes = ((*instr & 0xf0) == 0xc0) ? 1 : 0;
   1350     cx = (*instr == 0xD2) || (*instr == 0xD3);
   1351     byte_operand = (*instr == 0xC0);
   1352     break;
   1353   case 0xC3: opcode1 = "ret"; break;
   1354   case 0xC6:
   1355     static const char* c6_opcodes[] = {"mov",        "unknown-c6", "unknown-c6",
   1356                                        "unknown-c6", "unknown-c6", "unknown-c6",
   1357                                        "unknown-c6", "unknown-c6"};
   1358     modrm_opcodes = c6_opcodes;
   1359     store = true;
   1360     immediate_bytes = 1;
   1361     has_modrm = true;
   1362     reg_is_opcode = true;
   1363     byte_operand = true;
   1364     break;
   1365   case 0xC7:
   1366     static const char* c7_opcodes[] = {"mov",        "unknown-c7", "unknown-c7",
   1367                                        "unknown-c7", "unknown-c7", "unknown-c7",
   1368                                        "unknown-c7", "unknown-c7"};
   1369     modrm_opcodes = c7_opcodes;
   1370     store = true;
   1371     immediate_bytes = 4;
   1372     has_modrm = true;
   1373     reg_is_opcode = true;
   1374     break;
   1375   case 0xCC: opcode1 = "int 3"; break;
   1376   case 0xD9:
   1377     if (instr[1] == 0xF8) {
   1378       opcode1 = "fprem";
   1379       instr++;
   1380     } else {
   1381       static const char* d9_opcodes[] = {"flds", "unknown-d9", "fsts", "fstps", "fldenv", "fldcw",
   1382                                          "fnstenv", "fnstcw"};
   1383       modrm_opcodes = d9_opcodes;
   1384       store = true;
   1385       has_modrm = true;
   1386       reg_is_opcode = true;
   1387     }
   1388     break;
   1389   case 0xDA:
   1390     if (instr[1] == 0xE9) {
   1391       opcode1 = "fucompp";
   1392       instr++;
   1393     } else {
   1394       opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr);
   1395       opcode1 = opcode_tmp.c_str();
   1396     }
   1397     break;
   1398   case 0xDB:
   1399     static const char* db_opcodes[] = {"fildl",      "unknown-db", "unknown-db",
   1400                                        "unknown-db", "unknown-db", "unknown-db",
   1401                                        "unknown-db", "unknown-db"};
   1402     modrm_opcodes = db_opcodes;
   1403     load = true;
   1404     has_modrm = true;
   1405     reg_is_opcode = true;
   1406     break;
   1407   case 0xDD:
   1408     static const char* dd_opcodes[] = {"fldl",   "fisttp", "fstl",
   1409                                        "fstpl",  "frstor", "unknown-dd",
   1410                                        "fnsave", "fnstsw"};
   1411     modrm_opcodes = dd_opcodes;
   1412     store = true;
   1413     has_modrm = true;
   1414     reg_is_opcode = true;
   1415     break;
   1416   case 0xDF:
   1417     static const char* df_opcodes[] = {"fild",       "unknown-df", "unknown-df",
   1418                                        "unknown-df", "unknown-df", "fildll",
   1419                                        "unknown-df", "unknown-df"};
   1420     modrm_opcodes = df_opcodes;
   1421     load = true;
   1422     has_modrm = true;
   1423     reg_is_opcode = true;
   1424     break;
   1425   case 0xE3: opcode1 = "jecxz"; branch_bytes = 1; break;
   1426   case 0xE8: opcode1 = "call"; branch_bytes = 4; break;
   1427   case 0xE9: opcode1 = "jmp"; branch_bytes = 4; break;
   1428   case 0xEB: opcode1 = "jmp"; branch_bytes = 1; break;
   1429   case 0xF5: opcode1 = "cmc"; break;
   1430   case 0xF6: case 0xF7:
   1431     static const char* f7_opcodes[] = {
   1432         "test", "unknown-f7", "not", "neg", "mul edx:eax, eax *",
   1433         "imul edx:eax, eax *", "div edx:eax, edx:eax /",
   1434         "idiv edx:eax, edx:eax /"};
   1435     modrm_opcodes = f7_opcodes;
   1436     has_modrm = true;
   1437     reg_is_opcode = true;
   1438     store = true;
   1439     immediate_bytes = ((instr[1] & 0x38) == 0) ? (instr[0] == 0xF7 ? 4 : 1) : 0;
   1440     break;
   1441   case 0xFF:
   1442     {
   1443       static const char* ff_opcodes[] = {
   1444           "inc", "dec", "call", "call",
   1445           "jmp", "jmp", "push", "unknown-ff"};
   1446       modrm_opcodes = ff_opcodes;
   1447       has_modrm = true;
   1448       reg_is_opcode = true;
   1449       load = true;
   1450       const uint8_t opcode_digit = (instr[1] >> 3) & 7;
   1451       // 'call', 'jmp' and 'push' are target specific instructions
   1452       if (opcode_digit == 2 || opcode_digit == 4 || opcode_digit == 6) {
   1453         target_specific = true;
   1454       }
   1455     }
   1456     break;
   1457   default:
   1458     opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr);
   1459     opcode1 = opcode_tmp.c_str();
   1460     break;
   1461   }
   1462   std::ostringstream args;
   1463   // We force the REX prefix to be available for 64-bit target
   1464   // in order to dump addr (base/index) registers correctly.
   1465   uint8_t rex64 = supports_rex_ ? (rex | 0x40) : rex;
   1466   // REX.W should be forced for 64-target and target-specific instructions (i.e., push or pop).
   1467   uint8_t rex_w = (supports_rex_ && target_specific) ? (rex | 0x48) : rex;
   1468   if (reg_in_opcode) {
   1469     DCHECK(!has_modrm);
   1470     DumpOpcodeReg(args, rex_w, *instr & 0x7, byte_operand, prefix[2]);
   1471   }
   1472   instr++;
   1473   uint32_t address_bits = 0;
   1474   if (has_modrm) {
   1475     uint8_t modrm = *instr;
   1476     instr++;
   1477     uint8_t mod = modrm >> 6;
   1478     uint8_t reg_or_opcode = (modrm >> 3) & 7;
   1479     uint8_t rm = modrm & 7;
   1480     std::string address = DumpAddress(mod, rm, rex64, rex_w, no_ops, byte_operand,
   1481                                       byte_second_operand, prefix, load, src_reg_file, dst_reg_file,
   1482                                       &instr, &address_bits);
   1483 
   1484     if (reg_is_opcode && modrm_opcodes != nullptr) {
   1485       opcode3 = modrm_opcodes[reg_or_opcode];
   1486     }
   1487 
   1488     // Add opcode suffixes to indicate size.
   1489     if (byte_operand) {
   1490       opcode4 = "b";
   1491     } else if ((rex & REX_W) != 0) {
   1492       opcode4 = "q";
   1493     } else if (prefix[2] == 0x66) {
   1494       opcode4 = "w";
   1495     }
   1496 
   1497     if (load) {
   1498       if (!reg_is_opcode) {
   1499         DumpReg(args, rex, reg_or_opcode, byte_operand, prefix[2], dst_reg_file);
   1500         args << ", ";
   1501       }
   1502       DumpSegmentOverride(args, prefix[1]);
   1503       args << address;
   1504     } else {
   1505       DCHECK(store);
   1506       DumpSegmentOverride(args, prefix[1]);
   1507       args << address;
   1508       if (!reg_is_opcode) {
   1509         args << ", ";
   1510         DumpReg(args, rex, reg_or_opcode, byte_operand, prefix[2], src_reg_file);
   1511       }
   1512     }
   1513   }
   1514   if (ax) {
   1515     // If this opcode implicitly uses ax, ax is always the first arg.
   1516     DumpReg(args, rex, 0 /* EAX */, byte_operand, prefix[2], GPR);
   1517   }
   1518   if (cx) {
   1519     args << ", ";
   1520     DumpReg(args, rex, 1 /* ECX */, true, prefix[2], GPR);
   1521   }
   1522   if (immediate_bytes > 0) {
   1523     if (has_modrm || reg_in_opcode || ax || cx) {
   1524       args << ", ";
   1525     }
   1526     if (immediate_bytes == 1) {
   1527       args << StringPrintf("%d", *reinterpret_cast<const int8_t*>(instr));
   1528       instr++;
   1529     } else if (immediate_bytes == 4) {
   1530       if (prefix[2] == 0x66) {  // Operand size override from 32-bit to 16-bit.
   1531         args << StringPrintf("%d", *reinterpret_cast<const int16_t*>(instr));
   1532         instr += 2;
   1533       } else {
   1534         args << StringPrintf("%d", *reinterpret_cast<const int32_t*>(instr));
   1535         instr += 4;
   1536       }
   1537     } else {
   1538       CHECK_EQ(immediate_bytes, 8u);
   1539       args << StringPrintf("%" PRId64, *reinterpret_cast<const int64_t*>(instr));
   1540       instr += 8;
   1541     }
   1542   } else if (branch_bytes > 0) {
   1543     DCHECK(!has_modrm);
   1544     int32_t displacement;
   1545     if (branch_bytes == 1) {
   1546       displacement = *reinterpret_cast<const int8_t*>(instr);
   1547       instr++;
   1548     } else {
   1549       CHECK_EQ(branch_bytes, 4u);
   1550       displacement = *reinterpret_cast<const int32_t*>(instr);
   1551       instr += 4;
   1552     }
   1553     args << StringPrintf("%+d (", displacement)
   1554          << FormatInstructionPointer(instr + displacement)
   1555          << ")";
   1556   }
   1557   if (prefix[1] == kFs && !supports_rex_) {
   1558     args << "  ; ";
   1559     GetDisassemblerOptions()->thread_offset_name_function_(args, address_bits);
   1560   }
   1561   if (prefix[1] == kGs && supports_rex_) {
   1562     args << "  ; ";
   1563     GetDisassemblerOptions()->thread_offset_name_function_(args, address_bits);
   1564   }
   1565   const char* prefix_str;
   1566   switch (prefix[0]) {
   1567     case 0xF0: prefix_str = "lock "; break;
   1568     case 0xF2: prefix_str = "repne "; break;
   1569     case 0xF3: prefix_str = "repe "; break;
   1570     case 0: prefix_str = ""; break;
   1571     default: LOG(FATAL) << "Unreachable"; UNREACHABLE();
   1572   }
   1573   os << FormatInstructionPointer(begin_instr)
   1574      << StringPrintf(": %22s    \t%-7s%s%s%s%s%s ", DumpCodeHex(begin_instr, instr).c_str(),
   1575                      prefix_str, opcode0, opcode1, opcode2, opcode3, opcode4)
   1576      << args.str() << '\n';
   1577   return instr - begin_instr;
   1578 }  // NOLINT(readability/fn_size)
   1579 
   1580 }  // namespace x86
   1581 }  // namespace art
   1582