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