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