35 #if V8_TARGET_ARCH_ARM64
75 void Disassembler::VisitAddSubImmediate(Instruction* instr) {
77 bool stack_op = (rd_is_zr ||
RnIsZROrSP(instr)) &&
78 (instr->ImmAddSub() == 0) ?
true :
false;
79 const char *mnemonic =
"";
80 const char *form =
"'Rds, 'Rns, 'IAddSub";
81 const char *form_cmp =
"'Rns, 'IAddSub";
82 const char *form_mov =
"'Rds, 'Rns";
104 case SUB_x_imm: mnemonic =
"sub";
break;
116 Format(instr, mnemonic, form);
120 void Disassembler::VisitAddSubShifted(Instruction* instr) {
123 const char *mnemonic =
"";
124 const char *form =
"'Rd, 'Rn, 'Rm'HDP";
125 const char *form_cmp =
"'Rn, 'Rm'HDP";
126 const char *form_neg =
"'Rd, 'Rm'HDP";
130 case ADD_x_shift: mnemonic =
"add";
break;
155 }
else if (rn_is_zr) {
163 Format(instr, mnemonic, form);
167 void Disassembler::VisitAddSubExtended(Instruction* instr) {
169 const char *mnemonic =
"";
171 const char *form = ((mode ==
UXTX) || (mode ==
SXTX)) ?
172 "'Rds, 'Rns, 'Xm'Ext" :
"'Rds, 'Rns, 'Wm'Ext";
173 const char *form_cmp = ((mode ==
UXTX) || (mode ==
SXTX)) ?
174 "'Rns, 'Xm'Ext" :
"'Rns, 'Wm'Ext";
178 case ADD_x_ext: mnemonic =
"add";
break;
189 case SUB_x_ext: mnemonic =
"sub";
break;
201 Format(instr, mnemonic, form);
205 void Disassembler::VisitAddSubWithCarry(Instruction* instr) {
207 const char *mnemonic =
"";
208 const char *form =
"'Rd, 'Rn, 'Rm";
209 const char *form_neg =
"'Rd, 'Rm";
213 case ADC_x: mnemonic =
"adc";
break;
215 case ADCS_x: mnemonic =
"adcs";
break;
236 Format(instr, mnemonic, form);
240 void Disassembler::VisitLogicalImmediate(Instruction* instr) {
243 const char *mnemonic =
"";
244 const char *form =
"'Rds, 'Rn, 'ITri";
246 if (instr->ImmLogical() == 0) {
248 Format(instr,
"unallocated",
"(LogicalImmediate)");
260 if (rn_is_zr && !
IsMovzMovnImm(reg_size, instr->ImmLogical())) {
262 form =
"'Rds, 'ITri";
279 Format(instr, mnemonic, form);
288 if (((value & 0xffffffffffff0000UL) == 0UL) ||
289 ((value & 0xffffffff0000ffffUL) == 0UL) ||
290 ((value & 0xffff0000ffffffffUL) == 0UL) ||
291 ((value & 0x0000ffffffffffffUL) == 0UL)) {
297 (((value & 0xffffffffffff0000UL) == 0xffffffffffff0000UL) ||
298 ((value & 0xffffffff0000ffffUL) == 0xffffffff0000ffffUL) ||
299 ((value & 0xffff0000ffffffffUL) == 0xffff0000ffffffffUL) ||
300 ((value & 0x0000ffffffffffffUL) == 0x0000ffffffffffffUL))) {
304 (((value & 0xffff0000) == 0xffff0000) ||
305 ((value & 0x0000ffff) == 0x0000ffff))) {
312 void Disassembler::VisitLogicalShifted(Instruction* instr) {
315 const char *mnemonic =
"";
316 const char *form =
"'Rd, 'Rn, 'Rm'HLo";
320 case AND_x: mnemonic =
"and";
break;
322 case BIC_x: mnemonic =
"bic";
break;
324 case EOR_x: mnemonic =
"eor";
break;
326 case EON_x: mnemonic =
"eon";
break;
328 case BICS_x: mnemonic =
"bics";
break;
334 form =
"'Rn, 'Rm'HLo";
341 if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() ==
LSL)) {
352 form =
"'Rd, 'Rm'HLo";
359 Format(instr, mnemonic, form);
363 void Disassembler::VisitConditionalCompareRegister(Instruction* instr) {
364 const char *mnemonic =
"";
365 const char *form =
"'Rn, 'Rm, 'INzcv, 'Cond";
369 case CCMN_x: mnemonic =
"ccmn";
break;
371 case CCMP_x: mnemonic =
"ccmp";
break;
374 Format(instr, mnemonic, form);
378 void Disassembler::VisitConditionalCompareImmediate(Instruction* instr) {
379 const char *mnemonic =
"";
380 const char *form =
"'Rn, 'IP, 'INzcv, 'Cond";
389 Format(instr, mnemonic, form);
393 void Disassembler::VisitConditionalSelect(Instruction* instr) {
395 bool rn_is_rm = (instr->Rn() == instr->Rm());
396 const char *mnemonic =
"";
397 const char *form =
"'Rd, 'Rn, 'Rm, 'Cond";
398 const char *form_test =
"'Rd, 'CInv";
399 const char *form_update =
"'Rd, 'Rn, 'CInv";
402 bool invertible_cond = (cond !=
al) && (cond !=
nv);
406 case CSEL_x: mnemonic =
"csel";
break;
410 if (rnm_is_zr && invertible_cond) {
413 }
else if (rn_is_rm && invertible_cond) {
422 if (rnm_is_zr && invertible_cond) {
425 }
else if (rn_is_rm && invertible_cond) {
434 if (rn_is_rm && invertible_cond) {
442 Format(instr, mnemonic, form);
446 void Disassembler::VisitBitfield(Instruction* instr) {
447 unsigned s = instr->ImmS();
448 unsigned r = instr->ImmR();
449 unsigned rd_size_minus_1 =
451 const char *mnemonic =
"";
452 const char *form =
"";
453 const char *form_shift_right =
"'Rd, 'Rn, 'IBr";
454 const char *form_extend =
"'Rd, 'Wn";
455 const char *form_bfiz =
"'Rd, 'Rn, 'IBZ-r, 'IBs+1";
456 const char *form_bfx =
"'Rd, 'Rn, 'IBr, 'IBs-r+1";
457 const char *form_lsl =
"'Rd, 'Rn, 'IBZ-r";
468 }
else if (s == 15) {
470 }
else if ((s == 31) && (instr->SixtyFourBits() == 1)) {
475 }
else if (s == rd_size_minus_1) {
477 form = form_shift_right;
492 }
else if (s == 15) {
498 if (s == rd_size_minus_1) {
500 form = form_shift_right;
501 }
else if (r == s + 1) {
520 Format(instr, mnemonic, form);
524 void Disassembler::VisitExtract(Instruction* instr) {
525 const char *mnemonic =
"";
526 const char *form =
"'Rd, 'Rn, 'Rm, 'IExtract";
531 if (instr->Rn() == instr->Rm()) {
533 form =
"'Rd, 'Rn, 'IExtract";
541 Format(instr, mnemonic, form);
545 void Disassembler::VisitPCRelAddressing(Instruction* instr) {
547 case ADR:
Format(instr,
"adr",
"'Xd, 'AddrPCRelByte");
break;
549 default:
Format(instr,
"unimplemented",
"(PCRelAddressing)");
554 void Disassembler::VisitConditionalBranch(Instruction* instr) {
556 case B_cond:
Format(instr,
"b.'CBrn",
"'BImmCond");
break;
562 void Disassembler::VisitUnconditionalBranchToRegister(Instruction* instr) {
563 const char *mnemonic =
"unimplemented";
564 const char *form =
"'Xn";
567 case BR: mnemonic =
"br";
break;
568 case BLR: mnemonic =
"blr";
break;
576 default: form =
"(UnconditionalBranchToRegister)";
578 Format(instr, mnemonic, form);
582 void Disassembler::VisitUnconditionalBranch(Instruction* instr) {
583 const char *mnemonic =
"";
584 const char *form =
"'BImmUncn";
587 case B: mnemonic =
"b";
break;
588 case BL: mnemonic =
"bl";
break;
591 Format(instr, mnemonic, form);
595 void Disassembler::VisitDataProcessing1Source(Instruction* instr) {
596 const char *mnemonic =
"";
597 const char *form =
"'Rd, 'Rn";
600 #define FORMAT(A, B) \
602 case A##_x: mnemonic = B; break;
603 FORMAT(
RBIT,
"rbit");
604 FORMAT(
REV16,
"rev16");
609 case REV32_x: mnemonic =
"rev32";
break;
612 Format(instr, mnemonic, form);
616 void Disassembler::VisitDataProcessing2Source(Instruction* instr) {
617 const char *mnemonic =
"unimplemented";
618 const char *form =
"'Rd, 'Rn, 'Rm";
621 #define FORMAT(A, B) \
623 case A##_x: mnemonic = B; break;
624 FORMAT(
UDIV,
"udiv");
625 FORMAT(
SDIV,
"sdiv");
631 default: form =
"(DataProcessing2Source)";
633 Format(instr, mnemonic, form);
637 void Disassembler::VisitDataProcessing3Source(Instruction* instr) {
639 const char *mnemonic =
"";
640 const char *form =
"'Xd, 'Wn, 'Wm, 'Xa";
641 const char *form_rrr =
"'Rd, 'Rn, 'Rm";
642 const char *form_rrrr =
"'Rd, 'Rn, 'Rm, 'Ra";
643 const char *form_xww =
"'Xd, 'Wn, 'Wm";
644 const char *form_xxx =
"'Xd, 'Xn, 'Xm";
711 Format(instr, mnemonic, form);
715 void Disassembler::VisitCompareBranch(Instruction* instr) {
716 const char *mnemonic =
"";
717 const char *form =
"'Rt, 'BImmCmpa";
721 case CBZ_x: mnemonic =
"cbz";
break;
723 case CBNZ_x: mnemonic =
"cbnz";
break;
726 Format(instr, mnemonic, form);
730 void Disassembler::VisitTestBranch(Instruction* instr) {
731 const char *mnemonic =
"";
736 const char *form =
"'Rt, 'IS, 'BImmTest";
739 case TBZ: mnemonic =
"tbz";
break;
740 case TBNZ: mnemonic =
"tbnz";
break;
743 Format(instr, mnemonic, form);
747 void Disassembler::VisitMoveWideImmediate(Instruction* instr) {
748 const char *mnemonic =
"";
749 const char *form =
"'Rd, 'IMoveImm";
756 case MOVN_x: mnemonic =
"movn";
break;
758 case MOVZ_x: mnemonic =
"movz";
break;
760 case MOVK_x: mnemonic =
"movk"; form =
"'Rd, 'IMoveLSL";
break;
763 Format(instr, mnemonic, form);
767 #define LOAD_STORE_LIST(V) \
768 V(STRB_w, "strb", "'Wt") \
769 V(STRH_w, "strh", "'Wt") \
770 V(STR_w, "str", "'Wt") \
771 V(STR_x, "str", "'Xt") \
772 V(LDRB_w, "ldrb", "'Wt") \
773 V(LDRH_w, "ldrh", "'Wt") \
774 V(LDR_w, "ldr", "'Wt") \
775 V(LDR_x, "ldr", "'Xt") \
776 V(LDRSB_x, "ldrsb", "'Xt") \
777 V(LDRSH_x, "ldrsh", "'Xt") \
778 V(LDRSW_x, "ldrsw", "'Xt") \
779 V(LDRSB_w, "ldrsb", "'Wt") \
780 V(LDRSH_w, "ldrsh", "'Wt") \
781 V(STR_s, "str", "'St") \
782 V(STR_d, "str", "'Dt") \
783 V(LDR_s, "ldr", "'St") \
784 V(LDR_d, "ldr", "'Dt")
786 void Disassembler::VisitLoadStorePreIndex(Instruction* instr) {
787 const char *mnemonic =
"unimplemented";
788 const char *form =
"(LoadStorePreIndex)";
791 #define LS_PREINDEX(A, B, C) \
792 case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break;
793 LOAD_STORE_LIST(LS_PREINDEX)
796 Format(instr, mnemonic, form);
800 void Disassembler::VisitLoadStorePostIndex(Instruction* instr) {
801 const char *mnemonic =
"unimplemented";
802 const char *form =
"(LoadStorePostIndex)";
805 #define LS_POSTINDEX(A, B, C) \
806 case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break;
807 LOAD_STORE_LIST(LS_POSTINDEX)
810 Format(instr, mnemonic, form);
814 void Disassembler::VisitLoadStoreUnsignedOffset(Instruction* instr) {
815 const char *mnemonic =
"unimplemented";
816 const char *form =
"(LoadStoreUnsignedOffset)";
819 #define LS_UNSIGNEDOFFSET(A, B, C) \
820 case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break;
821 LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
822 #undef LS_UNSIGNEDOFFSET
823 case PRFM_unsigned: mnemonic =
"prfm"; form =
"'PrefOp, ['Xn'ILU]";
825 Format(instr, mnemonic, form);
829 void Disassembler::VisitLoadStoreRegisterOffset(Instruction* instr) {
830 const char *mnemonic =
"unimplemented";
831 const char *form =
"(LoadStoreRegisterOffset)";
834 #define LS_REGISTEROFFSET(A, B, C) \
835 case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break;
836 LOAD_STORE_LIST(LS_REGISTEROFFSET)
837 #undef LS_REGISTEROFFSET
838 case PRFM_reg: mnemonic =
"prfm"; form =
"'PrefOp, ['Xns, 'Offsetreg]";
840 Format(instr, mnemonic, form);
844 void Disassembler::VisitLoadStoreUnscaledOffset(Instruction* instr) {
845 const char *mnemonic =
"unimplemented";
846 const char *form =
"'Wt, ['Xns'ILS]";
847 const char *form_x =
"'Xt, ['Xns'ILS]";
848 const char *form_s =
"'St, ['Xns'ILS]";
849 const char *form_d =
"'Dt, ['Xns'ILS]";
852 case STURB_w: mnemonic =
"sturb";
break;
853 case STURH_w: mnemonic =
"sturh";
break;
854 case STUR_w: mnemonic =
"stur";
break;
855 case STUR_x: mnemonic =
"stur"; form = form_x;
break;
856 case STUR_s: mnemonic =
"stur"; form = form_s;
break;
857 case STUR_d: mnemonic =
"stur"; form = form_d;
break;
858 case LDURB_w: mnemonic =
"ldurb";
break;
859 case LDURH_w: mnemonic =
"ldurh";
break;
860 case LDUR_w: mnemonic =
"ldur";
break;
861 case LDUR_x: mnemonic =
"ldur"; form = form_x;
break;
862 case LDUR_s: mnemonic =
"ldur"; form = form_s;
break;
863 case LDUR_d: mnemonic =
"ldur"; form = form_d;
break;
864 case LDURSB_x: form = form_x;
865 case LDURSB_w: mnemonic =
"ldursb";
break;
866 case LDURSH_x: form = form_x;
867 case LDURSH_w: mnemonic =
"ldursh";
break;
868 case LDURSW_x: mnemonic =
"ldursw"; form = form_x;
break;
869 default: form =
"(LoadStoreUnscaledOffset)";
871 Format(instr, mnemonic, form);
875 void Disassembler::VisitLoadLiteral(Instruction* instr) {
876 const char *mnemonic =
"ldr";
877 const char *form =
"(LoadLiteral)";
880 case LDR_w_lit: form =
"'Wt, 'ILLiteral 'LValue";
break;
881 case LDR_x_lit: form =
"'Xt, 'ILLiteral 'LValue";
break;
882 case LDR_s_lit: form =
"'St, 'ILLiteral 'LValue";
break;
883 case LDR_d_lit: form =
"'Dt, 'ILLiteral 'LValue";
break;
884 default: mnemonic =
"unimplemented";
886 Format(instr, mnemonic, form);
890 #define LOAD_STORE_PAIR_LIST(V) \
891 V(STP_w, "stp", "'Wt, 'Wt2", "4") \
892 V(LDP_w, "ldp", "'Wt, 'Wt2", "4") \
893 V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "4") \
894 V(STP_x, "stp", "'Xt, 'Xt2", "8") \
895 V(LDP_x, "ldp", "'Xt, 'Xt2", "8") \
896 V(STP_s, "stp", "'St, 'St2", "4") \
897 V(LDP_s, "ldp", "'St, 'St2", "4") \
898 V(STP_d, "stp", "'Dt, 'Dt2", "8") \
899 V(LDP_d, "ldp", "'Dt, 'Dt2", "8")
901 void Disassembler::VisitLoadStorePairPostIndex(Instruction* instr) {
902 const char *mnemonic =
"unimplemented";
903 const char *form =
"(LoadStorePairPostIndex)";
906 #define LSP_POSTINDEX(A, B, C, D) \
907 case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break;
908 LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
911 Format(instr, mnemonic, form);
915 void Disassembler::VisitLoadStorePairPreIndex(Instruction* instr) {
916 const char *mnemonic =
"unimplemented";
917 const char *form =
"(LoadStorePairPreIndex)";
920 #define LSP_PREINDEX(A, B, C, D) \
921 case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break;
922 LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
925 Format(instr, mnemonic, form);
929 void Disassembler::VisitLoadStorePairOffset(Instruction* instr) {
930 const char *mnemonic =
"unimplemented";
931 const char *form =
"(LoadStorePairOffset)";
934 #define LSP_OFFSET(A, B, C, D) \
935 case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break;
936 LOAD_STORE_PAIR_LIST(LSP_OFFSET)
939 Format(instr, mnemonic, form);
943 void Disassembler::VisitLoadStorePairNonTemporal(Instruction* instr) {
944 const char *mnemonic =
"unimplemented";
948 case STNP_w: mnemonic =
"stnp"; form =
"'Wt, 'Wt2, ['Xns'ILP4]";
break;
949 case LDNP_w: mnemonic =
"ldnp"; form =
"'Wt, 'Wt2, ['Xns'ILP4]";
break;
950 case STNP_x: mnemonic =
"stnp"; form =
"'Xt, 'Xt2, ['Xns'ILP8]";
break;
951 case LDNP_x: mnemonic =
"ldnp"; form =
"'Xt, 'Xt2, ['Xns'ILP8]";
break;
952 case STNP_s: mnemonic =
"stnp"; form =
"'St, 'St2, ['Xns'ILP4]";
break;
953 case LDNP_s: mnemonic =
"ldnp"; form =
"'St, 'St2, ['Xns'ILP4]";
break;
954 case STNP_d: mnemonic =
"stnp"; form =
"'Dt, 'Dt2, ['Xns'ILP8]";
break;
955 case LDNP_d: mnemonic =
"ldnp"; form =
"'Dt, 'Dt2, ['Xns'ILP8]";
break;
956 default: form =
"(LoadStorePairNonTemporal)";
958 Format(instr, mnemonic, form);
962 void Disassembler::VisitFPCompare(Instruction* instr) {
963 const char *mnemonic =
"unimplemented";
964 const char *form =
"'Fn, 'Fm";
965 const char *form_zero =
"'Fn, #0.0";
971 case FCMP_d: mnemonic =
"fcmp";
break;
972 default: form =
"(FPCompare)";
974 Format(instr, mnemonic, form);
978 void Disassembler::VisitFPConditionalCompare(Instruction* instr) {
979 const char *mnemonic =
"unimplemented";
980 const char *form =
"'Fn, 'Fm, 'INzcv, 'Cond";
984 case FCCMP_d: mnemonic =
"fccmp";
break;
986 case FCCMPE_d: mnemonic =
"fccmpe";
break;
987 default: form =
"(FPConditionalCompare)";
989 Format(instr, mnemonic, form);
993 void Disassembler::VisitFPConditionalSelect(Instruction* instr) {
994 const char *mnemonic =
"";
995 const char *form =
"'Fd, 'Fn, 'Fm, 'Cond";
999 case FCSEL_d: mnemonic =
"fcsel";
break;
1002 Format(instr, mnemonic, form);
1006 void Disassembler::VisitFPDataProcessing1Source(Instruction* instr) {
1007 const char *mnemonic =
"unimplemented";
1008 const char *form =
"'Fd, 'Fn";
1011 #define FORMAT(A, B) \
1013 case A##_d: mnemonic = B; break;
1014 FORMAT(
FMOV,
"fmov");
1015 FORMAT(
FABS,
"fabs");
1016 FORMAT(
FNEG,
"fneg");
1017 FORMAT(
FSQRT,
"fsqrt");
1018 FORMAT(
FRINTN,
"frintn");
1019 FORMAT(
FRINTP,
"frintp");
1020 FORMAT(
FRINTM,
"frintm");
1021 FORMAT(
FRINTZ,
"frintz");
1022 FORMAT(
FRINTA,
"frinta");
1023 FORMAT(
FRINTX,
"frintx");
1024 FORMAT(
FRINTI,
"frinti");
1026 case FCVT_ds: mnemonic =
"fcvt"; form =
"'Dd, 'Sn";
break;
1027 case FCVT_sd: mnemonic =
"fcvt"; form =
"'Sd, 'Dn";
break;
1028 default: form =
"(FPDataProcessing1Source)";
1030 Format(instr, mnemonic, form);
1034 void Disassembler::VisitFPDataProcessing2Source(Instruction* instr) {
1035 const char *mnemonic =
"";
1036 const char *form =
"'Fd, 'Fn, 'Fm";
1039 #define FORMAT(A, B) \
1041 case A##_d: mnemonic = B; break;
1042 FORMAT(
FMUL,
"fmul");
1043 FORMAT(
FDIV,
"fdiv");
1044 FORMAT(
FADD,
"fadd");
1045 FORMAT(
FSUB,
"fsub");
1046 FORMAT(
FMAX,
"fmax");
1047 FORMAT(
FMIN,
"fmin");
1048 FORMAT(
FMAXNM,
"fmaxnm");
1049 FORMAT(
FMINNM,
"fminnm");
1050 FORMAT(
FNMUL,
"fnmul");
1054 Format(instr, mnemonic, form);
1058 void Disassembler::VisitFPDataProcessing3Source(Instruction* instr) {
1059 const char *mnemonic =
"";
1060 const char *form =
"'Fd, 'Fn, 'Fm, 'Fa";
1063 #define FORMAT(A, B) \
1065 case A##_d: mnemonic = B; break;
1066 FORMAT(FMADD,
"fmadd");
1067 FORMAT(FMSUB,
"fmsub");
1068 FORMAT(FNMADD,
"fnmadd");
1069 FORMAT(FNMSUB,
"fnmsub");
1073 Format(instr, mnemonic, form);
1077 void Disassembler::VisitFPImmediate(Instruction* instr) {
1078 const char *mnemonic =
"";
1079 const char *form =
"(FPImmediate)";
1082 case FMOV_s_imm: mnemonic =
"fmov"; form =
"'Sd, 'IFPSingle";
break;
1083 case FMOV_d_imm: mnemonic =
"fmov"; form =
"'Dd, 'IFPDouble";
break;
1086 Format(instr, mnemonic, form);
1090 void Disassembler::VisitFPIntegerConvert(Instruction* instr) {
1091 const char *mnemonic =
"unimplemented";
1092 const char *form =
"(FPIntegerConvert)";
1093 const char *form_rf =
"'Rd, 'Fn";
1094 const char *form_fr =
"'Fd, 'Rn";
1098 case FMOV_xd: mnemonic =
"fmov"; form = form_rf;
break;
1100 case FMOV_dx: mnemonic =
"fmov"; form = form_fr;
break;
1104 case FCVTAS_xd: mnemonic =
"fcvtas"; form = form_rf;
break;
1108 case FCVTAU_xd: mnemonic =
"fcvtau"; form = form_rf;
break;
1112 case FCVTMS_xd: mnemonic =
"fcvtms"; form = form_rf;
break;
1116 case FCVTMU_xd: mnemonic =
"fcvtmu"; form = form_rf;
break;
1120 case FCVTNS_xd: mnemonic =
"fcvtns"; form = form_rf;
break;
1124 case FCVTNU_xd: mnemonic =
"fcvtnu"; form = form_rf;
break;
1128 case FCVTZU_xs: mnemonic =
"fcvtzu"; form = form_rf;
break;
1132 case FCVTZS_ws: mnemonic =
"fcvtzs"; form = form_rf;
break;
1136 case SCVTF_dx: mnemonic =
"scvtf"; form = form_fr;
break;
1140 case UCVTF_dx: mnemonic =
"ucvtf"; form = form_fr;
break;
1142 Format(instr, mnemonic, form);
1146 void Disassembler::VisitFPFixedPointConvert(Instruction* instr) {
1147 const char *mnemonic =
"";
1148 const char *form =
"'Rd, 'Fn, 'IFPFBits";
1149 const char *form_fr =
"'Fd, 'Rn, 'IFPFBits";
1169 Format(instr, mnemonic, form);
1173 void Disassembler::VisitSystem(Instruction* instr) {
1177 const char *mnemonic =
"unimplemented";
1178 const char *form =
"(System)";
1184 switch (instr->ImmSystemRegister()) {
1185 case NZCV: form =
"'Xt, nzcv";
break;
1186 case FPCR: form =
"'Xt, fpcr";
break;
1187 default: form =
"'Xt, (unknown)";
break;
1193 switch (instr->ImmSystemRegister()) {
1194 case NZCV: form =
"nzcv, 'Xt";
break;
1195 case FPCR: form =
"fpcr, 'Xt";
break;
1196 default: form =
"(unknown), 'Xt";
break;
1203 switch (instr->ImmHint()) {
1230 Format(instr, mnemonic, form);
1234 void Disassembler::VisitException(Instruction* instr) {
1235 const char *mnemonic =
"unimplemented";
1236 const char *form =
"'IDebug";
1239 case HLT: mnemonic =
"hlt";
break;
1240 case BRK: mnemonic =
"brk";
break;
1241 case SVC: mnemonic =
"svc";
break;
1242 case HVC: mnemonic =
"hvc";
break;
1243 case SMC: mnemonic =
"smc";
break;
1244 case DCPS1: mnemonic =
"dcps1"; form =
"{'IDebug}";
break;
1245 case DCPS2: mnemonic =
"dcps2"; form =
"{'IDebug}";
break;
1246 case DCPS3: mnemonic =
"dcps3"; form =
"{'IDebug}";
break;
1247 default: form =
"(Exception)";
1249 Format(instr, mnemonic, form);
1253 void Disassembler::VisitUnimplemented(Instruction* instr) {
1254 Format(instr,
"unimplemented",
"(Unimplemented)");
1258 void Disassembler::VisitUnallocated(Instruction* instr) {
1259 Format(instr,
"unallocated",
"(Unallocated)");
1269 const char* format) {
1275 if (format !=
NULL) {
1285 char chr = *
string++;
1286 while (chr !=
'\0') {
1298 switch (format[0]) {
1324 const char* format) {
1325 unsigned reg_num = 0;
1326 unsigned field_len = 2;
1327 switch (format[1]) {
1328 case 'd': reg_num = instr->Rd();
break;
1329 case 'n': reg_num = instr->Rn();
break;
1330 case 'm': reg_num = instr->Rm();
break;
1331 case 'a': reg_num = instr->Ra();
break;
1333 if (format[2] ==
'2') {
1334 reg_num = instr->Rt2();
1337 reg_num = instr->Rt();
1345 if (format[2] ==
's') {
1350 if (format[0] ==
'R') {
1352 reg_type = instr->SixtyFourBits() ?
'x' :
'w';
1353 }
else if (format[0] ==
'F') {
1355 reg_type = ((instr->FPType() & 1) == 0) ?
's' :
'd';
1358 reg_type = format[0] + 0x20;
1361 if ((reg_num !=
kZeroRegCode) || (reg_type ==
's') || (reg_type ==
'd')) {
1365 if ((reg_type ==
'x') && (reg_num == 27)) {
1367 }
else if ((reg_type ==
'x') && (reg_num == 28)) {
1369 }
else if ((reg_type ==
'x') && (reg_num == 29)) {
1371 }
else if ((reg_type ==
'x') && (reg_num == 30)) {
1376 }
else if (format[2] ==
's') {
1389 const char* format) {
1390 ASSERT(format[0] ==
'I');
1392 switch (format[1]) {
1394 if (format[5] ==
'I') {
1395 uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide());
1398 ASSERT(format[5] ==
'L');
1400 if (instr->ShiftMoveWide() > 0) {
1407 switch (format[2]) {
1414 if (instr->ImmLS() != 0) {
1420 if (instr->ImmLSPair() != 0) {
1422 int scale = format[3] - 0x30;
1428 if (instr->ImmLSUnsigned() != 0) {
1430 instr->ImmLSUnsigned() << instr->SizeLS());
1437 int64_t offset = instr->ImmCondBranch() << 2;
1438 char sign = (offset >= 0) ?
'+' :
'-';
1443 ASSERT(instr->ShiftAddSub() <= 1);
1444 int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
1449 if (format[3] ==
'F') {
1454 format[3] ==
'S' ? instr->ImmFP32() : instr->ImmFP64());
1463 int nzcv = (instr->Nzcv() << Flags_offset);
1465 ((nzcv &
ZFlag) == 0) ?
'z' :
'Z',
1466 ((nzcv &
CFlag) == 0) ?
'c' :
'C',
1467 ((nzcv &
VFlag) == 0) ?
'v' :
'V');
1483 instr->ImmTestBranchBit40());
1499 const char* format) {
1500 ASSERT((format[0] ==
'I') && (format[1] ==
'B'));
1501 unsigned r = instr->ImmR();
1502 unsigned s = instr->ImmS();
1504 switch (format[2]) {
1510 if (format[3] ==
'+') {
1514 ASSERT(format[3] ==
'-');
1520 ASSERT((format[3] ==
'-') && (format[4] ==
'r'));
1535 const char* format) {
1536 ASSERT(strncmp(format,
"LValue", 6) == 0);
1552 ASSERT(format[0] ==
'H');
1553 ASSERT(instr->ShiftDP() <= 0x3);
1555 switch (format[1]) {
1560 if (instr->ImmDPShift() != 0) {
1561 const char* shift_type[] = {
"lsl",
"lsr",
"asr",
"ror"};
1563 instr->ImmDPShift());
1575 const char* format) {
1576 ASSERT(format[0] ==
'C');
1577 const char* condition_code[] = {
"eq",
"ne",
"hs",
"lo",
1578 "mi",
"pl",
"vs",
"vc",
1579 "hi",
"ls",
"ge",
"lt",
1580 "gt",
"le",
"al",
"nv" };
1582 switch (format[1]) {
1583 case 'B': cond = instr->ConditionBranch();
break;
1588 default: cond = instr->Condition();
1596 const char* format) {
1598 ASSERT(strncmp(format,
"AddrPCRel", 9) == 0);
1600 int offset = instr->ImmPCRel();
1603 ASSERT(strcmp(format,
"AddrPCRelByte") == 0);
1617 const char* format) {
1618 ASSERT(strncmp(format,
"BImm", 4) == 0);
1621 switch (format[5]) {
1623 case 'n': offset = instr->ImmUncondBranch();
break;
1625 case 'o': offset = instr->ImmCondBranch();
break;
1627 case 'm': offset = instr->ImmCmpBranch();
break;
1629 case 'e': offset = instr->ImmTestBranch();
break;
1645 const char* format) {
1646 ASSERT(strncmp(format,
"Ext", 3) == 0);
1647 ASSERT(instr->ExtendMode() <= 7);
1650 const char* extend_mode[] = {
"uxtb",
"uxth",
"uxtw",
"uxtx",
1651 "sxtb",
"sxth",
"sxtw",
"sxtx" };
1656 (((instr->ExtendMode() ==
UXTW) && (instr->SixtyFourBits() == 0)) ||
1657 (instr->ExtendMode() ==
UXTX))) {
1658 if (instr->ImmExtendShift() > 0) {
1663 if (instr->ImmExtendShift() > 0) {
1672 const char* format) {
1673 ASSERT(strncmp(format,
"Offsetreg", 9) == 0);
1674 const char* extend_mode[] = {
"undefined",
"undefined",
"uxtw",
"lsl",
1675 "undefined",
"undefined",
"sxtw",
"sxtx" };
1678 unsigned shift = instr->ImmShiftLS();
1680 char reg_type = ((ext ==
UXTW) || (ext ==
SXTW)) ?
'w' :
'x';
1682 unsigned rm = instr->Rm();
1690 if (!((ext ==
UXTX) && (shift == 0))) {
1701 const char* format) {
1702 ASSERT(format[0] ==
'P');
1705 int prefetch_mode = instr->PrefetchMode();
1707 const char*
ls = (prefetch_mode & 0x10) ?
"st" :
"ld";
1708 int level = (prefetch_mode >> 1) + 1;
1709 const char* ks = (prefetch_mode & 1) ?
"strm" :
"keep";
1716 const char* format) {
1717 ASSERT(format[0] ==
'M');
1720 static const char* options[4][4] = {
1721 {
"sy (0b0000)",
"oshld",
"oshst",
"osh" },
1722 {
"sy (0b0100)",
"nshld",
"nshst",
"nsh" },
1723 {
"sy (0b1000)",
"ishld",
"ishst",
"ish" },
1724 {
"sy (0b1100)",
"ld",
"st",
"sy" }
1726 int domain = instr->ImmBarrierDomain();
1727 int type = instr->ImmBarrierType();
1742 va_start(args, format);
1749 fprintf(stream_,
"0x%016" PRIx64
" %08" PRIx32
"\t\t%s\n",
1750 reinterpret_cast<uint64_t>(instr), instr->InstructionBits(),
1772 unsigned ureg = reg;
1808 : out_buffer_(out_buffer) { }
1810 ~BufferDisassembler() { }
1821 : converter_(converter) {}
1824 Disassembler::~Disassembler() {}
1830 BufferDisassembler disasm(buffer);
1831 decoder.AppendVisitor(&disasm);
1833 decoder.
Decode(reinterpret_cast<v8::internal::Instruction*>(instr));
1838 int Disassembler::ConstantPoolSizeAt(
byte* instr) {
1840 reinterpret_cast<v8::internal::Instruction*>(instr));
1844 void Disassembler::Disassemble(FILE* file,
byte* start,
byte* end) {
1847 decoder.AppendVisitor(&disasm);
1850 decoder.
Decode(reinterpret_cast<v8::internal::Instruction*>(
pc));
1856 #endif // V8_TARGET_ARCH_ARM64
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
const unsigned kInstructionSizeLog2
int SubstituteLiteralField(Instruction *instr, const char *format)
Disassembler(const NameConverter &converter)
virtual const char * NameOfXMMRegister(int reg) const
virtual void ProcessOutput(Instruction *instr)
const unsigned kZeroRegCode
v8::internal::EmbeddedVector< char, 128 > tmp_buffer_
const unsigned kLiteralEntrySizeLog2
const unsigned kXRegSizeInBits
virtual const char * NameOfConstant(byte *addr) const
int SubstituteBitfieldImmediateField(Instruction *instr, const char *format)
int SubstituteShiftField(Instruction *instr, const char *format)
int SubstituteField(Instruction *instr, const char *format)
#define ASSERT(condition)
const unsigned kLinkRegCode
void AppendToOutput(const char *string,...)
virtual const char * NameInCode(byte *addr) const
int SubstituteConditionField(Instruction *instr, const char *format)
virtual const char * NameOfByteCPURegister(int reg) const
const unsigned kWRegSizeInBits
int SubstitutePrefetchField(Instruction *instr, const char *format)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_string(expose_natives_as
bool RaIsZROrSP(Instruction *instr) const
virtual const char * NameOfCPURegister(int reg) const
Condition InvertCondition(Condition cond)
const unsigned kInstructionSize
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array shift
bool RnIsZROrSP(Instruction *instr) const
bool RmIsZROrSP(Instruction *instr) const
int SubstituteExtendField(Instruction *instr, const char *format)
int SubstitutePCRelAddressField(Instruction *instr, const char *format)
virtual const char * NameOfAddress(byte *addr) const
int SubstituteRegisterField(Instruction *instr, const char *format)
bool RdIsZROrSP(Instruction *instr) const
int SubstituteLSRegOffsetField(Instruction *instr, const char *format)
static int SNPrintF(Vector< char > str, const char *format,...)
const unsigned kNumberOfRegisters
int SubstituteBranchTargetField(Instruction *instr, const char *format)
int SubstituteImmediateField(Instruction *instr, const char *format)
virtual void Decode(Instruction *instr)
virtual void ProcessOutput(Instruction *instr)
void Format(Instruction *instr, const char *mnemonic, const char *format)
bool IsMovzMovnImm(unsigned reg_size, uint64_t value)
void Substitute(Instruction *instr, const char *string)
int SubstituteBarrierField(Instruction *instr, const char *format)
static int ConstantPoolSizeAt(Instruction *instr)