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