OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <assert.h> | 5 #include <assert.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <string.h> | 8 #include <string.h> |
9 | 9 |
10 #if V8_TARGET_ARCH_ARM64 | 10 #if V8_TARGET_ARCH_ARM64 |
11 | 11 |
12 #include "src/arm64/decoder-arm64-inl.h" | 12 #include "src/arm64/decoder-arm64-inl.h" |
13 #include "src/arm64/disasm-arm64.h" | 13 #include "src/arm64/disasm-arm64.h" |
14 #include "src/arm64/utils-arm64.h" | |
14 #include "src/base/platform/platform.h" | 15 #include "src/base/platform/platform.h" |
15 #include "src/disasm.h" | 16 #include "src/disasm.h" |
16 #include "src/macro-assembler.h" | 17 #include "src/macro-assembler.h" |
17 | 18 |
18 namespace v8 { | 19 namespace v8 { |
19 namespace internal { | 20 namespace internal { |
20 | 21 |
21 | 22 |
22 DisassemblingDecoder::DisassemblingDecoder() { | 23 DisassemblingDecoder::DisassemblingDecoder() { |
23 buffer_size_ = 256; | 24 buffer_size_ = 256; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
87 default: UNREACHABLE(); | 88 default: UNREACHABLE(); |
88 } | 89 } |
89 Format(instr, mnemonic, form); | 90 Format(instr, mnemonic, form); |
90 } | 91 } |
91 | 92 |
92 | 93 |
93 void DisassemblingDecoder::VisitAddSubShifted(Instruction* instr) { | 94 void DisassemblingDecoder::VisitAddSubShifted(Instruction* instr) { |
94 bool rd_is_zr = RdIsZROrSP(instr); | 95 bool rd_is_zr = RdIsZROrSP(instr); |
95 bool rn_is_zr = RnIsZROrSP(instr); | 96 bool rn_is_zr = RnIsZROrSP(instr); |
96 const char *mnemonic = ""; | 97 const char *mnemonic = ""; |
97 const char *form = "'Rd, 'Rn, 'Rm'HDP"; | 98 const char *form = "'Rd, 'Rn, 'Rm'NDP"; |
98 const char *form_cmp = "'Rn, 'Rm'HDP"; | 99 const char *form_cmp = "'Rn, 'Rm'NDP"; |
99 const char *form_neg = "'Rd, 'Rm'HDP"; | 100 const char *form_neg = "'Rd, 'Rm'NDP"; |
100 | 101 |
101 switch (instr->Mask(AddSubShiftedMask)) { | 102 switch (instr->Mask(AddSubShiftedMask)) { |
102 case ADD_w_shift: | 103 case ADD_w_shift: |
103 case ADD_x_shift: mnemonic = "add"; break; | 104 case ADD_x_shift: mnemonic = "add"; break; |
104 case ADDS_w_shift: | 105 case ADDS_w_shift: |
105 case ADDS_x_shift: { | 106 case ADDS_x_shift: { |
106 mnemonic = "adds"; | 107 mnemonic = "adds"; |
107 if (rd_is_zr) { | 108 if (rd_is_zr) { |
108 mnemonic = "cmn"; | 109 mnemonic = "cmn"; |
109 form = form_cmp; | 110 form = form_cmp; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 return true; | 280 return true; |
280 } | 281 } |
281 return false; | 282 return false; |
282 } | 283 } |
283 | 284 |
284 | 285 |
285 void DisassemblingDecoder::VisitLogicalShifted(Instruction* instr) { | 286 void DisassemblingDecoder::VisitLogicalShifted(Instruction* instr) { |
286 bool rd_is_zr = RdIsZROrSP(instr); | 287 bool rd_is_zr = RdIsZROrSP(instr); |
287 bool rn_is_zr = RnIsZROrSP(instr); | 288 bool rn_is_zr = RnIsZROrSP(instr); |
288 const char *mnemonic = ""; | 289 const char *mnemonic = ""; |
289 const char *form = "'Rd, 'Rn, 'Rm'HLo"; | 290 const char *form = "'Rd, 'Rn, 'Rm'NLo"; |
290 | 291 |
291 switch (instr->Mask(LogicalShiftedMask)) { | 292 switch (instr->Mask(LogicalShiftedMask)) { |
292 case AND_w: | 293 case AND_w: |
293 case AND_x: mnemonic = "and"; break; | 294 case AND_x: mnemonic = "and"; break; |
294 case BIC_w: | 295 case BIC_w: |
295 case BIC_x: mnemonic = "bic"; break; | 296 case BIC_x: mnemonic = "bic"; break; |
296 case EOR_w: | 297 case EOR_w: |
297 case EOR_x: mnemonic = "eor"; break; | 298 case EOR_x: mnemonic = "eor"; break; |
298 case EON_w: | 299 case EON_w: |
299 case EON_x: mnemonic = "eon"; break; | 300 case EON_x: mnemonic = "eon"; break; |
300 case BICS_w: | 301 case BICS_w: |
301 case BICS_x: mnemonic = "bics"; break; | 302 case BICS_x: mnemonic = "bics"; break; |
302 case ANDS_w: | 303 case ANDS_w: |
303 case ANDS_x: { | 304 case ANDS_x: { |
304 mnemonic = "ands"; | 305 mnemonic = "ands"; |
305 if (rd_is_zr) { | 306 if (rd_is_zr) { |
306 mnemonic = "tst"; | 307 mnemonic = "tst"; |
307 form = "'Rn, 'Rm'HLo"; | 308 form = "'Rn, 'Rm'NLo"; |
308 } | 309 } |
309 break; | 310 break; |
310 } | 311 } |
311 case ORR_w: | 312 case ORR_w: |
312 case ORR_x: { | 313 case ORR_x: { |
313 mnemonic = "orr"; | 314 mnemonic = "orr"; |
314 if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) { | 315 if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) { |
315 mnemonic = "mov"; | 316 mnemonic = "mov"; |
316 form = "'Rd, 'Rm"; | 317 form = "'Rd, 'Rm"; |
317 } | 318 } |
318 break; | 319 break; |
319 } | 320 } |
320 case ORN_w: | 321 case ORN_w: |
321 case ORN_x: { | 322 case ORN_x: { |
322 mnemonic = "orn"; | 323 mnemonic = "orn"; |
323 if (rn_is_zr) { | 324 if (rn_is_zr) { |
324 mnemonic = "mvn"; | 325 mnemonic = "mvn"; |
325 form = "'Rd, 'Rm'HLo"; | 326 form = "'Rd, 'Rm'NLo"; |
326 } | 327 } |
327 break; | 328 break; |
328 } | 329 } |
329 default: UNREACHABLE(); | 330 default: UNREACHABLE(); |
330 } | 331 } |
331 | 332 |
332 Format(instr, mnemonic, form); | 333 Format(instr, mnemonic, form); |
333 } | 334 } |
334 | 335 |
335 | 336 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
520 switch (instr->Mask(PCRelAddressingMask)) { | 521 switch (instr->Mask(PCRelAddressingMask)) { |
521 case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break; | 522 case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break; |
522 // ADRP is not implemented. | 523 // ADRP is not implemented. |
523 default: Format(instr, "unimplemented", "(PCRelAddressing)"); | 524 default: Format(instr, "unimplemented", "(PCRelAddressing)"); |
524 } | 525 } |
525 } | 526 } |
526 | 527 |
527 | 528 |
528 void DisassemblingDecoder::VisitConditionalBranch(Instruction* instr) { | 529 void DisassemblingDecoder::VisitConditionalBranch(Instruction* instr) { |
529 switch (instr->Mask(ConditionalBranchMask)) { | 530 switch (instr->Mask(ConditionalBranchMask)) { |
530 case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break; | 531 case B_cond: |
532 Format(instr, "b.'CBrn", "'TImmCond"); | |
533 break; | |
531 default: UNREACHABLE(); | 534 default: UNREACHABLE(); |
532 } | 535 } |
533 } | 536 } |
534 | 537 |
535 | 538 |
536 void DisassemblingDecoder::VisitUnconditionalBranchToRegister( | 539 void DisassemblingDecoder::VisitUnconditionalBranchToRegister( |
537 Instruction* instr) { | 540 Instruction* instr) { |
538 const char *mnemonic = "unimplemented"; | 541 const char *mnemonic = "unimplemented"; |
539 const char *form = "'Xn"; | 542 const char *form = "'Xn"; |
540 | 543 |
541 switch (instr->Mask(UnconditionalBranchToRegisterMask)) { | 544 switch (instr->Mask(UnconditionalBranchToRegisterMask)) { |
542 case BR: mnemonic = "br"; break; | 545 case BR: mnemonic = "br"; break; |
543 case BLR: mnemonic = "blr"; break; | 546 case BLR: mnemonic = "blr"; break; |
544 case RET: { | 547 case RET: { |
545 mnemonic = "ret"; | 548 mnemonic = "ret"; |
546 if (instr->Rn() == kLinkRegCode) { | 549 if (instr->Rn() == kLinkRegCode) { |
547 form = NULL; | 550 form = NULL; |
548 } | 551 } |
549 break; | 552 break; |
550 } | 553 } |
551 default: form = "(UnconditionalBranchToRegister)"; | 554 default: form = "(UnconditionalBranchToRegister)"; |
552 } | 555 } |
553 Format(instr, mnemonic, form); | 556 Format(instr, mnemonic, form); |
554 } | 557 } |
555 | 558 |
556 | 559 |
557 void DisassemblingDecoder::VisitUnconditionalBranch(Instruction* instr) { | 560 void DisassemblingDecoder::VisitUnconditionalBranch(Instruction* instr) { |
558 const char *mnemonic = ""; | 561 const char *mnemonic = ""; |
559 const char *form = "'BImmUncn"; | 562 const char *form = "'TImmUncn"; |
560 | 563 |
561 switch (instr->Mask(UnconditionalBranchMask)) { | 564 switch (instr->Mask(UnconditionalBranchMask)) { |
562 case B: mnemonic = "b"; break; | 565 case B: mnemonic = "b"; break; |
563 case BL: mnemonic = "bl"; break; | 566 case BL: mnemonic = "bl"; break; |
564 default: UNREACHABLE(); | 567 default: UNREACHABLE(); |
565 } | 568 } |
566 Format(instr, mnemonic, form); | 569 Format(instr, mnemonic, form); |
567 } | 570 } |
568 | 571 |
569 | 572 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
682 break; | 685 break; |
683 } | 686 } |
684 default: UNREACHABLE(); | 687 default: UNREACHABLE(); |
685 } | 688 } |
686 Format(instr, mnemonic, form); | 689 Format(instr, mnemonic, form); |
687 } | 690 } |
688 | 691 |
689 | 692 |
690 void DisassemblingDecoder::VisitCompareBranch(Instruction* instr) { | 693 void DisassemblingDecoder::VisitCompareBranch(Instruction* instr) { |
691 const char *mnemonic = ""; | 694 const char *mnemonic = ""; |
692 const char *form = "'Rt, 'BImmCmpa"; | 695 const char *form = "'Rt, 'TImmCmpa"; |
693 | 696 |
694 switch (instr->Mask(CompareBranchMask)) { | 697 switch (instr->Mask(CompareBranchMask)) { |
695 case CBZ_w: | 698 case CBZ_w: |
696 case CBZ_x: mnemonic = "cbz"; break; | 699 case CBZ_x: mnemonic = "cbz"; break; |
697 case CBNZ_w: | 700 case CBNZ_w: |
698 case CBNZ_x: mnemonic = "cbnz"; break; | 701 case CBNZ_x: mnemonic = "cbnz"; break; |
699 default: UNREACHABLE(); | 702 default: UNREACHABLE(); |
700 } | 703 } |
701 Format(instr, mnemonic, form); | 704 Format(instr, mnemonic, form); |
702 } | 705 } |
703 | 706 |
704 | 707 |
705 void DisassemblingDecoder::VisitTestBranch(Instruction* instr) { | 708 void DisassemblingDecoder::VisitTestBranch(Instruction* instr) { |
706 const char *mnemonic = ""; | 709 const char *mnemonic = ""; |
707 // If the top bit of the immediate is clear, the tested register is | 710 // If the top bit of the immediate is clear, the tested register is |
708 // disassembled as Wt, otherwise Xt. As the top bit of the immediate is | 711 // disassembled as Wt, otherwise Xt. As the top bit of the immediate is |
709 // encoded in bit 31 of the instruction, we can reuse the Rt form, which | 712 // encoded in bit 31 of the instruction, we can reuse the Rt form, which |
710 // uses bit 31 (normally "sf") to choose the register size. | 713 // uses bit 31 (normally "sf") to choose the register size. |
711 const char *form = "'Rt, 'IS, 'BImmTest"; | 714 const char *form = "'Rt, 'IS, 'TImmTest"; |
712 | 715 |
713 switch (instr->Mask(TestBranchMask)) { | 716 switch (instr->Mask(TestBranchMask)) { |
714 case TBZ: mnemonic = "tbz"; break; | 717 case TBZ: mnemonic = "tbz"; break; |
715 case TBNZ: mnemonic = "tbnz"; break; | 718 case TBNZ: mnemonic = "tbnz"; break; |
716 default: UNREACHABLE(); | 719 default: UNREACHABLE(); |
717 } | 720 } |
718 Format(instr, mnemonic, form); | 721 Format(instr, mnemonic, form); |
719 } | 722 } |
720 | 723 |
721 | 724 |
722 void DisassemblingDecoder::VisitMoveWideImmediate(Instruction* instr) { | 725 void DisassemblingDecoder::VisitMoveWideImmediate(Instruction* instr) { |
723 const char *mnemonic = ""; | 726 const char *mnemonic = ""; |
724 const char *form = "'Rd, 'IMoveImm"; | 727 const char *form = "'Rd, 'IMoveImm"; |
725 | 728 |
726 // Print the shift separately for movk, to make it clear which half word will | 729 // Print the shift separately for movk, to make it clear which half word will |
727 // be overwritten. Movn and movz print the computed immediate, which includes | 730 // be overwritten. Movn and movz print the computed immediate, which includes |
728 // shift calculation. | 731 // shift calculation. |
729 switch (instr->Mask(MoveWideImmediateMask)) { | 732 switch (instr->Mask(MoveWideImmediateMask)) { |
730 case MOVN_w: | 733 case MOVN_w: |
731 case MOVN_x: mnemonic = "movn"; break; | 734 case MOVN_x: mnemonic = "movn"; break; |
732 case MOVZ_w: | 735 case MOVZ_w: |
733 case MOVZ_x: mnemonic = "movz"; break; | 736 case MOVZ_x: mnemonic = "movz"; break; |
734 case MOVK_w: | 737 case MOVK_w: |
735 case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break; | 738 case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break; |
736 default: UNREACHABLE(); | 739 default: UNREACHABLE(); |
737 } | 740 } |
738 Format(instr, mnemonic, form); | 741 Format(instr, mnemonic, form); |
739 } | 742 } |
740 | 743 |
741 | 744 #define LOAD_STORE_LIST(V) \ |
742 #define LOAD_STORE_LIST(V) \ | 745 V(STRB_w, "strb", "'Wt") \ |
743 V(STRB_w, "strb", "'Wt") \ | 746 V(STRH_w, "strh", "'Wt") \ |
744 V(STRH_w, "strh", "'Wt") \ | 747 V(STR_w, "str", "'Wt") \ |
745 V(STR_w, "str", "'Wt") \ | 748 V(STR_x, "str", "'Xt") \ |
746 V(STR_x, "str", "'Xt") \ | 749 V(LDRB_w, "ldrb", "'Wt") \ |
747 V(LDRB_w, "ldrb", "'Wt") \ | 750 V(LDRH_w, "ldrh", "'Wt") \ |
748 V(LDRH_w, "ldrh", "'Wt") \ | 751 V(LDR_w, "ldr", "'Wt") \ |
749 V(LDR_w, "ldr", "'Wt") \ | 752 V(LDR_x, "ldr", "'Xt") \ |
750 V(LDR_x, "ldr", "'Xt") \ | 753 V(LDRSB_x, "ldrsb", "'Xt") \ |
751 V(LDRSB_x, "ldrsb", "'Xt") \ | 754 V(LDRSH_x, "ldrsh", "'Xt") \ |
752 V(LDRSH_x, "ldrsh", "'Xt") \ | 755 V(LDRSW_x, "ldrsw", "'Xt") \ |
753 V(LDRSW_x, "ldrsw", "'Xt") \ | 756 V(LDRSB_w, "ldrsb", "'Wt") \ |
754 V(LDRSB_w, "ldrsb", "'Wt") \ | 757 V(LDRSH_w, "ldrsh", "'Wt") \ |
755 V(LDRSH_w, "ldrsh", "'Wt") \ | 758 V(STR_b, "str", "'Bt") \ |
756 V(STR_s, "str", "'St") \ | 759 V(STR_h, "str", "'Ht") \ |
757 V(STR_d, "str", "'Dt") \ | 760 V(STR_s, "str", "'St") \ |
758 V(LDR_s, "ldr", "'St") \ | 761 V(STR_d, "str", "'Dt") \ |
759 V(LDR_d, "ldr", "'Dt") | 762 V(LDR_b, "ldr", "'Bt") \ |
763 V(LDR_h, "ldr", "'Ht") \ | |
764 V(LDR_s, "ldr", "'St") \ | |
765 V(LDR_d, "ldr", "'Dt") \ | |
766 V(STR_q, "str", "'Qt") \ | |
767 V(LDR_q, "ldr", "'Qt") | |
760 | 768 |
761 void DisassemblingDecoder::VisitLoadStorePreIndex(Instruction* instr) { | 769 void DisassemblingDecoder::VisitLoadStorePreIndex(Instruction* instr) { |
762 const char *mnemonic = "unimplemented"; | 770 const char *mnemonic = "unimplemented"; |
763 const char *form = "(LoadStorePreIndex)"; | 771 const char *form = "(LoadStorePreIndex)"; |
764 | 772 |
765 switch (instr->Mask(LoadStorePreIndexMask)) { | 773 switch (instr->Mask(LoadStorePreIndexMask)) { |
766 #define LS_PREINDEX(A, B, C) \ | 774 #define LS_PREINDEX(A, B, C) \ |
767 case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break; | 775 case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break; |
768 LOAD_STORE_LIST(LS_PREINDEX) | 776 LOAD_STORE_LIST(LS_PREINDEX) |
769 #undef LS_PREINDEX | 777 #undef LS_PREINDEX |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
854 switch (instr->Mask(LoadLiteralMask)) { | 862 switch (instr->Mask(LoadLiteralMask)) { |
855 case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break; | 863 case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break; |
856 case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break; | 864 case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break; |
857 case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break; | 865 case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break; |
858 case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break; | 866 case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break; |
859 default: mnemonic = "unimplemented"; | 867 default: mnemonic = "unimplemented"; |
860 } | 868 } |
861 Format(instr, mnemonic, form); | 869 Format(instr, mnemonic, form); |
862 } | 870 } |
863 | 871 |
864 | |
865 #define LOAD_STORE_PAIR_LIST(V) \ | 872 #define LOAD_STORE_PAIR_LIST(V) \ |
866 V(STP_w, "stp", "'Wt, 'Wt2", "4") \ | 873 V(STP_w, "stp", "'Wt, 'Wt2", "2") \ |
867 V(LDP_w, "ldp", "'Wt, 'Wt2", "4") \ | 874 V(LDP_w, "ldp", "'Wt, 'Wt2", "2") \ |
868 V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "4") \ | 875 V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "2") \ |
869 V(STP_x, "stp", "'Xt, 'Xt2", "8") \ | 876 V(STP_x, "stp", "'Xt, 'Xt2", "3") \ |
870 V(LDP_x, "ldp", "'Xt, 'Xt2", "8") \ | 877 V(LDP_x, "ldp", "'Xt, 'Xt2", "3") \ |
871 V(STP_s, "stp", "'St, 'St2", "4") \ | 878 V(STP_s, "stp", "'St, 'St2", "2") \ |
872 V(LDP_s, "ldp", "'St, 'St2", "4") \ | 879 V(LDP_s, "ldp", "'St, 'St2", "2") \ |
873 V(STP_d, "stp", "'Dt, 'Dt2", "8") \ | 880 V(STP_d, "stp", "'Dt, 'Dt2", "3") \ |
874 V(LDP_d, "ldp", "'Dt, 'Dt2", "8") | 881 V(LDP_d, "ldp", "'Dt, 'Dt2", "3") \ |
882 V(LDP_q, "ldp", "'Qt, 'Qt2", "4") \ | |
883 V(STP_q, "stp", "'Qt, 'Qt2", "4") | |
875 | 884 |
876 void DisassemblingDecoder::VisitLoadStorePairPostIndex(Instruction* instr) { | 885 void DisassemblingDecoder::VisitLoadStorePairPostIndex(Instruction* instr) { |
877 const char *mnemonic = "unimplemented"; | 886 const char *mnemonic = "unimplemented"; |
878 const char *form = "(LoadStorePairPostIndex)"; | 887 const char *form = "(LoadStorePairPostIndex)"; |
879 | 888 |
880 switch (instr->Mask(LoadStorePairPostIndexMask)) { | 889 switch (instr->Mask(LoadStorePairPostIndexMask)) { |
881 #define LSP_POSTINDEX(A, B, C, D) \ | 890 #define LSP_POSTINDEX(A, B, C, D) \ |
882 case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break; | 891 case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break; |
883 LOAD_STORE_PAIR_LIST(LSP_POSTINDEX) | 892 LOAD_STORE_PAIR_LIST(LSP_POSTINDEX) |
884 #undef LSP_POSTINDEX | 893 #undef LSP_POSTINDEX |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1002 FORMAT(FRINTN, "frintn"); | 1011 FORMAT(FRINTN, "frintn"); |
1003 FORMAT(FRINTP, "frintp"); | 1012 FORMAT(FRINTP, "frintp"); |
1004 FORMAT(FRINTM, "frintm"); | 1013 FORMAT(FRINTM, "frintm"); |
1005 FORMAT(FRINTZ, "frintz"); | 1014 FORMAT(FRINTZ, "frintz"); |
1006 FORMAT(FRINTA, "frinta"); | 1015 FORMAT(FRINTA, "frinta"); |
1007 FORMAT(FRINTX, "frintx"); | 1016 FORMAT(FRINTX, "frintx"); |
1008 FORMAT(FRINTI, "frinti"); | 1017 FORMAT(FRINTI, "frinti"); |
1009 #undef FORMAT | 1018 #undef FORMAT |
1010 case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break; | 1019 case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break; |
1011 case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break; | 1020 case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break; |
1021 case FCVT_hs: | |
1022 mnemonic = "fcvt"; | |
1023 form = "'Hd, 'Sn"; | |
1024 break; | |
1025 case FCVT_sh: | |
1026 mnemonic = "fcvt"; | |
1027 form = "'Sd, 'Hn"; | |
1028 break; | |
1029 case FCVT_dh: | |
1030 mnemonic = "fcvt"; | |
1031 form = "'Dd, 'Hn"; | |
1032 break; | |
1033 case FCVT_hd: | |
1034 mnemonic = "fcvt"; | |
1035 form = "'Hd, 'Dn"; | |
1036 break; | |
1012 default: form = "(FPDataProcessing1Source)"; | 1037 default: form = "(FPDataProcessing1Source)"; |
1013 } | 1038 } |
1014 Format(instr, mnemonic, form); | 1039 Format(instr, mnemonic, form); |
1015 } | 1040 } |
1016 | 1041 |
1017 | 1042 |
1018 void DisassemblingDecoder::VisitFPDataProcessing2Source(Instruction* instr) { | 1043 void DisassemblingDecoder::VisitFPDataProcessing2Source(Instruction* instr) { |
1019 const char *mnemonic = ""; | 1044 const char *mnemonic = ""; |
1020 const char *form = "'Fd, 'Fn, 'Fm"; | 1045 const char *form = "'Fd, 'Fn, 'Fm"; |
1021 | 1046 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1075 const char *mnemonic = "unimplemented"; | 1100 const char *mnemonic = "unimplemented"; |
1076 const char *form = "(FPIntegerConvert)"; | 1101 const char *form = "(FPIntegerConvert)"; |
1077 const char *form_rf = "'Rd, 'Fn"; | 1102 const char *form_rf = "'Rd, 'Fn"; |
1078 const char *form_fr = "'Fd, 'Rn"; | 1103 const char *form_fr = "'Fd, 'Rn"; |
1079 | 1104 |
1080 switch (instr->Mask(FPIntegerConvertMask)) { | 1105 switch (instr->Mask(FPIntegerConvertMask)) { |
1081 case FMOV_ws: | 1106 case FMOV_ws: |
1082 case FMOV_xd: mnemonic = "fmov"; form = form_rf; break; | 1107 case FMOV_xd: mnemonic = "fmov"; form = form_rf; break; |
1083 case FMOV_sw: | 1108 case FMOV_sw: |
1084 case FMOV_dx: mnemonic = "fmov"; form = form_fr; break; | 1109 case FMOV_dx: mnemonic = "fmov"; form = form_fr; break; |
1110 case FMOV_d1_x: | |
1111 mnemonic = "fmov"; | |
1112 form = "'Vd.D[1], 'Rn"; | |
1113 break; | |
1114 case FMOV_x_d1: | |
1115 mnemonic = "fmov"; | |
1116 form = "'Rd, 'Vn.D[1]"; | |
1117 break; | |
1085 case FCVTAS_ws: | 1118 case FCVTAS_ws: |
1086 case FCVTAS_xs: | 1119 case FCVTAS_xs: |
1087 case FCVTAS_wd: | 1120 case FCVTAS_wd: |
1088 case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break; | 1121 case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break; |
1089 case FCVTAU_ws: | 1122 case FCVTAU_ws: |
1090 case FCVTAU_xs: | 1123 case FCVTAU_xs: |
1091 case FCVTAU_wd: | 1124 case FCVTAU_wd: |
1092 case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break; | 1125 case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break; |
1093 case FCVTMS_ws: | 1126 case FCVTMS_ws: |
1094 case FCVTMS_xs: | 1127 case FCVTMS_xs: |
(...skipping 12 matching lines...) Expand all Loading... | |
1107 case FCVTNU_wd: | 1140 case FCVTNU_wd: |
1108 case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break; | 1141 case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break; |
1109 case FCVTZU_xd: | 1142 case FCVTZU_xd: |
1110 case FCVTZU_ws: | 1143 case FCVTZU_ws: |
1111 case FCVTZU_wd: | 1144 case FCVTZU_wd: |
1112 case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break; | 1145 case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break; |
1113 case FCVTZS_xd: | 1146 case FCVTZS_xd: |
1114 case FCVTZS_wd: | 1147 case FCVTZS_wd: |
1115 case FCVTZS_xs: | 1148 case FCVTZS_xs: |
1116 case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break; | 1149 case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break; |
1150 case FCVTPU_xd: | |
1151 case FCVTPU_ws: | |
1152 case FCVTPU_wd: | |
1153 case FCVTPU_xs: | |
1154 mnemonic = "fcvtpu"; | |
1155 form = form_rf; | |
1156 break; | |
1157 case FCVTPS_xd: | |
1158 case FCVTPS_wd: | |
1159 case FCVTPS_xs: | |
1160 case FCVTPS_ws: | |
1161 mnemonic = "fcvtps"; | |
1162 form = form_rf; | |
1163 break; | |
1117 case SCVTF_sw: | 1164 case SCVTF_sw: |
1118 case SCVTF_sx: | 1165 case SCVTF_sx: |
1119 case SCVTF_dw: | 1166 case SCVTF_dw: |
1120 case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break; | 1167 case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break; |
1121 case UCVTF_sw: | 1168 case UCVTF_sw: |
1122 case UCVTF_sx: | 1169 case UCVTF_sx: |
1123 case UCVTF_dw: | 1170 case UCVTF_dw: |
1124 case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break; | 1171 case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break; |
1125 } | 1172 } |
1126 Format(instr, mnemonic, form); | 1173 Format(instr, mnemonic, form); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1226 case HVC: mnemonic = "hvc"; break; | 1273 case HVC: mnemonic = "hvc"; break; |
1227 case SMC: mnemonic = "smc"; break; | 1274 case SMC: mnemonic = "smc"; break; |
1228 case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break; | 1275 case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break; |
1229 case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break; | 1276 case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break; |
1230 case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break; | 1277 case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break; |
1231 default: form = "(Exception)"; | 1278 default: form = "(Exception)"; |
1232 } | 1279 } |
1233 Format(instr, mnemonic, form); | 1280 Format(instr, mnemonic, form); |
1234 } | 1281 } |
1235 | 1282 |
1236 | 1283 void DisassemblingDecoder::VisitNEON3Same(Instruction *instr) { |
1237 void DisassemblingDecoder::VisitUnimplemented(Instruction* instr) { | 1284 const char *mnemonic = "unimplemented"; |
1285 const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; | |
1286 NEONFormatDecoder nfd(instr); | |
1287 | |
1288 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) { | |
1289 switch (instr->Mask(NEON3SameLogicalMask)) { | |
1290 case NEON_AND: | |
1291 mnemonic = "and"; | |
1292 break; | |
1293 case NEON_ORR: | |
1294 mnemonic = "orr"; | |
1295 if (instr->Rm() == instr->Rn()) { | |
1296 mnemonic = "mov"; | |
1297 form = "'Vd.%s, 'Vn.%s"; | |
1298 } | |
1299 break; | |
1300 case NEON_ORN: | |
1301 mnemonic = "orn"; | |
1302 break; | |
1303 case NEON_EOR: | |
1304 mnemonic = "eor"; | |
1305 break; | |
1306 case NEON_BIC: | |
1307 mnemonic = "bic"; | |
1308 break; | |
1309 case NEON_BIF: | |
1310 mnemonic = "bif"; | |
1311 break; | |
1312 case NEON_BIT: | |
1313 mnemonic = "bit"; | |
1314 break; | |
1315 case NEON_BSL: | |
1316 mnemonic = "bsl"; | |
1317 break; | |
1318 default: | |
1319 form = "(NEON3Same)"; | |
1320 } | |
1321 nfd.SetFormatMaps(nfd.LogicalFormatMap()); | |
1322 } else { | |
1323 static const char *mnemonics[] = { | |
1324 "shadd", "uhadd", "shadd", "uhadd", | |
1325 "sqadd", "uqadd", "sqadd", "uqadd", | |
1326 "srhadd", "urhadd", "srhadd", "urhadd", | |
1327 NULL, NULL, NULL, | |
1328 NULL, // Handled by logical cases above. | |
1329 "shsub", "uhsub", "shsub", "uhsub", | |
1330 "sqsub", "uqsub", "sqsub", "uqsub", | |
1331 "cmgt", "cmhi", "cmgt", "cmhi", | |
1332 "cmge", "cmhs", "cmge", "cmhs", | |
1333 "sshl", "ushl", "sshl", "ushl", | |
1334 "sqshl", "uqshl", "sqshl", "uqshl", | |
1335 "srshl", "urshl", "srshl", "urshl", | |
1336 "sqrshl", "uqrshl", "sqrshl", "uqrshl", | |
1337 "smax", "umax", "smax", "umax", | |
1338 "smin", "umin", "smin", "umin", | |
1339 "sabd", "uabd", "sabd", "uabd", | |
1340 "saba", "uaba", "saba", "uaba", | |
1341 "add", "sub", "add", "sub", | |
1342 "cmtst", "cmeq", "cmtst", "cmeq", | |
1343 "mla", "mls", "mla", "mls", | |
1344 "mul", "pmul", "mul", "pmul", | |
1345 "smaxp", "umaxp", "smaxp", "umaxp", | |
1346 "sminp", "uminp", "sminp", "uminp", | |
1347 "sqdmulh", "sqrdmulh", "sqdmulh", "sqrdmulh", | |
1348 "addp", "unallocated", "addp", "unallocated", | |
1349 "fmaxnm", "fmaxnmp", "fminnm", "fminnmp", | |
1350 "fmla", "unallocated", "fmls", "unallocated", | |
1351 "fadd", "faddp", "fsub", "fabd", | |
1352 "fmulx", "fmul", "unallocated", "unallocated", | |
1353 "fcmeq", "fcmge", "unallocated", "fcmgt", | |
1354 "unallocated", "facge", "unallocated", "facgt", | |
1355 "fmax", "fmaxp", "fmin", "fminp", | |
1356 "frecps", "fdiv", "frsqrts", "unallocated"}; | |
1357 | |
1358 // Operation is determined by the opcode bits (15-11), the top bit of | |
1359 // size (23) and the U bit (29). | |
1360 unsigned index = | |
1361 (instr->Bits(15, 11) << 2) | (instr->Bit(23) << 1) | instr->Bit(29); | |
1362 DCHECK_LT(index, arraysize(mnemonics)); | |
1363 mnemonic = mnemonics[index]; | |
1364 // Assert that index is not one of the previously handled logical | |
1365 // instructions. | |
1366 DCHECK_NOT_NULL(mnemonic); | |
1367 | |
1368 if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) { | |
1369 nfd.SetFormatMaps(nfd.FPFormatMap()); | |
1370 } | |
1371 } | |
1372 Format(instr, mnemonic, nfd.Substitute(form)); | |
1373 } | |
1374 | |
1375 void DisassemblingDecoder::VisitNEON2RegMisc(Instruction *instr) { | |
1376 const char *mnemonic = "unimplemented"; | |
1377 const char *form = "'Vd.%s, 'Vn.%s"; | |
1378 const char *form_cmp_zero = "'Vd.%s, 'Vn.%s, #0"; | |
1379 const char *form_fcmp_zero = "'Vd.%s, 'Vn.%s, #0.0"; | |
1380 NEONFormatDecoder nfd(instr); | |
1381 | |
1382 static const NEONFormatMap map_lp_ta = { | |
1383 {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}}; | |
bbudge
2017/01/31 01:41:32
Could you define some constants to make it clearer
martyn.capewell
2017/02/03 11:01:31
They're just bit positions in the instruction, so
bbudge
2017/02/08 01:39:11
I see. It's OK like this then.
| |
1384 | |
1385 static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}}; | |
1386 | |
1387 static const NEONFormatMap map_cvt_tb = {{22, 30}, | |
1388 {NF_4H, NF_8H, NF_2S, NF_4S}}; | |
1389 | |
1390 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) { | |
1391 // These instructions all use a two bit size field, except NOT and RBIT, | |
1392 // which use the field to encode the operation. | |
1393 switch (instr->Mask(NEON2RegMiscMask)) { | |
1394 case NEON_REV64: | |
1395 mnemonic = "rev64"; | |
1396 break; | |
1397 case NEON_REV32: | |
1398 mnemonic = "rev32"; | |
1399 break; | |
1400 case NEON_REV16: | |
1401 mnemonic = "rev16"; | |
1402 break; | |
1403 case NEON_SADDLP: | |
1404 mnemonic = "saddlp"; | |
1405 nfd.SetFormatMap(0, &map_lp_ta); | |
1406 break; | |
1407 case NEON_UADDLP: | |
1408 mnemonic = "uaddlp"; | |
1409 nfd.SetFormatMap(0, &map_lp_ta); | |
1410 break; | |
1411 case NEON_SUQADD: | |
1412 mnemonic = "suqadd"; | |
1413 break; | |
1414 case NEON_USQADD: | |
1415 mnemonic = "usqadd"; | |
1416 break; | |
1417 case NEON_CLS: | |
1418 mnemonic = "cls"; | |
1419 break; | |
1420 case NEON_CLZ: | |
1421 mnemonic = "clz"; | |
1422 break; | |
1423 case NEON_CNT: | |
1424 mnemonic = "cnt"; | |
1425 break; | |
1426 case NEON_SADALP: | |
1427 mnemonic = "sadalp"; | |
1428 nfd.SetFormatMap(0, &map_lp_ta); | |
1429 break; | |
1430 case NEON_UADALP: | |
1431 mnemonic = "uadalp"; | |
1432 nfd.SetFormatMap(0, &map_lp_ta); | |
1433 break; | |
1434 case NEON_SQABS: | |
1435 mnemonic = "sqabs"; | |
1436 break; | |
1437 case NEON_SQNEG: | |
1438 mnemonic = "sqneg"; | |
1439 break; | |
1440 case NEON_CMGT_zero: | |
1441 mnemonic = "cmgt"; | |
1442 form = form_cmp_zero; | |
1443 break; | |
1444 case NEON_CMGE_zero: | |
1445 mnemonic = "cmge"; | |
1446 form = form_cmp_zero; | |
1447 break; | |
1448 case NEON_CMEQ_zero: | |
1449 mnemonic = "cmeq"; | |
1450 form = form_cmp_zero; | |
1451 break; | |
1452 case NEON_CMLE_zero: | |
1453 mnemonic = "cmle"; | |
1454 form = form_cmp_zero; | |
1455 break; | |
1456 case NEON_CMLT_zero: | |
1457 mnemonic = "cmlt"; | |
1458 form = form_cmp_zero; | |
1459 break; | |
1460 case NEON_ABS: | |
1461 mnemonic = "abs"; | |
1462 break; | |
1463 case NEON_NEG: | |
1464 mnemonic = "neg"; | |
1465 break; | |
1466 case NEON_RBIT_NOT: | |
1467 switch (instr->FPType()) { | |
1468 case 0: | |
1469 mnemonic = "mvn"; | |
1470 break; | |
1471 case 1: | |
1472 mnemonic = "rbit"; | |
1473 break; | |
1474 default: | |
1475 form = "(NEON2RegMisc)"; | |
1476 } | |
1477 nfd.SetFormatMaps(nfd.LogicalFormatMap()); | |
1478 break; | |
1479 } | |
1480 } else { | |
1481 // These instructions all use a one bit size field, except XTN, SQXTUN, | |
1482 // SHLL, SQXTN and UQXTN, which use a two bit size field. | |
1483 nfd.SetFormatMaps(nfd.FPFormatMap()); | |
1484 switch (instr->Mask(NEON2RegMiscFPMask)) { | |
1485 case NEON_FABS: | |
1486 mnemonic = "fabs"; | |
1487 break; | |
1488 case NEON_FNEG: | |
1489 mnemonic = "fneg"; | |
1490 break; | |
1491 case NEON_FCVTN: | |
1492 mnemonic = instr->Mask(NEON_Q) ? "fcvtn2" : "fcvtn"; | |
1493 nfd.SetFormatMap(0, &map_cvt_tb); | |
1494 nfd.SetFormatMap(1, &map_cvt_ta); | |
1495 break; | |
1496 case NEON_FCVTXN: | |
1497 mnemonic = instr->Mask(NEON_Q) ? "fcvtxn2" : "fcvtxn"; | |
1498 nfd.SetFormatMap(0, &map_cvt_tb); | |
1499 nfd.SetFormatMap(1, &map_cvt_ta); | |
1500 break; | |
1501 case NEON_FCVTL: | |
1502 mnemonic = instr->Mask(NEON_Q) ? "fcvtl2" : "fcvtl"; | |
1503 nfd.SetFormatMap(0, &map_cvt_ta); | |
1504 nfd.SetFormatMap(1, &map_cvt_tb); | |
1505 break; | |
1506 case NEON_FRINTN: | |
1507 mnemonic = "frintn"; | |
1508 break; | |
1509 case NEON_FRINTA: | |
1510 mnemonic = "frinta"; | |
1511 break; | |
1512 case NEON_FRINTP: | |
1513 mnemonic = "frintp"; | |
1514 break; | |
1515 case NEON_FRINTM: | |
1516 mnemonic = "frintm"; | |
1517 break; | |
1518 case NEON_FRINTX: | |
1519 mnemonic = "frintx"; | |
1520 break; | |
1521 case NEON_FRINTZ: | |
1522 mnemonic = "frintz"; | |
1523 break; | |
1524 case NEON_FRINTI: | |
1525 mnemonic = "frinti"; | |
1526 break; | |
1527 case NEON_FCVTNS: | |
1528 mnemonic = "fcvtns"; | |
1529 break; | |
1530 case NEON_FCVTNU: | |
1531 mnemonic = "fcvtnu"; | |
1532 break; | |
1533 case NEON_FCVTPS: | |
1534 mnemonic = "fcvtps"; | |
1535 break; | |
1536 case NEON_FCVTPU: | |
1537 mnemonic = "fcvtpu"; | |
1538 break; | |
1539 case NEON_FCVTMS: | |
1540 mnemonic = "fcvtms"; | |
1541 break; | |
1542 case NEON_FCVTMU: | |
1543 mnemonic = "fcvtmu"; | |
1544 break; | |
1545 case NEON_FCVTZS: | |
1546 mnemonic = "fcvtzs"; | |
1547 break; | |
1548 case NEON_FCVTZU: | |
1549 mnemonic = "fcvtzu"; | |
1550 break; | |
1551 case NEON_FCVTAS: | |
1552 mnemonic = "fcvtas"; | |
1553 break; | |
1554 case NEON_FCVTAU: | |
1555 mnemonic = "fcvtau"; | |
1556 break; | |
1557 case NEON_FSQRT: | |
1558 mnemonic = "fsqrt"; | |
1559 break; | |
1560 case NEON_SCVTF: | |
1561 mnemonic = "scvtf"; | |
1562 break; | |
1563 case NEON_UCVTF: | |
1564 mnemonic = "ucvtf"; | |
1565 break; | |
1566 case NEON_URSQRTE: | |
1567 mnemonic = "ursqrte"; | |
1568 break; | |
1569 case NEON_URECPE: | |
1570 mnemonic = "urecpe"; | |
1571 break; | |
1572 case NEON_FRSQRTE: | |
1573 mnemonic = "frsqrte"; | |
1574 break; | |
1575 case NEON_FRECPE: | |
1576 mnemonic = "frecpe"; | |
1577 break; | |
1578 case NEON_FCMGT_zero: | |
1579 mnemonic = "fcmgt"; | |
1580 form = form_fcmp_zero; | |
1581 break; | |
1582 case NEON_FCMGE_zero: | |
1583 mnemonic = "fcmge"; | |
1584 form = form_fcmp_zero; | |
1585 break; | |
1586 case NEON_FCMEQ_zero: | |
1587 mnemonic = "fcmeq"; | |
1588 form = form_fcmp_zero; | |
1589 break; | |
1590 case NEON_FCMLE_zero: | |
1591 mnemonic = "fcmle"; | |
1592 form = form_fcmp_zero; | |
1593 break; | |
1594 case NEON_FCMLT_zero: | |
1595 mnemonic = "fcmlt"; | |
1596 form = form_fcmp_zero; | |
1597 break; | |
1598 default: | |
1599 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) && | |
1600 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) { | |
1601 nfd.SetFormatMap(0, nfd.IntegerFormatMap()); | |
1602 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap()); | |
1603 | |
1604 switch (instr->Mask(NEON2RegMiscMask)) { | |
1605 case NEON_XTN: | |
1606 mnemonic = "xtn"; | |
1607 break; | |
1608 case NEON_SQXTN: | |
1609 mnemonic = "sqxtn"; | |
1610 break; | |
1611 case NEON_UQXTN: | |
1612 mnemonic = "uqxtn"; | |
1613 break; | |
1614 case NEON_SQXTUN: | |
1615 mnemonic = "sqxtun"; | |
1616 break; | |
1617 case NEON_SHLL: | |
1618 mnemonic = "shll"; | |
1619 nfd.SetFormatMap(0, nfd.LongIntegerFormatMap()); | |
1620 nfd.SetFormatMap(1, nfd.IntegerFormatMap()); | |
1621 switch (instr->NEONSize()) { | |
1622 case 0: | |
1623 form = "'Vd.%s, 'Vn.%s, #8"; | |
1624 break; | |
1625 case 1: | |
1626 form = "'Vd.%s, 'Vn.%s, #16"; | |
1627 break; | |
1628 case 2: | |
1629 form = "'Vd.%s, 'Vn.%s, #32"; | |
1630 break; | |
1631 default: | |
1632 Format(instr, "unallocated", "(NEON2RegMisc)"); | |
1633 return; | |
1634 } | |
1635 } | |
1636 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form)); | |
1637 return; | |
1638 } else { | |
1639 form = "(NEON2RegMisc)"; | |
1640 } | |
1641 } | |
1642 } | |
1643 Format(instr, mnemonic, nfd.Substitute(form)); | |
1644 } | |
1645 | |
1646 void DisassemblingDecoder::VisitNEON3Different(Instruction *instr) { | |
1647 const char *mnemonic = "unimplemented"; | |
1648 const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; | |
1649 | |
1650 NEONFormatDecoder nfd(instr); | |
1651 nfd.SetFormatMap(0, nfd.LongIntegerFormatMap()); | |
1652 | |
1653 // Ignore the Q bit. Appending a "2" suffix is handled later. | |
1654 switch (instr->Mask(NEON3DifferentMask) & ~NEON_Q) { | |
1655 case NEON_PMULL: | |
1656 mnemonic = "pmull"; | |
1657 break; | |
1658 case NEON_SABAL: | |
1659 mnemonic = "sabal"; | |
1660 break; | |
1661 case NEON_SABDL: | |
1662 mnemonic = "sabdl"; | |
1663 break; | |
1664 case NEON_SADDL: | |
1665 mnemonic = "saddl"; | |
1666 break; | |
1667 case NEON_SMLAL: | |
1668 mnemonic = "smlal"; | |
1669 break; | |
1670 case NEON_SMLSL: | |
1671 mnemonic = "smlsl"; | |
1672 break; | |
1673 case NEON_SMULL: | |
1674 mnemonic = "smull"; | |
1675 break; | |
1676 case NEON_SSUBL: | |
1677 mnemonic = "ssubl"; | |
1678 break; | |
1679 case NEON_SQDMLAL: | |
1680 mnemonic = "sqdmlal"; | |
1681 break; | |
1682 case NEON_SQDMLSL: | |
1683 mnemonic = "sqdmlsl"; | |
1684 break; | |
1685 case NEON_SQDMULL: | |
1686 mnemonic = "sqdmull"; | |
1687 break; | |
1688 case NEON_UABAL: | |
1689 mnemonic = "uabal"; | |
1690 break; | |
1691 case NEON_UABDL: | |
1692 mnemonic = "uabdl"; | |
1693 break; | |
1694 case NEON_UADDL: | |
1695 mnemonic = "uaddl"; | |
1696 break; | |
1697 case NEON_UMLAL: | |
1698 mnemonic = "umlal"; | |
1699 break; | |
1700 case NEON_UMLSL: | |
1701 mnemonic = "umlsl"; | |
1702 break; | |
1703 case NEON_UMULL: | |
1704 mnemonic = "umull"; | |
1705 break; | |
1706 case NEON_USUBL: | |
1707 mnemonic = "usubl"; | |
1708 break; | |
1709 case NEON_SADDW: | |
1710 mnemonic = "saddw"; | |
1711 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap()); | |
1712 break; | |
1713 case NEON_SSUBW: | |
1714 mnemonic = "ssubw"; | |
1715 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap()); | |
1716 break; | |
1717 case NEON_UADDW: | |
1718 mnemonic = "uaddw"; | |
1719 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap()); | |
1720 break; | |
1721 case NEON_USUBW: | |
1722 mnemonic = "usubw"; | |
1723 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap()); | |
1724 break; | |
1725 case NEON_ADDHN: | |
1726 mnemonic = "addhn"; | |
1727 nfd.SetFormatMaps(nfd.LongIntegerFormatMap()); | |
1728 nfd.SetFormatMap(0, nfd.IntegerFormatMap()); | |
1729 break; | |
1730 case NEON_RADDHN: | |
1731 mnemonic = "raddhn"; | |
1732 nfd.SetFormatMaps(nfd.LongIntegerFormatMap()); | |
1733 nfd.SetFormatMap(0, nfd.IntegerFormatMap()); | |
1734 break; | |
1735 case NEON_RSUBHN: | |
1736 mnemonic = "rsubhn"; | |
1737 nfd.SetFormatMaps(nfd.LongIntegerFormatMap()); | |
1738 nfd.SetFormatMap(0, nfd.IntegerFormatMap()); | |
1739 break; | |
1740 case NEON_SUBHN: | |
1741 mnemonic = "subhn"; | |
1742 nfd.SetFormatMaps(nfd.LongIntegerFormatMap()); | |
1743 nfd.SetFormatMap(0, nfd.IntegerFormatMap()); | |
1744 break; | |
1745 default: | |
1746 form = "(NEON3Different)"; | |
1747 } | |
1748 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form)); | |
1749 } | |
1750 | |
1751 void DisassemblingDecoder::VisitNEONAcrossLanes(Instruction *instr) { | |
1752 const char *mnemonic = "unimplemented"; | |
1753 const char *form = "%sd, 'Vn.%s"; | |
1754 | |
1755 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap(), | |
1756 NEONFormatDecoder::IntegerFormatMap()); | |
1757 | |
1758 if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) { | |
1759 nfd.SetFormatMap(0, nfd.FPScalarFormatMap()); | |
1760 nfd.SetFormatMap(1, nfd.FPFormatMap()); | |
1761 switch (instr->Mask(NEONAcrossLanesFPMask)) { | |
1762 case NEON_FMAXV: | |
1763 mnemonic = "fmaxv"; | |
1764 break; | |
1765 case NEON_FMINV: | |
1766 mnemonic = "fminv"; | |
1767 break; | |
1768 case NEON_FMAXNMV: | |
1769 mnemonic = "fmaxnmv"; | |
1770 break; | |
1771 case NEON_FMINNMV: | |
1772 mnemonic = "fminnmv"; | |
1773 break; | |
1774 default: | |
1775 form = "(NEONAcrossLanes)"; | |
1776 break; | |
1777 } | |
1778 } else if (instr->Mask(NEONAcrossLanesFMask) == NEONAcrossLanesFixed) { | |
1779 switch (instr->Mask(NEONAcrossLanesMask)) { | |
1780 case NEON_ADDV: | |
1781 mnemonic = "addv"; | |
1782 break; | |
1783 case NEON_SMAXV: | |
1784 mnemonic = "smaxv"; | |
1785 break; | |
1786 case NEON_SMINV: | |
1787 mnemonic = "sminv"; | |
1788 break; | |
1789 case NEON_UMAXV: | |
1790 mnemonic = "umaxv"; | |
1791 break; | |
1792 case NEON_UMINV: | |
1793 mnemonic = "uminv"; | |
1794 break; | |
1795 case NEON_SADDLV: | |
1796 mnemonic = "saddlv"; | |
1797 nfd.SetFormatMap(0, nfd.LongScalarFormatMap()); | |
1798 break; | |
1799 case NEON_UADDLV: | |
1800 mnemonic = "uaddlv"; | |
1801 nfd.SetFormatMap(0, nfd.LongScalarFormatMap()); | |
1802 break; | |
1803 default: | |
1804 form = "(NEONAcrossLanes)"; | |
1805 break; | |
1806 } | |
1807 } | |
1808 Format(instr, mnemonic, nfd.Substitute(form, NEONFormatDecoder::kPlaceholder, | |
1809 NEONFormatDecoder::kFormat)); | |
1810 } | |
1811 | |
1812 void DisassemblingDecoder::VisitNEONByIndexedElement(Instruction *instr) { | |
1813 const char *mnemonic = "unimplemented"; | |
1814 bool l_instr = false; | |
1815 bool fp_instr = false; | |
1816 | |
1817 const char *form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]"; | |
1818 | |
1819 static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}}; | |
bbudge
2017/01/31 01:41:32
magic numbers
bbudge
2017/02/08 01:39:11
OK
| |
1820 NEONFormatDecoder nfd(instr, &map_ta, NEONFormatDecoder::IntegerFormatMap(), | |
1821 NEONFormatDecoder::ScalarFormatMap()); | |
1822 | |
1823 switch (instr->Mask(NEONByIndexedElementMask)) { | |
1824 case NEON_SMULL_byelement: | |
1825 mnemonic = "smull"; | |
1826 l_instr = true; | |
1827 break; | |
1828 case NEON_UMULL_byelement: | |
1829 mnemonic = "umull"; | |
1830 l_instr = true; | |
1831 break; | |
1832 case NEON_SMLAL_byelement: | |
1833 mnemonic = "smlal"; | |
1834 l_instr = true; | |
1835 break; | |
1836 case NEON_UMLAL_byelement: | |
1837 mnemonic = "umlal"; | |
1838 l_instr = true; | |
1839 break; | |
1840 case NEON_SMLSL_byelement: | |
1841 mnemonic = "smlsl"; | |
1842 l_instr = true; | |
1843 break; | |
1844 case NEON_UMLSL_byelement: | |
1845 mnemonic = "umlsl"; | |
1846 l_instr = true; | |
1847 break; | |
1848 case NEON_SQDMULL_byelement: | |
1849 mnemonic = "sqdmull"; | |
1850 l_instr = true; | |
1851 break; | |
1852 case NEON_SQDMLAL_byelement: | |
1853 mnemonic = "sqdmlal"; | |
1854 l_instr = true; | |
1855 break; | |
1856 case NEON_SQDMLSL_byelement: | |
1857 mnemonic = "sqdmlsl"; | |
1858 l_instr = true; | |
1859 break; | |
1860 case NEON_MUL_byelement: | |
1861 mnemonic = "mul"; | |
1862 break; | |
1863 case NEON_MLA_byelement: | |
1864 mnemonic = "mla"; | |
1865 break; | |
1866 case NEON_MLS_byelement: | |
1867 mnemonic = "mls"; | |
1868 break; | |
1869 case NEON_SQDMULH_byelement: | |
1870 mnemonic = "sqdmulh"; | |
1871 break; | |
1872 case NEON_SQRDMULH_byelement: | |
1873 mnemonic = "sqrdmulh"; | |
1874 break; | |
1875 default: | |
1876 switch (instr->Mask(NEONByIndexedElementFPMask)) { | |
1877 case NEON_FMUL_byelement: | |
1878 mnemonic = "fmul"; | |
1879 fp_instr = true; | |
1880 break; | |
1881 case NEON_FMLA_byelement: | |
1882 mnemonic = "fmla"; | |
1883 fp_instr = true; | |
1884 break; | |
1885 case NEON_FMLS_byelement: | |
1886 mnemonic = "fmls"; | |
1887 fp_instr = true; | |
1888 break; | |
1889 case NEON_FMULX_byelement: | |
1890 mnemonic = "fmulx"; | |
1891 fp_instr = true; | |
1892 break; | |
1893 } | |
1894 } | |
1895 | |
1896 if (l_instr) { | |
1897 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form)); | |
1898 } else if (fp_instr) { | |
1899 nfd.SetFormatMap(0, nfd.FPFormatMap()); | |
1900 Format(instr, mnemonic, nfd.Substitute(form)); | |
1901 } else { | |
1902 nfd.SetFormatMap(0, nfd.IntegerFormatMap()); | |
1903 Format(instr, mnemonic, nfd.Substitute(form)); | |
1904 } | |
1905 } | |
1906 | |
1907 void DisassemblingDecoder::VisitNEONCopy(Instruction *instr) { | |
1908 const char *mnemonic = "unimplemented"; | |
1909 const char *form = "(NEONCopy)"; | |
1910 | |
1911 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap(), | |
1912 NEONFormatDecoder::TriangularScalarFormatMap()); | |
1913 | |
1914 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) { | |
1915 mnemonic = "mov"; | |
1916 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap()); | |
1917 form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]"; | |
1918 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) { | |
1919 mnemonic = "mov"; | |
1920 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap()); | |
1921 if (nfd.GetVectorFormat() == kFormatD) { | |
1922 form = "'Vd.%s['IVInsIndex1], 'Xn"; | |
1923 } else { | |
1924 form = "'Vd.%s['IVInsIndex1], 'Wn"; | |
1925 } | |
1926 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) { | |
1927 if (instr->Mask(NEON_Q) || ((instr->ImmNEON5() & 7) == 4)) { | |
1928 mnemonic = "mov"; | |
1929 } else { | |
1930 mnemonic = "umov"; | |
1931 } | |
1932 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap()); | |
1933 if (nfd.GetVectorFormat() == kFormatD) { | |
1934 form = "'Xd, 'Vn.%s['IVInsIndex1]"; | |
1935 } else { | |
1936 form = "'Wd, 'Vn.%s['IVInsIndex1]"; | |
1937 } | |
1938 } else if (instr->Mask(NEONCopySmovMask) == NEON_SMOV) { | |
1939 mnemonic = "smov"; | |
1940 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap()); | |
1941 form = "'Rdq, 'Vn.%s['IVInsIndex1]"; | |
1942 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) { | |
1943 mnemonic = "dup"; | |
1944 form = "'Vd.%s, 'Vn.%s['IVInsIndex1]"; | |
1945 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) { | |
1946 mnemonic = "dup"; | |
1947 if (nfd.GetVectorFormat() == kFormat2D) { | |
1948 form = "'Vd.%s, 'Xn"; | |
1949 } else { | |
1950 form = "'Vd.%s, 'Wn"; | |
1951 } | |
1952 } | |
1953 Format(instr, mnemonic, nfd.Substitute(form)); | |
1954 } | |
1955 | |
1956 void DisassemblingDecoder::VisitNEONExtract(Instruction *instr) { | |
1957 const char *mnemonic = "unimplemented"; | |
1958 const char *form = "(NEONExtract)"; | |
1959 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap()); | |
1960 if (instr->Mask(NEONExtractMask) == NEON_EXT) { | |
1961 mnemonic = "ext"; | |
1962 form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract"; | |
1963 } | |
1964 Format(instr, mnemonic, nfd.Substitute(form)); | |
1965 } | |
1966 | |
1967 void DisassemblingDecoder::VisitNEONLoadStoreMultiStruct(Instruction *instr) { | |
1968 const char *mnemonic = NULL; | |
1969 const char *form = NULL; | |
1970 const char *form_1v = "{'Vt.%1$s}, ['Xns]"; | |
1971 const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]"; | |
1972 const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]"; | |
1973 const char *form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]"; | |
1974 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); | |
1975 | |
1976 switch (instr->Mask(NEONLoadStoreMultiStructMask)) { | |
1977 case NEON_LD1_1v: | |
1978 mnemonic = "ld1"; | |
1979 form = form_1v; | |
1980 break; | |
1981 case NEON_LD1_2v: | |
1982 mnemonic = "ld1"; | |
1983 form = form_2v; | |
1984 break; | |
1985 case NEON_LD1_3v: | |
1986 mnemonic = "ld1"; | |
1987 form = form_3v; | |
1988 break; | |
1989 case NEON_LD1_4v: | |
1990 mnemonic = "ld1"; | |
1991 form = form_4v; | |
1992 break; | |
1993 case NEON_LD2: | |
1994 mnemonic = "ld2"; | |
1995 form = form_2v; | |
1996 break; | |
1997 case NEON_LD3: | |
1998 mnemonic = "ld3"; | |
1999 form = form_3v; | |
2000 break; | |
2001 case NEON_LD4: | |
2002 mnemonic = "ld4"; | |
2003 form = form_4v; | |
2004 break; | |
2005 case NEON_ST1_1v: | |
2006 mnemonic = "st1"; | |
2007 form = form_1v; | |
2008 break; | |
2009 case NEON_ST1_2v: | |
2010 mnemonic = "st1"; | |
2011 form = form_2v; | |
2012 break; | |
2013 case NEON_ST1_3v: | |
2014 mnemonic = "st1"; | |
2015 form = form_3v; | |
2016 break; | |
2017 case NEON_ST1_4v: | |
2018 mnemonic = "st1"; | |
2019 form = form_4v; | |
2020 break; | |
2021 case NEON_ST2: | |
2022 mnemonic = "st2"; | |
2023 form = form_2v; | |
2024 break; | |
2025 case NEON_ST3: | |
2026 mnemonic = "st3"; | |
2027 form = form_3v; | |
2028 break; | |
2029 case NEON_ST4: | |
2030 mnemonic = "st4"; | |
2031 form = form_4v; | |
2032 break; | |
2033 default: | |
2034 break; | |
2035 } | |
2036 | |
2037 // Work out unallocated encodings. | |
2038 bool allocated = (mnemonic != NULL); | |
2039 switch (instr->Mask(NEONLoadStoreMultiStructMask)) { | |
2040 case NEON_LD2: | |
2041 case NEON_LD3: | |
2042 case NEON_LD4: | |
2043 case NEON_ST2: | |
2044 case NEON_ST3: | |
2045 case NEON_ST4: | |
2046 // LD[2-4] and ST[2-4] cannot use .1d format. | |
2047 allocated = (instr->NEONQ() != 0) || (instr->NEONLSSize() != 3); | |
2048 break; | |
2049 default: | |
2050 break; | |
2051 } | |
2052 if (allocated) { | |
2053 DCHECK_NOT_NULL(mnemonic); | |
2054 DCHECK_NOT_NULL(form); | |
2055 } else { | |
2056 mnemonic = "unallocated"; | |
2057 form = "(NEONLoadStoreMultiStruct)"; | |
2058 } | |
2059 | |
2060 Format(instr, mnemonic, nfd.Substitute(form)); | |
2061 } | |
2062 | |
2063 void DisassemblingDecoder::VisitNEONLoadStoreMultiStructPostIndex( | |
2064 Instruction *instr) { | |
2065 const char *mnemonic = NULL; | |
2066 const char *form = NULL; | |
2067 const char *form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1"; | |
2068 const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2"; | |
2069 const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3"; | |
2070 const char *form_4v = | |
2071 "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4"; | |
2072 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); | |
2073 | |
2074 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) { | |
2075 case NEON_LD1_1v_post: | |
2076 mnemonic = "ld1"; | |
2077 form = form_1v; | |
2078 break; | |
2079 case NEON_LD1_2v_post: | |
2080 mnemonic = "ld1"; | |
2081 form = form_2v; | |
2082 break; | |
2083 case NEON_LD1_3v_post: | |
2084 mnemonic = "ld1"; | |
2085 form = form_3v; | |
2086 break; | |
2087 case NEON_LD1_4v_post: | |
2088 mnemonic = "ld1"; | |
2089 form = form_4v; | |
2090 break; | |
2091 case NEON_LD2_post: | |
2092 mnemonic = "ld2"; | |
2093 form = form_2v; | |
2094 break; | |
2095 case NEON_LD3_post: | |
2096 mnemonic = "ld3"; | |
2097 form = form_3v; | |
2098 break; | |
2099 case NEON_LD4_post: | |
2100 mnemonic = "ld4"; | |
2101 form = form_4v; | |
2102 break; | |
2103 case NEON_ST1_1v_post: | |
2104 mnemonic = "st1"; | |
2105 form = form_1v; | |
2106 break; | |
2107 case NEON_ST1_2v_post: | |
2108 mnemonic = "st1"; | |
2109 form = form_2v; | |
2110 break; | |
2111 case NEON_ST1_3v_post: | |
2112 mnemonic = "st1"; | |
2113 form = form_3v; | |
2114 break; | |
2115 case NEON_ST1_4v_post: | |
2116 mnemonic = "st1"; | |
2117 form = form_4v; | |
2118 break; | |
2119 case NEON_ST2_post: | |
2120 mnemonic = "st2"; | |
2121 form = form_2v; | |
2122 break; | |
2123 case NEON_ST3_post: | |
2124 mnemonic = "st3"; | |
2125 form = form_3v; | |
2126 break; | |
2127 case NEON_ST4_post: | |
2128 mnemonic = "st4"; | |
2129 form = form_4v; | |
2130 break; | |
2131 default: | |
2132 break; | |
2133 } | |
2134 | |
2135 // Work out unallocated encodings. | |
2136 bool allocated = (mnemonic != NULL); | |
2137 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) { | |
2138 case NEON_LD2_post: | |
2139 case NEON_LD3_post: | |
2140 case NEON_LD4_post: | |
2141 case NEON_ST2_post: | |
2142 case NEON_ST3_post: | |
2143 case NEON_ST4_post: | |
2144 // LD[2-4] and ST[2-4] cannot use .1d format. | |
2145 allocated = (instr->NEONQ() != 0) || (instr->NEONLSSize() != 3); | |
2146 break; | |
2147 default: | |
2148 break; | |
2149 } | |
2150 if (allocated) { | |
2151 DCHECK_NOT_NULL(mnemonic); | |
2152 DCHECK_NOT_NULL(form); | |
2153 } else { | |
2154 mnemonic = "unallocated"; | |
2155 form = "(NEONLoadStoreMultiStructPostIndex)"; | |
2156 } | |
2157 | |
2158 Format(instr, mnemonic, nfd.Substitute(form)); | |
2159 } | |
2160 | |
2161 void DisassemblingDecoder::VisitNEONLoadStoreSingleStruct(Instruction *instr) { | |
2162 const char *mnemonic = NULL; | |
2163 const char *form = NULL; | |
2164 | |
2165 const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns]"; | |
2166 const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns]"; | |
2167 const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns]"; | |
2168 const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns]"; | |
2169 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); | |
2170 | |
2171 switch (instr->Mask(NEONLoadStoreSingleStructMask)) { | |
2172 case NEON_LD1_b: | |
2173 mnemonic = "ld1"; | |
2174 form = form_1b; | |
2175 break; | |
2176 case NEON_LD1_h: | |
2177 mnemonic = "ld1"; | |
2178 form = form_1h; | |
2179 break; | |
2180 case NEON_LD1_s: | |
2181 mnemonic = "ld1"; | |
2182 static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d, | |
2183 "LSB of size distinguishes S and D registers."); | |
2184 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d; | |
2185 break; | |
2186 case NEON_ST1_b: | |
2187 mnemonic = "st1"; | |
2188 form = form_1b; | |
2189 break; | |
2190 case NEON_ST1_h: | |
2191 mnemonic = "st1"; | |
2192 form = form_1h; | |
2193 break; | |
2194 case NEON_ST1_s: | |
2195 mnemonic = "st1"; | |
2196 static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d, | |
2197 "LSB of size distinguishes S and D registers."); | |
2198 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d; | |
2199 break; | |
2200 case NEON_LD1R: | |
2201 mnemonic = "ld1r"; | |
2202 form = "{'Vt.%s}, ['Xns]"; | |
2203 break; | |
2204 case NEON_LD2_b: | |
2205 case NEON_ST2_b: | |
2206 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2"; | |
2207 form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]"; | |
2208 break; | |
2209 case NEON_LD2_h: | |
2210 case NEON_ST2_h: | |
2211 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2"; | |
2212 form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]"; | |
2213 break; | |
2214 case NEON_LD2_s: | |
2215 case NEON_ST2_s: | |
2216 static_assert((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d, | |
2217 "LSB of size distinguishes S and D registers."); | |
2218 static_assert((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d, | |
2219 "LSB of size distinguishes S and D registers."); | |
2220 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2"; | |
2221 if ((instr->NEONLSSize() & 1) == 0) { | |
2222 form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]"; | |
2223 } else { | |
2224 form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]"; | |
2225 } | |
2226 break; | |
2227 case NEON_LD2R: | |
2228 mnemonic = "ld2r"; | |
2229 form = "{'Vt.%s, 'Vt2.%s}, ['Xns]"; | |
2230 break; | |
2231 case NEON_LD3_b: | |
2232 case NEON_ST3_b: | |
2233 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3"; | |
2234 form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]"; | |
2235 break; | |
2236 case NEON_LD3_h: | |
2237 case NEON_ST3_h: | |
2238 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3"; | |
2239 form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]"; | |
2240 break; | |
2241 case NEON_LD3_s: | |
2242 case NEON_ST3_s: | |
2243 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3"; | |
2244 if ((instr->NEONLSSize() & 1) == 0) { | |
2245 form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]"; | |
2246 } else { | |
2247 form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]"; | |
2248 } | |
2249 break; | |
2250 case NEON_LD3R: | |
2251 mnemonic = "ld3r"; | |
2252 form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]"; | |
2253 break; | |
2254 case NEON_LD4_b: | |
2255 case NEON_ST4_b: | |
2256 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4"; | |
2257 form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]"; | |
2258 break; | |
2259 case NEON_LD4_h: | |
2260 case NEON_ST4_h: | |
2261 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4"; | |
2262 form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]"; | |
2263 break; | |
2264 case NEON_LD4_s: | |
2265 case NEON_ST4_s: | |
2266 static_assert((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d, | |
2267 "LSB of size distinguishes S and D registers."); | |
2268 static_assert((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d, | |
2269 "LSB of size distinguishes S and D registers."); | |
2270 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4"; | |
2271 if ((instr->NEONLSSize() & 1) == 0) { | |
2272 form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]"; | |
2273 } else { | |
2274 form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]"; | |
2275 } | |
2276 break; | |
2277 case NEON_LD4R: | |
2278 mnemonic = "ld4r"; | |
2279 form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]"; | |
2280 break; | |
2281 default: | |
2282 break; | |
2283 } | |
2284 | |
2285 // Work out unallocated encodings. | |
2286 bool allocated = (mnemonic != NULL); | |
2287 switch (instr->Mask(NEONLoadStoreSingleStructMask)) { | |
2288 case NEON_LD1_h: | |
2289 case NEON_LD2_h: | |
2290 case NEON_LD3_h: | |
2291 case NEON_LD4_h: | |
2292 case NEON_ST1_h: | |
2293 case NEON_ST2_h: | |
2294 case NEON_ST3_h: | |
2295 case NEON_ST4_h: | |
2296 DCHECK(allocated); | |
2297 allocated = ((instr->NEONLSSize() & 1) == 0); | |
2298 break; | |
2299 case NEON_LD1_s: | |
2300 case NEON_LD2_s: | |
2301 case NEON_LD3_s: | |
2302 case NEON_LD4_s: | |
2303 case NEON_ST1_s: | |
2304 case NEON_ST2_s: | |
2305 case NEON_ST3_s: | |
2306 case NEON_ST4_s: | |
2307 DCHECK(allocated); | |
2308 allocated = (instr->NEONLSSize() <= 1) && | |
2309 ((instr->NEONLSSize() == 0) || (instr->NEONS() == 0)); | |
2310 break; | |
2311 case NEON_LD1R: | |
2312 case NEON_LD2R: | |
2313 case NEON_LD3R: | |
2314 case NEON_LD4R: | |
2315 DCHECK(allocated); | |
2316 allocated = (instr->NEONS() == 0); | |
2317 break; | |
2318 default: | |
2319 break; | |
2320 } | |
2321 if (allocated) { | |
2322 DCHECK_NOT_NULL(mnemonic); | |
2323 DCHECK_NOT_NULL(form); | |
2324 } else { | |
2325 mnemonic = "unallocated"; | |
2326 form = "(NEONLoadStoreSingleStruct)"; | |
2327 } | |
2328 | |
2329 Format(instr, mnemonic, nfd.Substitute(form)); | |
2330 } | |
2331 | |
2332 void DisassemblingDecoder::VisitNEONLoadStoreSingleStructPostIndex( | |
2333 Instruction *instr) { | |
2334 const char *mnemonic = NULL; | |
2335 const char *form = NULL; | |
2336 | |
2337 const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1"; | |
2338 const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2"; | |
2339 const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4"; | |
2340 const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8"; | |
2341 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); | |
2342 | |
2343 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) { | |
2344 case NEON_LD1_b_post: | |
2345 mnemonic = "ld1"; | |
2346 form = form_1b; | |
2347 break; | |
2348 case NEON_LD1_h_post: | |
2349 mnemonic = "ld1"; | |
2350 form = form_1h; | |
2351 break; | |
2352 case NEON_LD1_s_post: | |
2353 mnemonic = "ld1"; | |
2354 static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d, | |
2355 "LSB of size distinguishes S and D registers."); | |
2356 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d; | |
2357 break; | |
2358 case NEON_ST1_b_post: | |
2359 mnemonic = "st1"; | |
2360 form = form_1b; | |
2361 break; | |
2362 case NEON_ST1_h_post: | |
2363 mnemonic = "st1"; | |
2364 form = form_1h; | |
2365 break; | |
2366 case NEON_ST1_s_post: | |
2367 mnemonic = "st1"; | |
2368 static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d, | |
2369 "LSB of size distinguishes S and D registers."); | |
2370 form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d; | |
2371 break; | |
2372 case NEON_LD1R_post: | |
2373 mnemonic = "ld1r"; | |
2374 form = "{'Vt.%s}, ['Xns], 'Xmz1"; | |
2375 break; | |
2376 case NEON_LD2_b_post: | |
2377 case NEON_ST2_b_post: | |
2378 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2"; | |
2379 form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2"; | |
2380 break; | |
2381 case NEON_ST2_h_post: | |
2382 case NEON_LD2_h_post: | |
2383 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2"; | |
2384 form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4"; | |
2385 break; | |
2386 case NEON_LD2_s_post: | |
2387 case NEON_ST2_s_post: | |
2388 mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2"; | |
2389 if ((instr->NEONLSSize() & 1) == 0) | |
2390 form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8"; | |
2391 else | |
2392 form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16"; | |
2393 break; | |
2394 case NEON_LD2R_post: | |
2395 mnemonic = "ld2r"; | |
2396 form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2"; | |
2397 break; | |
2398 case NEON_LD3_b_post: | |
2399 case NEON_ST3_b_post: | |
2400 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3"; | |
2401 form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3"; | |
2402 break; | |
2403 case NEON_LD3_h_post: | |
2404 case NEON_ST3_h_post: | |
2405 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3"; | |
2406 form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6"; | |
2407 break; | |
2408 case NEON_LD3_s_post: | |
2409 case NEON_ST3_s_post: | |
2410 mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3"; | |
2411 if ((instr->NEONLSSize() & 1) == 0) | |
2412 form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12"; | |
2413 else | |
2414 form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24"; | |
2415 break; | |
2416 case NEON_LD3R_post: | |
2417 mnemonic = "ld3r"; | |
2418 form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3"; | |
2419 break; | |
2420 case NEON_LD4_b_post: | |
2421 case NEON_ST4_b_post: | |
2422 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4"; | |
2423 form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4"; | |
2424 break; | |
2425 case NEON_LD4_h_post: | |
2426 case NEON_ST4_h_post: | |
2427 mnemonic = (instr->NEONLoad()) == 1 ? "ld4" : "st4"; | |
2428 form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8"; | |
2429 break; | |
2430 case NEON_LD4_s_post: | |
2431 case NEON_ST4_s_post: | |
2432 mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4"; | |
2433 if ((instr->NEONLSSize() & 1) == 0) | |
2434 form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16"; | |
2435 else | |
2436 form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32"; | |
2437 break; | |
2438 case NEON_LD4R_post: | |
2439 mnemonic = "ld4r"; | |
2440 form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4"; | |
2441 break; | |
2442 default: | |
2443 break; | |
2444 } | |
2445 | |
2446 // Work out unallocated encodings. | |
2447 bool allocated = (mnemonic != NULL); | |
2448 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) { | |
2449 case NEON_LD1_h_post: | |
2450 case NEON_LD2_h_post: | |
2451 case NEON_LD3_h_post: | |
2452 case NEON_LD4_h_post: | |
2453 case NEON_ST1_h_post: | |
2454 case NEON_ST2_h_post: | |
2455 case NEON_ST3_h_post: | |
2456 case NEON_ST4_h_post: | |
2457 DCHECK(allocated); | |
2458 allocated = ((instr->NEONLSSize() & 1) == 0); | |
2459 break; | |
2460 case NEON_LD1_s_post: | |
2461 case NEON_LD2_s_post: | |
2462 case NEON_LD3_s_post: | |
2463 case NEON_LD4_s_post: | |
2464 case NEON_ST1_s_post: | |
2465 case NEON_ST2_s_post: | |
2466 case NEON_ST3_s_post: | |
2467 case NEON_ST4_s_post: | |
2468 DCHECK(allocated); | |
2469 allocated = (instr->NEONLSSize() <= 1) && | |
2470 ((instr->NEONLSSize() == 0) || (instr->NEONS() == 0)); | |
2471 break; | |
2472 case NEON_LD1R_post: | |
2473 case NEON_LD2R_post: | |
2474 case NEON_LD3R_post: | |
2475 case NEON_LD4R_post: | |
2476 DCHECK(allocated); | |
2477 allocated = (instr->NEONS() == 0); | |
2478 break; | |
2479 default: | |
2480 break; | |
2481 } | |
2482 if (allocated) { | |
2483 DCHECK_NOT_NULL(mnemonic); | |
2484 DCHECK_NOT_NULL(form); | |
2485 } else { | |
2486 mnemonic = "unallocated"; | |
2487 form = "(NEONLoadStoreSingleStructPostIndex)"; | |
2488 } | |
2489 | |
2490 Format(instr, mnemonic, nfd.Substitute(form)); | |
2491 } | |
2492 | |
2493 void DisassemblingDecoder::VisitNEONModifiedImmediate(Instruction *instr) { | |
2494 const char *mnemonic = "unimplemented"; | |
2495 const char *form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1"; | |
2496 | |
2497 int cmode = instr->NEONCmode(); | |
2498 int cmode_3 = (cmode >> 3) & 1; | |
2499 int cmode_2 = (cmode >> 2) & 1; | |
2500 int cmode_1 = (cmode >> 1) & 1; | |
2501 int cmode_0 = cmode & 1; | |
2502 int q = instr->NEONQ(); | |
2503 int op = instr->NEONModImmOp(); | |
2504 | |
2505 static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}}; | |
2506 static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}}; | |
2507 static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}}; | |
2508 NEONFormatDecoder nfd(instr, &map_b); | |
2509 | |
2510 if (cmode_3 == 0) { | |
2511 if (cmode_0 == 0) { | |
2512 mnemonic = (op == 1) ? "mvni" : "movi"; | |
2513 } else { // cmode<0> == '1'. | |
2514 mnemonic = (op == 1) ? "bic" : "orr"; | |
2515 } | |
2516 nfd.SetFormatMap(0, &map_s); | |
2517 } else { // cmode<3> == '1'. | |
2518 if (cmode_2 == 0) { | |
2519 if (cmode_0 == 0) { | |
2520 mnemonic = (op == 1) ? "mvni" : "movi"; | |
2521 } else { // cmode<0> == '1'. | |
2522 mnemonic = (op == 1) ? "bic" : "orr"; | |
2523 } | |
2524 nfd.SetFormatMap(0, &map_h); | |
2525 } else { // cmode<2> == '1'. | |
2526 if (cmode_1 == 0) { | |
2527 mnemonic = (op == 1) ? "mvni" : "movi"; | |
2528 form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2"; | |
2529 nfd.SetFormatMap(0, &map_s); | |
2530 } else { // cmode<1> == '1'. | |
2531 if (cmode_0 == 0) { | |
2532 mnemonic = "movi"; | |
2533 if (op == 0) { | |
2534 form = "'Vt.%s, 'IVMIImm8"; | |
2535 } else { | |
2536 form = (q == 0) ? "'Dd, 'IVMIImm" : "'Vt.2d, 'IVMIImm"; | |
2537 } | |
2538 } else { // cmode<0> == '1' | |
2539 mnemonic = "fmov"; | |
2540 if (op == 0) { | |
2541 form = "'Vt.%s, 'IVMIImmFPSingle"; | |
2542 nfd.SetFormatMap(0, &map_s); | |
2543 } else { | |
2544 if (q == 1) { | |
2545 form = "'Vt.2d, 'IVMIImmFPDouble"; | |
2546 } else { | |
2547 mnemonic = "unallocated"; | |
2548 form = "(NEONModifiedImmediate)"; | |
2549 } | |
2550 } | |
2551 } | |
2552 } | |
2553 } | |
2554 } | |
2555 Format(instr, mnemonic, nfd.Substitute(form)); | |
2556 } | |
2557 | |
2558 void DisassemblingDecoder::VisitNEONPerm(Instruction *instr) { | |
2559 const char *mnemonic = "unimplemented"; | |
2560 const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; | |
2561 NEONFormatDecoder nfd(instr); | |
2562 | |
2563 switch (instr->Mask(NEONPermMask)) { | |
2564 case NEON_TRN1: | |
2565 mnemonic = "trn1"; | |
2566 break; | |
2567 case NEON_TRN2: | |
2568 mnemonic = "trn2"; | |
2569 break; | |
2570 case NEON_UZP1: | |
2571 mnemonic = "uzp1"; | |
2572 break; | |
2573 case NEON_UZP2: | |
2574 mnemonic = "uzp2"; | |
2575 break; | |
2576 case NEON_ZIP1: | |
2577 mnemonic = "zip1"; | |
2578 break; | |
2579 case NEON_ZIP2: | |
2580 mnemonic = "zip2"; | |
2581 break; | |
2582 default: | |
2583 form = "(NEONPerm)"; | |
2584 } | |
2585 Format(instr, mnemonic, nfd.Substitute(form)); | |
2586 } | |
2587 | |
2588 void DisassemblingDecoder::VisitNEONScalar2RegMisc(Instruction *instr) { | |
2589 const char *mnemonic = "unimplemented"; | |
2590 const char *form = "%sd, %sn"; | |
2591 const char *form_0 = "%sd, %sn, #0"; | |
2592 const char *form_fp0 = "%sd, %sn, #0.0"; | |
2593 | |
2594 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); | |
2595 | |
2596 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) { | |
2597 // These instructions all use a two bit size field, except NOT and RBIT, | |
2598 // which use the field to encode the operation. | |
2599 switch (instr->Mask(NEONScalar2RegMiscMask)) { | |
2600 case NEON_CMGT_zero_scalar: | |
2601 mnemonic = "cmgt"; | |
2602 form = form_0; | |
2603 break; | |
2604 case NEON_CMGE_zero_scalar: | |
2605 mnemonic = "cmge"; | |
2606 form = form_0; | |
2607 break; | |
2608 case NEON_CMLE_zero_scalar: | |
2609 mnemonic = "cmle"; | |
2610 form = form_0; | |
2611 break; | |
2612 case NEON_CMLT_zero_scalar: | |
2613 mnemonic = "cmlt"; | |
2614 form = form_0; | |
2615 break; | |
2616 case NEON_CMEQ_zero_scalar: | |
2617 mnemonic = "cmeq"; | |
2618 form = form_0; | |
2619 break; | |
2620 case NEON_NEG_scalar: | |
2621 mnemonic = "neg"; | |
2622 break; | |
2623 case NEON_SQNEG_scalar: | |
2624 mnemonic = "sqneg"; | |
2625 break; | |
2626 case NEON_ABS_scalar: | |
2627 mnemonic = "abs"; | |
2628 break; | |
2629 case NEON_SQABS_scalar: | |
2630 mnemonic = "sqabs"; | |
2631 break; | |
2632 case NEON_SUQADD_scalar: | |
2633 mnemonic = "suqadd"; | |
2634 break; | |
2635 case NEON_USQADD_scalar: | |
2636 mnemonic = "usqadd"; | |
2637 break; | |
2638 default: | |
2639 form = "(NEONScalar2RegMisc)"; | |
2640 } | |
2641 } else { | |
2642 // These instructions all use a one bit size field, except SQXTUN, SQXTN | |
2643 // and UQXTN, which use a two bit size field. | |
2644 nfd.SetFormatMaps(nfd.FPScalarFormatMap()); | |
2645 switch (instr->Mask(NEONScalar2RegMiscFPMask)) { | |
2646 case NEON_FRSQRTE_scalar: | |
2647 mnemonic = "frsqrte"; | |
2648 break; | |
2649 case NEON_FRECPE_scalar: | |
2650 mnemonic = "frecpe"; | |
2651 break; | |
2652 case NEON_SCVTF_scalar: | |
2653 mnemonic = "scvtf"; | |
2654 break; | |
2655 case NEON_UCVTF_scalar: | |
2656 mnemonic = "ucvtf"; | |
2657 break; | |
2658 case NEON_FCMGT_zero_scalar: | |
2659 mnemonic = "fcmgt"; | |
2660 form = form_fp0; | |
2661 break; | |
2662 case NEON_FCMGE_zero_scalar: | |
2663 mnemonic = "fcmge"; | |
2664 form = form_fp0; | |
2665 break; | |
2666 case NEON_FCMLE_zero_scalar: | |
2667 mnemonic = "fcmle"; | |
2668 form = form_fp0; | |
2669 break; | |
2670 case NEON_FCMLT_zero_scalar: | |
2671 mnemonic = "fcmlt"; | |
2672 form = form_fp0; | |
2673 break; | |
2674 case NEON_FCMEQ_zero_scalar: | |
2675 mnemonic = "fcmeq"; | |
2676 form = form_fp0; | |
2677 break; | |
2678 case NEON_FRECPX_scalar: | |
2679 mnemonic = "frecpx"; | |
2680 break; | |
2681 case NEON_FCVTNS_scalar: | |
2682 mnemonic = "fcvtns"; | |
2683 break; | |
2684 case NEON_FCVTNU_scalar: | |
2685 mnemonic = "fcvtnu"; | |
2686 break; | |
2687 case NEON_FCVTPS_scalar: | |
2688 mnemonic = "fcvtps"; | |
2689 break; | |
2690 case NEON_FCVTPU_scalar: | |
2691 mnemonic = "fcvtpu"; | |
2692 break; | |
2693 case NEON_FCVTMS_scalar: | |
2694 mnemonic = "fcvtms"; | |
2695 break; | |
2696 case NEON_FCVTMU_scalar: | |
2697 mnemonic = "fcvtmu"; | |
2698 break; | |
2699 case NEON_FCVTZS_scalar: | |
2700 mnemonic = "fcvtzs"; | |
2701 break; | |
2702 case NEON_FCVTZU_scalar: | |
2703 mnemonic = "fcvtzu"; | |
2704 break; | |
2705 case NEON_FCVTAS_scalar: | |
2706 mnemonic = "fcvtas"; | |
2707 break; | |
2708 case NEON_FCVTAU_scalar: | |
2709 mnemonic = "fcvtau"; | |
2710 break; | |
2711 case NEON_FCVTXN_scalar: | |
2712 nfd.SetFormatMap(0, nfd.LongScalarFormatMap()); | |
2713 mnemonic = "fcvtxn"; | |
2714 break; | |
2715 default: | |
2716 nfd.SetFormatMap(0, nfd.ScalarFormatMap()); | |
2717 nfd.SetFormatMap(1, nfd.LongScalarFormatMap()); | |
2718 switch (instr->Mask(NEONScalar2RegMiscMask)) { | |
2719 case NEON_SQXTN_scalar: | |
2720 mnemonic = "sqxtn"; | |
2721 break; | |
2722 case NEON_UQXTN_scalar: | |
2723 mnemonic = "uqxtn"; | |
2724 break; | |
2725 case NEON_SQXTUN_scalar: | |
2726 mnemonic = "sqxtun"; | |
2727 break; | |
2728 default: | |
2729 form = "(NEONScalar2RegMisc)"; | |
2730 } | |
2731 } | |
2732 } | |
2733 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); | |
2734 } | |
2735 | |
2736 void DisassemblingDecoder::VisitNEONScalar3Diff(Instruction *instr) { | |
2737 const char *mnemonic = "unimplemented"; | |
2738 const char *form = "%sd, %sn, %sm"; | |
2739 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap(), | |
2740 NEONFormatDecoder::ScalarFormatMap()); | |
2741 | |
2742 switch (instr->Mask(NEONScalar3DiffMask)) { | |
2743 case NEON_SQDMLAL_scalar: | |
2744 mnemonic = "sqdmlal"; | |
2745 break; | |
2746 case NEON_SQDMLSL_scalar: | |
2747 mnemonic = "sqdmlsl"; | |
2748 break; | |
2749 case NEON_SQDMULL_scalar: | |
2750 mnemonic = "sqdmull"; | |
2751 break; | |
2752 default: | |
2753 form = "(NEONScalar3Diff)"; | |
2754 } | |
2755 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); | |
2756 } | |
2757 | |
2758 void DisassemblingDecoder::VisitNEONScalar3Same(Instruction *instr) { | |
2759 const char *mnemonic = "unimplemented"; | |
2760 const char *form = "%sd, %sn, %sm"; | |
2761 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); | |
2762 | |
2763 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) { | |
2764 nfd.SetFormatMaps(nfd.FPScalarFormatMap()); | |
2765 switch (instr->Mask(NEONScalar3SameFPMask)) { | |
2766 case NEON_FACGE_scalar: | |
2767 mnemonic = "facge"; | |
2768 break; | |
2769 case NEON_FACGT_scalar: | |
2770 mnemonic = "facgt"; | |
2771 break; | |
2772 case NEON_FCMEQ_scalar: | |
2773 mnemonic = "fcmeq"; | |
2774 break; | |
2775 case NEON_FCMGE_scalar: | |
2776 mnemonic = "fcmge"; | |
2777 break; | |
2778 case NEON_FCMGT_scalar: | |
2779 mnemonic = "fcmgt"; | |
2780 break; | |
2781 case NEON_FMULX_scalar: | |
2782 mnemonic = "fmulx"; | |
2783 break; | |
2784 case NEON_FRECPS_scalar: | |
2785 mnemonic = "frecps"; | |
2786 break; | |
2787 case NEON_FRSQRTS_scalar: | |
2788 mnemonic = "frsqrts"; | |
2789 break; | |
2790 case NEON_FABD_scalar: | |
2791 mnemonic = "fabd"; | |
2792 break; | |
2793 default: | |
2794 form = "(NEONScalar3Same)"; | |
2795 } | |
2796 } else { | |
2797 switch (instr->Mask(NEONScalar3SameMask)) { | |
2798 case NEON_ADD_scalar: | |
2799 mnemonic = "add"; | |
2800 break; | |
2801 case NEON_SUB_scalar: | |
2802 mnemonic = "sub"; | |
2803 break; | |
2804 case NEON_CMEQ_scalar: | |
2805 mnemonic = "cmeq"; | |
2806 break; | |
2807 case NEON_CMGE_scalar: | |
2808 mnemonic = "cmge"; | |
2809 break; | |
2810 case NEON_CMGT_scalar: | |
2811 mnemonic = "cmgt"; | |
2812 break; | |
2813 case NEON_CMHI_scalar: | |
2814 mnemonic = "cmhi"; | |
2815 break; | |
2816 case NEON_CMHS_scalar: | |
2817 mnemonic = "cmhs"; | |
2818 break; | |
2819 case NEON_CMTST_scalar: | |
2820 mnemonic = "cmtst"; | |
2821 break; | |
2822 case NEON_UQADD_scalar: | |
2823 mnemonic = "uqadd"; | |
2824 break; | |
2825 case NEON_SQADD_scalar: | |
2826 mnemonic = "sqadd"; | |
2827 break; | |
2828 case NEON_UQSUB_scalar: | |
2829 mnemonic = "uqsub"; | |
2830 break; | |
2831 case NEON_SQSUB_scalar: | |
2832 mnemonic = "sqsub"; | |
2833 break; | |
2834 case NEON_USHL_scalar: | |
2835 mnemonic = "ushl"; | |
2836 break; | |
2837 case NEON_SSHL_scalar: | |
2838 mnemonic = "sshl"; | |
2839 break; | |
2840 case NEON_UQSHL_scalar: | |
2841 mnemonic = "uqshl"; | |
2842 break; | |
2843 case NEON_SQSHL_scalar: | |
2844 mnemonic = "sqshl"; | |
2845 break; | |
2846 case NEON_URSHL_scalar: | |
2847 mnemonic = "urshl"; | |
2848 break; | |
2849 case NEON_SRSHL_scalar: | |
2850 mnemonic = "srshl"; | |
2851 break; | |
2852 case NEON_UQRSHL_scalar: | |
2853 mnemonic = "uqrshl"; | |
2854 break; | |
2855 case NEON_SQRSHL_scalar: | |
2856 mnemonic = "sqrshl"; | |
2857 break; | |
2858 case NEON_SQDMULH_scalar: | |
2859 mnemonic = "sqdmulh"; | |
2860 break; | |
2861 case NEON_SQRDMULH_scalar: | |
2862 mnemonic = "sqrdmulh"; | |
2863 break; | |
2864 default: | |
2865 form = "(NEONScalar3Same)"; | |
2866 } | |
2867 } | |
2868 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); | |
2869 } | |
2870 | |
2871 void DisassemblingDecoder::VisitNEONScalarByIndexedElement(Instruction *instr) { | |
2872 const char *mnemonic = "unimplemented"; | |
2873 const char *form = "%sd, %sn, 'Ve.%s['IVByElemIndex]"; | |
2874 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); | |
2875 bool long_instr = false; | |
2876 | |
2877 switch (instr->Mask(NEONScalarByIndexedElementMask)) { | |
2878 case NEON_SQDMULL_byelement_scalar: | |
2879 mnemonic = "sqdmull"; | |
2880 long_instr = true; | |
2881 break; | |
2882 case NEON_SQDMLAL_byelement_scalar: | |
2883 mnemonic = "sqdmlal"; | |
2884 long_instr = true; | |
2885 break; | |
2886 case NEON_SQDMLSL_byelement_scalar: | |
2887 mnemonic = "sqdmlsl"; | |
2888 long_instr = true; | |
2889 break; | |
2890 case NEON_SQDMULH_byelement_scalar: | |
2891 mnemonic = "sqdmulh"; | |
2892 break; | |
2893 case NEON_SQRDMULH_byelement_scalar: | |
2894 mnemonic = "sqrdmulh"; | |
2895 break; | |
2896 default: | |
2897 nfd.SetFormatMap(0, nfd.FPScalarFormatMap()); | |
2898 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) { | |
2899 case NEON_FMUL_byelement_scalar: | |
2900 mnemonic = "fmul"; | |
2901 break; | |
2902 case NEON_FMLA_byelement_scalar: | |
2903 mnemonic = "fmla"; | |
2904 break; | |
2905 case NEON_FMLS_byelement_scalar: | |
2906 mnemonic = "fmls"; | |
2907 break; | |
2908 case NEON_FMULX_byelement_scalar: | |
2909 mnemonic = "fmulx"; | |
2910 break; | |
2911 default: | |
2912 form = "(NEONScalarByIndexedElement)"; | |
2913 } | |
2914 } | |
2915 | |
2916 if (long_instr) { | |
2917 nfd.SetFormatMap(0, nfd.LongScalarFormatMap()); | |
2918 } | |
2919 | |
2920 Format(instr, mnemonic, | |
2921 nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat)); | |
2922 } | |
2923 | |
2924 void DisassemblingDecoder::VisitNEONScalarCopy(Instruction *instr) { | |
2925 const char *mnemonic = "unimplemented"; | |
2926 const char *form = "(NEONScalarCopy)"; | |
2927 | |
2928 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap()); | |
2929 | |
2930 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) { | |
2931 mnemonic = "mov"; | |
2932 form = "%sd, 'Vn.%s['IVInsIndex1]"; | |
2933 } | |
2934 | |
2935 Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat)); | |
2936 } | |
2937 | |
2938 void DisassemblingDecoder::VisitNEONScalarPairwise(Instruction *instr) { | |
2939 const char *mnemonic = "unimplemented"; | |
2940 const char *form = "%sd, 'Vn.%s"; | |
2941 NEONFormatMap map = {{22}, {NF_2S, NF_2D}}; | |
bbudge
2017/01/31 01:41:32
magic numbers
bbudge
2017/02/08 01:39:11
OK
| |
2942 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap(), &map); | |
2943 | |
2944 switch (instr->Mask(NEONScalarPairwiseMask)) { | |
2945 case NEON_ADDP_scalar: | |
2946 mnemonic = "addp"; | |
2947 break; | |
2948 case NEON_FADDP_scalar: | |
2949 mnemonic = "faddp"; | |
2950 break; | |
2951 case NEON_FMAXP_scalar: | |
2952 mnemonic = "fmaxp"; | |
2953 break; | |
2954 case NEON_FMAXNMP_scalar: | |
2955 mnemonic = "fmaxnmp"; | |
2956 break; | |
2957 case NEON_FMINP_scalar: | |
2958 mnemonic = "fminp"; | |
2959 break; | |
2960 case NEON_FMINNMP_scalar: | |
2961 mnemonic = "fminnmp"; | |
2962 break; | |
2963 default: | |
2964 form = "(NEONScalarPairwise)"; | |
2965 } | |
2966 Format(instr, mnemonic, nfd.Substitute(form, NEONFormatDecoder::kPlaceholder, | |
2967 NEONFormatDecoder::kFormat)); | |
2968 } | |
2969 | |
2970 void DisassemblingDecoder::VisitNEONScalarShiftImmediate(Instruction *instr) { | |
2971 const char *mnemonic = "unimplemented"; | |
2972 const char *form = "%sd, %sn, 'Is1"; | |
2973 const char *form_2 = "%sd, %sn, 'Is2"; | |
2974 | |
2975 static const NEONFormatMap map_shift = { | |
2976 {22, 21, 20, 19}, | |
bbudge
2017/01/31 01:41:32
magic numbers
bbudge
2017/02/08 01:39:11
OK
| |
2977 {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S, NF_D, NF_D, NF_D, | |
2978 NF_D, NF_D, NF_D, NF_D, NF_D}}; | |
2979 static const NEONFormatMap map_shift_narrow = { | |
2980 {21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}}; | |
2981 NEONFormatDecoder nfd(instr, &map_shift); | |
2982 | |
2983 if (instr->ImmNEONImmh()) { // immh has to be non-zero. | |
2984 switch (instr->Mask(NEONScalarShiftImmediateMask)) { | |
2985 case NEON_FCVTZU_imm_scalar: | |
2986 mnemonic = "fcvtzu"; | |
2987 break; | |
2988 case NEON_FCVTZS_imm_scalar: | |
2989 mnemonic = "fcvtzs"; | |
2990 break; | |
2991 case NEON_SCVTF_imm_scalar: | |
2992 mnemonic = "scvtf"; | |
2993 break; | |
2994 case NEON_UCVTF_imm_scalar: | |
2995 mnemonic = "ucvtf"; | |
2996 break; | |
2997 case NEON_SRI_scalar: | |
2998 mnemonic = "sri"; | |
2999 break; | |
3000 case NEON_SSHR_scalar: | |
3001 mnemonic = "sshr"; | |
3002 break; | |
3003 case NEON_USHR_scalar: | |
3004 mnemonic = "ushr"; | |
3005 break; | |
3006 case NEON_SRSHR_scalar: | |
3007 mnemonic = "srshr"; | |
3008 break; | |
3009 case NEON_URSHR_scalar: | |
3010 mnemonic = "urshr"; | |
3011 break; | |
3012 case NEON_SSRA_scalar: | |
3013 mnemonic = "ssra"; | |
3014 break; | |
3015 case NEON_USRA_scalar: | |
3016 mnemonic = "usra"; | |
3017 break; | |
3018 case NEON_SRSRA_scalar: | |
3019 mnemonic = "srsra"; | |
3020 break; | |
3021 case NEON_URSRA_scalar: | |
3022 mnemonic = "ursra"; | |
3023 break; | |
3024 case NEON_SHL_scalar: | |
3025 mnemonic = "shl"; | |
3026 form = form_2; | |
3027 break; | |
3028 case NEON_SLI_scalar: | |
3029 mnemonic = "sli"; | |
3030 form = form_2; | |
3031 break; | |
3032 case NEON_SQSHLU_scalar: | |
3033 mnemonic = "sqshlu"; | |
3034 form = form_2; | |
3035 break; | |
3036 case NEON_SQSHL_imm_scalar: | |
3037 mnemonic = "sqshl"; | |
3038 form = form_2; | |
3039 break; | |
3040 case NEON_UQSHL_imm_scalar: | |
3041 mnemonic = "uqshl"; | |
3042 form = form_2; | |
3043 break; | |
3044 case NEON_UQSHRN_scalar: | |
3045 mnemonic = "uqshrn"; | |
3046 nfd.SetFormatMap(1, &map_shift_narrow); | |
3047 break; | |
3048 case NEON_UQRSHRN_scalar: | |
3049 mnemonic = "uqrshrn"; | |
3050 nfd.SetFormatMap(1, &map_shift_narrow); | |
3051 break; | |
3052 case NEON_SQSHRN_scalar: | |
3053 mnemonic = "sqshrn"; | |
3054 nfd.SetFormatMap(1, &map_shift_narrow); | |
3055 break; | |
3056 case NEON_SQRSHRN_scalar: | |
3057 mnemonic = "sqrshrn"; | |
3058 nfd.SetFormatMap(1, &map_shift_narrow); | |
3059 break; | |
3060 case NEON_SQSHRUN_scalar: | |
3061 mnemonic = "sqshrun"; | |
3062 nfd.SetFormatMap(1, &map_shift_narrow); | |
3063 break; | |
3064 case NEON_SQRSHRUN_scalar: | |
3065 mnemonic = "sqrshrun"; | |
3066 nfd.SetFormatMap(1, &map_shift_narrow); | |
3067 break; | |
3068 default: | |
3069 form = "(NEONScalarShiftImmediate)"; | |
3070 } | |
3071 } else { | |
3072 form = "(NEONScalarShiftImmediate)"; | |
3073 } | |
3074 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); | |
3075 } | |
3076 | |
3077 void DisassemblingDecoder::VisitNEONShiftImmediate(Instruction *instr) { | |
3078 const char *mnemonic = "unimplemented"; | |
3079 const char *form = "'Vd.%s, 'Vn.%s, 'Is1"; | |
3080 const char *form_shift_2 = "'Vd.%s, 'Vn.%s, 'Is2"; | |
3081 const char *form_xtl = "'Vd.%s, 'Vn.%s"; | |
3082 | |
3083 // 0001->8H, 001x->4S, 01xx->2D, all others undefined. | |
3084 static const NEONFormatMap map_shift_ta = { | |
3085 {22, 21, 20, 19}, | |
bbudge
2017/01/31 01:41:32
magic numbers
bbudge
2017/02/08 01:39:11
OK
| |
3086 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}}; | |
3087 | |
3088 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H, | |
3089 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined. | |
3090 static const NEONFormatMap map_shift_tb = { | |
3091 {22, 21, 20, 19, 30}, | |
3092 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H, NF_8H, | |
3093 NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, | |
3094 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, | |
3095 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}}; | |
3096 | |
3097 NEONFormatDecoder nfd(instr, &map_shift_tb); | |
3098 | |
3099 if (instr->ImmNEONImmh()) { // immh has to be non-zero. | |
3100 switch (instr->Mask(NEONShiftImmediateMask)) { | |
3101 case NEON_SQSHLU: | |
3102 mnemonic = "sqshlu"; | |
3103 form = form_shift_2; | |
3104 break; | |
3105 case NEON_SQSHL_imm: | |
3106 mnemonic = "sqshl"; | |
3107 form = form_shift_2; | |
3108 break; | |
3109 case NEON_UQSHL_imm: | |
3110 mnemonic = "uqshl"; | |
3111 form = form_shift_2; | |
3112 break; | |
3113 case NEON_SHL: | |
3114 mnemonic = "shl"; | |
3115 form = form_shift_2; | |
3116 break; | |
3117 case NEON_SLI: | |
3118 mnemonic = "sli"; | |
3119 form = form_shift_2; | |
3120 break; | |
3121 case NEON_SCVTF_imm: | |
3122 mnemonic = "scvtf"; | |
3123 break; | |
3124 case NEON_UCVTF_imm: | |
3125 mnemonic = "ucvtf"; | |
3126 break; | |
3127 case NEON_FCVTZU_imm: | |
3128 mnemonic = "fcvtzu"; | |
3129 break; | |
3130 case NEON_FCVTZS_imm: | |
3131 mnemonic = "fcvtzs"; | |
3132 break; | |
3133 case NEON_SRI: | |
3134 mnemonic = "sri"; | |
3135 break; | |
3136 case NEON_SSHR: | |
3137 mnemonic = "sshr"; | |
3138 break; | |
3139 case NEON_USHR: | |
3140 mnemonic = "ushr"; | |
3141 break; | |
3142 case NEON_SRSHR: | |
3143 mnemonic = "srshr"; | |
3144 break; | |
3145 case NEON_URSHR: | |
3146 mnemonic = "urshr"; | |
3147 break; | |
3148 case NEON_SSRA: | |
3149 mnemonic = "ssra"; | |
3150 break; | |
3151 case NEON_USRA: | |
3152 mnemonic = "usra"; | |
3153 break; | |
3154 case NEON_SRSRA: | |
3155 mnemonic = "srsra"; | |
3156 break; | |
3157 case NEON_URSRA: | |
3158 mnemonic = "ursra"; | |
3159 break; | |
3160 case NEON_SHRN: | |
3161 mnemonic = instr->Mask(NEON_Q) ? "shrn2" : "shrn"; | |
3162 nfd.SetFormatMap(1, &map_shift_ta); | |
3163 break; | |
3164 case NEON_RSHRN: | |
3165 mnemonic = instr->Mask(NEON_Q) ? "rshrn2" : "rshrn"; | |
3166 nfd.SetFormatMap(1, &map_shift_ta); | |
3167 break; | |
3168 case NEON_UQSHRN: | |
3169 mnemonic = instr->Mask(NEON_Q) ? "uqshrn2" : "uqshrn"; | |
3170 nfd.SetFormatMap(1, &map_shift_ta); | |
3171 break; | |
3172 case NEON_UQRSHRN: | |
3173 mnemonic = instr->Mask(NEON_Q) ? "uqrshrn2" : "uqrshrn"; | |
3174 nfd.SetFormatMap(1, &map_shift_ta); | |
3175 break; | |
3176 case NEON_SQSHRN: | |
3177 mnemonic = instr->Mask(NEON_Q) ? "sqshrn2" : "sqshrn"; | |
3178 nfd.SetFormatMap(1, &map_shift_ta); | |
3179 break; | |
3180 case NEON_SQRSHRN: | |
3181 mnemonic = instr->Mask(NEON_Q) ? "sqrshrn2" : "sqrshrn"; | |
3182 nfd.SetFormatMap(1, &map_shift_ta); | |
3183 break; | |
3184 case NEON_SQSHRUN: | |
3185 mnemonic = instr->Mask(NEON_Q) ? "sqshrun2" : "sqshrun"; | |
3186 nfd.SetFormatMap(1, &map_shift_ta); | |
3187 break; | |
3188 case NEON_SQRSHRUN: | |
3189 mnemonic = instr->Mask(NEON_Q) ? "sqrshrun2" : "sqrshrun"; | |
3190 nfd.SetFormatMap(1, &map_shift_ta); | |
3191 break; | |
3192 case NEON_SSHLL: | |
3193 nfd.SetFormatMap(0, &map_shift_ta); | |
3194 if (instr->ImmNEONImmb() == 0 && | |
3195 CountSetBits(instr->ImmNEONImmh(), 32) == 1) { // sxtl variant. | |
3196 form = form_xtl; | |
3197 mnemonic = instr->Mask(NEON_Q) ? "sxtl2" : "sxtl"; | |
3198 } else { // sshll variant. | |
3199 form = form_shift_2; | |
3200 mnemonic = instr->Mask(NEON_Q) ? "sshll2" : "sshll"; | |
3201 } | |
3202 break; | |
3203 case NEON_USHLL: | |
3204 nfd.SetFormatMap(0, &map_shift_ta); | |
3205 if (instr->ImmNEONImmb() == 0 && | |
3206 CountSetBits(instr->ImmNEONImmh(), 32) == 1) { // uxtl variant. | |
3207 form = form_xtl; | |
3208 mnemonic = instr->Mask(NEON_Q) ? "uxtl2" : "uxtl"; | |
3209 } else { // ushll variant. | |
3210 form = form_shift_2; | |
3211 mnemonic = instr->Mask(NEON_Q) ? "ushll2" : "ushll"; | |
3212 } | |
3213 break; | |
3214 default: | |
3215 form = "(NEONShiftImmediate)"; | |
3216 } | |
3217 } else { | |
3218 form = "(NEONShiftImmediate)"; | |
3219 } | |
3220 Format(instr, mnemonic, nfd.Substitute(form)); | |
3221 } | |
3222 | |
3223 void DisassemblingDecoder::VisitNEONTable(Instruction *instr) { | |
3224 const char *mnemonic = "unimplemented"; | |
3225 const char *form = "(NEONTable)"; | |
3226 const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s"; | |
3227 const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s"; | |
3228 const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s"; | |
3229 const char form_4v[] = | |
3230 "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s"; | |
3231 static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}}; | |
3232 NEONFormatDecoder nfd(instr, &map_b); | |
3233 | |
3234 switch (instr->Mask(NEONTableMask)) { | |
3235 case NEON_TBL_1v: | |
3236 mnemonic = "tbl"; | |
3237 form = form_1v; | |
3238 break; | |
3239 case NEON_TBL_2v: | |
3240 mnemonic = "tbl"; | |
3241 form = form_2v; | |
3242 break; | |
3243 case NEON_TBL_3v: | |
3244 mnemonic = "tbl"; | |
3245 form = form_3v; | |
3246 break; | |
3247 case NEON_TBL_4v: | |
3248 mnemonic = "tbl"; | |
3249 form = form_4v; | |
3250 break; | |
3251 case NEON_TBX_1v: | |
3252 mnemonic = "tbx"; | |
3253 form = form_1v; | |
3254 break; | |
3255 case NEON_TBX_2v: | |
3256 mnemonic = "tbx"; | |
3257 form = form_2v; | |
3258 break; | |
3259 case NEON_TBX_3v: | |
3260 mnemonic = "tbx"; | |
3261 form = form_3v; | |
3262 break; | |
3263 case NEON_TBX_4v: | |
3264 mnemonic = "tbx"; | |
3265 form = form_4v; | |
3266 break; | |
3267 default: | |
3268 break; | |
3269 } | |
3270 | |
3271 char re_form[sizeof(form_4v) + 6]; | |
bbudge
2017/01/31 01:41:32
magic number (6)
martyn.capewell
2017/02/03 11:01:31
Done.
| |
3272 int reg_num = instr->Rn(); | |
3273 snprintf(re_form, sizeof(re_form), form, (reg_num + 1) % kNumberOfVRegisters, | |
3274 (reg_num + 2) % kNumberOfVRegisters, | |
3275 (reg_num + 3) % kNumberOfVRegisters); | |
3276 | |
3277 Format(instr, mnemonic, nfd.Substitute(re_form)); | |
3278 } | |
3279 | |
3280 void DisassemblingDecoder::VisitUnimplemented(Instruction *instr) { | |
1238 Format(instr, "unimplemented", "(Unimplemented)"); | 3281 Format(instr, "unimplemented", "(Unimplemented)"); |
1239 } | 3282 } |
1240 | 3283 |
1241 | 3284 void DisassemblingDecoder::VisitUnallocated(Instruction *instr) { |
1242 void DisassemblingDecoder::VisitUnallocated(Instruction* instr) { | |
1243 Format(instr, "unallocated", "(Unallocated)"); | 3285 Format(instr, "unallocated", "(Unallocated)"); |
1244 } | 3286 } |
1245 | 3287 |
1246 | 3288 void DisassemblingDecoder::ProcessOutput(Instruction * /*instr*/) { |
1247 void DisassemblingDecoder::ProcessOutput(Instruction* /*instr*/) { | |
1248 // The base disasm does nothing more than disassembling into a buffer. | 3289 // The base disasm does nothing more than disassembling into a buffer. |
1249 } | 3290 } |
1250 | 3291 |
1251 | 3292 void DisassemblingDecoder::AppendRegisterNameToOutput(const Instruction *instr, |
1252 void DisassemblingDecoder::Format(Instruction* instr, const char* mnemonic, | 3293 const CPURegister ®) { |
1253 const char* format) { | 3294 USE(instr); |
3295 DCHECK(reg.IsValid()); | |
3296 char reg_char; | |
3297 | |
3298 if (reg.IsRegister()) { | |
3299 reg_char = reg.Is64Bits() ? 'x' : 'w'; | |
3300 } else { | |
3301 DCHECK(reg.IsVRegister()); | |
3302 switch (reg.SizeInBits()) { | |
3303 case kBRegSizeInBits: | |
3304 reg_char = 'b'; | |
3305 break; | |
3306 case kHRegSizeInBits: | |
3307 reg_char = 'h'; | |
3308 break; | |
3309 case kSRegSizeInBits: | |
3310 reg_char = 's'; | |
3311 break; | |
3312 case kDRegSizeInBits: | |
3313 reg_char = 'd'; | |
3314 break; | |
3315 default: | |
3316 DCHECK(reg.Is128Bits()); | |
3317 reg_char = 'q'; | |
3318 } | |
3319 } | |
3320 | |
3321 if (reg.IsVRegister() || !(reg.Aliases(csp) || reg.Aliases(xzr))) { | |
3322 // Filter special registers | |
3323 if (reg.IsX() && (reg.code() == 27)) { | |
3324 AppendToOutput("cp"); | |
3325 } else if (reg.IsX() && (reg.code() == 28)) { | |
3326 AppendToOutput("jssp"); | |
3327 } else if (reg.IsX() && (reg.code() == 29)) { | |
3328 AppendToOutput("fp"); | |
3329 } else if (reg.IsX() && (reg.code() == 30)) { | |
3330 AppendToOutput("lr"); | |
3331 } else { | |
3332 // A core or scalar/vector register: [wx]0 - 30, [bhsdq]0 - 31. | |
3333 AppendToOutput("%c%d", reg_char, reg.code()); | |
3334 } | |
3335 } else if (reg.Aliases(csp)) { | |
3336 // Disassemble w31/x31 as stack pointer wcsp/csp. | |
3337 AppendToOutput("%s", reg.Is64Bits() ? "csp" : "wcsp"); | |
3338 } else { | |
3339 // Disassemble w31/x31 as zero register wzr/xzr. | |
3340 AppendToOutput("%czr", reg_char); | |
3341 } | |
3342 } | |
3343 | |
3344 void DisassemblingDecoder::Format(Instruction *instr, const char *mnemonic, | |
3345 const char *format) { | |
1254 // TODO(mcapewel) don't think I can use the instr address here - there needs | 3346 // TODO(mcapewel) don't think I can use the instr address here - there needs |
1255 // to be a base address too | 3347 // to be a base address too |
1256 DCHECK(mnemonic != NULL); | 3348 DCHECK(mnemonic != NULL); |
1257 ResetOutput(); | 3349 ResetOutput(); |
1258 Substitute(instr, mnemonic); | 3350 Substitute(instr, mnemonic); |
1259 if (format != NULL) { | 3351 if (format != NULL) { |
1260 buffer_[buffer_pos_++] = ' '; | 3352 buffer_[buffer_pos_++] = ' '; |
1261 Substitute(instr, format); | 3353 Substitute(instr, format); |
1262 } | 3354 } |
1263 buffer_[buffer_pos_] = 0; | 3355 buffer_[buffer_pos_] = 0; |
1264 ProcessOutput(instr); | 3356 ProcessOutput(instr); |
1265 } | 3357 } |
1266 | 3358 |
1267 | 3359 void DisassemblingDecoder::Substitute(Instruction *instr, const char *string) { |
1268 void DisassemblingDecoder::Substitute(Instruction* instr, const char* string) { | |
1269 char chr = *string++; | 3360 char chr = *string++; |
1270 while (chr != '\0') { | 3361 while (chr != '\0') { |
1271 if (chr == '\'') { | 3362 if (chr == '\'') { |
1272 string += SubstituteField(instr, string); | 3363 string += SubstituteField(instr, string); |
1273 } else { | 3364 } else { |
1274 buffer_[buffer_pos_++] = chr; | 3365 buffer_[buffer_pos_++] = chr; |
1275 } | 3366 } |
1276 chr = *string++; | 3367 chr = *string++; |
1277 } | 3368 } |
1278 } | 3369 } |
1279 | 3370 |
1280 | 3371 int DisassemblingDecoder::SubstituteField(Instruction *instr, |
1281 int DisassemblingDecoder::SubstituteField(Instruction* instr, | 3372 const char *format) { |
1282 const char* format) { | |
1283 switch (format[0]) { | 3373 switch (format[0]) { |
3374 // NB. The remaining substitution prefix characters are: GJKUZ. | |
1284 case 'R': // Register. X or W, selected by sf bit. | 3375 case 'R': // Register. X or W, selected by sf bit. |
1285 case 'F': // FP Register. S or D, selected by type field. | 3376 case 'F': // FP register. S or D, selected by type field. |
3377 case 'V': // Vector register, V, vector format. | |
1286 case 'W': | 3378 case 'W': |
1287 case 'X': | 3379 case 'X': |
3380 case 'B': | |
3381 case 'H': | |
1288 case 'S': | 3382 case 'S': |
1289 case 'D': return SubstituteRegisterField(instr, format); | 3383 case 'D': |
1290 case 'I': return SubstituteImmediateField(instr, format); | 3384 case 'Q': |
1291 case 'L': return SubstituteLiteralField(instr, format); | 3385 return SubstituteRegisterField(instr, format); |
1292 case 'H': return SubstituteShiftField(instr, format); | 3386 case 'I': |
1293 case 'P': return SubstitutePrefetchField(instr, format); | 3387 return SubstituteImmediateField(instr, format); |
1294 case 'C': return SubstituteConditionField(instr, format); | 3388 case 'L': |
1295 case 'E': return SubstituteExtendField(instr, format); | 3389 return SubstituteLiteralField(instr, format); |
1296 case 'A': return SubstitutePCRelAddressField(instr, format); | 3390 case 'N': |
1297 case 'B': return SubstituteBranchTargetField(instr, format); | 3391 return SubstituteShiftField(instr, format); |
1298 case 'O': return SubstituteLSRegOffsetField(instr, format); | 3392 case 'P': |
1299 case 'M': return SubstituteBarrierField(instr, format); | 3393 return SubstitutePrefetchField(instr, format); |
3394 case 'C': | |
3395 return SubstituteConditionField(instr, format); | |
3396 case 'E': | |
3397 return SubstituteExtendField(instr, format); | |
3398 case 'A': | |
3399 return SubstitutePCRelAddressField(instr, format); | |
3400 case 'T': | |
3401 return SubstituteBranchTargetField(instr, format); | |
3402 case 'O': | |
3403 return SubstituteLSRegOffsetField(instr, format); | |
3404 case 'M': | |
3405 return SubstituteBarrierField(instr, format); | |
1300 default: { | 3406 default: { |
1301 UNREACHABLE(); | 3407 UNREACHABLE(); |
1302 return 1; | 3408 return 1; |
1303 } | 3409 } |
1304 } | 3410 } |
1305 } | 3411 } |
1306 | 3412 |
1307 | 3413 int DisassemblingDecoder::SubstituteRegisterField(Instruction *instr, |
1308 int DisassemblingDecoder::SubstituteRegisterField(Instruction* instr, | 3414 const char *format) { |
1309 const char* format) { | 3415 char reg_prefix = format[0]; |
1310 unsigned reg_num = 0; | 3416 unsigned reg_num = 0; |
1311 unsigned field_len = 2; | 3417 unsigned field_len = 2; |
3418 | |
1312 switch (format[1]) { | 3419 switch (format[1]) { |
1313 case 'd': reg_num = instr->Rd(); break; | 3420 case 'd': |
1314 case 'n': reg_num = instr->Rn(); break; | 3421 reg_num = instr->Rd(); |
1315 case 'm': reg_num = instr->Rm(); break; | 3422 if (format[2] == 'q') { |
1316 case 'a': reg_num = instr->Ra(); break; | 3423 reg_prefix = instr->NEONQ() ? 'X' : 'W'; |
1317 case 't': { | |
1318 if (format[2] == '2') { | |
1319 reg_num = instr->Rt2(); | |
1320 field_len = 3; | 3424 field_len = 3; |
3425 } | |
3426 break; | |
3427 case 'n': | |
3428 reg_num = instr->Rn(); | |
3429 break; | |
3430 case 'm': | |
3431 reg_num = instr->Rm(); | |
3432 switch (format[2]) { | |
3433 // Handle registers tagged with b (bytes), z (instruction), or | |
3434 // r (registers), used for address updates in | |
3435 // NEON load/store instructions. | |
3436 case 'r': | |
3437 case 'b': | |
3438 case 'z': { | |
3439 field_len = 3; | |
3440 char *eimm; | |
3441 int imm = static_cast<int>(strtol(&format[3], &eimm, 10)); | |
3442 field_len += eimm - &format[3]; | |
3443 if (reg_num == 31) { | |
3444 switch (format[2]) { | |
3445 case 'z': | |
3446 imm *= (1 << instr->NEONLSSize()); | |
3447 break; | |
3448 case 'r': | |
3449 imm *= (instr->NEONQ() == 0) ? kDRegSize : kQRegSize; | |
3450 break; | |
3451 case 'b': | |
3452 break; | |
3453 } | |
3454 AppendToOutput("#%d", imm); | |
3455 return field_len; | |
3456 } | |
3457 break; | |
3458 } | |
3459 } | |
3460 break; | |
3461 case 'e': | |
3462 // This is register Rm, but using a 4-bit specifier. Used in NEON | |
3463 // by-element instructions. | |
3464 reg_num = (instr->Rm() & 0xf); | |
3465 break; | |
3466 case 'a': | |
3467 reg_num = instr->Ra(); | |
3468 break; | |
3469 case 't': | |
3470 reg_num = instr->Rt(); | |
3471 if (format[0] == 'V') { | |
3472 if ((format[2] >= '2') && (format[2] <= '4')) { | |
3473 // Handle consecutive vector register specifiers Vt2, Vt3 and Vt4. | |
3474 reg_num = (reg_num + format[2] - '1') % 32; | |
3475 field_len = 3; | |
3476 } | |
1321 } else { | 3477 } else { |
1322 reg_num = instr->Rt(); | 3478 if (format[2] == '2') { |
3479 // Handle register specifier Rt2. | |
3480 reg_num = instr->Rt2(); | |
3481 field_len = 3; | |
3482 } | |
1323 } | 3483 } |
1324 break; | 3484 break; |
1325 } | |
1326 case 's': | 3485 case 's': |
1327 reg_num = instr->Rs(); | 3486 reg_num = instr->Rs(); |
1328 break; | 3487 break; |
1329 default: UNREACHABLE(); | 3488 default: |
3489 UNREACHABLE(); | |
1330 } | 3490 } |
1331 | 3491 |
1332 // Increase field length for registers tagged as stack. | 3492 // Increase field length for registers tagged as stack. |
1333 if (format[2] == 's') { | 3493 if (format[2] == 's') { |
1334 field_len = 3; | 3494 field_len = 3; |
1335 } | 3495 } |
1336 | 3496 |
1337 char reg_type; | 3497 CPURegister::RegisterType reg_type; |
1338 if (format[0] == 'R') { | 3498 unsigned reg_size; |
1339 // Register type is R: use sf bit to choose X and W. | 3499 |
1340 reg_type = instr->SixtyFourBits() ? 'x' : 'w'; | 3500 if (reg_prefix == 'R') { |
1341 } else if (format[0] == 'F') { | 3501 reg_prefix = instr->SixtyFourBits() ? 'X' : 'W'; |
1342 // Floating-point register: use type field to choose S or D. | 3502 } else if (reg_prefix == 'F') { |
1343 reg_type = ((instr->FPType() & 1) == 0) ? 's' : 'd'; | 3503 reg_prefix = ((instr->FPType() & 1) == 0) ? 'S' : 'D'; |
1344 } else { | 3504 } |
1345 // Register type is specified. Make it lower case. | 3505 |
1346 reg_type = format[0] + 0x20; | 3506 switch (reg_prefix) { |
1347 } | 3507 case 'W': |
1348 | 3508 reg_type = CPURegister::kRegister; |
1349 if ((reg_num != kZeroRegCode) || (reg_type == 's') || (reg_type == 'd')) { | 3509 reg_size = kWRegSizeInBits; |
1350 // A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31. | 3510 break; |
1351 | 3511 case 'X': |
1352 // Filter special registers | 3512 reg_type = CPURegister::kRegister; |
1353 if ((reg_type == 'x') && (reg_num == 27)) { | 3513 reg_size = kXRegSizeInBits; |
1354 AppendToOutput("cp"); | 3514 break; |
1355 } else if ((reg_type == 'x') && (reg_num == 28)) { | 3515 case 'B': |
1356 AppendToOutput("jssp"); | 3516 reg_type = CPURegister::kVRegister; |
1357 } else if ((reg_type == 'x') && (reg_num == 29)) { | 3517 reg_size = kBRegSizeInBits; |
1358 AppendToOutput("fp"); | 3518 break; |
1359 } else if ((reg_type == 'x') && (reg_num == 30)) { | 3519 case 'H': |
1360 AppendToOutput("lr"); | 3520 reg_type = CPURegister::kVRegister; |
1361 } else { | 3521 reg_size = kHRegSizeInBits; |
1362 AppendToOutput("%c%d", reg_type, reg_num); | 3522 break; |
1363 } | 3523 case 'S': |
1364 } else if (format[2] == 's') { | 3524 reg_type = CPURegister::kVRegister; |
1365 // Disassemble w31/x31 as stack pointer wcsp/csp. | 3525 reg_size = kSRegSizeInBits; |
1366 AppendToOutput("%s", (reg_type == 'w') ? "wcsp" : "csp"); | 3526 break; |
1367 } else { | 3527 case 'D': |
1368 // Disassemble w31/x31 as zero register wzr/xzr. | 3528 reg_type = CPURegister::kVRegister; |
1369 AppendToOutput("%czr", reg_type); | 3529 reg_size = kDRegSizeInBits; |
1370 } | 3530 break; |
3531 case 'Q': | |
3532 reg_type = CPURegister::kVRegister; | |
3533 reg_size = kQRegSizeInBits; | |
3534 break; | |
3535 case 'V': | |
3536 AppendToOutput("v%d", reg_num); | |
3537 return field_len; | |
3538 default: | |
3539 UNREACHABLE(); | |
3540 reg_type = CPURegister::kRegister; | |
3541 reg_size = kXRegSizeInBits; | |
3542 } | |
3543 | |
3544 if ((reg_type == CPURegister::kRegister) && (reg_num == kZeroRegCode) && | |
3545 (format[2] == 's')) { | |
3546 reg_num = kSPRegInternalCode; | |
3547 } | |
3548 | |
3549 AppendRegisterNameToOutput(instr, | |
3550 CPURegister::Create(reg_num, reg_size, reg_type)); | |
1371 | 3551 |
1372 return field_len; | 3552 return field_len; |
1373 } | 3553 } |
1374 | 3554 |
1375 | 3555 int DisassemblingDecoder::SubstituteImmediateField(Instruction *instr, |
1376 int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr, | 3556 const char *format) { |
1377 const char* format) { | |
1378 DCHECK(format[0] == 'I'); | 3557 DCHECK(format[0] == 'I'); |
1379 | 3558 |
1380 switch (format[1]) { | 3559 switch (format[1]) { |
1381 case 'M': { // IMoveImm or IMoveLSL. | 3560 case 'M': { // IMoveImm or IMoveLSL. |
1382 if (format[5] == 'I') { | 3561 if (format[5] == 'I' || format[5] == 'N') { |
1383 uint64_t imm = static_cast<uint64_t>(instr->ImmMoveWide()) | 3562 uint64_t imm = static_cast<uint64_t>(instr->ImmMoveWide()) |
1384 << (16 * instr->ShiftMoveWide()); | 3563 << (16 * instr->ShiftMoveWide()); |
3564 if (format[5] == 'N') imm = ~imm; | |
3565 if (!instr->SixtyFourBits()) imm &= UINT64_C(0xffffffff); | |
1385 AppendToOutput("#0x%" PRIx64, imm); | 3566 AppendToOutput("#0x%" PRIx64, imm); |
1386 } else { | 3567 } else { |
1387 DCHECK(format[5] == 'L'); | 3568 DCHECK(format[5] == 'L'); |
1388 AppendToOutput("#0x%" PRIx32, instr->ImmMoveWide()); | 3569 AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide()); |
1389 if (instr->ShiftMoveWide() > 0) { | 3570 if (instr->ShiftMoveWide() > 0) { |
1390 AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide()); | 3571 AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide()); |
1391 } | 3572 } |
1392 } | 3573 } |
1393 return 8; | 3574 return 8; |
1394 } | 3575 } |
1395 case 'L': { | 3576 case 'L': { |
1396 switch (format[2]) { | 3577 switch (format[2]) { |
1397 case 'L': { // ILLiteral - Immediate Load Literal. | 3578 case 'L': { // ILLiteral - Immediate Load Literal. |
1398 AppendToOutput("pc%+" PRId32, instr->ImmLLiteral() | 3579 AppendToOutput("pc%+" PRId32, instr->ImmLLiteral() |
1399 << kLoadLiteralScaleLog2); | 3580 << kLoadLiteralScaleLog2); |
1400 return 9; | 3581 return 9; |
1401 } | 3582 } |
1402 case 'S': { // ILS - Immediate Load/Store. | 3583 case 'S': { // ILS - Immediate Load/Store. |
1403 if (instr->ImmLS() != 0) { | 3584 if (instr->ImmLS() != 0) { |
1404 AppendToOutput(", #%" PRId32, instr->ImmLS()); | 3585 AppendToOutput(", #%" PRId32, instr->ImmLS()); |
1405 } | 3586 } |
1406 return 3; | 3587 return 3; |
1407 } | 3588 } |
1408 case 'P': { // ILPx - Immediate Load/Store Pair, x = access size. | 3589 case 'P': { // ILPx - Immediate Load/Store Pair, x = access size. |
1409 if (instr->ImmLSPair() != 0) { | 3590 if (instr->ImmLSPair() != 0) { |
1410 // format[3] is the scale value. Convert to a number. | 3591 // format[3] is the scale value. Convert to a number. |
1411 int scale = format[3] - 0x30; | 3592 int scale = 1 << (format[3] - '0'); |
1412 AppendToOutput(", #%" PRId32, instr->ImmLSPair() * scale); | 3593 AppendToOutput(", #%" PRId32, instr->ImmLSPair() * scale); |
1413 } | 3594 } |
1414 return 4; | 3595 return 4; |
1415 } | 3596 } |
1416 case 'U': { // ILU - Immediate Load/Store Unsigned. | 3597 case 'U': { // ILU - Immediate Load/Store Unsigned. |
1417 if (instr->ImmLSUnsigned() != 0) { | 3598 if (instr->ImmLSUnsigned() != 0) { |
1418 AppendToOutput(", #%" PRId32, instr->ImmLSUnsigned() | 3599 int shift = instr->SizeLS(); |
1419 << instr->SizeLS()); | 3600 AppendToOutput(", #%" PRId32, instr->ImmLSUnsigned() << shift); |
1420 } | 3601 } |
1421 return 3; | 3602 return 3; |
1422 } | 3603 } |
1423 } | 3604 } |
1424 } | 3605 } |
1425 case 'C': { // ICondB - Immediate Conditional Branch. | 3606 case 'C': { // ICondB - Immediate Conditional Branch. |
1426 int64_t offset = instr->ImmCondBranch() << 2; | 3607 int64_t offset = instr->ImmCondBranch() << 2; |
1427 char sign = (offset >= 0) ? '+' : '-'; | 3608 char sign = (offset >= 0) ? '+' : '-'; |
1428 AppendToOutput("#%c0x%" PRIx64, sign, offset); | 3609 AppendToOutput("#%c0x%" PRIx64, sign, offset); |
1429 return 6; | 3610 return 6; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1465 } | 3646 } |
1466 case 'E': { // IExtract. | 3647 case 'E': { // IExtract. |
1467 AppendToOutput("#%d", instr->ImmS()); | 3648 AppendToOutput("#%d", instr->ImmS()); |
1468 return 8; | 3649 return 8; |
1469 } | 3650 } |
1470 case 'S': { // IS - Test and branch bit. | 3651 case 'S': { // IS - Test and branch bit. |
1471 AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) | | 3652 AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) | |
1472 instr->ImmTestBranchBit40()); | 3653 instr->ImmTestBranchBit40()); |
1473 return 2; | 3654 return 2; |
1474 } | 3655 } |
3656 case 's': { // Is - Shift (immediate). | |
3657 switch (format[2]) { | |
3658 case '1': { // Is1 - SSHR. | |
3659 int shift = 16 << HighestSetBitPosition(instr->ImmNEONImmh()); | |
3660 shift -= instr->ImmNEONImmhImmb(); | |
3661 AppendToOutput("#%d", shift); | |
3662 return 3; | |
3663 } | |
3664 case '2': { // Is2 - SLI. | |
3665 int shift = instr->ImmNEONImmhImmb(); | |
3666 shift -= 8 << HighestSetBitPosition(instr->ImmNEONImmh()); | |
3667 AppendToOutput("#%d", shift); | |
3668 return 3; | |
3669 } | |
3670 default: { | |
3671 UNIMPLEMENTED(); | |
3672 return 0; | |
3673 } | |
3674 } | |
3675 } | |
1475 case 'D': { // IDebug - HLT and BRK instructions. | 3676 case 'D': { // IDebug - HLT and BRK instructions. |
1476 AppendToOutput("#0x%x", instr->ImmException()); | 3677 AppendToOutput("#0x%x", instr->ImmException()); |
1477 return 6; | 3678 return 6; |
1478 } | 3679 } |
3680 case 'V': { // Immediate Vector. | |
3681 switch (format[2]) { | |
3682 case 'E': { // IVExtract. | |
3683 AppendToOutput("#%" PRId64, instr->ImmNEONExt()); | |
3684 return 9; | |
3685 } | |
3686 case 'B': { // IVByElemIndex. | |
3687 int vm_index = (instr->NEONH() << 1) | instr->NEONL(); | |
3688 if (instr->NEONSize() == 1) { | |
3689 vm_index = (vm_index << 1) | instr->NEONM(); | |
3690 } | |
3691 AppendToOutput("%d", vm_index); | |
3692 return strlen("IVByElemIndex"); | |
3693 } | |
3694 case 'I': { // INS element. | |
3695 if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) { | |
3696 unsigned rd_index, rn_index; | |
3697 unsigned imm5 = instr->ImmNEON5(); | |
3698 unsigned imm4 = instr->ImmNEON4(); | |
3699 int tz = CountTrailingZeros(imm5, 32); | |
3700 if (tz <= 3) { // Defined for 0 <= tz <= 3 only. | |
3701 rd_index = imm5 >> (tz + 1); | |
3702 rn_index = imm4 >> tz; | |
3703 if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) { | |
3704 AppendToOutput("%d", rd_index); | |
3705 return strlen("IVInsIndex1"); | |
3706 } else if (strncmp(format, "IVInsIndex2", | |
3707 strlen("IVInsIndex2")) == 0) { | |
3708 AppendToOutput("%d", rn_index); | |
3709 return strlen("IVInsIndex2"); | |
3710 } | |
3711 } | |
3712 return 0; | |
3713 } | |
3714 } | |
3715 case 'L': { // IVLSLane[0123] - suffix indicates access size shift. | |
3716 AppendToOutput("%d", instr->NEONLSIndex(format[8] - '0')); | |
3717 return 9; | |
3718 } | |
3719 case 'M': { // Modified Immediate cases. | |
3720 if (strncmp(format, "IVMIImmFPSingle", strlen("IVMIImmFPSingle")) == | |
3721 0) { | |
3722 AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmNEONabcdefgh(), | |
3723 instr->ImmNEONFP32()); | |
3724 return strlen("IVMIImmFPSingle"); | |
3725 } else if (strncmp(format, "IVMIImmFPDouble", | |
3726 strlen("IVMIImmFPDouble")) == 0) { | |
3727 AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmNEONabcdefgh(), | |
3728 instr->ImmNEONFP64()); | |
3729 return strlen("IVMIImmFPDouble"); | |
3730 } else if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) { | |
3731 uint64_t imm8 = instr->ImmNEONabcdefgh(); | |
3732 AppendToOutput("#0x%" PRIx64, imm8); | |
3733 return strlen("IVMIImm8"); | |
3734 } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) { | |
3735 uint64_t imm8 = instr->ImmNEONabcdefgh(); | |
3736 uint64_t imm = 0; | |
3737 for (int i = 0; i < 8; ++i) { | |
3738 if (imm8 & (1 << i)) { | |
3739 imm |= (UINT64_C(0xff) << (8 * i)); | |
3740 } | |
3741 } | |
3742 AppendToOutput("#0x%" PRIx64, imm); | |
3743 return strlen("IVMIImm"); | |
3744 } else if (strncmp(format, "IVMIShiftAmt1", | |
3745 strlen("IVMIShiftAmt1")) == 0) { | |
3746 int cmode = instr->NEONCmode(); | |
3747 int shift_amount = 8 * ((cmode >> 1) & 3); | |
3748 AppendToOutput("#%d", shift_amount); | |
3749 return strlen("IVMIShiftAmt1"); | |
3750 } else if (strncmp(format, "IVMIShiftAmt2", | |
3751 strlen("IVMIShiftAmt2")) == 0) { | |
3752 int cmode = instr->NEONCmode(); | |
3753 int shift_amount = 8 << (cmode & 1); | |
3754 AppendToOutput("#%d", shift_amount); | |
3755 return strlen("IVMIShiftAmt2"); | |
3756 } else { | |
3757 UNIMPLEMENTED(); | |
3758 return 0; | |
3759 } | |
3760 } | |
3761 default: { | |
3762 UNIMPLEMENTED(); | |
3763 return 0; | |
3764 } | |
3765 } | |
3766 } | |
1479 default: { | 3767 default: { |
3768 printf("%s", format); | |
1480 UNREACHABLE(); | 3769 UNREACHABLE(); |
1481 return 0; | 3770 return 0; |
1482 } | 3771 } |
1483 } | 3772 } |
1484 } | 3773 } |
1485 | 3774 |
1486 | 3775 |
1487 int DisassemblingDecoder::SubstituteBitfieldImmediateField(Instruction* instr, | 3776 int DisassemblingDecoder::SubstituteBitfieldImmediateField(Instruction* instr, |
1488 const char* format) { | 3777 const char* format) { |
1489 DCHECK((format[0] == 'I') && (format[1] == 'B')); | 3778 DCHECK((format[0] == 'I') && (format[1] == 'B')); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1534 break; | 3823 break; |
1535 default: UNREACHABLE(); | 3824 default: UNREACHABLE(); |
1536 } | 3825 } |
1537 | 3826 |
1538 return 6; | 3827 return 6; |
1539 } | 3828 } |
1540 | 3829 |
1541 | 3830 |
1542 int DisassemblingDecoder::SubstituteShiftField(Instruction* instr, | 3831 int DisassemblingDecoder::SubstituteShiftField(Instruction* instr, |
1543 const char* format) { | 3832 const char* format) { |
1544 DCHECK(format[0] == 'H'); | 3833 DCHECK_EQ(format[0], 'N'); |
1545 DCHECK(instr->ShiftDP() <= 0x3); | 3834 DCHECK_LE(instr->ShiftDP(), 0x3); |
1546 | 3835 |
1547 switch (format[1]) { | 3836 switch (format[1]) { |
1548 case 'D': { // HDP. | 3837 case 'D': { // NDP. |
1549 DCHECK(instr->ShiftDP() != ROR); | 3838 DCHECK(instr->ShiftDP() != ROR); |
1550 } // Fall through. | 3839 } // Fall through. |
1551 case 'L': { // HLo. | 3840 case 'L': { // NLo. |
1552 if (instr->ImmDPShift() != 0) { | 3841 if (instr->ImmDPShift() != 0) { |
1553 const char* shift_type[] = {"lsl", "lsr", "asr", "ror"}; | 3842 const char* shift_type[] = {"lsl", "lsr", "asr", "ror"}; |
1554 AppendToOutput(", %s #%" PRId32, shift_type[instr->ShiftDP()], | 3843 AppendToOutput(", %s #%" PRId32, shift_type[instr->ShiftDP()], |
1555 instr->ImmDPShift()); | 3844 instr->ImmDPShift()); |
1556 } | 3845 } |
1557 return 3; | 3846 return 3; |
1558 } | 3847 } |
1559 default: | 3848 default: |
1560 UNREACHABLE(); | 3849 UNREACHABLE(); |
1561 return 0; | 3850 return 0; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1600 sign = '-'; | 3889 sign = '-'; |
1601 } | 3890 } |
1602 AppendToOutput("#%c0x%x (addr %p)", sign, offset, | 3891 AppendToOutput("#%c0x%x (addr %p)", sign, offset, |
1603 instr->InstructionAtOffset(offset, Instruction::NO_CHECK)); | 3892 instr->InstructionAtOffset(offset, Instruction::NO_CHECK)); |
1604 return 13; | 3893 return 13; |
1605 } | 3894 } |
1606 | 3895 |
1607 | 3896 |
1608 int DisassemblingDecoder::SubstituteBranchTargetField(Instruction* instr, | 3897 int DisassemblingDecoder::SubstituteBranchTargetField(Instruction* instr, |
1609 const char* format) { | 3898 const char* format) { |
1610 DCHECK(strncmp(format, "BImm", 4) == 0); | 3899 DCHECK_EQ(strncmp(format, "TImm", 4), 0); |
1611 | 3900 |
1612 int64_t offset = 0; | 3901 int64_t offset = 0; |
1613 switch (format[5]) { | 3902 switch (format[5]) { |
1614 // BImmUncn - unconditional branch immediate. | 3903 // TImmUncn - unconditional branch immediate. |
1615 case 'n': offset = instr->ImmUncondBranch(); break; | 3904 case 'n': offset = instr->ImmUncondBranch(); break; |
1616 // BImmCond - conditional branch immediate. | 3905 // TImmCond - conditional branch immediate. |
1617 case 'o': offset = instr->ImmCondBranch(); break; | 3906 case 'o': offset = instr->ImmCondBranch(); break; |
1618 // BImmCmpa - compare and branch immediate. | 3907 // TImmCmpa - compare and branch immediate. |
1619 case 'm': offset = instr->ImmCmpBranch(); break; | 3908 case 'm': offset = instr->ImmCmpBranch(); break; |
1620 // BImmTest - test and branch immediate. | 3909 // TImmTest - test and branch immediate. |
1621 case 'e': offset = instr->ImmTestBranch(); break; | 3910 case 'e': offset = instr->ImmTestBranch(); break; |
1622 default: UNREACHABLE(); | 3911 default: UNREACHABLE(); |
1623 } | 3912 } |
1624 offset <<= kInstructionSizeLog2; | 3913 offset <<= kInstructionSizeLog2; |
1625 char sign = '+'; | 3914 char sign = '+'; |
1626 if (offset < 0) { | 3915 if (offset < 0) { |
1627 sign = '-'; | 3916 sign = '-'; |
1628 } | 3917 } |
1629 AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset), | 3918 AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset), |
1630 instr->InstructionAtOffset(offset), Instruction::NO_CHECK); | 3919 instr->InstructionAtOffset(offset), Instruction::NO_CHECK); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1840 decoder.AppendVisitor(&disasm); | 4129 decoder.AppendVisitor(&disasm); |
1841 | 4130 |
1842 for (byte* pc = start; pc < end; pc += v8::internal::kInstructionSize) { | 4131 for (byte* pc = start; pc < end; pc += v8::internal::kInstructionSize) { |
1843 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc)); | 4132 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc)); |
1844 } | 4133 } |
1845 } | 4134 } |
1846 | 4135 |
1847 } // namespace disasm | 4136 } // namespace disasm |
1848 | 4137 |
1849 #endif // V8_TARGET_ARCH_ARM64 | 4138 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |