1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6#if defined(TARGET_ARCH_ARM)
7
8#include "vm/compiler/assembler/disassembler.h"
9
10#include "platform/assert.h"
11#include "vm/cpu.h"
12#include "vm/instructions.h"
13
14namespace dart {
15
16#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
17
18class ARMDecoder : public ValueObject {
19 public:
20 ARMDecoder(char* buffer, size_t buffer_size)
21 : buffer_(buffer), buffer_size_(buffer_size), buffer_pos_(0) {
22 buffer_[buffer_pos_] = '\0';
23 }
24
25 ~ARMDecoder() {}
26
27 // Writes one disassembled instruction into 'buffer' (0-terminated).
28 // Returns true if the instruction was successfully decoded, false otherwise.
29 void InstructionDecode(uword pc);
30
31 private:
32 // Bottleneck functions to print into the out_buffer.
33 void Print(const char* str);
34
35 // Printing of common values.
36 void PrintRegister(int reg);
37 void PrintSRegister(int reg);
38 void PrintDRegister(int reg);
39 void PrintDRegisterList(int start, int reg_count);
40 void PrintQRegister(int reg);
41 void PrintCondition(Instr* instr);
42 void PrintShiftRm(Instr* instr);
43 void PrintShiftImm(Instr* instr);
44 void PrintPU(Instr* instr);
45
46 // Handle formatting of instructions and their options.
47 int FormatRegister(Instr* instr, const char* option);
48 int FormatSRegister(Instr* instr, const char* option);
49 int FormatDRegister(Instr* instr, const char* option);
50 int FormatQRegister(Instr* instr, const char* option);
51 int FormatOption(Instr* instr, const char* option);
52 void Format(Instr* instr, const char* format);
53 void Unknown(Instr* instr);
54
55 // Each of these functions decodes one particular instruction type, a 3-bit
56 // field in the instruction encoding.
57 // Types 0 and 1 are combined as they are largely the same except for the way
58 // they interpret the shifter operand.
59 void DecodeType01(Instr* instr);
60 void DecodeType2(Instr* instr);
61 void DecodeType3(Instr* instr);
62 void DecodeType4(Instr* instr);
63 void DecodeType5(Instr* instr);
64 void DecodeType6(Instr* instr);
65 void DecodeType7(Instr* instr);
66 void DecodeSIMDDataProcessing(Instr* instr);
67
68 // Convenience functions.
69 char* get_buffer() const { return buffer_; }
70 char* current_position_in_buffer() { return buffer_ + buffer_pos_; }
71 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; }
72
73 char* buffer_; // Decode instructions into this buffer.
74 size_t buffer_size_; // The size of the character buffer.
75 size_t buffer_pos_; // Current character position in buffer.
76
77 DISALLOW_ALLOCATION();
78 DISALLOW_COPY_AND_ASSIGN(ARMDecoder);
79};
80
81// Support for assertions in the ARMDecoder formatting functions.
82#define STRING_STARTS_WITH(string, compare_string) \
83 (strncmp(string, compare_string, strlen(compare_string)) == 0)
84
85// Append the str to the output buffer.
86void ARMDecoder::Print(const char* str) {
87 char cur = *str++;
88 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) {
89 buffer_[buffer_pos_++] = cur;
90 cur = *str++;
91 }
92 buffer_[buffer_pos_] = '\0';
93}
94
95// These condition names are defined in a way to match the native disassembler
96// formatting. See for example the command "objdump -d <binary file>".
97static const char* cond_names[kNumberOfConditions] = {
98 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
99 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
100};
101
102// Print the condition guarding the instruction.
103void ARMDecoder::PrintCondition(Instr* instr) {
104 Print(cond_names[instr->ConditionField()]);
105}
106
107// These register names are defined in a way to match the native disassembler
108// formatting, except for register alias pp (r5).
109// See for example the command "objdump -d <binary file>".
110static const char* reg_names[kNumberOfCpuRegisters] = {
111#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
112 "r0", "r1", "r2", "r3", "r4", "pp", "r6", "fp",
113 "r8", "r9", "thr", "r11", "ip", "sp", "lr", "pc",
114#else
115 "r0", "r1", "r2", "r3", "r4", "pp", "r6", "r7",
116 "r8", "r9", "thr", "fp", "ip", "sp", "lr", "pc",
117#endif
118};
119
120// Print the register name according to the active name converter.
121void ARMDecoder::PrintRegister(int reg) {
122 ASSERT(0 <= reg);
123 ASSERT(reg < kNumberOfCpuRegisters);
124 Print(reg_names[reg]);
125}
126
127void ARMDecoder::PrintSRegister(int reg) {
128 ASSERT(0 <= reg);
129 ASSERT(reg < kNumberOfSRegisters);
130 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
131 remaining_size_in_buffer(), "s%d", reg);
132}
133
134void ARMDecoder::PrintDRegister(int reg) {
135 ASSERT(0 <= reg);
136 ASSERT(reg < kNumberOfDRegisters);
137 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
138 remaining_size_in_buffer(), "d%d", reg);
139}
140
141void ARMDecoder::PrintQRegister(int reg) {
142 ASSERT(0 <= reg);
143 ASSERT(reg < kNumberOfQRegisters);
144 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
145 remaining_size_in_buffer(), "q%d", reg);
146}
147
148// These shift names are defined in a way to match the native disassembler
149// formatting. See for example the command "objdump -d <binary file>".
150static const char* shift_names[kMaxShift] = {"lsl", "lsr", "asr", "ror"};
151
152// Print the register shift operands for the instruction. Generally used for
153// data processing instructions.
154void ARMDecoder::PrintShiftRm(Instr* instr) {
155 Shift shift = instr->ShiftField();
156 int shift_amount = instr->ShiftAmountField();
157 int rm = instr->RmField();
158
159 PrintRegister(rm);
160
161 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
162 // Special case for using rm only.
163 return;
164 }
165 if (instr->RegShiftField() == 0) {
166 // by immediate
167 if ((shift == ROR) && (shift_amount == 0)) {
168 Print(", RRX");
169 return;
170 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
171 shift_amount = 32;
172 }
173 buffer_pos_ +=
174 Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
175 ", %s #%d", shift_names[shift], shift_amount);
176 } else {
177 // by register
178 int rs = instr->RsField();
179 buffer_pos_ +=
180 Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
181 ", %s ", shift_names[shift]);
182 PrintRegister(rs);
183 }
184}
185
186// Print the immediate operand for the instruction. Generally used for data
187// processing instructions.
188void ARMDecoder::PrintShiftImm(Instr* instr) {
189 uint8_t rotate = instr->RotateField() * 2;
190 int32_t immed8 = instr->Immed8Field();
191 int32_t imm = Utils::RotateRight(immed8, rotate);
192 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
193 remaining_size_in_buffer(), "#%d", imm);
194}
195
196// Print PU formatting to reduce complexity of FormatOption.
197void ARMDecoder::PrintPU(Instr* instr) {
198 switch (instr->PUField()) {
199 case 0: {
200 Print("da");
201 break;
202 }
203 case 1: {
204 Print("ia");
205 break;
206 }
207 case 2: {
208 Print("db");
209 break;
210 }
211 case 3: {
212 Print("ib");
213 break;
214 }
215 default: {
216 UNREACHABLE();
217 break;
218 }
219 }
220}
221
222// Handle all register based formatting in these functions to reduce the
223// complexity of FormatOption.
224int ARMDecoder::FormatRegister(Instr* instr, const char* format) {
225 ASSERT(format[0] == 'r');
226 if (format[1] == 'n') { // 'rn: Rn register
227 int reg = instr->RnField();
228 PrintRegister(reg);
229 return 2;
230 } else if (format[1] == 'd') { // 'rd: Rd register
231 int reg = instr->RdField();
232 PrintRegister(reg);
233 if (format[2] == '2') { // 'rd2: possibly Rd, Rd+1 register pair
234 if (instr->HasSign() && !instr->HasL()) {
235 if ((reg % 2) != 0) {
236 Print(" *** unknown (odd register pair) ***");
237 } else {
238 Print(", ");
239 PrintRegister(reg + 1);
240 }
241 }
242 return 3;
243 }
244 return 2;
245 } else if (format[1] == 's') { // 'rs: Rs register
246 int reg = instr->RsField();
247 PrintRegister(reg);
248 return 2;
249 } else if (format[1] == 'm') { // 'rm: Rm register
250 int reg = instr->RmField();
251 PrintRegister(reg);
252 return 2;
253 } else if (format[1] == 'l') {
254 // 'rlist: register list for load and store multiple instructions
255 ASSERT(STRING_STARTS_WITH(format, "rlist"));
256 int rlist = instr->RlistField();
257 int reg = 0;
258 Print("{");
259 // Print register list in ascending order, by scanning the bit mask.
260 while (rlist != 0) {
261 if ((rlist & 1) != 0) {
262 PrintRegister(reg);
263 if ((rlist >> 1) != 0) {
264 Print(", ");
265 }
266 }
267 reg++;
268 rlist >>= 1;
269 }
270 Print("}");
271 return 5;
272 }
273 UNREACHABLE();
274 return -1;
275}
276
277int ARMDecoder::FormatSRegister(Instr* instr, const char* format) {
278 ASSERT(format[0] == 's');
279 if (format[1] == 'n') { // 'sn: Sn register
280 int reg = instr->SnField();
281 PrintSRegister(reg);
282 return 2;
283 } else if (format[1] == 'd') { // 'sd: Sd register
284 int reg = instr->SdField();
285 PrintSRegister(reg);
286 return 2;
287 } else if (format[1] == 'm') {
288 int reg = instr->SmField();
289 if (format[2] == '1') { // 'sm1: S[m+1] register
290 reg++;
291 ASSERT(reg < kNumberOfSRegisters);
292 PrintSRegister(reg);
293 return 3;
294 } else { // 'sm: Sm register
295 PrintSRegister(reg);
296 return 2;
297 }
298 } else if (format[1] == 'l') {
299 ASSERT(STRING_STARTS_WITH(format, "slist"));
300 int reg_count = instr->Bits(0, 8);
301 int start = instr->Bit(22) | (instr->Bits(12, 4) << 1);
302 Print("{");
303 for (int i = start; i < start + reg_count; i++) {
304 PrintSRegister(i);
305 if (i != start + reg_count - 1) {
306 Print(", ");
307 }
308 }
309 Print("}");
310 return 5;
311 }
312 UNREACHABLE();
313 return -1;
314}
315
316void ARMDecoder::PrintDRegisterList(int start, int reg_count) {
317 Print("{");
318 for (int i = start; i < start + reg_count; i++) {
319 PrintDRegister(i);
320 if (i != start + reg_count - 1) {
321 Print(", ");
322 }
323 }
324 Print("}");
325}
326
327int ARMDecoder::FormatDRegister(Instr* instr, const char* format) {
328 ASSERT(format[0] == 'd');
329 if (format[1] == 'n') { // 'dn: Dn register
330 int reg = instr->DnField();
331 PrintDRegister(reg);
332 return 2;
333 } else if (format[1] == 'd') { // 'dd: Dd register
334 int reg = instr->DdField();
335 PrintDRegister(reg);
336 return 2;
337 } else if (format[1] == 'm') { // 'dm: Dm register
338 int reg = instr->DmField();
339 PrintDRegister(reg);
340 return 2;
341 } else if (format[1] == 'l') {
342 ASSERT(STRING_STARTS_WITH(format, "dlist"));
343 int reg_count = instr->Bits(0, 8) >> 1;
344 int start = (instr->Bit(22) << 4) | instr->Bits(12, 4);
345 PrintDRegisterList(start, reg_count);
346 return 5;
347 } else if (format[1] == 't') {
348 ASSERT(STRING_STARTS_WITH(format, "dtbllist"));
349 int reg_count = instr->Bits(8, 2) + 1;
350 int start = (instr->Bit(7) << 4) | instr->Bits(16, 4);
351 PrintDRegisterList(start, reg_count);
352 return 8;
353 }
354 UNREACHABLE();
355 return -1;
356}
357
358int ARMDecoder::FormatQRegister(Instr* instr, const char* format) {
359 ASSERT(format[0] == 'q');
360 if (format[1] == 'n') { // 'qn: Qn register
361 int reg = instr->QnField();
362 PrintQRegister(reg);
363 return 2;
364 } else if (format[1] == 'd') { // 'qd: Qd register
365 int reg = instr->QdField();
366 PrintQRegister(reg);
367 return 2;
368 } else if (format[1] == 'm') { // 'qm: Qm register
369 int reg = instr->QmField();
370 PrintQRegister(reg);
371 return 2;
372 }
373 UNREACHABLE();
374 return -1;
375}
376
377// FormatOption takes a formatting string and interprets it based on
378// the current instructions. The format string points to the first
379// character of the option string (the option escape has already been
380// consumed by the caller.) FormatOption returns the number of
381// characters that were consumed from the formatting string.
382int ARMDecoder::FormatOption(Instr* instr, const char* format) {
383 switch (format[0]) {
384 case 'a': { // 'a: accumulate multiplies
385 if (instr->Bit(21) == 0) {
386 Print("ul");
387 } else {
388 Print("la");
389 }
390 return 1;
391 }
392 case 'b': { // 'b: byte loads or stores
393 if (instr->HasB()) {
394 Print("b");
395 }
396 return 1;
397 }
398 case 'c': { // 'cond: conditional execution
399 ASSERT(STRING_STARTS_WITH(format, "cond"));
400 PrintCondition(instr);
401 return 4;
402 }
403 case 'd': {
404 if (format[1] == 'e') { // 'dest: branch destination
405 ASSERT(STRING_STARTS_WITH(format, "dest"));
406 const int32_t off =
407 (static_cast<uint32_t>(instr->SImmed24Field()) << 2) + 8;
408 if (FLAG_disassemble_relative) {
409 buffer_pos_ +=
410 Utils::SNPrint(current_position_in_buffer(),
411 remaining_size_in_buffer(), "%+" Pd32 "", off);
412 } else {
413 uword destination = reinterpret_cast<uword>(instr) + off;
414 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
415 remaining_size_in_buffer(), "%#" Px "",
416 destination);
417 }
418 return 4;
419 } else {
420 return FormatDRegister(instr, format);
421 }
422 }
423 case 'q': {
424 return FormatQRegister(instr, format);
425 }
426 case 'i': { // 'imm12_4, imm4_12, immf, or immd
427 uint16_t immed16;
428 if (format[3] == 'f') {
429 ASSERT(STRING_STARTS_WITH(format, "immf"));
430 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
431 remaining_size_in_buffer(), "%f",
432 instr->ImmFloatField());
433 return 4;
434 } else if (format[3] == 'd') {
435 ASSERT(STRING_STARTS_WITH(format, "immd"));
436 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
437 remaining_size_in_buffer(), "%g",
438 instr->ImmDoubleField());
439 return 4;
440 } else if (format[3] == '1') {
441 ASSERT(STRING_STARTS_WITH(format, "imm12_4"));
442 immed16 = instr->BkptField();
443 } else {
444 ASSERT(format[3] == '4');
445 if (format[5] == 'v') {
446 ASSERT(STRING_STARTS_WITH(format, "imm4_vdup"));
447 int32_t idx = -1;
448 int32_t imm4 = instr->Bits(16, 4);
449 if ((imm4 & 1) != 0)
450 idx = imm4 >> 1;
451 else if ((imm4 & 2) != 0)
452 idx = imm4 >> 2;
453 else if ((imm4 & 4) != 0)
454 idx = imm4 >> 3;
455 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
456 remaining_size_in_buffer(), "%d", idx);
457 return 9;
458 } else {
459 ASSERT(STRING_STARTS_WITH(format, "imm4_12"));
460 immed16 = instr->MovwField();
461 }
462 }
463 buffer_pos_ +=
464 Utils::SNPrint(current_position_in_buffer(),
465 remaining_size_in_buffer(), "0x%x", immed16);
466 return 7;
467 }
468 case 'l': { // 'l: branch and link
469 if (instr->HasLink()) {
470 Print("l");
471 }
472 return 1;
473 }
474 case 'm': { // 'memop: load/store instructions
475 ASSERT(STRING_STARTS_WITH(format, "memop"));
476 if (instr->HasL() ||
477 // Extra load/store instructions.
478 ((instr->TypeField() == 0) && instr->HasSign() && !instr->HasH())) {
479 Print("ldr");
480 } else {
481 Print("str");
482 }
483 return 5;
484 }
485 case 'o': {
486 if (format[3] == '1') {
487 if (format[4] == '0') {
488 // 'off10: 10-bit offset for VFP load and store instructions
489 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
490 remaining_size_in_buffer(), "%d",
491 instr->Bits(0, 8) << 2);
492 } else {
493 // 'off12: 12-bit offset for load and store instructions.
494 ASSERT(STRING_STARTS_WITH(format, "off12"));
495 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
496 remaining_size_in_buffer(), "%d",
497 instr->Offset12Field());
498 }
499 return 5;
500 }
501 // 'off8: 8-bit offset for extra load and store instructions.
502 ASSERT(STRING_STARTS_WITH(format, "off8"));
503 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
504 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
505 remaining_size_in_buffer(), "%d", offs8);
506 return 4;
507 }
508 case 'p': { // 'pu: P and U bits for load and store instructions.
509 ASSERT(STRING_STARTS_WITH(format, "pu"));
510 PrintPU(instr);
511 return 2;
512 }
513 case 'r': {
514 return FormatRegister(instr, format);
515 }
516 case 's': {
517 if (format[1] == 'h') { // 'shift_op or 'shift_rm
518 if (format[6] == 'o') { // 'shift_op
519 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
520 if (instr->TypeField() == 0) {
521 PrintShiftRm(instr);
522 } else {
523 ASSERT(instr->TypeField() == 1);
524 PrintShiftImm(instr);
525 }
526 return 8;
527 } else { // 'shift_rm
528 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
529 PrintShiftRm(instr);
530 return 8;
531 }
532 } else if (format[1] == 'v') { // 'svc
533 ASSERT(STRING_STARTS_WITH(format, "svc"));
534 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
535 remaining_size_in_buffer(), "0x%x",
536 instr->SvcField());
537 return 3;
538 } else if (format[1] == 'z') {
539 // 'sz: Size field of SIMD instructions.
540 int sz = instr->Bits(20, 2);
541 char const* sz_str;
542 switch (sz) {
543 case 0:
544 sz_str = "b";
545 break;
546 case 1:
547 sz_str = "h";
548 break;
549 case 2:
550 sz_str = "w";
551 break;
552 case 3:
553 sz_str = "l";
554 break;
555 default:
556 sz_str = "?";
557 break;
558 }
559 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
560 remaining_size_in_buffer(), "%s", sz_str);
561 return 2;
562 } else if (format[1] == ' ') {
563 // 's: S field of data processing instructions.
564 if (instr->HasS()) {
565 Print("s");
566 }
567 return 1;
568 } else {
569 return FormatSRegister(instr, format);
570 }
571 }
572 case 't': { // 'target: target of branch instructions.
573 ASSERT(STRING_STARTS_WITH(format, "target"));
574 int32_t off = (static_cast<uint32_t>(instr->SImmed24Field()) << 2) + 8;
575 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
576 remaining_size_in_buffer(), "%+d", off);
577 return 6;
578 }
579 case 'u': { // 'u: signed or unsigned multiplies.
580 if (instr->Bit(22) == 0) {
581 Print("u");
582 } else {
583 Print("s");
584 }
585 return 1;
586 }
587 case 'w': { // 'w: W field of load and store instructions.
588 if (instr->HasW()) {
589 Print("!");
590 }
591 return 1;
592 }
593 case 'x': { // 'x: type of extra load/store instructions.
594 if (!instr->HasSign()) {
595 Print("h");
596 } else if (instr->HasL()) {
597 if (instr->HasH()) {
598 Print("sh");
599 } else {
600 Print("sb");
601 }
602 } else {
603 Print("d");
604 }
605 return 1;
606 }
607 default: {
608 UNREACHABLE();
609 break;
610 }
611 }
612 UNREACHABLE();
613 return -1;
614}
615
616// Format takes a formatting string for a whole instruction and prints it into
617// the output buffer. All escaped options are handed to FormatOption to be
618// parsed further.
619void ARMDecoder::Format(Instr* instr, const char* format) {
620 char cur = *format++;
621 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) {
622 if (cur == '\'') { // Single quote is used as the formatting escape.
623 format += FormatOption(instr, format);
624 } else {
625 buffer_[buffer_pos_++] = cur;
626 }
627 cur = *format++;
628 }
629 buffer_[buffer_pos_] = '\0';
630}
631
632// For currently unimplemented decodings the disassembler calls Unknown(instr)
633// which will just print "unknown" of the instruction bits.
634void ARMDecoder::Unknown(Instr* instr) {
635 Format(instr, "unknown");
636}
637
638void ARMDecoder::DecodeType01(Instr* instr) {
639 if (!instr->IsDataProcessing()) {
640 // miscellaneous, multiply, sync primitives, extra loads and stores.
641 if (instr->IsMiscellaneous()) {
642 switch (instr->Bits(4, 3)) {
643 case 1: {
644 if (instr->Bits(21, 2) == 0x3) {
645 Format(instr, "clz'cond 'rd, 'rm");
646 } else if (instr->Bits(21, 2) == 0x1) {
647 Format(instr, "bx'cond 'rm");
648 } else {
649 Unknown(instr);
650 }
651 break;
652 }
653 case 3: {
654 if (instr->Bits(21, 2) == 0x1) {
655 Format(instr, "blx'cond 'rm");
656 } else {
657 // Could be inlined constant.
658 Unknown(instr);
659 }
660 break;
661 }
662 case 7: {
663 if ((instr->Bits(21, 2) == 0x1) && (instr->ConditionField() == AL)) {
664 Format(instr, "bkpt #'imm12_4");
665 } else {
666 // Format(instr, "smc'cond");
667 Unknown(instr); // Not used.
668 }
669 break;
670 }
671 default: {
672 Unknown(instr); // Not used.
673 break;
674 }
675 }
676 } else if (instr->IsMultiplyOrSyncPrimitive()) {
677 if (instr->Bit(24) == 0) {
678 // multiply instructions
679 switch (instr->Bits(21, 3)) {
680 case 0: {
681 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
682 Format(instr, "mul'cond's 'rn, 'rm, 'rs");
683 break;
684 }
685 case 1: {
686 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
687 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
688 break;
689 }
690 case 2: {
691 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
692 Format(instr, "umaal'cond's 'rd, 'rn, 'rm, 'rs");
693 break;
694 }
695 case 3: {
696 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
697 Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
698 break;
699 }
700 case 4: {
701 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
702 Format(instr, "umull'cond's 'rd, 'rn, 'rm, 'rs");
703 break;
704 }
705 case 5: {
706 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
707 Format(instr, "umlal'cond's 'rd, 'rn, 'rm, 'rs");
708 break;
709 }
710 case 6: {
711 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
712 Format(instr, "smull'cond's 'rd, 'rn, 'rm, 'rs");
713 break;
714 }
715 default: {
716 Unknown(instr); // Not used.
717 break;
718 }
719 }
720 } else {
721 // synchronization primitives
722 switch (instr->Bits(20, 4)) {
723 case 8: {
724 Format(instr, "strex'cond 'rd, 'rm, ['rn]");
725 break;
726 }
727 case 9: {
728 Format(instr, "ldrex'cond 'rd, ['rn]");
729 break;
730 }
731 default: {
732 Unknown(instr); // Not used.
733 break;
734 }
735 }
736 }
737 } else if (instr->Bit(25) == 1) {
738 // 16-bit immediate loads, msr (immediate), and hints
739 switch (instr->Bits(20, 5)) {
740 case 16: {
741 Format(instr, "movw'cond 'rd, #'imm4_12");
742 break;
743 }
744 case 18: {
745 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) {
746 Format(instr, "nop'cond");
747 } else {
748 Unknown(instr); // Not used.
749 }
750 break;
751 }
752 case 20: {
753 Format(instr, "movt'cond 'rd, #'imm4_12");
754 break;
755 }
756 default: {
757 Unknown(instr); // Not used.
758 break;
759 }
760 }
761 } else {
762 // extra load/store instructions
763 switch (instr->PUField()) {
764 case 0: {
765 if (instr->Bit(22) == 0) {
766 Format(instr, "'memop'cond'x 'rd2, ['rn], -'rm");
767 } else {
768 Format(instr, "'memop'cond'x 'rd2, ['rn], #-'off8");
769 }
770 break;
771 }
772 case 1: {
773 if (instr->Bit(22) == 0) {
774 Format(instr, "'memop'cond'x 'rd2, ['rn], +'rm");
775 } else {
776 Format(instr, "'memop'cond'x 'rd2, ['rn], #+'off8");
777 }
778 break;
779 }
780 case 2: {
781 if (instr->Bit(22) == 0) {
782 Format(instr, "'memop'cond'x 'rd2, ['rn, -'rm]'w");
783 } else {
784 Format(instr, "'memop'cond'x 'rd2, ['rn, #-'off8]'w");
785 }
786 break;
787 }
788 case 3: {
789 if (instr->Bit(22) == 0) {
790 Format(instr, "'memop'cond'x 'rd2, ['rn, +'rm]'w");
791 } else {
792 Format(instr, "'memop'cond'x 'rd2, ['rn, #+'off8]'w");
793 }
794 break;
795 }
796 default: {
797 // The PU field is a 2-bit field.
798 UNREACHABLE();
799 break;
800 }
801 }
802 }
803 } else {
804 switch (instr->OpcodeField()) {
805 case AND: {
806 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
807 break;
808 }
809 case EOR: {
810 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
811 break;
812 }
813 case SUB: {
814 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
815 break;
816 }
817 case RSB: {
818 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
819 break;
820 }
821 case ADD: {
822 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
823 break;
824 }
825 case ADC: {
826 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
827 break;
828 }
829 case SBC: {
830 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
831 break;
832 }
833 case RSC: {
834 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
835 break;
836 }
837 case TST: {
838 if (instr->HasS()) {
839 Format(instr, "tst'cond 'rn, 'shift_op");
840 } else {
841 Unknown(instr); // Not used.
842 }
843 break;
844 }
845 case TEQ: {
846 if (instr->HasS()) {
847 Format(instr, "teq'cond 'rn, 'shift_op");
848 } else {
849 Unknown(instr); // Not used.
850 }
851 break;
852 }
853 case CMP: {
854 if (instr->HasS()) {
855 Format(instr, "cmp'cond 'rn, 'shift_op");
856 } else {
857 Unknown(instr); // Not used.
858 }
859 break;
860 }
861 case CMN: {
862 if (instr->HasS()) {
863 Format(instr, "cmn'cond 'rn, 'shift_op");
864 } else {
865 Unknown(instr); // Not used.
866 }
867 break;
868 }
869 case ORR: {
870 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
871 break;
872 }
873 case MOV: {
874 Format(instr, "mov'cond's 'rd, 'shift_op");
875 break;
876 }
877 case BIC: {
878 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
879 break;
880 }
881 case MVN: {
882 Format(instr, "mvn'cond's 'rd, 'shift_op");
883 break;
884 }
885 default: {
886 // The Opcode field is a 4-bit field.
887 UNREACHABLE();
888 break;
889 }
890 }
891 }
892}
893
894void ARMDecoder::DecodeType2(Instr* instr) {
895 switch (instr->PUField()) {
896 case 0: {
897 if (instr->HasW()) {
898 Unknown(instr); // Not used.
899 } else {
900 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
901 }
902 break;
903 }
904 case 1: {
905 if (instr->HasW()) {
906 Unknown(instr); // Not used.
907 } else {
908 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
909 }
910 break;
911 }
912 case 2: {
913 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
914 break;
915 }
916 case 3: {
917 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
918 break;
919 }
920 default: {
921 // The PU field is a 2-bit field.
922 UNREACHABLE();
923 break;
924 }
925 }
926}
927
928void ARMDecoder::DecodeType3(Instr* instr) {
929 if (instr->IsDivision()) {
930 if (!TargetCPUFeatures::integer_division_supported()) {
931 Unknown(instr);
932 return;
933 }
934 if (instr->Bit(21)) {
935 Format(instr, "udiv'cond 'rn, 'rs, 'rm");
936 } else {
937 Format(instr, "sdiv'cond 'rn, 'rs, 'rm");
938 }
939 return;
940 }
941 switch (instr->PUField()) {
942 case 0: {
943 if (instr->HasW()) {
944 Unknown(instr);
945 } else {
946 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
947 }
948 break;
949 }
950 case 1: {
951 if (instr->HasW()) {
952 Unknown(instr);
953 } else {
954 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
955 }
956 break;
957 }
958 case 2: {
959 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
960 break;
961 }
962 case 3: {
963 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
964 break;
965 }
966 default: {
967 // The PU field is a 2-bit field.
968 UNREACHABLE();
969 break;
970 }
971 }
972}
973
974void ARMDecoder::DecodeType4(Instr* instr) {
975 if (instr->Bit(22) == 1) {
976 Unknown(instr); // Privileged mode currently not supported.
977 } else if (instr->HasL()) {
978 Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
979 } else {
980 Format(instr, "stm'cond'pu 'rn'w, 'rlist");
981 }
982}
983
984void ARMDecoder::DecodeType5(Instr* instr) {
985 Format(instr, "b'l'cond 'target ; 'dest");
986}
987
988void ARMDecoder::DecodeType6(Instr* instr) {
989 if (instr->IsVFPDoubleTransfer()) {
990 if (instr->Bit(8) == 0) {
991 if (instr->Bit(20) == 1) {
992 Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm, 'sm1}");
993 } else {
994 Format(instr, "vmovsrr'cond {'sm, 'sm1}, 'rd, 'rn");
995 }
996 } else {
997 if (instr->Bit(20) == 1) {
998 Format(instr, "vmovrrd'cond 'rd, 'rn, 'dm");
999 } else {
1000 Format(instr, "vmovdrr'cond 'dm, 'rd, 'rn");
1001 }
1002 }
1003 } else if (instr->IsVFPLoadStore()) {
1004 if (instr->Bit(8) == 0) {
1005 if (instr->Bit(20) == 1) { // vldrs
1006 if (instr->Bit(23) == 1) {
1007 Format(instr, "vldrs'cond 'sd, ['rn, #+'off10]");
1008 } else {
1009 Format(instr, "vldrs'cond 'sd, ['rn, #-'off10]");
1010 }
1011 } else { // vstrs
1012 if (instr->Bit(23) == 1) {
1013 Format(instr, "vstrs'cond 'sd, ['rn, #+'off10]");
1014 } else {
1015 Format(instr, "vstrs'cond 'sd, ['rn, #-'off10]");
1016 }
1017 }
1018 } else {
1019 if (instr->Bit(20) == 1) { // vldrd
1020 if (instr->Bit(23) == 1) {
1021 Format(instr, "vldrd'cond 'dd, ['rn, #+'off10]");
1022 } else {
1023 Format(instr, "vldrd'cond 'dd, ['rn, #-'off10]");
1024 }
1025 } else { // vstrd
1026 if (instr->Bit(23) == 1) {
1027 Format(instr, "vstrd'cond 'dd, ['rn, #+'off10]");
1028 } else {
1029 Format(instr, "vstrd'cond 'dd, ['rn, #-'off10]");
1030 }
1031 }
1032 }
1033 } else if (instr->IsVFPMultipleLoadStore()) {
1034 if (instr->HasL()) { // vldm
1035 if (instr->Bit(8)) { // vldmd
1036 Format(instr, "vldmd'cond'pu 'rn'w, 'dlist");
1037 } else { // vldms
1038 Format(instr, "vldms'cond'pu 'rn'w, 'slist");
1039 }
1040 } else { // vstm
1041 if (instr->Bit(8)) { // vstmd
1042 Format(instr, "vstmd'cond'pu 'rn'w, 'dlist");
1043 } else { // vstms
1044 Format(instr, "vstms'cond'pu 'rn'w, 'slist");
1045 }
1046 }
1047 } else {
1048 Unknown(instr);
1049 }
1050}
1051
1052void ARMDecoder::DecodeType7(Instr* instr) {
1053 if (instr->Bit(24) == 1) {
1054 Format(instr, "svc'cond #'svc");
1055 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) {
1056 if (instr->Bit(4) == 0) {
1057 // VFP Data Processing
1058 switch (instr->Bits(20, 4) & 0xb) {
1059 case 0: { // vmla, vmls floating-point
1060 if (instr->Bit(8) == 0) {
1061 if (instr->Bit(6) == 0) {
1062 Format(instr, "vmlas'cond 'sd, 'sn, 'sm");
1063 } else {
1064 Format(instr, "vmlss'cond 'sd, 'sn, 'sm");
1065 }
1066 } else {
1067 if (instr->Bit(6) == 0) {
1068 Format(instr, "vmlad'cond 'dd, 'dn, 'dm");
1069 } else {
1070 Format(instr, "vmlsd'cond 'dd, 'dn, 'dm");
1071 }
1072 }
1073 break;
1074 }
1075 case 1: // vnmla, vnmls, vnmul
1076 default: {
1077 Unknown(instr);
1078 break;
1079 }
1080 case 2: { // vmul
1081 if (instr->Bit(8) == 0) {
1082 Format(instr, "vmuls'cond 'sd, 'sn, 'sm");
1083 } else {
1084 Format(instr, "vmuld'cond 'dd, 'dn, 'dm");
1085 }
1086 break;
1087 }
1088 case 8: { // vdiv
1089 if (instr->Bit(8) == 0) {
1090 Format(instr, "vdivs'cond 'sd, 'sn, 'sm");
1091 } else {
1092 Format(instr, "vdivd'cond 'dd, 'dn, 'dm");
1093 }
1094 break;
1095 }
1096 case 3: { // vadd, vsub floating-point
1097 if (instr->Bit(8) == 0) {
1098 if (instr->Bit(6) == 0) {
1099 Format(instr, "vadds'cond 'sd, 'sn, 'sm");
1100 } else {
1101 Format(instr, "vsubs'cond 'sd, 'sn, 'sm");
1102 }
1103 } else {
1104 if (instr->Bit(6) == 0) {
1105 Format(instr, "vaddd'cond 'dd, 'dn, 'dm");
1106 } else {
1107 Format(instr, "vsubd'cond 'dd, 'dn, 'dm");
1108 }
1109 }
1110 break;
1111 }
1112 case 0xb: { // Other VFP data-processing instructions
1113 if (instr->Bit(6) == 0) { // vmov immediate
1114 if (instr->Bit(8) == 0) {
1115 Format(instr, "vmovs'cond 'sd, #'immf");
1116 } else {
1117 Format(instr, "vmovd'cond 'dd, #'immd");
1118 }
1119 break;
1120 }
1121 switch (instr->Bits(16, 4)) {
1122 case 0: { // vmov register, vabs
1123 switch (instr->Bits(6, 2)) {
1124 case 1: { // vmov register
1125 if (instr->Bit(8) == 0) {
1126 Format(instr, "vmovs'cond 'sd, 'sm");
1127 } else {
1128 Format(instr, "vmovd'cond 'dd, 'dm");
1129 }
1130 break;
1131 }
1132 case 3: { // vabs
1133 if (instr->Bit(8) == 0) {
1134 Format(instr, "vabss'cond 'sd, 'sm");
1135 } else {
1136 Format(instr, "vabsd'cond 'dd, 'dm");
1137 }
1138 break;
1139 }
1140 default: {
1141 Unknown(instr);
1142 break;
1143 }
1144 }
1145 break;
1146 }
1147 case 1: { // vneg, vsqrt
1148 switch (instr->Bits(6, 2)) {
1149 case 1: { // vneg
1150 if (instr->Bit(8) == 0) {
1151 Format(instr, "vnegs'cond 'sd, 'sm");
1152 } else {
1153 Format(instr, "vnegd'cond 'dd, 'dm");
1154 }
1155 break;
1156 }
1157 case 3: { // vsqrt
1158 if (instr->Bit(8) == 0) {
1159 Format(instr, "vsqrts'cond 'sd, 'sm");
1160 } else {
1161 Format(instr, "vsqrtd'cond 'dd, 'dm");
1162 }
1163 break;
1164 }
1165 default: {
1166 Unknown(instr);
1167 break;
1168 }
1169 }
1170 break;
1171 }
1172 case 4: // vcmp, vcmpe
1173 case 5: { // vcmp #0.0, vcmpe #0.0
1174 if (instr->Bit(7) == 1) { // vcmpe
1175 Unknown(instr);
1176 } else {
1177 if (instr->Bit(8) == 0) { // vcmps
1178 if (instr->Bit(16) == 0) {
1179 Format(instr, "vcmps'cond 'sd, 'sm");
1180 } else {
1181 Format(instr, "vcmps'cond 'sd, #0.0");
1182 }
1183 } else { // vcmpd
1184 if (instr->Bit(16) == 0) {
1185 Format(instr, "vcmpd'cond 'dd, 'dm");
1186 } else {
1187 Format(instr, "vcmpd'cond 'dd, #0.0");
1188 }
1189 }
1190 }
1191 break;
1192 }
1193 case 7: { // vcvt between double-precision and single-precision
1194 if (instr->Bit(8) == 0) {
1195 Format(instr, "vcvtds'cond 'dd, 'sm");
1196 } else {
1197 Format(instr, "vcvtsd'cond 'sd, 'dm");
1198 }
1199 break;
1200 }
1201 case 8: { // vcvt, vcvtr between floating-point and integer
1202 if (instr->Bit(8) == 0) {
1203 if (instr->Bit(7) == 0) {
1204 Format(instr, "vcvtsu'cond 'sd, 'sm");
1205 } else {
1206 Format(instr, "vcvtsi'cond 'sd, 'sm");
1207 }
1208 } else {
1209 if (instr->Bit(7) == 0) {
1210 Format(instr, "vcvtdu'cond 'dd, 'sm");
1211 } else {
1212 Format(instr, "vcvtdi'cond 'dd, 'sm");
1213 }
1214 }
1215 break;
1216 }
1217 case 12:
1218 case 13: { // vcvt, vcvtr between floating-point and integer
1219 if (instr->Bit(7) == 0) {
1220 // We only support round-to-zero mode
1221 Unknown(instr);
1222 break;
1223 }
1224 if (instr->Bit(8) == 0) {
1225 if (instr->Bit(16) == 0) {
1226 Format(instr, "vcvtus'cond 'sd, 'sm");
1227 } else {
1228 Format(instr, "vcvtis'cond 'sd, 'sm");
1229 }
1230 } else {
1231 if (instr->Bit(16) == 0) {
1232 Format(instr, "vcvtud'cond 'sd, 'dm");
1233 } else {
1234 Format(instr, "vcvtid'cond 'sd, 'dm");
1235 }
1236 }
1237 break;
1238 }
1239 case 2: // vcvtb, vcvtt
1240 case 3: // vcvtb, vcvtt
1241 case 9: // undefined
1242 case 10: // vcvt between floating-point and fixed-point
1243 case 11: // vcvt between floating-point and fixed-point
1244 case 14: // vcvt between floating-point and fixed-point
1245 case 15: // vcvt between floating-point and fixed-point
1246 default: {
1247 Unknown(instr);
1248 break;
1249 }
1250 }
1251 } break;
1252 }
1253 } else {
1254 // 8, 16, or 32-bit Transfer between ARM Core and VFP
1255 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) {
1256 if (instr->Bit(20) == 0) {
1257 Format(instr, "vmovs'cond 'sn, 'rd");
1258 } else {
1259 Format(instr, "vmovr'cond 'rd, 'sn");
1260 }
1261 } else if ((instr->Bits(22, 3) == 0) && (instr->Bit(20) == 0) &&
1262 (instr->Bit(8) == 1) && (instr->Bits(5, 2) == 0)) {
1263 if (instr->Bit(21) == 0) {
1264 Format(instr, "vmovd'cond 'dn[0], 'rd");
1265 } else {
1266 Format(instr, "vmovd'cond 'dn[1], 'rd");
1267 }
1268 } else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0)) {
1269 if (instr->Bits(12, 4) == 0xf) {
1270 Format(instr, "vmrs'cond APSR, FPSCR");
1271 } else {
1272 Format(instr, "vmrs'cond 'rd, FPSCR");
1273 }
1274 } else {
1275 Unknown(instr);
1276 }
1277 }
1278 } else {
1279 Unknown(instr);
1280 }
1281}
1282
1283void ARMDecoder::DecodeSIMDDataProcessing(Instr* instr) {
1284 ASSERT(instr->ConditionField() == kSpecialCondition);
1285 if (instr->Bit(6) == 1) {
1286 if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
1287 (instr->Bits(23, 2) == 0)) {
1288 Format(instr, "vaddq'sz 'qd, 'qn, 'qm");
1289 } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
1290 (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 0)) {
1291 Format(instr, "vaddqs 'qd, 'qn, 'qm");
1292 } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
1293 (instr->Bits(23, 2) == 2)) {
1294 Format(instr, "vsubq'sz 'qd, 'qn, 'qm");
1295 } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
1296 (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 1)) {
1297 Format(instr, "vsubqs 'qd, 'qn, 'qm");
1298 } else if ((instr->Bits(8, 4) == 9) && (instr->Bit(4) == 1) &&
1299 (instr->Bits(23, 2) == 0)) {
1300 Format(instr, "vmulq'sz 'qd, 'qn, 'qm");
1301 } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 1) &&
1302 (instr->Bits(23, 2) == 2) && (instr->Bit(21) == 0)) {
1303 Format(instr, "vmulqs 'qd, 'qn, 'qm");
1304 } else if ((instr->Bits(8, 4) == 4) && (instr->Bit(4) == 0) &&
1305 (instr->Bits(23, 5) == 4)) {
1306 Format(instr, "vshlqi'sz 'qd, 'qm, 'qn");
1307 } else if ((instr->Bits(8, 4) == 4) && (instr->Bit(4) == 0) &&
1308 (instr->Bits(23, 5) == 6)) {
1309 Format(instr, "vshlqu'sz 'qd, 'qm, 'qn");
1310 } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
1311 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
1312 Format(instr, "veorq 'qd, 'qn, 'qm");
1313 } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
1314 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 0)) {
1315 Format(instr, "vornq 'qd, 'qn, 'qm");
1316 } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
1317 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
1318 if (instr->QmField() == instr->QnField()) {
1319 Format(instr, "vmovq 'qd, 'qm");
1320 } else {
1321 Format(instr, "vorrq 'qd, 'qm");
1322 }
1323 } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
1324 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
1325 Format(instr, "vandq 'qd, 'qn, 'qm");
1326 } else if ((instr->Bits(7, 5) == 11) && (instr->Bit(4) == 0) &&
1327 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 5) == 7) &&
1328 (instr->Bits(16, 4) == 0)) {
1329 Format(instr, "vmvnq 'qd, 'qm");
1330 } else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 0) &&
1331 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
1332 Format(instr, "vminqs 'qd, 'qn, 'qm");
1333 } else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 0) &&
1334 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
1335 Format(instr, "vmaxqs 'qd, 'qn, 'qm");
1336 } else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) &&
1337 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
1338 (instr->Bit(7) == 0) && (instr->Bits(16, 4) == 9)) {
1339 Format(instr, "vabsqs 'qd, 'qm");
1340 } else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) &&
1341 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
1342 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 9)) {
1343 Format(instr, "vnegqs 'qd, 'qm");
1344 } else if ((instr->Bits(7, 5) == 10) && (instr->Bit(4) == 0) &&
1345 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
1346 (instr->Bits(16, 4) == 11)) {
1347 Format(instr, "vrecpeqs 'qd, 'qm");
1348 } else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 1) &&
1349 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
1350 Format(instr, "vrecpsqs 'qd, 'qn, 'qm");
1351 } else if ((instr->Bits(8, 4) == 5) && (instr->Bit(4) == 0) &&
1352 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
1353 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 11)) {
1354 Format(instr, "vrsqrteqs 'qd, 'qm");
1355 } else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 1) &&
1356 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
1357 Format(instr, "vrsqrtsqs 'qd, 'qn, 'qm");
1358 } else if ((instr->Bits(8, 4) == 12) && (instr->Bit(4) == 0) &&
1359 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
1360 (instr->Bit(7) == 0)) {
1361 int32_t imm4 = instr->Bits(16, 4);
1362 if (imm4 & 1) {
1363 Format(instr, "vdupb 'qd, 'dm['imm4_vdup]");
1364 } else if (imm4 & 2) {
1365 Format(instr, "vduph 'qd, 'dm['imm4_vdup]");
1366 } else if (imm4 & 4) {
1367 Format(instr, "vdupw 'qd, 'dm['imm4_vdup]");
1368 } else {
1369 Unknown(instr);
1370 }
1371 } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 0) &&
1372 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
1373 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 10)) {
1374 Format(instr, "vzipqw 'qd, 'qm");
1375 } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
1376 (instr->Bits(23, 2) == 2)) {
1377 Format(instr, "vceqq'sz 'qd, 'qn, 'qm");
1378 } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
1379 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
1380 Format(instr, "vceqqs 'qd, 'qn, 'qm");
1381 } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
1382 (instr->Bits(23, 2) == 0)) {
1383 Format(instr, "vcgeq'sz 'qd, 'qn, 'qm");
1384 } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
1385 (instr->Bits(23, 2) == 2)) {
1386 Format(instr, "vcugeq'sz 'qd, 'qn, 'qm");
1387 } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
1388 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
1389 Format(instr, "vcgeqs 'qd, 'qn, 'qm");
1390 } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
1391 (instr->Bits(23, 2) == 0)) {
1392 Format(instr, "vcgtq'sz 'qd, 'qn, 'qm");
1393 } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
1394 (instr->Bits(23, 2) == 2)) {
1395 Format(instr, "vcugtq'sz 'qd, 'qn, 'qm");
1396 } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
1397 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 2)) {
1398 Format(instr, "vcgtqs 'qd, 'qn, 'qm");
1399 } else {
1400 Unknown(instr);
1401 }
1402 } else {
1403 if ((instr->Bits(23, 2) == 3) && (instr->Bits(20, 2) == 3) &&
1404 (instr->Bits(10, 2) == 2) && (instr->Bit(4) == 0)) {
1405 Format(instr, "vtbl 'dd, 'dtbllist, 'dm");
1406 } else {
1407 Unknown(instr);
1408 }
1409 }
1410}
1411
1412void ARMDecoder::InstructionDecode(uword pc) {
1413 Instr* instr = Instr::At(pc);
1414
1415 if (instr->ConditionField() == kSpecialCondition) {
1416 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
1417 Format(instr, "clrex");
1418 } else if (instr->InstructionBits() ==
1419 static_cast<int32_t>(kDataMemoryBarrier)) {
1420 Format(instr, "dmb ish");
1421 } else {
1422 if (instr->IsSIMDDataProcessing()) {
1423 DecodeSIMDDataProcessing(instr);
1424 } else {
1425 Unknown(instr);
1426 }
1427 }
1428 } else {
1429 switch (instr->TypeField()) {
1430 case 0:
1431 case 1: {
1432 DecodeType01(instr);
1433 break;
1434 }
1435 case 2: {
1436 DecodeType2(instr);
1437 break;
1438 }
1439 case 3: {
1440 DecodeType3(instr);
1441 break;
1442 }
1443 case 4: {
1444 DecodeType4(instr);
1445 break;
1446 }
1447 case 5: {
1448 DecodeType5(instr);
1449 break;
1450 }
1451 case 6: {
1452 DecodeType6(instr);
1453 break;
1454 }
1455 case 7: {
1456 DecodeType7(instr);
1457 break;
1458 }
1459 default: {
1460 // The type field is 3-bits in the ARM encoding.
1461 UNREACHABLE();
1462 break;
1463 }
1464 }
1465 }
1466}
1467
1468void Disassembler::DecodeInstruction(char* hex_buffer,
1469 intptr_t hex_size,
1470 char* human_buffer,
1471 intptr_t human_size,
1472 int* out_instr_size,
1473 const Code& code,
1474 Object** object,
1475 uword pc) {
1476 ARMDecoder decoder(human_buffer, human_size);
1477 decoder.InstructionDecode(pc);
1478 int32_t instruction_bits = Instr::At(pc)->InstructionBits();
1479 Utils::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
1480 if (out_instr_size) {
1481 *out_instr_size = Instr::kInstrSize;
1482 }
1483
1484 *object = NULL;
1485 // TODO(36839): Make DecodeLoadObjectFromPoolOrThread work on simarm_x64.
1486#if !defined(IS_SIMARM_X64)
1487 if (!code.IsNull()) {
1488 *object = &Object::Handle();
1489 if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
1490 *object = NULL;
1491 }
1492 }
1493#endif // !defined(IS_SIMARM_X64)
1494}
1495
1496#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
1497
1498} // namespace dart
1499
1500#endif // defined(TARGET_ARCH_ARM)
1501