Flutter Engine
The Flutter Engine
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:483
#define ASSERT(E)
uint32_t uint32_t * format
Definition: dart_vm.cc:33
uintptr_t uword
Definition: globals.h:501
@ kSpecialCondition
@ kNumberOfConditions
@ kNumberOfCpuRegisters
Definition: constants_arm.h:98
constexpr uword kDataMemoryBarrier
bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code &code, Object *obj)
@ kRnShift
@ kDivRmShift
@ kRmShift
@ kDivRnShift
@ kBitFieldExtractRnShift
@ kDivRdShift
@ kRsShift
@ kNumberOfSRegisters
const char *const cpu_reg_names[kNumberOfCpuRegisters]
@ kNumberOfQRegisters
@ kNumberOfDRegisters
@ kMaxShift
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
def 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