Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
static const uint8_t buffer[]
uint32_t uint32_t * format
static Condition InvertCondition(Condition c)
uintptr_t uword
Definition globals.h:501
@ kNumberOfConditions
@ kNumberOfCpuRegisters
bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code &code, Object *obj)
@ kNumberOfVRegisters
const char *const cpu_reg_names[kNumberOfCpuRegisters]
@ MiscDP3SourceMask
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
Point offset