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