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_arm.h"
     18 
     19 #include <inttypes.h>
     20 
     21 #include <ostream>
     22 #include <sstream>
     23 
     24 #include "arch/arm/registers_arm.h"
     25 #include "base/bit_utils.h"
     26 #include "base/logging.h"
     27 #include "base/stringprintf.h"
     28 #include "thread.h"
     29 
     30 namespace art {
     31 namespace arm {
     32 
     33 size_t DisassemblerArm::Dump(std::ostream& os, const uint8_t* begin) {
     34   if ((reinterpret_cast<intptr_t>(begin) & 1) == 0) {
     35     DumpArm(os, begin);
     36     return 4;
     37   } else {
     38     // remove thumb specifier bits
     39     begin = reinterpret_cast<const uint8_t*>(reinterpret_cast<uintptr_t>(begin) & ~1);
     40     return DumpThumb16(os, begin);
     41   }
     42 }
     43 
     44 void DisassemblerArm::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) {
     45   if ((reinterpret_cast<intptr_t>(begin) & 1) == 0) {
     46     for (const uint8_t* cur = begin; cur < end; cur += 4) {
     47       DumpArm(os, cur);
     48     }
     49   } else {
     50     // remove thumb specifier bits
     51     begin = reinterpret_cast<const uint8_t*>(reinterpret_cast<uintptr_t>(begin) & ~1);
     52     end = reinterpret_cast<const uint8_t*>(reinterpret_cast<uintptr_t>(end) & ~1);
     53     for (const uint8_t* cur = begin; cur < end;) {
     54       cur += DumpThumb16(os, cur);
     55     }
     56   }
     57 }
     58 
     59 static const char* kConditionCodeNames[] = {
     60   "eq",  // 0000 - equal
     61   "ne",  // 0001 - not-equal
     62   "cs",  // 0010 - carry-set, greater than, equal or unordered
     63   "cc",  // 0011 - carry-clear, less than
     64   "mi",  // 0100 - minus, negative
     65   "pl",  // 0101 - plus, positive or zero
     66   "vs",  // 0110 - overflow
     67   "vc",  // 0111 - no overflow
     68   "hi",  // 1000 - unsigned higher
     69   "ls",  // 1001 - unsigned lower or same
     70   "ge",  // 1010 - signed greater than or equal
     71   "lt",  // 1011 - signed less than
     72   "gt",  // 1100 - signed greater than
     73   "le",  // 1101 - signed less than or equal
     74   "",    // 1110 - always
     75   "nv",  // 1111 - never (mostly obsolete, but might be a clue that we're mistranslating)
     76 };
     77 
     78 void DisassemblerArm::DumpCond(std::ostream& os, uint32_t cond) {
     79   if (cond < 15) {
     80     os << kConditionCodeNames[cond];
     81   } else {
     82     os << "Unexpected condition: " << cond;
     83   }
     84 }
     85 
     86 void DisassemblerArm::DumpMemoryDomain(std::ostream& os, uint32_t domain) {
     87   switch (domain) {
     88     case 15U /* 0b1111 */: os << "sy"; break;
     89     case 14U /* 0b1110 */: os << "st"; break;
     90     case 11U /* 0b1011 */: os << "ish"; break;
     91     case 10U /* 0b1010 */: os << "ishst"; break;
     92     case  7U /* 0b0111 */: os << "nsh"; break;
     93     case  6U /* 0b0110 */: os << "nshst"; break;
     94     case  3U /* 0b0011 */: os << "osh"; break;
     95     case  2U /* 0b0010 */: os << "oshst"; break;
     96   }
     97 }
     98 
     99 void DisassemblerArm::DumpBranchTarget(std::ostream& os, const uint8_t* instr_ptr, int32_t imm32) {
    100   os << StringPrintf("%+d (", imm32) << FormatInstructionPointer(instr_ptr + imm32) << ")";
    101 }
    102 
    103 static uint32_t ReadU16(const uint8_t* ptr) {
    104   return ptr[0] | (ptr[1] << 8);
    105 }
    106 
    107 static uint32_t ReadU32(const uint8_t* ptr) {
    108   return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
    109 }
    110 
    111 static const char* kDataProcessingOperations[] = {
    112   "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
    113   "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn",
    114 };
    115 
    116 static const char* kThumbDataProcessingOperations[] = {
    117   "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror",
    118   "tst", "rsb", "cmp", "cmn", "orr", "mul", "bic", "mvn",
    119 };
    120 
    121 static const char* const kThumb2ShiftOperations[] = {
    122     "lsl", "lsr", "asr", "ror"
    123 };
    124 
    125 static const char* kThumbReverseOperations[] = {
    126     "rev", "rev16", "rbit", "revsh"
    127 };
    128 
    129 struct ArmRegister {
    130   explicit ArmRegister(uint32_t r_in) : r(r_in) { CHECK_LE(r_in, 15U); }
    131   ArmRegister(uint32_t instruction, uint32_t at_bit) : r((instruction >> at_bit) & 0xf) {
    132     CHECK_LE(r, 15U);
    133   }
    134   uint32_t r;
    135 };
    136 std::ostream& operator<<(std::ostream& os, const ArmRegister& r) {
    137   if (r.r == 13) {
    138     os << "sp";
    139   } else if (r.r == 14) {
    140     os << "lr";
    141   } else if (r.r == 15) {
    142     os << "pc";
    143   } else {
    144     os << "r" << r.r;
    145   }
    146   return os;
    147 }
    148 
    149 struct ThumbRegister : ArmRegister {
    150   ThumbRegister(uint16_t instruction, uint16_t at_bit) : ArmRegister((instruction >> at_bit) & 0x7) {}
    151 };
    152 
    153 struct RmLslImm2 {
    154   explicit RmLslImm2(uint32_t instr) : imm2((instr >> 4) & 0x3), rm(instr & 0xf) {}
    155   uint32_t imm2;
    156   ArmRegister rm;
    157 };
    158 std::ostream& operator<<(std::ostream& os, const RmLslImm2& r) {
    159   os << r.rm;
    160   if (r.imm2 != 0) {
    161     os << ", lsl #" << r.imm2;
    162   }
    163   return os;
    164 }
    165 
    166 struct ShiftedImmediate {
    167   explicit ShiftedImmediate(uint32_t instruction) {
    168     uint32_t rotate = ((instruction >> 8) & 0xf);
    169     uint32_t imm = (instruction & 0xff);
    170     value = (imm >> (2 * rotate)) | (imm << (32 - (2 * rotate)));
    171   }
    172   uint32_t value;
    173 };
    174 std::ostream& operator<<(std::ostream& os, const ShiftedImmediate& rhs) {
    175   os << "#" << rhs.value;
    176   return os;
    177 }
    178 
    179 struct RegisterList {
    180   explicit RegisterList(uint32_t instruction) : register_list(instruction & 0xffff) {}
    181   uint32_t register_list;
    182 };
    183 std::ostream& operator<<(std::ostream& os, const RegisterList& rhs) {
    184   if (rhs.register_list == 0) {
    185     os << "<no register list?>";
    186     return os;
    187   }
    188   os << "{";
    189   bool first = true;
    190   for (size_t i = 0; i < 16; i++) {
    191     if ((rhs.register_list & (1 << i)) != 0) {
    192       if (first) {
    193         first = false;
    194       } else {
    195         os << ", ";
    196       }
    197       os << ArmRegister(i);
    198     }
    199   }
    200   os << "}";
    201   return os;
    202 }
    203 
    204 struct FpRegister {
    205   FpRegister(uint32_t instr, uint16_t at_bit, uint16_t extra_at_bit) {
    206     size = (instr >> 8) & 1;
    207     uint32_t Vn = (instr >> at_bit) & 0xF;
    208     uint32_t N = (instr >> extra_at_bit) & 1;
    209     r = (size != 0 ? ((N << 4) | Vn) : ((Vn << 1) | N));
    210   }
    211   FpRegister(uint32_t instr, uint16_t at_bit, uint16_t extra_at_bit, uint32_t forced_size) {
    212     size = forced_size;
    213     uint32_t Vn = (instr >> at_bit) & 0xF;
    214     uint32_t N = (instr >> extra_at_bit) & 1;
    215     r = (size != 0 ? ((N << 4) | Vn) : ((Vn << 1) | N));
    216   }
    217   FpRegister(const FpRegister& other, uint32_t offset)
    218       : size(other.size), r(other.r + offset) {}
    219 
    220   uint32_t size;  // 0 = f32, 1 = f64
    221   uint32_t r;
    222 };
    223 std::ostream& operator<<(std::ostream& os, const FpRegister& rhs) {
    224   return os << ((rhs.size != 0) ? "d" : "s") << rhs.r;
    225 }
    226 
    227 struct FpRegisterRange {
    228   explicit FpRegisterRange(uint32_t instr)
    229       : first(instr, 12, 22), imm8(instr & 0xFF) {}
    230   FpRegister first;
    231   uint32_t imm8;
    232 };
    233 std::ostream& operator<<(std::ostream& os, const FpRegisterRange& rhs) {
    234   os << "{" << rhs.first;
    235   int count = (rhs.first.size != 0 ? ((rhs.imm8 + 1u) >> 1) : rhs.imm8);
    236   if (count > 1) {
    237     os << "-" << FpRegister(rhs.first, count - 1);
    238   }
    239   if (rhs.imm8 == 0) {
    240     os << " (EMPTY)";
    241   } else if (rhs.first.size != 0 && (rhs.imm8 & 1) != 0) {
    242     os << rhs.first << " (HALF)";
    243   }
    244   os << "}";
    245   return os;
    246 }
    247 
    248 void DisassemblerArm::DumpArm(std::ostream& os, const uint8_t* instr_ptr) {
    249   uint32_t instruction = ReadU32(instr_ptr);
    250   uint32_t cond = (instruction >> 28) & 0xf;
    251   uint32_t op1 = (instruction >> 25) & 0x7;
    252   std::string opcode;
    253   std::string suffixes;
    254   std::ostringstream args;
    255   switch (op1) {
    256     case 0:
    257     case 1:  // Data processing instructions.
    258       {
    259         if ((instruction & 0x0ff000f0) == 0x01200070) {  // BKPT
    260           opcode = "bkpt";
    261           uint32_t imm12 = (instruction >> 8) & 0xfff;
    262           uint32_t imm4 = (instruction & 0xf);
    263           args << '#' << ((imm12 << 4) | imm4);
    264           break;
    265         }
    266         if ((instruction & 0x0fffffd0) == 0x012fff10) {  // BX and BLX (register)
    267           opcode = (((instruction >> 5) & 1) ? "blx" : "bx");
    268           args << ArmRegister(instruction & 0xf);
    269           break;
    270         }
    271         bool i = (instruction & (1 << 25)) != 0;
    272         bool s = (instruction & (1 << 20)) != 0;
    273         uint32_t op = (instruction >> 21) & 0xf;
    274         opcode = kDataProcessingOperations[op];
    275         bool implicit_s = ((op & ~3) == 8);  // TST, TEQ, CMP, and CMN.
    276         bool is_mov = op == 13U /* 0b1101 */ || op == 15U /* 0b1111 */;
    277         if (is_mov) {
    278           // Show only Rd and Rm.
    279           if (s) {
    280              suffixes += 's';
    281            }
    282            args << ArmRegister(instruction, 12) << ", ";
    283            if (i) {
    284               args << ShiftedImmediate(instruction);
    285             } else {
    286               // TODO: Shifted register.
    287               args << ArmRegister(instruction, 16) << ", " << ArmRegister(instruction, 0);
    288             }
    289         } else {
    290           if (implicit_s) {
    291             // Rd is unused (and not shown), and we don't show the 's' suffix either.
    292           } else {
    293             if (s) {
    294               suffixes += 's';
    295             }
    296             args << ArmRegister(instruction, 12) << ", ";
    297           }
    298           if (i) {
    299             args << ArmRegister(instruction, 16) << ", " << ShiftedImmediate(instruction);
    300           } else {
    301             // TODO: Shifted register.
    302             args << ArmRegister(instruction, 16) << ", " << ArmRegister(instruction, 0);
    303           }
    304         }
    305       }
    306       break;
    307     case 2:  // Load/store word and unsigned byte.
    308       {
    309         bool p = (instruction & (1 << 24)) != 0;
    310         bool b = (instruction & (1 << 22)) != 0;
    311         bool w = (instruction & (1 << 21)) != 0;
    312         bool l = (instruction & (1 << 20)) != 0;
    313         opcode = StringPrintf("%s%s", (l ? "ldr" : "str"), (b ? "b" : ""));
    314         args << ArmRegister(instruction, 12) << ", ";
    315         ArmRegister rn(instruction, 16);
    316         if (rn.r == 0xf) {
    317           UNIMPLEMENTED(FATAL) << "literals";
    318         } else {
    319           bool wback = !p || w;
    320           uint32_t offset = (instruction & 0xfff);
    321           if (p && !wback) {
    322             args << "[" << rn << ", #" << offset << "]";
    323           } else if (p && wback) {
    324             args << "[" << rn << ", #" << offset << "]!";
    325           } else if (!p && wback) {
    326             args << "[" << rn << "], #" << offset;
    327           } else {
    328             LOG(FATAL) << p << " " << w;
    329           }
    330           if (rn.r == 9) {
    331             args << "  ; ";
    332             Thread::DumpThreadOffset<4>(args, offset);
    333           }
    334         }
    335       }
    336       break;
    337     case 4:  // Load/store multiple.
    338       {
    339         bool p = (instruction & (1 << 24)) != 0;
    340         bool u = (instruction & (1 << 23)) != 0;
    341         bool w = (instruction & (1 << 21)) != 0;
    342         bool l = (instruction & (1 << 20)) != 0;
    343         opcode = StringPrintf("%s%c%c", (l ? "ldm" : "stm"), (u ? 'i' : 'd'), (p ? 'b' : 'a'));
    344         args << ArmRegister(instruction, 16) << (w ? "!" : "") << ", " << RegisterList(instruction);
    345       }
    346       break;
    347     case 5:  // Branch/branch with link.
    348       {
    349         bool bl = (instruction & (1 << 24)) != 0;
    350         opcode = (bl ? "bl" : "b");
    351         int32_t imm26 = (instruction & 0xffffff) << 2;
    352         int32_t imm32 = (imm26 << 6) >> 6;  // Sign extend.
    353         DumpBranchTarget(args, instr_ptr + 8, imm32);
    354       }
    355       break;
    356     default:
    357       opcode = "???";
    358       break;
    359     }
    360     opcode += kConditionCodeNames[cond];
    361     opcode += suffixes;
    362     // TODO: a more complete ARM disassembler could generate wider opcodes.
    363     os << FormatInstructionPointer(instr_ptr)
    364        << StringPrintf(": %08x\t%-7s ", instruction, opcode.c_str())
    365        << args.str() << '\n';
    366 }
    367 
    368 int32_t ThumbExpand(int32_t imm12) {
    369   if ((imm12 & 0xC00) == 0) {
    370     switch ((imm12 >> 8) & 3) {
    371       case 0:
    372         return imm12 & 0xFF;
    373       case 1:
    374         return ((imm12 & 0xFF) << 16) | (imm12 & 0xFF);
    375       case 2:
    376         return ((imm12 & 0xFF) << 24) | ((imm12 & 0xFF) << 8);
    377       default:  // 3
    378         return ((imm12 & 0xFF) << 24) | ((imm12 & 0xFF) << 16) | ((imm12 & 0xFF) << 8) |
    379             (imm12 & 0xFF);
    380     }
    381   } else {
    382     uint32_t val = 0x80 | (imm12 & 0x7F);
    383     int32_t rotate = (imm12 >> 7) & 0x1F;
    384     return (val >> rotate) | (val << (32 - rotate));
    385   }
    386 }
    387 
    388 uint32_t VFPExpand32(uint32_t imm8) {
    389   CHECK_EQ(imm8 & 0xffu, imm8);
    390   uint32_t bit_a = (imm8 >> 7) & 1;
    391   uint32_t bit_b = (imm8 >> 6) & 1;
    392   uint32_t slice = imm8 & 0x3f;
    393   return (bit_a << 31) | ((1 << 30) - (bit_b << 25)) | (slice << 19);
    394 }
    395 
    396 static uint64_t VFPExpand64(uint32_t imm8) {
    397   CHECK_EQ(imm8 & 0xffu, imm8);
    398   uint64_t bit_a = (imm8 >> 7) & 1;
    399   uint64_t bit_b = (imm8 >> 6) & 1;
    400   uint64_t slice = imm8 & 0x3f;
    401   return (bit_a << 63) | ((UINT64_C(1) << 62) - (bit_b << 54)) | (slice << 48);
    402 }
    403 
    404 enum T2LitType {
    405   kT2LitInvalid,
    406   kT2LitUByte,
    407   kT2LitSByte,
    408   kT2LitUHalf,
    409   kT2LitSHalf,
    410   kT2LitUWord,
    411   kT2LitSWord,
    412   kT2LitHexWord,
    413   kT2LitULong,
    414   kT2LitSLong,
    415   kT2LitHexLong,
    416 };
    417 std::ostream& operator<<(std::ostream& os, T2LitType type) {
    418   return os << static_cast<int>(type);
    419 }
    420 
    421 void DumpThumb2Literal(std::ostream& args,
    422                        const uint8_t* instr_ptr,
    423                        const uintptr_t lo_adr,
    424                        const uintptr_t hi_adr,
    425                        uint32_t U,
    426                        uint32_t imm32,
    427                        T2LitType type) {
    428   // Literal offsets (imm32) are not required to be aligned so we may need unaligned access.
    429   typedef const int16_t unaligned_int16_t __attribute__ ((aligned (1)));
    430   typedef const uint16_t unaligned_uint16_t __attribute__ ((aligned (1)));
    431   typedef const int32_t unaligned_int32_t __attribute__ ((aligned (1)));
    432   typedef const uint32_t unaligned_uint32_t __attribute__ ((aligned (1)));
    433   typedef const int64_t unaligned_int64_t __attribute__ ((aligned (1)));
    434   typedef const uint64_t unaligned_uint64_t __attribute__ ((aligned (1)));
    435 
    436   // Get address of literal. Bail if not within expected buffer range to
    437   // avoid trying to fetch invalid literals (we can encounter this when
    438   // interpreting raw data as instructions).
    439   uintptr_t pc = RoundDown(reinterpret_cast<intptr_t>(instr_ptr) + 4, 4);
    440   uintptr_t lit_adr = U ? pc + imm32 : pc - imm32;
    441   if (lit_adr < lo_adr || lit_adr >= hi_adr) {
    442     args << "  ; (?)";
    443     return;
    444   }
    445 
    446   args << "  ; ";
    447   switch (type) {
    448     case kT2LitUByte:
    449       args << *reinterpret_cast<const uint8_t*>(lit_adr);
    450       break;
    451     case kT2LitSByte:
    452       args << *reinterpret_cast<const int8_t*>(lit_adr);
    453       break;
    454     case kT2LitUHalf:
    455       args << *reinterpret_cast<const unaligned_uint16_t*>(lit_adr);
    456       break;
    457     case kT2LitSHalf:
    458       args << *reinterpret_cast<const unaligned_int16_t*>(lit_adr);
    459       break;
    460     case kT2LitUWord:
    461       args << *reinterpret_cast<const unaligned_uint32_t*>(lit_adr);
    462       break;
    463     case kT2LitSWord:
    464       args << *reinterpret_cast<const unaligned_int32_t*>(lit_adr);
    465       break;
    466     case kT2LitHexWord:
    467       args << StringPrintf("0x%08x", *reinterpret_cast<const unaligned_uint32_t*>(lit_adr));
    468       break;
    469     case kT2LitULong:
    470       args << *reinterpret_cast<const unaligned_uint64_t*>(lit_adr);
    471       break;
    472     case kT2LitSLong:
    473       args << *reinterpret_cast<const unaligned_int64_t*>(lit_adr);
    474       break;
    475     case kT2LitHexLong:
    476       args << StringPrintf("0x%" PRIx64, *reinterpret_cast<unaligned_int64_t*>(lit_adr));
    477       break;
    478     default:
    479       LOG(FATAL) << "Invalid type: " << type;
    480       break;
    481   }
    482 }
    483 
    484 size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr) {
    485   uint32_t instr = (ReadU16(instr_ptr) << 16) | ReadU16(instr_ptr + 2);
    486   // |111|1 1|1000000|0000|1111110000000000|
    487   // |5 3|2 1|0987654|3  0|5    0    5    0|
    488   // |---|---|-------|----|----------------|
    489   // |332|2 2|2222222|1111|1111110000000000|
    490   // |1 9|8 7|6543210|9  6|5    0    5    0|
    491   // |---|---|-------|----|----------------|
    492   // |111|op1| op2   |    |                |
    493   uint32_t op1 = (instr >> 27) & 3;
    494   if (op1 == 0) {
    495     return DumpThumb16(os, instr_ptr);
    496   }
    497 
    498   // Set valid address range of backing buffer.
    499   const uintptr_t lo_adr = reinterpret_cast<intptr_t>(GetDisassemblerOptions()->base_address_);
    500   const uintptr_t hi_adr = reinterpret_cast<intptr_t>(GetDisassemblerOptions()->end_address_);
    501 
    502   uint32_t op2 = (instr >> 20) & 0x7F;
    503   std::ostringstream opcode;
    504   std::ostringstream args;
    505   switch (op1) {
    506     case 0:
    507       break;
    508     case 1:
    509       if ((op2 & 0x64) == 0) {  // 00x x0xx
    510         // |111|11|10|00|0|00|0000|1111110000000000|
    511         // |5 3|21|09|87|6|54|3  0|5    0    5    0|
    512         // |---|--|--|--|-|--|----|----------------|
    513         // |332|22|22|22|2|22|1111|1111110000000000|
    514         // |1 9|87|65|43|2|10|9  6|5    0    5    0|
    515         // |---|--|--|--|-|--|----|----------------|
    516         // |111|01|00|op|0|WL| Rn |                |
    517         // |111|01| op2      |    |                |
    518         // STM - 111 01 00-01-0-W0 nnnn rrrrrrrrrrrrrrrr
    519         // LDM - 111 01 00-01-0-W1 nnnn rrrrrrrrrrrrrrrr
    520         // PUSH- 111 01 00-01-0-10 1101 0M0rrrrrrrrrrrrr
    521         // POP - 111 01 00-01-0-11 1101 PM0rrrrrrrrrrrrr
    522         uint32_t op = (instr >> 23) & 3;
    523         uint32_t W = (instr >> 21) & 1;
    524         uint32_t L = (instr >> 20) & 1;
    525         ArmRegister Rn(instr, 16);
    526         if (op == 1 || op == 2) {
    527           if (op == 1) {
    528             if (L == 0) {
    529               opcode << "stm";
    530               args << Rn << (W == 0 ? "" : "!") << ", ";
    531             } else {
    532               if (Rn.r != 13) {
    533                 opcode << "ldm";
    534                 args << Rn << (W == 0 ? "" : "!") << ", ";
    535               } else {
    536                 opcode << "pop";
    537               }
    538             }
    539           } else {
    540             if (L == 0) {
    541               if (Rn.r != 13) {
    542                 opcode << "stmdb";
    543                 args << Rn << (W == 0 ? "" : "!") << ", ";
    544               } else {
    545                 opcode << "push";
    546               }
    547             } else {
    548               opcode << "ldmdb";
    549               args << Rn << (W == 0 ? "" : "!") << ", ";
    550             }
    551           }
    552           args << RegisterList(instr);
    553         }
    554       } else if ((op2 & 0x64) == 4) {  // 00x x1xx
    555         uint32_t op3 = (instr >> 23) & 3;
    556         uint32_t op4 = (instr >> 20) & 3;
    557         // uint32_t op5 = (instr >> 4) & 0xF;
    558         ArmRegister Rn(instr, 16);
    559         ArmRegister Rt(instr, 12);
    560         ArmRegister Rd(instr, 8);
    561         uint32_t imm8 = instr & 0xFF;
    562         if ((op3 & 2) == 2) {     // 1x
    563           int W = (instr >> 21) & 1;
    564           int U = (instr >> 23) & 1;
    565           int P = (instr >> 24) & 1;
    566 
    567           if ((op4 & 1) == 1) {
    568             opcode << "ldrd";
    569           } else {
    570             opcode << "strd";
    571           }
    572           args << Rt << "," << Rd << ", [" << Rn;
    573           const char *sign = U ? "+" : "-";
    574           if (P == 0 && W == 1) {
    575             args << "], #" << sign << (imm8 << 2);
    576           } else {
    577             args << ", #" << sign << (imm8 << 2) << "]";
    578             if (W == 1) {
    579               args << "!";
    580             }
    581           }
    582         } else {                  // 0x
    583           switch (op4) {
    584             case 0:
    585               if (op3 == 0) {   // op3 is 00, op4 is 00
    586                 opcode << "strex";
    587                 args << Rd << ", " << Rt << ", [" << Rn << ", #" << (imm8 << 2) << "]";
    588                 if (Rd.r == 13 || Rd.r == 15 || Rt.r == 13 || Rt.r == 15 || Rn.r == 15 ||
    589                     Rd.r == Rn.r || Rd.r == Rt.r) {
    590                   args << " (UNPREDICTABLE)";
    591                 }
    592               } else {          // op3 is 01, op4 is 00
    593                 // this is one of strexb, strexh or strexd
    594                 int op5 = (instr >> 4) & 0xf;
    595                 switch (op5) {
    596                   case 4:
    597                   case 5:
    598                     opcode << ((op5 == 4) ? "strexb" : "strexh");
    599                     Rd = ArmRegister(instr, 0);
    600                     args << Rd << ", " << Rt << ", [" << Rn << "]";
    601                     if (Rd.r == 13 || Rd.r == 15 || Rt.r == 13 || Rt.r == 15 || Rn.r == 15 ||
    602                         Rd.r == Rn.r || Rd.r == Rt.r || (instr & 0xf00) != 0xf00) {
    603                       args << " (UNPREDICTABLE)";
    604                     }
    605                     break;
    606                   case 7:
    607                     opcode << "strexd";
    608                     ArmRegister Rt2 = Rd;
    609                     Rd = ArmRegister(instr, 0);
    610                     args << Rd << ", " << Rt << ", " << Rt2 << ", [" << Rn << "]";
    611                     if (Rd.r == 13 || Rd.r == 15 || Rt.r == 13 || Rt.r == 15 ||
    612                         Rt2.r == 13 || Rt2.r == 15 || Rn.r == 15 ||
    613                         Rd.r == Rn.r || Rd.r == Rt.r || Rd.r == Rt2.r) {
    614                       args << " (UNPREDICTABLE)";
    615                     }
    616                     break;
    617                 }
    618               }
    619               break;
    620             case 1:
    621               if (op3 == 0) {   // op3 is 00, op4 is 01
    622                 opcode << "ldrex";
    623                 args << Rt << ", [" << Rn << ", #" << (imm8 << 2) << "]";
    624                 if (Rt.r == 13 || Rt.r == 15 || Rn.r == 15 || (instr & 0xf00) != 0xf00) {
    625                   args << " (UNPREDICTABLE)";
    626                 }
    627               } else {          // op3 is 01, op4 is 01
    628                 // this is one of strexb, strexh or strexd
    629                 int op5 = (instr >> 4) & 0xf;
    630                 switch (op5) {
    631                   case 0:
    632                     opcode << "tbb";
    633                     break;
    634                   case 1:
    635                     opcode << "tbh";
    636                     break;
    637                   case 4:
    638                   case 5:
    639                     opcode << ((op5 == 4) ? "ldrexb" : "ldrexh");
    640                     args << Rt << ", [" << Rn << "]";
    641                     if (Rt.r == 13 || Rt.r == 15 || Rn.r == 15 || (instr & 0xf0f) != 0xf0f) {
    642                       args << " (UNPREDICTABLE)";
    643                     }
    644                     break;
    645                   case 7:
    646                     opcode << "ldrexd";
    647                     args << Rt << ", " << Rd /* Rt2 */ << ", [" << Rn << "]";
    648                     if (Rt.r == 13 || Rt.r == 15 || Rd.r == 13 /* Rt2 */ || Rd.r == 15 /* Rt2 */ ||
    649                         Rn.r == 15 || (instr & 0x00f) != 0x00f) {
    650                       args << " (UNPREDICTABLE)";
    651                     }
    652                     break;
    653                 }
    654               }
    655               break;
    656             case 2:     // op3 is 0x, op4 is 10
    657             case 3:   // op3 is 0x, op4 is 11
    658               if (op4 == 2) {
    659                 opcode << "strd";
    660               } else {
    661                 opcode << "ldrd";
    662               }
    663               int W = (instr >> 21) & 1;
    664               int U = (instr >> 23) & 1;
    665               int P = (instr >> 24) & 1;
    666 
    667               args << Rt << "," << Rd << ", [" << Rn;
    668               const char *sign = U ? "+" : "-";
    669               if (P == 0 && W == 1) {
    670                 args << "], #" << sign << imm8;
    671               } else {
    672                 args << ", #" << sign << imm8 << "]";
    673                 if (W == 1) {
    674                   args << "!";
    675                 }
    676               }
    677               break;
    678           }
    679         }
    680 
    681       } else if ((op2 & 0x60) == 0x20) {  // 01x xxxx
    682         // Data-processing (shifted register)
    683         // |111|1110|0000|0|0000|1111|1100|00|00|0000|
    684         // |5 3|2109|8765|4|3  0|5   |10 8|7 |5 |3  0|
    685         // |---|----|----|-|----|----|----|--|--|----|
    686         // |332|2222|2222|2|1111|1111|1100|00|00|0000|
    687         // |1 9|8765|4321|0|9  6|5   |10 8|7 |5 |3  0|
    688         // |---|----|----|-|----|----|----|--|--|----|
    689         // |111|0101| op3|S| Rn |imm3| Rd |i2|ty| Rm |
    690         uint32_t op3 = (instr >> 21) & 0xF;
    691         uint32_t S = (instr >> 20) & 1;
    692         uint32_t imm3 = ((instr >> 12) & 0x7);
    693         uint32_t imm2 = ((instr >> 6) & 0x3);
    694         uint32_t imm5 = ((imm3 << 2) | imm2);
    695         uint32_t shift_type = ((instr >> 4) & 0x3);
    696         ArmRegister Rd(instr, 8);
    697         ArmRegister Rn(instr, 16);
    698         ArmRegister Rm(instr, 0);
    699         switch (op3) {
    700           case 0x0:
    701             if (Rd.r != 0xF) {
    702               opcode << "and";
    703             } else {
    704               if (S != 1U) {
    705                 opcode << "UNKNOWN TST-" << S;
    706                 break;
    707               }
    708               opcode << "tst";
    709               S = 0;  // don't print 's'
    710             }
    711             break;
    712           case 0x1: opcode << "bic"; break;
    713           case 0x2:
    714             if (Rn.r != 0xF) {
    715               opcode << "orr";
    716             } else {
    717               // TODO: use canonical form if there is a shift (lsl, ...).
    718               opcode << "mov";
    719             }
    720             break;
    721           case 0x3:
    722             if (Rn.r != 0xF) {
    723               opcode << "orn";
    724             } else {
    725               opcode << "mvn";
    726             }
    727             break;
    728           case 0x4:
    729             if (Rd.r != 0xF) {
    730               opcode << "eor";
    731             } else {
    732               if (S != 1U) {
    733                 opcode << "UNKNOWN TEQ-" << S;
    734                 break;
    735               }
    736               opcode << "teq";
    737               S = 0;  // don't print 's'
    738             }
    739             break;
    740           case 0x6: opcode << "pkh"; break;
    741           case 0x8:
    742             if (Rd.r != 0xF) {
    743               opcode << "add";
    744             } else {
    745               if (S != 1U) {
    746                 opcode << "UNKNOWN CMN-" << S;
    747                 break;
    748               }
    749               opcode << "cmn";
    750               S = 0;  // don't print 's'
    751             }
    752             break;
    753           case 0xA: opcode << "adc"; break;
    754           case 0xB: opcode << "sbc"; break;
    755           case 0xD:
    756             if (Rd.r != 0xF) {
    757               opcode << "sub";
    758             } else {
    759               if (S != 1U) {
    760                 opcode << "UNKNOWN CMP-" << S;
    761                 break;
    762               }
    763               opcode << "cmp";
    764               S = 0;  // don't print 's'
    765             }
    766             break;
    767           case 0xE: opcode << "rsb"; break;
    768           default: opcode << "UNKNOWN DPSR-" << op3; break;
    769         }
    770 
    771         if (S == 1) {
    772           opcode << "s";
    773         }
    774         opcode << ".w";
    775 
    776         if (Rd.r != 0xF) {
    777           args << Rd << ", ";
    778         }
    779         if (Rn.r != 0xF) {
    780           args << Rn << ", ";
    781         }
    782         args << Rm;
    783 
    784         // Shift operand.
    785         bool noShift = (imm5 == 0 && shift_type != 0x3);
    786         if (!noShift) {
    787           args << ", ";
    788           switch (shift_type) {
    789             case 0x0: args << "lsl"; break;
    790             case 0x1: args << "lsr"; break;
    791             case 0x2: args << "asr"; break;
    792             case 0x3:
    793               if (imm5 == 0) {
    794                 args << "rrx";
    795               } else {
    796                 args << "ror #" << imm5;
    797               }
    798               break;
    799           }
    800           if (shift_type != 0x3 /* rrx */) {
    801             args << StringPrintf(" #%d", (0 != imm5 || 0 == shift_type) ? imm5 : 32);
    802           }
    803         }
    804 
    805       } else if ((op2 & 0x40) == 0x40) {  // 1xx xxxx
    806         // Co-processor instructions
    807         // |111|1|11|000000|0000|1111|1100|000|0  |0000|
    808         // |5 3|2|10|987654|3  0|54 2|10 8|7 5|4  |   0|
    809         // |---|-|--|------|----|----|----|---|---|----|
    810         // |332|2|22|222222|1111|1111|1100|000|0  |0000|
    811         // |1 9|8|76|543210|9  6|54 2|10 8|7 5|4  |   0|
    812         // |---|-|--|------|----|----|----|---|---|----|
    813         // |111| |11| op3  | Rn |    |copr|   |op4|    |
    814         uint32_t op3 = (instr >> 20) & 0x3F;
    815         uint32_t coproc = (instr >> 8) & 0xF;
    816         uint32_t op4 = (instr >> 4) & 0x1;
    817 
    818         if (coproc == 0xA || coproc == 0xB) {   // 101x
    819           if (op3 < 0x20 && (op3 & ~5) != 0) {     // 0xxxxx and not 000x0x
    820             // Extension register load/store instructions
    821             // |1111|110|00000|0000|1111|110|0|00000000|
    822             // |5  2|1 9|87654|3  0|5  2|1 9|8|7      0|
    823             // |----|---|-----|----|----|---|-|--------|
    824             // |3322|222|22222|1111|1111|110|0|00000000|
    825             // |1  8|7 5|4   0|9  6|5  2|1 9|8|7      0|
    826             // |----|---|-----|----|----|---|-|--------|
    827             // |1110|110|PUDWL| Rn | Vd |101|S|  imm8  |
    828             uint32_t P = (instr >> 24) & 1;
    829             uint32_t U = (instr >> 23) & 1;
    830             uint32_t W = (instr >> 21) & 1;
    831             if (P == U && W == 1) {
    832               opcode << "UNDEFINED";
    833             } else {
    834               uint32_t L = (instr >> 20) & 1;
    835               uint32_t S = (instr >> 8) & 1;
    836               ArmRegister Rn(instr, 16);
    837               if (P == 1 && W == 0) {  // VLDR
    838                 FpRegister d(instr, 12, 22);
    839                 uint32_t imm8 = instr & 0xFF;
    840                 opcode << (L == 1 ? "vldr" : "vstr");
    841                 args << d << ", [" << Rn << ", #" << ((U == 1) ? "" : "-")
    842                      << (imm8 << 2) << "]";
    843                 if (Rn.r == 15 && U == 1) {
    844                   DumpThumb2Literal(args, instr_ptr, lo_adr, hi_adr, U, imm8 << 2, kT2LitHexLong);
    845                 }
    846               } else if (Rn.r == 13 && W == 1 && U == L) {  // VPUSH/VPOP
    847                 opcode << (L == 1 ? "vpop" : "vpush");
    848                 args << FpRegisterRange(instr);
    849               } else {  // VLDM
    850                 opcode << (L == 1 ? "vldm" : "vstm");
    851                 args << Rn << ((W == 1) ? "!" : "") << ", "
    852                      << FpRegisterRange(instr);
    853               }
    854               opcode << (S == 1 ? ".f64" : ".f32");
    855             }
    856           } else if ((op3 >> 1) == 2) {      // 00010x
    857             if ((instr & 0xD0) == 0x10) {
    858               // 64bit transfers between ARM core and extension registers.
    859               uint32_t L = (instr >> 20) & 1;
    860               uint32_t S = (instr >> 8) & 1;
    861               ArmRegister Rt2(instr, 16);
    862               ArmRegister Rt(instr, 12);
    863               FpRegister m(instr, 0, 5);
    864               opcode << "vmov" << (S ? ".f64" : ".f32");
    865               if (L == 1) {
    866                 args << Rt << ", " << Rt2 << ", ";
    867               }
    868               if (S) {
    869                 args << m;
    870               } else {
    871                 args << m << ", " << FpRegister(m, 1);
    872               }
    873               if (L == 0) {
    874                 args << ", " << Rt << ", " << Rt2;
    875               }
    876               if (Rt.r == 15 || Rt.r == 13 || Rt2.r == 15 || Rt2.r == 13 ||
    877                   (S == 0 && m.r == 31) || (L == 1 && Rt.r == Rt2.r)) {
    878                 args << " (UNPREDICTABLE)";
    879               }
    880             }
    881           } else if ((op3 >> 4) == 2 && op4 == 0) {     // 10xxxx, op = 0
    882             // fp data processing
    883             // VMLA, VMLS, VMUL, VNMUL, VADD, VSUB, VDIV, VMOV, ...
    884             // |1111|1100|0|0|00|0000|1111|110|0|0|0|0|0|0000|
    885             // |5  2|1  8|7|6|54|3  0|5  2|1 9|8|7|6|5|4|3  0|
    886             // |----|----|-|-|--|----|----|---|-|-|-|-|-|----|
    887             // |3322|2222|2|2|22|1111|1111|110|0|0|0|0|0|0000|
    888             // |1  8|7  4|3|2|10|9  6|5  2|1 9|8|7|6|5|4|3  0|
    889             // |----|----|-|-|--|----|----|---|-|-|-|-|-|----|
    890             // |1110|1110|  op3 | Vn | Vd |101|S|N|Q|M|0| Vm |
    891             // |1110|1110|0|D|00| Vn | Vd |101|S|N|0|M|0| Vm | VMLA
    892             // |1110|1110|0|D|00| Vn | Vd |101|S|N|1|M|0| Vm | VMLS
    893             // |1110|1110|0|D|10| Vn | Vd |101|S|N|0|M|0| Vm | VMUL
    894             // |1110|1110|0|D|10| Vn | Vd |101|S|N|1|M|0| Vm | VNMUL
    895             // |1110|1110|0|D|11| Vn | Vd |101|S|N|0|M|0| Vm | VADD
    896             // |1110|1110|0|D|11| Vn | Vd |101|S|N|1|M|0| Vm | VSUB
    897             // |1110|1110|1|D|00| Vn | Vd |101|S|N|0|M|0| Vm | VDIV
    898             // |1110|1110|1|D|11| iH | Vd |101|S|0|0|0|0| iL | VMOV (imm)
    899             // |1110|1110|1|D|11|op5 | Vd |101|S|.|1|M|0| Vm | ... (see below)
    900             uint32_t S = (instr >> 8) & 1;
    901             uint32_t Q = (instr >> 6) & 1;
    902             FpRegister d(instr, 12, 22);
    903             FpRegister n(instr, 16, 7);
    904             FpRegister m(instr, 0, 5);
    905             if ((op3 & 0xB) == 0) {  // 100x00
    906               opcode << (Q == 0 ? "vmla" : "vmls") << (S != 0 ? ".f64" : ".f32");
    907               args << d << ", " << n << ", " << m;
    908             } else if ((op3 & 0xB) == 0x2) {  // 100x10
    909               opcode << (Q == 0 ? "vmul" : "vnmul") << (S != 0 ? ".f64" : ".f32");
    910               args << d << ", " << n << ", " << m;
    911             } else if ((op3 & 0xB) == 0x3) {  // 100x11
    912               opcode << (Q == 0 ? "vadd" : "vsub") << (S != 0 ? ".f64" : ".f32");
    913               args << d << ", " << n << ", " << m;
    914             } else if ((op3 & 0xB) == 0x8 && Q == 0) {  // 101x00, Q == 0
    915               opcode << "vdiv" << (S != 0 ? ".f64" : ".f32");
    916               args << d << ", " << n << ", " << m;
    917             } else if ((op3 & 0xB) == 0xB && Q == 0) {  // 101x11, Q == 0
    918               uint32_t imm8 = ((instr & 0xf0000u) >> 12) | (instr & 0xfu);
    919               opcode << "vmov" << (S != 0 ? ".f64" : ".f32");
    920               args << d << ", " << (S != 0 ? StringPrintf("0x%016" PRIx64, VFPExpand64(imm8))
    921                                            : StringPrintf("0x%08x", VFPExpand32(imm8)));
    922               if ((instr & 0xa0) != 0) {
    923                 args << " (UNPREDICTABLE)";
    924               }
    925             } else if ((op3 & 0xB) == 0xB && Q == 1) {  // 101x11, Q == 1
    926               // VNEG, VSQRT, VCMP, VCMPE, VCVT (floating-point conversion)
    927               // |1111|1100|0|0|00|0000|1111|110|0|0 |0|0|0|0000|
    928               // |5  2|1  8|7|6|54|3  0|5  2|1 9|8|7 |6|5|4|3  0|
    929               // |----|----|-|-|--|----|----|---|-|- |-|-|-|----|
    930               // |3322|2222|2|2|22|1111|1111|110|0|0 |0|0|0|0000|
    931               // |1  8|7  4|3|2|10|9  6|5  2|1 9|8|7 |6|5|4|3  0|
    932               // |----|----|-|-|--|----|----|---|-|- |-|-|-|----|
    933               // |1110|1110|1|D|11|0000| Vd |101|S|0 |1|M|0| Vm | VMOV (reg)
    934               // |1110|1110|1|D|11|0000| Vd |101|S|1 |1|M|0| Vm | VABS
    935               // |1110|1110|1|D|11|0001| Vd |101|S|0 |1|M|0| Vm | VNEG
    936               // |1110|1110|1|D|11|0001| Vd |101|S|1 |1|M|0| Vm | VSQRT
    937               // |1110|1110|1|D|11|0100| Vd |101|S|op|1|M|0| Vm | VCMP
    938               // |1110|1110|1|D|11|0101| Vd |101|S|op|1|0|0|0000| VCMPE
    939               // |1110|1110|1|D|11|op5 | Vd |101|S|op|1|M|0| Vm | VCVT
    940               uint32_t op5 = (instr >> 16) & 0xF;
    941               uint32_t op = (instr >> 7) & 1;
    942               // Register types in VCVT instructions rely on the combination of op5 and S.
    943               FpRegister Dd(instr, 12, 22, 1);
    944               FpRegister Sd(instr, 12, 22, 0);
    945               FpRegister Dm(instr, 0, 5, 1);
    946               FpRegister Sm(instr, 0, 5, 0);
    947               if (op5 == 0) {
    948                 opcode << (op == 0 ? "vmov" : "vabs") << (S != 0 ? ".f64" : ".f32");
    949                 args << d << ", " << m;
    950               } else if (op5 == 1) {
    951                 opcode << (op != 0 ? "vsqrt" : "vneg") << (S != 0 ? ".f64" : ".f32");
    952                 args << d << ", " << m;
    953               } else if (op5 == 4) {
    954                 opcode << "vcmp" << (S != 0 ? ".f64" : ".f32");
    955                 args << d << ", " << m;
    956                 if (op != 0) {
    957                   args << " (quiet nan)";
    958                 }
    959               } else if (op5 == 5) {
    960                 opcode << "vcmpe" << (S != 0 ? ".f64" : ".f32");
    961                 args << d << ", #0.0";
    962                 if (op != 0) {
    963                   args << " (quiet nan)";
    964                 }
    965                 if ((instr & 0x2f) != 0) {
    966                   args << " (UNPREDICTABLE)";
    967                 }
    968               } else if (op5 == 0xD) {
    969                 if (S == 1) {
    970                   // vcvt{r}.s32.f64
    971                   opcode << "vcvt" << (op == 0 ? "r" : "") << ".s32.f64";
    972                   args << Sd << ", " << Dm;
    973                 } else {
    974                   // vcvt{r}.s32.f32
    975                   opcode << "vcvt" << (op == 0 ? "r" : "") << ".s32.f32";
    976                   args << Sd << ", " << Sm;
    977                 }
    978               } else if (op5 == 0xC) {
    979                 if (S == 1) {
    980                   // vcvt{r}.u32.f64
    981                   opcode << "vcvt" << (op == 0 ? "r" : "") << ".u32.f64";
    982                   args << Sd << ", " << Dm;
    983                 } else {
    984                   // vcvt{r}.u32.f32
    985                   opcode << "vcvt" << (op == 0 ? "r" : "") << ".u32.f32";
    986                   args << Sd << ", " << Sm;
    987                 }
    988               } else if (op5 == 0x8) {
    989                 if (S == 1) {
    990                   // vcvt.f64.<Tm>
    991                   opcode << "vcvt.f64." << (op == 0 ? "u" : "s") << "32";
    992                   args << Dd << ", " << Sm;
    993                 } else {
    994                   // vcvt.f32.<Tm>
    995                   opcode << "vcvt.f32." << (op == 0 ? "u" : "s") << "32";
    996                   args << Sd << ", " << Sm;
    997                 }
    998               } else if (op5 == 0x7) {
    999                 if (op == 1) {
   1000                   if (S == 1) {
   1001                     // vcvt.f64.f32
   1002                     opcode << "vcvt.f64.f32";
   1003                     args << Dd << ", " << Sm;
   1004                   } else {
   1005                     // vcvt.f32.f64
   1006                     opcode << "vcvt.f32.f64";
   1007                     args << Sd << ", " << Dm;
   1008                   }
   1009                 }
   1010               } else if ((op5 & 0xa) == 0xa) {
   1011                 opcode << "vcvt";
   1012                 args << "[undecoded: floating <-> fixed]";
   1013               }
   1014             }
   1015           } else if ((op3 >> 4) == 2 && op4 == 1) {     // 10xxxx, op = 1
   1016             if (coproc == 10 && (op3 & 0xE) == 0) {
   1017               // VMOV (between ARM core register and single-precision register)
   1018               // |1111|1100|000|0 |0000|1111|1100|0|00|0|0000|
   1019               // |5   |1  8|7 5|4 |3  0|5  2|1  8|7|65|4|3  0|
   1020               // |----|----|---|- |----|----|----|-|--|-|----|
   1021               // |3322|2222|222|2 |1111|1111|1100|0|00|0|0000|
   1022               // |1  8|7  4|3 1|0 |9  6|5  2|1  8|7|65|4|3  0|
   1023               // |----|----|---|- |----|----|----|-|--|-|----|
   1024               // |1110|1110|000|op| Vn | Rt |1010|N|00|1|0000|
   1025               uint32_t op = op3 & 1;
   1026               ArmRegister Rt(instr, 12);
   1027               FpRegister n(instr, 16, 7);
   1028               opcode << "vmov.f32";
   1029               if (op) {
   1030                 args << Rt << ", " << n;
   1031               } else {
   1032                 args << n << ", " << Rt;
   1033               }
   1034               if (Rt.r == 13 || Rt.r == 15 || (instr & 0x6F) != 0) {
   1035                 args << " (UNPREDICTABLE)";
   1036               }
   1037             } else if (coproc == 10 && op3 == 0x2F) {
   1038               // VMRS
   1039               // |1111|11000000|0000|1111|1100|000|0|0000|
   1040               // |5   |1      4|3  0|5  2|1  8|7 5|4|3  0|
   1041               // |----|--------|----|----|----|---|-|----|
   1042               // |3322|22222222|1111|1111|1100|000|0|0000|
   1043               // |1  8|7      0|9  6|5  2|1  8|7 5|4|3  0|
   1044               // |----|--------|----|----|----|---|-|----|
   1045               // |1110|11101111|reg | Rt |1010|000|1|0000| - last 7 0s are (0)
   1046               uint32_t spec_reg = (instr >> 16) & 0xF;
   1047               ArmRegister Rt(instr, 12);
   1048               opcode << "vmrs";
   1049               if (spec_reg == 1) {
   1050                 if (Rt.r == 15) {
   1051                   args << "APSR_nzcv, FPSCR";
   1052                 } else if (Rt.r == 13) {
   1053                   args << Rt << ", FPSCR (UNPREDICTABLE)";
   1054                 } else {
   1055                   args << Rt << ", FPSCR";
   1056                 }
   1057               } else {
   1058                 args << "(PRIVILEGED)";
   1059               }
   1060             } else if (coproc == 11 && (op3 & 0x9) != 8) {
   1061               // VMOV (ARM core register to scalar or vice versa; 8/16/32-bit)
   1062             }
   1063           }
   1064         }
   1065       }
   1066       break;
   1067     case 2:
   1068       if ((instr & 0x8000) == 0 && (op2 & 0x20) == 0) {
   1069         // Data-processing (modified immediate)
   1070         // |111|11|10|0000|0|0000|1|111|1100|00000000|
   1071         // |5 3|21|09|8765|4|3  0|5|4 2|10 8|7 5    0|
   1072         // |---|--|--|----|-|----|-|---|----|--------|
   1073         // |332|22|22|2222|2|1111|1|111|1100|00000000|
   1074         // |1 9|87|65|4321|0|9  6|5|4 2|10 8|7 5    0|
   1075         // |---|--|--|----|-|----|-|---|----|--------|
   1076         // |111|10|i0| op3|S| Rn |0|iii| Rd |iiiiiiii|
   1077         //  111 10 x0 xxxx x xxxx opxxx xxxx xxxxxxxx
   1078         uint32_t i = (instr >> 26) & 1;
   1079         uint32_t op3 = (instr >> 21) & 0xF;
   1080         uint32_t S = (instr >> 20) & 1;
   1081         ArmRegister Rn(instr, 16);
   1082         uint32_t imm3 = (instr >> 12) & 7;
   1083         ArmRegister Rd(instr, 8);
   1084         uint32_t imm8 = instr & 0xFF;
   1085         int32_t imm32 = (i << 11) | (imm3 << 8) | imm8;
   1086         if (Rn.r == 0xF && (op3 == 0x2 || op3 == 0x3)) {
   1087           if (op3 == 0x2) {
   1088             opcode << "mov";
   1089             if (S == 1) {
   1090               opcode << "s";
   1091             }
   1092             opcode << ".w";
   1093           } else {
   1094             opcode << "mvn";
   1095             if (S == 1) {
   1096               opcode << "s";
   1097             }
   1098           }
   1099           args << Rd << ", #" << ThumbExpand(imm32);
   1100         } else if (Rd.r == 0xF && S == 1 &&
   1101                    (op3 == 0x0 || op3 == 0x4 || op3 == 0x8 || op3 == 0xD)) {
   1102           if (op3 == 0x0) {
   1103             opcode << "tst";
   1104           } else if (op3 == 0x4) {
   1105             opcode << "teq";
   1106           } else if (op3 == 0x8) {
   1107             opcode << "cmn.w";
   1108           } else {
   1109             opcode << "cmp.w";
   1110           }
   1111           args << Rn << ", #" << ThumbExpand(imm32);
   1112         } else {
   1113           switch (op3) {
   1114             case 0x0: opcode << "and"; break;
   1115             case 0x1: opcode << "bic"; break;
   1116             case 0x2: opcode << "orr"; break;
   1117             case 0x3: opcode << "orn"; break;
   1118             case 0x4: opcode << "eor"; break;
   1119             case 0x8: opcode << "add"; break;
   1120             case 0xA: opcode << "adc"; break;
   1121             case 0xB: opcode << "sbc"; break;
   1122             case 0xD: opcode << "sub"; break;
   1123             case 0xE: opcode << "rsb"; break;
   1124             default: opcode << "UNKNOWN DPMI-" << op3; break;
   1125           }
   1126           if (S == 1) {
   1127             opcode << "s";
   1128           }
   1129           args << Rd << ", " << Rn << ", #" << ThumbExpand(imm32);
   1130         }
   1131       } else if ((instr & 0x8000) == 0 && (op2 & 0x20) != 0) {
   1132         // Data-processing (plain binary immediate)
   1133         // |111|11|10|00000|0000|1|111110000000000|
   1134         // |5 3|21|09|87654|3  0|5|4   0    5    0|
   1135         // |---|--|--|-----|----|-|---------------|
   1136         // |332|22|22|22222|1111|1|111110000000000|
   1137         // |1 9|87|65|43210|9  6|5|4   0    5    0|
   1138         // |---|--|--|-----|----|-|---------------|
   1139         // |111|10|x1| op3 | Rn |0|xxxxxxxxxxxxxxx|
   1140         uint32_t op3 = (instr >> 20) & 0x1F;
   1141         switch (op3) {
   1142           case 0x00: case 0x0A: {
   1143             // ADD/SUB.W Rd, Rn #imm12 - 111 10 i1 0101 0 nnnn 0 iii dddd iiiiiiii
   1144             ArmRegister Rd(instr, 8);
   1145             ArmRegister Rn(instr, 16);
   1146             uint32_t i = (instr >> 26) & 1;
   1147             uint32_t imm3 = (instr >> 12) & 0x7;
   1148             uint32_t imm8 = instr & 0xFF;
   1149             uint32_t imm12 = (i << 11) | (imm3 << 8) | imm8;
   1150             if (Rn.r != 0xF) {
   1151               opcode << (op3 == 0 ? "addw" : "subw");
   1152               args << Rd << ", " << Rn << ", #" << imm12;
   1153             } else {
   1154               opcode << "adr";
   1155               args << Rd << ", ";
   1156               DumpBranchTarget(args, instr_ptr + 4, (op3 == 0) ? imm12 : -imm12);
   1157             }
   1158             break;
   1159           }
   1160           case 0x04: case 0x0C: {
   1161             // MOVW/T Rd, #imm16     - 111 10 i0 0010 0 iiii 0 iii dddd iiiiiiii
   1162             ArmRegister Rd(instr, 8);
   1163             uint32_t i = (instr >> 26) & 1;
   1164             uint32_t imm3 = (instr >> 12) & 0x7;
   1165             uint32_t imm8 = instr & 0xFF;
   1166             uint32_t Rn = (instr >> 16) & 0xF;
   1167             uint32_t imm16 = (Rn << 12) | (i << 11) | (imm3 << 8) | imm8;
   1168             opcode << (op3 == 0x04 ? "movw" : "movt");
   1169             args << Rd << ", #" << imm16;
   1170             break;
   1171           }
   1172           case 0x16: case 0x14: case 0x1C: {
   1173             // BFI Rd, Rn, #lsb, #width - 111 10 0 11 011 0 nnnn 0 iii dddd ii 0 iiiii
   1174             // SBFX Rd, Rn, #lsb, #width - 111 10 0 11 010 0 nnnn 0 iii dddd ii 0 iiiii
   1175             // UBFX Rd, Rn, #lsb, #width - 111 10 0 11 110 0 nnnn 0 iii dddd ii 0 iiiii
   1176             ArmRegister Rd(instr, 8);
   1177             ArmRegister Rn(instr, 16);
   1178             uint32_t msb = instr & 0x1F;
   1179             uint32_t imm2 = (instr >> 6) & 0x3;
   1180             uint32_t imm3 = (instr >> 12) & 0x7;
   1181             uint32_t lsb = (imm3 << 2) | imm2;
   1182             uint32_t width = msb - lsb + 1;
   1183             if (op3 == 0x16) {
   1184               if (Rn.r != 0xF) {
   1185                 opcode << "bfi";
   1186                 args << Rd << ", " << Rn << ", #" << lsb << ", #" << width;
   1187               } else {
   1188                 opcode << "bfc";
   1189                 args << Rd << ", #" << lsb << ", #" << width;
   1190               }
   1191             } else {
   1192               opcode << ((op3 & 0x8) != 0u ? "ubfx" : "sbfx");
   1193               args << Rd << ", " << Rn << ", #" << lsb << ", #" << width;
   1194               if (Rd.r == 13 || Rd.r == 15 || Rn.r == 13 || Rn.r == 15 ||
   1195                   (instr & 0x04000020) != 0u) {
   1196                 args << " (UNPREDICTABLE)";
   1197               }
   1198             }
   1199             break;
   1200           }
   1201           default:
   1202             break;
   1203         }
   1204       } else {
   1205         // Branches and miscellaneous control
   1206         // |111|11|1000000|0000|1|111|1100|00000000|
   1207         // |5 3|21|0987654|3  0|5|4 2|10 8|7 5    0|
   1208         // |---|--|-------|----|-|---|----|--------|
   1209         // |332|22|2222222|1111|1|111|1100|00000000|
   1210         // |1 9|87|6543210|9  6|5|4 2|10 8|7 5    0|
   1211         // |---|--|-------|----|-|---|----|--------|
   1212         // |111|10| op2   |    |1|op3|op4 |        |
   1213 
   1214         uint32_t op3 = (instr >> 12) & 7;
   1215         // uint32_t op4 = (instr >> 8) & 0xF;
   1216         switch (op3) {
   1217           case 0:
   1218             if ((op2 & 0x38) != 0x38) {
   1219               // Conditional branch
   1220               // |111|11|1|0000|000000|1|1|1 |1|1 |10000000000|
   1221               // |5 3|21|0|9876|543  0|5|4|3 |2|1 |0    5    0|
   1222               // |---|--|-|----|------|-|-|--|-|--|-----------|
   1223               // |332|22|2|2222|221111|1|1|1 |1|1 |10000000000|
   1224               // |1 9|87|6|5432|109  6|5|4|3 |2|1 |0    5    0|
   1225               // |---|--|-|----|------|-|-|--|-|--|-----------|
   1226               // |111|10|S|cond| imm6 |1|0|J1|0|J2| imm11     |
   1227               uint32_t S = (instr >> 26) & 1;
   1228               uint32_t J2 = (instr >> 11) & 1;
   1229               uint32_t J1 = (instr >> 13) & 1;
   1230               uint32_t imm6 = (instr >> 16) & 0x3F;
   1231               uint32_t imm11 = instr & 0x7FF;
   1232               uint32_t cond = (instr >> 22) & 0xF;
   1233               int32_t imm32 = (S << 20) |  (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
   1234               imm32 = (imm32 << 11) >> 11;  // sign extend 21bit immediate
   1235               opcode << "b";
   1236               DumpCond(opcode, cond);
   1237               opcode << ".w";
   1238               DumpBranchTarget(args, instr_ptr + 4, imm32);
   1239             } else if (op2 == 0x3B) {
   1240               // Miscellaneous control instructions
   1241               uint32_t op5 = (instr >> 4) & 0xF;
   1242               switch (op5) {
   1243                 case 4: opcode << "dsb"; DumpMemoryDomain(args, instr & 0xF); break;
   1244                 case 5: opcode << "dmb"; DumpMemoryDomain(args, instr & 0xF); break;
   1245                 case 6: opcode << "isb"; DumpMemoryDomain(args, instr & 0xF); break;
   1246               }
   1247             }
   1248             break;
   1249           case 2:
   1250             if ((op2 & 0x38) == 0x38) {
   1251               if (op2 == 0x7F) {
   1252                 opcode << "udf";
   1253               }
   1254               break;
   1255             }
   1256             FALLTHROUGH_INTENDED;  // Else deliberate fall-through to B.
   1257           case 1: case 3: {
   1258             // B
   1259             // |111|11|1|0000|000000|11|1 |1|1 |10000000000|
   1260             // |5 3|21|0|9876|543  0|54|3 |2|1 |0    5    0|
   1261             // |---|--|-|----|------|--|--|-|--|-----------|
   1262             // |332|22|2|2222|221111|11|1 |1|1 |10000000000|
   1263             // |1 9|87|6|5  2|10   6|54|3 |2|1 |0    5    0|
   1264             // |---|--|-|----|------|--|--|-|--|-----------|
   1265             // |111|10|S|cond| imm6 |10|J1|0|J2| imm11     |
   1266             // |111|10|S| imm10     |10|J1|1|J2| imm11     |
   1267             uint32_t S = (instr >> 26) & 1;
   1268             uint32_t cond = (instr >> 22) & 0xF;
   1269             uint32_t J2 = (instr >> 11) & 1;
   1270             uint32_t form = (instr >> 12) & 1;
   1271             uint32_t J1 = (instr >> 13) & 1;
   1272             uint32_t imm10 = (instr >> 16) & 0x3FF;
   1273             uint32_t imm6  = (instr >> 16) & 0x3F;
   1274             uint32_t imm11 = instr & 0x7FF;
   1275             opcode << "b";
   1276             int32_t imm32;
   1277             if (form == 0) {
   1278               DumpCond(opcode, cond);
   1279               imm32 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
   1280               imm32 = (imm32 << 11) >> 11;  // sign extend 21 bit immediate.
   1281             } else {
   1282               uint32_t I1 = (J1 ^ S) ^ 1;
   1283               uint32_t I2 = (J2 ^ S) ^ 1;
   1284               imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
   1285               imm32 = (imm32 << 7) >> 7;  // sign extend 25 bit immediate.
   1286             }
   1287             opcode << ".w";
   1288             DumpBranchTarget(args, instr_ptr + 4, imm32);
   1289             break;
   1290           }
   1291           case 4: case 6: case 5: case 7: {
   1292             // BL, BLX (immediate)
   1293             // |111|11|1|0000000000|11|1 |1|1 |10000000000|
   1294             // |5 3|21|0|9876543  0|54|3 |2|1 |0    5    0|
   1295             // |---|--|-|----------|--|--|-|--|-----------|
   1296             // |332|22|2|2222221111|11|1 |1|1 |10000000000|
   1297             // |1 9|87|6|5    0   6|54|3 |2|1 |0    5    0|
   1298             // |---|--|-|----------|--|--|-|--|-----------|
   1299             // |111|10|S| imm10    |11|J1|L|J2| imm11     |
   1300             uint32_t S = (instr >> 26) & 1;
   1301             uint32_t J2 = (instr >> 11) & 1;
   1302             uint32_t L = (instr >> 12) & 1;
   1303             uint32_t J1 = (instr >> 13) & 1;
   1304             uint32_t imm10 = (instr >> 16) & 0x3FF;
   1305             uint32_t imm11 = instr & 0x7FF;
   1306             if (L == 0) {
   1307               opcode << "bx";
   1308             } else {
   1309               opcode << "blx";
   1310             }
   1311             uint32_t I1 = ~(J1 ^ S);
   1312             uint32_t I2 = ~(J2 ^ S);
   1313             int32_t imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
   1314             imm32 = (imm32 << 8) >> 8;  // sign extend 24 bit immediate.
   1315             DumpBranchTarget(args, instr_ptr + 4, imm32);
   1316             break;
   1317           }
   1318         }
   1319       }
   1320       break;
   1321     case 3:
   1322       switch (op2) {
   1323         case 0x07: case 0x0F: case 0x17: case 0x1F: {  // Explicitly UNDEFINED, A6.3.
   1324           opcode << "UNDEFINED";
   1325           break;
   1326         }
   1327         case 0x06: case 0x0E: {  // "Store single data item" undefined opcodes, A6.3.10.
   1328           opcode << "UNDEFINED [store]";
   1329           break;
   1330         }
   1331         case 0x15: case 0x1D: {  // "Load word" undefined opcodes, A6.3.7.
   1332           opcode << "UNDEFINED [load]";
   1333           break;
   1334         }
   1335         case 0x10: case 0x12: case 0x14: case 0x16: case 0x18: case 0x1A: case 0x1C: case 0x1E: {
   1336           opcode << "UNKNOWN " << op2 << " [SIMD]";
   1337           break;
   1338         }
   1339         case 0x01: case 0x00: case 0x09: case 0x08:   // {LD,ST}RB{,T}
   1340         case 0x03: case 0x02: case 0x0B: case 0x0A:   // {LD,ST}RH{,T}
   1341         case 0x05: case 0x04: case 0x0D: case 0x0C:   // {LD,ST}R{,T}
   1342         case 0x11:            case 0x19:              // LDRSB{,T} (no signed store)
   1343         case 0x13:            case 0x1B: {            // LDRSH{,T} (no signed store)
   1344           // Load:
   1345           // (Store is the same except that l==0 and always s==0 below.)
   1346           //                       00s.whl (sign, word, half, load)
   1347           // LDR{S}B  imm12: 11111|00s1001| Rn | Rt |imm12             (0x09)
   1348           // LDR{S}B   imm8: 11111|00s0001| Rn | Rt |1PUW|imm8         (0x01)
   1349           // LDR{S}BT  imm8: 11111|00s0001| Rn | Rt |1110|imm8         (0x01)
   1350           // LDR{S}B    lit: 11111|00sU001|1111| Rt |imm12             (0x01/0x09)
   1351           // LDR{S}B    reg: 11111|00s0001| Rn | Rt |000000|imm2| Rm   (0x01)
   1352           // LDR{S}H  imm12: 11111|00s1011| Rn | Rt |imm12             (0x0B)
   1353           // LDR{S}H   imm8: 11111|00s0011| Rn | Rt |1PUW|imm8         (0x03)
   1354           // LDR{S}HT  imm8: 11111|00s0011| Rn | Rt |1110|imm8         (0x03)
   1355           // LDR{S}H    lit: 11111|00sU011|1111| Rt |imm12             (0x03/0x0B)
   1356           // LDR{S}H    reg: 11111|00s0011| Rn | Rt |000000|imm2| Rm   (0x03)
   1357           // LDR      imm12: 11111|0001101| Rn | Rt |imm12             (0x0D)
   1358           // LDR       imm8: 11111|0000101| Rn | Rt |1PUW|imm8         (0x05)
   1359           // LDRT      imm8: 11111|0000101| Rn | Rt |1110|imm8         (0x05)
   1360           // LDR        lit: 11111|000U101|1111| Rt |imm12             (0x05/0x0D)
   1361           // LDR        reg: 11111|0000101| Rn | Rt |000000|imm2| Rm   (0x05)
   1362           //
   1363           // If Rt == 15, instead of load we have preload:
   1364           // PLD{W}   imm12: 11111|00010W1| Rn |1111|imm12             (0x09/0x0B)
   1365           // PLD{W}    imm8: 11111|00000W1| Rn |1111|1100|imm8         (0x01/0x03); -imm8
   1366           // PLD        lit: 11111|000U001|1111|1111|imm12             (0x01/0x09)
   1367           // PLD{W}     reg: 11111|00000W1| Rn |1111|000000|imm2| Rm   (0x01/0x03)
   1368           // PLI      imm12: 11111|0011001| Rn |1111|imm12             (0x19)
   1369           // PLI       imm8: 11111|0010001| Rn |1111|1100|imm8         (0x11); -imm8
   1370           // PLI        lit: 11111|001U001|1111|1111|imm12             (0x01/0x09)
   1371           // PLI        reg: 11111|0010001| Rn |1111|000000|imm2| Rm   (0x01/0x03)
   1372 
   1373           bool is_load = HasBitSet(instr, 20);
   1374           bool is_half = HasBitSet(instr, 21);  // W for PLD/PLDW.
   1375           bool is_word = HasBitSet(instr, 22);
   1376           bool is_signed = HasBitSet(instr, 24);
   1377           ArmRegister Rn(instr, 16);
   1378           ArmRegister Rt(instr, 12);
   1379           uint32_t imm12 = instr & 0xFFF;
   1380           uint32_t U = (instr >> 23) & 1;  // U for imm12
   1381           uint32_t imm8 = instr & 0xFF;
   1382           uint32_t op4 = (instr >> 8) & 0xF;  // 1PUW for imm8
   1383           if (Rt.r == PC && is_load && !is_word) {
   1384             // PLD, PLDW, PLI
   1385             const char* pld_pli = (is_signed ? "pli" : "pld");
   1386             const char* w = (is_half ? "w" : "");
   1387             if (is_signed && !is_half) {
   1388               opcode << "UNDEFINED [PLI+W]";
   1389             } else if (Rn.r == PC || U != 0u) {
   1390               opcode << pld_pli << w;
   1391               args << "[" << Rn << ", #" << (U != 0u ? "" : "-") << imm12 << "]";
   1392               if (Rn.r == PC && is_half) {
   1393                 args << " (UNPREDICTABLE)";
   1394               }
   1395             } else if ((instr & 0xFC0) == 0) {
   1396               opcode << pld_pli << w;
   1397               RmLslImm2 Rm(instr);
   1398               args << "[" << Rn << ", " << Rm << "]";
   1399             } else if (op4 == 0xC) {
   1400               opcode << pld_pli << w;
   1401               args << "[" << Rn << ", #-" << imm8 << "]";
   1402             } else {
   1403               opcode << "UNDEFINED [~" << pld_pli << "]";
   1404             }
   1405             break;
   1406           }
   1407           const char* ldr_str = is_load ? "ldr" : "str";
   1408           const char* sign = is_signed ? "s" : "";
   1409           const char* type = is_word ? "" : is_half ? "h" : "b";
   1410           bool unpred = (Rt.r == SP && !is_word) || (Rt.r == PC && !is_load);
   1411           if (Rn.r == PC && !is_load) {
   1412             opcode << "UNDEFINED [STR-lit]";
   1413             unpred = false;
   1414           } else if (Rn.r == PC || U != 0u) {
   1415             // Load/store with imm12 (load literal if Rn.r == PC; there's no store literal).
   1416             opcode << ldr_str << sign << type << ".w";
   1417             args << Rt << ", [" << Rn << ", #" << (U != 0u ? "" : "-") << imm12 << "]";
   1418             if (Rn.r == TR && is_load) {
   1419               args << "  ; ";
   1420               Thread::DumpThreadOffset<4>(args, imm12);
   1421             } else if (Rn.r == PC) {
   1422               T2LitType lit_type[] = {
   1423                   kT2LitUByte, kT2LitUHalf, kT2LitHexWord, kT2LitInvalid,
   1424                   kT2LitUByte, kT2LitUHalf, kT2LitHexWord, kT2LitInvalid,
   1425                   kT2LitSByte, kT2LitSHalf, kT2LitInvalid, kT2LitInvalid,
   1426                   kT2LitSByte, kT2LitSHalf, kT2LitInvalid, kT2LitInvalid,
   1427               };
   1428               DCHECK_LT(op2 >> 1, arraysize(lit_type));
   1429               DCHECK_NE(lit_type[op2 >> 1], kT2LitInvalid);
   1430               DumpThumb2Literal(args, instr_ptr, lo_adr, hi_adr, U, imm12, lit_type[op2 >> 1]);
   1431             }
   1432           } else if ((instr & 0xFC0) == 0) {
   1433             opcode << ldr_str << sign << type << ".w";
   1434             RmLslImm2 Rm(instr);
   1435             args << Rt << ", [" << Rn << ", " << Rm << "]";
   1436             unpred = unpred || (Rm.rm.r == SP) || (Rm.rm.r == PC);
   1437           } else if (is_word && Rn.r == SP && imm8 == 4 && op4 == (is_load ? 0xB : 0xD)) {
   1438             opcode << (is_load ? "pop" : "push") << ".w";
   1439             args << Rn;
   1440             unpred = unpred || (Rn.r == SP);
   1441           } else if ((op4 & 5) == 0) {
   1442             opcode << "UNDEFINED [P = W = 0 for " << ldr_str << "]";
   1443             unpred = false;
   1444           } else {
   1445             uint32_t P = (instr >> 10) & 1;
   1446             U = (instr >> 9) & 1;
   1447             uint32_t W = (instr >> 8) & 1;
   1448             bool pre_index = (P != 0 && W == 1);
   1449             bool post_index = (P == 0 && W == 1);
   1450             const char* t = (P != 0 && U != 0 && W == 0) ? "t" : "";  // Unprivileged load/store?
   1451             opcode << ldr_str << sign << type << t << ".w";
   1452             args << Rt << ", [" << Rn << (post_index ? "]" : "") << ", #" << (U != 0 ? "" : "-")
   1453                 << imm8 << (post_index ? "" : "]") << (pre_index ? "!" : "");
   1454             unpred = (W != 0 && Rn.r == Rt.r);
   1455           }
   1456           if (unpred) {
   1457             args << " (UNPREDICTABLE)";
   1458           }
   1459           break;
   1460         }
   1461         case 0x29: {  // 0101001
   1462           // |111|11|1000000|0000|1111|1100|00|0 0|0000|
   1463           // |5 3|21|0     4|3  0|5  2|1  8|76|5 4|3  0|
   1464           // |---|--|-------|----|----|----|--|---|----|
   1465           // |332|22|2222222|1111|1111|1100|00|0 0|0000|
   1466           // |1 9|87|6     0|9  6|5  2|1  8|76|5 4|3  0|
   1467           // |---|--|-------|----|----|----|--|---|----|
   1468           // |111|11|0101001| Rm |1111| Rd |11|op3| Rm |
   1469           // REV   - 111 11 0101001 mmmm 1111 dddd 1000 mmmm
   1470           // REV16 - 111 11 0101001 mmmm 1111 dddd 1001 mmmm
   1471           // RBIT  - 111 11 0101001 mmmm 1111 dddd 1010 mmmm
   1472           // REVSH - 111 11 0101001 mmmm 1111 dddd 1011 mmmm
   1473           if ((instr & 0xf0c0) == 0xf080) {
   1474             uint32_t op3 = (instr >> 4) & 3;
   1475             opcode << kThumbReverseOperations[op3];
   1476             ArmRegister Rm(instr, 0);
   1477             ArmRegister Rd(instr, 8);
   1478             args << Rd << ", " << Rm;
   1479             ArmRegister Rm2(instr, 16);
   1480             if (Rm.r != Rm2.r || Rm.r == 13 || Rm.r == 15 || Rd.r == 13 || Rd.r == 15) {
   1481               args << " (UNPREDICTABLE)";
   1482             }
   1483           }  // else unknown instruction
   1484           break;
   1485         }
   1486         case 0x2B: {  // 0101011
   1487           //  CLZ - 111 11 0101011 mmmm 1111 dddd 1000 mmmm
   1488           if ((instr & 0xf0f0) == 0xf080) {
   1489             opcode << "clz";
   1490             ArmRegister Rm(instr, 0);
   1491             ArmRegister Rd(instr, 8);
   1492             args << Rd << ", " << Rm;
   1493             ArmRegister Rm2(instr, 16);
   1494             if (Rm.r != Rm2.r || Rm.r == 13 || Rm.r == 15 || Rd.r == 13 || Rd.r == 15) {
   1495               args << " (UNPREDICTABLE)";
   1496             }
   1497           }
   1498           break;
   1499         }
   1500       default:      // more formats
   1501         if ((op2 >> 4) == 2) {      // 010xxxx
   1502           // data processing (register)
   1503           if ((instr & 0x0080f0f0) == 0x0000f000) {
   1504             // LSL, LSR, ASR, ROR
   1505             uint32_t shift_op = (instr >> 21) & 3;
   1506             uint32_t S = (instr >> 20) & 1;
   1507             ArmRegister Rd(instr, 8);
   1508             ArmRegister Rn(instr, 16);
   1509             ArmRegister Rm(instr, 0);
   1510             opcode << kThumb2ShiftOperations[shift_op] << (S != 0 ? "s" : "");
   1511             args << Rd << ", " << Rn << ", " << Rm;
   1512           }
   1513         } else if ((op2 >> 3) == 6) {       // 0110xxx
   1514           // Multiply, multiply accumulate, and absolute difference
   1515           op1 = (instr >> 20) & 0x7;
   1516           op2 = (instr >> 4) & 0x1;
   1517           ArmRegister Ra(instr, 12);
   1518           ArmRegister Rn(instr, 16);
   1519           ArmRegister Rm(instr, 0);
   1520           ArmRegister Rd(instr, 8);
   1521           switch (op1) {
   1522           case 0:
   1523             if (op2 == 0) {
   1524               if (Ra.r == 0xf) {
   1525                 opcode << "mul";
   1526                 args << Rd << ", " << Rn << ", " << Rm;
   1527               } else {
   1528                 opcode << "mla";
   1529                 args << Rd << ", " << Rn << ", " << Rm << ", " << Ra;
   1530               }
   1531             } else {
   1532               opcode << "mls";
   1533               args << Rd << ", " << Rn << ", " << Rm << ", " << Ra;
   1534             }
   1535             break;
   1536           case 1:
   1537           case 2:
   1538           case 3:
   1539           case 4:
   1540           case 5:
   1541           case 6:
   1542               break;        // do these sometime
   1543           }
   1544         } else if ((op2 >> 3) == 7) {       // 0111xxx
   1545           // Long multiply, long multiply accumulate, and divide
   1546           op1 = (instr >> 20) & 0x7;
   1547           op2 = (instr >> 4) & 0xf;
   1548           ArmRegister Rn(instr, 16);
   1549           ArmRegister Rm(instr, 0);
   1550           ArmRegister Rd(instr, 8);
   1551           ArmRegister RdHi(instr, 8);
   1552           ArmRegister RdLo(instr, 12);
   1553           switch (op1) {
   1554           case 0:
   1555             opcode << "smull";
   1556             args << RdLo << ", " << RdHi << ", " << Rn << ", " << Rm;
   1557             break;
   1558           case 1:
   1559             opcode << "sdiv";
   1560             args << Rd << ", " << Rn << ", " << Rm;
   1561             break;
   1562           case 2:
   1563             opcode << "umull";
   1564             args << RdLo << ", " << RdHi << ", " << Rn << ", " << Rm;
   1565             break;
   1566           case 3:
   1567             opcode << "udiv";
   1568             args << Rd << ", " << Rn << ", " << Rm;
   1569             break;
   1570           case 4:
   1571           case 5:
   1572           case 6:
   1573             break;      // TODO: when we generate these...
   1574           }
   1575         }
   1576       }
   1577       break;
   1578     default:
   1579       break;
   1580   }
   1581 
   1582   // Apply any IT-block conditions to the opcode if necessary.
   1583   if (!it_conditions_.empty()) {
   1584     opcode << it_conditions_.back();
   1585     it_conditions_.pop_back();
   1586   }
   1587   if (opcode.str().size() == 0) {
   1588     opcode << "UNKNOWN " << op2;
   1589   }
   1590 
   1591   os << FormatInstructionPointer(instr_ptr)
   1592      << StringPrintf(": %08x\t%-7s ", instr, opcode.str().c_str())
   1593      << args.str() << '\n';
   1594   return 4;
   1595 }  // NOLINT(readability/fn_size)
   1596 
   1597 size_t DisassemblerArm::DumpThumb16(std::ostream& os, const uint8_t* instr_ptr) {
   1598   uint16_t instr = ReadU16(instr_ptr);
   1599   bool is_32bit = ((instr & 0xF000) == 0xF000) || ((instr & 0xF800) == 0xE800);
   1600   if (is_32bit) {
   1601     return DumpThumb32(os, instr_ptr);
   1602   } else {
   1603     std::ostringstream opcode;
   1604     std::ostringstream args;
   1605     uint16_t opcode1 = instr >> 10;
   1606     if (opcode1 < 0x10) {
   1607       // shift (immediate), add, subtract, move, and compare
   1608       uint16_t opcode2 = instr >> 9;
   1609       switch (opcode2) {
   1610         case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7:
   1611         case 0x8: case 0x9: case 0xA: case 0xB: {
   1612           // Logical shift left     - 00 000xx iii mmm ddd
   1613           // Logical shift right    - 00 001xx iii mmm ddd
   1614           // Arithmetic shift right - 00 010xx iii mmm ddd
   1615           uint16_t imm5 = (instr >> 6) & 0x1F;
   1616           ThumbRegister rm(instr, 3);
   1617           ThumbRegister Rd(instr, 0);
   1618           if (opcode2 <= 3) {
   1619             opcode << "lsls";
   1620           } else if (opcode2 <= 7) {
   1621             opcode << "lsrs";
   1622           } else {
   1623             opcode << "asrs";
   1624           }
   1625           args << Rd << ", " << rm << ", #" << imm5;
   1626           break;
   1627         }
   1628         case 0xC: case 0xD: case 0xE: case 0xF: {
   1629           // Add register        - 00 01100 mmm nnn ddd
   1630           // Sub register        - 00 01101 mmm nnn ddd
   1631           // Add 3-bit immediate - 00 01110 iii nnn ddd
   1632           // Sub 3-bit immediate - 00 01111 iii nnn ddd
   1633           uint16_t imm3_or_Rm = (instr >> 6) & 7;
   1634           ThumbRegister Rn(instr, 3);
   1635           ThumbRegister Rd(instr, 0);
   1636           if ((opcode2 & 2) != 0 && imm3_or_Rm == 0) {
   1637             opcode << "mov";
   1638           } else {
   1639             if ((opcode2 & 1) == 0) {
   1640               opcode << "adds";
   1641             } else {
   1642               opcode << "subs";
   1643             }
   1644           }
   1645           args << Rd << ", " << Rn;
   1646           if ((opcode2 & 2) == 0) {
   1647             ArmRegister Rm(imm3_or_Rm);
   1648             args << ", " << Rm;
   1649           } else if (imm3_or_Rm != 0) {
   1650             args << ", #" << imm3_or_Rm;
   1651           }
   1652           break;
   1653         }
   1654         case 0x10: case 0x11: case 0x12: case 0x13:
   1655         case 0x14: case 0x15: case 0x16: case 0x17:
   1656         case 0x18: case 0x19: case 0x1A: case 0x1B:
   1657         case 0x1C: case 0x1D: case 0x1E: case 0x1F: {
   1658           // MOVS Rd, #imm8 - 00100 ddd iiiiiiii
   1659           // CMP  Rn, #imm8 - 00101 nnn iiiiiiii
   1660           // ADDS Rn, #imm8 - 00110 nnn iiiiiiii
   1661           // SUBS Rn, #imm8 - 00111 nnn iiiiiiii
   1662           ThumbRegister Rn(instr, 8);
   1663           uint16_t imm8 = instr & 0xFF;
   1664           switch (opcode2 >> 2) {
   1665             case 4: opcode << "movs"; break;
   1666             case 5: opcode << "cmp"; break;
   1667             case 6: opcode << "adds"; break;
   1668             case 7: opcode << "subs"; break;
   1669           }
   1670           args << Rn << ", #" << imm8;
   1671           break;
   1672         }
   1673         default:
   1674           break;
   1675       }
   1676     } else if (opcode1 == 0x10) {
   1677       // Data-processing
   1678       uint16_t opcode2 = (instr >> 6) & 0xF;
   1679       ThumbRegister rm(instr, 3);
   1680       ThumbRegister rdn(instr, 0);
   1681       opcode << kThumbDataProcessingOperations[opcode2];
   1682       args << rdn << ", " << rm;
   1683     } else if (opcode1 == 0x11) {
   1684       // Special data instructions and branch and exchange
   1685       uint16_t opcode2 = (instr >> 6) & 0x0F;
   1686       switch (opcode2) {
   1687         case 0x0: case 0x1: case 0x2: case 0x3: {
   1688           // Add low registers  - 010001 0000 xxxxxx
   1689           // Add high registers - 010001 0001/001x xxxxxx
   1690           uint16_t DN = (instr >> 7) & 1;
   1691           ArmRegister rm(instr, 3);
   1692           uint16_t Rdn = instr & 7;
   1693           ArmRegister DN_Rdn((DN << 3) | Rdn);
   1694           opcode << "add";
   1695           args << DN_Rdn << ", " << rm;
   1696           break;
   1697         }
   1698         case 0x8: case 0x9: case 0xA: case 0xB: {
   1699           // Move low registers  - 010001 1000 xxxxxx
   1700           // Move high registers - 010001 1001/101x xxxxxx
   1701           uint16_t DN = (instr >> 7) & 1;
   1702           ArmRegister rm(instr, 3);
   1703           uint16_t Rdn = instr & 7;
   1704           ArmRegister DN_Rdn((DN << 3) | Rdn);
   1705           opcode << "mov";
   1706           args << DN_Rdn << ", " << rm;
   1707           break;
   1708         }
   1709         case 0x5: case 0x6: case 0x7: {
   1710           // Compare high registers - 010001 0101/011x xxxxxx
   1711           uint16_t N = (instr >> 7) & 1;
   1712           ArmRegister rm(instr, 3);
   1713           uint16_t Rn = instr & 7;
   1714           ArmRegister N_Rn((N << 3) | Rn);
   1715           opcode << "cmp";
   1716           args << N_Rn << ", " << rm;
   1717           break;
   1718         }
   1719         case 0xC: case 0xD: case 0xE: case 0xF: {
   1720           // Branch and exchange           - 010001 110x xxxxxx
   1721           // Branch with link and exchange - 010001 111x xxxxxx
   1722           ArmRegister rm(instr, 3);
   1723           opcode << ((opcode2 & 0x2) == 0 ? "bx" : "blx");
   1724           args << rm;
   1725           break;
   1726         }
   1727         default:
   1728           break;
   1729       }
   1730     } else if (opcode1 == 0x12 || opcode1 == 0x13) {  // 01001x
   1731       const uintptr_t lo_adr = reinterpret_cast<intptr_t>(GetDisassemblerOptions()->base_address_);
   1732       const uintptr_t hi_adr = reinterpret_cast<intptr_t>(GetDisassemblerOptions()->end_address_);
   1733       ThumbRegister Rt(instr, 8);
   1734       uint16_t imm8 = instr & 0xFF;
   1735       opcode << "ldr";
   1736       args << Rt << ", [pc, #" << (imm8 << 2) << "]";
   1737       DumpThumb2Literal(args, instr_ptr, lo_adr, hi_adr, /*U*/ 1u, imm8 << 2, kT2LitHexWord);
   1738     } else if ((opcode1 >= 0x14 && opcode1 <= 0x17) ||  // 0101xx
   1739                (opcode1 >= 0x18 && opcode1 <= 0x1f) ||  // 011xxx
   1740                (opcode1 >= 0x20 && opcode1 <= 0x27)) {  // 100xxx
   1741       // Load/store single data item
   1742       uint16_t opA = (instr >> 12) & 0xF;
   1743       if (opA == 0x5) {
   1744         uint16_t opB = (instr >> 9) & 0x7;
   1745         ThumbRegister Rm(instr, 6);
   1746         ThumbRegister Rn(instr, 3);
   1747         ThumbRegister Rt(instr, 0);
   1748         switch (opB) {
   1749           case 0: opcode << "str"; break;
   1750           case 1: opcode << "strh"; break;
   1751           case 2: opcode << "strb"; break;
   1752           case 3: opcode << "ldrsb"; break;
   1753           case 4: opcode << "ldr"; break;
   1754           case 5: opcode << "ldrh"; break;
   1755           case 6: opcode << "ldrb"; break;
   1756           case 7: opcode << "ldrsh"; break;
   1757         }
   1758         args << Rt << ", [" << Rn << ", " << Rm << "]";
   1759       } else if (opA == 9) {
   1760         uint16_t opB = (instr >> 11) & 1;
   1761         ThumbRegister Rt(instr, 8);
   1762         uint16_t imm8 = instr & 0xFF;
   1763         opcode << (opB == 0 ? "str" : "ldr");
   1764         args << Rt << ", [sp, #" << (imm8 << 2) << "]";
   1765       } else {
   1766         uint16_t imm5 = (instr >> 6) & 0x1F;
   1767         uint16_t opB = (instr >> 11) & 1;
   1768         ThumbRegister Rn(instr, 3);
   1769         ThumbRegister Rt(instr, 0);
   1770         switch (opA) {
   1771           case 6:
   1772             imm5 <<= 2;
   1773             opcode << (opB == 0 ? "str" : "ldr");
   1774             break;
   1775           case 7:
   1776             imm5 <<= 0;
   1777             opcode << (opB == 0 ? "strb" : "ldrb");
   1778             break;
   1779           case 8:
   1780             imm5 <<= 1;
   1781             opcode << (opB == 0 ? "strh" : "ldrh");
   1782             break;
   1783         }
   1784         args << Rt << ", [" << Rn << ", #" << imm5 << "]";
   1785       }
   1786     } else if (opcode1 >= 0x34 && opcode1 <= 0x37) {  // 1101xx
   1787       int8_t imm8 = instr & 0xFF;
   1788       uint32_t cond = (instr >> 8) & 0xF;
   1789       opcode << "b";
   1790       DumpCond(opcode, cond);
   1791       DumpBranchTarget(args, instr_ptr + 4, (imm8 << 1));
   1792     } else if ((instr & 0xF800) == 0xA800) {
   1793       // Generate SP-relative address
   1794       ThumbRegister rd(instr, 8);
   1795       int imm8 = instr & 0xFF;
   1796       opcode << "add";
   1797       args << rd << ", sp, #" << (imm8 << 2);
   1798     } else if ((instr & 0xF000) == 0xB000) {
   1799       // Miscellaneous 16-bit instructions
   1800       uint16_t opcode2 = (instr >> 5) & 0x7F;
   1801       switch (opcode2) {
   1802         case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: {
   1803           // Add immediate to SP        - 1011 00000 ii iiiii
   1804           // Subtract immediate from SP - 1011 00001 ii iiiii
   1805           int imm7 = instr & 0x7F;
   1806           opcode << ((opcode2 & 4) == 0 ? "add" : "sub");
   1807           args << "sp, sp, #" << (imm7 << 2);
   1808           break;
   1809         }
   1810         case 0x08: case 0x09: case 0x0A: case 0x0B:  // 0001xxx
   1811         case 0x0C: case 0x0D: case 0x0E: case 0x0F:
   1812         case 0x18: case 0x19: case 0x1A: case 0x1B:  // 0011xxx
   1813         case 0x1C: case 0x1D: case 0x1E: case 0x1F:
   1814         case 0x48: case 0x49: case 0x4A: case 0x4B:  // 1001xxx
   1815         case 0x4C: case 0x4D: case 0x4E: case 0x4F:
   1816         case 0x58: case 0x59: case 0x5A: case 0x5B:  // 1011xxx
   1817         case 0x5C: case 0x5D: case 0x5E: case 0x5F: {
   1818           // CBNZ, CBZ
   1819           uint16_t op = (instr >> 11) & 1;
   1820           uint16_t i = (instr >> 9) & 1;
   1821           uint16_t imm5 = (instr >> 3) & 0x1F;
   1822           ThumbRegister Rn(instr, 0);
   1823           opcode << (op != 0 ? "cbnz" : "cbz");
   1824           uint32_t imm32 = (i << 6) | (imm5 << 1);
   1825           args << Rn << ", ";
   1826           DumpBranchTarget(args, instr_ptr + 4, imm32);
   1827           break;
   1828         }
   1829         case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
   1830         case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F: {
   1831           opcode << "push";
   1832           args << RegisterList((instr & 0xFF) | ((instr & 0x100) << 6));
   1833           break;
   1834         }
   1835         case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
   1836         case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F: {
   1837           opcode << "pop";
   1838           args << RegisterList((instr & 0xFF) | ((instr & 0x100) << 7));
   1839           break;
   1840         }
   1841         case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: {
   1842           opcode << "bkpt";
   1843           args << "#" << (instr & 0xFF);
   1844           break;
   1845         }
   1846         case 0x50: case 0x51:    // 101000x
   1847         case 0x52: case 0x53:    // 101001x
   1848         case 0x56: case 0x57: {  // 101011x
   1849           uint16_t op = (instr >> 6) & 3;
   1850           opcode << kThumbReverseOperations[op];
   1851           ThumbRegister Rm(instr, 3);
   1852           ThumbRegister Rd(instr, 0);
   1853           args << Rd << ", " << Rm;
   1854           break;
   1855         }
   1856         case 0x78: case 0x79: case 0x7A: case 0x7B:  // 1111xxx
   1857         case 0x7C: case 0x7D: case 0x7E: case 0x7F: {
   1858           // If-Then, and hints
   1859           uint16_t opA = (instr >> 4) & 0xF;
   1860           uint16_t opB = instr & 0xF;
   1861           if (opB == 0) {
   1862             switch (opA) {
   1863               case 0: opcode << "nop"; break;
   1864               case 1: opcode << "yield"; break;
   1865               case 2: opcode << "wfe";  break;
   1866               case 3: opcode << "sev"; break;
   1867               default: break;
   1868             }
   1869           } else {
   1870             uint32_t first_cond = opA;
   1871             uint32_t mask = opB;
   1872             opcode << "it";
   1873 
   1874             // Flesh out the base "it" opcode with the specific collection of 't's and 'e's,
   1875             // and store up the actual condition codes we'll want to add to the next few opcodes.
   1876             size_t count = 3 - CTZ(mask);
   1877             it_conditions_.resize(count + 2);  // Plus the implicit 't', plus the "" for the IT itself.
   1878             for (size_t i = 0; i < count; ++i) {
   1879               bool positive_cond = ((first_cond & 1) != 0);
   1880               bool positive_mask = ((mask & (1 << (3 - i))) != 0);
   1881               if (positive_mask == positive_cond) {
   1882                 opcode << 't';
   1883                 it_conditions_[i] = kConditionCodeNames[first_cond];
   1884               } else {
   1885                 opcode << 'e';
   1886                 it_conditions_[i] = kConditionCodeNames[first_cond ^ 1];
   1887               }
   1888             }
   1889             it_conditions_[count] = kConditionCodeNames[first_cond];  // The implicit 't'.
   1890 
   1891             it_conditions_[count + 1] = "";  // No condition code for the IT itself...
   1892             DumpCond(args, first_cond);  // ...because it's considered an argument.
   1893           }
   1894           break;
   1895         }
   1896         default:
   1897           break;
   1898       }
   1899     } else if (((instr & 0xF000) == 0x5000) || ((instr & 0xE000) == 0x6000) ||
   1900         ((instr & 0xE000) == 0x8000)) {
   1901       // Load/store single data item
   1902       uint16_t opA = instr >> 12;
   1903       // uint16_t opB = (instr >> 9) & 7;
   1904       switch (opA) {
   1905         case 0x6: {
   1906           // STR Rt, [Rn, #imm] - 01100 iiiii nnn ttt
   1907           // LDR Rt, [Rn, #imm] - 01101 iiiii nnn ttt
   1908           uint16_t imm5 = (instr >> 6) & 0x1F;
   1909           ThumbRegister Rn(instr, 3);
   1910           ThumbRegister Rt(instr, 0);
   1911           opcode << ((instr & 0x800) == 0 ? "str" : "ldr");
   1912           args << Rt << ", [" << Rn << ", #" << (imm5 << 2) << "]";
   1913           break;
   1914         }
   1915         case 0x9: {
   1916           // STR Rt, [SP, #imm] - 01100 ttt iiiiiiii
   1917           // LDR Rt, [SP, #imm] - 01101 ttt iiiiiiii
   1918           uint16_t imm8 = instr & 0xFF;
   1919           ThumbRegister Rt(instr, 8);
   1920           opcode << ((instr & 0x800) == 0 ? "str" : "ldr");
   1921           args << Rt << ", [sp, #" << (imm8 << 2) << "]";
   1922           break;
   1923         }
   1924         default:
   1925           break;
   1926       }
   1927     } else if (opcode1 == 0x38 || opcode1 == 0x39) {
   1928       uint16_t imm11 = instr & 0x7FFF;
   1929       int32_t imm32 = imm11 << 1;
   1930       imm32 = (imm32 << 20) >> 20;  // sign extend 12 bit immediate
   1931       opcode << "b";
   1932       DumpBranchTarget(args, instr_ptr + 4, imm32);
   1933     }
   1934 
   1935     // Apply any IT-block conditions to the opcode if necessary.
   1936     if (!it_conditions_.empty()) {
   1937       opcode << it_conditions_.back();
   1938       it_conditions_.pop_back();
   1939     }
   1940 
   1941     os << FormatInstructionPointer(instr_ptr)
   1942        << StringPrintf(": %04x    \t%-7s ", instr, opcode.str().c_str())
   1943        << args.str() << '\n';
   1944   }
   1945   return 2;
   1946 }
   1947 
   1948 }  // namespace arm
   1949 }  // namespace art
   1950