Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: src/arm64/disasm-arm64.cc

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

Powered by Google App Engine
This is Rietveld 408576698