10 #if V8_TARGET_ARCH_ARM64 12 #include "src/arm64/decoder-arm64-inl.h" 13 #include "src/arm64/disasm-arm64.h" 14 #include "src/arm64/utils-arm64.h" 15 #include "src/base/platform/platform.h" 16 #include "src/disasm.h" 17 #include "src/macro-assembler.h" 23 DisassemblingDecoder::DisassemblingDecoder() {
25 buffer_ =
reinterpret_cast<char*
>(malloc(buffer_size_));
31 DisassemblingDecoder::DisassemblingDecoder(
char* text_buffer,
int buffer_size) {
32 buffer_size_ = buffer_size;
33 buffer_ = text_buffer;
39 DisassemblingDecoder::~DisassemblingDecoder() {
46 char* DisassemblingDecoder::GetOutput() {
return buffer_; }
49 void DisassemblingDecoder::VisitAddSubImmediate(Instruction* instr) {
50 bool rd_is_zr = RdIsZROrSP(instr);
51 bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
52 (instr->ImmAddSub() == 0) ?
true :
false;
53 const char *mnemonic =
"";
54 const char *form =
"'Rds, 'Rns, 'IAddSub";
55 const char *form_cmp =
"'Rns, 'IAddSub";
56 const char *form_mov =
"'Rds, 'Rns";
58 switch (instr->Mask(AddSubImmediateMask)) {
78 case SUB_x_imm: mnemonic =
"sub";
break;
88 default: UNREACHABLE();
90 Format(instr, mnemonic, form);
94 void DisassemblingDecoder::VisitAddSubShifted(Instruction* instr) {
95 bool rd_is_zr = RdIsZROrSP(instr);
96 bool rn_is_zr = RnIsZROrSP(instr);
97 const char *mnemonic =
"";
98 const char* form =
"'Rd, 'Rn, 'Rm'NDP";
99 const char* form_cmp =
"'Rn, 'Rm'NDP";
100 const char* form_neg =
"'Rd, 'Rm'NDP";
102 switch (instr->Mask(AddSubShiftedMask)) {
104 case ADD_x_shift: mnemonic =
"add";
break;
129 }
else if (rn_is_zr) {
135 default: UNREACHABLE();
137 Format(instr, mnemonic, form);
141 void DisassemblingDecoder::VisitAddSubExtended(Instruction* instr) {
142 bool rd_is_zr = RdIsZROrSP(instr);
143 const char *mnemonic =
"";
144 Extend mode =
static_cast<Extend
>(instr->ExtendMode());
145 const char *form = ((mode == UXTX) || (mode == SXTX)) ?
146 "'Rds, 'Rns, 'Xm'Ext" :
"'Rds, 'Rns, 'Wm'Ext";
147 const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ?
148 "'Rns, 'Xm'Ext" :
"'Rns, 'Wm'Ext";
150 switch (instr->Mask(AddSubExtendedMask)) {
152 case ADD_x_ext: mnemonic =
"add";
break;
163 case SUB_x_ext: mnemonic =
"sub";
break;
173 default: UNREACHABLE();
175 Format(instr, mnemonic, form);
179 void DisassemblingDecoder::VisitAddSubWithCarry(Instruction* instr) {
180 bool rn_is_zr = RnIsZROrSP(instr);
181 const char *mnemonic =
"";
182 const char *form =
"'Rd, 'Rn, 'Rm";
183 const char *form_neg =
"'Rd, 'Rm";
185 switch (instr->Mask(AddSubWithCarryMask)) {
187 case ADC_x: mnemonic =
"adc";
break;
189 case ADCS_x: mnemonic =
"adcs";
break;
208 default: UNREACHABLE();
210 Format(instr, mnemonic, form);
214 void DisassemblingDecoder::VisitLogicalImmediate(Instruction* instr) {
215 bool rd_is_zr = RdIsZROrSP(instr);
216 bool rn_is_zr = RnIsZROrSP(instr);
217 const char *mnemonic =
"";
218 const char *form =
"'Rds, 'Rn, 'ITri";
220 if (instr->ImmLogical() == 0) {
222 Format(instr,
"unallocated",
"(LogicalImmediate)");
226 switch (instr->Mask(LogicalImmediateMask)) {
228 case AND_x_imm: mnemonic =
"and";
break;
232 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
234 if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) {
236 form =
"'Rds, 'ITri";
241 case EOR_x_imm: mnemonic =
"eor";
break;
251 default: UNREACHABLE();
253 Format(instr, mnemonic, form);
257 bool DisassemblingDecoder::IsMovzMovnImm(
unsigned reg_size, uint64_t value) {
258 DCHECK((reg_size == kXRegSizeInBits) ||
259 ((reg_size == kWRegSizeInBits) && (value <= 0xFFFFFFFF)));
262 if (((value & 0xFFFFFFFFFFFF0000UL) == 0UL) ||
263 ((value & 0xFFFFFFFF0000FFFFUL) == 0UL) ||
264 ((value & 0xFFFF0000FFFFFFFFUL) == 0UL) ||
265 ((value & 0x0000FFFFFFFFFFFFUL) == 0UL)) {
270 if ((reg_size == kXRegSizeInBits) &&
271 (((value & 0xFFFFFFFFFFFF0000UL) == 0xFFFFFFFFFFFF0000UL) ||
272 ((value & 0xFFFFFFFF0000FFFFUL) == 0xFFFFFFFF0000FFFFUL) ||
273 ((value & 0xFFFF0000FFFFFFFFUL) == 0xFFFF0000FFFFFFFFUL) ||
274 ((value & 0x0000FFFFFFFFFFFFUL) == 0x0000FFFFFFFFFFFFUL))) {
277 if ((reg_size == kWRegSizeInBits) && (((value & 0xFFFF0000) == 0xFFFF0000) ||
278 ((value & 0x0000FFFF) == 0x0000FFFF))) {
285 void DisassemblingDecoder::VisitLogicalShifted(Instruction* instr) {
286 bool rd_is_zr = RdIsZROrSP(instr);
287 bool rn_is_zr = RnIsZROrSP(instr);
288 const char *mnemonic =
"";
289 const char* form =
"'Rd, 'Rn, 'Rm'NLo";
291 switch (instr->Mask(LogicalShiftedMask)) {
293 case AND_x: mnemonic =
"and";
break;
295 case BIC_x: mnemonic =
"bic";
break;
297 case EOR_x: mnemonic =
"eor";
break;
299 case EON_x: mnemonic =
"eon";
break;
301 case BICS_x: mnemonic =
"bics";
break;
307 form =
"'Rn, 'Rm'NLo";
314 if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) {
325 form =
"'Rd, 'Rm'NLo";
329 default: UNREACHABLE();
332 Format(instr, mnemonic, form);
336 void DisassemblingDecoder::VisitConditionalCompareRegister(Instruction* instr) {
337 const char *mnemonic =
"";
338 const char *form =
"'Rn, 'Rm, 'INzcv, 'Cond";
340 switch (instr->Mask(ConditionalCompareRegisterMask)) {
342 case CCMN_x: mnemonic =
"ccmn";
break;
344 case CCMP_x: mnemonic =
"ccmp";
break;
345 default: UNREACHABLE();
347 Format(instr, mnemonic, form);
351 void DisassemblingDecoder::VisitConditionalCompareImmediate(
352 Instruction* instr) {
353 const char *mnemonic =
"";
354 const char *form =
"'Rn, 'IP, 'INzcv, 'Cond";
356 switch (instr->Mask(ConditionalCompareImmediateMask)) {
358 case CCMN_x_imm: mnemonic =
"ccmn";
break;
360 case CCMP_x_imm: mnemonic =
"ccmp";
break;
361 default: UNREACHABLE();
363 Format(instr, mnemonic, form);
367 void DisassemblingDecoder::VisitConditionalSelect(Instruction* instr) {
368 bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
369 bool rn_is_rm = (instr->Rn() == instr->Rm());
370 const char *mnemonic =
"";
371 const char *form =
"'Rd, 'Rn, 'Rm, 'Cond";
372 const char *form_test =
"'Rd, 'CInv";
373 const char *form_update =
"'Rd, 'Rn, 'CInv";
375 Condition cond =
static_cast<Condition
>(instr->Condition());
376 bool invertible_cond = (cond != al) && (cond != nv);
378 switch (instr->Mask(ConditionalSelectMask)) {
380 case CSEL_x: mnemonic =
"csel";
break;
384 if (rnm_is_zr && invertible_cond) {
387 }
else if (rn_is_rm && invertible_cond) {
396 if (rnm_is_zr && invertible_cond) {
399 }
else if (rn_is_rm && invertible_cond) {
408 if (rn_is_rm && invertible_cond) {
414 default: UNREACHABLE();
416 Format(instr, mnemonic, form);
420 void DisassemblingDecoder::VisitBitfield(Instruction* instr) {
421 unsigned s = instr->ImmS();
422 unsigned r = instr->ImmR();
423 unsigned rd_size_minus_1 =
424 ((instr->SixtyFourBits() == 1) ? kXRegSizeInBits : kWRegSizeInBits) - 1;
425 const char *mnemonic =
"";
426 const char *form =
"";
427 const char *form_shift_right =
"'Rd, 'Rn, 'IBr";
428 const char *form_extend =
"'Rd, 'Wn";
429 const char *form_bfiz =
"'Rd, 'Rn, 'IBZ-r, 'IBs+1";
430 const char *form_bfx =
"'Rd, 'Rn, 'IBr, 'IBs-r+1";
431 const char *form_lsl =
"'Rd, 'Rn, 'IBZ-r";
433 switch (instr->Mask(BitfieldMask)) {
442 }
else if (s == 15) {
444 }
else if ((s == 31) && (instr->SixtyFourBits() == 1)) {
449 }
else if (s == rd_size_minus_1) {
451 form = form_shift_right;
466 }
else if (s == 15) {
472 if (s == rd_size_minus_1) {
474 form = form_shift_right;
475 }
else if (r == s + 1) {
494 Format(instr, mnemonic, form);
498 void DisassemblingDecoder::VisitExtract(Instruction* instr) {
499 const char *mnemonic =
"";
500 const char *form =
"'Rd, 'Rn, 'Rm, 'IExtract";
502 switch (instr->Mask(ExtractMask)) {
505 if (instr->Rn() == instr->Rm()) {
507 form =
"'Rd, 'Rn, 'IExtract";
513 default: UNREACHABLE();
515 Format(instr, mnemonic, form);
519 void DisassemblingDecoder::VisitPCRelAddressing(Instruction* instr) {
520 switch (instr->Mask(PCRelAddressingMask)) {
521 case ADR: Format(instr,
"adr",
"'Xd, 'AddrPCRelByte");
break;
523 default: Format(instr,
"unimplemented",
"(PCRelAddressing)");
528 void DisassemblingDecoder::VisitConditionalBranch(Instruction* instr) {
529 switch (instr->Mask(ConditionalBranchMask)) {
531 Format(instr,
"b.'CBrn",
"'TImmCond");
533 default: UNREACHABLE();
538 void DisassemblingDecoder::VisitUnconditionalBranchToRegister(
539 Instruction* instr) {
540 const char *mnemonic =
"unimplemented";
541 const char *form =
"'Xn";
543 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
544 case BR: mnemonic =
"br";
break;
545 case BLR: mnemonic =
"blr";
break;
548 if (instr->Rn() == kLinkRegCode) {
553 default: form =
"(UnconditionalBranchToRegister)";
555 Format(instr, mnemonic, form);
559 void DisassemblingDecoder::VisitUnconditionalBranch(Instruction* instr) {
560 const char *mnemonic =
"";
561 const char* form =
"'TImmUncn";
563 switch (instr->Mask(UnconditionalBranchMask)) {
564 case B: mnemonic =
"b";
break;
565 case BL: mnemonic =
"bl";
break;
566 default: UNREACHABLE();
568 Format(instr, mnemonic, form);
572 void DisassemblingDecoder::VisitDataProcessing1Source(Instruction* instr) {
573 const char *mnemonic =
"";
574 const char *form =
"'Rd, 'Rn";
576 switch (instr->Mask(DataProcessing1SourceMask)) {
577 #define FORMAT(A, B) \ 579 case A##_x: mnemonic = B; break; 580 FORMAT(RBIT,
"rbit");
581 FORMAT(REV16,
"rev16");
586 case REV32_x: mnemonic =
"rev32";
break;
587 default: UNREACHABLE();
589 Format(instr, mnemonic, form);
593 void DisassemblingDecoder::VisitDataProcessing2Source(Instruction* instr) {
594 const char *mnemonic =
"unimplemented";
595 const char *form =
"'Rd, 'Rn, 'Rm";
597 switch (instr->Mask(DataProcessing2SourceMask)) {
598 #define FORMAT(A, B) \ 600 case A##_x: mnemonic = B; break; 601 FORMAT(UDIV,
"udiv");
602 FORMAT(SDIV,
"sdiv");
608 default: form =
"(DataProcessing2Source)";
610 Format(instr, mnemonic, form);
614 void DisassemblingDecoder::VisitDataProcessing3Source(Instruction* instr) {
615 bool ra_is_zr = RaIsZROrSP(instr);
616 const char *mnemonic =
"";
617 const char *form =
"'Xd, 'Wn, 'Wm, 'Xa";
618 const char *form_rrr =
"'Rd, 'Rn, 'Rm";
619 const char *form_rrrr =
"'Rd, 'Rn, 'Rm, 'Ra";
620 const char *form_xww =
"'Xd, 'Wn, 'Wm";
621 const char *form_xxx =
"'Xd, 'Xn, 'Xm";
623 switch (instr->Mask(DataProcessing3SourceMask)) {
686 default: UNREACHABLE();
688 Format(instr, mnemonic, form);
692 void DisassemblingDecoder::VisitCompareBranch(Instruction* instr) {
693 const char *mnemonic =
"";
694 const char* form =
"'Rt, 'TImmCmpa";
696 switch (instr->Mask(CompareBranchMask)) {
698 case CBZ_x: mnemonic =
"cbz";
break;
700 case CBNZ_x: mnemonic =
"cbnz";
break;
701 default: UNREACHABLE();
703 Format(instr, mnemonic, form);
707 void DisassemblingDecoder::VisitTestBranch(Instruction* instr) {
708 const char *mnemonic =
"";
713 const char* form =
"'Rt, 'IS, 'TImmTest";
715 switch (instr->Mask(TestBranchMask)) {
716 case TBZ: mnemonic =
"tbz";
break;
717 case TBNZ: mnemonic =
"tbnz";
break;
718 default: UNREACHABLE();
720 Format(instr, mnemonic, form);
724 void DisassemblingDecoder::VisitMoveWideImmediate(Instruction* instr) {
725 const char *mnemonic =
"";
726 const char *form =
"'Rd, 'IMoveImm";
731 switch (instr->Mask(MoveWideImmediateMask)) {
733 case MOVN_x: mnemonic =
"movn";
break;
735 case MOVZ_x: mnemonic =
"movz";
break;
737 case MOVK_x: mnemonic =
"movk"; form =
"'Rd, 'IMoveLSL";
break;
738 default: UNREACHABLE();
740 Format(instr, mnemonic, form);
743 #define LOAD_STORE_LIST(V) \ 744 V(STRB_w, "strb", "'Wt") \ 745 V(STRH_w, "strh", "'Wt") \ 746 V(STR_w, "str", "'Wt") \ 747 V(STR_x, "str", "'Xt") \ 748 V(LDRB_w, "ldrb", "'Wt") \ 749 V(LDRH_w, "ldrh", "'Wt") \ 750 V(LDR_w, "ldr", "'Wt") \ 751 V(LDR_x, "ldr", "'Xt") \ 752 V(LDRSB_x, "ldrsb", "'Xt") \ 753 V(LDRSH_x, "ldrsh", "'Xt") \ 754 V(LDRSW_x, "ldrsw", "'Xt") \ 755 V(LDRSB_w, "ldrsb", "'Wt") \ 756 V(LDRSH_w, "ldrsh", "'Wt") \ 757 V(STR_b, "str", "'Bt") \ 758 V(STR_h, "str", "'Ht") \ 759 V(STR_s, "str", "'St") \ 760 V(STR_d, "str", "'Dt") \ 761 V(LDR_b, "ldr", "'Bt") \ 762 V(LDR_h, "ldr", "'Ht") \ 763 V(LDR_s, "ldr", "'St") \ 764 V(LDR_d, "ldr", "'Dt") \ 765 V(STR_q, "str", "'Qt") \ 766 V(LDR_q, "ldr", "'Qt") 768 void DisassemblingDecoder::VisitLoadStorePreIndex(Instruction* instr) {
769 const char *mnemonic =
"unimplemented";
770 const char *form =
"(LoadStorePreIndex)";
772 switch (instr->Mask(LoadStorePreIndexMask)) {
773 #define LS_PREINDEX(A, B, C) \ 774 case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break; 775 LOAD_STORE_LIST(LS_PREINDEX)
778 Format(instr, mnemonic, form);
782 void DisassemblingDecoder::VisitLoadStorePostIndex(Instruction* instr) {
783 const char *mnemonic =
"unimplemented";
784 const char *form =
"(LoadStorePostIndex)";
786 switch (instr->Mask(LoadStorePostIndexMask)) {
787 #define LS_POSTINDEX(A, B, C) \ 788 case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break; 789 LOAD_STORE_LIST(LS_POSTINDEX)
792 Format(instr, mnemonic, form);
796 void DisassemblingDecoder::VisitLoadStoreUnsignedOffset(Instruction* instr) {
797 const char *mnemonic =
"unimplemented";
798 const char *form =
"(LoadStoreUnsignedOffset)";
800 switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
801 #define LS_UNSIGNEDOFFSET(A, B, C) \ 802 case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break; 803 LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
804 #undef LS_UNSIGNEDOFFSET 805 case PRFM_unsigned: mnemonic =
"prfm"; form =
"'PrefOp, ['Xn'ILU]";
807 Format(instr, mnemonic, form);
811 void DisassemblingDecoder::VisitLoadStoreRegisterOffset(Instruction* instr) {
812 const char *mnemonic =
"unimplemented";
813 const char *form =
"(LoadStoreRegisterOffset)";
815 switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
816 #define LS_REGISTEROFFSET(A, B, C) \ 817 case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break; 818 LOAD_STORE_LIST(LS_REGISTEROFFSET)
819 #undef LS_REGISTEROFFSET 820 case PRFM_reg: mnemonic =
"prfm"; form =
"'PrefOp, ['Xns, 'Offsetreg]";
822 Format(instr, mnemonic, form);
825 #define LOAD_STORE_UNSCALED_LIST(V) \ 826 V(STURB_w, "sturb", "'Wt") \ 827 V(STURH_w, "sturh", "'Wt") \ 828 V(STUR_w, "stur", "'Wt") \ 829 V(STUR_x, "stur", "'Xt") \ 830 V(LDURB_w, "ldurb", "'Wt") \ 831 V(LDURH_w, "ldurh", "'Wt") \ 832 V(LDUR_w, "ldur", "'Wt") \ 833 V(LDUR_x, "ldur", "'Xt") \ 834 V(LDURSB_x, "ldursb", "'Xt") \ 835 V(LDURSH_x, "ldursh", "'Xt") \ 836 V(LDURSW_x, "ldursw", "'Xt") \ 837 V(LDURSB_w, "ldursb", "'Wt") \ 838 V(LDURSH_w, "ldursh", "'Wt") \ 839 V(STUR_b, "stur", "'Bt") \ 840 V(STUR_h, "stur", "'Ht") \ 841 V(STUR_s, "stur", "'St") \ 842 V(STUR_d, "stur", "'Dt") \ 843 V(LDUR_b, "ldur", "'Bt") \ 844 V(LDUR_h, "ldur", "'Ht") \ 845 V(LDUR_s, "ldur", "'St") \ 846 V(LDUR_d, "ldur", "'Dt") \ 847 V(STUR_q, "stur", "'Qt") \ 848 V(LDUR_q, "ldur", "'Qt") 850 void DisassemblingDecoder::VisitLoadStoreUnscaledOffset(Instruction* instr) {
851 const char* mnemonic =
"unimplemented";
852 const char* form =
"(LoadStoreUnscaledOffset)";
854 switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
855 #define LS_UNSCALEDOFFSET(A, B, C) \ 858 form = C ", ['Xns'ILS]"; \ 860 LOAD_STORE_UNSCALED_LIST(LS_UNSCALEDOFFSET)
861 #undef LS_UNSCALEDOFFSET 863 Format(instr, mnemonic, form);
866 void DisassemblingDecoder::VisitLoadLiteral(Instruction* instr) {
867 const char *mnemonic =
"ldr";
868 const char *form =
"(LoadLiteral)";
870 switch (instr->Mask(LoadLiteralMask)) {
871 case LDR_w_lit: form =
"'Wt, 'ILLiteral 'LValue";
break;
872 case LDR_x_lit: form =
"'Xt, 'ILLiteral 'LValue";
break;
873 case LDR_s_lit: form =
"'St, 'ILLiteral 'LValue";
break;
874 case LDR_d_lit: form =
"'Dt, 'ILLiteral 'LValue";
break;
875 default: mnemonic =
"unimplemented";
877 Format(instr, mnemonic, form);
880 #define LOAD_STORE_PAIR_LIST(V) \ 881 V(STP_w, "stp", "'Wt, 'Wt2", "2") \ 882 V(LDP_w, "ldp", "'Wt, 'Wt2", "2") \ 883 V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "2") \ 884 V(STP_x, "stp", "'Xt, 'Xt2", "3") \ 885 V(LDP_x, "ldp", "'Xt, 'Xt2", "3") \ 886 V(STP_s, "stp", "'St, 'St2", "2") \ 887 V(LDP_s, "ldp", "'St, 'St2", "2") \ 888 V(STP_d, "stp", "'Dt, 'Dt2", "3") \ 889 V(LDP_d, "ldp", "'Dt, 'Dt2", "3") \ 890 V(LDP_q, "ldp", "'Qt, 'Qt2", "4") \ 891 V(STP_q, "stp", "'Qt, 'Qt2", "4") 893 void DisassemblingDecoder::VisitLoadStorePairPostIndex(Instruction* instr) {
894 const char *mnemonic =
"unimplemented";
895 const char *form =
"(LoadStorePairPostIndex)";
897 switch (instr->Mask(LoadStorePairPostIndexMask)) {
898 #define LSP_POSTINDEX(A, B, C, D) \ 899 case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break; 900 LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
903 Format(instr, mnemonic, form);
907 void DisassemblingDecoder::VisitLoadStorePairPreIndex(Instruction* instr) {
908 const char *mnemonic =
"unimplemented";
909 const char *form =
"(LoadStorePairPreIndex)";
911 switch (instr->Mask(LoadStorePairPreIndexMask)) {
912 #define LSP_PREINDEX(A, B, C, D) \ 913 case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break; 914 LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
917 Format(instr, mnemonic, form);
921 void DisassemblingDecoder::VisitLoadStorePairOffset(Instruction* instr) {
922 const char *mnemonic =
"unimplemented";
923 const char *form =
"(LoadStorePairOffset)";
925 switch (instr->Mask(LoadStorePairOffsetMask)) {
926 #define LSP_OFFSET(A, B, C, D) \ 927 case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break; 928 LOAD_STORE_PAIR_LIST(LSP_OFFSET)
931 Format(instr, mnemonic, form);
934 void DisassemblingDecoder::VisitLoadStoreAcquireRelease(Instruction *instr) {
935 const char *mnemonic =
"unimplemented";
936 const char* form =
"'Wt, ['Xns]";
937 const char* form_x =
"'Xt, ['Xns]";
938 const char* form_stlx =
"'Ws, 'Wt, ['Xns]";
939 const char* form_stlx_x =
"'Ws, 'Xt, ['Xns]";
941 switch (instr->Mask(LoadStoreAcquireReleaseMask)) {
942 case LDAXR_b: mnemonic =
"ldaxrb";
break;
943 case STLR_b: mnemonic =
"stlrb";
break;
944 case LDAR_b: mnemonic =
"ldarb";
break;
945 case LDAXR_h: mnemonic =
"ldaxrh";
break;
946 case STLR_h: mnemonic =
"stlrh";
break;
947 case LDAR_h: mnemonic =
"ldarh";
break;
948 case LDAXR_w: mnemonic =
"ldaxr";
break;
949 case STLR_w: mnemonic =
"stlr";
break;
950 case LDAR_w: mnemonic =
"ldar";
break;
951 case LDAXR_x: mnemonic =
"ldaxr"; form = form_x;
break;
952 case STLR_x: mnemonic =
"stlr"; form = form_x;
break;
953 case LDAR_x: mnemonic =
"ldar"; form = form_x;
break;
954 case STLXR_h: mnemonic =
"stlxrh"; form = form_stlx;
break;
955 case STLXR_b: mnemonic =
"stlxrb"; form = form_stlx;
break;
956 case STLXR_w: mnemonic =
"stlxr"; form = form_stlx;
break;
957 case STLXR_x: mnemonic =
"stlxr"; form = form_stlx_x;
break;
959 form =
"(LoadStoreAcquireRelease)";
961 Format(instr, mnemonic, form);
964 void DisassemblingDecoder::VisitFPCompare(Instruction* instr) {
965 const char *mnemonic =
"unimplemented";
966 const char *form =
"'Fn, 'Fm";
967 const char *form_zero =
"'Fn, #0.0";
969 switch (instr->Mask(FPCompareMask)) {
971 case FCMP_d_zero: form = form_zero; V8_FALLTHROUGH;
973 case FCMP_d: mnemonic =
"fcmp";
break;
974 default: form =
"(FPCompare)";
976 Format(instr, mnemonic, form);
980 void DisassemblingDecoder::VisitFPConditionalCompare(Instruction* instr) {
981 const char *mnemonic =
"unimplemented";
982 const char *form =
"'Fn, 'Fm, 'INzcv, 'Cond";
984 switch (instr->Mask(FPConditionalCompareMask)) {
986 case FCCMP_d: mnemonic =
"fccmp";
break;
988 case FCCMPE_d: mnemonic =
"fccmpe";
break;
989 default: form =
"(FPConditionalCompare)";
991 Format(instr, mnemonic, form);
995 void DisassemblingDecoder::VisitFPConditionalSelect(Instruction* instr) {
996 const char *mnemonic =
"";
997 const char *form =
"'Fd, 'Fn, 'Fm, 'Cond";
999 switch (instr->Mask(FPConditionalSelectMask)) {
1001 case FCSEL_d: mnemonic =
"fcsel";
break;
1002 default: UNREACHABLE();
1004 Format(instr, mnemonic, form);
1008 void DisassemblingDecoder::VisitFPDataProcessing1Source(Instruction* instr) {
1009 const char *mnemonic =
"unimplemented";
1010 const char *form =
"'Fd, 'Fn";
1012 switch (instr->Mask(FPDataProcessing1SourceMask)) {
1013 #define FORMAT(A, B) \ 1015 case A##_d: mnemonic = B; break; 1016 FORMAT(FMOV,
"fmov");
1017 FORMAT(FABS,
"fabs");
1018 FORMAT(FNEG,
"fneg");
1019 FORMAT(FSQRT,
"fsqrt");
1020 FORMAT(FRINTN,
"frintn");
1021 FORMAT(FRINTP,
"frintp");
1022 FORMAT(FRINTM,
"frintm");
1023 FORMAT(FRINTZ,
"frintz");
1024 FORMAT(FRINTA,
"frinta");
1025 FORMAT(FRINTX,
"frintx");
1026 FORMAT(FRINTI,
"frinti");
1028 case FCVT_ds: mnemonic =
"fcvt"; form =
"'Dd, 'Sn";
break;
1029 case FCVT_sd: mnemonic =
"fcvt"; form =
"'Sd, 'Dn";
break;
1046 default: form =
"(FPDataProcessing1Source)";
1048 Format(instr, mnemonic, form);
1052 void DisassemblingDecoder::VisitFPDataProcessing2Source(Instruction* instr) {
1053 const char *mnemonic =
"";
1054 const char *form =
"'Fd, 'Fn, 'Fm";
1056 switch (instr->Mask(FPDataProcessing2SourceMask)) {
1057 #define FORMAT(A, B) \ 1059 case A##_d: mnemonic = B; break; 1060 FORMAT(FMUL,
"fmul");
1061 FORMAT(FDIV,
"fdiv");
1062 FORMAT(FADD,
"fadd");
1063 FORMAT(FSUB,
"fsub");
1064 FORMAT(FMAX,
"fmax");
1065 FORMAT(FMIN,
"fmin");
1066 FORMAT(FMAXNM,
"fmaxnm");
1067 FORMAT(FMINNM,
"fminnm");
1068 FORMAT(FNMUL,
"fnmul");
1070 default: UNREACHABLE();
1072 Format(instr, mnemonic, form);
1076 void DisassemblingDecoder::VisitFPDataProcessing3Source(Instruction* instr) {
1077 const char *mnemonic =
"";
1078 const char *form =
"'Fd, 'Fn, 'Fm, 'Fa";
1080 switch (instr->Mask(FPDataProcessing3SourceMask)) {
1081 #define FORMAT(A, B) \ 1083 case A##_d: mnemonic = B; break; 1084 FORMAT(FMADD,
"fmadd");
1085 FORMAT(FMSUB,
"fmsub");
1086 FORMAT(FNMADD,
"fnmadd");
1087 FORMAT(FNMSUB,
"fnmsub");
1089 default: UNREACHABLE();
1091 Format(instr, mnemonic, form);
1095 void DisassemblingDecoder::VisitFPImmediate(Instruction* instr) {
1096 const char *mnemonic =
"";
1097 const char *form =
"(FPImmediate)";
1099 switch (instr->Mask(FPImmediateMask)) {
1100 case FMOV_s_imm: mnemonic =
"fmov"; form =
"'Sd, 'IFPSingle";
break;
1101 case FMOV_d_imm: mnemonic =
"fmov"; form =
"'Dd, 'IFPDouble";
break;
1102 default: UNREACHABLE();
1104 Format(instr, mnemonic, form);
1108 void DisassemblingDecoder::VisitFPIntegerConvert(Instruction* instr) {
1109 const char *mnemonic =
"unimplemented";
1110 const char *form =
"(FPIntegerConvert)";
1111 const char *form_rf =
"'Rd, 'Fn";
1112 const char *form_fr =
"'Fd, 'Rn";
1114 switch (instr->Mask(FPIntegerConvertMask)) {
1116 case FMOV_xd: mnemonic =
"fmov"; form = form_rf;
break;
1118 case FMOV_dx: mnemonic =
"fmov"; form = form_fr;
break;
1121 form =
"'Vd.D[1], 'Rn";
1125 form =
"'Rd, 'Vn.D[1]";
1130 case FCVTAS_xd: mnemonic =
"fcvtas"; form = form_rf;
break;
1134 case FCVTAU_xd: mnemonic =
"fcvtau"; form = form_rf;
break;
1138 case FCVTMS_xd: mnemonic =
"fcvtms"; form = form_rf;
break;
1142 case FCVTMU_xd: mnemonic =
"fcvtmu"; form = form_rf;
break;
1146 case FCVTNS_xd: mnemonic =
"fcvtns"; form = form_rf;
break;
1150 case FCVTNU_xd: mnemonic =
"fcvtnu"; form = form_rf;
break;
1154 case FCVTZU_xs: mnemonic =
"fcvtzu"; form = form_rf;
break;
1158 case FCVTZS_ws: mnemonic =
"fcvtzs"; form = form_rf;
break;
1163 mnemonic =
"fcvtpu";
1170 mnemonic =
"fcvtps";
1176 case SCVTF_dx: mnemonic =
"scvtf"; form = form_fr;
break;
1180 case UCVTF_dx: mnemonic =
"ucvtf"; form = form_fr;
break;
1182 Format(instr, mnemonic, form);
1186 void DisassemblingDecoder::VisitFPFixedPointConvert(Instruction* instr) {
1187 const char *mnemonic =
"";
1188 const char *form =
"'Rd, 'Fn, 'IFPFBits";
1189 const char *form_fr =
"'Fd, 'Rn, 'IFPFBits";
1191 switch (instr->Mask(FPFixedPointConvertMask)) {
1192 case FCVTZS_ws_fixed:
1193 case FCVTZS_xs_fixed:
1194 case FCVTZS_wd_fixed:
1195 case FCVTZS_xd_fixed: mnemonic =
"fcvtzs";
break;
1196 case FCVTZU_ws_fixed:
1197 case FCVTZU_xs_fixed:
1198 case FCVTZU_wd_fixed:
1199 case FCVTZU_xd_fixed: mnemonic =
"fcvtzu";
break;
1200 case SCVTF_sw_fixed:
1201 case SCVTF_sx_fixed:
1202 case SCVTF_dw_fixed:
1203 case SCVTF_dx_fixed: mnemonic =
"scvtf"; form = form_fr;
break;
1204 case UCVTF_sw_fixed:
1205 case UCVTF_sx_fixed:
1206 case UCVTF_dw_fixed:
1207 case UCVTF_dx_fixed: mnemonic =
"ucvtf"; form = form_fr;
break;
1209 Format(instr, mnemonic, form);
1213 void DisassemblingDecoder::VisitSystem(Instruction* instr) {
1217 const char *mnemonic =
"unimplemented";
1218 const char *form =
"(System)";
1220 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
1221 switch (instr->Mask(SystemSysRegMask)) {
1224 switch (instr->ImmSystemRegister()) {
1225 case NZCV: form =
"'Xt, nzcv";
break;
1226 case FPCR: form =
"'Xt, fpcr";
break;
1227 default: form =
"'Xt, (unknown)";
break;
1233 switch (instr->ImmSystemRegister()) {
1234 case NZCV: form =
"nzcv, 'Xt";
break;
1235 case FPCR: form =
"fpcr, 'Xt";
break;
1236 default: form =
"(unknown), 'Xt";
break;
1241 }
else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
1242 DCHECK(instr->Mask(SystemHintMask) == HINT);
1243 switch (instr->ImmHint()) {
1255 }
else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
1256 switch (instr->Mask(MemBarrierMask)) {
1275 Format(instr, mnemonic, form);
1279 void DisassemblingDecoder::VisitException(Instruction* instr) {
1280 const char *mnemonic =
"unimplemented";
1281 const char *form =
"'IDebug";
1283 switch (instr->Mask(ExceptionMask)) {
1284 case HLT: mnemonic =
"hlt";
break;
1285 case BRK: mnemonic =
"brk";
break;
1286 case SVC: mnemonic =
"svc";
break;
1287 case HVC: mnemonic =
"hvc";
break;
1288 case SMC: mnemonic =
"smc";
break;
1289 case DCPS1: mnemonic =
"dcps1"; form =
"{'IDebug}";
break;
1290 case DCPS2: mnemonic =
"dcps2"; form =
"{'IDebug}";
break;
1291 case DCPS3: mnemonic =
"dcps3"; form =
"{'IDebug}";
break;
1292 default: form =
"(Exception)";
1294 Format(instr, mnemonic, form);
1297 void DisassemblingDecoder::VisitNEON3Same(Instruction* instr) {
1298 const char* mnemonic =
"unimplemented";
1299 const char* form =
"'Vd.%s, 'Vn.%s, 'Vm.%s";
1300 NEONFormatDecoder nfd(instr);
1302 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
1303 switch (instr->Mask(NEON3SameLogicalMask)) {
1309 if (instr->Rm() == instr->Rn()) {
1311 form =
"'Vd.%s, 'Vn.%s";
1333 form =
"(NEON3Same)";
1335 nfd.SetFormatMaps(nfd.LogicalFormatMap());
1337 static const char* mnemonics[] = {
1338 "shadd",
"uhadd",
"shadd",
"uhadd",
1339 "sqadd",
"uqadd",
"sqadd",
"uqadd",
1340 "srhadd",
"urhadd",
"srhadd",
"urhadd",
1341 nullptr,
nullptr,
nullptr,
1343 "shsub",
"uhsub",
"shsub",
"uhsub",
1344 "sqsub",
"uqsub",
"sqsub",
"uqsub",
1345 "cmgt",
"cmhi",
"cmgt",
"cmhi",
1346 "cmge",
"cmhs",
"cmge",
"cmhs",
1347 "sshl",
"ushl",
"sshl",
"ushl",
1348 "sqshl",
"uqshl",
"sqshl",
"uqshl",
1349 "srshl",
"urshl",
"srshl",
"urshl",
1350 "sqrshl",
"uqrshl",
"sqrshl",
"uqrshl",
1351 "smax",
"umax",
"smax",
"umax",
1352 "smin",
"umin",
"smin",
"umin",
1353 "sabd",
"uabd",
"sabd",
"uabd",
1354 "saba",
"uaba",
"saba",
"uaba",
1355 "add",
"sub",
"add",
"sub",
1356 "cmtst",
"cmeq",
"cmtst",
"cmeq",
1357 "mla",
"mls",
"mla",
"mls",
1358 "mul",
"pmul",
"mul",
"pmul",
1359 "smaxp",
"umaxp",
"smaxp",
"umaxp",
1360 "sminp",
"uminp",
"sminp",
"uminp",
1361 "sqdmulh",
"sqrdmulh",
"sqdmulh",
"sqrdmulh",
1362 "addp",
"unallocated",
"addp",
"unallocated",
1363 "fmaxnm",
"fmaxnmp",
"fminnm",
"fminnmp",
1364 "fmla",
"unallocated",
"fmls",
"unallocated",
1365 "fadd",
"faddp",
"fsub",
"fabd",
1366 "fmulx",
"fmul",
"unallocated",
"unallocated",
1367 "fcmeq",
"fcmge",
"unallocated",
"fcmgt",
1368 "unallocated",
"facge",
"unallocated",
"facgt",
1369 "fmax",
"fmaxp",
"fmin",
"fminp",
1370 "frecps",
"fdiv",
"frsqrts",
"unallocated"};
1375 (instr->Bits(15, 11) << 2) | (instr->Bit(23) << 1) | instr->Bit(29);
1376 DCHECK_LT(index, arraysize(mnemonics));
1377 mnemonic = mnemonics[index];
1380 DCHECK_NOT_NULL(mnemonic);
1382 if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
1383 nfd.SetFormatMaps(nfd.FPFormatMap());
1386 Format(instr, mnemonic, nfd.Substitute(form));
1389 void DisassemblingDecoder::VisitNEON2RegMisc(Instruction* instr) {
1390 const char* mnemonic =
"unimplemented";
1391 const char* form =
"'Vd.%s, 'Vn.%s";
1392 const char* form_cmp_zero =
"'Vd.%s, 'Vn.%s, #0";
1393 const char* form_fcmp_zero =
"'Vd.%s, 'Vn.%s, #0.0";
1394 NEONFormatDecoder nfd(instr);
1396 static const NEONFormatMap map_lp_ta = {
1397 {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
1399 static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}};
1401 static const NEONFormatMap map_cvt_tb = {{22, 30},
1402 {NF_4H, NF_8H, NF_2S, NF_4S}};
1404 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
1407 switch (instr->Mask(NEON2RegMiscMask)) {
1418 mnemonic =
"saddlp";
1419 nfd.SetFormatMap(0, &map_lp_ta);
1422 mnemonic =
"uaddlp";
1423 nfd.SetFormatMap(0, &map_lp_ta);
1426 mnemonic =
"suqadd";
1429 mnemonic =
"usqadd";
1441 mnemonic =
"sadalp";
1442 nfd.SetFormatMap(0, &map_lp_ta);
1445 mnemonic =
"uadalp";
1446 nfd.SetFormatMap(0, &map_lp_ta);
1454 case NEON_CMGT_zero:
1456 form = form_cmp_zero;
1458 case NEON_CMGE_zero:
1460 form = form_cmp_zero;
1462 case NEON_CMEQ_zero:
1464 form = form_cmp_zero;
1466 case NEON_CMLE_zero:
1468 form = form_cmp_zero;
1470 case NEON_CMLT_zero:
1472 form = form_cmp_zero;
1481 switch (instr->FPType()) {
1489 form =
"(NEON2RegMisc)";
1491 nfd.SetFormatMaps(nfd.LogicalFormatMap());
1497 nfd.SetFormatMaps(nfd.FPFormatMap());
1498 switch (instr->Mask(NEON2RegMiscFPMask)) {
1506 mnemonic = instr->Mask(NEON_Q) ?
"fcvtn2" :
"fcvtn";
1507 nfd.SetFormatMap(0, &map_cvt_tb);
1508 nfd.SetFormatMap(1, &map_cvt_ta);
1511 mnemonic = instr->Mask(NEON_Q) ?
"fcvtxn2" :
"fcvtxn";
1512 nfd.SetFormatMap(0, &map_cvt_tb);
1513 nfd.SetFormatMap(1, &map_cvt_ta);
1516 mnemonic = instr->Mask(NEON_Q) ?
"fcvtl2" :
"fcvtl";
1517 nfd.SetFormatMap(0, &map_cvt_ta);
1518 nfd.SetFormatMap(1, &map_cvt_tb);
1521 mnemonic =
"frintn";
1524 mnemonic =
"frinta";
1527 mnemonic =
"frintp";
1530 mnemonic =
"frintm";
1533 mnemonic =
"frintx";
1536 mnemonic =
"frintz";
1539 mnemonic =
"frinti";
1542 mnemonic =
"fcvtns";
1545 mnemonic =
"fcvtnu";
1548 mnemonic =
"fcvtps";
1551 mnemonic =
"fcvtpu";
1554 mnemonic =
"fcvtms";
1557 mnemonic =
"fcvtmu";
1560 mnemonic =
"fcvtzs";
1563 mnemonic =
"fcvtzu";
1566 mnemonic =
"fcvtas";
1569 mnemonic =
"fcvtau";
1581 mnemonic =
"ursqrte";
1584 mnemonic =
"urecpe";
1587 mnemonic =
"frsqrte";
1590 mnemonic =
"frecpe";
1592 case NEON_FCMGT_zero:
1594 form = form_fcmp_zero;
1596 case NEON_FCMGE_zero:
1598 form = form_fcmp_zero;
1600 case NEON_FCMEQ_zero:
1602 form = form_fcmp_zero;
1604 case NEON_FCMLE_zero:
1606 form = form_fcmp_zero;
1608 case NEON_FCMLT_zero:
1610 form = form_fcmp_zero;
1613 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
1614 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
1615 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1616 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1618 switch (instr->Mask(NEON2RegMiscMask)) {
1629 mnemonic =
"sqxtun";
1633 nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
1634 nfd.SetFormatMap(1, nfd.IntegerFormatMap());
1635 switch (instr->NEONSize()) {
1637 form =
"'Vd.%s, 'Vn.%s, #8";
1640 form =
"'Vd.%s, 'Vn.%s, #16";
1643 form =
"'Vd.%s, 'Vn.%s, #32";
1646 Format(instr,
"unallocated",
"(NEON2RegMisc)");
1650 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1653 form =
"(NEON2RegMisc)";
1657 Format(instr, mnemonic, nfd.Substitute(form));
1660 void DisassemblingDecoder::VisitNEON3Different(Instruction* instr) {
1661 const char* mnemonic =
"unimplemented";
1662 const char* form =
"'Vd.%s, 'Vn.%s, 'Vm.%s";
1664 NEONFormatDecoder nfd(instr);
1665 nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
1668 switch (instr->Mask(NEON3DifferentMask) & ~NEON_Q) {
1694 mnemonic =
"sqdmlal";
1697 mnemonic =
"sqdmlsl";
1700 mnemonic =
"sqdmull";
1725 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1729 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1733 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1737 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1741 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1742 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1745 mnemonic =
"raddhn";
1746 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1747 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1750 mnemonic =
"rsubhn";
1751 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1752 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1756 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1757 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1760 form =
"(NEON3Different)";
1762 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1765 void DisassemblingDecoder::VisitNEONAcrossLanes(Instruction* instr) {
1766 const char* mnemonic =
"unimplemented";
1767 const char* form =
"%sd, 'Vn.%s";
1769 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap(),
1770 NEONFormatDecoder::IntegerFormatMap());
1772 if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
1773 nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
1774 nfd.SetFormatMap(1, nfd.FPFormatMap());
1775 switch (instr->Mask(NEONAcrossLanesFPMask)) {
1783 mnemonic =
"fmaxnmv";
1786 mnemonic =
"fminnmv";
1789 form =
"(NEONAcrossLanes)";
1792 }
else if (instr->Mask(NEONAcrossLanesFMask) == NEONAcrossLanesFixed) {
1793 switch (instr->Mask(NEONAcrossLanesMask)) {
1810 mnemonic =
"saddlv";
1811 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
1814 mnemonic =
"uaddlv";
1815 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
1818 form =
"(NEONAcrossLanes)";
1822 Format(instr, mnemonic,
1823 nfd.Substitute(form, NEONFormatDecoder::kPlaceholder,
1824 NEONFormatDecoder::kFormat));
1827 void DisassemblingDecoder::VisitNEONByIndexedElement(Instruction* instr) {
1828 const char* mnemonic =
"unimplemented";
1829 bool l_instr =
false;
1830 bool fp_instr =
false;
1832 const char* form =
"'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
1834 static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}};
1835 NEONFormatDecoder nfd(instr, &map_ta, NEONFormatDecoder::IntegerFormatMap(),
1836 NEONFormatDecoder::ScalarFormatMap());
1838 switch (instr->Mask(NEONByIndexedElementMask)) {
1839 case NEON_SMULL_byelement:
1843 case NEON_UMULL_byelement:
1847 case NEON_SMLAL_byelement:
1851 case NEON_UMLAL_byelement:
1855 case NEON_SMLSL_byelement:
1859 case NEON_UMLSL_byelement:
1863 case NEON_SQDMULL_byelement:
1864 mnemonic =
"sqdmull";
1867 case NEON_SQDMLAL_byelement:
1868 mnemonic =
"sqdmlal";
1871 case NEON_SQDMLSL_byelement:
1872 mnemonic =
"sqdmlsl";
1875 case NEON_MUL_byelement:
1878 case NEON_MLA_byelement:
1881 case NEON_MLS_byelement:
1884 case NEON_SQDMULH_byelement:
1885 mnemonic =
"sqdmulh";
1887 case NEON_SQRDMULH_byelement:
1888 mnemonic =
"sqrdmulh";
1891 switch (instr->Mask(NEONByIndexedElementFPMask)) {
1892 case NEON_FMUL_byelement:
1896 case NEON_FMLA_byelement:
1900 case NEON_FMLS_byelement:
1904 case NEON_FMULX_byelement:
1912 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1913 }
else if (fp_instr) {
1914 nfd.SetFormatMap(0, nfd.FPFormatMap());
1915 Format(instr, mnemonic, nfd.Substitute(form));
1917 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1918 Format(instr, mnemonic, nfd.Substitute(form));
1922 void DisassemblingDecoder::VisitNEONCopy(Instruction* instr) {
1923 const char* mnemonic =
"unimplemented";
1924 const char* form =
"(NEONCopy)";
1926 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap(),
1927 NEONFormatDecoder::TriangularScalarFormatMap());
1929 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
1931 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1932 form =
"'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]";
1933 }
else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
1935 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1936 if (nfd.GetVectorFormat() == kFormatD) {
1937 form =
"'Vd.%s['IVInsIndex1], 'Xn";
1939 form =
"'Vd.%s['IVInsIndex1], 'Wn";
1941 }
else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
1942 if (instr->Mask(NEON_Q) || ((instr->ImmNEON5() & 7) == 4)) {
1947 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1948 if (nfd.GetVectorFormat() == kFormatD) {
1949 form =
"'Xd, 'Vn.%s['IVInsIndex1]";
1951 form =
"'Wd, 'Vn.%s['IVInsIndex1]";
1953 }
else if (instr->Mask(NEONCopySmovMask) == NEON_SMOV) {
1955 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1956 form =
"'Rdq, 'Vn.%s['IVInsIndex1]";
1957 }
else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
1959 form =
"'Vd.%s, 'Vn.%s['IVInsIndex1]";
1960 }
else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
1962 if (nfd.GetVectorFormat() == kFormat2D) {
1963 form =
"'Vd.%s, 'Xn";
1965 form =
"'Vd.%s, 'Wn";
1968 Format(instr, mnemonic, nfd.Substitute(form));
1971 void DisassemblingDecoder::VisitNEONExtract(Instruction* instr) {
1972 const char* mnemonic =
"unimplemented";
1973 const char* form =
"(NEONExtract)";
1974 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
1975 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
1977 form =
"'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract";
1979 Format(instr, mnemonic, nfd.Substitute(form));
1982 void DisassemblingDecoder::VisitNEONLoadStoreMultiStruct(Instruction* instr) {
1983 const char* mnemonic =
nullptr;
1984 const char* form =
nullptr;
1985 const char* form_1v =
"{'Vt.%1$s}, ['Xns]";
1986 const char* form_2v =
"{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]";
1987 const char* form_3v =
"{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]";
1988 const char* form_4v =
"{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
1989 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
1991 switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
2053 bool allocated = (mnemonic !=
nullptr);
2054 switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
2062 allocated = (instr->NEONQ() != 0) || (instr->NEONLSSize() != 3);
2068 DCHECK_NOT_NULL(mnemonic);
2069 DCHECK_NOT_NULL(form);
2071 mnemonic =
"unallocated";
2072 form =
"(NEONLoadStoreMultiStruct)";
2075 Format(instr, mnemonic, nfd.Substitute(form));
2078 void DisassemblingDecoder::VisitNEONLoadStoreMultiStructPostIndex(
2079 Instruction* instr) {
2080 const char* mnemonic =
nullptr;
2081 const char* form =
nullptr;
2082 const char* form_1v =
"{'Vt.%1$s}, ['Xns], 'Xmr1";
2083 const char* form_2v =
"{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2";
2084 const char* form_3v =
"{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3";
2085 const char* form_4v =
2086 "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4";
2087 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2089 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
2090 case NEON_LD1_1v_post:
2094 case NEON_LD1_2v_post:
2098 case NEON_LD1_3v_post:
2102 case NEON_LD1_4v_post:
2118 case NEON_ST1_1v_post:
2122 case NEON_ST1_2v_post:
2126 case NEON_ST1_3v_post:
2130 case NEON_ST1_4v_post:
2151 bool allocated = (mnemonic !=
nullptr);
2152 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
2160 allocated = (instr->NEONQ() != 0) || (instr->NEONLSSize() != 3);
2166 DCHECK_NOT_NULL(mnemonic);
2167 DCHECK_NOT_NULL(form);
2169 mnemonic =
"unallocated";
2170 form =
"(NEONLoadStoreMultiStructPostIndex)";
2173 Format(instr, mnemonic, nfd.Substitute(form));
2176 void DisassemblingDecoder::VisitNEONLoadStoreSingleStruct(Instruction* instr) {
2177 const char* mnemonic =
nullptr;
2178 const char* form =
nullptr;
2180 const char* form_1b =
"{'Vt.b}['IVLSLane0], ['Xns]";
2181 const char* form_1h =
"{'Vt.h}['IVLSLane1], ['Xns]";
2182 const char* form_1s =
"{'Vt.s}['IVLSLane2], ['Xns]";
2183 const char* form_1d =
"{'Vt.d}['IVLSLane3], ['Xns]";
2184 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2186 switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
2197 static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
2198 "LSB of size distinguishes S and D registers.");
2199 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2211 static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
2212 "LSB of size distinguishes S and D registers.");
2213 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2217 form =
"{'Vt.%s}, ['Xns]";
2221 mnemonic = (instr->NEONLoad() == 1) ?
"ld2" :
"st2";
2222 form =
"{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]";
2226 mnemonic = (instr->NEONLoad() == 1) ?
"ld2" :
"st2";
2227 form =
"{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]";
2231 static_assert((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d,
2232 "LSB of size distinguishes S and D registers.");
2233 static_assert((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d,
2234 "LSB of size distinguishes S and D registers.");
2235 mnemonic = (instr->NEONLoad() == 1) ?
"ld2" :
"st2";
2236 if ((instr->NEONLSSize() & 1) == 0) {
2237 form =
"{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]";
2239 form =
"{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]";
2244 form =
"{'Vt.%s, 'Vt2.%s}, ['Xns]";
2248 mnemonic = (instr->NEONLoad() == 1) ?
"ld3" :
"st3";
2249 form =
"{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]";
2253 mnemonic = (instr->NEONLoad() == 1) ?
"ld3" :
"st3";
2254 form =
"{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]";
2258 mnemonic = (instr->NEONLoad() == 1) ?
"ld3" :
"st3";
2259 if ((instr->NEONLSSize() & 1) == 0) {
2260 form =
"{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]";
2262 form =
"{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]";
2267 form =
"{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]";
2271 mnemonic = (instr->NEONLoad() == 1) ?
"ld4" :
"st4";
2272 form =
"{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]";
2276 mnemonic = (instr->NEONLoad() == 1) ?
"ld4" :
"st4";
2277 form =
"{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]";
2281 static_assert((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d,
2282 "LSB of size distinguishes S and D registers.");
2283 static_assert((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d,
2284 "LSB of size distinguishes S and D registers.");
2285 mnemonic = (instr->NEONLoad() == 1) ?
"ld4" :
"st4";
2286 if ((instr->NEONLSSize() & 1) == 0) {
2287 form =
"{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]";
2289 form =
"{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]";
2294 form =
"{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
2301 bool allocated = (mnemonic !=
nullptr);
2302 switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
2312 allocated = ((instr->NEONLSSize() & 1) == 0);
2323 allocated = (instr->NEONLSSize() <= 1) &&
2324 ((instr->NEONLSSize() == 0) || (instr->NEONS() == 0));
2331 allocated = (instr->NEONS() == 0);
2337 DCHECK_NOT_NULL(mnemonic);
2338 DCHECK_NOT_NULL(form);
2340 mnemonic =
"unallocated";
2341 form =
"(NEONLoadStoreSingleStruct)";
2344 Format(instr, mnemonic, nfd.Substitute(form));
2347 void DisassemblingDecoder::VisitNEONLoadStoreSingleStructPostIndex(
2348 Instruction* instr) {
2349 const char* mnemonic =
nullptr;
2350 const char* form =
nullptr;
2352 const char* form_1b =
"{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1";
2353 const char* form_1h =
"{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2";
2354 const char* form_1s =
"{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4";
2355 const char* form_1d =
"{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8";
2356 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2358 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
2359 case NEON_LD1_b_post:
2363 case NEON_LD1_h_post:
2367 case NEON_LD1_s_post:
2369 static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
2370 "LSB of size distinguishes S and D registers.");
2371 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2373 case NEON_ST1_b_post:
2377 case NEON_ST1_h_post:
2381 case NEON_ST1_s_post:
2383 static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
2384 "LSB of size distinguishes S and D registers.");
2385 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2387 case NEON_LD1R_post:
2389 form =
"{'Vt.%s}, ['Xns], 'Xmz1";
2391 case NEON_LD2_b_post:
2392 case NEON_ST2_b_post:
2393 mnemonic = (instr->NEONLoad() == 1) ?
"ld2" :
"st2";
2394 form =
"{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2";
2396 case NEON_ST2_h_post:
2397 case NEON_LD2_h_post:
2398 mnemonic = (instr->NEONLoad() == 1) ?
"ld2" :
"st2";
2399 form =
"{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4";
2401 case NEON_LD2_s_post:
2402 case NEON_ST2_s_post:
2403 mnemonic = (instr->NEONLoad() == 1) ?
"ld2" :
"st2";
2404 if ((instr->NEONLSSize() & 1) == 0)
2405 form =
"{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8";
2407 form =
"{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16";
2409 case NEON_LD2R_post:
2411 form =
"{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2";
2413 case NEON_LD3_b_post:
2414 case NEON_ST3_b_post:
2415 mnemonic = (instr->NEONLoad() == 1) ?
"ld3" :
"st3";
2416 form =
"{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3";
2418 case NEON_LD3_h_post:
2419 case NEON_ST3_h_post:
2420 mnemonic = (instr->NEONLoad() == 1) ?
"ld3" :
"st3";
2421 form =
"{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6";
2423 case NEON_LD3_s_post:
2424 case NEON_ST3_s_post:
2425 mnemonic = (instr->NEONLoad() == 1) ?
"ld3" :
"st3";
2426 if ((instr->NEONLSSize() & 1) == 0)
2427 form =
"{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12";
2429 form =
"{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24";
2431 case NEON_LD3R_post:
2433 form =
"{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3";
2435 case NEON_LD4_b_post:
2436 case NEON_ST4_b_post:
2437 mnemonic = (instr->NEONLoad() == 1) ?
"ld4" :
"st4";
2438 form =
"{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4";
2440 case NEON_LD4_h_post:
2441 case NEON_ST4_h_post:
2442 mnemonic = (instr->NEONLoad()) == 1 ?
"ld4" :
"st4";
2443 form =
"{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8";
2445 case NEON_LD4_s_post:
2446 case NEON_ST4_s_post:
2447 mnemonic = (instr->NEONLoad() == 1) ?
"ld4" :
"st4";
2448 if ((instr->NEONLSSize() & 1) == 0)
2449 form =
"{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16";
2451 form =
"{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32";
2453 case NEON_LD4R_post:
2455 form =
"{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4";
2462 bool allocated = (mnemonic !=
nullptr);
2463 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
2464 case NEON_LD1_h_post:
2465 case NEON_LD2_h_post:
2466 case NEON_LD3_h_post:
2467 case NEON_LD4_h_post:
2468 case NEON_ST1_h_post:
2469 case NEON_ST2_h_post:
2470 case NEON_ST3_h_post:
2471 case NEON_ST4_h_post:
2473 allocated = ((instr->NEONLSSize() & 1) == 0);
2475 case NEON_LD1_s_post:
2476 case NEON_LD2_s_post:
2477 case NEON_LD3_s_post:
2478 case NEON_LD4_s_post:
2479 case NEON_ST1_s_post:
2480 case NEON_ST2_s_post:
2481 case NEON_ST3_s_post:
2482 case NEON_ST4_s_post:
2484 allocated = (instr->NEONLSSize() <= 1) &&
2485 ((instr->NEONLSSize() == 0) || (instr->NEONS() == 0));
2487 case NEON_LD1R_post:
2488 case NEON_LD2R_post:
2489 case NEON_LD3R_post:
2490 case NEON_LD4R_post:
2492 allocated = (instr->NEONS() == 0);
2498 DCHECK_NOT_NULL(mnemonic);
2499 DCHECK_NOT_NULL(form);
2501 mnemonic =
"unallocated";
2502 form =
"(NEONLoadStoreSingleStructPostIndex)";
2505 Format(instr, mnemonic, nfd.Substitute(form));
2508 void DisassemblingDecoder::VisitNEONModifiedImmediate(Instruction* instr) {
2509 const char* mnemonic =
"unimplemented";
2510 const char* form =
"'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1";
2512 int cmode = instr->NEONCmode();
2513 int cmode_3 = (cmode >> 3) & 1;
2514 int cmode_2 = (cmode >> 2) & 1;
2515 int cmode_1 = (cmode >> 1) & 1;
2516 int cmode_0 = cmode & 1;
2517 int q = instr->NEONQ();
2518 int op = instr->NEONModImmOp();
2520 static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
2521 static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}};
2522 static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}};
2523 NEONFormatDecoder nfd(instr, &map_b);
2527 mnemonic = (op == 1) ?
"mvni" :
"movi";
2529 mnemonic = (op == 1) ?
"bic" :
"orr";
2531 nfd.SetFormatMap(0, &map_s);
2535 mnemonic = (op == 1) ?
"mvni" :
"movi";
2537 mnemonic = (op == 1) ?
"bic" :
"orr";
2539 nfd.SetFormatMap(0, &map_h);
2542 mnemonic = (op == 1) ?
"mvni" :
"movi";
2543 form =
"'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2";
2544 nfd.SetFormatMap(0, &map_s);
2549 form =
"'Vt.%s, 'IVMIImm8";
2551 form = (q == 0) ?
"'Dd, 'IVMIImm" :
"'Vt.2d, 'IVMIImm";
2556 form =
"'Vt.%s, 'IVMIImmFPSingle";
2557 nfd.SetFormatMap(0, &map_s);
2560 form =
"'Vt.2d, 'IVMIImmFPDouble";
2562 mnemonic =
"unallocated";
2563 form =
"(NEONModifiedImmediate)";
2570 Format(instr, mnemonic, nfd.Substitute(form));
2573 void DisassemblingDecoder::VisitNEONPerm(Instruction* instr) {
2574 const char* mnemonic =
"unimplemented";
2575 const char* form =
"'Vd.%s, 'Vn.%s, 'Vm.%s";
2576 NEONFormatDecoder nfd(instr);
2578 switch (instr->Mask(NEONPermMask)) {
2598 form =
"(NEONPerm)";
2600 Format(instr, mnemonic, nfd.Substitute(form));
2603 void DisassemblingDecoder::VisitNEONScalar2RegMisc(Instruction* instr) {
2604 const char* mnemonic =
"unimplemented";
2605 const char* form =
"%sd, %sn";
2606 const char* form_0 =
"%sd, %sn, #0";
2607 const char* form_fp0 =
"%sd, %sn, #0.0";
2609 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2611 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
2614 switch (instr->Mask(NEONScalar2RegMiscMask)) {
2615 case NEON_CMGT_zero_scalar:
2619 case NEON_CMGE_zero_scalar:
2623 case NEON_CMLE_zero_scalar:
2627 case NEON_CMLT_zero_scalar:
2631 case NEON_CMEQ_zero_scalar:
2635 case NEON_NEG_scalar:
2638 case NEON_SQNEG_scalar:
2641 case NEON_ABS_scalar:
2644 case NEON_SQABS_scalar:
2647 case NEON_SUQADD_scalar:
2648 mnemonic =
"suqadd";
2650 case NEON_USQADD_scalar:
2651 mnemonic =
"usqadd";
2654 form =
"(NEONScalar2RegMisc)";
2659 nfd.SetFormatMaps(nfd.FPScalarFormatMap());
2660 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
2661 case NEON_FRSQRTE_scalar:
2662 mnemonic =
"frsqrte";
2664 case NEON_FRECPE_scalar:
2665 mnemonic =
"frecpe";
2667 case NEON_SCVTF_scalar:
2670 case NEON_UCVTF_scalar:
2673 case NEON_FCMGT_zero_scalar:
2677 case NEON_FCMGE_zero_scalar:
2681 case NEON_FCMLE_zero_scalar:
2685 case NEON_FCMLT_zero_scalar:
2689 case NEON_FCMEQ_zero_scalar:
2693 case NEON_FRECPX_scalar:
2694 mnemonic =
"frecpx";
2696 case NEON_FCVTNS_scalar:
2697 mnemonic =
"fcvtns";
2699 case NEON_FCVTNU_scalar:
2700 mnemonic =
"fcvtnu";
2702 case NEON_FCVTPS_scalar:
2703 mnemonic =
"fcvtps";
2705 case NEON_FCVTPU_scalar:
2706 mnemonic =
"fcvtpu";
2708 case NEON_FCVTMS_scalar:
2709 mnemonic =
"fcvtms";
2711 case NEON_FCVTMU_scalar:
2712 mnemonic =
"fcvtmu";
2714 case NEON_FCVTZS_scalar:
2715 mnemonic =
"fcvtzs";
2717 case NEON_FCVTZU_scalar:
2718 mnemonic =
"fcvtzu";
2720 case NEON_FCVTAS_scalar:
2721 mnemonic =
"fcvtas";
2723 case NEON_FCVTAU_scalar:
2724 mnemonic =
"fcvtau";
2726 case NEON_FCVTXN_scalar:
2727 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
2728 mnemonic =
"fcvtxn";
2731 nfd.SetFormatMap(0, nfd.ScalarFormatMap());
2732 nfd.SetFormatMap(1, nfd.LongScalarFormatMap());
2733 switch (instr->Mask(NEONScalar2RegMiscMask)) {
2734 case NEON_SQXTN_scalar:
2737 case NEON_UQXTN_scalar:
2740 case NEON_SQXTUN_scalar:
2741 mnemonic =
"sqxtun";
2744 form =
"(NEONScalar2RegMisc)";
2748 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2751 void DisassemblingDecoder::VisitNEONScalar3Diff(Instruction* instr) {
2752 const char* mnemonic =
"unimplemented";
2753 const char* form =
"%sd, %sn, %sm";
2754 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap(),
2755 NEONFormatDecoder::ScalarFormatMap());
2757 switch (instr->Mask(NEONScalar3DiffMask)) {
2758 case NEON_SQDMLAL_scalar:
2759 mnemonic =
"sqdmlal";
2761 case NEON_SQDMLSL_scalar:
2762 mnemonic =
"sqdmlsl";
2764 case NEON_SQDMULL_scalar:
2765 mnemonic =
"sqdmull";
2768 form =
"(NEONScalar3Diff)";
2770 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2773 void DisassemblingDecoder::VisitNEONScalar3Same(Instruction* instr) {
2774 const char* mnemonic =
"unimplemented";
2775 const char* form =
"%sd, %sn, %sm";
2776 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2778 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
2779 nfd.SetFormatMaps(nfd.FPScalarFormatMap());
2780 switch (instr->Mask(NEONScalar3SameFPMask)) {
2781 case NEON_FACGE_scalar:
2784 case NEON_FACGT_scalar:
2787 case NEON_FCMEQ_scalar:
2790 case NEON_FCMGE_scalar:
2793 case NEON_FCMGT_scalar:
2796 case NEON_FMULX_scalar:
2799 case NEON_FRECPS_scalar:
2800 mnemonic =
"frecps";
2802 case NEON_FRSQRTS_scalar:
2803 mnemonic =
"frsqrts";
2805 case NEON_FABD_scalar:
2809 form =
"(NEONScalar3Same)";
2812 switch (instr->Mask(NEONScalar3SameMask)) {
2813 case NEON_ADD_scalar:
2816 case NEON_SUB_scalar:
2819 case NEON_CMEQ_scalar:
2822 case NEON_CMGE_scalar:
2825 case NEON_CMGT_scalar:
2828 case NEON_CMHI_scalar:
2831 case NEON_CMHS_scalar:
2834 case NEON_CMTST_scalar:
2837 case NEON_UQADD_scalar:
2840 case NEON_SQADD_scalar:
2843 case NEON_UQSUB_scalar:
2846 case NEON_SQSUB_scalar:
2849 case NEON_USHL_scalar:
2852 case NEON_SSHL_scalar:
2855 case NEON_UQSHL_scalar:
2858 case NEON_SQSHL_scalar:
2861 case NEON_URSHL_scalar:
2864 case NEON_SRSHL_scalar:
2867 case NEON_UQRSHL_scalar:
2868 mnemonic =
"uqrshl";
2870 case NEON_SQRSHL_scalar:
2871 mnemonic =
"sqrshl";
2873 case NEON_SQDMULH_scalar:
2874 mnemonic =
"sqdmulh";
2876 case NEON_SQRDMULH_scalar:
2877 mnemonic =
"sqrdmulh";
2880 form =
"(NEONScalar3Same)";
2883 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2886 void DisassemblingDecoder::VisitNEONScalarByIndexedElement(Instruction* instr) {
2887 const char* mnemonic =
"unimplemented";
2888 const char* form =
"%sd, %sn, 'Ve.%s['IVByElemIndex]";
2889 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2890 bool long_instr =
false;
2892 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
2893 case NEON_SQDMULL_byelement_scalar:
2894 mnemonic =
"sqdmull";
2897 case NEON_SQDMLAL_byelement_scalar:
2898 mnemonic =
"sqdmlal";
2901 case NEON_SQDMLSL_byelement_scalar:
2902 mnemonic =
"sqdmlsl";
2905 case NEON_SQDMULH_byelement_scalar:
2906 mnemonic =
"sqdmulh";
2908 case NEON_SQRDMULH_byelement_scalar:
2909 mnemonic =
"sqrdmulh";
2912 nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
2913 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
2914 case NEON_FMUL_byelement_scalar:
2917 case NEON_FMLA_byelement_scalar:
2920 case NEON_FMLS_byelement_scalar:
2923 case NEON_FMULX_byelement_scalar:
2927 form =
"(NEONScalarByIndexedElement)";
2932 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
2935 Format(instr, mnemonic,
2936 nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
2939 void DisassemblingDecoder::VisitNEONScalarCopy(Instruction* instr) {
2940 const char* mnemonic =
"unimplemented";
2941 const char* form =
"(NEONScalarCopy)";
2943 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
2945 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
2947 form =
"%sd, 'Vn.%s['IVInsIndex1]";
2950 Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat));
2953 void DisassemblingDecoder::VisitNEONScalarPairwise(Instruction* instr) {
2954 const char* mnemonic =
"unimplemented";
2955 const char* form =
"%sd, 'Vn.%s";
2956 NEONFormatMap map = {{22}, {NF_2S, NF_2D}};
2957 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap(), &map);
2959 switch (instr->Mask(NEONScalarPairwiseMask)) {
2960 case NEON_ADDP_scalar:
2963 case NEON_FADDP_scalar:
2966 case NEON_FMAXP_scalar:
2969 case NEON_FMAXNMP_scalar:
2970 mnemonic =
"fmaxnmp";
2972 case NEON_FMINP_scalar:
2975 case NEON_FMINNMP_scalar:
2976 mnemonic =
"fminnmp";
2979 form =
"(NEONScalarPairwise)";
2981 Format(instr, mnemonic,
2982 nfd.Substitute(form, NEONFormatDecoder::kPlaceholder,
2983 NEONFormatDecoder::kFormat));
2986 void DisassemblingDecoder::VisitNEONScalarShiftImmediate(Instruction* instr) {
2987 const char* mnemonic =
"unimplemented";
2988 const char* form =
"%sd, %sn, 'Is1";
2989 const char* form_2 =
"%sd, %sn, 'Is2";
2991 static const NEONFormatMap map_shift = {
2993 {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S, NF_D, NF_D, NF_D,
2994 NF_D, NF_D, NF_D, NF_D, NF_D}};
2995 static const NEONFormatMap map_shift_narrow = {
2996 {21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}};
2997 NEONFormatDecoder nfd(instr, &map_shift);
2999 if (instr->ImmNEONImmh()) {
3000 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
3001 case NEON_FCVTZU_imm_scalar:
3002 mnemonic =
"fcvtzu";
3004 case NEON_FCVTZS_imm_scalar:
3005 mnemonic =
"fcvtzs";
3007 case NEON_SCVTF_imm_scalar:
3010 case NEON_UCVTF_imm_scalar:
3013 case NEON_SRI_scalar:
3016 case NEON_SSHR_scalar:
3019 case NEON_USHR_scalar:
3022 case NEON_SRSHR_scalar:
3025 case NEON_URSHR_scalar:
3028 case NEON_SSRA_scalar:
3031 case NEON_USRA_scalar:
3034 case NEON_SRSRA_scalar:
3037 case NEON_URSRA_scalar:
3040 case NEON_SHL_scalar:
3044 case NEON_SLI_scalar:
3048 case NEON_SQSHLU_scalar:
3049 mnemonic =
"sqshlu";
3052 case NEON_SQSHL_imm_scalar:
3056 case NEON_UQSHL_imm_scalar:
3060 case NEON_UQSHRN_scalar:
3061 mnemonic =
"uqshrn";
3062 nfd.SetFormatMap(1, &map_shift_narrow);
3064 case NEON_UQRSHRN_scalar:
3065 mnemonic =
"uqrshrn";
3066 nfd.SetFormatMap(1, &map_shift_narrow);
3068 case NEON_SQSHRN_scalar:
3069 mnemonic =
"sqshrn";
3070 nfd.SetFormatMap(1, &map_shift_narrow);
3072 case NEON_SQRSHRN_scalar:
3073 mnemonic =
"sqrshrn";
3074 nfd.SetFormatMap(1, &map_shift_narrow);
3076 case NEON_SQSHRUN_scalar:
3077 mnemonic =
"sqshrun";
3078 nfd.SetFormatMap(1, &map_shift_narrow);
3080 case NEON_SQRSHRUN_scalar:
3081 mnemonic =
"sqrshrun";
3082 nfd.SetFormatMap(1, &map_shift_narrow);
3085 form =
"(NEONScalarShiftImmediate)";
3088 form =
"(NEONScalarShiftImmediate)";
3090 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
3093 void DisassemblingDecoder::VisitNEONShiftImmediate(Instruction* instr) {
3094 const char* mnemonic =
"unimplemented";
3095 const char* form =
"'Vd.%s, 'Vn.%s, 'Is1";
3096 const char* form_shift_2 =
"'Vd.%s, 'Vn.%s, 'Is2";
3097 const char* form_xtl =
"'Vd.%s, 'Vn.%s";
3100 static const NEONFormatMap map_shift_ta = {
3102 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
3106 static const NEONFormatMap map_shift_tb = {
3107 {22, 21, 20, 19, 30},
3108 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H, NF_8H,
3109 NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S,
3110 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
3111 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
3113 NEONFormatDecoder nfd(instr, &map_shift_tb);
3115 if (instr->ImmNEONImmh()) {
3116 switch (instr->Mask(NEONShiftImmediateMask)) {
3118 mnemonic =
"sqshlu";
3119 form = form_shift_2;
3121 case NEON_SQSHL_imm:
3123 form = form_shift_2;
3125 case NEON_UQSHL_imm:
3127 form = form_shift_2;
3131 form = form_shift_2;
3135 form = form_shift_2;
3137 case NEON_SCVTF_imm:
3140 case NEON_UCVTF_imm:
3143 case NEON_FCVTZU_imm:
3144 mnemonic =
"fcvtzu";
3146 case NEON_FCVTZS_imm:
3147 mnemonic =
"fcvtzs";
3177 mnemonic = instr->Mask(NEON_Q) ?
"shrn2" :
"shrn";
3178 nfd.SetFormatMap(1, &map_shift_ta);
3181 mnemonic = instr->Mask(NEON_Q) ?
"rshrn2" :
"rshrn";
3182 nfd.SetFormatMap(1, &map_shift_ta);
3185 mnemonic = instr->Mask(NEON_Q) ?
"uqshrn2" :
"uqshrn";
3186 nfd.SetFormatMap(1, &map_shift_ta);
3189 mnemonic = instr->Mask(NEON_Q) ?
"uqrshrn2" :
"uqrshrn";
3190 nfd.SetFormatMap(1, &map_shift_ta);
3193 mnemonic = instr->Mask(NEON_Q) ?
"sqshrn2" :
"sqshrn";
3194 nfd.SetFormatMap(1, &map_shift_ta);
3197 mnemonic = instr->Mask(NEON_Q) ?
"sqrshrn2" :
"sqrshrn";
3198 nfd.SetFormatMap(1, &map_shift_ta);
3201 mnemonic = instr->Mask(NEON_Q) ?
"sqshrun2" :
"sqshrun";
3202 nfd.SetFormatMap(1, &map_shift_ta);
3205 mnemonic = instr->Mask(NEON_Q) ?
"sqrshrun2" :
"sqrshrun";
3206 nfd.SetFormatMap(1, &map_shift_ta);
3209 nfd.SetFormatMap(0, &map_shift_ta);
3210 if (instr->ImmNEONImmb() == 0 &&
3211 CountSetBits(instr->ImmNEONImmh(), 32) == 1) {
3213 mnemonic = instr->Mask(NEON_Q) ?
"sxtl2" :
"sxtl";
3215 form = form_shift_2;
3216 mnemonic = instr->Mask(NEON_Q) ?
"sshll2" :
"sshll";
3220 nfd.SetFormatMap(0, &map_shift_ta);
3221 if (instr->ImmNEONImmb() == 0 &&
3222 CountSetBits(instr->ImmNEONImmh(), 32) == 1) {
3224 mnemonic = instr->Mask(NEON_Q) ?
"uxtl2" :
"uxtl";
3226 form = form_shift_2;
3227 mnemonic = instr->Mask(NEON_Q) ?
"ushll2" :
"ushll";
3231 form =
"(NEONShiftImmediate)";
3234 form =
"(NEONShiftImmediate)";
3236 Format(instr, mnemonic, nfd.Substitute(form));
3239 void DisassemblingDecoder::VisitNEONTable(Instruction* instr) {
3240 const char* mnemonic =
"unimplemented";
3241 const char* form =
"(NEONTable)";
3242 const char form_1v[] =
"'Vd.%%s, {'Vn.16b}, 'Vm.%%s";
3243 const char form_2v[] =
"'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s";
3244 const char form_3v[] =
"'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
3245 const char form_4v[] =
3246 "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
3247 static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
3248 NEONFormatDecoder nfd(instr, &map_b);
3250 switch (instr->Mask(NEONTableMask)) {
3287 char re_form[
sizeof(form_4v)];
3288 int reg_num = instr->Rn();
3289 snprintf(re_form,
sizeof(re_form), form, (reg_num + 1) % kNumberOfVRegisters,
3290 (reg_num + 2) % kNumberOfVRegisters,
3291 (reg_num + 3) % kNumberOfVRegisters);
3293 Format(instr, mnemonic, nfd.Substitute(re_form));
3296 void DisassemblingDecoder::VisitUnimplemented(Instruction* instr) {
3297 Format(instr,
"unimplemented",
"(Unimplemented)");
3300 void DisassemblingDecoder::VisitUnallocated(Instruction* instr) {
3301 Format(instr,
"unallocated",
"(Unallocated)");
3304 void DisassemblingDecoder::ProcessOutput(Instruction* ) {
3308 void DisassemblingDecoder::AppendRegisterNameToOutput(
const CPURegister& reg) {
3309 DCHECK(reg.IsValid());
3312 if (reg.IsRegister()) {
3313 reg_char = reg.Is64Bits() ?
'x' :
'w';
3315 DCHECK(reg.IsVRegister());
3316 switch (reg.SizeInBits()) {
3317 case kBRegSizeInBits:
3320 case kHRegSizeInBits:
3323 case kSRegSizeInBits:
3326 case kDRegSizeInBits:
3330 DCHECK(reg.Is128Bits());
3335 if (reg.IsVRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
3337 if (reg.IsX() && (reg.code() == 27)) {
3338 AppendToOutput(
"cp");
3339 }
else if (reg.IsX() && (reg.code() == 29)) {
3340 AppendToOutput(
"fp");
3341 }
else if (reg.IsX() && (reg.code() == 30)) {
3342 AppendToOutput(
"lr");
3345 AppendToOutput(
"%c%d", reg_char, reg.code());
3347 }
else if (reg.Aliases(sp)) {
3349 AppendToOutput(
"%s", reg.Is64Bits() ?
"sp" :
"wsp");
3352 AppendToOutput(
"%czr", reg_char);
3356 void DisassemblingDecoder::Format(Instruction* instr,
const char* mnemonic,
3357 const char* format) {
3360 DCHECK_NOT_NULL(mnemonic);
3362 Substitute(instr, mnemonic);
3363 if (format !=
nullptr) {
3364 buffer_[buffer_pos_++] =
' ';
3365 Substitute(instr, format);
3367 buffer_[buffer_pos_] = 0;
3368 ProcessOutput(instr);
3371 void DisassemblingDecoder::Substitute(Instruction* instr,
const char*
string) {
3372 char chr = *
string++;
3373 while (chr !=
'\0') {
3375 string += SubstituteField(instr,
string);
3377 buffer_[buffer_pos_++] = chr;
3383 int DisassemblingDecoder::SubstituteField(Instruction* instr,
3384 const char* format) {
3385 switch (format[0]) {
3397 return SubstituteRegisterField(instr, format);
3399 return SubstituteImmediateField(instr, format);
3401 return SubstituteLiteralField(instr, format);
3403 return SubstituteShiftField(instr, format);
3405 return SubstitutePrefetchField(instr, format);
3407 return SubstituteConditionField(instr, format);
3409 return SubstituteExtendField(instr, format);
3411 return SubstitutePCRelAddressField(instr, format);
3413 return SubstituteBranchTargetField(instr, format);
3415 return SubstituteLSRegOffsetField(instr, format);
3417 return SubstituteBarrierField(instr, format);
3423 int DisassemblingDecoder::SubstituteRegisterField(Instruction* instr,
3424 const char* format) {
3425 char reg_prefix = format[0];
3426 unsigned reg_num = 0;
3427 unsigned field_len = 2;
3429 switch (format[1]) {
3431 reg_num = instr->Rd();
3432 if (format[2] ==
'q') {
3433 reg_prefix = instr->NEONQ() ?
'X' :
'W';
3438 reg_num = instr->Rn();
3441 reg_num = instr->Rm();
3442 switch (format[2]) {
3451 int imm =
static_cast<int>(strtol(&format[3], &eimm, 10));
3452 field_len += eimm - &format[3];
3453 if (reg_num == 31) {
3454 switch (format[2]) {
3456 imm *= (1 << instr->NEONLSSize());
3459 imm *= (instr->NEONQ() == 0) ? kDRegSize : kQRegSize;
3464 AppendToOutput(
"#%d", imm);
3474 reg_num = (instr->Rm() & 0xF);
3477 reg_num = instr->Ra();
3480 reg_num = instr->Rt();
3481 if (format[0] ==
'V') {
3482 if ((format[2] >=
'2') && (format[2] <=
'4')) {
3484 reg_num = (reg_num + format[2] -
'1') % 32;
3488 if (format[2] ==
'2') {
3490 reg_num = instr->Rt2();
3496 reg_num = instr->Rs();
3503 if (format[2] ==
's') {
3507 CPURegister::RegisterType reg_type;
3510 if (reg_prefix ==
'R') {
3511 reg_prefix = instr->SixtyFourBits() ?
'X' :
'W';
3512 }
else if (reg_prefix ==
'F') {
3513 reg_prefix = ((instr->FPType() & 1) == 0) ?
'S' :
'D';
3516 switch (reg_prefix) {
3518 reg_type = CPURegister::kRegister;
3519 reg_size = kWRegSizeInBits;
3522 reg_type = CPURegister::kRegister;
3523 reg_size = kXRegSizeInBits;
3526 reg_type = CPURegister::kVRegister;
3527 reg_size = kBRegSizeInBits;
3530 reg_type = CPURegister::kVRegister;
3531 reg_size = kHRegSizeInBits;
3534 reg_type = CPURegister::kVRegister;
3535 reg_size = kSRegSizeInBits;
3538 reg_type = CPURegister::kVRegister;
3539 reg_size = kDRegSizeInBits;
3542 reg_type = CPURegister::kVRegister;
3543 reg_size = kQRegSizeInBits;
3546 AppendToOutput(
"v%d", reg_num);
3552 if ((reg_type == CPURegister::kRegister) && (reg_num == kZeroRegCode) &&
3553 (format[2] ==
's')) {
3554 reg_num = kSPRegInternalCode;
3557 AppendRegisterNameToOutput(CPURegister::Create(reg_num, reg_size, reg_type));
3562 int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr,
3563 const char* format) {
3564 DCHECK_EQ(format[0],
'I');
3566 switch (format[1]) {
3568 if (format[5] ==
'I' || format[5] ==
'N') {
3569 uint64_t imm =
static_cast<uint64_t
>(instr->ImmMoveWide())
3570 << (16 * instr->ShiftMoveWide());
3571 if (format[5] ==
'N') imm = ~imm;
3572 if (!instr->SixtyFourBits()) imm &= UINT64_C(0xFFFFFFFF);
3573 AppendToOutput(
"#0x%" PRIx64, imm);
3575 DCHECK_EQ(format[5],
'L');
3576 AppendToOutput(
"#0x%" PRIx64, instr->ImmMoveWide());
3577 if (instr->ShiftMoveWide() > 0) {
3578 AppendToOutput(
", lsl #%d", 16 * instr->ShiftMoveWide());
3584 switch (format[2]) {
3586 AppendToOutput(
"pc%+" PRId32, instr->ImmLLiteral()
3587 << kLoadLiteralScaleLog2);
3591 if (instr->ImmLS() != 0) {
3592 AppendToOutput(
", #%" PRId32, instr->ImmLS());
3597 if (instr->ImmLSPair() != 0) {
3599 int scale = 1 << (format[3] -
'0');
3600 AppendToOutput(
", #%" PRId32, instr->ImmLSPair() * scale);
3605 if (instr->ImmLSUnsigned() != 0) {
3606 int shift = instr->SizeLS();
3607 AppendToOutput(
", #%" PRId32, instr->ImmLSUnsigned() << shift);
3614 int64_t offset = instr->ImmCondBranch() << 2;
3615 char sign = (offset >= 0) ?
'+' :
'-';
3616 AppendToOutput(
"#%c0x%" PRIx64, sign, offset);
3620 DCHECK_LE(instr->ShiftAddSub(), 1);
3621 int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
3622 AppendToOutput(
"#0x%" PRIx64
" (%" PRId64
")", imm, imm);
3626 if (format[3] ==
'F') {
3627 AppendToOutput(
"#%d", 64 - instr->FPScale());
3630 AppendToOutput(
"#0x%" PRIx32
" (%.4f)", instr->ImmFP(),
3631 format[3] ==
'S' ? instr->ImmFP32() : instr->ImmFP64());
3636 AppendToOutput(
"#0x%" PRIx64, instr->ImmLogical());
3640 int nzcv = (instr->Nzcv() << Flags_offset);
3641 AppendToOutput(
"#%c%c%c%c", ((nzcv & NFlag) == 0) ?
'n' :
'N',
3642 ((nzcv & ZFlag) == 0) ?
'z' :
'Z',
3643 ((nzcv & CFlag) == 0) ?
'c' :
'C',
3644 ((nzcv & VFlag) == 0) ?
'v' :
'V');
3648 AppendToOutput(
"#%d", instr->ImmCondCmp());
3652 return SubstituteBitfieldImmediateField(instr, format);
3655 AppendToOutput(
"#%d", instr->ImmS());
3659 AppendToOutput(
"#%d", (instr->ImmTestBranchBit5() << 5) |
3660 instr->ImmTestBranchBit40());
3664 switch (format[2]) {
3666 int shift = 16 << HighestSetBitPosition(instr->ImmNEONImmh());
3667 shift -= instr->ImmNEONImmhImmb();
3668 AppendToOutput(
"#%d", shift);
3672 int shift = instr->ImmNEONImmhImmb();
3673 shift -= 8 << HighestSetBitPosition(instr->ImmNEONImmh());
3674 AppendToOutput(
"#%d", shift);
3684 AppendToOutput(
"#0x%x", instr->ImmException());
3688 switch (format[2]) {
3690 AppendToOutput(
"#%" PRId64, instr->ImmNEONExt());
3694 int vm_index = (instr->NEONH() << 1) | instr->NEONL();
3695 if (instr->NEONSize() == 1) {
3696 vm_index = (vm_index << 1) | instr->NEONM();
3698 AppendToOutput(
"%d", vm_index);
3699 return static_cast<int>(strlen(
"IVByElemIndex"));
3702 if (strncmp(format,
"IVInsIndex", strlen(
"IVInsIndex")) == 0) {
3703 unsigned rd_index, rn_index;
3704 unsigned imm5 = instr->ImmNEON5();
3705 unsigned imm4 = instr->ImmNEON4();
3706 int tz = CountTrailingZeros(imm5, 32);
3708 rd_index = imm5 >> (tz + 1);
3709 rn_index = imm4 >> tz;
3710 if (strncmp(format,
"IVInsIndex1", strlen(
"IVInsIndex1")) == 0) {
3711 AppendToOutput(
"%d", rd_index);
3712 return static_cast<int>(strlen(
"IVInsIndex1"));
3713 }
else if (strncmp(format,
"IVInsIndex2",
3714 strlen(
"IVInsIndex2")) == 0) {
3715 AppendToOutput(
"%d", rn_index);
3716 return static_cast<int>(strlen(
"IVInsIndex2"));
3725 AppendToOutput(
"%d", instr->NEONLSIndex(format[8] -
'0'));
3729 if (strncmp(format,
"IVMIImmFPSingle", strlen(
"IVMIImmFPSingle")) ==
3731 AppendToOutput(
"#0x%" PRIx32
" (%.4f)", instr->ImmNEONabcdefgh(),
3732 instr->ImmNEONFP32());
3733 return static_cast<int>(strlen(
"IVMIImmFPSingle"));
3734 }
else if (strncmp(format,
"IVMIImmFPDouble",
3735 strlen(
"IVMIImmFPDouble")) == 0) {
3736 AppendToOutput(
"#0x%" PRIx32
" (%.4f)", instr->ImmNEONabcdefgh(),
3737 instr->ImmNEONFP64());
3738 return static_cast<int>(strlen(
"IVMIImmFPDouble"));
3739 }
else if (strncmp(format,
"IVMIImm8", strlen(
"IVMIImm8")) == 0) {
3740 uint64_t imm8 = instr->ImmNEONabcdefgh();
3741 AppendToOutput(
"#0x%" PRIx64, imm8);
3742 return static_cast<int>(strlen(
"IVMIImm8"));
3743 }
else if (strncmp(format,
"IVMIImm", strlen(
"IVMIImm")) == 0) {
3744 uint64_t imm8 = instr->ImmNEONabcdefgh();
3746 for (
int i = 0;
i < 8; ++
i) {
3747 if (imm8 & (1ULL <<
i)) {
3748 imm |= (UINT64_C(0xFF) << (8 *
i));
3751 AppendToOutput(
"#0x%" PRIx64, imm);
3752 return static_cast<int>(strlen(
"IVMIImm"));
3753 }
else if (strncmp(format,
"IVMIShiftAmt1",
3754 strlen(
"IVMIShiftAmt1")) == 0) {
3755 int cmode = instr->NEONCmode();
3756 int shift_amount = 8 * ((cmode >> 1) & 3);
3757 AppendToOutput(
"#%d", shift_amount);
3758 return static_cast<int>(strlen(
"IVMIShiftAmt1"));
3759 }
else if (strncmp(format,
"IVMIShiftAmt2",
3760 strlen(
"IVMIShiftAmt2")) == 0) {
3761 int cmode = instr->NEONCmode();
3762 int shift_amount = 8 << (cmode & 1);
3763 AppendToOutput(
"#%d", shift_amount);
3764 return static_cast<int>(strlen(
"IVMIShiftAmt2"));
3777 printf(
"%s", format);
3784 int DisassemblingDecoder::SubstituteBitfieldImmediateField(Instruction* instr,
3785 const char* format) {
3786 DCHECK((format[0] ==
'I') && (format[1] ==
'B'));
3787 unsigned r = instr->ImmR();
3788 unsigned s = instr->ImmS();
3790 switch (format[2]) {
3792 AppendToOutput(
"#%d", r);
3796 if (format[3] ==
'+') {
3797 AppendToOutput(
"#%d", s + 1);
3800 DCHECK_EQ(format[3],
'-');
3801 AppendToOutput(
"#%d", s - r + 1);
3806 DCHECK((format[3] ==
'-') && (format[4] ==
'r'));
3807 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
3809 AppendToOutput(
"#%d", reg_size - r);
3819 int DisassemblingDecoder::SubstituteLiteralField(Instruction* instr,
3820 const char* format) {
3821 DCHECK_EQ(strncmp(format,
"LValue", 6), 0);
3824 switch (instr->Mask(LoadLiteralMask)) {
3829 AppendToOutput(
"(addr 0x%016" PRIxPTR
")", instr->LiteralAddress());
3831 default: UNREACHABLE();
3838 int DisassemblingDecoder::SubstituteShiftField(Instruction* instr,
3839 const char* format) {
3840 DCHECK_EQ(format[0],
'N');
3841 DCHECK_LE(instr->ShiftDP(), 0x3);
3843 switch (format[1]) {
3845 DCHECK(instr->ShiftDP() != ROR);
3849 if (instr->ImmDPShift() != 0) {
3850 const char* shift_type[] = {
"lsl",
"lsr",
"asr",
"ror"};
3851 AppendToOutput(
", %s #%" PRId32, shift_type[instr->ShiftDP()],
3852 instr->ImmDPShift());
3862 int DisassemblingDecoder::SubstituteConditionField(Instruction* instr,
3863 const char* format) {
3864 DCHECK_EQ(format[0],
'C');
3865 const char* condition_code[] = {
"eq",
"ne",
"hs",
"lo",
3866 "mi",
"pl",
"vs",
"vc",
3867 "hi",
"ls",
"ge",
"lt",
3868 "gt",
"le",
"al",
"nv" };
3870 switch (format[1]) {
3871 case 'B': cond = instr->ConditionBranch();
break;
3873 cond = NegateCondition(static_cast<Condition>(instr->Condition()));
3876 default: cond = instr->Condition();
3878 AppendToOutput(
"%s", condition_code[cond]);
3883 int DisassemblingDecoder::SubstitutePCRelAddressField(Instruction* instr,
3884 const char* format) {
3886 DCHECK_EQ(strncmp(format,
"AddrPCRel", 9), 0);
3888 int offset = instr->ImmPCRel();
3891 DCHECK_EQ(strcmp(format,
"AddrPCRelByte"), 0);
3897 AppendToOutput(
"#%c0x%x (addr %p)", sign, Abs(offset),
3898 instr->InstructionAtOffset(offset, Instruction::NO_CHECK));
3903 int DisassemblingDecoder::SubstituteBranchTargetField(Instruction* instr,
3904 const char* format) {
3905 DCHECK_EQ(strncmp(format,
"TImm", 4), 0);
3908 switch (format[5]) {
3910 case 'n': offset = instr->ImmUncondBranch();
break;
3912 case 'o': offset = instr->ImmCondBranch();
break;
3914 case 'm': offset = instr->ImmCmpBranch();
break;
3916 case 'e': offset = instr->ImmTestBranch();
break;
3917 default: UNREACHABLE();
3919 offset <<= kInstrSizeLog2;
3924 AppendToOutput(
"#%c0x%" PRIx64
" (addr %p)", sign, Abs(offset),
3925 instr->InstructionAtOffset(offset), Instruction::NO_CHECK);
3930 int DisassemblingDecoder::SubstituteExtendField(Instruction* instr,
3931 const char* format) {
3932 DCHECK_EQ(strncmp(format,
"Ext", 3), 0);
3933 DCHECK_LE(instr->ExtendMode(), 7);
3936 const char* extend_mode[] = {
"uxtb",
"uxth",
"uxtw",
"uxtx",
3937 "sxtb",
"sxth",
"sxtw",
"sxtx" };
3941 if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
3942 (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
3943 (instr->ExtendMode() == UXTX))) {
3944 if (instr->ImmExtendShift() > 0) {
3945 AppendToOutput(
", lsl #%d", instr->ImmExtendShift());
3948 AppendToOutput(
", %s", extend_mode[instr->ExtendMode()]);
3949 if (instr->ImmExtendShift() > 0) {
3950 AppendToOutput(
" #%d", instr->ImmExtendShift());
3957 int DisassemblingDecoder::SubstituteLSRegOffsetField(Instruction* instr,
3958 const char* format) {
3959 DCHECK_EQ(strncmp(format,
"Offsetreg", 9), 0);
3960 const char* extend_mode[] = {
"undefined",
"undefined",
"uxtw",
"lsl",
3961 "undefined",
"undefined",
"sxtw",
"sxtx" };
3964 unsigned shift = instr->ImmShiftLS();
3965 Extend ext =
static_cast<Extend
>(instr->ExtendMode());
3966 char reg_type = ((ext == UXTW) || (ext == SXTW)) ?
'w' :
'x';
3968 unsigned rm = instr->Rm();
3969 if (rm == kZeroRegCode) {
3970 AppendToOutput(
"%czr", reg_type);
3972 AppendToOutput(
"%c%d", reg_type, rm);
3976 if (!((ext == UXTX) && (shift == 0))) {
3977 AppendToOutput(
", %s", extend_mode[ext]);
3979 AppendToOutput(
" #%d", instr->SizeLS());
3986 int DisassemblingDecoder::SubstitutePrefetchField(Instruction* instr,
3987 const char* format) {
3988 DCHECK_EQ(format[0],
'P');
3991 int prefetch_mode = instr->PrefetchMode();
3993 const char* ls = (prefetch_mode & 0x10) ?
"st" :
"ld";
3994 int level = (prefetch_mode >> 1) + 1;
3995 const char* ks = (prefetch_mode & 1) ?
"strm" :
"keep";
3997 AppendToOutput(
"p%sl%d%s", ls, level, ks);
4001 int DisassemblingDecoder::SubstituteBarrierField(Instruction* instr,
4002 const char* format) {
4003 DCHECK_EQ(format[0],
'M');
4006 static const char*
const options[4][4] = {
4007 {
"sy (0b0000)",
"oshld",
"oshst",
"osh" },
4008 {
"sy (0b0100)",
"nshld",
"nshst",
"nsh" },
4009 {
"sy (0b1000)",
"ishld",
"ishst",
"ish" },
4010 {
"sy (0b1100)",
"ld",
"st",
"sy" }
4012 int domain = instr->ImmBarrierDomain();
4013 int type = instr->ImmBarrierType();
4015 AppendToOutput(
"%s", options[domain][type]);
4020 void DisassemblingDecoder::ResetOutput() {
4022 buffer_[buffer_pos_] = 0;
4026 void DisassemblingDecoder::AppendToOutput(
const char* format, ...) {
4028 va_start(args, format);
4029 buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args);
4034 void PrintDisassembler::ProcessOutput(Instruction* instr) {
4035 fprintf(stream_,
"0x%016" PRIx64
" %08" PRIx32
"\t\t%s\n",
4036 reinterpret_cast<uint64_t>(instr), instr->InstructionBits(),
4047 const char* NameConverter::NameOfAddress(byte* addr)
const {
4048 v8::internal::SNPrintF(tmp_buffer_,
"%p", static_cast<void *>(addr));
4049 return tmp_buffer_.start();
4053 const char* NameConverter::NameOfConstant(byte* addr)
const {
4054 return NameOfAddress(addr);
4058 const char* NameConverter::NameOfCPURegister(
int reg)
const {
4059 unsigned ureg = reg;
4060 if (ureg >= v8::internal::kNumberOfRegisters) {
4063 if (ureg == v8::internal::kZeroRegCode) {
4066 v8::internal::SNPrintF(tmp_buffer_,
"x%u", ureg);
4067 return tmp_buffer_.start();
4071 const char* NameConverter::NameOfByteCPURegister(
int reg)
const {
4077 const char* NameConverter::NameOfXMMRegister(
int reg)
const {
4083 const char* NameConverter::NameInCode(byte* addr)
const {
4095 : out_buffer_(out_buffer) { }
4097 ~BufferDisassembler() { }
4100 v8::internal::SNPrintF(out_buffer_,
"%08" PRIx32
" %s",
4101 instr->InstructionBits(), GetOutput());
4112 BufferDisassembler
disasm(buffer);
4113 decoder.AppendVisitor(&
disasm);
4115 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(instr));
4116 return v8::internal::kInstrSize;
4120 int Disassembler::ConstantPoolSizeAt(byte* instr) {
4121 return v8::internal::Assembler::ConstantPoolSizeAt(
4122 reinterpret_cast<v8::internal::Instruction*>(instr));
4125 void Disassembler::Disassemble(FILE* file, byte* start, byte* end,
4126 UnimplementedOpcodeAction) {
4129 decoder.AppendVisitor(&
disasm);
4131 for (byte* pc = start; pc < end; pc += v8::internal::kInstrSize) {
4132 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc));
4138 #endif // V8_TARGET_ARCH_ARM64