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 
Dump(std::ostream & os,const uint8_t * begin)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 
Dump(std::ostream & os,const uint8_t * begin,const uint8_t * end)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 
DumpCond(std::ostream & os,uint32_t cond)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 
DumpMemoryDomain(std::ostream & os,uint32_t domain)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 
DumpBranchTarget(std::ostream & os,const uint8_t * instr_ptr,int32_t imm32)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 
ReadU16(const uint8_t * ptr)100 static uint32_t ReadU16(const uint8_t* ptr) {
101   return ptr[0] | (ptr[1] << 8);
102 }
103 
ReadU32(const uint8_t * ptr)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 {
ArmRegisterart::arm::ArmRegister127   explicit ArmRegister(uint32_t r) : r(r) { CHECK_LE(r, 15U); }
ArmRegisterart::arm::ArmRegister128   ArmRegister(uint32_t instruction, uint32_t at_bit) : r((instruction >> at_bit) & 0xf) { CHECK_LE(r, 15U); }
129   uint32_t r;
130 };
operator <<(std::ostream & os,const ArmRegister & r)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 {
ThumbRegisterart::arm::ThumbRegister145   ThumbRegister(uint16_t instruction, uint16_t at_bit) : ArmRegister((instruction >> at_bit) & 0x7) {}
146 };
147 
148 struct Rm {
Rmart::arm::Rm149   explicit Rm(uint32_t instruction) : shift((instruction >> 4) & 0xff), rm(instruction & 0xf) {}
150   uint32_t shift;
151   ArmRegister rm;
152 };
operator <<(std::ostream & os,const Rm & r)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 {
ShiftedImmediateart::arm::ShiftedImmediate162   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 };
operator <<(std::ostream & os,const ShiftedImmediate & rhs)169 std::ostream& operator<<(std::ostream& os, const ShiftedImmediate& rhs) {
170   os << "#" << rhs.value;
171   return os;
172 }
173 
174 struct RegisterList {
RegisterListart::arm::RegisterList175   explicit RegisterList(uint32_t instruction) : register_list(instruction & 0xffff) {}
176   uint32_t register_list;
177 };
operator <<(std::ostream & os,const RegisterList & rhs)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 {
FpRegisterart::arm::FpRegister200   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   }
FpRegisterart::arm::FpRegister206   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   }
FpRegisterart::arm::FpRegister213   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 };
operator <<(std::ostream & os,const FpRegister & rhs)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 {
FpRegisterRangeart::arm::FpRegisterRange224   explicit FpRegisterRange(uint32_t instr)
225       : first(instr, 12, 22), imm8(instr & 0xFF) {}
226   FpRegister first;
227   uint32_t imm8;
228 };
operator <<(std::ostream & os,const FpRegisterRange & rhs)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 
DumpArm(std::ostream & os,const uint8_t * instr_ptr)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 
ThumbExpand(int32_t imm12)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 
VFPExpand32(uint32_t imm8)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 
VFPExpand64(uint32_t imm8)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 
AdvSIMDExpand(uint32_t op,uint32_t cmode,uint32_t imm8)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 
DumpThumb32(std::ostream & os,const uint8_t * instr_ptr)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 
DumpThumb16(std::ostream & os,const uint8_t * instr_ptr)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