1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <assert.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <string.h>
9
10 #if V8_TARGET_ARCH_ARM64
11
12 #include "src/arm64/decoder-arm64-inl.h"
13 #include "src/arm64/disasm-arm64.h"
14 #include "src/arm64/utils-arm64.h"
15 #include "src/base/platform/platform.h"
16 #include "src/disasm.h"
17 #include "src/macro-assembler.h"
18
19 namespace v8 {
20 namespace internal {
21
22
DisassemblingDecoder()23 DisassemblingDecoder::DisassemblingDecoder() {
24 buffer_size_ = 256;
25 buffer_ = reinterpret_cast<char*>(malloc(buffer_size_));
26 buffer_pos_ = 0;
27 own_buffer_ = true;
28 }
29
30
DisassemblingDecoder(char * text_buffer,int buffer_size)31 DisassemblingDecoder::DisassemblingDecoder(char* text_buffer, int buffer_size) {
32 buffer_size_ = buffer_size;
33 buffer_ = text_buffer;
34 buffer_pos_ = 0;
35 own_buffer_ = false;
36 }
37
38
~DisassemblingDecoder()39 DisassemblingDecoder::~DisassemblingDecoder() {
40 if (own_buffer_) {
41 free(buffer_);
42 }
43 }
44
45
GetOutput()46 char* DisassemblingDecoder::GetOutput() { return buffer_; }
47
48
VisitAddSubImmediate(Instruction * instr)49 void DisassemblingDecoder::VisitAddSubImmediate(Instruction* instr) {
50 bool rd_is_zr = RdIsZROrSP(instr);
51 bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
52 (instr->ImmAddSub() == 0) ? true : false;
53 const char *mnemonic = "";
54 const char *form = "'Rds, 'Rns, 'IAddSub";
55 const char *form_cmp = "'Rns, 'IAddSub";
56 const char *form_mov = "'Rds, 'Rns";
57
58 switch (instr->Mask(AddSubImmediateMask)) {
59 case ADD_w_imm:
60 case ADD_x_imm: {
61 mnemonic = "add";
62 if (stack_op) {
63 mnemonic = "mov";
64 form = form_mov;
65 }
66 break;
67 }
68 case ADDS_w_imm:
69 case ADDS_x_imm: {
70 mnemonic = "adds";
71 if (rd_is_zr) {
72 mnemonic = "cmn";
73 form = form_cmp;
74 }
75 break;
76 }
77 case SUB_w_imm:
78 case SUB_x_imm: mnemonic = "sub"; break;
79 case SUBS_w_imm:
80 case SUBS_x_imm: {
81 mnemonic = "subs";
82 if (rd_is_zr) {
83 mnemonic = "cmp";
84 form = form_cmp;
85 }
86 break;
87 }
88 default: UNREACHABLE();
89 }
90 Format(instr, mnemonic, form);
91 }
92
93
VisitAddSubShifted(Instruction * instr)94 void DisassemblingDecoder::VisitAddSubShifted(Instruction* instr) {
95 bool rd_is_zr = RdIsZROrSP(instr);
96 bool rn_is_zr = RnIsZROrSP(instr);
97 const char *mnemonic = "";
98 const char* form = "'Rd, 'Rn, 'Rm'NDP";
99 const char* form_cmp = "'Rn, 'Rm'NDP";
100 const char* form_neg = "'Rd, 'Rm'NDP";
101
102 switch (instr->Mask(AddSubShiftedMask)) {
103 case ADD_w_shift:
104 case ADD_x_shift: mnemonic = "add"; break;
105 case ADDS_w_shift:
106 case ADDS_x_shift: {
107 mnemonic = "adds";
108 if (rd_is_zr) {
109 mnemonic = "cmn";
110 form = form_cmp;
111 }
112 break;
113 }
114 case SUB_w_shift:
115 case SUB_x_shift: {
116 mnemonic = "sub";
117 if (rn_is_zr) {
118 mnemonic = "neg";
119 form = form_neg;
120 }
121 break;
122 }
123 case SUBS_w_shift:
124 case SUBS_x_shift: {
125 mnemonic = "subs";
126 if (rd_is_zr) {
127 mnemonic = "cmp";
128 form = form_cmp;
129 } else if (rn_is_zr) {
130 mnemonic = "negs";
131 form = form_neg;
132 }
133 break;
134 }
135 default: UNREACHABLE();
136 }
137 Format(instr, mnemonic, form);
138 }
139
140
VisitAddSubExtended(Instruction * instr)141 void DisassemblingDecoder::VisitAddSubExtended(Instruction* instr) {
142 bool rd_is_zr = RdIsZROrSP(instr);
143 const char *mnemonic = "";
144 Extend mode = static_cast<Extend>(instr->ExtendMode());
145 const char *form = ((mode == UXTX) || (mode == SXTX)) ?
146 "'Rds, 'Rns, 'Xm'Ext" : "'Rds, 'Rns, 'Wm'Ext";
147 const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ?
148 "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
149
150 switch (instr->Mask(AddSubExtendedMask)) {
151 case ADD_w_ext:
152 case ADD_x_ext: mnemonic = "add"; break;
153 case ADDS_w_ext:
154 case ADDS_x_ext: {
155 mnemonic = "adds";
156 if (rd_is_zr) {
157 mnemonic = "cmn";
158 form = form_cmp;
159 }
160 break;
161 }
162 case SUB_w_ext:
163 case SUB_x_ext: mnemonic = "sub"; break;
164 case SUBS_w_ext:
165 case SUBS_x_ext: {
166 mnemonic = "subs";
167 if (rd_is_zr) {
168 mnemonic = "cmp";
169 form = form_cmp;
170 }
171 break;
172 }
173 default: UNREACHABLE();
174 }
175 Format(instr, mnemonic, form);
176 }
177
178
VisitAddSubWithCarry(Instruction * instr)179 void DisassemblingDecoder::VisitAddSubWithCarry(Instruction* instr) {
180 bool rn_is_zr = RnIsZROrSP(instr);
181 const char *mnemonic = "";
182 const char *form = "'Rd, 'Rn, 'Rm";
183 const char *form_neg = "'Rd, 'Rm";
184
185 switch (instr->Mask(AddSubWithCarryMask)) {
186 case ADC_w:
187 case ADC_x: mnemonic = "adc"; break;
188 case ADCS_w:
189 case ADCS_x: mnemonic = "adcs"; break;
190 case SBC_w:
191 case SBC_x: {
192 mnemonic = "sbc";
193 if (rn_is_zr) {
194 mnemonic = "ngc";
195 form = form_neg;
196 }
197 break;
198 }
199 case SBCS_w:
200 case SBCS_x: {
201 mnemonic = "sbcs";
202 if (rn_is_zr) {
203 mnemonic = "ngcs";
204 form = form_neg;
205 }
206 break;
207 }
208 default: UNREACHABLE();
209 }
210 Format(instr, mnemonic, form);
211 }
212
213
VisitLogicalImmediate(Instruction * instr)214 void DisassemblingDecoder::VisitLogicalImmediate(Instruction* instr) {
215 bool rd_is_zr = RdIsZROrSP(instr);
216 bool rn_is_zr = RnIsZROrSP(instr);
217 const char *mnemonic = "";
218 const char *form = "'Rds, 'Rn, 'ITri";
219
220 if (instr->ImmLogical() == 0) {
221 // The immediate encoded in the instruction is not in the expected format.
222 Format(instr, "unallocated", "(LogicalImmediate)");
223 return;
224 }
225
226 switch (instr->Mask(LogicalImmediateMask)) {
227 case AND_w_imm:
228 case AND_x_imm: mnemonic = "and"; break;
229 case ORR_w_imm:
230 case ORR_x_imm: {
231 mnemonic = "orr";
232 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
233 : kWRegSizeInBits;
234 if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) {
235 mnemonic = "mov";
236 form = "'Rds, 'ITri";
237 }
238 break;
239 }
240 case EOR_w_imm:
241 case EOR_x_imm: mnemonic = "eor"; break;
242 case ANDS_w_imm:
243 case ANDS_x_imm: {
244 mnemonic = "ands";
245 if (rd_is_zr) {
246 mnemonic = "tst";
247 form = "'Rn, 'ITri";
248 }
249 break;
250 }
251 default: UNREACHABLE();
252 }
253 Format(instr, mnemonic, form);
254 }
255
256
IsMovzMovnImm(unsigned reg_size,uint64_t value)257 bool DisassemblingDecoder::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
258 DCHECK((reg_size == kXRegSizeInBits) ||
259 ((reg_size == kWRegSizeInBits) && (value <= 0xFFFFFFFF)));
260
261 // Test for movz: 16-bits set at positions 0, 16, 32 or 48.
262 if (((value & 0xFFFFFFFFFFFF0000UL) == 0UL) ||
263 ((value & 0xFFFFFFFF0000FFFFUL) == 0UL) ||
264 ((value & 0xFFFF0000FFFFFFFFUL) == 0UL) ||
265 ((value & 0x0000FFFFFFFFFFFFUL) == 0UL)) {
266 return true;
267 }
268
269 // Test for movn: NOT(16-bits set at positions 0, 16, 32 or 48).
270 if ((reg_size == kXRegSizeInBits) &&
271 (((value & 0xFFFFFFFFFFFF0000UL) == 0xFFFFFFFFFFFF0000UL) ||
272 ((value & 0xFFFFFFFF0000FFFFUL) == 0xFFFFFFFF0000FFFFUL) ||
273 ((value & 0xFFFF0000FFFFFFFFUL) == 0xFFFF0000FFFFFFFFUL) ||
274 ((value & 0x0000FFFFFFFFFFFFUL) == 0x0000FFFFFFFFFFFFUL))) {
275 return true;
276 }
277 if ((reg_size == kWRegSizeInBits) && (((value & 0xFFFF0000) == 0xFFFF0000) ||
278 ((value & 0x0000FFFF) == 0x0000FFFF))) {
279 return true;
280 }
281 return false;
282 }
283
284
VisitLogicalShifted(Instruction * instr)285 void DisassemblingDecoder::VisitLogicalShifted(Instruction* instr) {
286 bool rd_is_zr = RdIsZROrSP(instr);
287 bool rn_is_zr = RnIsZROrSP(instr);
288 const char *mnemonic = "";
289 const char* form = "'Rd, 'Rn, 'Rm'NLo";
290
291 switch (instr->Mask(LogicalShiftedMask)) {
292 case AND_w:
293 case AND_x: mnemonic = "and"; break;
294 case BIC_w:
295 case BIC_x: mnemonic = "bic"; break;
296 case EOR_w:
297 case EOR_x: mnemonic = "eor"; break;
298 case EON_w:
299 case EON_x: mnemonic = "eon"; break;
300 case BICS_w:
301 case BICS_x: mnemonic = "bics"; break;
302 case ANDS_w:
303 case ANDS_x: {
304 mnemonic = "ands";
305 if (rd_is_zr) {
306 mnemonic = "tst";
307 form = "'Rn, 'Rm'NLo";
308 }
309 break;
310 }
311 case ORR_w:
312 case ORR_x: {
313 mnemonic = "orr";
314 if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) {
315 mnemonic = "mov";
316 form = "'Rd, 'Rm";
317 }
318 break;
319 }
320 case ORN_w:
321 case ORN_x: {
322 mnemonic = "orn";
323 if (rn_is_zr) {
324 mnemonic = "mvn";
325 form = "'Rd, 'Rm'NLo";
326 }
327 break;
328 }
329 default: UNREACHABLE();
330 }
331
332 Format(instr, mnemonic, form);
333 }
334
335
VisitConditionalCompareRegister(Instruction * instr)336 void DisassemblingDecoder::VisitConditionalCompareRegister(Instruction* instr) {
337 const char *mnemonic = "";
338 const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
339
340 switch (instr->Mask(ConditionalCompareRegisterMask)) {
341 case CCMN_w:
342 case CCMN_x: mnemonic = "ccmn"; break;
343 case CCMP_w:
344 case CCMP_x: mnemonic = "ccmp"; break;
345 default: UNREACHABLE();
346 }
347 Format(instr, mnemonic, form);
348 }
349
350
VisitConditionalCompareImmediate(Instruction * instr)351 void DisassemblingDecoder::VisitConditionalCompareImmediate(
352 Instruction* instr) {
353 const char *mnemonic = "";
354 const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
355
356 switch (instr->Mask(ConditionalCompareImmediateMask)) {
357 case CCMN_w_imm:
358 case CCMN_x_imm: mnemonic = "ccmn"; break;
359 case CCMP_w_imm:
360 case CCMP_x_imm: mnemonic = "ccmp"; break;
361 default: UNREACHABLE();
362 }
363 Format(instr, mnemonic, form);
364 }
365
366
VisitConditionalSelect(Instruction * instr)367 void DisassemblingDecoder::VisitConditionalSelect(Instruction* instr) {
368 bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
369 bool rn_is_rm = (instr->Rn() == instr->Rm());
370 const char *mnemonic = "";
371 const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
372 const char *form_test = "'Rd, 'CInv";
373 const char *form_update = "'Rd, 'Rn, 'CInv";
374
375 Condition cond = static_cast<Condition>(instr->Condition());
376 bool invertible_cond = (cond != al) && (cond != nv);
377
378 switch (instr->Mask(ConditionalSelectMask)) {
379 case CSEL_w:
380 case CSEL_x: mnemonic = "csel"; break;
381 case CSINC_w:
382 case CSINC_x: {
383 mnemonic = "csinc";
384 if (rnm_is_zr && invertible_cond) {
385 mnemonic = "cset";
386 form = form_test;
387 } else if (rn_is_rm && invertible_cond) {
388 mnemonic = "cinc";
389 form = form_update;
390 }
391 break;
392 }
393 case CSINV_w:
394 case CSINV_x: {
395 mnemonic = "csinv";
396 if (rnm_is_zr && invertible_cond) {
397 mnemonic = "csetm";
398 form = form_test;
399 } else if (rn_is_rm && invertible_cond) {
400 mnemonic = "cinv";
401 form = form_update;
402 }
403 break;
404 }
405 case CSNEG_w:
406 case CSNEG_x: {
407 mnemonic = "csneg";
408 if (rn_is_rm && invertible_cond) {
409 mnemonic = "cneg";
410 form = form_update;
411 }
412 break;
413 }
414 default: UNREACHABLE();
415 }
416 Format(instr, mnemonic, form);
417 }
418
419
VisitBitfield(Instruction * instr)420 void DisassemblingDecoder::VisitBitfield(Instruction* instr) {
421 unsigned s = instr->ImmS();
422 unsigned r = instr->ImmR();
423 unsigned rd_size_minus_1 =
424 ((instr->SixtyFourBits() == 1) ? kXRegSizeInBits : kWRegSizeInBits) - 1;
425 const char *mnemonic = "";
426 const char *form = "";
427 const char *form_shift_right = "'Rd, 'Rn, 'IBr";
428 const char *form_extend = "'Rd, 'Wn";
429 const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
430 const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
431 const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
432
433 switch (instr->Mask(BitfieldMask)) {
434 case SBFM_w:
435 case SBFM_x: {
436 mnemonic = "sbfx";
437 form = form_bfx;
438 if (r == 0) {
439 form = form_extend;
440 if (s == 7) {
441 mnemonic = "sxtb";
442 } else if (s == 15) {
443 mnemonic = "sxth";
444 } else if ((s == 31) && (instr->SixtyFourBits() == 1)) {
445 mnemonic = "sxtw";
446 } else {
447 form = form_bfx;
448 }
449 } else if (s == rd_size_minus_1) {
450 mnemonic = "asr";
451 form = form_shift_right;
452 } else if (s < r) {
453 mnemonic = "sbfiz";
454 form = form_bfiz;
455 }
456 break;
457 }
458 case UBFM_w:
459 case UBFM_x: {
460 mnemonic = "ubfx";
461 form = form_bfx;
462 if (r == 0) {
463 form = form_extend;
464 if (s == 7) {
465 mnemonic = "uxtb";
466 } else if (s == 15) {
467 mnemonic = "uxth";
468 } else {
469 form = form_bfx;
470 }
471 }
472 if (s == rd_size_minus_1) {
473 mnemonic = "lsr";
474 form = form_shift_right;
475 } else if (r == s + 1) {
476 mnemonic = "lsl";
477 form = form_lsl;
478 } else if (s < r) {
479 mnemonic = "ubfiz";
480 form = form_bfiz;
481 }
482 break;
483 }
484 case BFM_w:
485 case BFM_x: {
486 mnemonic = "bfxil";
487 form = form_bfx;
488 if (s < r) {
489 mnemonic = "bfi";
490 form = form_bfiz;
491 }
492 }
493 }
494 Format(instr, mnemonic, form);
495 }
496
497
VisitExtract(Instruction * instr)498 void DisassemblingDecoder::VisitExtract(Instruction* instr) {
499 const char *mnemonic = "";
500 const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
501
502 switch (instr->Mask(ExtractMask)) {
503 case EXTR_w:
504 case EXTR_x: {
505 if (instr->Rn() == instr->Rm()) {
506 mnemonic = "ror";
507 form = "'Rd, 'Rn, 'IExtract";
508 } else {
509 mnemonic = "extr";
510 }
511 break;
512 }
513 default: UNREACHABLE();
514 }
515 Format(instr, mnemonic, form);
516 }
517
518
VisitPCRelAddressing(Instruction * instr)519 void DisassemblingDecoder::VisitPCRelAddressing(Instruction* instr) {
520 switch (instr->Mask(PCRelAddressingMask)) {
521 case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break;
522 // ADRP is not implemented.
523 default: Format(instr, "unimplemented", "(PCRelAddressing)");
524 }
525 }
526
527
VisitConditionalBranch(Instruction * instr)528 void DisassemblingDecoder::VisitConditionalBranch(Instruction* instr) {
529 switch (instr->Mask(ConditionalBranchMask)) {
530 case B_cond:
531 Format(instr, "b.'CBrn", "'TImmCond");
532 break;
533 default: UNREACHABLE();
534 }
535 }
536
537
VisitUnconditionalBranchToRegister(Instruction * instr)538 void DisassemblingDecoder::VisitUnconditionalBranchToRegister(
539 Instruction* instr) {
540 const char *mnemonic = "unimplemented";
541 const char *form = "'Xn";
542
543 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
544 case BR: mnemonic = "br"; break;
545 case BLR: mnemonic = "blr"; break;
546 case RET: {
547 mnemonic = "ret";
548 if (instr->Rn() == kLinkRegCode) {
549 form = nullptr;
550 }
551 break;
552 }
553 default: form = "(UnconditionalBranchToRegister)";
554 }
555 Format(instr, mnemonic, form);
556 }
557
558
VisitUnconditionalBranch(Instruction * instr)559 void DisassemblingDecoder::VisitUnconditionalBranch(Instruction* instr) {
560 const char *mnemonic = "";
561 const char* form = "'TImmUncn";
562
563 switch (instr->Mask(UnconditionalBranchMask)) {
564 case B: mnemonic = "b"; break;
565 case BL: mnemonic = "bl"; break;
566 default: UNREACHABLE();
567 }
568 Format(instr, mnemonic, form);
569 }
570
571
VisitDataProcessing1Source(Instruction * instr)572 void DisassemblingDecoder::VisitDataProcessing1Source(Instruction* instr) {
573 const char *mnemonic = "";
574 const char *form = "'Rd, 'Rn";
575
576 switch (instr->Mask(DataProcessing1SourceMask)) {
577 #define FORMAT(A, B) \
578 case A##_w: \
579 case A##_x: mnemonic = B; break;
580 FORMAT(RBIT, "rbit");
581 FORMAT(REV16, "rev16");
582 FORMAT(REV, "rev");
583 FORMAT(CLZ, "clz");
584 FORMAT(CLS, "cls");
585 #undef FORMAT
586 case REV32_x: mnemonic = "rev32"; break;
587 default: UNREACHABLE();
588 }
589 Format(instr, mnemonic, form);
590 }
591
592
VisitDataProcessing2Source(Instruction * instr)593 void DisassemblingDecoder::VisitDataProcessing2Source(Instruction* instr) {
594 const char *mnemonic = "unimplemented";
595 const char *form = "'Rd, 'Rn, 'Rm";
596
597 switch (instr->Mask(DataProcessing2SourceMask)) {
598 #define FORMAT(A, B) \
599 case A##_w: \
600 case A##_x: mnemonic = B; break;
601 FORMAT(UDIV, "udiv");
602 FORMAT(SDIV, "sdiv");
603 FORMAT(LSLV, "lsl");
604 FORMAT(LSRV, "lsr");
605 FORMAT(ASRV, "asr");
606 FORMAT(RORV, "ror");
607 #undef FORMAT
608 default: form = "(DataProcessing2Source)";
609 }
610 Format(instr, mnemonic, form);
611 }
612
613
VisitDataProcessing3Source(Instruction * instr)614 void DisassemblingDecoder::VisitDataProcessing3Source(Instruction* instr) {
615 bool ra_is_zr = RaIsZROrSP(instr);
616 const char *mnemonic = "";
617 const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
618 const char *form_rrr = "'Rd, 'Rn, 'Rm";
619 const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
620 const char *form_xww = "'Xd, 'Wn, 'Wm";
621 const char *form_xxx = "'Xd, 'Xn, 'Xm";
622
623 switch (instr->Mask(DataProcessing3SourceMask)) {
624 case MADD_w:
625 case MADD_x: {
626 mnemonic = "madd";
627 form = form_rrrr;
628 if (ra_is_zr) {
629 mnemonic = "mul";
630 form = form_rrr;
631 }
632 break;
633 }
634 case MSUB_w:
635 case MSUB_x: {
636 mnemonic = "msub";
637 form = form_rrrr;
638 if (ra_is_zr) {
639 mnemonic = "mneg";
640 form = form_rrr;
641 }
642 break;
643 }
644 case SMADDL_x: {
645 mnemonic = "smaddl";
646 if (ra_is_zr) {
647 mnemonic = "smull";
648 form = form_xww;
649 }
650 break;
651 }
652 case SMSUBL_x: {
653 mnemonic = "smsubl";
654 if (ra_is_zr) {
655 mnemonic = "smnegl";
656 form = form_xww;
657 }
658 break;
659 }
660 case UMADDL_x: {
661 mnemonic = "umaddl";
662 if (ra_is_zr) {
663 mnemonic = "umull";
664 form = form_xww;
665 }
666 break;
667 }
668 case UMSUBL_x: {
669 mnemonic = "umsubl";
670 if (ra_is_zr) {
671 mnemonic = "umnegl";
672 form = form_xww;
673 }
674 break;
675 }
676 case SMULH_x: {
677 mnemonic = "smulh";
678 form = form_xxx;
679 break;
680 }
681 case UMULH_x: {
682 mnemonic = "umulh";
683 form = form_xxx;
684 break;
685 }
686 default: UNREACHABLE();
687 }
688 Format(instr, mnemonic, form);
689 }
690
691
VisitCompareBranch(Instruction * instr)692 void DisassemblingDecoder::VisitCompareBranch(Instruction* instr) {
693 const char *mnemonic = "";
694 const char* form = "'Rt, 'TImmCmpa";
695
696 switch (instr->Mask(CompareBranchMask)) {
697 case CBZ_w:
698 case CBZ_x: mnemonic = "cbz"; break;
699 case CBNZ_w:
700 case CBNZ_x: mnemonic = "cbnz"; break;
701 default: UNREACHABLE();
702 }
703 Format(instr, mnemonic, form);
704 }
705
706
VisitTestBranch(Instruction * instr)707 void DisassemblingDecoder::VisitTestBranch(Instruction* instr) {
708 const char *mnemonic = "";
709 // If the top bit of the immediate is clear, the tested register is
710 // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
711 // encoded in bit 31 of the instruction, we can reuse the Rt form, which
712 // uses bit 31 (normally "sf") to choose the register size.
713 const char* form = "'Rt, 'IS, 'TImmTest";
714
715 switch (instr->Mask(TestBranchMask)) {
716 case TBZ: mnemonic = "tbz"; break;
717 case TBNZ: mnemonic = "tbnz"; break;
718 default: UNREACHABLE();
719 }
720 Format(instr, mnemonic, form);
721 }
722
723
VisitMoveWideImmediate(Instruction * instr)724 void DisassemblingDecoder::VisitMoveWideImmediate(Instruction* instr) {
725 const char *mnemonic = "";
726 const char *form = "'Rd, 'IMoveImm";
727
728 // Print the shift separately for movk, to make it clear which half word will
729 // be overwritten. Movn and movz print the computed immediate, which includes
730 // shift calculation.
731 switch (instr->Mask(MoveWideImmediateMask)) {
732 case MOVN_w:
733 case MOVN_x: mnemonic = "movn"; break;
734 case MOVZ_w:
735 case MOVZ_x: mnemonic = "movz"; break;
736 case MOVK_w:
737 case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
738 default: UNREACHABLE();
739 }
740 Format(instr, mnemonic, form);
741 }
742
743 #define LOAD_STORE_LIST(V) \
744 V(STRB_w, "strb", "'Wt") \
745 V(STRH_w, "strh", "'Wt") \
746 V(STR_w, "str", "'Wt") \
747 V(STR_x, "str", "'Xt") \
748 V(LDRB_w, "ldrb", "'Wt") \
749 V(LDRH_w, "ldrh", "'Wt") \
750 V(LDR_w, "ldr", "'Wt") \
751 V(LDR_x, "ldr", "'Xt") \
752 V(LDRSB_x, "ldrsb", "'Xt") \
753 V(LDRSH_x, "ldrsh", "'Xt") \
754 V(LDRSW_x, "ldrsw", "'Xt") \
755 V(LDRSB_w, "ldrsb", "'Wt") \
756 V(LDRSH_w, "ldrsh", "'Wt") \
757 V(STR_b, "str", "'Bt") \
758 V(STR_h, "str", "'Ht") \
759 V(STR_s, "str", "'St") \
760 V(STR_d, "str", "'Dt") \
761 V(LDR_b, "ldr", "'Bt") \
762 V(LDR_h, "ldr", "'Ht") \
763 V(LDR_s, "ldr", "'St") \
764 V(LDR_d, "ldr", "'Dt") \
765 V(STR_q, "str", "'Qt") \
766 V(LDR_q, "ldr", "'Qt")
767
VisitLoadStorePreIndex(Instruction * instr)768 void DisassemblingDecoder::VisitLoadStorePreIndex(Instruction* instr) {
769 const char *mnemonic = "unimplemented";
770 const char *form = "(LoadStorePreIndex)";
771
772 switch (instr->Mask(LoadStorePreIndexMask)) {
773 #define LS_PREINDEX(A, B, C) \
774 case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break;
775 LOAD_STORE_LIST(LS_PREINDEX)
776 #undef LS_PREINDEX
777 }
778 Format(instr, mnemonic, form);
779 }
780
781
VisitLoadStorePostIndex(Instruction * instr)782 void DisassemblingDecoder::VisitLoadStorePostIndex(Instruction* instr) {
783 const char *mnemonic = "unimplemented";
784 const char *form = "(LoadStorePostIndex)";
785
786 switch (instr->Mask(LoadStorePostIndexMask)) {
787 #define LS_POSTINDEX(A, B, C) \
788 case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break;
789 LOAD_STORE_LIST(LS_POSTINDEX)
790 #undef LS_POSTINDEX
791 }
792 Format(instr, mnemonic, form);
793 }
794
795
VisitLoadStoreUnsignedOffset(Instruction * instr)796 void DisassemblingDecoder::VisitLoadStoreUnsignedOffset(Instruction* instr) {
797 const char *mnemonic = "unimplemented";
798 const char *form = "(LoadStoreUnsignedOffset)";
799
800 switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
801 #define LS_UNSIGNEDOFFSET(A, B, C) \
802 case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break;
803 LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
804 #undef LS_UNSIGNEDOFFSET
805 case PRFM_unsigned: mnemonic = "prfm"; form = "'PrefOp, ['Xn'ILU]";
806 }
807 Format(instr, mnemonic, form);
808 }
809
810
VisitLoadStoreRegisterOffset(Instruction * instr)811 void DisassemblingDecoder::VisitLoadStoreRegisterOffset(Instruction* instr) {
812 const char *mnemonic = "unimplemented";
813 const char *form = "(LoadStoreRegisterOffset)";
814
815 switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
816 #define LS_REGISTEROFFSET(A, B, C) \
817 case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break;
818 LOAD_STORE_LIST(LS_REGISTEROFFSET)
819 #undef LS_REGISTEROFFSET
820 case PRFM_reg: mnemonic = "prfm"; form = "'PrefOp, ['Xns, 'Offsetreg]";
821 }
822 Format(instr, mnemonic, form);
823 }
824
825 #define LOAD_STORE_UNSCALED_LIST(V) \
826 V(STURB_w, "sturb", "'Wt") \
827 V(STURH_w, "sturh", "'Wt") \
828 V(STUR_w, "stur", "'Wt") \
829 V(STUR_x, "stur", "'Xt") \
830 V(LDURB_w, "ldurb", "'Wt") \
831 V(LDURH_w, "ldurh", "'Wt") \
832 V(LDUR_w, "ldur", "'Wt") \
833 V(LDUR_x, "ldur", "'Xt") \
834 V(LDURSB_x, "ldursb", "'Xt") \
835 V(LDURSH_x, "ldursh", "'Xt") \
836 V(LDURSW_x, "ldursw", "'Xt") \
837 V(LDURSB_w, "ldursb", "'Wt") \
838 V(LDURSH_w, "ldursh", "'Wt") \
839 V(STUR_b, "stur", "'Bt") \
840 V(STUR_h, "stur", "'Ht") \
841 V(STUR_s, "stur", "'St") \
842 V(STUR_d, "stur", "'Dt") \
843 V(LDUR_b, "ldur", "'Bt") \
844 V(LDUR_h, "ldur", "'Ht") \
845 V(LDUR_s, "ldur", "'St") \
846 V(LDUR_d, "ldur", "'Dt") \
847 V(STUR_q, "stur", "'Qt") \
848 V(LDUR_q, "ldur", "'Qt")
849
VisitLoadStoreUnscaledOffset(Instruction * instr)850 void DisassemblingDecoder::VisitLoadStoreUnscaledOffset(Instruction* instr) {
851 const char* mnemonic = "unimplemented";
852 const char* form = "(LoadStoreUnscaledOffset)";
853
854 switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
855 #define LS_UNSCALEDOFFSET(A, B, C) \
856 case A: \
857 mnemonic = B; \
858 form = C ", ['Xns'ILS]"; \
859 break;
860 LOAD_STORE_UNSCALED_LIST(LS_UNSCALEDOFFSET)
861 #undef LS_UNSCALEDOFFSET
862 }
863 Format(instr, mnemonic, form);
864 }
865
VisitLoadLiteral(Instruction * instr)866 void DisassemblingDecoder::VisitLoadLiteral(Instruction* instr) {
867 const char *mnemonic = "ldr";
868 const char *form = "(LoadLiteral)";
869
870 switch (instr->Mask(LoadLiteralMask)) {
871 case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break;
872 case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break;
873 case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break;
874 case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break;
875 default: mnemonic = "unimplemented";
876 }
877 Format(instr, mnemonic, form);
878 }
879
880 #define LOAD_STORE_PAIR_LIST(V) \
881 V(STP_w, "stp", "'Wt, 'Wt2", "2") \
882 V(LDP_w, "ldp", "'Wt, 'Wt2", "2") \
883 V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "2") \
884 V(STP_x, "stp", "'Xt, 'Xt2", "3") \
885 V(LDP_x, "ldp", "'Xt, 'Xt2", "3") \
886 V(STP_s, "stp", "'St, 'St2", "2") \
887 V(LDP_s, "ldp", "'St, 'St2", "2") \
888 V(STP_d, "stp", "'Dt, 'Dt2", "3") \
889 V(LDP_d, "ldp", "'Dt, 'Dt2", "3") \
890 V(LDP_q, "ldp", "'Qt, 'Qt2", "4") \
891 V(STP_q, "stp", "'Qt, 'Qt2", "4")
892
VisitLoadStorePairPostIndex(Instruction * instr)893 void DisassemblingDecoder::VisitLoadStorePairPostIndex(Instruction* instr) {
894 const char *mnemonic = "unimplemented";
895 const char *form = "(LoadStorePairPostIndex)";
896
897 switch (instr->Mask(LoadStorePairPostIndexMask)) {
898 #define LSP_POSTINDEX(A, B, C, D) \
899 case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break;
900 LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
901 #undef LSP_POSTINDEX
902 }
903 Format(instr, mnemonic, form);
904 }
905
906
VisitLoadStorePairPreIndex(Instruction * instr)907 void DisassemblingDecoder::VisitLoadStorePairPreIndex(Instruction* instr) {
908 const char *mnemonic = "unimplemented";
909 const char *form = "(LoadStorePairPreIndex)";
910
911 switch (instr->Mask(LoadStorePairPreIndexMask)) {
912 #define LSP_PREINDEX(A, B, C, D) \
913 case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break;
914 LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
915 #undef LSP_PREINDEX
916 }
917 Format(instr, mnemonic, form);
918 }
919
920
VisitLoadStorePairOffset(Instruction * instr)921 void DisassemblingDecoder::VisitLoadStorePairOffset(Instruction* instr) {
922 const char *mnemonic = "unimplemented";
923 const char *form = "(LoadStorePairOffset)";
924
925 switch (instr->Mask(LoadStorePairOffsetMask)) {
926 #define LSP_OFFSET(A, B, C, D) \
927 case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break;
928 LOAD_STORE_PAIR_LIST(LSP_OFFSET)
929 #undef LSP_OFFSET
930 }
931 Format(instr, mnemonic, form);
932 }
933
VisitLoadStoreAcquireRelease(Instruction * instr)934 void DisassemblingDecoder::VisitLoadStoreAcquireRelease(Instruction *instr) {
935 const char *mnemonic = "unimplemented";
936 const char* form = "'Wt, ['Xns]";
937 const char* form_x = "'Xt, ['Xns]";
938 const char* form_stlx = "'Ws, 'Wt, ['Xns]";
939 const char* form_stlx_x = "'Ws, 'Xt, ['Xns]";
940
941 switch (instr->Mask(LoadStoreAcquireReleaseMask)) {
942 case LDAXR_b: mnemonic = "ldaxrb"; break;
943 case STLR_b: mnemonic = "stlrb"; break;
944 case LDAR_b: mnemonic = "ldarb"; break;
945 case LDAXR_h: mnemonic = "ldaxrh"; break;
946 case STLR_h: mnemonic = "stlrh"; break;
947 case LDAR_h: mnemonic = "ldarh"; break;
948 case LDAXR_w: mnemonic = "ldaxr"; break;
949 case STLR_w: mnemonic = "stlr"; break;
950 case LDAR_w: mnemonic = "ldar"; break;
951 case LDAXR_x: mnemonic = "ldaxr"; form = form_x; break;
952 case STLR_x: mnemonic = "stlr"; form = form_x; break;
953 case LDAR_x: mnemonic = "ldar"; form = form_x; break;
954 case STLXR_h: mnemonic = "stlxrh"; form = form_stlx; break;
955 case STLXR_b: mnemonic = "stlxrb"; form = form_stlx; break;
956 case STLXR_w: mnemonic = "stlxr"; form = form_stlx; break;
957 case STLXR_x: mnemonic = "stlxr"; form = form_stlx_x; break;
958 default:
959 form = "(LoadStoreAcquireRelease)";
960 }
961 Format(instr, mnemonic, form);
962 }
963
VisitFPCompare(Instruction * instr)964 void DisassemblingDecoder::VisitFPCompare(Instruction* instr) {
965 const char *mnemonic = "unimplemented";
966 const char *form = "'Fn, 'Fm";
967 const char *form_zero = "'Fn, #0.0";
968
969 switch (instr->Mask(FPCompareMask)) {
970 case FCMP_s_zero:
971 case FCMP_d_zero: form = form_zero; V8_FALLTHROUGH;
972 case FCMP_s:
973 case FCMP_d: mnemonic = "fcmp"; break;
974 default: form = "(FPCompare)";
975 }
976 Format(instr, mnemonic, form);
977 }
978
979
VisitFPConditionalCompare(Instruction * instr)980 void DisassemblingDecoder::VisitFPConditionalCompare(Instruction* instr) {
981 const char *mnemonic = "unimplemented";
982 const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
983
984 switch (instr->Mask(FPConditionalCompareMask)) {
985 case FCCMP_s:
986 case FCCMP_d: mnemonic = "fccmp"; break;
987 case FCCMPE_s:
988 case FCCMPE_d: mnemonic = "fccmpe"; break;
989 default: form = "(FPConditionalCompare)";
990 }
991 Format(instr, mnemonic, form);
992 }
993
994
VisitFPConditionalSelect(Instruction * instr)995 void DisassemblingDecoder::VisitFPConditionalSelect(Instruction* instr) {
996 const char *mnemonic = "";
997 const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
998
999 switch (instr->Mask(FPConditionalSelectMask)) {
1000 case FCSEL_s:
1001 case FCSEL_d: mnemonic = "fcsel"; break;
1002 default: UNREACHABLE();
1003 }
1004 Format(instr, mnemonic, form);
1005 }
1006
1007
VisitFPDataProcessing1Source(Instruction * instr)1008 void DisassemblingDecoder::VisitFPDataProcessing1Source(Instruction* instr) {
1009 const char *mnemonic = "unimplemented";
1010 const char *form = "'Fd, 'Fn";
1011
1012 switch (instr->Mask(FPDataProcessing1SourceMask)) {
1013 #define FORMAT(A, B) \
1014 case A##_s: \
1015 case A##_d: mnemonic = B; break;
1016 FORMAT(FMOV, "fmov");
1017 FORMAT(FABS, "fabs");
1018 FORMAT(FNEG, "fneg");
1019 FORMAT(FSQRT, "fsqrt");
1020 FORMAT(FRINTN, "frintn");
1021 FORMAT(FRINTP, "frintp");
1022 FORMAT(FRINTM, "frintm");
1023 FORMAT(FRINTZ, "frintz");
1024 FORMAT(FRINTA, "frinta");
1025 FORMAT(FRINTX, "frintx");
1026 FORMAT(FRINTI, "frinti");
1027 #undef FORMAT
1028 case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break;
1029 case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break;
1030 case FCVT_hs:
1031 mnemonic = "fcvt";
1032 form = "'Hd, 'Sn";
1033 break;
1034 case FCVT_sh:
1035 mnemonic = "fcvt";
1036 form = "'Sd, 'Hn";
1037 break;
1038 case FCVT_dh:
1039 mnemonic = "fcvt";
1040 form = "'Dd, 'Hn";
1041 break;
1042 case FCVT_hd:
1043 mnemonic = "fcvt";
1044 form = "'Hd, 'Dn";
1045 break;
1046 default: form = "(FPDataProcessing1Source)";
1047 }
1048 Format(instr, mnemonic, form);
1049 }
1050
1051
VisitFPDataProcessing2Source(Instruction * instr)1052 void DisassemblingDecoder::VisitFPDataProcessing2Source(Instruction* instr) {
1053 const char *mnemonic = "";
1054 const char *form = "'Fd, 'Fn, 'Fm";
1055
1056 switch (instr->Mask(FPDataProcessing2SourceMask)) {
1057 #define FORMAT(A, B) \
1058 case A##_s: \
1059 case A##_d: mnemonic = B; break;
1060 FORMAT(FMUL, "fmul");
1061 FORMAT(FDIV, "fdiv");
1062 FORMAT(FADD, "fadd");
1063 FORMAT(FSUB, "fsub");
1064 FORMAT(FMAX, "fmax");
1065 FORMAT(FMIN, "fmin");
1066 FORMAT(FMAXNM, "fmaxnm");
1067 FORMAT(FMINNM, "fminnm");
1068 FORMAT(FNMUL, "fnmul");
1069 #undef FORMAT
1070 default: UNREACHABLE();
1071 }
1072 Format(instr, mnemonic, form);
1073 }
1074
1075
VisitFPDataProcessing3Source(Instruction * instr)1076 void DisassemblingDecoder::VisitFPDataProcessing3Source(Instruction* instr) {
1077 const char *mnemonic = "";
1078 const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
1079
1080 switch (instr->Mask(FPDataProcessing3SourceMask)) {
1081 #define FORMAT(A, B) \
1082 case A##_s: \
1083 case A##_d: mnemonic = B; break;
1084 FORMAT(FMADD, "fmadd");
1085 FORMAT(FMSUB, "fmsub");
1086 FORMAT(FNMADD, "fnmadd");
1087 FORMAT(FNMSUB, "fnmsub");
1088 #undef FORMAT
1089 default: UNREACHABLE();
1090 }
1091 Format(instr, mnemonic, form);
1092 }
1093
1094
VisitFPImmediate(Instruction * instr)1095 void DisassemblingDecoder::VisitFPImmediate(Instruction* instr) {
1096 const char *mnemonic = "";
1097 const char *form = "(FPImmediate)";
1098
1099 switch (instr->Mask(FPImmediateMask)) {
1100 case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
1101 case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
1102 default: UNREACHABLE();
1103 }
1104 Format(instr, mnemonic, form);
1105 }
1106
1107
VisitFPIntegerConvert(Instruction * instr)1108 void DisassemblingDecoder::VisitFPIntegerConvert(Instruction* instr) {
1109 const char *mnemonic = "unimplemented";
1110 const char *form = "(FPIntegerConvert)";
1111 const char *form_rf = "'Rd, 'Fn";
1112 const char *form_fr = "'Fd, 'Rn";
1113
1114 switch (instr->Mask(FPIntegerConvertMask)) {
1115 case FMOV_ws:
1116 case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
1117 case FMOV_sw:
1118 case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
1119 case FMOV_d1_x:
1120 mnemonic = "fmov";
1121 form = "'Vd.D[1], 'Rn";
1122 break;
1123 case FMOV_x_d1:
1124 mnemonic = "fmov";
1125 form = "'Rd, 'Vn.D[1]";
1126 break;
1127 case FCVTAS_ws:
1128 case FCVTAS_xs:
1129 case FCVTAS_wd:
1130 case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break;
1131 case FCVTAU_ws:
1132 case FCVTAU_xs:
1133 case FCVTAU_wd:
1134 case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break;
1135 case FCVTMS_ws:
1136 case FCVTMS_xs:
1137 case FCVTMS_wd:
1138 case FCVTMS_xd: mnemonic = "fcvtms"; form = form_rf; break;
1139 case FCVTMU_ws:
1140 case FCVTMU_xs:
1141 case FCVTMU_wd:
1142 case FCVTMU_xd: mnemonic = "fcvtmu"; form = form_rf; break;
1143 case FCVTNS_ws:
1144 case FCVTNS_xs:
1145 case FCVTNS_wd:
1146 case FCVTNS_xd: mnemonic = "fcvtns"; form = form_rf; break;
1147 case FCVTNU_ws:
1148 case FCVTNU_xs:
1149 case FCVTNU_wd:
1150 case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break;
1151 case FCVTZU_xd:
1152 case FCVTZU_ws:
1153 case FCVTZU_wd:
1154 case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break;
1155 case FCVTZS_xd:
1156 case FCVTZS_wd:
1157 case FCVTZS_xs:
1158 case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break;
1159 case FCVTPU_xd:
1160 case FCVTPU_ws:
1161 case FCVTPU_wd:
1162 case FCVTPU_xs:
1163 mnemonic = "fcvtpu";
1164 form = form_rf;
1165 break;
1166 case FCVTPS_xd:
1167 case FCVTPS_wd:
1168 case FCVTPS_xs:
1169 case FCVTPS_ws:
1170 mnemonic = "fcvtps";
1171 form = form_rf;
1172 break;
1173 case SCVTF_sw:
1174 case SCVTF_sx:
1175 case SCVTF_dw:
1176 case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break;
1177 case UCVTF_sw:
1178 case UCVTF_sx:
1179 case UCVTF_dw:
1180 case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break;
1181 }
1182 Format(instr, mnemonic, form);
1183 }
1184
1185
VisitFPFixedPointConvert(Instruction * instr)1186 void DisassemblingDecoder::VisitFPFixedPointConvert(Instruction* instr) {
1187 const char *mnemonic = "";
1188 const char *form = "'Rd, 'Fn, 'IFPFBits";
1189 const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
1190
1191 switch (instr->Mask(FPFixedPointConvertMask)) {
1192 case FCVTZS_ws_fixed:
1193 case FCVTZS_xs_fixed:
1194 case FCVTZS_wd_fixed:
1195 case FCVTZS_xd_fixed: mnemonic = "fcvtzs"; break;
1196 case FCVTZU_ws_fixed:
1197 case FCVTZU_xs_fixed:
1198 case FCVTZU_wd_fixed:
1199 case FCVTZU_xd_fixed: mnemonic = "fcvtzu"; break;
1200 case SCVTF_sw_fixed:
1201 case SCVTF_sx_fixed:
1202 case SCVTF_dw_fixed:
1203 case SCVTF_dx_fixed: mnemonic = "scvtf"; form = form_fr; break;
1204 case UCVTF_sw_fixed:
1205 case UCVTF_sx_fixed:
1206 case UCVTF_dw_fixed:
1207 case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
1208 }
1209 Format(instr, mnemonic, form);
1210 }
1211
1212
VisitSystem(Instruction * instr)1213 void DisassemblingDecoder::VisitSystem(Instruction* instr) {
1214 // Some system instructions hijack their Op and Cp fields to represent a
1215 // range of immediates instead of indicating a different instruction. This
1216 // makes the decoding tricky.
1217 const char *mnemonic = "unimplemented";
1218 const char *form = "(System)";
1219
1220 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
1221 switch (instr->Mask(SystemSysRegMask)) {
1222 case MRS: {
1223 mnemonic = "mrs";
1224 switch (instr->ImmSystemRegister()) {
1225 case NZCV: form = "'Xt, nzcv"; break;
1226 case FPCR: form = "'Xt, fpcr"; break;
1227 default: form = "'Xt, (unknown)"; break;
1228 }
1229 break;
1230 }
1231 case MSR: {
1232 mnemonic = "msr";
1233 switch (instr->ImmSystemRegister()) {
1234 case NZCV: form = "nzcv, 'Xt"; break;
1235 case FPCR: form = "fpcr, 'Xt"; break;
1236 default: form = "(unknown), 'Xt"; break;
1237 }
1238 break;
1239 }
1240 }
1241 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
1242 DCHECK(instr->Mask(SystemHintMask) == HINT);
1243 switch (instr->ImmHint()) {
1244 case NOP: {
1245 mnemonic = "nop";
1246 form = nullptr;
1247 break;
1248 }
1249 case CSDB: {
1250 mnemonic = "csdb";
1251 form = nullptr;
1252 break;
1253 }
1254 }
1255 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
1256 switch (instr->Mask(MemBarrierMask)) {
1257 case DMB: {
1258 mnemonic = "dmb";
1259 form = "'M";
1260 break;
1261 }
1262 case DSB: {
1263 mnemonic = "dsb";
1264 form = "'M";
1265 break;
1266 }
1267 case ISB: {
1268 mnemonic = "isb";
1269 form = nullptr;
1270 break;
1271 }
1272 }
1273 }
1274
1275 Format(instr, mnemonic, form);
1276 }
1277
1278
VisitException(Instruction * instr)1279 void DisassemblingDecoder::VisitException(Instruction* instr) {
1280 const char *mnemonic = "unimplemented";
1281 const char *form = "'IDebug";
1282
1283 switch (instr->Mask(ExceptionMask)) {
1284 case HLT: mnemonic = "hlt"; break;
1285 case BRK: mnemonic = "brk"; break;
1286 case SVC: mnemonic = "svc"; break;
1287 case HVC: mnemonic = "hvc"; break;
1288 case SMC: mnemonic = "smc"; break;
1289 case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break;
1290 case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break;
1291 case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break;
1292 default: form = "(Exception)";
1293 }
1294 Format(instr, mnemonic, form);
1295 }
1296
VisitNEON3Same(Instruction * instr)1297 void DisassemblingDecoder::VisitNEON3Same(Instruction* instr) {
1298 const char* mnemonic = "unimplemented";
1299 const char* form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
1300 NEONFormatDecoder nfd(instr);
1301
1302 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
1303 switch (instr->Mask(NEON3SameLogicalMask)) {
1304 case NEON_AND:
1305 mnemonic = "and";
1306 break;
1307 case NEON_ORR:
1308 mnemonic = "orr";
1309 if (instr->Rm() == instr->Rn()) {
1310 mnemonic = "mov";
1311 form = "'Vd.%s, 'Vn.%s";
1312 }
1313 break;
1314 case NEON_ORN:
1315 mnemonic = "orn";
1316 break;
1317 case NEON_EOR:
1318 mnemonic = "eor";
1319 break;
1320 case NEON_BIC:
1321 mnemonic = "bic";
1322 break;
1323 case NEON_BIF:
1324 mnemonic = "bif";
1325 break;
1326 case NEON_BIT:
1327 mnemonic = "bit";
1328 break;
1329 case NEON_BSL:
1330 mnemonic = "bsl";
1331 break;
1332 default:
1333 form = "(NEON3Same)";
1334 }
1335 nfd.SetFormatMaps(nfd.LogicalFormatMap());
1336 } else {
1337 static const char* mnemonics[] = {
1338 "shadd", "uhadd", "shadd", "uhadd",
1339 "sqadd", "uqadd", "sqadd", "uqadd",
1340 "srhadd", "urhadd", "srhadd", "urhadd",
1341 nullptr, nullptr, nullptr,
1342 nullptr, // Handled by logical cases above.
1343 "shsub", "uhsub", "shsub", "uhsub",
1344 "sqsub", "uqsub", "sqsub", "uqsub",
1345 "cmgt", "cmhi", "cmgt", "cmhi",
1346 "cmge", "cmhs", "cmge", "cmhs",
1347 "sshl", "ushl", "sshl", "ushl",
1348 "sqshl", "uqshl", "sqshl", "uqshl",
1349 "srshl", "urshl", "srshl", "urshl",
1350 "sqrshl", "uqrshl", "sqrshl", "uqrshl",
1351 "smax", "umax", "smax", "umax",
1352 "smin", "umin", "smin", "umin",
1353 "sabd", "uabd", "sabd", "uabd",
1354 "saba", "uaba", "saba", "uaba",
1355 "add", "sub", "add", "sub",
1356 "cmtst", "cmeq", "cmtst", "cmeq",
1357 "mla", "mls", "mla", "mls",
1358 "mul", "pmul", "mul", "pmul",
1359 "smaxp", "umaxp", "smaxp", "umaxp",
1360 "sminp", "uminp", "sminp", "uminp",
1361 "sqdmulh", "sqrdmulh", "sqdmulh", "sqrdmulh",
1362 "addp", "unallocated", "addp", "unallocated",
1363 "fmaxnm", "fmaxnmp", "fminnm", "fminnmp",
1364 "fmla", "unallocated", "fmls", "unallocated",
1365 "fadd", "faddp", "fsub", "fabd",
1366 "fmulx", "fmul", "unallocated", "unallocated",
1367 "fcmeq", "fcmge", "unallocated", "fcmgt",
1368 "unallocated", "facge", "unallocated", "facgt",
1369 "fmax", "fmaxp", "fmin", "fminp",
1370 "frecps", "fdiv", "frsqrts", "unallocated"};
1371
1372 // Operation is determined by the opcode bits (15-11), the top bit of
1373 // size (23) and the U bit (29).
1374 unsigned index =
1375 (instr->Bits(15, 11) << 2) | (instr->Bit(23) << 1) | instr->Bit(29);
1376 DCHECK_LT(index, arraysize(mnemonics));
1377 mnemonic = mnemonics[index];
1378 // Assert that index is not one of the previously handled logical
1379 // instructions.
1380 DCHECK_NOT_NULL(mnemonic);
1381
1382 if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
1383 nfd.SetFormatMaps(nfd.FPFormatMap());
1384 }
1385 }
1386 Format(instr, mnemonic, nfd.Substitute(form));
1387 }
1388
VisitNEON2RegMisc(Instruction * instr)1389 void DisassemblingDecoder::VisitNEON2RegMisc(Instruction* instr) {
1390 const char* mnemonic = "unimplemented";
1391 const char* form = "'Vd.%s, 'Vn.%s";
1392 const char* form_cmp_zero = "'Vd.%s, 'Vn.%s, #0";
1393 const char* form_fcmp_zero = "'Vd.%s, 'Vn.%s, #0.0";
1394 NEONFormatDecoder nfd(instr);
1395
1396 static const NEONFormatMap map_lp_ta = {
1397 {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
1398
1399 static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}};
1400
1401 static const NEONFormatMap map_cvt_tb = {{22, 30},
1402 {NF_4H, NF_8H, NF_2S, NF_4S}};
1403
1404 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
1405 // These instructions all use a two bit size field, except NOT and RBIT,
1406 // which use the field to encode the operation.
1407 switch (instr->Mask(NEON2RegMiscMask)) {
1408 case NEON_REV64:
1409 mnemonic = "rev64";
1410 break;
1411 case NEON_REV32:
1412 mnemonic = "rev32";
1413 break;
1414 case NEON_REV16:
1415 mnemonic = "rev16";
1416 break;
1417 case NEON_SADDLP:
1418 mnemonic = "saddlp";
1419 nfd.SetFormatMap(0, &map_lp_ta);
1420 break;
1421 case NEON_UADDLP:
1422 mnemonic = "uaddlp";
1423 nfd.SetFormatMap(0, &map_lp_ta);
1424 break;
1425 case NEON_SUQADD:
1426 mnemonic = "suqadd";
1427 break;
1428 case NEON_USQADD:
1429 mnemonic = "usqadd";
1430 break;
1431 case NEON_CLS:
1432 mnemonic = "cls";
1433 break;
1434 case NEON_CLZ:
1435 mnemonic = "clz";
1436 break;
1437 case NEON_CNT:
1438 mnemonic = "cnt";
1439 break;
1440 case NEON_SADALP:
1441 mnemonic = "sadalp";
1442 nfd.SetFormatMap(0, &map_lp_ta);
1443 break;
1444 case NEON_UADALP:
1445 mnemonic = "uadalp";
1446 nfd.SetFormatMap(0, &map_lp_ta);
1447 break;
1448 case NEON_SQABS:
1449 mnemonic = "sqabs";
1450 break;
1451 case NEON_SQNEG:
1452 mnemonic = "sqneg";
1453 break;
1454 case NEON_CMGT_zero:
1455 mnemonic = "cmgt";
1456 form = form_cmp_zero;
1457 break;
1458 case NEON_CMGE_zero:
1459 mnemonic = "cmge";
1460 form = form_cmp_zero;
1461 break;
1462 case NEON_CMEQ_zero:
1463 mnemonic = "cmeq";
1464 form = form_cmp_zero;
1465 break;
1466 case NEON_CMLE_zero:
1467 mnemonic = "cmle";
1468 form = form_cmp_zero;
1469 break;
1470 case NEON_CMLT_zero:
1471 mnemonic = "cmlt";
1472 form = form_cmp_zero;
1473 break;
1474 case NEON_ABS:
1475 mnemonic = "abs";
1476 break;
1477 case NEON_NEG:
1478 mnemonic = "neg";
1479 break;
1480 case NEON_RBIT_NOT:
1481 switch (instr->FPType()) {
1482 case 0:
1483 mnemonic = "mvn";
1484 break;
1485 case 1:
1486 mnemonic = "rbit";
1487 break;
1488 default:
1489 form = "(NEON2RegMisc)";
1490 }
1491 nfd.SetFormatMaps(nfd.LogicalFormatMap());
1492 break;
1493 }
1494 } else {
1495 // These instructions all use a one bit size field, except XTN, SQXTUN,
1496 // SHLL, SQXTN and UQXTN, which use a two bit size field.
1497 nfd.SetFormatMaps(nfd.FPFormatMap());
1498 switch (instr->Mask(NEON2RegMiscFPMask)) {
1499 case NEON_FABS:
1500 mnemonic = "fabs";
1501 break;
1502 case NEON_FNEG:
1503 mnemonic = "fneg";
1504 break;
1505 case NEON_FCVTN:
1506 mnemonic = instr->Mask(NEON_Q) ? "fcvtn2" : "fcvtn";
1507 nfd.SetFormatMap(0, &map_cvt_tb);
1508 nfd.SetFormatMap(1, &map_cvt_ta);
1509 break;
1510 case NEON_FCVTXN:
1511 mnemonic = instr->Mask(NEON_Q) ? "fcvtxn2" : "fcvtxn";
1512 nfd.SetFormatMap(0, &map_cvt_tb);
1513 nfd.SetFormatMap(1, &map_cvt_ta);
1514 break;
1515 case NEON_FCVTL:
1516 mnemonic = instr->Mask(NEON_Q) ? "fcvtl2" : "fcvtl";
1517 nfd.SetFormatMap(0, &map_cvt_ta);
1518 nfd.SetFormatMap(1, &map_cvt_tb);
1519 break;
1520 case NEON_FRINTN:
1521 mnemonic = "frintn";
1522 break;
1523 case NEON_FRINTA:
1524 mnemonic = "frinta";
1525 break;
1526 case NEON_FRINTP:
1527 mnemonic = "frintp";
1528 break;
1529 case NEON_FRINTM:
1530 mnemonic = "frintm";
1531 break;
1532 case NEON_FRINTX:
1533 mnemonic = "frintx";
1534 break;
1535 case NEON_FRINTZ:
1536 mnemonic = "frintz";
1537 break;
1538 case NEON_FRINTI:
1539 mnemonic = "frinti";
1540 break;
1541 case NEON_FCVTNS:
1542 mnemonic = "fcvtns";
1543 break;
1544 case NEON_FCVTNU:
1545 mnemonic = "fcvtnu";
1546 break;
1547 case NEON_FCVTPS:
1548 mnemonic = "fcvtps";
1549 break;
1550 case NEON_FCVTPU:
1551 mnemonic = "fcvtpu";
1552 break;
1553 case NEON_FCVTMS:
1554 mnemonic = "fcvtms";
1555 break;
1556 case NEON_FCVTMU:
1557 mnemonic = "fcvtmu";
1558 break;
1559 case NEON_FCVTZS:
1560 mnemonic = "fcvtzs";
1561 break;
1562 case NEON_FCVTZU:
1563 mnemonic = "fcvtzu";
1564 break;
1565 case NEON_FCVTAS:
1566 mnemonic = "fcvtas";
1567 break;
1568 case NEON_FCVTAU:
1569 mnemonic = "fcvtau";
1570 break;
1571 case NEON_FSQRT:
1572 mnemonic = "fsqrt";
1573 break;
1574 case NEON_SCVTF:
1575 mnemonic = "scvtf";
1576 break;
1577 case NEON_UCVTF:
1578 mnemonic = "ucvtf";
1579 break;
1580 case NEON_URSQRTE:
1581 mnemonic = "ursqrte";
1582 break;
1583 case NEON_URECPE:
1584 mnemonic = "urecpe";
1585 break;
1586 case NEON_FRSQRTE:
1587 mnemonic = "frsqrte";
1588 break;
1589 case NEON_FRECPE:
1590 mnemonic = "frecpe";
1591 break;
1592 case NEON_FCMGT_zero:
1593 mnemonic = "fcmgt";
1594 form = form_fcmp_zero;
1595 break;
1596 case NEON_FCMGE_zero:
1597 mnemonic = "fcmge";
1598 form = form_fcmp_zero;
1599 break;
1600 case NEON_FCMEQ_zero:
1601 mnemonic = "fcmeq";
1602 form = form_fcmp_zero;
1603 break;
1604 case NEON_FCMLE_zero:
1605 mnemonic = "fcmle";
1606 form = form_fcmp_zero;
1607 break;
1608 case NEON_FCMLT_zero:
1609 mnemonic = "fcmlt";
1610 form = form_fcmp_zero;
1611 break;
1612 default:
1613 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
1614 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
1615 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1616 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1617
1618 switch (instr->Mask(NEON2RegMiscMask)) {
1619 case NEON_XTN:
1620 mnemonic = "xtn";
1621 break;
1622 case NEON_SQXTN:
1623 mnemonic = "sqxtn";
1624 break;
1625 case NEON_UQXTN:
1626 mnemonic = "uqxtn";
1627 break;
1628 case NEON_SQXTUN:
1629 mnemonic = "sqxtun";
1630 break;
1631 case NEON_SHLL:
1632 mnemonic = "shll";
1633 nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
1634 nfd.SetFormatMap(1, nfd.IntegerFormatMap());
1635 switch (instr->NEONSize()) {
1636 case 0:
1637 form = "'Vd.%s, 'Vn.%s, #8";
1638 break;
1639 case 1:
1640 form = "'Vd.%s, 'Vn.%s, #16";
1641 break;
1642 case 2:
1643 form = "'Vd.%s, 'Vn.%s, #32";
1644 break;
1645 default:
1646 Format(instr, "unallocated", "(NEON2RegMisc)");
1647 return;
1648 }
1649 }
1650 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1651 return;
1652 } else {
1653 form = "(NEON2RegMisc)";
1654 }
1655 }
1656 }
1657 Format(instr, mnemonic, nfd.Substitute(form));
1658 }
1659
VisitNEON3Different(Instruction * instr)1660 void DisassemblingDecoder::VisitNEON3Different(Instruction* instr) {
1661 const char* mnemonic = "unimplemented";
1662 const char* form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
1663
1664 NEONFormatDecoder nfd(instr);
1665 nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
1666
1667 // Ignore the Q bit. Appending a "2" suffix is handled later.
1668 switch (instr->Mask(NEON3DifferentMask) & ~NEON_Q) {
1669 case NEON_PMULL:
1670 mnemonic = "pmull";
1671 break;
1672 case NEON_SABAL:
1673 mnemonic = "sabal";
1674 break;
1675 case NEON_SABDL:
1676 mnemonic = "sabdl";
1677 break;
1678 case NEON_SADDL:
1679 mnemonic = "saddl";
1680 break;
1681 case NEON_SMLAL:
1682 mnemonic = "smlal";
1683 break;
1684 case NEON_SMLSL:
1685 mnemonic = "smlsl";
1686 break;
1687 case NEON_SMULL:
1688 mnemonic = "smull";
1689 break;
1690 case NEON_SSUBL:
1691 mnemonic = "ssubl";
1692 break;
1693 case NEON_SQDMLAL:
1694 mnemonic = "sqdmlal";
1695 break;
1696 case NEON_SQDMLSL:
1697 mnemonic = "sqdmlsl";
1698 break;
1699 case NEON_SQDMULL:
1700 mnemonic = "sqdmull";
1701 break;
1702 case NEON_UABAL:
1703 mnemonic = "uabal";
1704 break;
1705 case NEON_UABDL:
1706 mnemonic = "uabdl";
1707 break;
1708 case NEON_UADDL:
1709 mnemonic = "uaddl";
1710 break;
1711 case NEON_UMLAL:
1712 mnemonic = "umlal";
1713 break;
1714 case NEON_UMLSL:
1715 mnemonic = "umlsl";
1716 break;
1717 case NEON_UMULL:
1718 mnemonic = "umull";
1719 break;
1720 case NEON_USUBL:
1721 mnemonic = "usubl";
1722 break;
1723 case NEON_SADDW:
1724 mnemonic = "saddw";
1725 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1726 break;
1727 case NEON_SSUBW:
1728 mnemonic = "ssubw";
1729 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1730 break;
1731 case NEON_UADDW:
1732 mnemonic = "uaddw";
1733 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1734 break;
1735 case NEON_USUBW:
1736 mnemonic = "usubw";
1737 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1738 break;
1739 case NEON_ADDHN:
1740 mnemonic = "addhn";
1741 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1742 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1743 break;
1744 case NEON_RADDHN:
1745 mnemonic = "raddhn";
1746 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1747 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1748 break;
1749 case NEON_RSUBHN:
1750 mnemonic = "rsubhn";
1751 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1752 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1753 break;
1754 case NEON_SUBHN:
1755 mnemonic = "subhn";
1756 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1757 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1758 break;
1759 default:
1760 form = "(NEON3Different)";
1761 }
1762 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1763 }
1764
VisitNEONAcrossLanes(Instruction * instr)1765 void DisassemblingDecoder::VisitNEONAcrossLanes(Instruction* instr) {
1766 const char* mnemonic = "unimplemented";
1767 const char* form = "%sd, 'Vn.%s";
1768
1769 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap(),
1770 NEONFormatDecoder::IntegerFormatMap());
1771
1772 if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
1773 nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
1774 nfd.SetFormatMap(1, nfd.FPFormatMap());
1775 switch (instr->Mask(NEONAcrossLanesFPMask)) {
1776 case NEON_FMAXV:
1777 mnemonic = "fmaxv";
1778 break;
1779 case NEON_FMINV:
1780 mnemonic = "fminv";
1781 break;
1782 case NEON_FMAXNMV:
1783 mnemonic = "fmaxnmv";
1784 break;
1785 case NEON_FMINNMV:
1786 mnemonic = "fminnmv";
1787 break;
1788 default:
1789 form = "(NEONAcrossLanes)";
1790 break;
1791 }
1792 } else if (instr->Mask(NEONAcrossLanesFMask) == NEONAcrossLanesFixed) {
1793 switch (instr->Mask(NEONAcrossLanesMask)) {
1794 case NEON_ADDV:
1795 mnemonic = "addv";
1796 break;
1797 case NEON_SMAXV:
1798 mnemonic = "smaxv";
1799 break;
1800 case NEON_SMINV:
1801 mnemonic = "sminv";
1802 break;
1803 case NEON_UMAXV:
1804 mnemonic = "umaxv";
1805 break;
1806 case NEON_UMINV:
1807 mnemonic = "uminv";
1808 break;
1809 case NEON_SADDLV:
1810 mnemonic = "saddlv";
1811 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
1812 break;
1813 case NEON_UADDLV:
1814 mnemonic = "uaddlv";
1815 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
1816 break;
1817 default:
1818 form = "(NEONAcrossLanes)";
1819 break;
1820 }
1821 }
1822 Format(instr, mnemonic,
1823 nfd.Substitute(form, NEONFormatDecoder::kPlaceholder,
1824 NEONFormatDecoder::kFormat));
1825 }
1826
VisitNEONByIndexedElement(Instruction * instr)1827 void DisassemblingDecoder::VisitNEONByIndexedElement(Instruction* instr) {
1828 const char* mnemonic = "unimplemented";
1829 bool l_instr = false;
1830 bool fp_instr = false;
1831
1832 const char* form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
1833
1834 static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}};
1835 NEONFormatDecoder nfd(instr, &map_ta, NEONFormatDecoder::IntegerFormatMap(),
1836 NEONFormatDecoder::ScalarFormatMap());
1837
1838 switch (instr->Mask(NEONByIndexedElementMask)) {
1839 case NEON_SMULL_byelement:
1840 mnemonic = "smull";
1841 l_instr = true;
1842 break;
1843 case NEON_UMULL_byelement:
1844 mnemonic = "umull";
1845 l_instr = true;
1846 break;
1847 case NEON_SMLAL_byelement:
1848 mnemonic = "smlal";
1849 l_instr = true;
1850 break;
1851 case NEON_UMLAL_byelement:
1852 mnemonic = "umlal";
1853 l_instr = true;
1854 break;
1855 case NEON_SMLSL_byelement:
1856 mnemonic = "smlsl";
1857 l_instr = true;
1858 break;
1859 case NEON_UMLSL_byelement:
1860 mnemonic = "umlsl";
1861 l_instr = true;
1862 break;
1863 case NEON_SQDMULL_byelement:
1864 mnemonic = "sqdmull";
1865 l_instr = true;
1866 break;
1867 case NEON_SQDMLAL_byelement:
1868 mnemonic = "sqdmlal";
1869 l_instr = true;
1870 break;
1871 case NEON_SQDMLSL_byelement:
1872 mnemonic = "sqdmlsl";
1873 l_instr = true;
1874 break;
1875 case NEON_MUL_byelement:
1876 mnemonic = "mul";
1877 break;
1878 case NEON_MLA_byelement:
1879 mnemonic = "mla";
1880 break;
1881 case NEON_MLS_byelement:
1882 mnemonic = "mls";
1883 break;
1884 case NEON_SQDMULH_byelement:
1885 mnemonic = "sqdmulh";
1886 break;
1887 case NEON_SQRDMULH_byelement:
1888 mnemonic = "sqrdmulh";
1889 break;
1890 default:
1891 switch (instr->Mask(NEONByIndexedElementFPMask)) {
1892 case NEON_FMUL_byelement:
1893 mnemonic = "fmul";
1894 fp_instr = true;
1895 break;
1896 case NEON_FMLA_byelement:
1897 mnemonic = "fmla";
1898 fp_instr = true;
1899 break;
1900 case NEON_FMLS_byelement:
1901 mnemonic = "fmls";
1902 fp_instr = true;
1903 break;
1904 case NEON_FMULX_byelement:
1905 mnemonic = "fmulx";
1906 fp_instr = true;
1907 break;
1908 }
1909 }
1910
1911 if (l_instr) {
1912 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1913 } else if (fp_instr) {
1914 nfd.SetFormatMap(0, nfd.FPFormatMap());
1915 Format(instr, mnemonic, nfd.Substitute(form));
1916 } else {
1917 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1918 Format(instr, mnemonic, nfd.Substitute(form));
1919 }
1920 }
1921
VisitNEONCopy(Instruction * instr)1922 void DisassemblingDecoder::VisitNEONCopy(Instruction* instr) {
1923 const char* mnemonic = "unimplemented";
1924 const char* form = "(NEONCopy)";
1925
1926 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap(),
1927 NEONFormatDecoder::TriangularScalarFormatMap());
1928
1929 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
1930 mnemonic = "mov";
1931 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1932 form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]";
1933 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
1934 mnemonic = "mov";
1935 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1936 if (nfd.GetVectorFormat() == kFormatD) {
1937 form = "'Vd.%s['IVInsIndex1], 'Xn";
1938 } else {
1939 form = "'Vd.%s['IVInsIndex1], 'Wn";
1940 }
1941 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
1942 if (instr->Mask(NEON_Q) || ((instr->ImmNEON5() & 7) == 4)) {
1943 mnemonic = "mov";
1944 } else {
1945 mnemonic = "umov";
1946 }
1947 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1948 if (nfd.GetVectorFormat() == kFormatD) {
1949 form = "'Xd, 'Vn.%s['IVInsIndex1]";
1950 } else {
1951 form = "'Wd, 'Vn.%s['IVInsIndex1]";
1952 }
1953 } else if (instr->Mask(NEONCopySmovMask) == NEON_SMOV) {
1954 mnemonic = "smov";
1955 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1956 form = "'Rdq, 'Vn.%s['IVInsIndex1]";
1957 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
1958 mnemonic = "dup";
1959 form = "'Vd.%s, 'Vn.%s['IVInsIndex1]";
1960 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
1961 mnemonic = "dup";
1962 if (nfd.GetVectorFormat() == kFormat2D) {
1963 form = "'Vd.%s, 'Xn";
1964 } else {
1965 form = "'Vd.%s, 'Wn";
1966 }
1967 }
1968 Format(instr, mnemonic, nfd.Substitute(form));
1969 }
1970
VisitNEONExtract(Instruction * instr)1971 void DisassemblingDecoder::VisitNEONExtract(Instruction* instr) {
1972 const char* mnemonic = "unimplemented";
1973 const char* form = "(NEONExtract)";
1974 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
1975 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
1976 mnemonic = "ext";
1977 form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract";
1978 }
1979 Format(instr, mnemonic, nfd.Substitute(form));
1980 }
1981
VisitNEONLoadStoreMultiStruct(Instruction * instr)1982 void DisassemblingDecoder::VisitNEONLoadStoreMultiStruct(Instruction* instr) {
1983 const char* mnemonic = nullptr;
1984 const char* form = nullptr;
1985 const char* form_1v = "{'Vt.%1$s}, ['Xns]";
1986 const char* form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]";
1987 const char* form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]";
1988 const char* form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
1989 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
1990
1991 switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
1992 case NEON_LD1_1v:
1993 mnemonic = "ld1";
1994 form = form_1v;
1995 break;
1996 case NEON_LD1_2v:
1997 mnemonic = "ld1";
1998 form = form_2v;
1999 break;
2000 case NEON_LD1_3v:
2001 mnemonic = "ld1";
2002 form = form_3v;
2003 break;
2004 case NEON_LD1_4v:
2005 mnemonic = "ld1";
2006 form = form_4v;
2007 break;
2008 case NEON_LD2:
2009 mnemonic = "ld2";
2010 form = form_2v;
2011 break;
2012 case NEON_LD3:
2013 mnemonic = "ld3";
2014 form = form_3v;
2015 break;
2016 case NEON_LD4:
2017 mnemonic = "ld4";
2018 form = form_4v;
2019 break;
2020 case NEON_ST1_1v:
2021 mnemonic = "st1";
2022 form = form_1v;
2023 break;
2024 case NEON_ST1_2v:
2025 mnemonic = "st1";
2026 form = form_2v;
2027 break;
2028 case NEON_ST1_3v:
2029 mnemonic = "st1";
2030 form = form_3v;
2031 break;
2032 case NEON_ST1_4v:
2033 mnemonic = "st1";
2034 form = form_4v;
2035 break;
2036 case NEON_ST2:
2037 mnemonic = "st2";
2038 form = form_2v;
2039 break;
2040 case NEON_ST3:
2041 mnemonic = "st3";
2042 form = form_3v;
2043 break;
2044 case NEON_ST4:
2045 mnemonic = "st4";
2046 form = form_4v;
2047 break;
2048 default:
2049 break;
2050 }
2051
2052 // Work out unallocated encodings.
2053 bool allocated = (mnemonic != nullptr);
2054 switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
2055 case NEON_LD2:
2056 case NEON_LD3:
2057 case NEON_LD4:
2058 case NEON_ST2:
2059 case NEON_ST3:
2060 case NEON_ST4:
2061 // LD[2-4] and ST[2-4] cannot use .1d format.
2062 allocated = (instr->NEONQ() != 0) || (instr->NEONLSSize() != 3);
2063 break;
2064 default:
2065 break;
2066 }
2067 if (allocated) {
2068 DCHECK_NOT_NULL(mnemonic);
2069 DCHECK_NOT_NULL(form);
2070 } else {
2071 mnemonic = "unallocated";
2072 form = "(NEONLoadStoreMultiStruct)";
2073 }
2074
2075 Format(instr, mnemonic, nfd.Substitute(form));
2076 }
2077
VisitNEONLoadStoreMultiStructPostIndex(Instruction * instr)2078 void DisassemblingDecoder::VisitNEONLoadStoreMultiStructPostIndex(
2079 Instruction* instr) {
2080 const char* mnemonic = nullptr;
2081 const char* form = nullptr;
2082 const char* form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1";
2083 const char* form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2";
2084 const char* form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3";
2085 const char* form_4v =
2086 "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4";
2087 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2088
2089 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
2090 case NEON_LD1_1v_post:
2091 mnemonic = "ld1";
2092 form = form_1v;
2093 break;
2094 case NEON_LD1_2v_post:
2095 mnemonic = "ld1";
2096 form = form_2v;
2097 break;
2098 case NEON_LD1_3v_post:
2099 mnemonic = "ld1";
2100 form = form_3v;
2101 break;
2102 case NEON_LD1_4v_post:
2103 mnemonic = "ld1";
2104 form = form_4v;
2105 break;
2106 case NEON_LD2_post:
2107 mnemonic = "ld2";
2108 form = form_2v;
2109 break;
2110 case NEON_LD3_post:
2111 mnemonic = "ld3";
2112 form = form_3v;
2113 break;
2114 case NEON_LD4_post:
2115 mnemonic = "ld4";
2116 form = form_4v;
2117 break;
2118 case NEON_ST1_1v_post:
2119 mnemonic = "st1";
2120 form = form_1v;
2121 break;
2122 case NEON_ST1_2v_post:
2123 mnemonic = "st1";
2124 form = form_2v;
2125 break;
2126 case NEON_ST1_3v_post:
2127 mnemonic = "st1";
2128 form = form_3v;
2129 break;
2130 case NEON_ST1_4v_post:
2131 mnemonic = "st1";
2132 form = form_4v;
2133 break;
2134 case NEON_ST2_post:
2135 mnemonic = "st2";
2136 form = form_2v;
2137 break;
2138 case NEON_ST3_post:
2139 mnemonic = "st3";
2140 form = form_3v;
2141 break;
2142 case NEON_ST4_post:
2143 mnemonic = "st4";
2144 form = form_4v;
2145 break;
2146 default:
2147 break;
2148 }
2149
2150 // Work out unallocated encodings.
2151 bool allocated = (mnemonic != nullptr);
2152 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
2153 case NEON_LD2_post:
2154 case NEON_LD3_post:
2155 case NEON_LD4_post:
2156 case NEON_ST2_post:
2157 case NEON_ST3_post:
2158 case NEON_ST4_post:
2159 // LD[2-4] and ST[2-4] cannot use .1d format.
2160 allocated = (instr->NEONQ() != 0) || (instr->NEONLSSize() != 3);
2161 break;
2162 default:
2163 break;
2164 }
2165 if (allocated) {
2166 DCHECK_NOT_NULL(mnemonic);
2167 DCHECK_NOT_NULL(form);
2168 } else {
2169 mnemonic = "unallocated";
2170 form = "(NEONLoadStoreMultiStructPostIndex)";
2171 }
2172
2173 Format(instr, mnemonic, nfd.Substitute(form));
2174 }
2175
VisitNEONLoadStoreSingleStruct(Instruction * instr)2176 void DisassemblingDecoder::VisitNEONLoadStoreSingleStruct(Instruction* instr) {
2177 const char* mnemonic = nullptr;
2178 const char* form = nullptr;
2179
2180 const char* form_1b = "{'Vt.b}['IVLSLane0], ['Xns]";
2181 const char* form_1h = "{'Vt.h}['IVLSLane1], ['Xns]";
2182 const char* form_1s = "{'Vt.s}['IVLSLane2], ['Xns]";
2183 const char* form_1d = "{'Vt.d}['IVLSLane3], ['Xns]";
2184 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2185
2186 switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
2187 case NEON_LD1_b:
2188 mnemonic = "ld1";
2189 form = form_1b;
2190 break;
2191 case NEON_LD1_h:
2192 mnemonic = "ld1";
2193 form = form_1h;
2194 break;
2195 case NEON_LD1_s:
2196 mnemonic = "ld1";
2197 static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
2198 "LSB of size distinguishes S and D registers.");
2199 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2200 break;
2201 case NEON_ST1_b:
2202 mnemonic = "st1";
2203 form = form_1b;
2204 break;
2205 case NEON_ST1_h:
2206 mnemonic = "st1";
2207 form = form_1h;
2208 break;
2209 case NEON_ST1_s:
2210 mnemonic = "st1";
2211 static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
2212 "LSB of size distinguishes S and D registers.");
2213 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2214 break;
2215 case NEON_LD1R:
2216 mnemonic = "ld1r";
2217 form = "{'Vt.%s}, ['Xns]";
2218 break;
2219 case NEON_LD2_b:
2220 case NEON_ST2_b:
2221 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2222 form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]";
2223 break;
2224 case NEON_LD2_h:
2225 case NEON_ST2_h:
2226 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2227 form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]";
2228 break;
2229 case NEON_LD2_s:
2230 case NEON_ST2_s:
2231 static_assert((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d,
2232 "LSB of size distinguishes S and D registers.");
2233 static_assert((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d,
2234 "LSB of size distinguishes S and D registers.");
2235 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2236 if ((instr->NEONLSSize() & 1) == 0) {
2237 form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]";
2238 } else {
2239 form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]";
2240 }
2241 break;
2242 case NEON_LD2R:
2243 mnemonic = "ld2r";
2244 form = "{'Vt.%s, 'Vt2.%s}, ['Xns]";
2245 break;
2246 case NEON_LD3_b:
2247 case NEON_ST3_b:
2248 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2249 form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]";
2250 break;
2251 case NEON_LD3_h:
2252 case NEON_ST3_h:
2253 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2254 form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]";
2255 break;
2256 case NEON_LD3_s:
2257 case NEON_ST3_s:
2258 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2259 if ((instr->NEONLSSize() & 1) == 0) {
2260 form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]";
2261 } else {
2262 form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]";
2263 }
2264 break;
2265 case NEON_LD3R:
2266 mnemonic = "ld3r";
2267 form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]";
2268 break;
2269 case NEON_LD4_b:
2270 case NEON_ST4_b:
2271 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2272 form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]";
2273 break;
2274 case NEON_LD4_h:
2275 case NEON_ST4_h:
2276 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2277 form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]";
2278 break;
2279 case NEON_LD4_s:
2280 case NEON_ST4_s:
2281 static_assert((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d,
2282 "LSB of size distinguishes S and D registers.");
2283 static_assert((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d,
2284 "LSB of size distinguishes S and D registers.");
2285 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2286 if ((instr->NEONLSSize() & 1) == 0) {
2287 form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]";
2288 } else {
2289 form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]";
2290 }
2291 break;
2292 case NEON_LD4R:
2293 mnemonic = "ld4r";
2294 form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
2295 break;
2296 default:
2297 break;
2298 }
2299
2300 // Work out unallocated encodings.
2301 bool allocated = (mnemonic != nullptr);
2302 switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
2303 case NEON_LD1_h:
2304 case NEON_LD2_h:
2305 case NEON_LD3_h:
2306 case NEON_LD4_h:
2307 case NEON_ST1_h:
2308 case NEON_ST2_h:
2309 case NEON_ST3_h:
2310 case NEON_ST4_h:
2311 DCHECK(allocated);
2312 allocated = ((instr->NEONLSSize() & 1) == 0);
2313 break;
2314 case NEON_LD1_s:
2315 case NEON_LD2_s:
2316 case NEON_LD3_s:
2317 case NEON_LD4_s:
2318 case NEON_ST1_s:
2319 case NEON_ST2_s:
2320 case NEON_ST3_s:
2321 case NEON_ST4_s:
2322 DCHECK(allocated);
2323 allocated = (instr->NEONLSSize() <= 1) &&
2324 ((instr->NEONLSSize() == 0) || (instr->NEONS() == 0));
2325 break;
2326 case NEON_LD1R:
2327 case NEON_LD2R:
2328 case NEON_LD3R:
2329 case NEON_LD4R:
2330 DCHECK(allocated);
2331 allocated = (instr->NEONS() == 0);
2332 break;
2333 default:
2334 break;
2335 }
2336 if (allocated) {
2337 DCHECK_NOT_NULL(mnemonic);
2338 DCHECK_NOT_NULL(form);
2339 } else {
2340 mnemonic = "unallocated";
2341 form = "(NEONLoadStoreSingleStruct)";
2342 }
2343
2344 Format(instr, mnemonic, nfd.Substitute(form));
2345 }
2346
VisitNEONLoadStoreSingleStructPostIndex(Instruction * instr)2347 void DisassemblingDecoder::VisitNEONLoadStoreSingleStructPostIndex(
2348 Instruction* instr) {
2349 const char* mnemonic = nullptr;
2350 const char* form = nullptr;
2351
2352 const char* form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1";
2353 const char* form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2";
2354 const char* form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4";
2355 const char* form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8";
2356 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2357
2358 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
2359 case NEON_LD1_b_post:
2360 mnemonic = "ld1";
2361 form = form_1b;
2362 break;
2363 case NEON_LD1_h_post:
2364 mnemonic = "ld1";
2365 form = form_1h;
2366 break;
2367 case NEON_LD1_s_post:
2368 mnemonic = "ld1";
2369 static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
2370 "LSB of size distinguishes S and D registers.");
2371 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2372 break;
2373 case NEON_ST1_b_post:
2374 mnemonic = "st1";
2375 form = form_1b;
2376 break;
2377 case NEON_ST1_h_post:
2378 mnemonic = "st1";
2379 form = form_1h;
2380 break;
2381 case NEON_ST1_s_post:
2382 mnemonic = "st1";
2383 static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
2384 "LSB of size distinguishes S and D registers.");
2385 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2386 break;
2387 case NEON_LD1R_post:
2388 mnemonic = "ld1r";
2389 form = "{'Vt.%s}, ['Xns], 'Xmz1";
2390 break;
2391 case NEON_LD2_b_post:
2392 case NEON_ST2_b_post:
2393 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2394 form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2";
2395 break;
2396 case NEON_ST2_h_post:
2397 case NEON_LD2_h_post:
2398 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2399 form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4";
2400 break;
2401 case NEON_LD2_s_post:
2402 case NEON_ST2_s_post:
2403 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2404 if ((instr->NEONLSSize() & 1) == 0)
2405 form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8";
2406 else
2407 form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16";
2408 break;
2409 case NEON_LD2R_post:
2410 mnemonic = "ld2r";
2411 form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2";
2412 break;
2413 case NEON_LD3_b_post:
2414 case NEON_ST3_b_post:
2415 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2416 form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3";
2417 break;
2418 case NEON_LD3_h_post:
2419 case NEON_ST3_h_post:
2420 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2421 form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6";
2422 break;
2423 case NEON_LD3_s_post:
2424 case NEON_ST3_s_post:
2425 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2426 if ((instr->NEONLSSize() & 1) == 0)
2427 form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12";
2428 else
2429 form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24";
2430 break;
2431 case NEON_LD3R_post:
2432 mnemonic = "ld3r";
2433 form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3";
2434 break;
2435 case NEON_LD4_b_post:
2436 case NEON_ST4_b_post:
2437 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2438 form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4";
2439 break;
2440 case NEON_LD4_h_post:
2441 case NEON_ST4_h_post:
2442 mnemonic = (instr->NEONLoad()) == 1 ? "ld4" : "st4";
2443 form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8";
2444 break;
2445 case NEON_LD4_s_post:
2446 case NEON_ST4_s_post:
2447 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2448 if ((instr->NEONLSSize() & 1) == 0)
2449 form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16";
2450 else
2451 form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32";
2452 break;
2453 case NEON_LD4R_post:
2454 mnemonic = "ld4r";
2455 form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4";
2456 break;
2457 default:
2458 break;
2459 }
2460
2461 // Work out unallocated encodings.
2462 bool allocated = (mnemonic != nullptr);
2463 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
2464 case NEON_LD1_h_post:
2465 case NEON_LD2_h_post:
2466 case NEON_LD3_h_post:
2467 case NEON_LD4_h_post:
2468 case NEON_ST1_h_post:
2469 case NEON_ST2_h_post:
2470 case NEON_ST3_h_post:
2471 case NEON_ST4_h_post:
2472 DCHECK(allocated);
2473 allocated = ((instr->NEONLSSize() & 1) == 0);
2474 break;
2475 case NEON_LD1_s_post:
2476 case NEON_LD2_s_post:
2477 case NEON_LD3_s_post:
2478 case NEON_LD4_s_post:
2479 case NEON_ST1_s_post:
2480 case NEON_ST2_s_post:
2481 case NEON_ST3_s_post:
2482 case NEON_ST4_s_post:
2483 DCHECK(allocated);
2484 allocated = (instr->NEONLSSize() <= 1) &&
2485 ((instr->NEONLSSize() == 0) || (instr->NEONS() == 0));
2486 break;
2487 case NEON_LD1R_post:
2488 case NEON_LD2R_post:
2489 case NEON_LD3R_post:
2490 case NEON_LD4R_post:
2491 DCHECK(allocated);
2492 allocated = (instr->NEONS() == 0);
2493 break;
2494 default:
2495 break;
2496 }
2497 if (allocated) {
2498 DCHECK_NOT_NULL(mnemonic);
2499 DCHECK_NOT_NULL(form);
2500 } else {
2501 mnemonic = "unallocated";
2502 form = "(NEONLoadStoreSingleStructPostIndex)";
2503 }
2504
2505 Format(instr, mnemonic, nfd.Substitute(form));
2506 }
2507
VisitNEONModifiedImmediate(Instruction * instr)2508 void DisassemblingDecoder::VisitNEONModifiedImmediate(Instruction* instr) {
2509 const char* mnemonic = "unimplemented";
2510 const char* form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1";
2511
2512 int cmode = instr->NEONCmode();
2513 int cmode_3 = (cmode >> 3) & 1;
2514 int cmode_2 = (cmode >> 2) & 1;
2515 int cmode_1 = (cmode >> 1) & 1;
2516 int cmode_0 = cmode & 1;
2517 int q = instr->NEONQ();
2518 int op = instr->NEONModImmOp();
2519
2520 static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
2521 static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}};
2522 static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}};
2523 NEONFormatDecoder nfd(instr, &map_b);
2524
2525 if (cmode_3 == 0) {
2526 if (cmode_0 == 0) {
2527 mnemonic = (op == 1) ? "mvni" : "movi";
2528 } else { // cmode<0> == '1'.
2529 mnemonic = (op == 1) ? "bic" : "orr";
2530 }
2531 nfd.SetFormatMap(0, &map_s);
2532 } else { // cmode<3> == '1'.
2533 if (cmode_2 == 0) {
2534 if (cmode_0 == 0) {
2535 mnemonic = (op == 1) ? "mvni" : "movi";
2536 } else { // cmode<0> == '1'.
2537 mnemonic = (op == 1) ? "bic" : "orr";
2538 }
2539 nfd.SetFormatMap(0, &map_h);
2540 } else { // cmode<2> == '1'.
2541 if (cmode_1 == 0) {
2542 mnemonic = (op == 1) ? "mvni" : "movi";
2543 form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2";
2544 nfd.SetFormatMap(0, &map_s);
2545 } else { // cmode<1> == '1'.
2546 if (cmode_0 == 0) {
2547 mnemonic = "movi";
2548 if (op == 0) {
2549 form = "'Vt.%s, 'IVMIImm8";
2550 } else {
2551 form = (q == 0) ? "'Dd, 'IVMIImm" : "'Vt.2d, 'IVMIImm";
2552 }
2553 } else { // cmode<0> == '1'
2554 mnemonic = "fmov";
2555 if (op == 0) {
2556 form = "'Vt.%s, 'IVMIImmFPSingle";
2557 nfd.SetFormatMap(0, &map_s);
2558 } else {
2559 if (q == 1) {
2560 form = "'Vt.2d, 'IVMIImmFPDouble";
2561 } else {
2562 mnemonic = "unallocated";
2563 form = "(NEONModifiedImmediate)";
2564 }
2565 }
2566 }
2567 }
2568 }
2569 }
2570 Format(instr, mnemonic, nfd.Substitute(form));
2571 }
2572
VisitNEONPerm(Instruction * instr)2573 void DisassemblingDecoder::VisitNEONPerm(Instruction* instr) {
2574 const char* mnemonic = "unimplemented";
2575 const char* form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2576 NEONFormatDecoder nfd(instr);
2577
2578 switch (instr->Mask(NEONPermMask)) {
2579 case NEON_TRN1:
2580 mnemonic = "trn1";
2581 break;
2582 case NEON_TRN2:
2583 mnemonic = "trn2";
2584 break;
2585 case NEON_UZP1:
2586 mnemonic = "uzp1";
2587 break;
2588 case NEON_UZP2:
2589 mnemonic = "uzp2";
2590 break;
2591 case NEON_ZIP1:
2592 mnemonic = "zip1";
2593 break;
2594 case NEON_ZIP2:
2595 mnemonic = "zip2";
2596 break;
2597 default:
2598 form = "(NEONPerm)";
2599 }
2600 Format(instr, mnemonic, nfd.Substitute(form));
2601 }
2602
VisitNEONScalar2RegMisc(Instruction * instr)2603 void DisassemblingDecoder::VisitNEONScalar2RegMisc(Instruction* instr) {
2604 const char* mnemonic = "unimplemented";
2605 const char* form = "%sd, %sn";
2606 const char* form_0 = "%sd, %sn, #0";
2607 const char* form_fp0 = "%sd, %sn, #0.0";
2608
2609 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2610
2611 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
2612 // These instructions all use a two bit size field, except NOT and RBIT,
2613 // which use the field to encode the operation.
2614 switch (instr->Mask(NEONScalar2RegMiscMask)) {
2615 case NEON_CMGT_zero_scalar:
2616 mnemonic = "cmgt";
2617 form = form_0;
2618 break;
2619 case NEON_CMGE_zero_scalar:
2620 mnemonic = "cmge";
2621 form = form_0;
2622 break;
2623 case NEON_CMLE_zero_scalar:
2624 mnemonic = "cmle";
2625 form = form_0;
2626 break;
2627 case NEON_CMLT_zero_scalar:
2628 mnemonic = "cmlt";
2629 form = form_0;
2630 break;
2631 case NEON_CMEQ_zero_scalar:
2632 mnemonic = "cmeq";
2633 form = form_0;
2634 break;
2635 case NEON_NEG_scalar:
2636 mnemonic = "neg";
2637 break;
2638 case NEON_SQNEG_scalar:
2639 mnemonic = "sqneg";
2640 break;
2641 case NEON_ABS_scalar:
2642 mnemonic = "abs";
2643 break;
2644 case NEON_SQABS_scalar:
2645 mnemonic = "sqabs";
2646 break;
2647 case NEON_SUQADD_scalar:
2648 mnemonic = "suqadd";
2649 break;
2650 case NEON_USQADD_scalar:
2651 mnemonic = "usqadd";
2652 break;
2653 default:
2654 form = "(NEONScalar2RegMisc)";
2655 }
2656 } else {
2657 // These instructions all use a one bit size field, except SQXTUN, SQXTN
2658 // and UQXTN, which use a two bit size field.
2659 nfd.SetFormatMaps(nfd.FPScalarFormatMap());
2660 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
2661 case NEON_FRSQRTE_scalar:
2662 mnemonic = "frsqrte";
2663 break;
2664 case NEON_FRECPE_scalar:
2665 mnemonic = "frecpe";
2666 break;
2667 case NEON_SCVTF_scalar:
2668 mnemonic = "scvtf";
2669 break;
2670 case NEON_UCVTF_scalar:
2671 mnemonic = "ucvtf";
2672 break;
2673 case NEON_FCMGT_zero_scalar:
2674 mnemonic = "fcmgt";
2675 form = form_fp0;
2676 break;
2677 case NEON_FCMGE_zero_scalar:
2678 mnemonic = "fcmge";
2679 form = form_fp0;
2680 break;
2681 case NEON_FCMLE_zero_scalar:
2682 mnemonic = "fcmle";
2683 form = form_fp0;
2684 break;
2685 case NEON_FCMLT_zero_scalar:
2686 mnemonic = "fcmlt";
2687 form = form_fp0;
2688 break;
2689 case NEON_FCMEQ_zero_scalar:
2690 mnemonic = "fcmeq";
2691 form = form_fp0;
2692 break;
2693 case NEON_FRECPX_scalar:
2694 mnemonic = "frecpx";
2695 break;
2696 case NEON_FCVTNS_scalar:
2697 mnemonic = "fcvtns";
2698 break;
2699 case NEON_FCVTNU_scalar:
2700 mnemonic = "fcvtnu";
2701 break;
2702 case NEON_FCVTPS_scalar:
2703 mnemonic = "fcvtps";
2704 break;
2705 case NEON_FCVTPU_scalar:
2706 mnemonic = "fcvtpu";
2707 break;
2708 case NEON_FCVTMS_scalar:
2709 mnemonic = "fcvtms";
2710 break;
2711 case NEON_FCVTMU_scalar:
2712 mnemonic = "fcvtmu";
2713 break;
2714 case NEON_FCVTZS_scalar:
2715 mnemonic = "fcvtzs";
2716 break;
2717 case NEON_FCVTZU_scalar:
2718 mnemonic = "fcvtzu";
2719 break;
2720 case NEON_FCVTAS_scalar:
2721 mnemonic = "fcvtas";
2722 break;
2723 case NEON_FCVTAU_scalar:
2724 mnemonic = "fcvtau";
2725 break;
2726 case NEON_FCVTXN_scalar:
2727 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
2728 mnemonic = "fcvtxn";
2729 break;
2730 default:
2731 nfd.SetFormatMap(0, nfd.ScalarFormatMap());
2732 nfd.SetFormatMap(1, nfd.LongScalarFormatMap());
2733 switch (instr->Mask(NEONScalar2RegMiscMask)) {
2734 case NEON_SQXTN_scalar:
2735 mnemonic = "sqxtn";
2736 break;
2737 case NEON_UQXTN_scalar:
2738 mnemonic = "uqxtn";
2739 break;
2740 case NEON_SQXTUN_scalar:
2741 mnemonic = "sqxtun";
2742 break;
2743 default:
2744 form = "(NEONScalar2RegMisc)";
2745 }
2746 }
2747 }
2748 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2749 }
2750
VisitNEONScalar3Diff(Instruction * instr)2751 void DisassemblingDecoder::VisitNEONScalar3Diff(Instruction* instr) {
2752 const char* mnemonic = "unimplemented";
2753 const char* form = "%sd, %sn, %sm";
2754 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap(),
2755 NEONFormatDecoder::ScalarFormatMap());
2756
2757 switch (instr->Mask(NEONScalar3DiffMask)) {
2758 case NEON_SQDMLAL_scalar:
2759 mnemonic = "sqdmlal";
2760 break;
2761 case NEON_SQDMLSL_scalar:
2762 mnemonic = "sqdmlsl";
2763 break;
2764 case NEON_SQDMULL_scalar:
2765 mnemonic = "sqdmull";
2766 break;
2767 default:
2768 form = "(NEONScalar3Diff)";
2769 }
2770 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2771 }
2772
VisitNEONScalar3Same(Instruction * instr)2773 void DisassemblingDecoder::VisitNEONScalar3Same(Instruction* instr) {
2774 const char* mnemonic = "unimplemented";
2775 const char* form = "%sd, %sn, %sm";
2776 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2777
2778 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
2779 nfd.SetFormatMaps(nfd.FPScalarFormatMap());
2780 switch (instr->Mask(NEONScalar3SameFPMask)) {
2781 case NEON_FACGE_scalar:
2782 mnemonic = "facge";
2783 break;
2784 case NEON_FACGT_scalar:
2785 mnemonic = "facgt";
2786 break;
2787 case NEON_FCMEQ_scalar:
2788 mnemonic = "fcmeq";
2789 break;
2790 case NEON_FCMGE_scalar:
2791 mnemonic = "fcmge";
2792 break;
2793 case NEON_FCMGT_scalar:
2794 mnemonic = "fcmgt";
2795 break;
2796 case NEON_FMULX_scalar:
2797 mnemonic = "fmulx";
2798 break;
2799 case NEON_FRECPS_scalar:
2800 mnemonic = "frecps";
2801 break;
2802 case NEON_FRSQRTS_scalar:
2803 mnemonic = "frsqrts";
2804 break;
2805 case NEON_FABD_scalar:
2806 mnemonic = "fabd";
2807 break;
2808 default:
2809 form = "(NEONScalar3Same)";
2810 }
2811 } else {
2812 switch (instr->Mask(NEONScalar3SameMask)) {
2813 case NEON_ADD_scalar:
2814 mnemonic = "add";
2815 break;
2816 case NEON_SUB_scalar:
2817 mnemonic = "sub";
2818 break;
2819 case NEON_CMEQ_scalar:
2820 mnemonic = "cmeq";
2821 break;
2822 case NEON_CMGE_scalar:
2823 mnemonic = "cmge";
2824 break;
2825 case NEON_CMGT_scalar:
2826 mnemonic = "cmgt";
2827 break;
2828 case NEON_CMHI_scalar:
2829 mnemonic = "cmhi";
2830 break;
2831 case NEON_CMHS_scalar:
2832 mnemonic = "cmhs";
2833 break;
2834 case NEON_CMTST_scalar:
2835 mnemonic = "cmtst";
2836 break;
2837 case NEON_UQADD_scalar:
2838 mnemonic = "uqadd";
2839 break;
2840 case NEON_SQADD_scalar:
2841 mnemonic = "sqadd";
2842 break;
2843 case NEON_UQSUB_scalar:
2844 mnemonic = "uqsub";
2845 break;
2846 case NEON_SQSUB_scalar:
2847 mnemonic = "sqsub";
2848 break;
2849 case NEON_USHL_scalar:
2850 mnemonic = "ushl";
2851 break;
2852 case NEON_SSHL_scalar:
2853 mnemonic = "sshl";
2854 break;
2855 case NEON_UQSHL_scalar:
2856 mnemonic = "uqshl";
2857 break;
2858 case NEON_SQSHL_scalar:
2859 mnemonic = "sqshl";
2860 break;
2861 case NEON_URSHL_scalar:
2862 mnemonic = "urshl";
2863 break;
2864 case NEON_SRSHL_scalar:
2865 mnemonic = "srshl";
2866 break;
2867 case NEON_UQRSHL_scalar:
2868 mnemonic = "uqrshl";
2869 break;
2870 case NEON_SQRSHL_scalar:
2871 mnemonic = "sqrshl";
2872 break;
2873 case NEON_SQDMULH_scalar:
2874 mnemonic = "sqdmulh";
2875 break;
2876 case NEON_SQRDMULH_scalar:
2877 mnemonic = "sqrdmulh";
2878 break;
2879 default:
2880 form = "(NEONScalar3Same)";
2881 }
2882 }
2883 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2884 }
2885
VisitNEONScalarByIndexedElement(Instruction * instr)2886 void DisassemblingDecoder::VisitNEONScalarByIndexedElement(Instruction* instr) {
2887 const char* mnemonic = "unimplemented";
2888 const char* form = "%sd, %sn, 'Ve.%s['IVByElemIndex]";
2889 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2890 bool long_instr = false;
2891
2892 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
2893 case NEON_SQDMULL_byelement_scalar:
2894 mnemonic = "sqdmull";
2895 long_instr = true;
2896 break;
2897 case NEON_SQDMLAL_byelement_scalar:
2898 mnemonic = "sqdmlal";
2899 long_instr = true;
2900 break;
2901 case NEON_SQDMLSL_byelement_scalar:
2902 mnemonic = "sqdmlsl";
2903 long_instr = true;
2904 break;
2905 case NEON_SQDMULH_byelement_scalar:
2906 mnemonic = "sqdmulh";
2907 break;
2908 case NEON_SQRDMULH_byelement_scalar:
2909 mnemonic = "sqrdmulh";
2910 break;
2911 default:
2912 nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
2913 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
2914 case NEON_FMUL_byelement_scalar:
2915 mnemonic = "fmul";
2916 break;
2917 case NEON_FMLA_byelement_scalar:
2918 mnemonic = "fmla";
2919 break;
2920 case NEON_FMLS_byelement_scalar:
2921 mnemonic = "fmls";
2922 break;
2923 case NEON_FMULX_byelement_scalar:
2924 mnemonic = "fmulx";
2925 break;
2926 default:
2927 form = "(NEONScalarByIndexedElement)";
2928 }
2929 }
2930
2931 if (long_instr) {
2932 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
2933 }
2934
2935 Format(instr, mnemonic,
2936 nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
2937 }
2938
VisitNEONScalarCopy(Instruction * instr)2939 void DisassemblingDecoder::VisitNEONScalarCopy(Instruction* instr) {
2940 const char* mnemonic = "unimplemented";
2941 const char* form = "(NEONScalarCopy)";
2942
2943 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
2944
2945 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
2946 mnemonic = "mov";
2947 form = "%sd, 'Vn.%s['IVInsIndex1]";
2948 }
2949
2950 Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat));
2951 }
2952
VisitNEONScalarPairwise(Instruction * instr)2953 void DisassemblingDecoder::VisitNEONScalarPairwise(Instruction* instr) {
2954 const char* mnemonic = "unimplemented";
2955 const char* form = "%sd, 'Vn.%s";
2956 NEONFormatMap map = {{22}, {NF_2S, NF_2D}};
2957 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap(), &map);
2958
2959 switch (instr->Mask(NEONScalarPairwiseMask)) {
2960 case NEON_ADDP_scalar:
2961 mnemonic = "addp";
2962 break;
2963 case NEON_FADDP_scalar:
2964 mnemonic = "faddp";
2965 break;
2966 case NEON_FMAXP_scalar:
2967 mnemonic = "fmaxp";
2968 break;
2969 case NEON_FMAXNMP_scalar:
2970 mnemonic = "fmaxnmp";
2971 break;
2972 case NEON_FMINP_scalar:
2973 mnemonic = "fminp";
2974 break;
2975 case NEON_FMINNMP_scalar:
2976 mnemonic = "fminnmp";
2977 break;
2978 default:
2979 form = "(NEONScalarPairwise)";
2980 }
2981 Format(instr, mnemonic,
2982 nfd.Substitute(form, NEONFormatDecoder::kPlaceholder,
2983 NEONFormatDecoder::kFormat));
2984 }
2985
VisitNEONScalarShiftImmediate(Instruction * instr)2986 void DisassemblingDecoder::VisitNEONScalarShiftImmediate(Instruction* instr) {
2987 const char* mnemonic = "unimplemented";
2988 const char* form = "%sd, %sn, 'Is1";
2989 const char* form_2 = "%sd, %sn, 'Is2";
2990
2991 static const NEONFormatMap map_shift = {
2992 {22, 21, 20, 19},
2993 {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S, NF_D, NF_D, NF_D,
2994 NF_D, NF_D, NF_D, NF_D, NF_D}};
2995 static const NEONFormatMap map_shift_narrow = {
2996 {21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}};
2997 NEONFormatDecoder nfd(instr, &map_shift);
2998
2999 if (instr->ImmNEONImmh()) { // immh has to be non-zero.
3000 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
3001 case NEON_FCVTZU_imm_scalar:
3002 mnemonic = "fcvtzu";
3003 break;
3004 case NEON_FCVTZS_imm_scalar:
3005 mnemonic = "fcvtzs";
3006 break;
3007 case NEON_SCVTF_imm_scalar:
3008 mnemonic = "scvtf";
3009 break;
3010 case NEON_UCVTF_imm_scalar:
3011 mnemonic = "ucvtf";
3012 break;
3013 case NEON_SRI_scalar:
3014 mnemonic = "sri";
3015 break;
3016 case NEON_SSHR_scalar:
3017 mnemonic = "sshr";
3018 break;
3019 case NEON_USHR_scalar:
3020 mnemonic = "ushr";
3021 break;
3022 case NEON_SRSHR_scalar:
3023 mnemonic = "srshr";
3024 break;
3025 case NEON_URSHR_scalar:
3026 mnemonic = "urshr";
3027 break;
3028 case NEON_SSRA_scalar:
3029 mnemonic = "ssra";
3030 break;
3031 case NEON_USRA_scalar:
3032 mnemonic = "usra";
3033 break;
3034 case NEON_SRSRA_scalar:
3035 mnemonic = "srsra";
3036 break;
3037 case NEON_URSRA_scalar:
3038 mnemonic = "ursra";
3039 break;
3040 case NEON_SHL_scalar:
3041 mnemonic = "shl";
3042 form = form_2;
3043 break;
3044 case NEON_SLI_scalar:
3045 mnemonic = "sli";
3046 form = form_2;
3047 break;
3048 case NEON_SQSHLU_scalar:
3049 mnemonic = "sqshlu";
3050 form = form_2;
3051 break;
3052 case NEON_SQSHL_imm_scalar:
3053 mnemonic = "sqshl";
3054 form = form_2;
3055 break;
3056 case NEON_UQSHL_imm_scalar:
3057 mnemonic = "uqshl";
3058 form = form_2;
3059 break;
3060 case NEON_UQSHRN_scalar:
3061 mnemonic = "uqshrn";
3062 nfd.SetFormatMap(1, &map_shift_narrow);
3063 break;
3064 case NEON_UQRSHRN_scalar:
3065 mnemonic = "uqrshrn";
3066 nfd.SetFormatMap(1, &map_shift_narrow);
3067 break;
3068 case NEON_SQSHRN_scalar:
3069 mnemonic = "sqshrn";
3070 nfd.SetFormatMap(1, &map_shift_narrow);
3071 break;
3072 case NEON_SQRSHRN_scalar:
3073 mnemonic = "sqrshrn";
3074 nfd.SetFormatMap(1, &map_shift_narrow);
3075 break;
3076 case NEON_SQSHRUN_scalar:
3077 mnemonic = "sqshrun";
3078 nfd.SetFormatMap(1, &map_shift_narrow);
3079 break;
3080 case NEON_SQRSHRUN_scalar:
3081 mnemonic = "sqrshrun";
3082 nfd.SetFormatMap(1, &map_shift_narrow);
3083 break;
3084 default:
3085 form = "(NEONScalarShiftImmediate)";
3086 }
3087 } else {
3088 form = "(NEONScalarShiftImmediate)";
3089 }
3090 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
3091 }
3092
VisitNEONShiftImmediate(Instruction * instr)3093 void DisassemblingDecoder::VisitNEONShiftImmediate(Instruction* instr) {
3094 const char* mnemonic = "unimplemented";
3095 const char* form = "'Vd.%s, 'Vn.%s, 'Is1";
3096 const char* form_shift_2 = "'Vd.%s, 'Vn.%s, 'Is2";
3097 const char* form_xtl = "'Vd.%s, 'Vn.%s";
3098
3099 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
3100 static const NEONFormatMap map_shift_ta = {
3101 {22, 21, 20, 19},
3102 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
3103
3104 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
3105 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
3106 static const NEONFormatMap map_shift_tb = {
3107 {22, 21, 20, 19, 30},
3108 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H, NF_8H,
3109 NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S,
3110 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
3111 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
3112
3113 NEONFormatDecoder nfd(instr, &map_shift_tb);
3114
3115 if (instr->ImmNEONImmh()) { // immh has to be non-zero.
3116 switch (instr->Mask(NEONShiftImmediateMask)) {
3117 case NEON_SQSHLU:
3118 mnemonic = "sqshlu";
3119 form = form_shift_2;
3120 break;
3121 case NEON_SQSHL_imm:
3122 mnemonic = "sqshl";
3123 form = form_shift_2;
3124 break;
3125 case NEON_UQSHL_imm:
3126 mnemonic = "uqshl";
3127 form = form_shift_2;
3128 break;
3129 case NEON_SHL:
3130 mnemonic = "shl";
3131 form = form_shift_2;
3132 break;
3133 case NEON_SLI:
3134 mnemonic = "sli";
3135 form = form_shift_2;
3136 break;
3137 case NEON_SCVTF_imm:
3138 mnemonic = "scvtf";
3139 break;
3140 case NEON_UCVTF_imm:
3141 mnemonic = "ucvtf";
3142 break;
3143 case NEON_FCVTZU_imm:
3144 mnemonic = "fcvtzu";
3145 break;
3146 case NEON_FCVTZS_imm:
3147 mnemonic = "fcvtzs";
3148 break;
3149 case NEON_SRI:
3150 mnemonic = "sri";
3151 break;
3152 case NEON_SSHR:
3153 mnemonic = "sshr";
3154 break;
3155 case NEON_USHR:
3156 mnemonic = "ushr";
3157 break;
3158 case NEON_SRSHR:
3159 mnemonic = "srshr";
3160 break;
3161 case NEON_URSHR:
3162 mnemonic = "urshr";
3163 break;
3164 case NEON_SSRA:
3165 mnemonic = "ssra";
3166 break;
3167 case NEON_USRA:
3168 mnemonic = "usra";
3169 break;
3170 case NEON_SRSRA:
3171 mnemonic = "srsra";
3172 break;
3173 case NEON_URSRA:
3174 mnemonic = "ursra";
3175 break;
3176 case NEON_SHRN:
3177 mnemonic = instr->Mask(NEON_Q) ? "shrn2" : "shrn";
3178 nfd.SetFormatMap(1, &map_shift_ta);
3179 break;
3180 case NEON_RSHRN:
3181 mnemonic = instr->Mask(NEON_Q) ? "rshrn2" : "rshrn";
3182 nfd.SetFormatMap(1, &map_shift_ta);
3183 break;
3184 case NEON_UQSHRN:
3185 mnemonic = instr->Mask(NEON_Q) ? "uqshrn2" : "uqshrn";
3186 nfd.SetFormatMap(1, &map_shift_ta);
3187 break;
3188 case NEON_UQRSHRN:
3189 mnemonic = instr->Mask(NEON_Q) ? "uqrshrn2" : "uqrshrn";
3190 nfd.SetFormatMap(1, &map_shift_ta);
3191 break;
3192 case NEON_SQSHRN:
3193 mnemonic = instr->Mask(NEON_Q) ? "sqshrn2" : "sqshrn";
3194 nfd.SetFormatMap(1, &map_shift_ta);
3195 break;
3196 case NEON_SQRSHRN:
3197 mnemonic = instr->Mask(NEON_Q) ? "sqrshrn2" : "sqrshrn";
3198 nfd.SetFormatMap(1, &map_shift_ta);
3199 break;
3200 case NEON_SQSHRUN:
3201 mnemonic = instr->Mask(NEON_Q) ? "sqshrun2" : "sqshrun";
3202 nfd.SetFormatMap(1, &map_shift_ta);
3203 break;
3204 case NEON_SQRSHRUN:
3205 mnemonic = instr->Mask(NEON_Q) ? "sqrshrun2" : "sqrshrun";
3206 nfd.SetFormatMap(1, &map_shift_ta);
3207 break;
3208 case NEON_SSHLL:
3209 nfd.SetFormatMap(0, &map_shift_ta);
3210 if (instr->ImmNEONImmb() == 0 &&
3211 CountSetBits(instr->ImmNEONImmh(), 32) == 1) { // sxtl variant.
3212 form = form_xtl;
3213 mnemonic = instr->Mask(NEON_Q) ? "sxtl2" : "sxtl";
3214 } else { // sshll variant.
3215 form = form_shift_2;
3216 mnemonic = instr->Mask(NEON_Q) ? "sshll2" : "sshll";
3217 }
3218 break;
3219 case NEON_USHLL:
3220 nfd.SetFormatMap(0, &map_shift_ta);
3221 if (instr->ImmNEONImmb() == 0 &&
3222 CountSetBits(instr->ImmNEONImmh(), 32) == 1) { // uxtl variant.
3223 form = form_xtl;
3224 mnemonic = instr->Mask(NEON_Q) ? "uxtl2" : "uxtl";
3225 } else { // ushll variant.
3226 form = form_shift_2;
3227 mnemonic = instr->Mask(NEON_Q) ? "ushll2" : "ushll";
3228 }
3229 break;
3230 default:
3231 form = "(NEONShiftImmediate)";
3232 }
3233 } else {
3234 form = "(NEONShiftImmediate)";
3235 }
3236 Format(instr, mnemonic, nfd.Substitute(form));
3237 }
3238
VisitNEONTable(Instruction * instr)3239 void DisassemblingDecoder::VisitNEONTable(Instruction* instr) {
3240 const char* mnemonic = "unimplemented";
3241 const char* form = "(NEONTable)";
3242 const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s";
3243 const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s";
3244 const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
3245 const char form_4v[] =
3246 "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
3247 static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
3248 NEONFormatDecoder nfd(instr, &map_b);
3249
3250 switch (instr->Mask(NEONTableMask)) {
3251 case NEON_TBL_1v:
3252 mnemonic = "tbl";
3253 form = form_1v;
3254 break;
3255 case NEON_TBL_2v:
3256 mnemonic = "tbl";
3257 form = form_2v;
3258 break;
3259 case NEON_TBL_3v:
3260 mnemonic = "tbl";
3261 form = form_3v;
3262 break;
3263 case NEON_TBL_4v:
3264 mnemonic = "tbl";
3265 form = form_4v;
3266 break;
3267 case NEON_TBX_1v:
3268 mnemonic = "tbx";
3269 form = form_1v;
3270 break;
3271 case NEON_TBX_2v:
3272 mnemonic = "tbx";
3273 form = form_2v;
3274 break;
3275 case NEON_TBX_3v:
3276 mnemonic = "tbx";
3277 form = form_3v;
3278 break;
3279 case NEON_TBX_4v:
3280 mnemonic = "tbx";
3281 form = form_4v;
3282 break;
3283 default:
3284 break;
3285 }
3286
3287 char re_form[sizeof(form_4v)];
3288 int reg_num = instr->Rn();
3289 snprintf(re_form, sizeof(re_form), form, (reg_num + 1) % kNumberOfVRegisters,
3290 (reg_num + 2) % kNumberOfVRegisters,
3291 (reg_num + 3) % kNumberOfVRegisters);
3292
3293 Format(instr, mnemonic, nfd.Substitute(re_form));
3294 }
3295
VisitUnimplemented(Instruction * instr)3296 void DisassemblingDecoder::VisitUnimplemented(Instruction* instr) {
3297 Format(instr, "unimplemented", "(Unimplemented)");
3298 }
3299
VisitUnallocated(Instruction * instr)3300 void DisassemblingDecoder::VisitUnallocated(Instruction* instr) {
3301 Format(instr, "unallocated", "(Unallocated)");
3302 }
3303
ProcessOutput(Instruction *)3304 void DisassemblingDecoder::ProcessOutput(Instruction* /*instr*/) {
3305 // The base disasm does nothing more than disassembling into a buffer.
3306 }
3307
AppendRegisterNameToOutput(const CPURegister & reg)3308 void DisassemblingDecoder::AppendRegisterNameToOutput(const CPURegister& reg) {
3309 DCHECK(reg.IsValid());
3310 char reg_char;
3311
3312 if (reg.IsRegister()) {
3313 reg_char = reg.Is64Bits() ? 'x' : 'w';
3314 } else {
3315 DCHECK(reg.IsVRegister());
3316 switch (reg.SizeInBits()) {
3317 case kBRegSizeInBits:
3318 reg_char = 'b';
3319 break;
3320 case kHRegSizeInBits:
3321 reg_char = 'h';
3322 break;
3323 case kSRegSizeInBits:
3324 reg_char = 's';
3325 break;
3326 case kDRegSizeInBits:
3327 reg_char = 'd';
3328 break;
3329 default:
3330 DCHECK(reg.Is128Bits());
3331 reg_char = 'q';
3332 }
3333 }
3334
3335 if (reg.IsVRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
3336 // Filter special registers
3337 if (reg.IsX() && (reg.code() == 27)) {
3338 AppendToOutput("cp");
3339 } else if (reg.IsX() && (reg.code() == 29)) {
3340 AppendToOutput("fp");
3341 } else if (reg.IsX() && (reg.code() == 30)) {
3342 AppendToOutput("lr");
3343 } else {
3344 // A core or scalar/vector register: [wx]0 - 30, [bhsdq]0 - 31.
3345 AppendToOutput("%c%d", reg_char, reg.code());
3346 }
3347 } else if (reg.Aliases(sp)) {
3348 // Disassemble w31/x31 as stack pointer wsp/sp.
3349 AppendToOutput("%s", reg.Is64Bits() ? "sp" : "wsp");
3350 } else {
3351 // Disassemble w31/x31 as zero register wzr/xzr.
3352 AppendToOutput("%czr", reg_char);
3353 }
3354 }
3355
Format(Instruction * instr,const char * mnemonic,const char * format)3356 void DisassemblingDecoder::Format(Instruction* instr, const char* mnemonic,
3357 const char* format) {
3358 // TODO(mcapewel) don't think I can use the instr address here - there needs
3359 // to be a base address too
3360 DCHECK_NOT_NULL(mnemonic);
3361 ResetOutput();
3362 Substitute(instr, mnemonic);
3363 if (format != nullptr) {
3364 buffer_[buffer_pos_++] = ' ';
3365 Substitute(instr, format);
3366 }
3367 buffer_[buffer_pos_] = 0;
3368 ProcessOutput(instr);
3369 }
3370
Substitute(Instruction * instr,const char * string)3371 void DisassemblingDecoder::Substitute(Instruction* instr, const char* string) {
3372 char chr = *string++;
3373 while (chr != '\0') {
3374 if (chr == '\'') {
3375 string += SubstituteField(instr, string);
3376 } else {
3377 buffer_[buffer_pos_++] = chr;
3378 }
3379 chr = *string++;
3380 }
3381 }
3382
SubstituteField(Instruction * instr,const char * format)3383 int DisassemblingDecoder::SubstituteField(Instruction* instr,
3384 const char* format) {
3385 switch (format[0]) {
3386 // NB. The remaining substitution prefix characters are: GJKUZ.
3387 case 'R': // Register. X or W, selected by sf bit.
3388 case 'F': // FP register. S or D, selected by type field.
3389 case 'V': // Vector register, V, vector format.
3390 case 'W':
3391 case 'X':
3392 case 'B':
3393 case 'H':
3394 case 'S':
3395 case 'D':
3396 case 'Q':
3397 return SubstituteRegisterField(instr, format);
3398 case 'I':
3399 return SubstituteImmediateField(instr, format);
3400 case 'L':
3401 return SubstituteLiteralField(instr, format);
3402 case 'N':
3403 return SubstituteShiftField(instr, format);
3404 case 'P':
3405 return SubstitutePrefetchField(instr, format);
3406 case 'C':
3407 return SubstituteConditionField(instr, format);
3408 case 'E':
3409 return SubstituteExtendField(instr, format);
3410 case 'A':
3411 return SubstitutePCRelAddressField(instr, format);
3412 case 'T':
3413 return SubstituteBranchTargetField(instr, format);
3414 case 'O':
3415 return SubstituteLSRegOffsetField(instr, format);
3416 case 'M':
3417 return SubstituteBarrierField(instr, format);
3418 default:
3419 UNREACHABLE();
3420 }
3421 }
3422
SubstituteRegisterField(Instruction * instr,const char * format)3423 int DisassemblingDecoder::SubstituteRegisterField(Instruction* instr,
3424 const char* format) {
3425 char reg_prefix = format[0];
3426 unsigned reg_num = 0;
3427 unsigned field_len = 2;
3428
3429 switch (format[1]) {
3430 case 'd':
3431 reg_num = instr->Rd();
3432 if (format[2] == 'q') {
3433 reg_prefix = instr->NEONQ() ? 'X' : 'W';
3434 field_len = 3;
3435 }
3436 break;
3437 case 'n':
3438 reg_num = instr->Rn();
3439 break;
3440 case 'm':
3441 reg_num = instr->Rm();
3442 switch (format[2]) {
3443 // Handle registers tagged with b (bytes), z (instruction), or
3444 // r (registers), used for address updates in
3445 // NEON load/store instructions.
3446 case 'r':
3447 case 'b':
3448 case 'z': {
3449 field_len = 3;
3450 char* eimm;
3451 int imm = static_cast<int>(strtol(&format[3], &eimm, 10));
3452 field_len += eimm - &format[3];
3453 if (reg_num == 31) {
3454 switch (format[2]) {
3455 case 'z':
3456 imm *= (1 << instr->NEONLSSize());
3457 break;
3458 case 'r':
3459 imm *= (instr->NEONQ() == 0) ? kDRegSize : kQRegSize;
3460 break;
3461 case 'b':
3462 break;
3463 }
3464 AppendToOutput("#%d", imm);
3465 return field_len;
3466 }
3467 break;
3468 }
3469 }
3470 break;
3471 case 'e':
3472 // This is register Rm, but using a 4-bit specifier. Used in NEON
3473 // by-element instructions.
3474 reg_num = (instr->Rm() & 0xF);
3475 break;
3476 case 'a':
3477 reg_num = instr->Ra();
3478 break;
3479 case 't':
3480 reg_num = instr->Rt();
3481 if (format[0] == 'V') {
3482 if ((format[2] >= '2') && (format[2] <= '4')) {
3483 // Handle consecutive vector register specifiers Vt2, Vt3 and Vt4.
3484 reg_num = (reg_num + format[2] - '1') % 32;
3485 field_len = 3;
3486 }
3487 } else {
3488 if (format[2] == '2') {
3489 // Handle register specifier Rt2.
3490 reg_num = instr->Rt2();
3491 field_len = 3;
3492 }
3493 }
3494 break;
3495 case 's':
3496 reg_num = instr->Rs();
3497 break;
3498 default:
3499 UNREACHABLE();
3500 }
3501
3502 // Increase field length for registers tagged as stack.
3503 if (format[2] == 's') {
3504 field_len = 3;
3505 }
3506
3507 CPURegister::RegisterType reg_type;
3508 unsigned reg_size;
3509
3510 if (reg_prefix == 'R') {
3511 reg_prefix = instr->SixtyFourBits() ? 'X' : 'W';
3512 } else if (reg_prefix == 'F') {
3513 reg_prefix = ((instr->FPType() & 1) == 0) ? 'S' : 'D';
3514 }
3515
3516 switch (reg_prefix) {
3517 case 'W':
3518 reg_type = CPURegister::kRegister;
3519 reg_size = kWRegSizeInBits;
3520 break;
3521 case 'X':
3522 reg_type = CPURegister::kRegister;
3523 reg_size = kXRegSizeInBits;
3524 break;
3525 case 'B':
3526 reg_type = CPURegister::kVRegister;
3527 reg_size = kBRegSizeInBits;
3528 break;
3529 case 'H':
3530 reg_type = CPURegister::kVRegister;
3531 reg_size = kHRegSizeInBits;
3532 break;
3533 case 'S':
3534 reg_type = CPURegister::kVRegister;
3535 reg_size = kSRegSizeInBits;
3536 break;
3537 case 'D':
3538 reg_type = CPURegister::kVRegister;
3539 reg_size = kDRegSizeInBits;
3540 break;
3541 case 'Q':
3542 reg_type = CPURegister::kVRegister;
3543 reg_size = kQRegSizeInBits;
3544 break;
3545 case 'V':
3546 AppendToOutput("v%d", reg_num);
3547 return field_len;
3548 default:
3549 UNREACHABLE();
3550 }
3551
3552 if ((reg_type == CPURegister::kRegister) && (reg_num == kZeroRegCode) &&
3553 (format[2] == 's')) {
3554 reg_num = kSPRegInternalCode;
3555 }
3556
3557 AppendRegisterNameToOutput(CPURegister::Create(reg_num, reg_size, reg_type));
3558
3559 return field_len;
3560 }
3561
SubstituteImmediateField(Instruction * instr,const char * format)3562 int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr,
3563 const char* format) {
3564 DCHECK_EQ(format[0], 'I');
3565
3566 switch (format[1]) {
3567 case 'M': { // IMoveImm or IMoveLSL.
3568 if (format[5] == 'I' || format[5] == 'N') {
3569 uint64_t imm = static_cast<uint64_t>(instr->ImmMoveWide())
3570 << (16 * instr->ShiftMoveWide());
3571 if (format[5] == 'N') imm = ~imm;
3572 if (!instr->SixtyFourBits()) imm &= UINT64_C(0xFFFFFFFF);
3573 AppendToOutput("#0x%" PRIx64, imm);
3574 } else {
3575 DCHECK_EQ(format[5], 'L');
3576 AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
3577 if (instr->ShiftMoveWide() > 0) {
3578 AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
3579 }
3580 }
3581 return 8;
3582 }
3583 case 'L': {
3584 switch (format[2]) {
3585 case 'L': { // ILLiteral - Immediate Load Literal.
3586 AppendToOutput("pc%+" PRId32, instr->ImmLLiteral()
3587 << kLoadLiteralScaleLog2);
3588 return 9;
3589 }
3590 case 'S': { // ILS - Immediate Load/Store.
3591 if (instr->ImmLS() != 0) {
3592 AppendToOutput(", #%" PRId32, instr->ImmLS());
3593 }
3594 return 3;
3595 }
3596 case 'P': { // ILPx - Immediate Load/Store Pair, x = access size.
3597 if (instr->ImmLSPair() != 0) {
3598 // format[3] is the scale value. Convert to a number.
3599 int scale = 1 << (format[3] - '0');
3600 AppendToOutput(", #%" PRId32, instr->ImmLSPair() * scale);
3601 }
3602 return 4;
3603 }
3604 case 'U': { // ILU - Immediate Load/Store Unsigned.
3605 if (instr->ImmLSUnsigned() != 0) {
3606 int shift = instr->SizeLS();
3607 AppendToOutput(", #%" PRId32, instr->ImmLSUnsigned() << shift);
3608 }
3609 return 3;
3610 }
3611 }
3612 }
3613 case 'C': { // ICondB - Immediate Conditional Branch.
3614 int64_t offset = instr->ImmCondBranch() << 2;
3615 char sign = (offset >= 0) ? '+' : '-';
3616 AppendToOutput("#%c0x%" PRIx64, sign, offset);
3617 return 6;
3618 }
3619 case 'A': { // IAddSub.
3620 DCHECK_LE(instr->ShiftAddSub(), 1);
3621 int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
3622 AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
3623 return 7;
3624 }
3625 case 'F': { // IFPSingle, IFPDouble or IFPFBits.
3626 if (format[3] == 'F') { // IFPFBits.
3627 AppendToOutput("#%d", 64 - instr->FPScale());
3628 return 8;
3629 } else {
3630 AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmFP(),
3631 format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64());
3632 return 9;
3633 }
3634 }
3635 case 'T': { // ITri - Immediate Triangular Encoded.
3636 AppendToOutput("#0x%" PRIx64, instr->ImmLogical());
3637 return 4;
3638 }
3639 case 'N': { // INzcv.
3640 int nzcv = (instr->Nzcv() << Flags_offset);
3641 AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N',
3642 ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
3643 ((nzcv & CFlag) == 0) ? 'c' : 'C',
3644 ((nzcv & VFlag) == 0) ? 'v' : 'V');
3645 return 5;
3646 }
3647 case 'P': { // IP - Conditional compare.
3648 AppendToOutput("#%d", instr->ImmCondCmp());
3649 return 2;
3650 }
3651 case 'B': { // Bitfields.
3652 return SubstituteBitfieldImmediateField(instr, format);
3653 }
3654 case 'E': { // IExtract.
3655 AppendToOutput("#%d", instr->ImmS());
3656 return 8;
3657 }
3658 case 'S': { // IS - Test and branch bit.
3659 AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
3660 instr->ImmTestBranchBit40());
3661 return 2;
3662 }
3663 case 's': { // Is - Shift (immediate).
3664 switch (format[2]) {
3665 case '1': { // Is1 - SSHR.
3666 int shift = 16 << HighestSetBitPosition(instr->ImmNEONImmh());
3667 shift -= instr->ImmNEONImmhImmb();
3668 AppendToOutput("#%d", shift);
3669 return 3;
3670 }
3671 case '2': { // Is2 - SLI.
3672 int shift = instr->ImmNEONImmhImmb();
3673 shift -= 8 << HighestSetBitPosition(instr->ImmNEONImmh());
3674 AppendToOutput("#%d", shift);
3675 return 3;
3676 }
3677 default: {
3678 UNIMPLEMENTED();
3679 return 0;
3680 }
3681 }
3682 }
3683 case 'D': { // IDebug - HLT and BRK instructions.
3684 AppendToOutput("#0x%x", instr->ImmException());
3685 return 6;
3686 }
3687 case 'V': { // Immediate Vector.
3688 switch (format[2]) {
3689 case 'E': { // IVExtract.
3690 AppendToOutput("#%" PRId64, instr->ImmNEONExt());
3691 return 9;
3692 }
3693 case 'B': { // IVByElemIndex.
3694 int vm_index = (instr->NEONH() << 1) | instr->NEONL();
3695 if (instr->NEONSize() == 1) {
3696 vm_index = (vm_index << 1) | instr->NEONM();
3697 }
3698 AppendToOutput("%d", vm_index);
3699 return static_cast<int>(strlen("IVByElemIndex"));
3700 }
3701 case 'I': { // INS element.
3702 if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) {
3703 unsigned rd_index, rn_index;
3704 unsigned imm5 = instr->ImmNEON5();
3705 unsigned imm4 = instr->ImmNEON4();
3706 int tz = CountTrailingZeros(imm5, 32);
3707 if (tz <= 3) { // Defined for 0 <= tz <= 3 only.
3708 rd_index = imm5 >> (tz + 1);
3709 rn_index = imm4 >> tz;
3710 if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) {
3711 AppendToOutput("%d", rd_index);
3712 return static_cast<int>(strlen("IVInsIndex1"));
3713 } else if (strncmp(format, "IVInsIndex2",
3714 strlen("IVInsIndex2")) == 0) {
3715 AppendToOutput("%d", rn_index);
3716 return static_cast<int>(strlen("IVInsIndex2"));
3717 }
3718 }
3719 return 0;
3720 }
3721 UNIMPLEMENTED();
3722 return 0;
3723 }
3724 case 'L': { // IVLSLane[0123] - suffix indicates access size shift.
3725 AppendToOutput("%d", instr->NEONLSIndex(format[8] - '0'));
3726 return 9;
3727 }
3728 case 'M': { // Modified Immediate cases.
3729 if (strncmp(format, "IVMIImmFPSingle", strlen("IVMIImmFPSingle")) ==
3730 0) {
3731 AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmNEONabcdefgh(),
3732 instr->ImmNEONFP32());
3733 return static_cast<int>(strlen("IVMIImmFPSingle"));
3734 } else if (strncmp(format, "IVMIImmFPDouble",
3735 strlen("IVMIImmFPDouble")) == 0) {
3736 AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmNEONabcdefgh(),
3737 instr->ImmNEONFP64());
3738 return static_cast<int>(strlen("IVMIImmFPDouble"));
3739 } else if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) {
3740 uint64_t imm8 = instr->ImmNEONabcdefgh();
3741 AppendToOutput("#0x%" PRIx64, imm8);
3742 return static_cast<int>(strlen("IVMIImm8"));
3743 } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) {
3744 uint64_t imm8 = instr->ImmNEONabcdefgh();
3745 uint64_t imm = 0;
3746 for (int i = 0; i < 8; ++i) {
3747 if (imm8 & (1 << i)) {
3748 imm |= (UINT64_C(0xFF) << (8 * i));
3749 }
3750 }
3751 AppendToOutput("#0x%" PRIx64, imm);
3752 return static_cast<int>(strlen("IVMIImm"));
3753 } else if (strncmp(format, "IVMIShiftAmt1",
3754 strlen("IVMIShiftAmt1")) == 0) {
3755 int cmode = instr->NEONCmode();
3756 int shift_amount = 8 * ((cmode >> 1) & 3);
3757 AppendToOutput("#%d", shift_amount);
3758 return static_cast<int>(strlen("IVMIShiftAmt1"));
3759 } else if (strncmp(format, "IVMIShiftAmt2",
3760 strlen("IVMIShiftAmt2")) == 0) {
3761 int cmode = instr->NEONCmode();
3762 int shift_amount = 8 << (cmode & 1);
3763 AppendToOutput("#%d", shift_amount);
3764 return static_cast<int>(strlen("IVMIShiftAmt2"));
3765 } else {
3766 UNIMPLEMENTED();
3767 return 0;
3768 }
3769 }
3770 default: {
3771 UNIMPLEMENTED();
3772 return 0;
3773 }
3774 }
3775 }
3776 default: {
3777 printf("%s", format);
3778 UNREACHABLE();
3779 }
3780 }
3781 }
3782
3783
SubstituteBitfieldImmediateField(Instruction * instr,const char * format)3784 int DisassemblingDecoder::SubstituteBitfieldImmediateField(Instruction* instr,
3785 const char* format) {
3786 DCHECK((format[0] == 'I') && (format[1] == 'B'));
3787 unsigned r = instr->ImmR();
3788 unsigned s = instr->ImmS();
3789
3790 switch (format[2]) {
3791 case 'r': { // IBr.
3792 AppendToOutput("#%d", r);
3793 return 3;
3794 }
3795 case 's': { // IBs+1 or IBs-r+1.
3796 if (format[3] == '+') {
3797 AppendToOutput("#%d", s + 1);
3798 return 5;
3799 } else {
3800 DCHECK_EQ(format[3], '-');
3801 AppendToOutput("#%d", s - r + 1);
3802 return 7;
3803 }
3804 }
3805 case 'Z': { // IBZ-r.
3806 DCHECK((format[3] == '-') && (format[4] == 'r'));
3807 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
3808 : kWRegSizeInBits;
3809 AppendToOutput("#%d", reg_size - r);
3810 return 5;
3811 }
3812 default: {
3813 UNREACHABLE();
3814 }
3815 }
3816 }
3817
3818
SubstituteLiteralField(Instruction * instr,const char * format)3819 int DisassemblingDecoder::SubstituteLiteralField(Instruction* instr,
3820 const char* format) {
3821 DCHECK_EQ(strncmp(format, "LValue", 6), 0);
3822 USE(format);
3823
3824 switch (instr->Mask(LoadLiteralMask)) {
3825 case LDR_w_lit:
3826 case LDR_x_lit:
3827 case LDR_s_lit:
3828 case LDR_d_lit:
3829 AppendToOutput("(addr 0x%016" PRIxPTR ")", instr->LiteralAddress());
3830 break;
3831 default: UNREACHABLE();
3832 }
3833
3834 return 6;
3835 }
3836
3837
SubstituteShiftField(Instruction * instr,const char * format)3838 int DisassemblingDecoder::SubstituteShiftField(Instruction* instr,
3839 const char* format) {
3840 DCHECK_EQ(format[0], 'N');
3841 DCHECK_LE(instr->ShiftDP(), 0x3);
3842
3843 switch (format[1]) {
3844 case 'D': { // NDP.
3845 DCHECK(instr->ShiftDP() != ROR);
3846 V8_FALLTHROUGH;
3847 }
3848 case 'L': { // NLo.
3849 if (instr->ImmDPShift() != 0) {
3850 const char* shift_type[] = {"lsl", "lsr", "asr", "ror"};
3851 AppendToOutput(", %s #%" PRId32, shift_type[instr->ShiftDP()],
3852 instr->ImmDPShift());
3853 }
3854 return 3;
3855 }
3856 default:
3857 UNREACHABLE();
3858 }
3859 }
3860
3861
SubstituteConditionField(Instruction * instr,const char * format)3862 int DisassemblingDecoder::SubstituteConditionField(Instruction* instr,
3863 const char* format) {
3864 DCHECK_EQ(format[0], 'C');
3865 const char* condition_code[] = { "eq", "ne", "hs", "lo",
3866 "mi", "pl", "vs", "vc",
3867 "hi", "ls", "ge", "lt",
3868 "gt", "le", "al", "nv" };
3869 int cond;
3870 switch (format[1]) {
3871 case 'B': cond = instr->ConditionBranch(); break;
3872 case 'I': {
3873 cond = NegateCondition(static_cast<Condition>(instr->Condition()));
3874 break;
3875 }
3876 default: cond = instr->Condition();
3877 }
3878 AppendToOutput("%s", condition_code[cond]);
3879 return 4;
3880 }
3881
3882
SubstitutePCRelAddressField(Instruction * instr,const char * format)3883 int DisassemblingDecoder::SubstitutePCRelAddressField(Instruction* instr,
3884 const char* format) {
3885 USE(format);
3886 DCHECK_EQ(strncmp(format, "AddrPCRel", 9), 0);
3887
3888 int offset = instr->ImmPCRel();
3889
3890 // Only ADR (AddrPCRelByte) is supported.
3891 DCHECK_EQ(strcmp(format, "AddrPCRelByte"), 0);
3892
3893 char sign = '+';
3894 if (offset < 0) {
3895 offset = -offset;
3896 sign = '-';
3897 }
3898 AppendToOutput("#%c0x%x (addr %p)", sign, offset,
3899 instr->InstructionAtOffset(offset, Instruction::NO_CHECK));
3900 return 13;
3901 }
3902
3903
SubstituteBranchTargetField(Instruction * instr,const char * format)3904 int DisassemblingDecoder::SubstituteBranchTargetField(Instruction* instr,
3905 const char* format) {
3906 DCHECK_EQ(strncmp(format, "TImm", 4), 0);
3907
3908 int64_t offset = 0;
3909 switch (format[5]) {
3910 // TImmUncn - unconditional branch immediate.
3911 case 'n': offset = instr->ImmUncondBranch(); break;
3912 // TImmCond - conditional branch immediate.
3913 case 'o': offset = instr->ImmCondBranch(); break;
3914 // TImmCmpa - compare and branch immediate.
3915 case 'm': offset = instr->ImmCmpBranch(); break;
3916 // TImmTest - test and branch immediate.
3917 case 'e': offset = instr->ImmTestBranch(); break;
3918 default: UNREACHABLE();
3919 }
3920 offset <<= kInstrSizeLog2;
3921 char sign = '+';
3922 if (offset < 0) {
3923 sign = '-';
3924 }
3925 AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset),
3926 instr->InstructionAtOffset(offset), Instruction::NO_CHECK);
3927 return 8;
3928 }
3929
3930
SubstituteExtendField(Instruction * instr,const char * format)3931 int DisassemblingDecoder::SubstituteExtendField(Instruction* instr,
3932 const char* format) {
3933 DCHECK_EQ(strncmp(format, "Ext", 3), 0);
3934 DCHECK_LE(instr->ExtendMode(), 7);
3935 USE(format);
3936
3937 const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
3938 "sxtb", "sxth", "sxtw", "sxtx" };
3939
3940 // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
3941 // registers becomes lsl.
3942 if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
3943 (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
3944 (instr->ExtendMode() == UXTX))) {
3945 if (instr->ImmExtendShift() > 0) {
3946 AppendToOutput(", lsl #%d", instr->ImmExtendShift());
3947 }
3948 } else {
3949 AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
3950 if (instr->ImmExtendShift() > 0) {
3951 AppendToOutput(" #%d", instr->ImmExtendShift());
3952 }
3953 }
3954 return 3;
3955 }
3956
3957
SubstituteLSRegOffsetField(Instruction * instr,const char * format)3958 int DisassemblingDecoder::SubstituteLSRegOffsetField(Instruction* instr,
3959 const char* format) {
3960 DCHECK_EQ(strncmp(format, "Offsetreg", 9), 0);
3961 const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
3962 "undefined", "undefined", "sxtw", "sxtx" };
3963 USE(format);
3964
3965 unsigned shift = instr->ImmShiftLS();
3966 Extend ext = static_cast<Extend>(instr->ExtendMode());
3967 char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
3968
3969 unsigned rm = instr->Rm();
3970 if (rm == kZeroRegCode) {
3971 AppendToOutput("%czr", reg_type);
3972 } else {
3973 AppendToOutput("%c%d", reg_type, rm);
3974 }
3975
3976 // Extend mode UXTX is an alias for shift mode LSL here.
3977 if (!((ext == UXTX) && (shift == 0))) {
3978 AppendToOutput(", %s", extend_mode[ext]);
3979 if (shift != 0) {
3980 AppendToOutput(" #%d", instr->SizeLS());
3981 }
3982 }
3983 return 9;
3984 }
3985
3986
SubstitutePrefetchField(Instruction * instr,const char * format)3987 int DisassemblingDecoder::SubstitutePrefetchField(Instruction* instr,
3988 const char* format) {
3989 DCHECK_EQ(format[0], 'P');
3990 USE(format);
3991
3992 int prefetch_mode = instr->PrefetchMode();
3993
3994 const char* ls = (prefetch_mode & 0x10) ? "st" : "ld";
3995 int level = (prefetch_mode >> 1) + 1;
3996 const char* ks = (prefetch_mode & 1) ? "strm" : "keep";
3997
3998 AppendToOutput("p%sl%d%s", ls, level, ks);
3999 return 6;
4000 }
4001
SubstituteBarrierField(Instruction * instr,const char * format)4002 int DisassemblingDecoder::SubstituteBarrierField(Instruction* instr,
4003 const char* format) {
4004 DCHECK_EQ(format[0], 'M');
4005 USE(format);
4006
4007 static const char* const options[4][4] = {
4008 { "sy (0b0000)", "oshld", "oshst", "osh" },
4009 { "sy (0b0100)", "nshld", "nshst", "nsh" },
4010 { "sy (0b1000)", "ishld", "ishst", "ish" },
4011 { "sy (0b1100)", "ld", "st", "sy" }
4012 };
4013 int domain = instr->ImmBarrierDomain();
4014 int type = instr->ImmBarrierType();
4015
4016 AppendToOutput("%s", options[domain][type]);
4017 return 1;
4018 }
4019
4020
ResetOutput()4021 void DisassemblingDecoder::ResetOutput() {
4022 buffer_pos_ = 0;
4023 buffer_[buffer_pos_] = 0;
4024 }
4025
4026
AppendToOutput(const char * format,...)4027 void DisassemblingDecoder::AppendToOutput(const char* format, ...) {
4028 va_list args;
4029 va_start(args, format);
4030 buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args);
4031 va_end(args);
4032 }
4033
4034
ProcessOutput(Instruction * instr)4035 void PrintDisassembler::ProcessOutput(Instruction* instr) {
4036 fprintf(stream_, "0x%016" PRIx64 " %08" PRIx32 "\t\t%s\n",
4037 reinterpret_cast<uint64_t>(instr), instr->InstructionBits(),
4038 GetOutput());
4039 }
4040
4041 } // namespace internal
4042 } // namespace v8
4043
4044
4045 namespace disasm {
4046
4047
NameOfAddress(byte * addr) const4048 const char* NameConverter::NameOfAddress(byte* addr) const {
4049 v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void *>(addr));
4050 return tmp_buffer_.start();
4051 }
4052
4053
NameOfConstant(byte * addr) const4054 const char* NameConverter::NameOfConstant(byte* addr) const {
4055 return NameOfAddress(addr);
4056 }
4057
4058
NameOfCPURegister(int reg) const4059 const char* NameConverter::NameOfCPURegister(int reg) const {
4060 unsigned ureg = reg; // Avoid warnings about signed/unsigned comparisons.
4061 if (ureg >= v8::internal::kNumberOfRegisters) {
4062 return "noreg";
4063 }
4064 if (ureg == v8::internal::kZeroRegCode) {
4065 return "xzr";
4066 }
4067 v8::internal::SNPrintF(tmp_buffer_, "x%u", ureg);
4068 return tmp_buffer_.start();
4069 }
4070
4071
NameOfByteCPURegister(int reg) const4072 const char* NameConverter::NameOfByteCPURegister(int reg) const {
4073 UNREACHABLE(); // ARM64 does not have the concept of a byte register
4074 return "nobytereg";
4075 }
4076
4077
NameOfXMMRegister(int reg) const4078 const char* NameConverter::NameOfXMMRegister(int reg) const {
4079 UNREACHABLE(); // ARM64 does not have any XMM registers
4080 return "noxmmreg";
4081 }
4082
4083
NameInCode(byte * addr) const4084 const char* NameConverter::NameInCode(byte* addr) const {
4085 // The default name converter is called for unknown code, so we will not try
4086 // to access any memory.
4087 return "";
4088 }
4089
4090
4091 //------------------------------------------------------------------------------
4092
4093 class BufferDisassembler : public v8::internal::DisassemblingDecoder {
4094 public:
BufferDisassembler(v8::internal::Vector<char> out_buffer)4095 explicit BufferDisassembler(v8::internal::Vector<char> out_buffer)
4096 : out_buffer_(out_buffer) { }
4097
~BufferDisassembler()4098 ~BufferDisassembler() { }
4099
ProcessOutput(v8::internal::Instruction * instr)4100 virtual void ProcessOutput(v8::internal::Instruction* instr) {
4101 v8::internal::SNPrintF(out_buffer_, "%08" PRIx32 " %s",
4102 instr->InstructionBits(), GetOutput());
4103 }
4104
4105 private:
4106 v8::internal::Vector<char> out_buffer_;
4107 };
4108
InstructionDecode(v8::internal::Vector<char> buffer,byte * instr)4109 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
4110 byte* instr) {
4111 USE(converter_); // avoid unused field warning
4112 v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder;
4113 BufferDisassembler disasm(buffer);
4114 decoder.AppendVisitor(&disasm);
4115
4116 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(instr));
4117 return v8::internal::kInstrSize;
4118 }
4119
4120
ConstantPoolSizeAt(byte * instr)4121 int Disassembler::ConstantPoolSizeAt(byte* instr) {
4122 return v8::internal::Assembler::ConstantPoolSizeAt(
4123 reinterpret_cast<v8::internal::Instruction*>(instr));
4124 }
4125
Disassemble(FILE * file,byte * start,byte * end,UnimplementedOpcodeAction)4126 void Disassembler::Disassemble(FILE* file, byte* start, byte* end,
4127 UnimplementedOpcodeAction) {
4128 v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder;
4129 v8::internal::PrintDisassembler disasm(file);
4130 decoder.AppendVisitor(&disasm);
4131
4132 for (byte* pc = start; pc < end; pc += v8::internal::kInstrSize) {
4133 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc));
4134 }
4135 }
4136
4137 } // namespace disasm
4138
4139 #endif // V8_TARGET_ARCH_ARM64
4140