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