Flutter Engine
The Flutter Engine
disassembler_arm64.cc
Go to the documentation of this file.
1// Copyright (c) 2014, 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_ARM64.
6#if defined(TARGET_ARCH_ARM64)
7
9
10#include "platform/assert.h"
11#include "vm/instructions.h"
12
13namespace dart {
14
15#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
16
17class ARM64Decoder : public ValueObject {
18 public:
19 ARM64Decoder(char* buffer, size_t buffer_size)
20 : buffer_(buffer), buffer_size_(buffer_size), buffer_pos_(0) {
21 buffer_[buffer_pos_] = '\0';
22 }
23
24 ~ARM64Decoder() {}
25
26 // Writes one disassembled instruction into 'buffer' (0-terminated).
27 // Returns true if the instruction was successfully decoded, false otherwise.
28 void InstructionDecode(uword pc);
29
30 private:
31 // Bottleneck functions to print into the out_buffer.
32 void Print(const char* str);
33 void PrintInt(int value);
34
35 // Printing of common values.
36 void PrintRegister(int reg, R31Type r31t);
37 void PrintVRegister(int reg);
38 void PrintShiftExtendRm(Instr* instr);
39 void PrintMemOperand(Instr* instr);
40 void PrintPairMemOperand(Instr* instr);
41 void PrintS(Instr* instr);
42 void PrintCondition(Instr* instr);
43 void PrintInvertedCondition(Instr* instr);
44
45 // Handle formatting of instructions and their options.
46 int FormatRegister(Instr* instr, const char* option);
47 int FormatVRegister(Instr* instr, const char* option);
48 int FormatOption(Instr* instr, const char* format);
49 void Format(Instr* instr, const char* format);
50 void Unknown(Instr* instr);
51
52// Decode instructions.
53#define DECODE_OP(op) void Decode##op(Instr* instr);
55#undef DECODE_OP
56
57 // Convenience functions.
58 char* get_buffer() const { return buffer_; }
59 char* current_position_in_buffer() { return buffer_ + buffer_pos_; }
60 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; }
61
62 char* buffer_; // Decode instructions into this buffer.
63 size_t buffer_size_; // The size of the character buffer.
64 size_t buffer_pos_; // Current character position in buffer.
65
67 DISALLOW_COPY_AND_ASSIGN(ARM64Decoder);
68};
69
70// Support for assertions in the ARM64Decoder formatting functions.
71#define STRING_STARTS_WITH(string, compare_string) \
72 (strncmp(string, compare_string, strlen(compare_string)) == 0)
73
74// Append the str to the output buffer.
75void ARM64Decoder::Print(const char* str) {
76 char cur = *str++;
77 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) {
78 buffer_[buffer_pos_++] = cur;
79 cur = *str++;
80 }
81 buffer_[buffer_pos_] = '\0';
82}
83
84void ARM64Decoder::PrintInt(int value) {
85 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
86 remaining_size_in_buffer(), "%d", value);
87 buffer_[buffer_pos_] = '\0';
88}
89
90// Print the register name according to the active name converter.
91void ARM64Decoder::PrintRegister(int reg, R31Type r31t) {
92 ASSERT(0 <= reg);
94 if (reg == 31) {
95 const char* rstr = (r31t == R31IsZR) ? "zr" : "csp";
96 Print(rstr);
97 } else {
98 Print(cpu_reg_names[reg]);
99 }
100}
101
102void ARM64Decoder::PrintVRegister(int reg) {
103 ASSERT(0 <= reg);
105 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
106 remaining_size_in_buffer(), "v%d", reg);
107}
108
109// These shift names are defined in a way to match the native disassembler
110// formatting. See for example the command "objdump -d <binary file>".
111static const char* shift_names[kMaxShift] = {"lsl", "lsr", "asr", "ror"};
112
113static const char* extend_names[kMaxExtend] = {
114 "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx",
115};
116
117// These condition names are defined in a way to match the native disassembler
118// formatting. See for example the command "objdump -d <binary file>".
119static const char* cond_names[kNumberOfConditions] = {
120 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
121 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
122};
123
124// Print the condition guarding the instruction.
125void ARM64Decoder::PrintCondition(Instr* instr) {
126 if (instr->IsConditionalSelectOp()) {
127 Print(cond_names[instr->SelectConditionField()]);
128 } else {
129 Print(cond_names[instr->ConditionField()]);
130 }
131}
132
133// Print the inverse of the condition guarding the instruction.
134void ARM64Decoder::PrintInvertedCondition(Instr* instr) {
135 if (instr->IsConditionalSelectOp()) {
136 Print(cond_names[InvertCondition(instr->SelectConditionField())]);
137 } else {
138 Print(cond_names[InvertCondition(instr->ConditionField())]);
139 }
140}
141
142// Print the register shift operands for the instruction. Generally used for
143// data processing instructions.
144void ARM64Decoder::PrintShiftExtendRm(Instr* instr) {
145 int rm = instr->RmField();
146 Shift shift = instr->ShiftTypeField();
147 int shift_amount = instr->ShiftAmountField();
148 Extend extend = instr->ExtendTypeField();
149 int extend_shift_amount = instr->ExtShiftAmountField();
150
151 PrintRegister(rm, R31IsZR);
152
153 if (instr->IsShift() && (shift == LSL) && (shift_amount == 0)) {
154 // Special case for using rm only.
155 return;
156 }
157 if (instr->IsShift()) {
158 // by immediate
159 if ((shift == ROR) && (shift_amount == 0)) {
160 Print(" RRX");
161 return;
162 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
163 shift_amount = 32;
164 }
165 buffer_pos_ +=
166 Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
167 " %s #%d", shift_names[shift], shift_amount);
168 } else {
169 ASSERT(instr->IsExtend());
170 // by register
171 buffer_pos_ +=
172 Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
173 " %s", extend_names[extend]);
174 if (((instr->SFField() == 1) && (extend == UXTX)) ||
175 ((instr->SFField() == 0) && (extend == UXTW))) {
176 // Shift amount.
177 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
178 remaining_size_in_buffer(), " %d",
179 extend_shift_amount);
180 }
181 }
182}
183
184void ARM64Decoder::PrintMemOperand(Instr* instr) {
185 const Register rn = instr->RnField();
186 if (instr->Bit(24) == 1) {
187 // rn + scaled unsigned 12-bit immediate offset.
188 const uint32_t scale = instr->SzField();
189 const uint32_t imm12 = instr->Imm12Field();
190 const uint32_t off = imm12 << scale;
191 Print("[");
192 PrintRegister(rn, R31IsSP);
193 if (off != 0) {
194 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
195 remaining_size_in_buffer(), ", #%d", off);
196 }
197 Print("]");
198 } else {
199 switch (instr->Bits(10, 2)) {
200 case 0: {
201 // rn + signed 9-bit immediate, pre-index, no writeback.
202 const int32_t imm9 = instr->SImm9Field();
203 Print("[");
204 PrintRegister(rn, R31IsSP);
205 buffer_pos_ +=
206 Utils::SNPrint(current_position_in_buffer(),
207 remaining_size_in_buffer(), ", #%d", imm9);
208 Print("]");
209 break;
210 }
211 case 1: {
212 const int32_t imm9 = instr->SImm9Field();
213 // rn + signed 9-bit immediate, post-index, writeback.
214 Print("[");
215 PrintRegister(rn, R31IsSP);
216 Print("]");
217 buffer_pos_ +=
218 Utils::SNPrint(current_position_in_buffer(),
219 remaining_size_in_buffer(), ", #%d !", imm9);
220 break;
221 }
222 case 2: {
223 const Register rm = instr->RmField();
224 const Extend ext = instr->ExtendTypeField();
225 const int s = instr->Bit(12);
226 Print("[");
227 PrintRegister(rn, R31IsSP);
228 Print(", ");
229 PrintRegister(rm, R31IsZR);
230 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
231 remaining_size_in_buffer(), " %s",
232 extend_names[ext]);
233 if (s == 1) {
234 Print(" scaled");
235 }
236 Print("]");
237 break;
238 }
239 case 3: {
240 const int32_t imm9 = instr->SImm9Field();
241 // rn + signed 9-bit immediate, pre-index, writeback.
242 Print("[");
243 PrintRegister(rn, R31IsSP);
244 buffer_pos_ +=
245 Utils::SNPrint(current_position_in_buffer(),
246 remaining_size_in_buffer(), ", #%d", imm9);
247 Print("]!");
248 break;
249 }
250 default: {
251 Print("???");
252 }
253 }
254 }
255}
256
257void ARM64Decoder::PrintPairMemOperand(Instr* instr) {
258 const Register rn = instr->RnField();
259 const uint32_t simm7 = instr->SImm7Field();
260 const intptr_t shift =
261 (instr->Bit(26) == 1) ? 2 + instr->SzField() : 2 + instr->SFField();
262 const int32_t offset = simm7 << shift;
263 Print("[");
264 PrintRegister(rn, R31IsSP);
265 switch (instr->Bits(23, 3)) {
266 case 1:
267 // rn + (imm7 << (2 + B31)), post-index, writeback.
268 buffer_pos_ +=
269 Utils::SNPrint(current_position_in_buffer(),
270 remaining_size_in_buffer(), "], #%d !", offset);
271 break;
272 case 2:
273 // rn + (imm7 << (2 + B31)), pre-index, no writeback.
274 buffer_pos_ +=
275 Utils::SNPrint(current_position_in_buffer(),
276 remaining_size_in_buffer(), ", #%d]", offset);
277 break;
278 case 3:
279 // rn + (imm7 << (2 + B31)), pre-index, writeback.
280 buffer_pos_ +=
281 Utils::SNPrint(current_position_in_buffer(),
282 remaining_size_in_buffer(), ", #%d]!", offset);
283 break;
284 default:
285 Print(", ???]");
286 break;
287 }
288}
289
290// Handle all register based formatting in these functions to reduce the
291// complexity of FormatOption.
292int ARM64Decoder::FormatRegister(Instr* instr, const char* format) {
293 ASSERT(format[0] == 'r');
294 if (format[1] == 'n') { // 'rn: Rn register
295 int reg = instr->RnField();
296 PrintRegister(reg, instr->RnMode());
297 return 2;
298 } else if (format[1] == 'd') { // 'rd: Rd register
299 int reg = instr->RdField();
300 PrintRegister(reg, instr->RdMode());
301 return 2;
302 } else if (format[1] == 'm') { // 'rm: Rm register
303 int reg = instr->RmField();
304 PrintRegister(reg, R31IsZR);
305 return 2;
306 } else if (format[1] == 't') { // 'rt: Rt register
307 if (format[2] == '2') {
308 int reg = instr->Rt2Field();
309 PrintRegister(reg, R31IsZR);
310 return 3;
311 }
312 int reg = instr->RtField();
313 PrintRegister(reg, R31IsZR);
314 return 2;
315 } else if (format[1] == 'a') { // 'ra: Ra register
316 int reg = instr->RaField();
317 PrintRegister(reg, R31IsZR);
318 return 2;
319 } else if (format[1] == 's') { // 'rs: Rs register
320 int reg = instr->RsField();
321 PrintRegister(reg, R31IsZR);
322 return 2;
323 }
324 UNREACHABLE();
325 return -1;
326}
327
328int ARM64Decoder::FormatVRegister(Instr* instr, const char* format) {
329 ASSERT(format[0] == 'v');
330 if (format[1] == 'd') {
331 int reg = instr->VdField();
332 PrintVRegister(reg);
333 return 2;
334 } else if (format[1] == 'n') {
335 int reg = instr->VnField();
336 PrintVRegister(reg);
337 return 2;
338 } else if (format[1] == 'm') {
339 int reg = instr->VmField();
340 PrintVRegister(reg);
341 return 2;
342 } else if (format[1] == 't') {
343 if (format[2] == '2') {
344 int reg = instr->Vt2Field();
345 PrintVRegister(reg);
346 return 3;
347 }
348 int reg = instr->VtField();
349 PrintVRegister(reg);
350 return 2;
351 }
352 UNREACHABLE();
353 return -1;
354}
355
356// FormatOption takes a formatting string and interprets it based on
357// the current instructions. The format string points to the first
358// character of the option string (the option escape has already been
359// consumed by the caller.) FormatOption returns the number of
360// characters that were consumed from the formatting string.
361int ARM64Decoder::FormatOption(Instr* instr, const char* format) {
362 switch (format[0]) {
363 case 'b': {
364 if (format[3] == 'i') {
365 ASSERT(STRING_STARTS_WITH(format, "bitimm"));
366 const uint64_t imm = instr->ImmLogical();
367 buffer_pos_ +=
368 Utils::SNPrint(current_position_in_buffer(),
369 remaining_size_in_buffer(), "0x%" Px64, imm);
370 return 6;
371 } else {
372 ASSERT(STRING_STARTS_WITH(format, "bitpos"));
373 int bitpos = instr->Bits(19, 5) | (instr->Bit(31) << 5);
374 buffer_pos_ +=
375 Utils::SNPrint(current_position_in_buffer(),
376 remaining_size_in_buffer(), "#%d", bitpos);
377 return 6;
378 }
379 }
380 case 'c': {
381 if (format[1] == 's') {
382 ASSERT(STRING_STARTS_WITH(format, "csz"));
383 const int32_t imm5 = instr->Bits(16, 5);
384 char const* typ = "??";
385 if ((imm5 & 0x1) != 0) {
386 typ = "b";
387 } else if ((imm5 & 0x2) != 0) {
388 typ = "h";
389 } else if ((imm5 & 0x4) != 0) {
390 typ = "s";
391 } else if ((imm5 & 0x8) != 0) {
392 typ = "d";
393 }
394 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
395 remaining_size_in_buffer(), "%s", typ);
396 return 3;
397 } else {
398 ASSERT(STRING_STARTS_WITH(format, "cond"));
399 if (format[4] == 'i') {
400 ASSERT(STRING_STARTS_WITH(format, "condinverted"));
401 PrintInvertedCondition(instr);
402 return 12;
403 } else {
404 PrintCondition(instr);
405 return 4;
406 }
407 }
408 }
409 case 'd': {
410 int64_t off;
411 if (format[4] == '2') {
412 ASSERT(STRING_STARTS_WITH(format, "dest26"));
413 off = static_cast<uint64_t>(instr->SImm26Field()) << 2;
414 } else {
415 if (format[5] == '4') {
416 ASSERT(STRING_STARTS_WITH(format, "dest14"));
417 off = static_cast<uint64_t>(instr->SImm14Field()) << 2;
418 } else {
419 ASSERT(STRING_STARTS_WITH(format, "dest19"));
420 off = static_cast<uint64_t>(instr->SImm19Field()) << 2;
421 }
422 }
423 if (FLAG_disassemble_relative) {
424 buffer_pos_ +=
425 Utils::SNPrint(current_position_in_buffer(),
426 remaining_size_in_buffer(), "%+" Pd64 "", off);
427 } else {
428 uword destination = reinterpret_cast<uword>(instr) + off;
429 buffer_pos_ +=
430 Utils::SNPrint(current_position_in_buffer(),
431 remaining_size_in_buffer(), "%#" Px "", destination);
432 }
433 return 6;
434 }
435 case 'f': {
436 ASSERT(STRING_STARTS_WITH(format, "fsz"));
437 const int sz = instr->SzField();
438 char const* sz_str;
439 switch (sz) {
440 case 0:
441 if (instr->Bit(23) == 1) {
442 sz_str = "q";
443 } else {
444 sz_str = "b";
445 }
446 break;
447 case 1:
448 sz_str = "h";
449 break;
450 case 2:
451 sz_str = "s";
452 break;
453 case 3:
454 sz_str = "d";
455 break;
456 default:
457 sz_str = "?";
458 break;
459 }
460 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
461 remaining_size_in_buffer(), "%s", sz_str);
462 return 3;
463 }
464 case 'h': {
465 ASSERT(STRING_STARTS_WITH(format, "hw"));
466 const int shift = instr->HWField() << 4;
467 if (shift != 0) {
468 buffer_pos_ +=
469 Utils::SNPrint(current_position_in_buffer(),
470 remaining_size_in_buffer(), " lsl %d", shift);
471 }
472 return 2;
473 }
474 case 'i': { // 'imm12, 'imm16, 'immd
475 if (format[1] == 'd') {
476 // Element index for a SIMD copy instruction.
477 ASSERT(STRING_STARTS_WITH(format, "idx"));
478 const int32_t imm4 = instr->Bits(11, 4);
479 const int32_t imm5 = instr->Bits(16, 5);
480 int32_t shift = 0;
481 int32_t imm = -1;
482 if (format[3] == '4') {
483 imm = imm4;
484 } else if (format[3] == '5') {
485 imm = imm5;
486 shift = 1;
487 }
488 int32_t idx = -1;
489 if ((imm5 & 0x1) != 0) {
490 idx = imm >> shift;
491 } else if ((imm5 & 0x2) != 0) {
492 idx = imm >> (shift + 1);
493 } else if ((imm5 & 0x4) != 0) {
494 idx = imm >> (shift + 2);
495 } else if ((imm5 & 0x8) != 0) {
496 idx = imm >> (shift + 3);
497 }
498 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
499 remaining_size_in_buffer(), "[%d]", idx);
500 return 4;
501 } else if (format[3] == '1') {
502 uint64_t imm;
503 int ret = 5;
504 if (format[4] == '2') {
505 ASSERT(STRING_STARTS_WITH(format, "imm12"));
506 imm = instr->Imm12Field();
507 if (format[5] == 's') {
508 // shifted immediate.
509 if (instr->Imm12ShiftField() == 1) {
510 imm = imm << 12;
511 } else if ((instr->Imm12ShiftField() & 0x2) != 0) {
512 Print("Unknown Shift");
513 }
514 ret = 6;
515 }
516 } else {
517 ASSERT(STRING_STARTS_WITH(format, "imm16"));
518 imm = instr->Imm16Field();
519 }
520 buffer_pos_ +=
521 Utils::SNPrint(current_position_in_buffer(),
522 remaining_size_in_buffer(), "#0x%" Px64, imm);
523 return ret;
524 } else {
525 ASSERT(STRING_STARTS_WITH(format, "imm"));
526 if (format[3] == 'd') {
527 double dimm = bit_cast<double, int64_t>(
528 Instr::VFPExpandImm(instr->Imm8Field()));
529 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
530 remaining_size_in_buffer(), "%f", dimm);
531 return 4;
532 } else if (format[3] == 'r') {
533 int immr = instr->ImmRField();
534 buffer_pos_ +=
535 Utils::SNPrint(current_position_in_buffer(),
536 remaining_size_in_buffer(), "#%d", immr);
537 return 4;
538 } else {
539 ASSERT(format[3] == 's');
540 int imms = instr->ImmSField();
541 buffer_pos_ +=
542 Utils::SNPrint(current_position_in_buffer(),
543 remaining_size_in_buffer(), "#%d", imms);
544 return 4;
545 }
546 }
547 }
548 case 'm': {
549 ASSERT(STRING_STARTS_WITH(format, "memop"));
550 PrintMemOperand(instr);
551 return 5;
552 }
553 case 'o': {
554 ASSERT(STRING_STARTS_WITH(format, "opc"));
555 if (instr->Bit(26) == 0) {
556 if (instr->Bit(31) == 0) {
557 if (instr->Bit(30) == 1) {
558 Print("sw");
559 } else {
560 Print("w");
561 }
562 } else {
563 // 64-bit width is most commonly used, no need to print "x".
564 }
565 } else {
566 switch (instr->Bits(30, 2)) {
567 case 0:
568 Print("s");
569 break;
570 case 1:
571 Print("d");
572 break;
573 case 2:
574 Print("q");
575 break;
576 case 3:
577 Print("?");
578 break;
579 }
580 }
581 return 3;
582 }
583 case 'p': {
584 if (format[1] == 'c') {
585 int64_t off;
586 if (format[2] == 'a') {
587 ASSERT(STRING_STARTS_WITH(format, "pcadr"));
588 const uint64_t immhi = instr->SImm19Field();
589 const uint64_t immlo = instr->Bits(29, 2);
590 off = (immhi << 2) | immlo;
591 } else {
592 ASSERT(STRING_STARTS_WITH(format, "pcldr"));
593 off = instr->SImm19Field() << 2;
594 }
595 if (FLAG_disassemble_relative) {
596 buffer_pos_ +=
597 Utils::SNPrint(current_position_in_buffer(),
598 remaining_size_in_buffer(), "%+" Pd64 "", off);
599 } else {
600 const uint64_t pc = reinterpret_cast<int64_t>(instr);
601 const uint64_t dest = pc + off;
602 buffer_pos_ +=
603 Utils::SNPrint(current_position_in_buffer(),
604 remaining_size_in_buffer(), "0x%" Px64, dest);
605 }
606 return 5;
607 } else {
608 ASSERT(STRING_STARTS_WITH(format, "pmemop"));
609 PrintPairMemOperand(instr);
610 return 6;
611 }
612 }
613 case 'r': {
614 return FormatRegister(instr, format);
615 }
616 case 'v': {
617 if (format[1] == 's') {
618 ASSERT(STRING_STARTS_WITH(format, "vsz"));
619 char const* sz_str = nullptr;
620 if (instr->Bits(14, 2) == 3) {
621 switch (instr->Bit(22)) {
622 case 0:
623 sz_str = "s";
624 break;
625 case 1:
626 sz_str = "d";
627 break;
628 default:
629 UNREACHABLE();
630 break;
631 }
632 } else {
633 switch (instr->Bit(22)) {
634 case 0:
635 sz_str = "w";
636 break;
637 case 1:
638 sz_str = "x";
639 break;
640 default:
641 UNREACHABLE();
642 break;
643 }
644 }
645 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
646 remaining_size_in_buffer(), "%s", sz_str);
647 return 3;
648 } else {
649 return FormatVRegister(instr, format);
650 }
651 }
652 case 's': { // 's: S flag.
653 if (format[1] == 'h') {
654 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
655 PrintShiftExtendRm(instr);
656 return 8;
657 } else if (format[1] == 'f') {
658 ASSERT(STRING_STARTS_WITH(format, "sf"));
659 if (instr->SFField() == 1) {
660 // 64-bit width is most commonly used, no need to print "x".
661 } else {
662 Print("w");
663 }
664 return 2;
665 } else if (format[1] == 'z') {
666 ASSERT(STRING_STARTS_WITH(format, "sz"));
667 const int sz = instr->SzField();
668 char const* sz_str;
669 switch (sz) {
670 case 0:
671 sz_str = "b";
672 break;
673 case 1:
674 sz_str = "h";
675 break;
676 case 2:
677 sz_str = "w";
678 break;
679 case 3:
680 // 64-bit width is most commonly used, no need to print "x".
681 sz_str = "";
682 break;
683 default:
684 sz_str = "?";
685 break;
686 }
687 buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
688 remaining_size_in_buffer(), "%s", sz_str);
689 return 2;
690 } else if (format[1] == ' ') {
691 if (instr->HasS()) {
692 Print("s");
693 }
694 return 1;
695 } else {
696 UNREACHABLE();
697 }
698 }
699 default: {
700 UNREACHABLE();
701 break;
702 }
703 }
704 UNREACHABLE();
705 return -1;
706}
707
708// Format takes a formatting string for a whole instruction and prints it into
709// the output buffer. All escaped options are handed to FormatOption to be
710// parsed further.
711void ARM64Decoder::Format(Instr* instr, const char* format) {
712 char cur = *format++;
713 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) {
714 if (cur == '\'') { // Single quote is used as the formatting escape.
715 format += FormatOption(instr, format);
716 } else {
717 buffer_[buffer_pos_++] = cur;
718 }
719 cur = *format++;
720 }
721 buffer_[buffer_pos_] = '\0';
722}
723
724// For currently unimplemented decodings the disassembler calls Unknown(instr)
725// which will just print "unknown" of the instruction bits.
726void ARM64Decoder::Unknown(Instr* instr) {
727 Format(instr, "unknown");
728}
729
730void ARM64Decoder::DecodeMoveWide(Instr* instr) {
731 switch (instr->Bits(29, 2)) {
732 case 0:
733 Format(instr, "movn'sf 'rd, 'imm16'hw");
734 break;
735 case 2:
736 Format(instr, "movz'sf 'rd, 'imm16'hw");
737 break;
738 case 3:
739 Format(instr, "movk'sf 'rd, 'imm16'hw");
740 break;
741 default:
742 Unknown(instr);
743 break;
744 }
745}
746
747void ARM64Decoder::DecodeLoadStoreReg(Instr* instr) {
748 if (instr->Bit(26) == 1) {
749 // SIMD or FP src/dst.
750 if (instr->Bit(22) == 1) {
751 Format(instr, "fldr'fsz 'vt, 'memop");
752 } else {
753 Format(instr, "fstr'fsz 'vt, 'memop");
754 }
755 } else {
756 // Integer src/dst.
757 if (instr->Bits(22, 2) == 0) {
758 Format(instr, "str'sz 'rt, 'memop");
759 } else if (instr->Bits(23, 1) == 1) {
760 Format(instr, "ldrs'sz 'rt, 'memop");
761 } else {
762 Format(instr, "ldr'sz 'rt, 'memop");
763 }
764 }
765}
766
767void ARM64Decoder::DecodeLoadStoreRegPair(Instr* instr) {
768 if (instr->Bit(26) == 1) {
769 // SIMD or FP src/dst.
770 if (instr->Bit(22) == 1) {
771 Format(instr, "fldp'opc 'vt, 'vt2, 'pmemop");
772 } else {
773 Format(instr, "fstp'opc 'vt, 'vt2, 'pmemop");
774 }
775 } else {
776 // Integer src/dst.
777 if (instr->Bit(22) == 1) {
778 Format(instr, "ldp'opc 'rt, 'rt2, 'pmemop");
779 } else {
780 Format(instr, "stp'opc 'rt, 'rt2, 'pmemop");
781 }
782 }
783}
784
785void ARM64Decoder::DecodeLoadRegLiteral(Instr* instr) {
786 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) ||
787 (instr->Bits(24, 3) != 0)) {
788 Unknown(instr);
789 }
790 if (instr->Bit(30) != 0) {
791 Format(instr, "ldrx 'rt, 'pcldr");
792 } else {
793 Format(instr, "ldrw 'rt, 'pcldr");
794 }
795}
796
797void ARM64Decoder::DecodeLoadStoreExclusive(Instr* instr) {
798 if (instr->Bit(32) != 1 || instr->Bit(21) != 0 ||
799 instr->Bit(23) != instr->Bit(15)) {
800 Unknown(instr);
801 }
802
803 const bool is_load = instr->Bit(22) == 1;
804 const bool is_exclusive = instr->Bit(23) == 0;
805 const bool is_ordered = instr->Bit(15) == 1;
806 if (is_load) {
807 const bool is_load_acquire = !is_exclusive && is_ordered;
808 if (is_load_acquire) {
809 Format(instr, "ldar'sz 'rt, ['rn]");
810 } else {
811 Format(instr, "ldxr'sz 'rt, ['rn]");
812 }
813 } else {
814 const bool is_store_release = !is_exclusive && is_ordered;
815 if (is_store_release) {
816 Format(instr, "stlr'sz 'rt, ['rn]");
817 } else {
818 Format(instr, "stxr'sz 'rs, 'rt, ['rn]");
819 }
820 }
821}
822
823void ARM64Decoder::DecodeAtomicMemory(Instr* instr) {
824 switch (instr->Bits(12, 3)) {
825 case 1:
826 Format(instr, "ldclr'sz 'rs, 'rt, ['rn]");
827 break;
828 case 3:
829 Format(instr, "ldset'sz 'rs, 'rt, ['rn]");
830 break;
831 default:
832 Unknown(instr);
833 break;
834 }
835}
836
837void ARM64Decoder::DecodeAddSubImm(Instr* instr) {
838 switch (instr->Bit(30)) {
839 case 0: {
840 if ((instr->RdField() == R31) && (instr->SField() == 1)) {
841 Format(instr, "cmn'sf 'rn, 'imm12s");
842 } else {
843 if (((instr->RdField() == R31) || (instr->RnField() == R31)) &&
844 (instr->Imm12Field() == 0) && (instr->Bit(29) == 0)) {
845 Format(instr, "mov'sf 'rd, 'rn");
846 } else {
847 Format(instr, "add'sf's 'rd, 'rn, 'imm12s");
848 }
849 }
850 break;
851 }
852 case 1: {
853 if ((instr->RdField() == R31) && (instr->SField() == 1)) {
854 Format(instr, "cmp'sf 'rn, 'imm12s");
855 } else {
856 Format(instr, "sub'sf's 'rd, 'rn, 'imm12s");
857 }
858 break;
859 }
860 default:
861 Unknown(instr);
862 break;
863 }
864}
865
866void ARM64Decoder::DecodeBitfield(Instr* instr) {
867 int reg_size = instr->SFField() == 0 ? 32 : 64;
868 int op = instr->Bits(29, 2);
869 int r_imm = instr->ImmRField();
870 int s_imm = instr->ImmSField();
871 switch (op) {
872 case 0:
873 if (r_imm == 0) {
874 if (s_imm == 7) {
875 Format(instr, "sxtb 'rd, 'rn");
876 break;
877 } else if (s_imm == 15) {
878 Format(instr, "sxth 'rd, 'rn");
879 break;
880 } else if (s_imm == 31) {
881 Format(instr, "sxtw 'rd, 'rn");
882 break;
883 }
884 }
885 if (s_imm == (reg_size - 1)) {
886 Format(instr, "asr'sf 'rd, 'rn, 'immr");
887 break;
888 }
889 Format(instr, "sbfm'sf 'rd, 'rn, 'immr, 'imms");
890 break;
891 case 1:
892 Format(instr, "bfm'sf 'rd, 'rn, 'immr, 'imms");
893 break;
894 case 2:
895 if (r_imm == 0) {
896 if (s_imm == 7) {
897 Format(instr, "uxtb 'rd, 'rn");
898 break;
899 } else if (s_imm == 15) {
900 Format(instr, "uxth 'rd, 'rn");
901 break;
902 }
903 }
904 if ((s_imm != (reg_size - 1)) && ((s_imm + 1) == r_imm)) {
905 int shift = reg_size - s_imm - 1;
906 Format(instr, "lsl'sf 'rd, 'rn, #");
907 PrintInt(shift);
908 break;
909 } else if (s_imm == (reg_size - 1)) {
910 Format(instr, "lsr'sf 'rd, 'rn, 'immr");
911 break;
912 }
913 Format(instr, "ubfm'sf 'rd, 'rn, 'immr, 'imms");
914 break;
915 default:
916 Unknown(instr);
917 break;
918 }
919}
920
921void ARM64Decoder::DecodeLogicalImm(Instr* instr) {
922 int op = instr->Bits(29, 2);
923 switch (op) {
924 case 0:
925 Format(instr, "and'sf 'rd, 'rn, 'bitimm");
926 break;
927 case 1: {
928 if (instr->RnField() == R31) {
929 Format(instr, "mov'sf 'rd, 'bitimm");
930 } else {
931 Format(instr, "orr'sf 'rd, 'rn, 'bitimm");
932 }
933 break;
934 }
935 case 2:
936 Format(instr, "eor'sf 'rd, 'rn, 'bitimm");
937 break;
938 case 3:
939 if (instr->RdField() == R31) {
940 Format(instr, "tst'sf 'rn, 'bitimm");
941 } else {
942 Format(instr, "and'sfs 'rd, 'rn, 'bitimm");
943 }
944 break;
945 default:
946 Unknown(instr);
947 break;
948 }
949}
950
951void ARM64Decoder::DecodePCRel(Instr* instr) {
952 const int op = instr->Bit(31);
953 if (op == 0) {
954 Format(instr, "adr 'rd, 'pcadr");
955 } else {
956 Unknown(instr);
957 }
958}
959
960void ARM64Decoder::DecodeDPImmediate(Instr* instr) {
961 if (instr->IsMoveWideOp()) {
962 DecodeMoveWide(instr);
963 } else if (instr->IsAddSubImmOp()) {
964 DecodeAddSubImm(instr);
965 } else if (instr->IsBitfieldOp()) {
966 DecodeBitfield(instr);
967 } else if (instr->IsLogicalImmOp()) {
968 DecodeLogicalImm(instr);
969 } else if (instr->IsPCRelOp()) {
970 DecodePCRel(instr);
971 } else {
972 Unknown(instr);
973 }
974}
975
976void ARM64Decoder::DecodeExceptionGen(Instr* instr) {
977 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) &&
978 (instr->Bits(21, 3) == 0)) {
979 Format(instr, "svc 'imm16");
980 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
981 (instr->Bits(21, 3) == 1)) {
982 Format(instr, "brk 'imm16");
983 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
984 (instr->Bits(21, 3) == 2)) {
985 Format(instr, "hlt 'imm16");
986 } else {
987 Unknown(instr);
988 }
989}
990
991void ARM64Decoder::DecodeSystem(Instr* instr) {
992 if (instr->InstructionBits() == CLREX) {
993 Format(instr, "clrex");
994 return;
995 }
996
997 if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) &&
998 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
999 (instr->Bit(21) == 0)) {
1000 if (instr->Bits(8, 4) == 0) {
1001 Format(instr, "nop");
1002 } else {
1003 Unknown(instr);
1004 }
1005 } else {
1006 Unknown(instr);
1007 }
1008}
1009
1010void ARM64Decoder::DecodeUnconditionalBranchReg(Instr* instr) {
1011 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 5) == 0) &&
1012 (instr->Bits(16, 5) == 0x1f)) {
1013 switch (instr->Bits(21, 4)) {
1014 case 0:
1015 Format(instr, "br 'rn");
1016 break;
1017 case 1:
1018 Format(instr, "blr 'rn");
1019 break;
1020 case 2:
1021 if (instr->RnField() == LINK_REGISTER) {
1022 Format(instr, "ret");
1023 } else {
1024 Format(instr, "ret 'rn");
1025 }
1026 break;
1027 default:
1028 Unknown(instr);
1029 break;
1030 }
1031 }
1032}
1033
1034void ARM64Decoder::DecodeCompareAndBranch(Instr* instr) {
1035 const int op = instr->Bit(24);
1036 if (op == 0) {
1037 Format(instr, "cbz'sf 'rt, 'dest19");
1038 } else {
1039 Format(instr, "cbnz'sf 'rt, 'dest19");
1040 }
1041}
1042
1043void ARM64Decoder::DecodeConditionalBranch(Instr* instr) {
1044 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) {
1045 Unknown(instr);
1046 return;
1047 }
1048 Format(instr, "b'cond 'dest19");
1049}
1050
1051void ARM64Decoder::DecodeTestAndBranch(Instr* instr) {
1052 const int op = instr->Bit(24);
1053 if (op == 0) {
1054 Format(instr, "tbz'sf 'rt, 'bitpos, 'dest14");
1055 } else {
1056 Format(instr, "tbnz'sf 'rt, 'bitpos, 'dest14");
1057 }
1058}
1059
1060void ARM64Decoder::DecodeUnconditionalBranch(Instr* instr) {
1061 const int op = instr->Bit(31);
1062 if (op == 0) {
1063 Format(instr, "b 'dest26");
1064 } else {
1065 Format(instr, "bl 'dest26");
1066 }
1067}
1068
1069void ARM64Decoder::DecodeCompareBranch(Instr* instr) {
1070 if (instr->IsExceptionGenOp()) {
1071 DecodeExceptionGen(instr);
1072 } else if (instr->IsSystemOp()) {
1073 DecodeSystem(instr);
1074 } else if (instr->IsUnconditionalBranchRegOp()) {
1075 DecodeUnconditionalBranchReg(instr);
1076 } else if (instr->IsCompareAndBranchOp()) {
1077 DecodeCompareAndBranch(instr);
1078 } else if (instr->IsConditionalBranchOp()) {
1079 DecodeConditionalBranch(instr);
1080 } else if (instr->IsTestAndBranchOp()) {
1081 DecodeTestAndBranch(instr);
1082 } else if (instr->IsUnconditionalBranchOp()) {
1083 DecodeUnconditionalBranch(instr);
1084 } else {
1085 Unknown(instr);
1086 }
1087}
1088
1089void ARM64Decoder::DecodeLoadStore(Instr* instr) {
1090 if (instr->IsAtomicMemoryOp()) {
1091 DecodeAtomicMemory(instr);
1092 } else if (instr->IsLoadStoreRegOp()) {
1093 DecodeLoadStoreReg(instr);
1094 } else if (instr->IsLoadStoreRegPairOp()) {
1095 DecodeLoadStoreRegPair(instr);
1096 } else if (instr->IsLoadRegLiteralOp()) {
1097 DecodeLoadRegLiteral(instr);
1098 } else if (instr->IsLoadStoreExclusiveOp()) {
1099 DecodeLoadStoreExclusive(instr);
1100 } else {
1101 Unknown(instr);
1102 }
1103}
1104
1105void ARM64Decoder::DecodeAddSubShiftExt(Instr* instr) {
1106 switch (instr->Bit(30)) {
1107 case 0: {
1108 if (instr->RdField() == R31) {
1109 Format(instr, "cmn'sf 'rn, 'shift_op");
1110 } else {
1111 Format(instr, "add'sf's 'rd, 'rn, 'shift_op");
1112 }
1113 break;
1114 }
1115 case 1: {
1116 if (instr->RdField() == R31) {
1117 Format(instr, "cmp'sf 'rn, 'shift_op");
1118 } else {
1119 if (instr->RnField() == R31) {
1120 Format(instr, "neg'sf's 'rd, 'shift_op");
1121 } else {
1122 Format(instr, "sub'sf's 'rd, 'rn, 'shift_op");
1123 }
1124 }
1125 break;
1126 }
1127 default:
1128 UNREACHABLE();
1129 break;
1130 }
1131}
1132
1133void ARM64Decoder::DecodeAddSubWithCarry(Instr* instr) {
1134 switch (instr->Bit(30)) {
1135 case 0: {
1136 Format(instr, "adc'sf's 'rd, 'rn, 'rm");
1137 break;
1138 }
1139 case 1: {
1140 Format(instr, "sbc'sf's 'rd, 'rn, 'rm");
1141 break;
1142 }
1143 default:
1144 UNREACHABLE();
1145 break;
1146 }
1147}
1148
1149void ARM64Decoder::DecodeLogicalShift(Instr* instr) {
1150 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21);
1151 switch (op) {
1152 case 0:
1153 Format(instr, "and'sf 'rd, 'rn, 'shift_op");
1154 break;
1155 case 1:
1156 Format(instr, "bic'sf 'rd, 'rn, 'shift_op");
1157 break;
1158 case 2: {
1159 if ((instr->RnField() == R31) && (instr->IsShift()) &&
1160 (instr->ShiftTypeField() == LSL)) {
1161 if (instr->ShiftAmountField() == 0) {
1162 Format(instr, "mov'sf 'rd, 'rm");
1163 } else {
1164 Format(instr, "lsl'sf 'rd, 'rm, 'imms");
1165 }
1166 } else {
1167 Format(instr, "orr'sf 'rd, 'rn, 'shift_op");
1168 }
1169 break;
1170 }
1171 case 3:
1172 Format(instr, "orn'sf 'rd, 'rn, 'shift_op");
1173 break;
1174 case 4:
1175 Format(instr, "eor'sf 'rd, 'rn, 'shift_op");
1176 break;
1177 case 5:
1178 Format(instr, "eon'sf 'rd, 'rn, 'shift_op");
1179 break;
1180 case 6:
1181 if (instr->RdField() == R31) {
1182 Format(instr, "tst'sf 'rn, 'shift_op");
1183 } else {
1184 Format(instr, "and'sfs 'rd, 'rn, 'shift_op");
1185 }
1186 break;
1187 case 7:
1188 Format(instr, "bic'sfs 'rd, 'rn, 'shift_op");
1189 break;
1190 default:
1191 UNREACHABLE();
1192 break;
1193 }
1194}
1195
1196void ARM64Decoder::DecodeMiscDP1Source(Instr* instr) {
1197 if (instr->Bit(29) != 0) {
1198 Unknown(instr);
1199 }
1200
1201 const int op = instr->Bits(10, 10);
1202 switch (op) {
1203 case 0:
1204 Format(instr, "rbit'sf 'rd, 'rn");
1205 break;
1206 case 4:
1207 Format(instr, "clz'sf 'rd, 'rn");
1208 break;
1209 default:
1210 Unknown(instr);
1211 break;
1212 }
1213}
1214
1215void ARM64Decoder::DecodeMiscDP2Source(Instr* instr) {
1216 if (instr->Bit(29) != 0) {
1217 Unknown(instr);
1218 }
1219
1220 const int op = instr->Bits(10, 5);
1221 switch (op) {
1222 case 2:
1223 Format(instr, "udiv'sf 'rd, 'rn, 'rm");
1224 break;
1225 case 3:
1226 Format(instr, "sdiv'sf 'rd, 'rn, 'rm");
1227 break;
1228 case 8:
1229 Format(instr, "lsl'sf 'rd, 'rn, 'rm");
1230 break;
1231 case 9:
1232 Format(instr, "lsr'sf 'rd, 'rn, 'rm");
1233 break;
1234 case 10:
1235 Format(instr, "asr'sf 'rd, 'rn, 'rm");
1236 break;
1237 default:
1238 Unknown(instr);
1239 break;
1240 }
1241}
1242
1243void ARM64Decoder::DecodeMiscDP3Source(Instr* instr) {
1244 bool zero_operand = instr->RaField() == R31;
1245 int32_t mask = B31 | B30 | B29 | B23 | B22 | B21 | B15 | MiscDP3SourceMask;
1246 int32_t bits = instr->InstructionBits() & mask;
1247
1248 if (bits == MADD || bits == MADDW) {
1249 if (zero_operand) {
1250 Format(instr, "mul'sf 'rd, 'rn, 'rm");
1251 } else {
1252 Format(instr, "madd'sf 'rd, 'rn, 'rm, 'ra");
1253 }
1254 } else if (bits == MSUB || bits == MSUBW) {
1255 if (zero_operand) {
1256 Format(instr, "mneg'sf 'rd, 'rn, 'rm");
1257 } else {
1258 Format(instr, "msub'sf 'rd, 'rn, 'rm, 'ra");
1259 }
1260 } else if (bits == SMULH) {
1261 Format(instr, "smulh 'rd, 'rn, 'rm");
1262 } else if (bits == UMULH) {
1263 Format(instr, "umulh 'rd, 'rn, 'rm");
1264 } else if (bits == UMADDL) {
1265 if (zero_operand) {
1266 Format(instr, "umull 'rd, 'rn, 'rm");
1267 } else {
1268 Format(instr, "umaddl 'rd, 'rn, 'rm, 'ra");
1269 }
1270 } else if (bits == SMADDL) {
1271 if (zero_operand) {
1272 Format(instr, "smull 'rd, 'rn, 'rm");
1273 } else {
1274 Format(instr, "smaddl 'rd, 'rn, 'rm, 'ra");
1275 }
1276 } else if (bits == SMSUBL) {
1277 if (zero_operand) {
1278 Format(instr, "smnegl 'rd, 'rn, 'rm");
1279 } else {
1280 Format(instr, "smsubl 'rd, 'rn, 'rm, 'ra");
1281 }
1282 } else if (bits == UMSUBL) {
1283 if (zero_operand) {
1284 Format(instr, "umnegl 'rd, 'rn, 'rm");
1285 } else {
1286 Format(instr, "umsubl 'rd, 'rn, 'rm, 'ra");
1287 }
1288 } else {
1289 Unknown(instr);
1290 }
1291}
1292
1293void ARM64Decoder::DecodeConditionalSelect(Instr* instr) {
1294 int cond = instr->SelectConditionField();
1295 bool non_select =
1296 (instr->RnField() == instr->RmField()) && ((cond & 0xe) != 0xe);
1297 if ((instr->Bits(29, 2) == 0) && (instr->Bits(10, 2) == 0)) {
1298 Format(instr, "csel'sf 'rd, 'rn, 'rm, 'cond");
1299 } else if ((instr->Bits(29, 2) == 0) && (instr->Bits(10, 2) == 1)) {
1300 if (non_select) {
1301 Format(instr, "csinc'sf 'rd, 'rn, 'rm, 'cond");
1302 } else {
1303 Format(instr, "cinc'sf 'rd, 'rn, 'condinverted");
1304 }
1305 } else if ((instr->Bits(29, 2) == 2) && (instr->Bits(10, 2) == 0)) {
1306 if (non_select) {
1307 Format(instr, "cinv'sf 'rd, 'rn, 'condinverted");
1308 } else {
1309 Format(instr, "csinv'sf 'rd, 'rn, 'rm, 'cond");
1310 }
1311 } else if ((instr->Bits(29, 2) == 2) && (instr->Bits(10, 2) == 1)) {
1312 if (non_select) {
1313 Format(instr, "cneg'sf 'rd, 'rn, 'condinverted");
1314 } else {
1315 Format(instr, "csneg'sf 'rd, 'rn, 'rm, 'cond");
1316 }
1317 } else {
1318 Unknown(instr);
1319 }
1320}
1321
1322void ARM64Decoder::DecodeDPRegister(Instr* instr) {
1323 if (instr->IsAddSubShiftExtOp()) {
1324 DecodeAddSubShiftExt(instr);
1325 } else if (instr->IsAddSubWithCarryOp()) {
1326 DecodeAddSubWithCarry(instr);
1327 } else if (instr->IsLogicalShiftOp()) {
1328 DecodeLogicalShift(instr);
1329 } else if (instr->IsMiscDP1SourceOp()) {
1330 DecodeMiscDP1Source(instr);
1331 } else if (instr->IsMiscDP2SourceOp()) {
1332 DecodeMiscDP2Source(instr);
1333 } else if (instr->IsMiscDP3SourceOp()) {
1334 DecodeMiscDP3Source(instr);
1335 } else if (instr->IsConditionalSelectOp()) {
1336 DecodeConditionalSelect(instr);
1337 } else {
1338 Unknown(instr);
1339 }
1340}
1341
1342void ARM64Decoder::DecodeSIMDCopy(Instr* instr) {
1343 const int32_t Q = instr->Bit(30);
1344 const int32_t op = instr->Bit(29);
1345 const int32_t imm4 = instr->Bits(11, 4);
1346
1347 if ((op == 0) && (imm4 == 7)) {
1348 if (Q == 0) {
1349 Format(instr, "vmovrs 'rd, 'vn'idx5");
1350 } else {
1351 Format(instr, "vmovrd 'rd, 'vn'idx5");
1352 }
1353 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) {
1354 Format(instr, "vdup'csz 'vd, 'vn'idx5");
1355 } else if ((Q == 1) && (op == 0) && (imm4 == 3)) {
1356 Format(instr, "vins'csz 'vd'idx5, 'rn");
1357 } else if ((Q == 1) && (op == 0) && (imm4 == 1)) {
1358 Format(instr, "vdup'csz 'vd, 'rn");
1359 } else if ((Q == 1) && (op == 1)) {
1360 Format(instr, "vins'csz 'vd'idx5, 'vn'idx4");
1361 } else {
1362 Unknown(instr);
1363 }
1364}
1365
1366void ARM64Decoder::DecodeSIMDThreeSame(Instr* instr) {
1367 const int32_t Q = instr->Bit(30);
1368 const int32_t U = instr->Bit(29);
1369 const int32_t opcode = instr->Bits(11, 5);
1370
1371 if (Q == 0) {
1372 Unknown(instr);
1373 return;
1374 }
1375
1376 if ((U == 0) && (opcode == 0x3)) {
1377 if (instr->Bit(23) == 0) {
1378 Format(instr, "vand 'vd, 'vn, 'vm");
1379 } else {
1380 Format(instr, "vorr 'vd, 'vn, 'vm");
1381 }
1382 } else if ((U == 1) && (opcode == 0x3)) {
1383 Format(instr, "veor 'vd, 'vn, 'vm");
1384 } else if ((U == 0) && (opcode == 0x10)) {
1385 Format(instr, "vadd'vsz 'vd, 'vn, 'vm");
1386 } else if ((U == 1) && (opcode == 0x10)) {
1387 Format(instr, "vsub'vsz 'vd, 'vn, 'vm");
1388 } else if ((U == 0) && (opcode == 0x1a)) {
1389 if (instr->Bit(23) == 0) {
1390 Format(instr, "vadd'vsz 'vd, 'vn, 'vm");
1391 } else {
1392 Format(instr, "vsub'vsz 'vd, 'vn, 'vm");
1393 }
1394 } else if ((U == 1) && (opcode == 0x1b)) {
1395 Format(instr, "vmul'vsz 'vd, 'vn, 'vm");
1396 } else if ((U == 1) && (opcode == 0x1f)) {
1397 Format(instr, "vdiv'vsz 'vd, 'vn, 'vm");
1398 } else if ((U == 0) && (opcode == 0x1c)) {
1399 Format(instr, "vceq'vsz 'vd, 'vn, 'vm");
1400 } else if ((U == 1) && (opcode == 0x1c)) {
1401 if (instr->Bit(23) == 1) {
1402 Format(instr, "vcgt'vsz 'vd, 'vn, 'vm");
1403 } else {
1404 Format(instr, "vcge'vsz 'vd, 'vn, 'vm");
1405 }
1406 } else if ((U == 0) && (opcode == 0x1e)) {
1407 if (instr->Bit(23) == 1) {
1408 Format(instr, "vmin'vsz 'vd, 'vn, 'vm");
1409 } else {
1410 Format(instr, "vmax'vsz 'vd, 'vn, 'vm");
1411 }
1412 } else if ((U == 0) && (opcode == 0x1f)) {
1413 if (instr->Bit(23) == 1) {
1414 Format(instr, "vrsqrt'vsz 'vd, 'vn, 'vm");
1415 } else {
1416 Format(instr, "vrecps'vsz 'vd, 'vn, 'vm");
1417 }
1418 } else {
1419 Unknown(instr);
1420 }
1421}
1422
1423void ARM64Decoder::DecodeSIMDTwoReg(Instr* instr) {
1424 const int32_t Q = instr->Bit(30);
1425 const int32_t U = instr->Bit(29);
1426 const int32_t op = instr->Bits(12, 5);
1427 const int32_t sz = instr->Bits(22, 2);
1428
1429 if (Q == 0) {
1430 Unknown(instr);
1431 return;
1432 }
1433
1434 if ((U == 1) && (op == 0x5)) {
1435 Format(instr, "vnot 'vd, 'vn");
1436 } else if ((U == 0) && (op == 0xf)) {
1437 if (sz == 2) {
1438 Format(instr, "vabss 'vd, 'vn");
1439 } else if (sz == 3) {
1440 Format(instr, "vabsd 'vd, 'vn");
1441 } else {
1442 Unknown(instr);
1443 }
1444 } else if ((U == 1) && (op == 0xf)) {
1445 if (sz == 2) {
1446 Format(instr, "vnegs 'vd, 'vn");
1447 } else if (sz == 3) {
1448 Format(instr, "vnegd 'vd, 'vn");
1449 } else {
1450 Unknown(instr);
1451 }
1452 } else if ((U == 1) && (op == 0x1f)) {
1453 if (sz == 2) {
1454 Format(instr, "vsqrts 'vd, 'vn");
1455 } else if (sz == 3) {
1456 Format(instr, "vsqrtd 'vd, 'vn");
1457 } else {
1458 Unknown(instr);
1459 }
1460 } else if ((U == 0) && (op == 0x1d)) {
1461 if (sz != 2) {
1462 Unknown(instr);
1463 return;
1464 }
1465 Format(instr, "vrecpes 'vd, 'vn");
1466 } else if ((U == 1) && (op == 0x1d)) {
1467 if (sz != 2) {
1468 Unknown(instr);
1469 return;
1470 }
1471 Format(instr, "vrsqrtes 'vd, 'vn");
1472 } else {
1473 Unknown(instr);
1474 }
1475}
1476
1477void ARM64Decoder::DecodeDPSimd1(Instr* instr) {
1478 if (instr->IsSIMDCopyOp()) {
1479 DecodeSIMDCopy(instr);
1480 } else if (instr->IsSIMDThreeSameOp()) {
1481 DecodeSIMDThreeSame(instr);
1482 } else if (instr->IsSIMDTwoRegOp()) {
1483 DecodeSIMDTwoReg(instr);
1484 } else {
1485 Unknown(instr);
1486 }
1487}
1488
1489void ARM64Decoder::DecodeFPImm(Instr* instr) {
1490 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || (instr->Bit(23) != 0) ||
1491 (instr->Bits(5, 5) != 0)) {
1492 Unknown(instr);
1493 return;
1494 }
1495 if (instr->Bit(22) == 1) {
1496 // Double.
1497 Format(instr, "fmovd 'vd, 'immd");
1498 } else {
1499 // Single.
1500 Unknown(instr);
1501 }
1502}
1503
1504void ARM64Decoder::DecodeFPIntCvt(Instr* instr) {
1505 if ((instr->Bit(29) != 0)) {
1506 Unknown(instr);
1507 return;
1508 }
1509
1510 if ((instr->SFField() == 0) && (instr->Bits(22, 2) == 0)) {
1511 if (instr->Bits(16, 5) == 6) {
1512 Format(instr, "fmovrs'sf 'rd, 'vn");
1513 } else if (instr->Bits(16, 5) == 7) {
1514 Format(instr, "fmovsr'sf 'vd, 'rn");
1515 } else {
1516 Unknown(instr);
1517 }
1518 } else if (instr->Bits(22, 2) == 1) {
1519 if (instr->Bits(16, 5) == 2) {
1520 Format(instr, "scvtfd'sf 'vd, 'rn");
1521 } else if (instr->Bits(16, 5) == 6) {
1522 Format(instr, "fmovrd'sf 'rd, 'vn");
1523 } else if (instr->Bits(16, 5) == 7) {
1524 Format(instr, "fmovdr'sf 'vd, 'rn");
1525 } else if (instr->Bits(16, 5) == 8) {
1526 Format(instr, "fcvtps'sf 'rd, 'vn");
1527 } else if (instr->Bits(16, 5) == 16) {
1528 Format(instr, "fcvtms'sf 'rd, 'vn");
1529 } else if (instr->Bits(16, 5) == 24) {
1530 Format(instr, "fcvtzs'sf 'rd, 'vn");
1531 } else {
1532 Unknown(instr);
1533 }
1534 } else {
1535 Unknown(instr);
1536 }
1537}
1538
1539void ARM64Decoder::DecodeFPOneSource(Instr* instr) {
1540 const int opc = instr->Bits(15, 6);
1541
1542 if ((opc != 5) && (instr->Bit(22) != 1)) {
1543 // Source is interpreted as single-precision only if we're doing a
1544 // conversion from single -> double.
1545 Unknown(instr);
1546 return;
1547 }
1548
1549 switch (opc) {
1550 case 0:
1551 Format(instr, "fmovdd 'vd, 'vn");
1552 break;
1553 case 1:
1554 Format(instr, "fabsd 'vd, 'vn");
1555 break;
1556 case 2:
1557 Format(instr, "fnegd 'vd, 'vn");
1558 break;
1559 case 3:
1560 Format(instr, "fsqrtd 'vd, 'vn");
1561 break;
1562 case 4:
1563 Format(instr, "fcvtsd 'vd, 'vn");
1564 break;
1565 case 5:
1566 Format(instr, "fcvtds 'vd, 'vn");
1567 break;
1568 default:
1569 Unknown(instr);
1570 break;
1571 }
1572}
1573
1574void ARM64Decoder::DecodeFPTwoSource(Instr* instr) {
1575 if (instr->Bits(22, 2) != 1) {
1576 Unknown(instr);
1577 return;
1578 }
1579 const int opc = instr->Bits(12, 4);
1580
1581 switch (opc) {
1582 case 0:
1583 Format(instr, "fmuld 'vd, 'vn, 'vm");
1584 break;
1585 case 1:
1586 Format(instr, "fdivd 'vd, 'vn, 'vm");
1587 break;
1588 case 2:
1589 Format(instr, "faddd 'vd, 'vn, 'vm");
1590 break;
1591 case 3:
1592 Format(instr, "fsubd 'vd, 'vn, 'vm");
1593 break;
1594 default:
1595 Unknown(instr);
1596 break;
1597 }
1598}
1599
1600void ARM64Decoder::DecodeFPCompare(Instr* instr) {
1601 if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 0)) {
1602 Format(instr, "fcmpd 'vn, 'vm");
1603 } else if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 1)) {
1604 if (instr->VmField() == V0) {
1605 Format(instr, "fcmpd 'vn, #0.0");
1606 } else {
1607 Unknown(instr);
1608 }
1609 } else {
1610 Unknown(instr);
1611 }
1612}
1613
1614void ARM64Decoder::DecodeFP(Instr* instr) {
1615 if (instr->IsFPImmOp()) {
1616 DecodeFPImm(instr);
1617 } else if (instr->IsFPIntCvtOp()) {
1618 DecodeFPIntCvt(instr);
1619 } else if (instr->IsFPOneSourceOp()) {
1620 DecodeFPOneSource(instr);
1621 } else if (instr->IsFPTwoSourceOp()) {
1622 DecodeFPTwoSource(instr);
1623 } else if (instr->IsFPCompareOp()) {
1624 DecodeFPCompare(instr);
1625 } else {
1626 Unknown(instr);
1627 }
1628}
1629
1630void ARM64Decoder::DecodeDPSimd2(Instr* instr) {
1631 if (instr->IsFPOp()) {
1632 DecodeFP(instr);
1633 } else {
1634 Unknown(instr);
1635 }
1636}
1637
1638void ARM64Decoder::InstructionDecode(uword pc) {
1639 Instr* instr = Instr::At(pc);
1640
1641 if (instr->IsDPImmediateOp()) {
1642 DecodeDPImmediate(instr);
1643 } else if (instr->IsCompareBranchOp()) {
1644 DecodeCompareBranch(instr);
1645 } else if (instr->IsLoadStoreOp()) {
1646 DecodeLoadStore(instr);
1647 } else if (instr->IsDPRegisterOp()) {
1648 DecodeDPRegister(instr);
1649 } else if (instr->IsDPSimd1Op()) {
1650 DecodeDPSimd1(instr);
1651 } else if (instr->IsDPSimd2Op()) {
1652 DecodeDPSimd2(instr);
1653 } else {
1654 Unknown(instr);
1655 }
1656}
1657
1658void Disassembler::DecodeInstruction(char* hex_buffer,
1659 intptr_t hex_size,
1660 char* human_buffer,
1661 intptr_t human_size,
1662 int* out_instr_size,
1663 const Code& code,
1664 Object** object,
1665 uword pc) {
1666 ARM64Decoder decoder(human_buffer, human_size);
1667 decoder.InstructionDecode(pc);
1668 int32_t instruction_bits = Instr::At(pc)->InstructionBits();
1669 Utils::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
1670 if (out_instr_size != nullptr) {
1671 *out_instr_size = Instr::kInstrSize;
1672 }
1673
1674 *object = nullptr;
1675 if (!code.IsNull()) {
1676 *object = &Object::Handle();
1677 if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
1678 *object = nullptr;
1679 }
1680 }
1681}
1682
1683#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
1684
1685} // namespace dart
1686
1687#endif // defined(TARGET_ARCH_ARM64)
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)
#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 int64_t VFPExpandImm(uint8_t imm8)
static Object & Handle()
Definition: object.h:407
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
#define APPLY_OP_LIST(_V)
#define LINK_REGISTER
#define ASSERT(E)
struct MyStruct s
uint8_t value
uint32_t uint32_t * format
Definition: dart_vm.cc:33
static Condition InvertCondition(Condition c)
uintptr_t uword
Definition: globals.h:501
@ kNumberOfConditions
@ kNumberOfCpuRegisters
Definition: constants_arm.h:98
bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code &code, Object *obj)
@ kNumberOfVRegisters
const char *const cpu_reg_names[kNumberOfCpuRegisters]
@ kMaxShift
@ MiscDP3SourceMask
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
dest
Definition: zip.py:79
#define Px
Definition: globals.h:410
#define Pd64
Definition: globals.h:416
#define Px64
Definition: globals.h:418
#define DISALLOW_ALLOCATION()
Definition: globals.h:604
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
#define DECODE_OP(op)
const Scalar scale
SeparatedVector2 offset