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