1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include <bitset>
28 #include <cstdlib>
29 #include <sstream>
30
31 #include "disasm-aarch64.h"
32
33 namespace vixl {
34 namespace aarch64 {
35
36
Disassembler()37 Disassembler::Disassembler() {
38 buffer_size_ = 256;
39 buffer_ = reinterpret_cast<char *>(malloc(buffer_size_));
40 buffer_pos_ = 0;
41 own_buffer_ = true;
42 code_address_offset_ = 0;
43 }
44
45
Disassembler(char * text_buffer,int buffer_size)46 Disassembler::Disassembler(char *text_buffer, int buffer_size) {
47 buffer_size_ = buffer_size;
48 buffer_ = text_buffer;
49 buffer_pos_ = 0;
50 own_buffer_ = false;
51 code_address_offset_ = 0;
52 }
53
54
~Disassembler()55 Disassembler::~Disassembler() {
56 if (own_buffer_) {
57 free(buffer_);
58 }
59 }
60
61
GetOutput()62 char *Disassembler::GetOutput() { return buffer_; }
63
64
VisitAddSubImmediate(const Instruction * instr)65 void Disassembler::VisitAddSubImmediate(const Instruction *instr) {
66 bool rd_is_zr = RdIsZROrSP(instr);
67 bool stack_op =
68 (rd_is_zr || RnIsZROrSP(instr)) && (instr->GetImmAddSub() == 0) ? true
69 : false;
70 const char *mnemonic = "";
71 const char *form = "'Rds, 'Rns, 'IAddSub";
72 const char *form_cmp = "'Rns, 'IAddSub";
73 const char *form_mov = "'Rds, 'Rns";
74
75 switch (instr->Mask(AddSubImmediateMask)) {
76 case ADD_w_imm:
77 case ADD_x_imm: {
78 mnemonic = "add";
79 if (stack_op) {
80 mnemonic = "mov";
81 form = form_mov;
82 }
83 break;
84 }
85 case ADDS_w_imm:
86 case ADDS_x_imm: {
87 mnemonic = "adds";
88 if (rd_is_zr) {
89 mnemonic = "cmn";
90 form = form_cmp;
91 }
92 break;
93 }
94 case SUB_w_imm:
95 case SUB_x_imm:
96 mnemonic = "sub";
97 break;
98 case SUBS_w_imm:
99 case SUBS_x_imm: {
100 mnemonic = "subs";
101 if (rd_is_zr) {
102 mnemonic = "cmp";
103 form = form_cmp;
104 }
105 break;
106 }
107 default:
108 VIXL_UNREACHABLE();
109 }
110 Format(instr, mnemonic, form);
111 }
112
113
VisitAddSubShifted(const Instruction * instr)114 void Disassembler::VisitAddSubShifted(const Instruction *instr) {
115 bool rd_is_zr = RdIsZROrSP(instr);
116 bool rn_is_zr = RnIsZROrSP(instr);
117 const char *mnemonic = "";
118 const char *form = "'Rd, 'Rn, 'Rm'NDP";
119 const char *form_cmp = "'Rn, 'Rm'NDP";
120 const char *form_neg = "'Rd, 'Rm'NDP";
121
122 switch (instr->Mask(AddSubShiftedMask)) {
123 case ADD_w_shift:
124 case ADD_x_shift:
125 mnemonic = "add";
126 break;
127 case ADDS_w_shift:
128 case ADDS_x_shift: {
129 mnemonic = "adds";
130 if (rd_is_zr) {
131 mnemonic = "cmn";
132 form = form_cmp;
133 }
134 break;
135 }
136 case SUB_w_shift:
137 case SUB_x_shift: {
138 mnemonic = "sub";
139 if (rn_is_zr) {
140 mnemonic = "neg";
141 form = form_neg;
142 }
143 break;
144 }
145 case SUBS_w_shift:
146 case SUBS_x_shift: {
147 mnemonic = "subs";
148 if (rd_is_zr) {
149 mnemonic = "cmp";
150 form = form_cmp;
151 } else if (rn_is_zr) {
152 mnemonic = "negs";
153 form = form_neg;
154 }
155 break;
156 }
157 default:
158 VIXL_UNREACHABLE();
159 }
160 Format(instr, mnemonic, form);
161 }
162
163
VisitAddSubExtended(const Instruction * instr)164 void Disassembler::VisitAddSubExtended(const Instruction *instr) {
165 bool rd_is_zr = RdIsZROrSP(instr);
166 const char *mnemonic = "";
167 Extend mode = static_cast<Extend>(instr->GetExtendMode());
168 const char *form = ((mode == UXTX) || (mode == SXTX)) ? "'Rds, 'Rns, 'Xm'Ext"
169 : "'Rds, 'Rns, 'Wm'Ext";
170 const char *form_cmp =
171 ((mode == UXTX) || (mode == SXTX)) ? "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
172
173 switch (instr->Mask(AddSubExtendedMask)) {
174 case ADD_w_ext:
175 case ADD_x_ext:
176 mnemonic = "add";
177 break;
178 case ADDS_w_ext:
179 case ADDS_x_ext: {
180 mnemonic = "adds";
181 if (rd_is_zr) {
182 mnemonic = "cmn";
183 form = form_cmp;
184 }
185 break;
186 }
187 case SUB_w_ext:
188 case SUB_x_ext:
189 mnemonic = "sub";
190 break;
191 case SUBS_w_ext:
192 case SUBS_x_ext: {
193 mnemonic = "subs";
194 if (rd_is_zr) {
195 mnemonic = "cmp";
196 form = form_cmp;
197 }
198 break;
199 }
200 default:
201 VIXL_UNREACHABLE();
202 }
203 Format(instr, mnemonic, form);
204 }
205
206
VisitAddSubWithCarry(const Instruction * instr)207 void Disassembler::VisitAddSubWithCarry(const Instruction *instr) {
208 bool rn_is_zr = RnIsZROrSP(instr);
209 const char *mnemonic = "";
210 const char *form = "'Rd, 'Rn, 'Rm";
211 const char *form_neg = "'Rd, 'Rm";
212
213 switch (instr->Mask(AddSubWithCarryMask)) {
214 case ADC_w:
215 case ADC_x:
216 mnemonic = "adc";
217 break;
218 case ADCS_w:
219 case ADCS_x:
220 mnemonic = "adcs";
221 break;
222 case SBC_w:
223 case SBC_x: {
224 mnemonic = "sbc";
225 if (rn_is_zr) {
226 mnemonic = "ngc";
227 form = form_neg;
228 }
229 break;
230 }
231 case SBCS_w:
232 case SBCS_x: {
233 mnemonic = "sbcs";
234 if (rn_is_zr) {
235 mnemonic = "ngcs";
236 form = form_neg;
237 }
238 break;
239 }
240 default:
241 VIXL_UNREACHABLE();
242 }
243 Format(instr, mnemonic, form);
244 }
245
246
VisitRotateRightIntoFlags(const Instruction * instr)247 void Disassembler::VisitRotateRightIntoFlags(const Instruction *instr) {
248 const char *mnemonic = "unimplemented";
249 const char *form = "(RotateRightIntoFlags)";
250
251 switch (instr->Mask(RotateRightIntoFlagsMask)) {
252 case RMIF:
253 mnemonic = "rmif";
254 form = "'Xn, 'IRr, 'INzcv";
255 break;
256 default:
257 VIXL_UNREACHABLE();
258 }
259
260 Format(instr, mnemonic, form);
261 }
262
263
VisitEvaluateIntoFlags(const Instruction * instr)264 void Disassembler::VisitEvaluateIntoFlags(const Instruction *instr) {
265 const char *mnemonic = "unimplemented";
266 const char *form = "(EvaluateIntoFlags)";
267
268 switch (instr->Mask(EvaluateIntoFlagsMask)) {
269 case SETF8:
270 mnemonic = "setf8";
271 form = "'Wn";
272 break;
273 case SETF16:
274 mnemonic = "setf16";
275 form = "'Wn";
276 break;
277 default:
278 VIXL_UNREACHABLE();
279 }
280
281 Format(instr, mnemonic, form);
282 }
283
284
VisitLogicalImmediate(const Instruction * instr)285 void Disassembler::VisitLogicalImmediate(const Instruction *instr) {
286 bool rd_is_zr = RdIsZROrSP(instr);
287 bool rn_is_zr = RnIsZROrSP(instr);
288 const char *mnemonic = "";
289 const char *form = "'Rds, 'Rn, 'ITri";
290
291 if (instr->GetImmLogical() == 0) {
292 // The immediate encoded in the instruction is not in the expected format.
293 Format(instr, "unallocated", "(LogicalImmediate)");
294 return;
295 }
296
297 switch (instr->Mask(LogicalImmediateMask)) {
298 case AND_w_imm:
299 case AND_x_imm:
300 mnemonic = "and";
301 break;
302 case ORR_w_imm:
303 case ORR_x_imm: {
304 mnemonic = "orr";
305 unsigned reg_size =
306 (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
307 if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->GetImmLogical())) {
308 mnemonic = "mov";
309 form = "'Rds, 'ITri";
310 }
311 break;
312 }
313 case EOR_w_imm:
314 case EOR_x_imm:
315 mnemonic = "eor";
316 break;
317 case ANDS_w_imm:
318 case ANDS_x_imm: {
319 mnemonic = "ands";
320 if (rd_is_zr) {
321 mnemonic = "tst";
322 form = "'Rn, 'ITri";
323 }
324 break;
325 }
326 default:
327 VIXL_UNREACHABLE();
328 }
329 Format(instr, mnemonic, form);
330 }
331
332
IsMovzMovnImm(unsigned reg_size,uint64_t value)333 bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
334 VIXL_ASSERT((reg_size == kXRegSize) ||
335 ((reg_size == kWRegSize) && (value <= 0xffffffff)));
336
337 // Test for movz: 16 bits set at positions 0, 16, 32 or 48.
338 if (((value & UINT64_C(0xffffffffffff0000)) == 0) ||
339 ((value & UINT64_C(0xffffffff0000ffff)) == 0) ||
340 ((value & UINT64_C(0xffff0000ffffffff)) == 0) ||
341 ((value & UINT64_C(0x0000ffffffffffff)) == 0)) {
342 return true;
343 }
344
345 // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
346 if ((reg_size == kXRegSize) &&
347 (((~value & UINT64_C(0xffffffffffff0000)) == 0) ||
348 ((~value & UINT64_C(0xffffffff0000ffff)) == 0) ||
349 ((~value & UINT64_C(0xffff0000ffffffff)) == 0) ||
350 ((~value & UINT64_C(0x0000ffffffffffff)) == 0))) {
351 return true;
352 }
353 if ((reg_size == kWRegSize) && (((value & 0xffff0000) == 0xffff0000) ||
354 ((value & 0x0000ffff) == 0x0000ffff))) {
355 return true;
356 }
357 return false;
358 }
359
360
VisitLogicalShifted(const Instruction * instr)361 void Disassembler::VisitLogicalShifted(const Instruction *instr) {
362 bool rd_is_zr = RdIsZROrSP(instr);
363 bool rn_is_zr = RnIsZROrSP(instr);
364 const char *mnemonic = "";
365 const char *form = "'Rd, 'Rn, 'Rm'NLo";
366
367 switch (instr->Mask(LogicalShiftedMask)) {
368 case AND_w:
369 case AND_x:
370 mnemonic = "and";
371 break;
372 case BIC_w:
373 case BIC_x:
374 mnemonic = "bic";
375 break;
376 case EOR_w:
377 case EOR_x:
378 mnemonic = "eor";
379 break;
380 case EON_w:
381 case EON_x:
382 mnemonic = "eon";
383 break;
384 case BICS_w:
385 case BICS_x:
386 mnemonic = "bics";
387 break;
388 case ANDS_w:
389 case ANDS_x: {
390 mnemonic = "ands";
391 if (rd_is_zr) {
392 mnemonic = "tst";
393 form = "'Rn, 'Rm'NLo";
394 }
395 break;
396 }
397 case ORR_w:
398 case ORR_x: {
399 mnemonic = "orr";
400 if (rn_is_zr && (instr->GetImmDPShift() == 0) &&
401 (instr->GetShiftDP() == LSL)) {
402 mnemonic = "mov";
403 form = "'Rd, 'Rm";
404 }
405 break;
406 }
407 case ORN_w:
408 case ORN_x: {
409 mnemonic = "orn";
410 if (rn_is_zr) {
411 mnemonic = "mvn";
412 form = "'Rd, 'Rm'NLo";
413 }
414 break;
415 }
416 default:
417 VIXL_UNREACHABLE();
418 }
419
420 Format(instr, mnemonic, form);
421 }
422
423
VisitConditionalCompareRegister(const Instruction * instr)424 void Disassembler::VisitConditionalCompareRegister(const Instruction *instr) {
425 const char *mnemonic = "";
426 const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
427
428 switch (instr->Mask(ConditionalCompareRegisterMask)) {
429 case CCMN_w:
430 case CCMN_x:
431 mnemonic = "ccmn";
432 break;
433 case CCMP_w:
434 case CCMP_x:
435 mnemonic = "ccmp";
436 break;
437 default:
438 VIXL_UNREACHABLE();
439 }
440 Format(instr, mnemonic, form);
441 }
442
443
VisitConditionalCompareImmediate(const Instruction * instr)444 void Disassembler::VisitConditionalCompareImmediate(const Instruction *instr) {
445 const char *mnemonic = "";
446 const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
447
448 switch (instr->Mask(ConditionalCompareImmediateMask)) {
449 case CCMN_w_imm:
450 case CCMN_x_imm:
451 mnemonic = "ccmn";
452 break;
453 case CCMP_w_imm:
454 case CCMP_x_imm:
455 mnemonic = "ccmp";
456 break;
457 default:
458 VIXL_UNREACHABLE();
459 }
460 Format(instr, mnemonic, form);
461 }
462
463
VisitConditionalSelect(const Instruction * instr)464 void Disassembler::VisitConditionalSelect(const Instruction *instr) {
465 bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
466 bool rn_is_rm = (instr->GetRn() == instr->GetRm());
467 const char *mnemonic = "";
468 const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
469 const char *form_test = "'Rd, 'CInv";
470 const char *form_update = "'Rd, 'Rn, 'CInv";
471
472 Condition cond = static_cast<Condition>(instr->GetCondition());
473 bool invertible_cond = (cond != al) && (cond != nv);
474
475 switch (instr->Mask(ConditionalSelectMask)) {
476 case CSEL_w:
477 case CSEL_x:
478 mnemonic = "csel";
479 break;
480 case CSINC_w:
481 case CSINC_x: {
482 mnemonic = "csinc";
483 if (rnm_is_zr && invertible_cond) {
484 mnemonic = "cset";
485 form = form_test;
486 } else if (rn_is_rm && invertible_cond) {
487 mnemonic = "cinc";
488 form = form_update;
489 }
490 break;
491 }
492 case CSINV_w:
493 case CSINV_x: {
494 mnemonic = "csinv";
495 if (rnm_is_zr && invertible_cond) {
496 mnemonic = "csetm";
497 form = form_test;
498 } else if (rn_is_rm && invertible_cond) {
499 mnemonic = "cinv";
500 form = form_update;
501 }
502 break;
503 }
504 case CSNEG_w:
505 case CSNEG_x: {
506 mnemonic = "csneg";
507 if (rn_is_rm && invertible_cond) {
508 mnemonic = "cneg";
509 form = form_update;
510 }
511 break;
512 }
513 default:
514 VIXL_UNREACHABLE();
515 }
516 Format(instr, mnemonic, form);
517 }
518
519
VisitBitfield(const Instruction * instr)520 void Disassembler::VisitBitfield(const Instruction *instr) {
521 unsigned s = instr->GetImmS();
522 unsigned r = instr->GetImmR();
523 unsigned rd_size_minus_1 =
524 ((instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize) - 1;
525 const char *mnemonic = "";
526 const char *form = "";
527 const char *form_shift_right = "'Rd, 'Rn, 'IBr";
528 const char *form_extend = "'Rd, 'Wn";
529 const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
530 const char *form_bfc = "'Rd, 'IBZ-r, 'IBs+1";
531 const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
532 const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
533
534 switch (instr->Mask(BitfieldMask)) {
535 case SBFM_w:
536 case SBFM_x: {
537 mnemonic = "sbfx";
538 form = form_bfx;
539 if (r == 0) {
540 form = form_extend;
541 if (s == 7) {
542 mnemonic = "sxtb";
543 } else if (s == 15) {
544 mnemonic = "sxth";
545 } else if ((s == 31) && (instr->GetSixtyFourBits() == 1)) {
546 mnemonic = "sxtw";
547 } else {
548 form = form_bfx;
549 }
550 } else if (s == rd_size_minus_1) {
551 mnemonic = "asr";
552 form = form_shift_right;
553 } else if (s < r) {
554 mnemonic = "sbfiz";
555 form = form_bfiz;
556 }
557 break;
558 }
559 case UBFM_w:
560 case UBFM_x: {
561 mnemonic = "ubfx";
562 form = form_bfx;
563 if (r == 0) {
564 form = form_extend;
565 if (s == 7) {
566 mnemonic = "uxtb";
567 } else if (s == 15) {
568 mnemonic = "uxth";
569 } else {
570 form = form_bfx;
571 }
572 }
573 if (s == rd_size_minus_1) {
574 mnemonic = "lsr";
575 form = form_shift_right;
576 } else if (r == s + 1) {
577 mnemonic = "lsl";
578 form = form_lsl;
579 } else if (s < r) {
580 mnemonic = "ubfiz";
581 form = form_bfiz;
582 }
583 break;
584 }
585 case BFM_w:
586 case BFM_x: {
587 mnemonic = "bfxil";
588 form = form_bfx;
589 if (s < r) {
590 if (instr->GetRn() == kZeroRegCode) {
591 mnemonic = "bfc";
592 form = form_bfc;
593 } else {
594 mnemonic = "bfi";
595 form = form_bfiz;
596 }
597 }
598 }
599 }
600 Format(instr, mnemonic, form);
601 }
602
603
VisitExtract(const Instruction * instr)604 void Disassembler::VisitExtract(const Instruction *instr) {
605 const char *mnemonic = "";
606 const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
607
608 switch (instr->Mask(ExtractMask)) {
609 case EXTR_w:
610 case EXTR_x: {
611 if (instr->GetRn() == instr->GetRm()) {
612 mnemonic = "ror";
613 form = "'Rd, 'Rn, 'IExtract";
614 } else {
615 mnemonic = "extr";
616 }
617 break;
618 }
619 default:
620 VIXL_UNREACHABLE();
621 }
622 Format(instr, mnemonic, form);
623 }
624
625
VisitPCRelAddressing(const Instruction * instr)626 void Disassembler::VisitPCRelAddressing(const Instruction *instr) {
627 switch (instr->Mask(PCRelAddressingMask)) {
628 case ADR:
629 Format(instr, "adr", "'Xd, 'AddrPCRelByte");
630 break;
631 case ADRP:
632 Format(instr, "adrp", "'Xd, 'AddrPCRelPage");
633 break;
634 default:
635 Format(instr, "unimplemented", "(PCRelAddressing)");
636 }
637 }
638
639
VisitConditionalBranch(const Instruction * instr)640 void Disassembler::VisitConditionalBranch(const Instruction *instr) {
641 switch (instr->Mask(ConditionalBranchMask)) {
642 case B_cond:
643 Format(instr, "b.'CBrn", "'TImmCond");
644 break;
645 default:
646 VIXL_UNREACHABLE();
647 }
648 }
649
650
VisitUnconditionalBranchToRegister(const Instruction * instr)651 void Disassembler::VisitUnconditionalBranchToRegister(
652 const Instruction *instr) {
653 const char *mnemonic = "unimplemented";
654 const char *form;
655
656 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
657 case BR:
658 mnemonic = "br";
659 form = "'Xn";
660 break;
661 case BLR:
662 mnemonic = "blr";
663 form = "'Xn";
664 break;
665 case RET: {
666 mnemonic = "ret";
667 if (instr->GetRn() == kLinkRegCode) {
668 form = NULL;
669 } else {
670 form = "'Xn";
671 }
672 break;
673 }
674 case BRAAZ:
675 mnemonic = "braaz";
676 form = "'Xn";
677 break;
678 case BRABZ:
679 mnemonic = "brabz";
680 form = "'Xn";
681 break;
682 case BLRAAZ:
683 mnemonic = "blraaz";
684 form = "'Xn";
685 break;
686 case BLRABZ:
687 mnemonic = "blrabz";
688 form = "'Xn";
689 break;
690 case RETAA:
691 mnemonic = "retaa";
692 form = NULL;
693 break;
694 case RETAB:
695 mnemonic = "retab";
696 form = NULL;
697 break;
698 case BRAA:
699 mnemonic = "braa";
700 form = "'Xn, 'Xds";
701 break;
702 case BRAB:
703 mnemonic = "brab";
704 form = "'Xn, 'Xds";
705 break;
706 case BLRAA:
707 mnemonic = "blraa";
708 form = "'Xn, 'Xds";
709 break;
710 case BLRAB:
711 mnemonic = "blrab";
712 form = "'Xn, 'Xds";
713 break;
714 default:
715 form = "(UnconditionalBranchToRegister)";
716 }
717 Format(instr, mnemonic, form);
718 }
719
720
VisitUnconditionalBranch(const Instruction * instr)721 void Disassembler::VisitUnconditionalBranch(const Instruction *instr) {
722 const char *mnemonic = "";
723 const char *form = "'TImmUncn";
724
725 switch (instr->Mask(UnconditionalBranchMask)) {
726 case B:
727 mnemonic = "b";
728 break;
729 case BL:
730 mnemonic = "bl";
731 break;
732 default:
733 VIXL_UNREACHABLE();
734 }
735 Format(instr, mnemonic, form);
736 }
737
738
VisitDataProcessing1Source(const Instruction * instr)739 void Disassembler::VisitDataProcessing1Source(const Instruction *instr) {
740 const char *mnemonic = "";
741 const char *form = "'Rd, 'Rn";
742
743 switch (instr->Mask(DataProcessing1SourceMask)) {
744 #define FORMAT(A, B) \
745 case A##_w: \
746 case A##_x: \
747 mnemonic = B; \
748 break;
749 FORMAT(RBIT, "rbit");
750 FORMAT(REV16, "rev16");
751 FORMAT(REV, "rev");
752 FORMAT(CLZ, "clz");
753 FORMAT(CLS, "cls");
754 #undef FORMAT
755
756 #define PAUTH_VARIATIONS(V) \
757 V(PACI, "paci") \
758 V(PACD, "pacd") \
759 V(AUTI, "auti") \
760 V(AUTD, "autd")
761 #define PAUTH_CASE(NAME, MN) \
762 case NAME##A: \
763 mnemonic = MN "a"; \
764 form = "'Xd, 'Xns"; \
765 break; \
766 case NAME##ZA: \
767 mnemonic = MN "za"; \
768 form = "'Xd"; \
769 break; \
770 case NAME##B: \
771 mnemonic = MN "b"; \
772 form = "'Xd, 'Xns"; \
773 break; \
774 case NAME##ZB: \
775 mnemonic = MN "zb"; \
776 form = "'Xd"; \
777 break;
778
779 PAUTH_VARIATIONS(PAUTH_CASE)
780 #undef PAUTH_CASE
781
782 case XPACI:
783 mnemonic = "xpaci";
784 form = "'Xd";
785 break;
786 case XPACD:
787 mnemonic = "xpacd";
788 form = "'Xd";
789 break;
790 case REV32_x:
791 mnemonic = "rev32";
792 break;
793 default:
794 VIXL_UNREACHABLE();
795 }
796 Format(instr, mnemonic, form);
797 }
798
799
VisitDataProcessing2Source(const Instruction * instr)800 void Disassembler::VisitDataProcessing2Source(const Instruction *instr) {
801 const char *mnemonic = "unimplemented";
802 const char *form = "'Rd, 'Rn, 'Rm";
803 const char *form_wwx = "'Wd, 'Wn, 'Xm";
804
805 switch (instr->Mask(DataProcessing2SourceMask)) {
806 #define FORMAT(A, B) \
807 case A##_w: \
808 case A##_x: \
809 mnemonic = B; \
810 break;
811 FORMAT(UDIV, "udiv");
812 FORMAT(SDIV, "sdiv");
813 FORMAT(LSLV, "lsl");
814 FORMAT(LSRV, "lsr");
815 FORMAT(ASRV, "asr");
816 FORMAT(RORV, "ror");
817 #undef FORMAT
818 case PACGA:
819 mnemonic = "pacga";
820 form = "'Xd, 'Xn, 'Xms";
821 break;
822 case CRC32B:
823 mnemonic = "crc32b";
824 break;
825 case CRC32H:
826 mnemonic = "crc32h";
827 break;
828 case CRC32W:
829 mnemonic = "crc32w";
830 break;
831 case CRC32X:
832 mnemonic = "crc32x";
833 form = form_wwx;
834 break;
835 case CRC32CB:
836 mnemonic = "crc32cb";
837 break;
838 case CRC32CH:
839 mnemonic = "crc32ch";
840 break;
841 case CRC32CW:
842 mnemonic = "crc32cw";
843 break;
844 case CRC32CX:
845 mnemonic = "crc32cx";
846 form = form_wwx;
847 break;
848 default:
849 form = "(DataProcessing2Source)";
850 }
851 Format(instr, mnemonic, form);
852 }
853
854
VisitDataProcessing3Source(const Instruction * instr)855 void Disassembler::VisitDataProcessing3Source(const Instruction *instr) {
856 bool ra_is_zr = RaIsZROrSP(instr);
857 const char *mnemonic = "";
858 const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
859 const char *form_rrr = "'Rd, 'Rn, 'Rm";
860 const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
861 const char *form_xww = "'Xd, 'Wn, 'Wm";
862 const char *form_xxx = "'Xd, 'Xn, 'Xm";
863
864 switch (instr->Mask(DataProcessing3SourceMask)) {
865 case MADD_w:
866 case MADD_x: {
867 mnemonic = "madd";
868 form = form_rrrr;
869 if (ra_is_zr) {
870 mnemonic = "mul";
871 form = form_rrr;
872 }
873 break;
874 }
875 case MSUB_w:
876 case MSUB_x: {
877 mnemonic = "msub";
878 form = form_rrrr;
879 if (ra_is_zr) {
880 mnemonic = "mneg";
881 form = form_rrr;
882 }
883 break;
884 }
885 case SMADDL_x: {
886 mnemonic = "smaddl";
887 if (ra_is_zr) {
888 mnemonic = "smull";
889 form = form_xww;
890 }
891 break;
892 }
893 case SMSUBL_x: {
894 mnemonic = "smsubl";
895 if (ra_is_zr) {
896 mnemonic = "smnegl";
897 form = form_xww;
898 }
899 break;
900 }
901 case UMADDL_x: {
902 mnemonic = "umaddl";
903 if (ra_is_zr) {
904 mnemonic = "umull";
905 form = form_xww;
906 }
907 break;
908 }
909 case UMSUBL_x: {
910 mnemonic = "umsubl";
911 if (ra_is_zr) {
912 mnemonic = "umnegl";
913 form = form_xww;
914 }
915 break;
916 }
917 case SMULH_x: {
918 mnemonic = "smulh";
919 form = form_xxx;
920 break;
921 }
922 case UMULH_x: {
923 mnemonic = "umulh";
924 form = form_xxx;
925 break;
926 }
927 default:
928 VIXL_UNREACHABLE();
929 }
930 Format(instr, mnemonic, form);
931 }
932
933
VisitCompareBranch(const Instruction * instr)934 void Disassembler::VisitCompareBranch(const Instruction *instr) {
935 const char *mnemonic = "";
936 const char *form = "'Rt, 'TImmCmpa";
937
938 switch (instr->Mask(CompareBranchMask)) {
939 case CBZ_w:
940 case CBZ_x:
941 mnemonic = "cbz";
942 break;
943 case CBNZ_w:
944 case CBNZ_x:
945 mnemonic = "cbnz";
946 break;
947 default:
948 VIXL_UNREACHABLE();
949 }
950 Format(instr, mnemonic, form);
951 }
952
953
VisitTestBranch(const Instruction * instr)954 void Disassembler::VisitTestBranch(const Instruction *instr) {
955 const char *mnemonic = "";
956 // If the top bit of the immediate is clear, the tested register is
957 // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
958 // encoded in bit 31 of the instruction, we can reuse the Rt form, which
959 // uses bit 31 (normally "sf") to choose the register size.
960 const char *form = "'Rt, 'It, 'TImmTest";
961
962 switch (instr->Mask(TestBranchMask)) {
963 case TBZ:
964 mnemonic = "tbz";
965 break;
966 case TBNZ:
967 mnemonic = "tbnz";
968 break;
969 default:
970 VIXL_UNREACHABLE();
971 }
972 Format(instr, mnemonic, form);
973 }
974
975
VisitMoveWideImmediate(const Instruction * instr)976 void Disassembler::VisitMoveWideImmediate(const Instruction *instr) {
977 const char *mnemonic = "";
978 const char *form = "'Rd, 'IMoveImm";
979
980 // Print the shift separately for movk, to make it clear which half word will
981 // be overwritten. Movn and movz print the computed immediate, which includes
982 // shift calculation.
983 switch (instr->Mask(MoveWideImmediateMask)) {
984 case MOVN_w:
985 case MOVN_x:
986 if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0)) {
987 if ((instr->GetSixtyFourBits() == 0) &&
988 (instr->GetImmMoveWide() == 0xffff)) {
989 mnemonic = "movn";
990 } else {
991 mnemonic = "mov";
992 form = "'Rd, 'IMoveNeg";
993 }
994 } else {
995 mnemonic = "movn";
996 }
997 break;
998 case MOVZ_w:
999 case MOVZ_x:
1000 if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0))
1001 mnemonic = "mov";
1002 else
1003 mnemonic = "movz";
1004 break;
1005 case MOVK_w:
1006 case MOVK_x:
1007 mnemonic = "movk";
1008 form = "'Rd, 'IMoveLSL";
1009 break;
1010 default:
1011 VIXL_UNREACHABLE();
1012 }
1013 Format(instr, mnemonic, form);
1014 }
1015
1016
1017 #define LOAD_STORE_LIST(V) \
1018 V(STRB_w, "strb", "'Wt") \
1019 V(STRH_w, "strh", "'Wt") \
1020 V(STR_w, "str", "'Wt") \
1021 V(STR_x, "str", "'Xt") \
1022 V(LDRB_w, "ldrb", "'Wt") \
1023 V(LDRH_w, "ldrh", "'Wt") \
1024 V(LDR_w, "ldr", "'Wt") \
1025 V(LDR_x, "ldr", "'Xt") \
1026 V(LDRSB_x, "ldrsb", "'Xt") \
1027 V(LDRSH_x, "ldrsh", "'Xt") \
1028 V(LDRSW_x, "ldrsw", "'Xt") \
1029 V(LDRSB_w, "ldrsb", "'Wt") \
1030 V(LDRSH_w, "ldrsh", "'Wt") \
1031 V(STR_b, "str", "'Bt") \
1032 V(STR_h, "str", "'Ht") \
1033 V(STR_s, "str", "'St") \
1034 V(STR_d, "str", "'Dt") \
1035 V(LDR_b, "ldr", "'Bt") \
1036 V(LDR_h, "ldr", "'Ht") \
1037 V(LDR_s, "ldr", "'St") \
1038 V(LDR_d, "ldr", "'Dt") \
1039 V(STR_q, "str", "'Qt") \
1040 V(LDR_q, "ldr", "'Qt")
1041
VisitLoadStorePreIndex(const Instruction * instr)1042 void Disassembler::VisitLoadStorePreIndex(const Instruction *instr) {
1043 const char *mnemonic = "unimplemented";
1044 const char *form = "(LoadStorePreIndex)";
1045
1046 switch (instr->Mask(LoadStorePreIndexMask)) {
1047 #define LS_PREINDEX(A, B, C) \
1048 case A##_pre: \
1049 mnemonic = B; \
1050 form = C ", ['Xns'ILSi]!"; \
1051 break;
1052 LOAD_STORE_LIST(LS_PREINDEX)
1053 #undef LS_PREINDEX
1054 }
1055 Format(instr, mnemonic, form);
1056 }
1057
1058
VisitLoadStorePostIndex(const Instruction * instr)1059 void Disassembler::VisitLoadStorePostIndex(const Instruction *instr) {
1060 const char *mnemonic = "unimplemented";
1061 const char *form = "(LoadStorePostIndex)";
1062
1063 switch (instr->Mask(LoadStorePostIndexMask)) {
1064 #define LS_POSTINDEX(A, B, C) \
1065 case A##_post: \
1066 mnemonic = B; \
1067 form = C ", ['Xns]'ILSi"; \
1068 break;
1069 LOAD_STORE_LIST(LS_POSTINDEX)
1070 #undef LS_POSTINDEX
1071 }
1072 Format(instr, mnemonic, form);
1073 }
1074
1075
VisitLoadStoreUnsignedOffset(const Instruction * instr)1076 void Disassembler::VisitLoadStoreUnsignedOffset(const Instruction *instr) {
1077 const char *mnemonic = "unimplemented";
1078 const char *form = "(LoadStoreUnsignedOffset)";
1079
1080 switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
1081 #define LS_UNSIGNEDOFFSET(A, B, C) \
1082 case A##_unsigned: \
1083 mnemonic = B; \
1084 form = C ", ['Xns'ILU]"; \
1085 break;
1086 LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
1087 #undef LS_UNSIGNEDOFFSET
1088 case PRFM_unsigned:
1089 mnemonic = "prfm";
1090 form = "'prefOp, ['Xns'ILU]";
1091 }
1092 Format(instr, mnemonic, form);
1093 }
1094
1095
VisitLoadStoreRCpcUnscaledOffset(const Instruction * instr)1096 void Disassembler::VisitLoadStoreRCpcUnscaledOffset(const Instruction *instr) {
1097 const char *mnemonic;
1098 const char *form = "'Wt, ['Xns'ILS]";
1099 const char *form_x = "'Xt, ['Xns'ILS]";
1100
1101 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
1102 case STLURB:
1103 mnemonic = "stlurb";
1104 break;
1105 case LDAPURB:
1106 mnemonic = "ldapurb";
1107 break;
1108 case LDAPURSB_w:
1109 mnemonic = "ldapursb";
1110 break;
1111 case LDAPURSB_x:
1112 mnemonic = "ldapursb";
1113 form = form_x;
1114 break;
1115 case STLURH:
1116 mnemonic = "stlurh";
1117 break;
1118 case LDAPURH:
1119 mnemonic = "ldapurh";
1120 break;
1121 case LDAPURSH_w:
1122 mnemonic = "ldapursh";
1123 break;
1124 case LDAPURSH_x:
1125 mnemonic = "ldapursh";
1126 form = form_x;
1127 break;
1128 case STLUR_w:
1129 mnemonic = "stlur";
1130 break;
1131 case LDAPUR_w:
1132 mnemonic = "ldapur";
1133 break;
1134 case LDAPURSW:
1135 mnemonic = "ldapursw";
1136 form = form_x;
1137 break;
1138 case STLUR_x:
1139 mnemonic = "stlur";
1140 form = form_x;
1141 break;
1142 case LDAPUR_x:
1143 mnemonic = "ldapur";
1144 form = form_x;
1145 break;
1146 default:
1147 mnemonic = "unimplemented";
1148 form = "(LoadStoreRCpcUnscaledOffset)";
1149 }
1150
1151 Format(instr, mnemonic, form);
1152 }
1153
1154
VisitLoadStoreRegisterOffset(const Instruction * instr)1155 void Disassembler::VisitLoadStoreRegisterOffset(const Instruction *instr) {
1156 const char *mnemonic = "unimplemented";
1157 const char *form = "(LoadStoreRegisterOffset)";
1158
1159 switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
1160 #define LS_REGISTEROFFSET(A, B, C) \
1161 case A##_reg: \
1162 mnemonic = B; \
1163 form = C ", ['Xns, 'Offsetreg]"; \
1164 break;
1165 LOAD_STORE_LIST(LS_REGISTEROFFSET)
1166 #undef LS_REGISTEROFFSET
1167 case PRFM_reg:
1168 mnemonic = "prfm";
1169 form = "'prefOp, ['Xns, 'Offsetreg]";
1170 }
1171 Format(instr, mnemonic, form);
1172 }
1173
1174
VisitLoadStoreUnscaledOffset(const Instruction * instr)1175 void Disassembler::VisitLoadStoreUnscaledOffset(const Instruction *instr) {
1176 const char *mnemonic = "unimplemented";
1177 const char *form = "'Wt, ['Xns'ILS]";
1178 const char *form_x = "'Xt, ['Xns'ILS]";
1179 const char *form_b = "'Bt, ['Xns'ILS]";
1180 const char *form_h = "'Ht, ['Xns'ILS]";
1181 const char *form_s = "'St, ['Xns'ILS]";
1182 const char *form_d = "'Dt, ['Xns'ILS]";
1183 const char *form_q = "'Qt, ['Xns'ILS]";
1184 const char *form_prefetch = "'prefOp, ['Xns'ILS]";
1185
1186 switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
1187 case STURB_w:
1188 mnemonic = "sturb";
1189 break;
1190 case STURH_w:
1191 mnemonic = "sturh";
1192 break;
1193 case STUR_w:
1194 mnemonic = "stur";
1195 break;
1196 case STUR_x:
1197 mnemonic = "stur";
1198 form = form_x;
1199 break;
1200 case STUR_b:
1201 mnemonic = "stur";
1202 form = form_b;
1203 break;
1204 case STUR_h:
1205 mnemonic = "stur";
1206 form = form_h;
1207 break;
1208 case STUR_s:
1209 mnemonic = "stur";
1210 form = form_s;
1211 break;
1212 case STUR_d:
1213 mnemonic = "stur";
1214 form = form_d;
1215 break;
1216 case STUR_q:
1217 mnemonic = "stur";
1218 form = form_q;
1219 break;
1220 case LDURB_w:
1221 mnemonic = "ldurb";
1222 break;
1223 case LDURH_w:
1224 mnemonic = "ldurh";
1225 break;
1226 case LDUR_w:
1227 mnemonic = "ldur";
1228 break;
1229 case LDUR_x:
1230 mnemonic = "ldur";
1231 form = form_x;
1232 break;
1233 case LDUR_b:
1234 mnemonic = "ldur";
1235 form = form_b;
1236 break;
1237 case LDUR_h:
1238 mnemonic = "ldur";
1239 form = form_h;
1240 break;
1241 case LDUR_s:
1242 mnemonic = "ldur";
1243 form = form_s;
1244 break;
1245 case LDUR_d:
1246 mnemonic = "ldur";
1247 form = form_d;
1248 break;
1249 case LDUR_q:
1250 mnemonic = "ldur";
1251 form = form_q;
1252 break;
1253 case LDURSB_x:
1254 form = form_x;
1255 VIXL_FALLTHROUGH();
1256 case LDURSB_w:
1257 mnemonic = "ldursb";
1258 break;
1259 case LDURSH_x:
1260 form = form_x;
1261 VIXL_FALLTHROUGH();
1262 case LDURSH_w:
1263 mnemonic = "ldursh";
1264 break;
1265 case LDURSW_x:
1266 mnemonic = "ldursw";
1267 form = form_x;
1268 break;
1269 case PRFUM:
1270 mnemonic = "prfum";
1271 form = form_prefetch;
1272 break;
1273 default:
1274 form = "(LoadStoreUnscaledOffset)";
1275 }
1276 Format(instr, mnemonic, form);
1277 }
1278
1279
VisitLoadLiteral(const Instruction * instr)1280 void Disassembler::VisitLoadLiteral(const Instruction *instr) {
1281 const char *mnemonic = "ldr";
1282 const char *form = "(LoadLiteral)";
1283
1284 switch (instr->Mask(LoadLiteralMask)) {
1285 case LDR_w_lit:
1286 form = "'Wt, 'ILLiteral 'LValue";
1287 break;
1288 case LDR_x_lit:
1289 form = "'Xt, 'ILLiteral 'LValue";
1290 break;
1291 case LDR_s_lit:
1292 form = "'St, 'ILLiteral 'LValue";
1293 break;
1294 case LDR_d_lit:
1295 form = "'Dt, 'ILLiteral 'LValue";
1296 break;
1297 case LDR_q_lit:
1298 form = "'Qt, 'ILLiteral 'LValue";
1299 break;
1300 case LDRSW_x_lit: {
1301 mnemonic = "ldrsw";
1302 form = "'Xt, 'ILLiteral 'LValue";
1303 break;
1304 }
1305 case PRFM_lit: {
1306 mnemonic = "prfm";
1307 form = "'prefOp, 'ILLiteral 'LValue";
1308 break;
1309 }
1310 default:
1311 mnemonic = "unimplemented";
1312 }
1313 Format(instr, mnemonic, form);
1314 }
1315
1316
1317 #define LOAD_STORE_PAIR_LIST(V) \
1318 V(STP_w, "stp", "'Wt, 'Wt2", "2") \
1319 V(LDP_w, "ldp", "'Wt, 'Wt2", "2") \
1320 V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "2") \
1321 V(STP_x, "stp", "'Xt, 'Xt2", "3") \
1322 V(LDP_x, "ldp", "'Xt, 'Xt2", "3") \
1323 V(STP_s, "stp", "'St, 'St2", "2") \
1324 V(LDP_s, "ldp", "'St, 'St2", "2") \
1325 V(STP_d, "stp", "'Dt, 'Dt2", "3") \
1326 V(LDP_d, "ldp", "'Dt, 'Dt2", "3") \
1327 V(LDP_q, "ldp", "'Qt, 'Qt2", "4") \
1328 V(STP_q, "stp", "'Qt, 'Qt2", "4")
1329
VisitLoadStorePairPostIndex(const Instruction * instr)1330 void Disassembler::VisitLoadStorePairPostIndex(const Instruction *instr) {
1331 const char *mnemonic = "unimplemented";
1332 const char *form = "(LoadStorePairPostIndex)";
1333
1334 switch (instr->Mask(LoadStorePairPostIndexMask)) {
1335 #define LSP_POSTINDEX(A, B, C, D) \
1336 case A##_post: \
1337 mnemonic = B; \
1338 form = C ", ['Xns]'ILP" D "i"; \
1339 break;
1340 LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
1341 #undef LSP_POSTINDEX
1342 }
1343 Format(instr, mnemonic, form);
1344 }
1345
1346
VisitLoadStorePairPreIndex(const Instruction * instr)1347 void Disassembler::VisitLoadStorePairPreIndex(const Instruction *instr) {
1348 const char *mnemonic = "unimplemented";
1349 const char *form = "(LoadStorePairPreIndex)";
1350
1351 switch (instr->Mask(LoadStorePairPreIndexMask)) {
1352 #define LSP_PREINDEX(A, B, C, D) \
1353 case A##_pre: \
1354 mnemonic = B; \
1355 form = C ", ['Xns'ILP" D "i]!"; \
1356 break;
1357 LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
1358 #undef LSP_PREINDEX
1359 }
1360 Format(instr, mnemonic, form);
1361 }
1362
1363
VisitLoadStorePairOffset(const Instruction * instr)1364 void Disassembler::VisitLoadStorePairOffset(const Instruction *instr) {
1365 const char *mnemonic = "unimplemented";
1366 const char *form = "(LoadStorePairOffset)";
1367
1368 switch (instr->Mask(LoadStorePairOffsetMask)) {
1369 #define LSP_OFFSET(A, B, C, D) \
1370 case A##_off: \
1371 mnemonic = B; \
1372 form = C ", ['Xns'ILP" D "]"; \
1373 break;
1374 LOAD_STORE_PAIR_LIST(LSP_OFFSET)
1375 #undef LSP_OFFSET
1376 }
1377 Format(instr, mnemonic, form);
1378 }
1379
1380
VisitLoadStorePairNonTemporal(const Instruction * instr)1381 void Disassembler::VisitLoadStorePairNonTemporal(const Instruction *instr) {
1382 const char *mnemonic = "unimplemented";
1383 const char *form;
1384
1385 switch (instr->Mask(LoadStorePairNonTemporalMask)) {
1386 case STNP_w:
1387 mnemonic = "stnp";
1388 form = "'Wt, 'Wt2, ['Xns'ILP2]";
1389 break;
1390 case LDNP_w:
1391 mnemonic = "ldnp";
1392 form = "'Wt, 'Wt2, ['Xns'ILP2]";
1393 break;
1394 case STNP_x:
1395 mnemonic = "stnp";
1396 form = "'Xt, 'Xt2, ['Xns'ILP3]";
1397 break;
1398 case LDNP_x:
1399 mnemonic = "ldnp";
1400 form = "'Xt, 'Xt2, ['Xns'ILP3]";
1401 break;
1402 case STNP_s:
1403 mnemonic = "stnp";
1404 form = "'St, 'St2, ['Xns'ILP2]";
1405 break;
1406 case LDNP_s:
1407 mnemonic = "ldnp";
1408 form = "'St, 'St2, ['Xns'ILP2]";
1409 break;
1410 case STNP_d:
1411 mnemonic = "stnp";
1412 form = "'Dt, 'Dt2, ['Xns'ILP3]";
1413 break;
1414 case LDNP_d:
1415 mnemonic = "ldnp";
1416 form = "'Dt, 'Dt2, ['Xns'ILP3]";
1417 break;
1418 case STNP_q:
1419 mnemonic = "stnp";
1420 form = "'Qt, 'Qt2, ['Xns'ILP4]";
1421 break;
1422 case LDNP_q:
1423 mnemonic = "ldnp";
1424 form = "'Qt, 'Qt2, ['Xns'ILP4]";
1425 break;
1426 default:
1427 form = "(LoadStorePairNonTemporal)";
1428 }
1429 Format(instr, mnemonic, form);
1430 }
1431
1432 // clang-format off
1433 #define LOAD_STORE_EXCLUSIVE_LIST(V) \
1434 V(STXRB_w, "stxrb", "'Ws, 'Wt") \
1435 V(STXRH_w, "stxrh", "'Ws, 'Wt") \
1436 V(STXR_w, "stxr", "'Ws, 'Wt") \
1437 V(STXR_x, "stxr", "'Ws, 'Xt") \
1438 V(LDXRB_w, "ldxrb", "'Wt") \
1439 V(LDXRH_w, "ldxrh", "'Wt") \
1440 V(LDXR_w, "ldxr", "'Wt") \
1441 V(LDXR_x, "ldxr", "'Xt") \
1442 V(STXP_w, "stxp", "'Ws, 'Wt, 'Wt2") \
1443 V(STXP_x, "stxp", "'Ws, 'Xt, 'Xt2") \
1444 V(LDXP_w, "ldxp", "'Wt, 'Wt2") \
1445 V(LDXP_x, "ldxp", "'Xt, 'Xt2") \
1446 V(STLXRB_w, "stlxrb", "'Ws, 'Wt") \
1447 V(STLXRH_w, "stlxrh", "'Ws, 'Wt") \
1448 V(STLXR_w, "stlxr", "'Ws, 'Wt") \
1449 V(STLXR_x, "stlxr", "'Ws, 'Xt") \
1450 V(LDAXRB_w, "ldaxrb", "'Wt") \
1451 V(LDAXRH_w, "ldaxrh", "'Wt") \
1452 V(LDAXR_w, "ldaxr", "'Wt") \
1453 V(LDAXR_x, "ldaxr", "'Xt") \
1454 V(STLXP_w, "stlxp", "'Ws, 'Wt, 'Wt2") \
1455 V(STLXP_x, "stlxp", "'Ws, 'Xt, 'Xt2") \
1456 V(LDAXP_w, "ldaxp", "'Wt, 'Wt2") \
1457 V(LDAXP_x, "ldaxp", "'Xt, 'Xt2") \
1458 V(STLRB_w, "stlrb", "'Wt") \
1459 V(STLRH_w, "stlrh", "'Wt") \
1460 V(STLR_w, "stlr", "'Wt") \
1461 V(STLR_x, "stlr", "'Xt") \
1462 V(LDARB_w, "ldarb", "'Wt") \
1463 V(LDARH_w, "ldarh", "'Wt") \
1464 V(LDAR_w, "ldar", "'Wt") \
1465 V(LDAR_x, "ldar", "'Xt") \
1466 V(STLLRB, "stllrb", "'Wt") \
1467 V(STLLRH, "stllrh", "'Wt") \
1468 V(STLLR_w, "stllr", "'Wt") \
1469 V(STLLR_x, "stllr", "'Xt") \
1470 V(LDLARB, "ldlarb", "'Wt") \
1471 V(LDLARH, "ldlarh", "'Wt") \
1472 V(LDLAR_w, "ldlar", "'Wt") \
1473 V(LDLAR_x, "ldlar", "'Xt") \
1474 V(CAS_w, "cas", "'Ws, 'Wt") \
1475 V(CAS_x, "cas", "'Xs, 'Xt") \
1476 V(CASA_w, "casa", "'Ws, 'Wt") \
1477 V(CASA_x, "casa", "'Xs, 'Xt") \
1478 V(CASL_w, "casl", "'Ws, 'Wt") \
1479 V(CASL_x, "casl", "'Xs, 'Xt") \
1480 V(CASAL_w, "casal", "'Ws, 'Wt") \
1481 V(CASAL_x, "casal", "'Xs, 'Xt") \
1482 V(CASB, "casb", "'Ws, 'Wt") \
1483 V(CASAB, "casab", "'Ws, 'Wt") \
1484 V(CASLB, "caslb", "'Ws, 'Wt") \
1485 V(CASALB, "casalb", "'Ws, 'Wt") \
1486 V(CASH, "cash", "'Ws, 'Wt") \
1487 V(CASAH, "casah", "'Ws, 'Wt") \
1488 V(CASLH, "caslh", "'Ws, 'Wt") \
1489 V(CASALH, "casalh", "'Ws, 'Wt") \
1490 V(CASP_w, "casp", "'Ws, 'Ws+, 'Wt, 'Wt+") \
1491 V(CASP_x, "casp", "'Xs, 'Xs+, 'Xt, 'Xt+") \
1492 V(CASPA_w, "caspa", "'Ws, 'Ws+, 'Wt, 'Wt+") \
1493 V(CASPA_x, "caspa", "'Xs, 'Xs+, 'Xt, 'Xt+") \
1494 V(CASPL_w, "caspl", "'Ws, 'Ws+, 'Wt, 'Wt+") \
1495 V(CASPL_x, "caspl", "'Xs, 'Xs+, 'Xt, 'Xt+") \
1496 V(CASPAL_w, "caspal", "'Ws, 'Ws+, 'Wt, 'Wt+") \
1497 V(CASPAL_x, "caspal", "'Xs, 'Xs+, 'Xt, 'Xt+")
1498 // clang-format on
1499
1500
VisitLoadStoreExclusive(const Instruction * instr)1501 void Disassembler::VisitLoadStoreExclusive(const Instruction *instr) {
1502 const char *mnemonic = "unimplemented";
1503 const char *form;
1504
1505 switch (instr->Mask(LoadStoreExclusiveMask)) {
1506 #define LSX(A, B, C) \
1507 case A: \
1508 mnemonic = B; \
1509 form = C ", ['Xns]"; \
1510 break;
1511 LOAD_STORE_EXCLUSIVE_LIST(LSX)
1512 #undef LSX
1513 default:
1514 form = "(LoadStoreExclusive)";
1515 }
1516
1517 switch (instr->Mask(LoadStoreExclusiveMask)) {
1518 case CASP_w:
1519 case CASP_x:
1520 case CASPA_w:
1521 case CASPA_x:
1522 case CASPL_w:
1523 case CASPL_x:
1524 case CASPAL_w:
1525 case CASPAL_x:
1526 if ((instr->GetRs() % 2 == 1) || (instr->GetRt() % 2 == 1)) {
1527 mnemonic = "unallocated";
1528 form = "(LoadStoreExclusive)";
1529 }
1530 break;
1531 }
1532
1533 Format(instr, mnemonic, form);
1534 }
1535
VisitLoadStorePAC(const Instruction * instr)1536 void Disassembler::VisitLoadStorePAC(const Instruction *instr) {
1537 const char *mnemonic = "unimplemented";
1538 const char *form = "(LoadStorePAC)";
1539
1540 switch (instr->Mask(LoadStorePACMask)) {
1541 case LDRAA:
1542 mnemonic = "ldraa";
1543 form = "'Xt, ['Xns'ILA]";
1544 break;
1545 case LDRAB:
1546 mnemonic = "ldrab";
1547 form = "'Xt, ['Xns'ILA]";
1548 break;
1549 case LDRAA_pre:
1550 mnemonic = "ldraa";
1551 form = "'Xt, ['Xns'ILA]!";
1552 break;
1553 case LDRAB_pre:
1554 mnemonic = "ldrab";
1555 form = "'Xt, ['Xns'ILA]!";
1556 break;
1557 }
1558
1559 Format(instr, mnemonic, form);
1560 }
1561
1562 #define ATOMIC_MEMORY_SIMPLE_LIST(V) \
1563 V(LDADD, "add") \
1564 V(LDCLR, "clr") \
1565 V(LDEOR, "eor") \
1566 V(LDSET, "set") \
1567 V(LDSMAX, "smax") \
1568 V(LDSMIN, "smin") \
1569 V(LDUMAX, "umax") \
1570 V(LDUMIN, "umin")
1571
VisitAtomicMemory(const Instruction * instr)1572 void Disassembler::VisitAtomicMemory(const Instruction *instr) {
1573 const int kMaxAtomicOpMnemonicLength = 16;
1574 const char *mnemonic;
1575 const char *form = "'Ws, 'Wt, ['Xns]";
1576
1577 switch (instr->Mask(AtomicMemoryMask)) {
1578 #define AMS(A, MN) \
1579 case A##B: \
1580 mnemonic = MN "b"; \
1581 break; \
1582 case A##AB: \
1583 mnemonic = MN "ab"; \
1584 break; \
1585 case A##LB: \
1586 mnemonic = MN "lb"; \
1587 break; \
1588 case A##ALB: \
1589 mnemonic = MN "alb"; \
1590 break; \
1591 case A##H: \
1592 mnemonic = MN "h"; \
1593 break; \
1594 case A##AH: \
1595 mnemonic = MN "ah"; \
1596 break; \
1597 case A##LH: \
1598 mnemonic = MN "lh"; \
1599 break; \
1600 case A##ALH: \
1601 mnemonic = MN "alh"; \
1602 break; \
1603 case A##_w: \
1604 mnemonic = MN; \
1605 break; \
1606 case A##A_w: \
1607 mnemonic = MN "a"; \
1608 break; \
1609 case A##L_w: \
1610 mnemonic = MN "l"; \
1611 break; \
1612 case A##AL_w: \
1613 mnemonic = MN "al"; \
1614 break; \
1615 case A##_x: \
1616 mnemonic = MN; \
1617 form = "'Xs, 'Xt, ['Xns]"; \
1618 break; \
1619 case A##A_x: \
1620 mnemonic = MN "a"; \
1621 form = "'Xs, 'Xt, ['Xns]"; \
1622 break; \
1623 case A##L_x: \
1624 mnemonic = MN "l"; \
1625 form = "'Xs, 'Xt, ['Xns]"; \
1626 break; \
1627 case A##AL_x: \
1628 mnemonic = MN "al"; \
1629 form = "'Xs, 'Xt, ['Xns]"; \
1630 break;
1631 ATOMIC_MEMORY_SIMPLE_LIST(AMS)
1632
1633 // SWP has the same semantics as ldadd etc but without the store aliases.
1634 AMS(SWP, "swp")
1635 #undef AMS
1636
1637 case LDAPRB:
1638 mnemonic = "ldaprb";
1639 form = "'Wt, ['Xns]";
1640 break;
1641 case LDAPRH:
1642 mnemonic = "ldaprh";
1643 form = "'Wt, ['Xns]";
1644 break;
1645 case LDAPR_w:
1646 mnemonic = "ldapr";
1647 form = "'Wt, ['Xns]";
1648 break;
1649 case LDAPR_x:
1650 mnemonic = "ldapr";
1651 form = "'Xt, ['Xns]";
1652 break;
1653 default:
1654 mnemonic = "unimplemented";
1655 form = "(AtomicMemory)";
1656 }
1657
1658 const char *prefix = "";
1659 switch (instr->Mask(AtomicMemoryMask)) {
1660 #define AMS(A, MN) \
1661 case A##AB: \
1662 case A##ALB: \
1663 case A##AH: \
1664 case A##ALH: \
1665 case A##A_w: \
1666 case A##AL_w: \
1667 case A##A_x: \
1668 case A##AL_x: \
1669 prefix = "ld"; \
1670 break; \
1671 case A##B: \
1672 case A##LB: \
1673 case A##H: \
1674 case A##LH: \
1675 case A##_w: \
1676 case A##L_w: { \
1677 prefix = "ld"; \
1678 unsigned rt = instr->GetRt(); \
1679 if (Register(rt, 32).IsZero()) { \
1680 prefix = "st"; \
1681 form = "'Ws, ['Xns]"; \
1682 } \
1683 break; \
1684 } \
1685 case A##_x: \
1686 case A##L_x: { \
1687 prefix = "ld"; \
1688 unsigned rt = instr->GetRt(); \
1689 if (Register(rt, 64).IsZero()) { \
1690 prefix = "st"; \
1691 form = "'Xs, ['Xns]"; \
1692 } \
1693 break; \
1694 }
1695 ATOMIC_MEMORY_SIMPLE_LIST(AMS)
1696 #undef AMS
1697 }
1698
1699 char buffer[kMaxAtomicOpMnemonicLength];
1700 if (strlen(prefix) > 0) {
1701 snprintf(buffer, kMaxAtomicOpMnemonicLength, "%s%s", prefix, mnemonic);
1702 mnemonic = buffer;
1703 }
1704
1705 Format(instr, mnemonic, form);
1706 }
1707
1708
VisitFPCompare(const Instruction * instr)1709 void Disassembler::VisitFPCompare(const Instruction *instr) {
1710 const char *mnemonic = "unimplemented";
1711 const char *form = "'Fn, 'Fm";
1712 const char *form_zero = "'Fn, #0.0";
1713
1714 switch (instr->Mask(FPCompareMask)) {
1715 case FCMP_h_zero:
1716 case FCMP_s_zero:
1717 case FCMP_d_zero:
1718 form = form_zero;
1719 VIXL_FALLTHROUGH();
1720 case FCMP_h:
1721 case FCMP_s:
1722 case FCMP_d:
1723 mnemonic = "fcmp";
1724 break;
1725 case FCMPE_h_zero:
1726 case FCMPE_s_zero:
1727 case FCMPE_d_zero:
1728 form = form_zero;
1729 VIXL_FALLTHROUGH();
1730 case FCMPE_h:
1731 case FCMPE_s:
1732 case FCMPE_d:
1733 mnemonic = "fcmpe";
1734 break;
1735 default:
1736 form = "(FPCompare)";
1737 }
1738 Format(instr, mnemonic, form);
1739 }
1740
1741
VisitFPConditionalCompare(const Instruction * instr)1742 void Disassembler::VisitFPConditionalCompare(const Instruction *instr) {
1743 const char *mnemonic = "unmplemented";
1744 const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
1745
1746 switch (instr->Mask(FPConditionalCompareMask)) {
1747 case FCCMP_h:
1748 case FCCMP_s:
1749 case FCCMP_d:
1750 mnemonic = "fccmp";
1751 break;
1752 case FCCMPE_h:
1753 case FCCMPE_s:
1754 case FCCMPE_d:
1755 mnemonic = "fccmpe";
1756 break;
1757 default:
1758 form = "(FPConditionalCompare)";
1759 }
1760 Format(instr, mnemonic, form);
1761 }
1762
1763
VisitFPConditionalSelect(const Instruction * instr)1764 void Disassembler::VisitFPConditionalSelect(const Instruction *instr) {
1765 const char *mnemonic = "";
1766 const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
1767
1768 switch (instr->Mask(FPConditionalSelectMask)) {
1769 case FCSEL_h:
1770 case FCSEL_s:
1771 case FCSEL_d:
1772 mnemonic = "fcsel";
1773 break;
1774 default:
1775 VIXL_UNREACHABLE();
1776 }
1777 Format(instr, mnemonic, form);
1778 }
1779
1780
VisitFPDataProcessing1Source(const Instruction * instr)1781 void Disassembler::VisitFPDataProcessing1Source(const Instruction *instr) {
1782 const char *mnemonic = "unimplemented";
1783 const char *form = "'Fd, 'Fn";
1784
1785 switch (instr->Mask(FPDataProcessing1SourceMask)) {
1786 #define FORMAT(A, B) \
1787 case A##_h: \
1788 case A##_s: \
1789 case A##_d: \
1790 mnemonic = B; \
1791 break;
1792 FORMAT(FMOV, "fmov");
1793 FORMAT(FABS, "fabs");
1794 FORMAT(FNEG, "fneg");
1795 FORMAT(FSQRT, "fsqrt");
1796 FORMAT(FRINTN, "frintn");
1797 FORMAT(FRINTP, "frintp");
1798 FORMAT(FRINTM, "frintm");
1799 FORMAT(FRINTZ, "frintz");
1800 FORMAT(FRINTA, "frinta");
1801 FORMAT(FRINTX, "frintx");
1802 FORMAT(FRINTI, "frinti");
1803 #undef FORMAT
1804 #define FORMAT(A, B) \
1805 case A##_s: \
1806 case A##_d: \
1807 mnemonic = B; \
1808 break;
1809 FORMAT(FRINT32X, "frint32x");
1810 FORMAT(FRINT32Z, "frint32z");
1811 FORMAT(FRINT64X, "frint64x");
1812 FORMAT(FRINT64Z, "frint64z");
1813 #undef FORMAT
1814 case FCVT_ds:
1815 mnemonic = "fcvt";
1816 form = "'Dd, 'Sn";
1817 break;
1818 case FCVT_sd:
1819 mnemonic = "fcvt";
1820 form = "'Sd, 'Dn";
1821 break;
1822 case FCVT_hs:
1823 mnemonic = "fcvt";
1824 form = "'Hd, 'Sn";
1825 break;
1826 case FCVT_sh:
1827 mnemonic = "fcvt";
1828 form = "'Sd, 'Hn";
1829 break;
1830 case FCVT_dh:
1831 mnemonic = "fcvt";
1832 form = "'Dd, 'Hn";
1833 break;
1834 case FCVT_hd:
1835 mnemonic = "fcvt";
1836 form = "'Hd, 'Dn";
1837 break;
1838 default:
1839 form = "(FPDataProcessing1Source)";
1840 }
1841 Format(instr, mnemonic, form);
1842 }
1843
1844
VisitFPDataProcessing2Source(const Instruction * instr)1845 void Disassembler::VisitFPDataProcessing2Source(const Instruction *instr) {
1846 const char *mnemonic = "";
1847 const char *form = "'Fd, 'Fn, 'Fm";
1848
1849 switch (instr->Mask(FPDataProcessing2SourceMask)) {
1850 #define FORMAT(A, B) \
1851 case A##_h: \
1852 case A##_s: \
1853 case A##_d: \
1854 mnemonic = B; \
1855 break;
1856 FORMAT(FADD, "fadd");
1857 FORMAT(FSUB, "fsub");
1858 FORMAT(FMUL, "fmul");
1859 FORMAT(FDIV, "fdiv");
1860 FORMAT(FMAX, "fmax");
1861 FORMAT(FMIN, "fmin");
1862 FORMAT(FMAXNM, "fmaxnm");
1863 FORMAT(FMINNM, "fminnm");
1864 FORMAT(FNMUL, "fnmul");
1865 #undef FORMAT
1866 default:
1867 VIXL_UNREACHABLE();
1868 }
1869 Format(instr, mnemonic, form);
1870 }
1871
1872
VisitFPDataProcessing3Source(const Instruction * instr)1873 void Disassembler::VisitFPDataProcessing3Source(const Instruction *instr) {
1874 const char *mnemonic = "";
1875 const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
1876
1877 switch (instr->Mask(FPDataProcessing3SourceMask)) {
1878 #define FORMAT(A, B) \
1879 case A##_h: \
1880 case A##_s: \
1881 case A##_d: \
1882 mnemonic = B; \
1883 break;
1884 FORMAT(FMADD, "fmadd");
1885 FORMAT(FMSUB, "fmsub");
1886 FORMAT(FNMADD, "fnmadd");
1887 FORMAT(FNMSUB, "fnmsub");
1888 #undef FORMAT
1889 default:
1890 VIXL_UNREACHABLE();
1891 }
1892 Format(instr, mnemonic, form);
1893 }
1894
1895
VisitFPImmediate(const Instruction * instr)1896 void Disassembler::VisitFPImmediate(const Instruction *instr) {
1897 const char *mnemonic = "";
1898 const char *form = "(FPImmediate)";
1899 switch (instr->Mask(FPImmediateMask)) {
1900 case FMOV_h_imm:
1901 mnemonic = "fmov";
1902 form = "'Hd, 'IFP";
1903 break;
1904 case FMOV_s_imm:
1905 mnemonic = "fmov";
1906 form = "'Sd, 'IFP";
1907 break;
1908 case FMOV_d_imm:
1909 mnemonic = "fmov";
1910 form = "'Dd, 'IFP";
1911 break;
1912 default:
1913 VIXL_UNREACHABLE();
1914 }
1915 Format(instr, mnemonic, form);
1916 }
1917
1918
VisitFPIntegerConvert(const Instruction * instr)1919 void Disassembler::VisitFPIntegerConvert(const Instruction *instr) {
1920 const char *mnemonic = "unimplemented";
1921 const char *form = "(FPIntegerConvert)";
1922 const char *form_rf = "'Rd, 'Fn";
1923 const char *form_fr = "'Fd, 'Rn";
1924
1925 switch (instr->Mask(FPIntegerConvertMask)) {
1926 case FMOV_wh:
1927 case FMOV_xh:
1928 case FMOV_ws:
1929 case FMOV_xd:
1930 mnemonic = "fmov";
1931 form = form_rf;
1932 break;
1933 case FMOV_hw:
1934 case FMOV_hx:
1935 case FMOV_sw:
1936 case FMOV_dx:
1937 mnemonic = "fmov";
1938 form = form_fr;
1939 break;
1940 case FMOV_d1_x:
1941 mnemonic = "fmov";
1942 form = "'Vd.D[1], 'Rn";
1943 break;
1944 case FMOV_x_d1:
1945 mnemonic = "fmov";
1946 form = "'Rd, 'Vn.D[1]";
1947 break;
1948 case FCVTAS_wh:
1949 case FCVTAS_xh:
1950 case FCVTAS_ws:
1951 case FCVTAS_xs:
1952 case FCVTAS_wd:
1953 case FCVTAS_xd:
1954 mnemonic = "fcvtas";
1955 form = form_rf;
1956 break;
1957 case FCVTAU_wh:
1958 case FCVTAU_xh:
1959 case FCVTAU_ws:
1960 case FCVTAU_xs:
1961 case FCVTAU_wd:
1962 case FCVTAU_xd:
1963 mnemonic = "fcvtau";
1964 form = form_rf;
1965 break;
1966 case FCVTMS_wh:
1967 case FCVTMS_xh:
1968 case FCVTMS_ws:
1969 case FCVTMS_xs:
1970 case FCVTMS_wd:
1971 case FCVTMS_xd:
1972 mnemonic = "fcvtms";
1973 form = form_rf;
1974 break;
1975 case FCVTMU_wh:
1976 case FCVTMU_xh:
1977 case FCVTMU_ws:
1978 case FCVTMU_xs:
1979 case FCVTMU_wd:
1980 case FCVTMU_xd:
1981 mnemonic = "fcvtmu";
1982 form = form_rf;
1983 break;
1984 case FCVTNS_wh:
1985 case FCVTNS_xh:
1986 case FCVTNS_ws:
1987 case FCVTNS_xs:
1988 case FCVTNS_wd:
1989 case FCVTNS_xd:
1990 mnemonic = "fcvtns";
1991 form = form_rf;
1992 break;
1993 case FCVTNU_wh:
1994 case FCVTNU_xh:
1995 case FCVTNU_ws:
1996 case FCVTNU_xs:
1997 case FCVTNU_wd:
1998 case FCVTNU_xd:
1999 mnemonic = "fcvtnu";
2000 form = form_rf;
2001 break;
2002 case FCVTZU_wh:
2003 case FCVTZU_xh:
2004 case FCVTZU_ws:
2005 case FCVTZU_xs:
2006 case FCVTZU_wd:
2007 case FCVTZU_xd:
2008 mnemonic = "fcvtzu";
2009 form = form_rf;
2010 break;
2011 case FCVTZS_wh:
2012 case FCVTZS_xh:
2013 case FCVTZS_ws:
2014 case FCVTZS_xs:
2015 case FCVTZS_wd:
2016 case FCVTZS_xd:
2017 mnemonic = "fcvtzs";
2018 form = form_rf;
2019 break;
2020 case FCVTPU_wh:
2021 case FCVTPU_xh:
2022 case FCVTPU_xs:
2023 case FCVTPU_wd:
2024 case FCVTPU_ws:
2025 case FCVTPU_xd:
2026 mnemonic = "fcvtpu";
2027 form = form_rf;
2028 break;
2029 case FCVTPS_wh:
2030 case FCVTPS_xh:
2031 case FCVTPS_ws:
2032 case FCVTPS_xs:
2033 case FCVTPS_wd:
2034 case FCVTPS_xd:
2035 mnemonic = "fcvtps";
2036 form = form_rf;
2037 break;
2038 case SCVTF_hw:
2039 case SCVTF_hx:
2040 case SCVTF_sw:
2041 case SCVTF_sx:
2042 case SCVTF_dw:
2043 case SCVTF_dx:
2044 mnemonic = "scvtf";
2045 form = form_fr;
2046 break;
2047 case UCVTF_hw:
2048 case UCVTF_hx:
2049 case UCVTF_sw:
2050 case UCVTF_sx:
2051 case UCVTF_dw:
2052 case UCVTF_dx:
2053 mnemonic = "ucvtf";
2054 form = form_fr;
2055 break;
2056 case FJCVTZS:
2057 mnemonic = "fjcvtzs";
2058 form = form_rf;
2059 break;
2060 }
2061 Format(instr, mnemonic, form);
2062 }
2063
2064
VisitFPFixedPointConvert(const Instruction * instr)2065 void Disassembler::VisitFPFixedPointConvert(const Instruction *instr) {
2066 const char *mnemonic = "";
2067 const char *form = "'Rd, 'Fn, 'IFPFBits";
2068 const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
2069
2070 switch (instr->Mask(FPFixedPointConvertMask)) {
2071 case FCVTZS_wh_fixed:
2072 case FCVTZS_xh_fixed:
2073 case FCVTZS_ws_fixed:
2074 case FCVTZS_xs_fixed:
2075 case FCVTZS_wd_fixed:
2076 case FCVTZS_xd_fixed:
2077 mnemonic = "fcvtzs";
2078 break;
2079 case FCVTZU_wh_fixed:
2080 case FCVTZU_xh_fixed:
2081 case FCVTZU_ws_fixed:
2082 case FCVTZU_xs_fixed:
2083 case FCVTZU_wd_fixed:
2084 case FCVTZU_xd_fixed:
2085 mnemonic = "fcvtzu";
2086 break;
2087 case SCVTF_hw_fixed:
2088 case SCVTF_hx_fixed:
2089 case SCVTF_sw_fixed:
2090 case SCVTF_sx_fixed:
2091 case SCVTF_dw_fixed:
2092 case SCVTF_dx_fixed:
2093 mnemonic = "scvtf";
2094 form = form_fr;
2095 break;
2096 case UCVTF_hw_fixed:
2097 case UCVTF_hx_fixed:
2098 case UCVTF_sw_fixed:
2099 case UCVTF_sx_fixed:
2100 case UCVTF_dw_fixed:
2101 case UCVTF_dx_fixed:
2102 mnemonic = "ucvtf";
2103 form = form_fr;
2104 break;
2105 default:
2106 VIXL_UNREACHABLE();
2107 }
2108 Format(instr, mnemonic, form);
2109 }
2110
2111 // clang-format off
2112 #define PAUTH_SYSTEM_MNEMONICS(V) \
2113 V(PACIA1716, "pacia1716") \
2114 V(PACIB1716, "pacib1716") \
2115 V(AUTIA1716, "autia1716") \
2116 V(AUTIB1716, "autib1716") \
2117 V(PACIAZ, "paciaz") \
2118 V(PACIASP, "paciasp") \
2119 V(PACIBZ, "pacibz") \
2120 V(PACIBSP, "pacibsp") \
2121 V(AUTIAZ, "autiaz") \
2122 V(AUTIASP, "autiasp") \
2123 V(AUTIBZ, "autibz") \
2124 V(AUTIBSP, "autibsp")
2125 // clang-format on
2126
VisitSystem(const Instruction * instr)2127 void Disassembler::VisitSystem(const Instruction *instr) {
2128 // Some system instructions hijack their Op and Cp fields to represent a
2129 // range of immediates instead of indicating a different instruction. This
2130 // makes the decoding tricky.
2131 const char *mnemonic = "unimplemented";
2132 const char *form = "(System)";
2133 if (instr->GetInstructionBits() == XPACLRI) {
2134 mnemonic = "xpaclri";
2135 form = NULL;
2136 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
2137 switch (instr->Mask(SystemPStateMask)) {
2138 case CFINV:
2139 mnemonic = "cfinv";
2140 form = NULL;
2141 break;
2142 case AXFLAG:
2143 mnemonic = "axflag";
2144 form = NULL;
2145 break;
2146 case XAFLAG:
2147 mnemonic = "xaflag";
2148 form = NULL;
2149 break;
2150 }
2151 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
2152 switch (instr->Mask(SystemPAuthMask)) {
2153 #define PAUTH_CASE(NAME, MN) \
2154 case NAME: \
2155 mnemonic = MN; \
2156 form = NULL; \
2157 break;
2158
2159 PAUTH_SYSTEM_MNEMONICS(PAUTH_CASE)
2160 #undef PAUTH_CASE
2161 }
2162 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
2163 SystemExclusiveMonitorFixed) {
2164 switch (instr->Mask(SystemExclusiveMonitorMask)) {
2165 case CLREX: {
2166 mnemonic = "clrex";
2167 form = (instr->GetCRm() == 0xf) ? NULL : "'IX";
2168 break;
2169 }
2170 }
2171 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2172 switch (instr->Mask(SystemSysRegMask)) {
2173 case MRS: {
2174 mnemonic = "mrs";
2175 form = "'Xt, 'IY";
2176 break;
2177 }
2178 case MSR: {
2179 mnemonic = "msr";
2180 form = "'IY, 'Xt";
2181 break;
2182 }
2183 }
2184 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
2185 form = NULL;
2186 switch (instr->GetImmHint()) {
2187 case NOP:
2188 mnemonic = "nop";
2189 break;
2190 case YIELD:
2191 mnemonic = "yield";
2192 break;
2193 case WFE:
2194 mnemonic = "wfe";
2195 break;
2196 case WFI:
2197 mnemonic = "wfi";
2198 break;
2199 case SEV:
2200 mnemonic = "sev";
2201 break;
2202 case SEVL:
2203 mnemonic = "sevl";
2204 break;
2205 case ESB:
2206 mnemonic = "esb";
2207 break;
2208 case CSDB:
2209 mnemonic = "csdb";
2210 break;
2211 case BTI:
2212 mnemonic = "bti";
2213 break;
2214 case BTI_c:
2215 mnemonic = "bti c";
2216 break;
2217 case BTI_j:
2218 mnemonic = "bti j";
2219 break;
2220 case BTI_jc:
2221 mnemonic = "bti jc";
2222 break;
2223 default:
2224 // Fall back to 'hint #<imm7>'.
2225 form = "'IH";
2226 mnemonic = "hint";
2227 break;
2228 }
2229 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
2230 switch (instr->Mask(MemBarrierMask)) {
2231 case DMB: {
2232 mnemonic = "dmb";
2233 form = "'M";
2234 break;
2235 }
2236 case DSB: {
2237 mnemonic = "dsb";
2238 form = "'M";
2239 break;
2240 }
2241 case ISB: {
2242 mnemonic = "isb";
2243 form = NULL;
2244 break;
2245 }
2246 }
2247 } else if (instr->Mask(SystemSysFMask) == SystemSysFixed) {
2248 switch (instr->GetSysOp()) {
2249 case IVAU:
2250 mnemonic = "ic";
2251 form = "ivau, 'Xt";
2252 break;
2253 case CVAC:
2254 mnemonic = "dc";
2255 form = "cvac, 'Xt";
2256 break;
2257 case CVAU:
2258 mnemonic = "dc";
2259 form = "cvau, 'Xt";
2260 break;
2261 case CVAP:
2262 mnemonic = "dc";
2263 form = "cvap, 'Xt";
2264 break;
2265 case CVADP:
2266 mnemonic = "dc";
2267 form = "cvadp, 'Xt";
2268 break;
2269 case CIVAC:
2270 mnemonic = "dc";
2271 form = "civac, 'Xt";
2272 break;
2273 case ZVA:
2274 mnemonic = "dc";
2275 form = "zva, 'Xt";
2276 break;
2277 default:
2278 mnemonic = "sys";
2279 if (instr->GetRt() == 31) {
2280 form = "'G1, 'Kn, 'Km, 'G2";
2281 } else {
2282 form = "'G1, 'Kn, 'Km, 'G2, 'Xt";
2283 }
2284 break;
2285 }
2286 }
2287 Format(instr, mnemonic, form);
2288 }
2289
2290
VisitException(const Instruction * instr)2291 void Disassembler::VisitException(const Instruction *instr) {
2292 const char *mnemonic = "unimplemented";
2293 const char *form = "'IDebug";
2294
2295 switch (instr->Mask(ExceptionMask)) {
2296 case HLT:
2297 mnemonic = "hlt";
2298 break;
2299 case BRK:
2300 mnemonic = "brk";
2301 break;
2302 case SVC:
2303 mnemonic = "svc";
2304 break;
2305 case HVC:
2306 mnemonic = "hvc";
2307 break;
2308 case SMC:
2309 mnemonic = "smc";
2310 break;
2311 case DCPS1:
2312 mnemonic = "dcps1";
2313 form = "{'IDebug}";
2314 break;
2315 case DCPS2:
2316 mnemonic = "dcps2";
2317 form = "{'IDebug}";
2318 break;
2319 case DCPS3:
2320 mnemonic = "dcps3";
2321 form = "{'IDebug}";
2322 break;
2323 default:
2324 form = "(Exception)";
2325 }
2326 Format(instr, mnemonic, form);
2327 }
2328
2329
VisitCrypto2RegSHA(const Instruction * instr)2330 void Disassembler::VisitCrypto2RegSHA(const Instruction *instr) {
2331 VisitUnimplemented(instr);
2332 }
2333
2334
VisitCrypto3RegSHA(const Instruction * instr)2335 void Disassembler::VisitCrypto3RegSHA(const Instruction *instr) {
2336 VisitUnimplemented(instr);
2337 }
2338
2339
VisitCryptoAES(const Instruction * instr)2340 void Disassembler::VisitCryptoAES(const Instruction *instr) {
2341 VisitUnimplemented(instr);
2342 }
2343
2344
VisitNEON2RegMisc(const Instruction * instr)2345 void Disassembler::VisitNEON2RegMisc(const Instruction *instr) {
2346 const char *mnemonic = "unimplemented";
2347 const char *form = "'Vd.%s, 'Vn.%s";
2348 const char *form_cmp_zero = "'Vd.%s, 'Vn.%s, #0";
2349 const char *form_fcmp_zero = "'Vd.%s, 'Vn.%s, #0.0";
2350 NEONFormatDecoder nfd(instr);
2351
2352 static const NEONFormatMap map_lp_ta =
2353 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
2354
2355 static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}};
2356
2357 static const NEONFormatMap map_cvt_tb = {{22, 30},
2358 {NF_4H, NF_8H, NF_2S, NF_4S}};
2359
2360 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
2361 // These instructions all use a two bit size field, except NOT and RBIT,
2362 // which use the field to encode the operation.
2363 switch (instr->Mask(NEON2RegMiscMask)) {
2364 case NEON_REV64:
2365 mnemonic = "rev64";
2366 break;
2367 case NEON_REV32:
2368 mnemonic = "rev32";
2369 break;
2370 case NEON_REV16:
2371 mnemonic = "rev16";
2372 break;
2373 case NEON_SADDLP:
2374 mnemonic = "saddlp";
2375 nfd.SetFormatMap(0, &map_lp_ta);
2376 break;
2377 case NEON_UADDLP:
2378 mnemonic = "uaddlp";
2379 nfd.SetFormatMap(0, &map_lp_ta);
2380 break;
2381 case NEON_SUQADD:
2382 mnemonic = "suqadd";
2383 break;
2384 case NEON_USQADD:
2385 mnemonic = "usqadd";
2386 break;
2387 case NEON_CLS:
2388 mnemonic = "cls";
2389 break;
2390 case NEON_CLZ:
2391 mnemonic = "clz";
2392 break;
2393 case NEON_CNT:
2394 mnemonic = "cnt";
2395 break;
2396 case NEON_SADALP:
2397 mnemonic = "sadalp";
2398 nfd.SetFormatMap(0, &map_lp_ta);
2399 break;
2400 case NEON_UADALP:
2401 mnemonic = "uadalp";
2402 nfd.SetFormatMap(0, &map_lp_ta);
2403 break;
2404 case NEON_SQABS:
2405 mnemonic = "sqabs";
2406 break;
2407 case NEON_SQNEG:
2408 mnemonic = "sqneg";
2409 break;
2410 case NEON_CMGT_zero:
2411 mnemonic = "cmgt";
2412 form = form_cmp_zero;
2413 break;
2414 case NEON_CMGE_zero:
2415 mnemonic = "cmge";
2416 form = form_cmp_zero;
2417 break;
2418 case NEON_CMEQ_zero:
2419 mnemonic = "cmeq";
2420 form = form_cmp_zero;
2421 break;
2422 case NEON_CMLE_zero:
2423 mnemonic = "cmle";
2424 form = form_cmp_zero;
2425 break;
2426 case NEON_CMLT_zero:
2427 mnemonic = "cmlt";
2428 form = form_cmp_zero;
2429 break;
2430 case NEON_ABS:
2431 mnemonic = "abs";
2432 break;
2433 case NEON_NEG:
2434 mnemonic = "neg";
2435 break;
2436 case NEON_RBIT_NOT:
2437 switch (instr->GetFPType()) {
2438 case 0:
2439 mnemonic = "mvn";
2440 break;
2441 case 1:
2442 mnemonic = "rbit";
2443 break;
2444 default:
2445 form = "(NEON2RegMisc)";
2446 }
2447 nfd.SetFormatMaps(nfd.LogicalFormatMap());
2448 break;
2449 }
2450 } else {
2451 // These instructions all use a one bit size field, except XTN, SQXTUN,
2452 // SHLL, SQXTN and UQXTN, which use a two bit size field.
2453 nfd.SetFormatMaps(nfd.FPFormatMap());
2454 switch (instr->Mask(NEON2RegMiscFPMask)) {
2455 case NEON_FABS:
2456 mnemonic = "fabs";
2457 break;
2458 case NEON_FNEG:
2459 mnemonic = "fneg";
2460 break;
2461 case NEON_FCVTN:
2462 mnemonic = instr->Mask(NEON_Q) ? "fcvtn2" : "fcvtn";
2463 nfd.SetFormatMap(0, &map_cvt_tb);
2464 nfd.SetFormatMap(1, &map_cvt_ta);
2465 break;
2466 case NEON_FCVTXN:
2467 mnemonic = instr->Mask(NEON_Q) ? "fcvtxn2" : "fcvtxn";
2468 nfd.SetFormatMap(0, &map_cvt_tb);
2469 nfd.SetFormatMap(1, &map_cvt_ta);
2470 break;
2471 case NEON_FCVTL:
2472 mnemonic = instr->Mask(NEON_Q) ? "fcvtl2" : "fcvtl";
2473 nfd.SetFormatMap(0, &map_cvt_ta);
2474 nfd.SetFormatMap(1, &map_cvt_tb);
2475 break;
2476 case NEON_FRINT32X:
2477 mnemonic = "frint32x";
2478 break;
2479 case NEON_FRINT32Z:
2480 mnemonic = "frint32z";
2481 break;
2482 case NEON_FRINT64X:
2483 mnemonic = "frint64x";
2484 break;
2485 case NEON_FRINT64Z:
2486 mnemonic = "frint64z";
2487 break;
2488 case NEON_FRINTN:
2489 mnemonic = "frintn";
2490 break;
2491 case NEON_FRINTA:
2492 mnemonic = "frinta";
2493 break;
2494 case NEON_FRINTP:
2495 mnemonic = "frintp";
2496 break;
2497 case NEON_FRINTM:
2498 mnemonic = "frintm";
2499 break;
2500 case NEON_FRINTX:
2501 mnemonic = "frintx";
2502 break;
2503 case NEON_FRINTZ:
2504 mnemonic = "frintz";
2505 break;
2506 case NEON_FRINTI:
2507 mnemonic = "frinti";
2508 break;
2509 case NEON_FCVTNS:
2510 mnemonic = "fcvtns";
2511 break;
2512 case NEON_FCVTNU:
2513 mnemonic = "fcvtnu";
2514 break;
2515 case NEON_FCVTPS:
2516 mnemonic = "fcvtps";
2517 break;
2518 case NEON_FCVTPU:
2519 mnemonic = "fcvtpu";
2520 break;
2521 case NEON_FCVTMS:
2522 mnemonic = "fcvtms";
2523 break;
2524 case NEON_FCVTMU:
2525 mnemonic = "fcvtmu";
2526 break;
2527 case NEON_FCVTZS:
2528 mnemonic = "fcvtzs";
2529 break;
2530 case NEON_FCVTZU:
2531 mnemonic = "fcvtzu";
2532 break;
2533 case NEON_FCVTAS:
2534 mnemonic = "fcvtas";
2535 break;
2536 case NEON_FCVTAU:
2537 mnemonic = "fcvtau";
2538 break;
2539 case NEON_FSQRT:
2540 mnemonic = "fsqrt";
2541 break;
2542 case NEON_SCVTF:
2543 mnemonic = "scvtf";
2544 break;
2545 case NEON_UCVTF:
2546 mnemonic = "ucvtf";
2547 break;
2548 case NEON_URSQRTE:
2549 mnemonic = "ursqrte";
2550 break;
2551 case NEON_URECPE:
2552 mnemonic = "urecpe";
2553 break;
2554 case NEON_FRSQRTE:
2555 mnemonic = "frsqrte";
2556 break;
2557 case NEON_FRECPE:
2558 mnemonic = "frecpe";
2559 break;
2560 case NEON_FCMGT_zero:
2561 mnemonic = "fcmgt";
2562 form = form_fcmp_zero;
2563 break;
2564 case NEON_FCMGE_zero:
2565 mnemonic = "fcmge";
2566 form = form_fcmp_zero;
2567 break;
2568 case NEON_FCMEQ_zero:
2569 mnemonic = "fcmeq";
2570 form = form_fcmp_zero;
2571 break;
2572 case NEON_FCMLE_zero:
2573 mnemonic = "fcmle";
2574 form = form_fcmp_zero;
2575 break;
2576 case NEON_FCMLT_zero:
2577 mnemonic = "fcmlt";
2578 form = form_fcmp_zero;
2579 break;
2580 default:
2581 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
2582 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
2583 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
2584 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
2585
2586 switch (instr->Mask(NEON2RegMiscMask)) {
2587 case NEON_XTN:
2588 mnemonic = "xtn";
2589 break;
2590 case NEON_SQXTN:
2591 mnemonic = "sqxtn";
2592 break;
2593 case NEON_UQXTN:
2594 mnemonic = "uqxtn";
2595 break;
2596 case NEON_SQXTUN:
2597 mnemonic = "sqxtun";
2598 break;
2599 case NEON_SHLL:
2600 mnemonic = "shll";
2601 nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
2602 nfd.SetFormatMap(1, nfd.IntegerFormatMap());
2603 switch (instr->GetNEONSize()) {
2604 case 0:
2605 form = "'Vd.%s, 'Vn.%s, #8";
2606 break;
2607 case 1:
2608 form = "'Vd.%s, 'Vn.%s, #16";
2609 break;
2610 case 2:
2611 form = "'Vd.%s, 'Vn.%s, #32";
2612 break;
2613 default:
2614 Format(instr, "unallocated", "(NEON2RegMisc)");
2615 return;
2616 }
2617 }
2618 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
2619 return;
2620 } else {
2621 form = "(NEON2RegMisc)";
2622 }
2623 }
2624 }
2625 Format(instr, mnemonic, nfd.Substitute(form));
2626 }
2627
VisitNEON2RegMiscFP16(const Instruction * instr)2628 void Disassembler::VisitNEON2RegMiscFP16(const Instruction *instr) {
2629 const char *mnemonic = "unimplemented";
2630 const char *form = "'Vd.%s, 'Vn.%s";
2631 const char *form_cmp = "'Vd.%s, 'Vn.%s, #0.0";
2632
2633 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
2634 NEONFormatDecoder nfd(instr, &map_half);
2635
2636 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
2637 // clang-format off
2638 #define FORMAT(A, B) \
2639 case NEON_##A##_H: \
2640 mnemonic = B; \
2641 break;
2642 FORMAT(FABS, "fabs")
2643 FORMAT(FCVTAS, "fcvtas")
2644 FORMAT(FCVTAU, "fcvtau")
2645 FORMAT(FCVTMS, "fcvtms")
2646 FORMAT(FCVTMU, "fcvtmu")
2647 FORMAT(FCVTNS, "fcvtns")
2648 FORMAT(FCVTNU, "fcvtnu")
2649 FORMAT(FCVTPS, "fcvtps")
2650 FORMAT(FCVTPU, "fcvtpu")
2651 FORMAT(FCVTZS, "fcvtzs")
2652 FORMAT(FCVTZU, "fcvtzu")
2653 FORMAT(FNEG, "fneg")
2654 FORMAT(FRECPE, "frecpe")
2655 FORMAT(FRINTA, "frinta")
2656 FORMAT(FRINTI, "frinti")
2657 FORMAT(FRINTM, "frintm")
2658 FORMAT(FRINTN, "frintn")
2659 FORMAT(FRINTP, "frintp")
2660 FORMAT(FRINTX, "frintx")
2661 FORMAT(FRINTZ, "frintz")
2662 FORMAT(FRSQRTE, "frsqrte")
2663 FORMAT(FSQRT, "fsqrt")
2664 FORMAT(SCVTF, "scvtf")
2665 FORMAT(UCVTF, "ucvtf")
2666 // clang-format on
2667 #undef FORMAT
2668
2669 case NEON_FCMEQ_H_zero:
2670 mnemonic = "fcmeq";
2671 form = form_cmp;
2672 break;
2673 case NEON_FCMGT_H_zero:
2674 mnemonic = "fcmgt";
2675 form = form_cmp;
2676 break;
2677 case NEON_FCMGE_H_zero:
2678 mnemonic = "fcmge";
2679 form = form_cmp;
2680 break;
2681 case NEON_FCMLT_H_zero:
2682 mnemonic = "fcmlt";
2683 form = form_cmp;
2684 break;
2685 case NEON_FCMLE_H_zero:
2686 mnemonic = "fcmle";
2687 form = form_cmp;
2688 break;
2689 default:
2690 form = "(NEON2RegMiscFP16)";
2691 }
2692 Format(instr, mnemonic, nfd.Substitute(form));
2693 }
2694
2695
VisitNEON3Same(const Instruction * instr)2696 void Disassembler::VisitNEON3Same(const Instruction *instr) {
2697 const char *mnemonic = "unimplemented";
2698 const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2699 NEONFormatDecoder nfd(instr);
2700
2701 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
2702 switch (instr->Mask(NEON3SameLogicalMask)) {
2703 case NEON_AND:
2704 mnemonic = "and";
2705 break;
2706 case NEON_ORR:
2707 mnemonic = "orr";
2708 if (instr->GetRm() == instr->GetRn()) {
2709 mnemonic = "mov";
2710 form = "'Vd.%s, 'Vn.%s";
2711 }
2712 break;
2713 case NEON_ORN:
2714 mnemonic = "orn";
2715 break;
2716 case NEON_EOR:
2717 mnemonic = "eor";
2718 break;
2719 case NEON_BIC:
2720 mnemonic = "bic";
2721 break;
2722 case NEON_BIF:
2723 mnemonic = "bif";
2724 break;
2725 case NEON_BIT:
2726 mnemonic = "bit";
2727 break;
2728 case NEON_BSL:
2729 mnemonic = "bsl";
2730 break;
2731 default:
2732 form = "(NEON3Same)";
2733 }
2734 nfd.SetFormatMaps(nfd.LogicalFormatMap());
2735 } else {
2736 static const char kUnknown[] = "unallocated";
2737 static const char *mnemonics[] = {"shadd",
2738 "uhadd",
2739 "shadd",
2740 "uhadd",
2741 "sqadd",
2742 "uqadd",
2743 "sqadd",
2744 "uqadd",
2745 "srhadd",
2746 "urhadd",
2747 "srhadd",
2748 "urhadd",
2749 // Handled by logical cases above.
2750 NULL,
2751 NULL,
2752 NULL,
2753 NULL,
2754 "shsub",
2755 "uhsub",
2756 "shsub",
2757 "uhsub",
2758 "sqsub",
2759 "uqsub",
2760 "sqsub",
2761 "uqsub",
2762 "cmgt",
2763 "cmhi",
2764 "cmgt",
2765 "cmhi",
2766 "cmge",
2767 "cmhs",
2768 "cmge",
2769 "cmhs",
2770 "sshl",
2771 "ushl",
2772 "sshl",
2773 "ushl",
2774 "sqshl",
2775 "uqshl",
2776 "sqshl",
2777 "uqshl",
2778 "srshl",
2779 "urshl",
2780 "srshl",
2781 "urshl",
2782 "sqrshl",
2783 "uqrshl",
2784 "sqrshl",
2785 "uqrshl",
2786 "smax",
2787 "umax",
2788 "smax",
2789 "umax",
2790 "smin",
2791 "umin",
2792 "smin",
2793 "umin",
2794 "sabd",
2795 "uabd",
2796 "sabd",
2797 "uabd",
2798 "saba",
2799 "uaba",
2800 "saba",
2801 "uaba",
2802 "add",
2803 "sub",
2804 "add",
2805 "sub",
2806 "cmtst",
2807 "cmeq",
2808 "cmtst",
2809 "cmeq",
2810 "mla",
2811 "mls",
2812 "mla",
2813 "mls",
2814 "mul",
2815 "pmul",
2816 "mul",
2817 "pmul",
2818 "smaxp",
2819 "umaxp",
2820 "smaxp",
2821 "umaxp",
2822 "sminp",
2823 "uminp",
2824 "sminp",
2825 "uminp",
2826 "sqdmulh",
2827 "sqrdmulh",
2828 "sqdmulh",
2829 "sqrdmulh",
2830 "addp",
2831 kUnknown,
2832 "addp",
2833 kUnknown,
2834 "fmaxnm",
2835 "fmaxnmp",
2836 "fminnm",
2837 "fminnmp",
2838 "fmla",
2839 kUnknown, // FMLAL2 or unallocated
2840 "fmls",
2841 kUnknown, // FMLSL2 or unallocated
2842 "fadd",
2843 "faddp",
2844 "fsub",
2845 "fabd",
2846 "fmulx",
2847 "fmul",
2848 kUnknown,
2849 kUnknown,
2850 "fcmeq",
2851 "fcmge",
2852 kUnknown,
2853 "fcmgt",
2854 kUnknown, // FMLAL or unallocated
2855 "facge",
2856 kUnknown, // FMLSL or unallocated
2857 "facgt",
2858 "fmax",
2859 "fmaxp",
2860 "fmin",
2861 "fminp",
2862 "frecps",
2863 "fdiv",
2864 "frsqrts",
2865 kUnknown};
2866
2867 // Operation is determined by the opcode bits (15-11), the top bit of
2868 // size (23) and the U bit (29).
2869 unsigned index = (instr->ExtractBits(15, 11) << 2) |
2870 (instr->ExtractBit(23) << 1) | instr->ExtractBit(29);
2871 VIXL_ASSERT(index < ArrayLength(mnemonics));
2872 mnemonic = mnemonics[index];
2873 // Assert that index is not one of the previously handled logical
2874 // instructions.
2875 VIXL_ASSERT(mnemonic != NULL);
2876
2877 if (mnemonic == kUnknown) {
2878 // Catch special cases where we need to check more bits than we have in
2879 // the table index. Anything not matched here is unallocated.
2880
2881 const char *fhm_form = (instr->Mask(NEON_Q) == 0)
2882 ? "'Vd.2s, 'Vn.2h, 'Vm.2h"
2883 : "'Vd.4s, 'Vn.4h, 'Vm.4h";
2884 switch (instr->Mask(NEON3SameFHMMask)) {
2885 case NEON_FMLAL:
2886 mnemonic = "fmlal";
2887 form = fhm_form;
2888 break;
2889 case NEON_FMLAL2:
2890 mnemonic = "fmlal2";
2891 form = fhm_form;
2892 break;
2893 case NEON_FMLSL:
2894 mnemonic = "fmlsl";
2895 form = fhm_form;
2896 break;
2897 case NEON_FMLSL2:
2898 mnemonic = "fmlsl2";
2899 form = fhm_form;
2900 break;
2901 default:
2902 VIXL_ASSERT(strcmp(mnemonic, "unallocated") == 0);
2903 form = "(NEON3Same)";
2904 break;
2905 }
2906 }
2907
2908 if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
2909 nfd.SetFormatMaps(nfd.FPFormatMap());
2910 }
2911 }
2912 Format(instr, mnemonic, nfd.Substitute(form));
2913 }
2914
VisitNEON3SameFP16(const Instruction * instr)2915 void Disassembler::VisitNEON3SameFP16(const Instruction *instr) {
2916 const char *mnemonic = "unimplemented";
2917 const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2918
2919 NEONFormatDecoder nfd(instr);
2920 nfd.SetFormatMaps(nfd.FP16FormatMap());
2921
2922 switch (instr->Mask(NEON3SameFP16Mask)) {
2923 #define FORMAT(A, B) \
2924 case NEON_##A##_H: \
2925 mnemonic = B; \
2926 break;
2927 FORMAT(FMAXNM, "fmaxnm");
2928 FORMAT(FMLA, "fmla");
2929 FORMAT(FADD, "fadd");
2930 FORMAT(FMULX, "fmulx");
2931 FORMAT(FCMEQ, "fcmeq");
2932 FORMAT(FMAX, "fmax");
2933 FORMAT(FRECPS, "frecps");
2934 FORMAT(FMINNM, "fminnm");
2935 FORMAT(FMLS, "fmls");
2936 FORMAT(FSUB, "fsub");
2937 FORMAT(FMIN, "fmin");
2938 FORMAT(FRSQRTS, "frsqrts");
2939 FORMAT(FMAXNMP, "fmaxnmp");
2940 FORMAT(FADDP, "faddp");
2941 FORMAT(FMUL, "fmul");
2942 FORMAT(FCMGE, "fcmge");
2943 FORMAT(FACGE, "facge");
2944 FORMAT(FMAXP, "fmaxp");
2945 FORMAT(FDIV, "fdiv");
2946 FORMAT(FMINNMP, "fminnmp");
2947 FORMAT(FABD, "fabd");
2948 FORMAT(FCMGT, "fcmgt");
2949 FORMAT(FACGT, "facgt");
2950 FORMAT(FMINP, "fminp");
2951 #undef FORMAT
2952 default:
2953 form = "(NEON3SameFP16)";
2954 }
2955
2956 Format(instr, mnemonic, nfd.Substitute(form));
2957 }
2958
VisitNEON3SameExtra(const Instruction * instr)2959 void Disassembler::VisitNEON3SameExtra(const Instruction *instr) {
2960 static const NEONFormatMap map_usdot = {{30}, {NF_8B, NF_16B}};
2961
2962 const char *mnemonic = "unallocated";
2963 const char *form = "(NEON3SameExtra)";
2964
2965 NEONFormatDecoder nfd(instr);
2966
2967 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
2968 mnemonic = "fcmla";
2969 form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNM";
2970 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
2971 mnemonic = "fcadd";
2972 form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNA";
2973 } else {
2974 form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2975 switch (instr->Mask(NEON3SameExtraMask)) {
2976 case NEON_SDOT:
2977 mnemonic = "sdot";
2978 nfd.SetFormatMap(1, &map_usdot);
2979 nfd.SetFormatMap(2, &map_usdot);
2980 break;
2981 case NEON_SQRDMLAH:
2982 mnemonic = "sqrdmlah";
2983 break;
2984 case NEON_UDOT:
2985 mnemonic = "udot";
2986 nfd.SetFormatMap(1, &map_usdot);
2987 nfd.SetFormatMap(2, &map_usdot);
2988 break;
2989 case NEON_SQRDMLSH:
2990 mnemonic = "sqrdmlsh";
2991 break;
2992 }
2993 }
2994
2995 Format(instr, mnemonic, nfd.Substitute(form));
2996 }
2997
2998
VisitNEON3Different(const Instruction * instr)2999 void Disassembler::VisitNEON3Different(const Instruction *instr) {
3000 const char *mnemonic = "unimplemented";
3001 const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
3002
3003 NEONFormatDecoder nfd(instr);
3004 nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
3005
3006 // Ignore the Q bit. Appending a "2" suffix is handled later.
3007 switch (instr->Mask(NEON3DifferentMask) & ~NEON_Q) {
3008 case NEON_PMULL:
3009 mnemonic = "pmull";
3010 break;
3011 case NEON_SABAL:
3012 mnemonic = "sabal";
3013 break;
3014 case NEON_SABDL:
3015 mnemonic = "sabdl";
3016 break;
3017 case NEON_SADDL:
3018 mnemonic = "saddl";
3019 break;
3020 case NEON_SMLAL:
3021 mnemonic = "smlal";
3022 break;
3023 case NEON_SMLSL:
3024 mnemonic = "smlsl";
3025 break;
3026 case NEON_SMULL:
3027 mnemonic = "smull";
3028 break;
3029 case NEON_SSUBL:
3030 mnemonic = "ssubl";
3031 break;
3032 case NEON_SQDMLAL:
3033 mnemonic = "sqdmlal";
3034 break;
3035 case NEON_SQDMLSL:
3036 mnemonic = "sqdmlsl";
3037 break;
3038 case NEON_SQDMULL:
3039 mnemonic = "sqdmull";
3040 break;
3041 case NEON_UABAL:
3042 mnemonic = "uabal";
3043 break;
3044 case NEON_UABDL:
3045 mnemonic = "uabdl";
3046 break;
3047 case NEON_UADDL:
3048 mnemonic = "uaddl";
3049 break;
3050 case NEON_UMLAL:
3051 mnemonic = "umlal";
3052 break;
3053 case NEON_UMLSL:
3054 mnemonic = "umlsl";
3055 break;
3056 case NEON_UMULL:
3057 mnemonic = "umull";
3058 break;
3059 case NEON_USUBL:
3060 mnemonic = "usubl";
3061 break;
3062 case NEON_SADDW:
3063 mnemonic = "saddw";
3064 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3065 break;
3066 case NEON_SSUBW:
3067 mnemonic = "ssubw";
3068 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3069 break;
3070 case NEON_UADDW:
3071 mnemonic = "uaddw";
3072 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3073 break;
3074 case NEON_USUBW:
3075 mnemonic = "usubw";
3076 nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3077 break;
3078 case NEON_ADDHN:
3079 mnemonic = "addhn";
3080 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3081 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3082 break;
3083 case NEON_RADDHN:
3084 mnemonic = "raddhn";
3085 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3086 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3087 break;
3088 case NEON_RSUBHN:
3089 mnemonic = "rsubhn";
3090 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3091 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3092 break;
3093 case NEON_SUBHN:
3094 mnemonic = "subhn";
3095 nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3096 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3097 break;
3098 default:
3099 form = "(NEON3Different)";
3100 }
3101 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
3102 }
3103
3104
VisitNEONAcrossLanes(const Instruction * instr)3105 void Disassembler::VisitNEONAcrossLanes(const Instruction *instr) {
3106 const char *mnemonic = "unimplemented";
3107 const char *form = "%sd, 'Vn.%s";
3108 const char *form_half = "'Hd, 'Vn.%s";
3109 bool half_op = false;
3110 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
3111
3112 NEONFormatDecoder nfd(instr,
3113 NEONFormatDecoder::ScalarFormatMap(),
3114 NEONFormatDecoder::IntegerFormatMap());
3115
3116 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
3117 half_op = true;
3118 form = form_half;
3119 nfd.SetFormatMaps(&map_half);
3120 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
3121 case NEON_FMAXV_H:
3122 mnemonic = "fmaxv";
3123 break;
3124 case NEON_FMINV_H:
3125 mnemonic = "fminv";
3126 break;
3127 case NEON_FMAXNMV_H:
3128 mnemonic = "fmaxnmv";
3129 break;
3130 case NEON_FMINNMV_H:
3131 mnemonic = "fminnmv";
3132 break;
3133 }
3134 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
3135 nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
3136 nfd.SetFormatMap(1, nfd.FPFormatMap());
3137 switch (instr->Mask(NEONAcrossLanesFPMask)) {
3138 case NEON_FMAXV:
3139 mnemonic = "fmaxv";
3140 break;
3141 case NEON_FMINV:
3142 mnemonic = "fminv";
3143 break;
3144 case NEON_FMAXNMV:
3145 mnemonic = "fmaxnmv";
3146 break;
3147 case NEON_FMINNMV:
3148 mnemonic = "fminnmv";
3149 break;
3150 default:
3151 form = "(NEONAcrossLanes)";
3152 break;
3153 }
3154 } else if (instr->Mask(NEONAcrossLanesFMask) == NEONAcrossLanesFixed) {
3155 switch (instr->Mask(NEONAcrossLanesMask)) {
3156 case NEON_ADDV:
3157 mnemonic = "addv";
3158 break;
3159 case NEON_SMAXV:
3160 mnemonic = "smaxv";
3161 break;
3162 case NEON_SMINV:
3163 mnemonic = "sminv";
3164 break;
3165 case NEON_UMAXV:
3166 mnemonic = "umaxv";
3167 break;
3168 case NEON_UMINV:
3169 mnemonic = "uminv";
3170 break;
3171 case NEON_SADDLV:
3172 mnemonic = "saddlv";
3173 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
3174 break;
3175 case NEON_UADDLV:
3176 mnemonic = "uaddlv";
3177 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
3178 break;
3179 default:
3180 form = "(NEONAcrossLanes)";
3181 break;
3182 }
3183 }
3184
3185 if (half_op) {
3186 Format(instr, mnemonic, nfd.Substitute(form));
3187 } else {
3188 Format(instr,
3189 mnemonic,
3190 nfd.Substitute(form,
3191 NEONFormatDecoder::kPlaceholder,
3192 NEONFormatDecoder::kFormat));
3193 }
3194 }
3195
3196
VisitNEONByIndexedElement(const Instruction * instr)3197 void Disassembler::VisitNEONByIndexedElement(const Instruction *instr) {
3198 const char *mnemonic = "unimplemented";
3199 bool l_instr = false;
3200 bool fp_instr = false;
3201 bool cn_instr = false;
3202 bool half_instr = false;
3203 bool fhm_instr = false; // FMLAL{2}, FMLSL{2}
3204
3205 const char *form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
3206
3207 static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}};
3208 static const NEONFormatMap map_cn =
3209 {{23, 22, 30},
3210 {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_UNDEF, NF_4S, NF_UNDEF, NF_UNDEF}};
3211 static const NEONFormatMap map_usdot = {{30}, {NF_8B, NF_16B}};
3212 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
3213
3214 NEONFormatDecoder nfd(instr,
3215 &map_ta,
3216 NEONFormatDecoder::IntegerFormatMap(),
3217 NEONFormatDecoder::ScalarFormatMap());
3218
3219 switch (instr->Mask(NEONByIndexedElementMask)) {
3220 case NEON_SMULL_byelement:
3221 mnemonic = "smull";
3222 l_instr = true;
3223 break;
3224 case NEON_UMULL_byelement:
3225 mnemonic = "umull";
3226 l_instr = true;
3227 break;
3228 case NEON_SMLAL_byelement:
3229 mnemonic = "smlal";
3230 l_instr = true;
3231 break;
3232 case NEON_UMLAL_byelement:
3233 mnemonic = "umlal";
3234 l_instr = true;
3235 break;
3236 case NEON_SMLSL_byelement:
3237 mnemonic = "smlsl";
3238 l_instr = true;
3239 break;
3240 case NEON_UMLSL_byelement:
3241 mnemonic = "umlsl";
3242 l_instr = true;
3243 break;
3244 case NEON_SQDMULL_byelement:
3245 mnemonic = "sqdmull";
3246 l_instr = true;
3247 break;
3248 case NEON_SQDMLAL_byelement:
3249 mnemonic = "sqdmlal";
3250 l_instr = true;
3251 break;
3252 case NEON_SQDMLSL_byelement:
3253 mnemonic = "sqdmlsl";
3254 l_instr = true;
3255 break;
3256 case NEON_MUL_byelement:
3257 mnemonic = "mul";
3258 break;
3259 case NEON_MLA_byelement:
3260 mnemonic = "mla";
3261 break;
3262 case NEON_MLS_byelement:
3263 mnemonic = "mls";
3264 break;
3265 case NEON_SQDMULH_byelement:
3266 mnemonic = "sqdmulh";
3267 break;
3268 case NEON_SQRDMULH_byelement:
3269 mnemonic = "sqrdmulh";
3270 break;
3271 case NEON_SDOT_byelement:
3272 mnemonic = "sdot";
3273 form = "'Vd.%s, 'Vn.%s, 'Ve.4b['IVByElemIndex]";
3274 nfd.SetFormatMap(1, &map_usdot);
3275 break;
3276 case NEON_SQRDMLAH_byelement:
3277 mnemonic = "sqrdmlah";
3278 break;
3279 case NEON_UDOT_byelement:
3280 mnemonic = "udot";
3281 form = "'Vd.%s, 'Vn.%s, 'Ve.4b['IVByElemIndex]";
3282 nfd.SetFormatMap(1, &map_usdot);
3283 break;
3284 case NEON_SQRDMLSH_byelement:
3285 mnemonic = "sqrdmlsh";
3286 break;
3287 default: {
3288 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
3289 case NEON_FMLAL_H_byelement:
3290 mnemonic = "fmlal";
3291 fhm_instr = true;
3292 break;
3293 case NEON_FMLAL2_H_byelement:
3294 mnemonic = "fmlal2";
3295 fhm_instr = true;
3296 break;
3297 case NEON_FMLSL_H_byelement:
3298 mnemonic = "fmlsl";
3299 fhm_instr = true;
3300 break;
3301 case NEON_FMLSL2_H_byelement:
3302 mnemonic = "fmlsl2";
3303 fhm_instr = true;
3304 break;
3305 default:
3306 switch (instr->Mask(NEONByIndexedElementFPMask)) {
3307 case NEON_FMUL_byelement:
3308 mnemonic = "fmul";
3309 fp_instr = true;
3310 break;
3311 case NEON_FMLA_byelement:
3312 mnemonic = "fmla";
3313 fp_instr = true;
3314 break;
3315 case NEON_FMLS_byelement:
3316 mnemonic = "fmls";
3317 fp_instr = true;
3318 break;
3319 case NEON_FMULX_byelement:
3320 mnemonic = "fmulx";
3321 fp_instr = true;
3322 break;
3323 case NEON_FMLA_H_byelement:
3324 mnemonic = "fmla";
3325 half_instr = true;
3326 break;
3327 case NEON_FMLS_H_byelement:
3328 mnemonic = "fmls";
3329 half_instr = true;
3330 break;
3331 case NEON_FMUL_H_byelement:
3332 mnemonic = "fmul";
3333 half_instr = true;
3334 break;
3335 case NEON_FMULX_H_byelement:
3336 mnemonic = "fmulx";
3337 half_instr = true;
3338 break;
3339 default:
3340 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
3341 case NEON_FCMLA_byelement:
3342 mnemonic = "fcmla";
3343 cn_instr = true;
3344 form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndexRot], 'ILFCNR";
3345 break;
3346 }
3347 }
3348 }
3349 }
3350 }
3351
3352 if (fhm_instr) {
3353 // These are oddballs. Set the format manually.
3354 form = (instr->Mask(NEON_Q) == 0)
3355 ? "'Vd.2s, 'Vn.2h, 'Ve.h['IVByElemIndexFHM]"
3356 : "'Vd.4s, 'Vn.4h, 'Ve.h['IVByElemIndexFHM]";
3357 Format(instr, mnemonic, nfd.Substitute(form));
3358 } else if (half_instr) {
3359 form = "'Vd.%s, 'Vn.%s, 'Ve.h['IVByElemIndex]";
3360 nfd.SetFormatMaps(&map_half, &map_half);
3361 Format(instr, mnemonic, nfd.Substitute(form));
3362 } else if (l_instr) {
3363 Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
3364 } else if (fp_instr) {
3365 nfd.SetFormatMap(0, nfd.FPFormatMap());
3366 Format(instr, mnemonic, nfd.Substitute(form));
3367 } else if (cn_instr) {
3368 nfd.SetFormatMap(0, &map_cn);
3369 nfd.SetFormatMap(1, &map_cn);
3370 Format(instr, mnemonic, nfd.Substitute(form));
3371 } else {
3372 nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3373 Format(instr, mnemonic, nfd.Substitute(form));
3374 }
3375 }
3376
3377
VisitNEONCopy(const Instruction * instr)3378 void Disassembler::VisitNEONCopy(const Instruction *instr) {
3379 const char *mnemonic = "unimplemented";
3380 const char *form = "(NEONCopy)";
3381
3382 NEONFormatDecoder nfd(instr,
3383 NEONFormatDecoder::TriangularFormatMap(),
3384 NEONFormatDecoder::TriangularScalarFormatMap());
3385
3386 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
3387 mnemonic = "mov";
3388 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3389 form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]";
3390 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
3391 mnemonic = "mov";
3392 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3393 if (nfd.GetVectorFormat() == kFormatD) {
3394 form = "'Vd.%s['IVInsIndex1], 'Xn";
3395 } else {
3396 form = "'Vd.%s['IVInsIndex1], 'Wn";
3397 }
3398 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
3399 if (instr->Mask(NEON_Q) || ((instr->GetImmNEON5() & 7) == 4)) {
3400 mnemonic = "mov";
3401 } else {
3402 mnemonic = "umov";
3403 }
3404 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3405 if (nfd.GetVectorFormat() == kFormatD) {
3406 form = "'Xd, 'Vn.%s['IVInsIndex1]";
3407 } else {
3408 form = "'Wd, 'Vn.%s['IVInsIndex1]";
3409 }
3410 } else if (instr->Mask(NEONCopySmovMask) == NEON_SMOV) {
3411 mnemonic = "smov";
3412 nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3413 form = "'R30d, 'Vn.%s['IVInsIndex1]";
3414 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
3415 mnemonic = "dup";
3416 form = "'Vd.%s, 'Vn.%s['IVInsIndex1]";
3417 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
3418 mnemonic = "dup";
3419 if (nfd.GetVectorFormat() == kFormat2D) {
3420 form = "'Vd.%s, 'Xn";
3421 } else {
3422 form = "'Vd.%s, 'Wn";
3423 }
3424 }
3425 Format(instr, mnemonic, nfd.Substitute(form));
3426 }
3427
3428
VisitNEONExtract(const Instruction * instr)3429 void Disassembler::VisitNEONExtract(const Instruction *instr) {
3430 const char *mnemonic = "unimplemented";
3431 const char *form = "(NEONExtract)";
3432 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
3433 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
3434 mnemonic = "ext";
3435 form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract";
3436 }
3437 Format(instr, mnemonic, nfd.Substitute(form));
3438 }
3439
3440
VisitNEONLoadStoreMultiStruct(const Instruction * instr)3441 void Disassembler::VisitNEONLoadStoreMultiStruct(const Instruction *instr) {
3442 const char *mnemonic = NULL;
3443 const char *form = NULL;
3444 const char *form_1v = "{'Vt.%1$s}, ['Xns]";
3445 const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]";
3446 const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]";
3447 const char *form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
3448 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3449
3450 switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
3451 case NEON_LD1_1v:
3452 mnemonic = "ld1";
3453 form = form_1v;
3454 break;
3455 case NEON_LD1_2v:
3456 mnemonic = "ld1";
3457 form = form_2v;
3458 break;
3459 case NEON_LD1_3v:
3460 mnemonic = "ld1";
3461 form = form_3v;
3462 break;
3463 case NEON_LD1_4v:
3464 mnemonic = "ld1";
3465 form = form_4v;
3466 break;
3467 case NEON_LD2:
3468 mnemonic = "ld2";
3469 form = form_2v;
3470 break;
3471 case NEON_LD3:
3472 mnemonic = "ld3";
3473 form = form_3v;
3474 break;
3475 case NEON_LD4:
3476 mnemonic = "ld4";
3477 form = form_4v;
3478 break;
3479 case NEON_ST1_1v:
3480 mnemonic = "st1";
3481 form = form_1v;
3482 break;
3483 case NEON_ST1_2v:
3484 mnemonic = "st1";
3485 form = form_2v;
3486 break;
3487 case NEON_ST1_3v:
3488 mnemonic = "st1";
3489 form = form_3v;
3490 break;
3491 case NEON_ST1_4v:
3492 mnemonic = "st1";
3493 form = form_4v;
3494 break;
3495 case NEON_ST2:
3496 mnemonic = "st2";
3497 form = form_2v;
3498 break;
3499 case NEON_ST3:
3500 mnemonic = "st3";
3501 form = form_3v;
3502 break;
3503 case NEON_ST4:
3504 mnemonic = "st4";
3505 form = form_4v;
3506 break;
3507 default:
3508 break;
3509 }
3510
3511 // Work out unallocated encodings.
3512 bool allocated = (mnemonic != NULL);
3513 switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
3514 case NEON_LD2:
3515 case NEON_LD3:
3516 case NEON_LD4:
3517 case NEON_ST2:
3518 case NEON_ST3:
3519 case NEON_ST4:
3520 // LD[2-4] and ST[2-4] cannot use .1d format.
3521 allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
3522 break;
3523 default:
3524 break;
3525 }
3526 if (allocated) {
3527 VIXL_ASSERT(mnemonic != NULL);
3528 VIXL_ASSERT(form != NULL);
3529 } else {
3530 mnemonic = "unallocated";
3531 form = "(NEONLoadStoreMultiStruct)";
3532 }
3533
3534 Format(instr, mnemonic, nfd.Substitute(form));
3535 }
3536
3537
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)3538 void Disassembler::VisitNEONLoadStoreMultiStructPostIndex(
3539 const Instruction *instr) {
3540 const char *mnemonic = NULL;
3541 const char *form = NULL;
3542 const char *form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1";
3543 const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2";
3544 const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3";
3545 const char *form_4v =
3546 "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4";
3547 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3548
3549 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3550 case NEON_LD1_1v_post:
3551 mnemonic = "ld1";
3552 form = form_1v;
3553 break;
3554 case NEON_LD1_2v_post:
3555 mnemonic = "ld1";
3556 form = form_2v;
3557 break;
3558 case NEON_LD1_3v_post:
3559 mnemonic = "ld1";
3560 form = form_3v;
3561 break;
3562 case NEON_LD1_4v_post:
3563 mnemonic = "ld1";
3564 form = form_4v;
3565 break;
3566 case NEON_LD2_post:
3567 mnemonic = "ld2";
3568 form = form_2v;
3569 break;
3570 case NEON_LD3_post:
3571 mnemonic = "ld3";
3572 form = form_3v;
3573 break;
3574 case NEON_LD4_post:
3575 mnemonic = "ld4";
3576 form = form_4v;
3577 break;
3578 case NEON_ST1_1v_post:
3579 mnemonic = "st1";
3580 form = form_1v;
3581 break;
3582 case NEON_ST1_2v_post:
3583 mnemonic = "st1";
3584 form = form_2v;
3585 break;
3586 case NEON_ST1_3v_post:
3587 mnemonic = "st1";
3588 form = form_3v;
3589 break;
3590 case NEON_ST1_4v_post:
3591 mnemonic = "st1";
3592 form = form_4v;
3593 break;
3594 case NEON_ST2_post:
3595 mnemonic = "st2";
3596 form = form_2v;
3597 break;
3598 case NEON_ST3_post:
3599 mnemonic = "st3";
3600 form = form_3v;
3601 break;
3602 case NEON_ST4_post:
3603 mnemonic = "st4";
3604 form = form_4v;
3605 break;
3606 default:
3607 break;
3608 }
3609
3610 // Work out unallocated encodings.
3611 bool allocated = (mnemonic != NULL);
3612 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3613 case NEON_LD2_post:
3614 case NEON_LD3_post:
3615 case NEON_LD4_post:
3616 case NEON_ST2_post:
3617 case NEON_ST3_post:
3618 case NEON_ST4_post:
3619 // LD[2-4] and ST[2-4] cannot use .1d format.
3620 allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
3621 break;
3622 default:
3623 break;
3624 }
3625 if (allocated) {
3626 VIXL_ASSERT(mnemonic != NULL);
3627 VIXL_ASSERT(form != NULL);
3628 } else {
3629 mnemonic = "unallocated";
3630 form = "(NEONLoadStoreMultiStructPostIndex)";
3631 }
3632
3633 Format(instr, mnemonic, nfd.Substitute(form));
3634 }
3635
3636
VisitNEONLoadStoreSingleStruct(const Instruction * instr)3637 void Disassembler::VisitNEONLoadStoreSingleStruct(const Instruction *instr) {
3638 const char *mnemonic = NULL;
3639 const char *form = NULL;
3640
3641 const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns]";
3642 const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns]";
3643 const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns]";
3644 const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns]";
3645 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3646
3647 switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
3648 case NEON_LD1_b:
3649 mnemonic = "ld1";
3650 form = form_1b;
3651 break;
3652 case NEON_LD1_h:
3653 mnemonic = "ld1";
3654 form = form_1h;
3655 break;
3656 case NEON_LD1_s:
3657 mnemonic = "ld1";
3658 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3659 form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3660 break;
3661 case NEON_ST1_b:
3662 mnemonic = "st1";
3663 form = form_1b;
3664 break;
3665 case NEON_ST1_h:
3666 mnemonic = "st1";
3667 form = form_1h;
3668 break;
3669 case NEON_ST1_s:
3670 mnemonic = "st1";
3671 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3672 form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3673 break;
3674 case NEON_LD1R:
3675 mnemonic = "ld1r";
3676 form = "{'Vt.%s}, ['Xns]";
3677 break;
3678 case NEON_LD2_b:
3679 case NEON_ST2_b:
3680 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3681 form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]";
3682 break;
3683 case NEON_LD2_h:
3684 case NEON_ST2_h:
3685 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3686 form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]";
3687 break;
3688 case NEON_LD2_s:
3689 case NEON_ST2_s:
3690 VIXL_STATIC_ASSERT((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d);
3691 VIXL_STATIC_ASSERT((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d);
3692 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3693 if ((instr->GetNEONLSSize() & 1) == 0) {
3694 form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]";
3695 } else {
3696 form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]";
3697 }
3698 break;
3699 case NEON_LD2R:
3700 mnemonic = "ld2r";
3701 form = "{'Vt.%s, 'Vt2.%s}, ['Xns]";
3702 break;
3703 case NEON_LD3_b:
3704 case NEON_ST3_b:
3705 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3706 form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]";
3707 break;
3708 case NEON_LD3_h:
3709 case NEON_ST3_h:
3710 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3711 form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]";
3712 break;
3713 case NEON_LD3_s:
3714 case NEON_ST3_s:
3715 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3716 if ((instr->GetNEONLSSize() & 1) == 0) {
3717 form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]";
3718 } else {
3719 form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]";
3720 }
3721 break;
3722 case NEON_LD3R:
3723 mnemonic = "ld3r";
3724 form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]";
3725 break;
3726 case NEON_LD4_b:
3727 case NEON_ST4_b:
3728 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3729 form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]";
3730 break;
3731 case NEON_LD4_h:
3732 case NEON_ST4_h:
3733 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3734 form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]";
3735 break;
3736 case NEON_LD4_s:
3737 case NEON_ST4_s:
3738 VIXL_STATIC_ASSERT((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d);
3739 VIXL_STATIC_ASSERT((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d);
3740 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3741 if ((instr->GetNEONLSSize() & 1) == 0) {
3742 form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]";
3743 } else {
3744 form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]";
3745 }
3746 break;
3747 case NEON_LD4R:
3748 mnemonic = "ld4r";
3749 form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
3750 break;
3751 default:
3752 break;
3753 }
3754
3755 // Work out unallocated encodings.
3756 bool allocated = (mnemonic != NULL);
3757 switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
3758 case NEON_LD1_h:
3759 case NEON_LD2_h:
3760 case NEON_LD3_h:
3761 case NEON_LD4_h:
3762 case NEON_ST1_h:
3763 case NEON_ST2_h:
3764 case NEON_ST3_h:
3765 case NEON_ST4_h:
3766 VIXL_ASSERT(allocated);
3767 allocated = ((instr->GetNEONLSSize() & 1) == 0);
3768 break;
3769 case NEON_LD1_s:
3770 case NEON_LD2_s:
3771 case NEON_LD3_s:
3772 case NEON_LD4_s:
3773 case NEON_ST1_s:
3774 case NEON_ST2_s:
3775 case NEON_ST3_s:
3776 case NEON_ST4_s:
3777 VIXL_ASSERT(allocated);
3778 allocated = (instr->GetNEONLSSize() <= 1) &&
3779 ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
3780 break;
3781 case NEON_LD1R:
3782 case NEON_LD2R:
3783 case NEON_LD3R:
3784 case NEON_LD4R:
3785 VIXL_ASSERT(allocated);
3786 allocated = (instr->GetNEONS() == 0);
3787 break;
3788 default:
3789 break;
3790 }
3791 if (allocated) {
3792 VIXL_ASSERT(mnemonic != NULL);
3793 VIXL_ASSERT(form != NULL);
3794 } else {
3795 mnemonic = "unallocated";
3796 form = "(NEONLoadStoreSingleStruct)";
3797 }
3798
3799 Format(instr, mnemonic, nfd.Substitute(form));
3800 }
3801
3802
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)3803 void Disassembler::VisitNEONLoadStoreSingleStructPostIndex(
3804 const Instruction *instr) {
3805 const char *mnemonic = NULL;
3806 const char *form = NULL;
3807
3808 const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1";
3809 const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2";
3810 const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4";
3811 const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8";
3812 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3813
3814 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3815 case NEON_LD1_b_post:
3816 mnemonic = "ld1";
3817 form = form_1b;
3818 break;
3819 case NEON_LD1_h_post:
3820 mnemonic = "ld1";
3821 form = form_1h;
3822 break;
3823 case NEON_LD1_s_post:
3824 mnemonic = "ld1";
3825 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3826 form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3827 break;
3828 case NEON_ST1_b_post:
3829 mnemonic = "st1";
3830 form = form_1b;
3831 break;
3832 case NEON_ST1_h_post:
3833 mnemonic = "st1";
3834 form = form_1h;
3835 break;
3836 case NEON_ST1_s_post:
3837 mnemonic = "st1";
3838 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3839 form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3840 break;
3841 case NEON_LD1R_post:
3842 mnemonic = "ld1r";
3843 form = "{'Vt.%s}, ['Xns], 'Xmz1";
3844 break;
3845 case NEON_LD2_b_post:
3846 case NEON_ST2_b_post:
3847 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3848 form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2";
3849 break;
3850 case NEON_ST2_h_post:
3851 case NEON_LD2_h_post:
3852 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3853 form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4";
3854 break;
3855 case NEON_LD2_s_post:
3856 case NEON_ST2_s_post:
3857 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3858 if ((instr->GetNEONLSSize() & 1) == 0)
3859 form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8";
3860 else
3861 form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16";
3862 break;
3863 case NEON_LD2R_post:
3864 mnemonic = "ld2r";
3865 form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2";
3866 break;
3867 case NEON_LD3_b_post:
3868 case NEON_ST3_b_post:
3869 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3870 form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3";
3871 break;
3872 case NEON_LD3_h_post:
3873 case NEON_ST3_h_post:
3874 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3875 form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6";
3876 break;
3877 case NEON_LD3_s_post:
3878 case NEON_ST3_s_post:
3879 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3880 if ((instr->GetNEONLSSize() & 1) == 0)
3881 form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12";
3882 else
3883 form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24";
3884 break;
3885 case NEON_LD3R_post:
3886 mnemonic = "ld3r";
3887 form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3";
3888 break;
3889 case NEON_LD4_b_post:
3890 case NEON_ST4_b_post:
3891 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3892 form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4";
3893 break;
3894 case NEON_LD4_h_post:
3895 case NEON_ST4_h_post:
3896 mnemonic = (instr->GetLdStXLoad()) == 1 ? "ld4" : "st4";
3897 form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8";
3898 break;
3899 case NEON_LD4_s_post:
3900 case NEON_ST4_s_post:
3901 mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3902 if ((instr->GetNEONLSSize() & 1) == 0)
3903 form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16";
3904 else
3905 form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32";
3906 break;
3907 case NEON_LD4R_post:
3908 mnemonic = "ld4r";
3909 form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4";
3910 break;
3911 default:
3912 break;
3913 }
3914
3915 // Work out unallocated encodings.
3916 bool allocated = (mnemonic != NULL);
3917 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3918 case NEON_LD1_h_post:
3919 case NEON_LD2_h_post:
3920 case NEON_LD3_h_post:
3921 case NEON_LD4_h_post:
3922 case NEON_ST1_h_post:
3923 case NEON_ST2_h_post:
3924 case NEON_ST3_h_post:
3925 case NEON_ST4_h_post:
3926 VIXL_ASSERT(allocated);
3927 allocated = ((instr->GetNEONLSSize() & 1) == 0);
3928 break;
3929 case NEON_LD1_s_post:
3930 case NEON_LD2_s_post:
3931 case NEON_LD3_s_post:
3932 case NEON_LD4_s_post:
3933 case NEON_ST1_s_post:
3934 case NEON_ST2_s_post:
3935 case NEON_ST3_s_post:
3936 case NEON_ST4_s_post:
3937 VIXL_ASSERT(allocated);
3938 allocated = (instr->GetNEONLSSize() <= 1) &&
3939 ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
3940 break;
3941 case NEON_LD1R_post:
3942 case NEON_LD2R_post:
3943 case NEON_LD3R_post:
3944 case NEON_LD4R_post:
3945 VIXL_ASSERT(allocated);
3946 allocated = (instr->GetNEONS() == 0);
3947 break;
3948 default:
3949 break;
3950 }
3951 if (allocated) {
3952 VIXL_ASSERT(mnemonic != NULL);
3953 VIXL_ASSERT(form != NULL);
3954 } else {
3955 mnemonic = "unallocated";
3956 form = "(NEONLoadStoreSingleStructPostIndex)";
3957 }
3958
3959 Format(instr, mnemonic, nfd.Substitute(form));
3960 }
3961
3962
VisitNEONModifiedImmediate(const Instruction * instr)3963 void Disassembler::VisitNEONModifiedImmediate(const Instruction *instr) {
3964 const char *mnemonic = "unimplemented";
3965 const char *form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1";
3966
3967 int half_enc = instr->ExtractBit(11);
3968 int cmode = instr->GetNEONCmode();
3969 int cmode_3 = (cmode >> 3) & 1;
3970 int cmode_2 = (cmode >> 2) & 1;
3971 int cmode_1 = (cmode >> 1) & 1;
3972 int cmode_0 = cmode & 1;
3973 int q = instr->GetNEONQ();
3974 int op = instr->GetNEONModImmOp();
3975
3976 static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
3977 static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}};
3978 static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}};
3979 NEONFormatDecoder nfd(instr, &map_b);
3980 if (cmode_3 == 0) {
3981 if (cmode_0 == 0) {
3982 mnemonic = (op == 1) ? "mvni" : "movi";
3983 } else { // cmode<0> == '1'.
3984 mnemonic = (op == 1) ? "bic" : "orr";
3985 }
3986 nfd.SetFormatMap(0, &map_s);
3987 } else { // cmode<3> == '1'.
3988 if (cmode_2 == 0) {
3989 if (cmode_0 == 0) {
3990 mnemonic = (op == 1) ? "mvni" : "movi";
3991 } else { // cmode<0> == '1'.
3992 mnemonic = (op == 1) ? "bic" : "orr";
3993 }
3994 nfd.SetFormatMap(0, &map_h);
3995 } else { // cmode<2> == '1'.
3996 if (cmode_1 == 0) {
3997 mnemonic = (op == 1) ? "mvni" : "movi";
3998 form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2";
3999 nfd.SetFormatMap(0, &map_s);
4000 } else { // cmode<1> == '1'.
4001 if (cmode_0 == 0) {
4002 mnemonic = "movi";
4003 if (op == 0) {
4004 form = "'Vt.%s, 'IVMIImm8";
4005 } else {
4006 form = (q == 0) ? "'Dd, 'IVMIImm" : "'Vt.2d, 'IVMIImm";
4007 }
4008 } else { // cmode<0> == '1'
4009 mnemonic = "fmov";
4010 form = "'Vt.%s, 'IFPNeon";
4011 if (half_enc == 1) {
4012 nfd.SetFormatMap(0, &map_h);
4013 } else if (op == 0) {
4014 nfd.SetFormatMap(0, &map_s);
4015 } else if (q == 1) {
4016 form = "'Vt.2d, 'IFPNeon";
4017 } else {
4018 mnemonic = "unallocated";
4019 form = "(NEONModifiedImmediate)";
4020 }
4021 }
4022 }
4023 }
4024 }
4025 Format(instr, mnemonic, nfd.Substitute(form));
4026 }
4027
4028
VisitNEONScalar2RegMisc(const Instruction * instr)4029 void Disassembler::VisitNEONScalar2RegMisc(const Instruction *instr) {
4030 const char *mnemonic = "unimplemented";
4031 const char *form = "%sd, %sn";
4032 const char *form_0 = "%sd, %sn, #0";
4033 const char *form_fp0 = "%sd, %sn, #0.0";
4034
4035 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4036
4037 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
4038 // These instructions all use a two bit size field, except NOT and RBIT,
4039 // which use the field to encode the operation.
4040 switch (instr->Mask(NEONScalar2RegMiscMask)) {
4041 case NEON_CMGT_zero_scalar:
4042 mnemonic = "cmgt";
4043 form = form_0;
4044 break;
4045 case NEON_CMGE_zero_scalar:
4046 mnemonic = "cmge";
4047 form = form_0;
4048 break;
4049 case NEON_CMLE_zero_scalar:
4050 mnemonic = "cmle";
4051 form = form_0;
4052 break;
4053 case NEON_CMLT_zero_scalar:
4054 mnemonic = "cmlt";
4055 form = form_0;
4056 break;
4057 case NEON_CMEQ_zero_scalar:
4058 mnemonic = "cmeq";
4059 form = form_0;
4060 break;
4061 case NEON_NEG_scalar:
4062 mnemonic = "neg";
4063 break;
4064 case NEON_SQNEG_scalar:
4065 mnemonic = "sqneg";
4066 break;
4067 case NEON_ABS_scalar:
4068 mnemonic = "abs";
4069 break;
4070 case NEON_SQABS_scalar:
4071 mnemonic = "sqabs";
4072 break;
4073 case NEON_SUQADD_scalar:
4074 mnemonic = "suqadd";
4075 break;
4076 case NEON_USQADD_scalar:
4077 mnemonic = "usqadd";
4078 break;
4079 default:
4080 form = "(NEONScalar2RegMisc)";
4081 }
4082 } else {
4083 // These instructions all use a one bit size field, except SQXTUN, SQXTN
4084 // and UQXTN, which use a two bit size field.
4085 nfd.SetFormatMaps(nfd.FPScalarFormatMap());
4086 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
4087 case NEON_FRSQRTE_scalar:
4088 mnemonic = "frsqrte";
4089 break;
4090 case NEON_FRECPE_scalar:
4091 mnemonic = "frecpe";
4092 break;
4093 case NEON_SCVTF_scalar:
4094 mnemonic = "scvtf";
4095 break;
4096 case NEON_UCVTF_scalar:
4097 mnemonic = "ucvtf";
4098 break;
4099 case NEON_FCMGT_zero_scalar:
4100 mnemonic = "fcmgt";
4101 form = form_fp0;
4102 break;
4103 case NEON_FCMGE_zero_scalar:
4104 mnemonic = "fcmge";
4105 form = form_fp0;
4106 break;
4107 case NEON_FCMLE_zero_scalar:
4108 mnemonic = "fcmle";
4109 form = form_fp0;
4110 break;
4111 case NEON_FCMLT_zero_scalar:
4112 mnemonic = "fcmlt";
4113 form = form_fp0;
4114 break;
4115 case NEON_FCMEQ_zero_scalar:
4116 mnemonic = "fcmeq";
4117 form = form_fp0;
4118 break;
4119 case NEON_FRECPX_scalar:
4120 mnemonic = "frecpx";
4121 break;
4122 case NEON_FCVTNS_scalar:
4123 mnemonic = "fcvtns";
4124 break;
4125 case NEON_FCVTNU_scalar:
4126 mnemonic = "fcvtnu";
4127 break;
4128 case NEON_FCVTPS_scalar:
4129 mnemonic = "fcvtps";
4130 break;
4131 case NEON_FCVTPU_scalar:
4132 mnemonic = "fcvtpu";
4133 break;
4134 case NEON_FCVTMS_scalar:
4135 mnemonic = "fcvtms";
4136 break;
4137 case NEON_FCVTMU_scalar:
4138 mnemonic = "fcvtmu";
4139 break;
4140 case NEON_FCVTZS_scalar:
4141 mnemonic = "fcvtzs";
4142 break;
4143 case NEON_FCVTZU_scalar:
4144 mnemonic = "fcvtzu";
4145 break;
4146 case NEON_FCVTAS_scalar:
4147 mnemonic = "fcvtas";
4148 break;
4149 case NEON_FCVTAU_scalar:
4150 mnemonic = "fcvtau";
4151 break;
4152 case NEON_FCVTXN_scalar:
4153 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
4154 mnemonic = "fcvtxn";
4155 break;
4156 default:
4157 nfd.SetFormatMap(0, nfd.ScalarFormatMap());
4158 nfd.SetFormatMap(1, nfd.LongScalarFormatMap());
4159 switch (instr->Mask(NEONScalar2RegMiscMask)) {
4160 case NEON_SQXTN_scalar:
4161 mnemonic = "sqxtn";
4162 break;
4163 case NEON_UQXTN_scalar:
4164 mnemonic = "uqxtn";
4165 break;
4166 case NEON_SQXTUN_scalar:
4167 mnemonic = "sqxtun";
4168 break;
4169 default:
4170 form = "(NEONScalar2RegMisc)";
4171 }
4172 }
4173 }
4174 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4175 }
4176
VisitNEONScalar2RegMiscFP16(const Instruction * instr)4177 void Disassembler::VisitNEONScalar2RegMiscFP16(const Instruction *instr) {
4178 const char *mnemonic = "unimplemented";
4179 const char *form = "'Hd, 'Hn";
4180 const char *form_fp0 = "'Hd, 'Hn, #0.0";
4181
4182 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
4183 #define FORMAT(A, B) \
4184 case NEON_##A##_H_scalar: \
4185 mnemonic = B; \
4186 break;
4187 // clang-format off
4188 FORMAT(FCVTNS, "fcvtns")
4189 FORMAT(FCVTMS, "fcvtms")
4190 FORMAT(FCVTAS, "fcvtas")
4191 FORMAT(SCVTF, "scvtf")
4192 FORMAT(FCVTPS, "fcvtps")
4193 FORMAT(FCVTZS, "fcvtzs")
4194 FORMAT(FRECPE, "frecpe")
4195 FORMAT(FRECPX, "frecpx")
4196 FORMAT(FCVTNU, "fcvtnu")
4197 FORMAT(FCVTMU, "fcvtmu")
4198 FORMAT(FCVTAU, "fcvtau")
4199 FORMAT(UCVTF, "ucvtf")
4200 FORMAT(FCVTPU, "fcvtpu")
4201 FORMAT(FCVTZU, "fcvtzu")
4202 FORMAT(FRSQRTE, "frsqrte")
4203 // clang-format on
4204 #undef FORMAT
4205 #define FORMAT(A, B) \
4206 case NEON_##A##_H_zero_scalar: \
4207 mnemonic = B; \
4208 form = form_fp0; \
4209 break;
4210 FORMAT(FCMGT, "fcmgt")
4211 FORMAT(FCMEQ, "fcmeq")
4212 FORMAT(FCMLT, "fcmlt")
4213 FORMAT(FCMGE, "fcmge")
4214 FORMAT(FCMLE, "fcmle")
4215 #undef FORMAT
4216
4217 default:
4218 VIXL_UNREACHABLE();
4219 }
4220 Format(instr, mnemonic, form);
4221 }
4222
4223
VisitNEONScalar3Diff(const Instruction * instr)4224 void Disassembler::VisitNEONScalar3Diff(const Instruction *instr) {
4225 const char *mnemonic = "unimplemented";
4226 const char *form = "%sd, %sn, %sm";
4227 NEONFormatDecoder nfd(instr,
4228 NEONFormatDecoder::LongScalarFormatMap(),
4229 NEONFormatDecoder::ScalarFormatMap());
4230
4231 switch (instr->Mask(NEONScalar3DiffMask)) {
4232 case NEON_SQDMLAL_scalar:
4233 mnemonic = "sqdmlal";
4234 break;
4235 case NEON_SQDMLSL_scalar:
4236 mnemonic = "sqdmlsl";
4237 break;
4238 case NEON_SQDMULL_scalar:
4239 mnemonic = "sqdmull";
4240 break;
4241 default:
4242 form = "(NEONScalar3Diff)";
4243 }
4244 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4245 }
4246
4247
VisitNEONScalar3Same(const Instruction * instr)4248 void Disassembler::VisitNEONScalar3Same(const Instruction *instr) {
4249 const char *mnemonic = "unimplemented";
4250 const char *form = "%sd, %sn, %sm";
4251 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4252
4253 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
4254 nfd.SetFormatMaps(nfd.FPScalarFormatMap());
4255 switch (instr->Mask(NEONScalar3SameFPMask)) {
4256 case NEON_FACGE_scalar:
4257 mnemonic = "facge";
4258 break;
4259 case NEON_FACGT_scalar:
4260 mnemonic = "facgt";
4261 break;
4262 case NEON_FCMEQ_scalar:
4263 mnemonic = "fcmeq";
4264 break;
4265 case NEON_FCMGE_scalar:
4266 mnemonic = "fcmge";
4267 break;
4268 case NEON_FCMGT_scalar:
4269 mnemonic = "fcmgt";
4270 break;
4271 case NEON_FMULX_scalar:
4272 mnemonic = "fmulx";
4273 break;
4274 case NEON_FRECPS_scalar:
4275 mnemonic = "frecps";
4276 break;
4277 case NEON_FRSQRTS_scalar:
4278 mnemonic = "frsqrts";
4279 break;
4280 case NEON_FABD_scalar:
4281 mnemonic = "fabd";
4282 break;
4283 default:
4284 form = "(NEONScalar3Same)";
4285 }
4286 } else {
4287 switch (instr->Mask(NEONScalar3SameMask)) {
4288 case NEON_ADD_scalar:
4289 mnemonic = "add";
4290 break;
4291 case NEON_SUB_scalar:
4292 mnemonic = "sub";
4293 break;
4294 case NEON_CMEQ_scalar:
4295 mnemonic = "cmeq";
4296 break;
4297 case NEON_CMGE_scalar:
4298 mnemonic = "cmge";
4299 break;
4300 case NEON_CMGT_scalar:
4301 mnemonic = "cmgt";
4302 break;
4303 case NEON_CMHI_scalar:
4304 mnemonic = "cmhi";
4305 break;
4306 case NEON_CMHS_scalar:
4307 mnemonic = "cmhs";
4308 break;
4309 case NEON_CMTST_scalar:
4310 mnemonic = "cmtst";
4311 break;
4312 case NEON_UQADD_scalar:
4313 mnemonic = "uqadd";
4314 break;
4315 case NEON_SQADD_scalar:
4316 mnemonic = "sqadd";
4317 break;
4318 case NEON_UQSUB_scalar:
4319 mnemonic = "uqsub";
4320 break;
4321 case NEON_SQSUB_scalar:
4322 mnemonic = "sqsub";
4323 break;
4324 case NEON_USHL_scalar:
4325 mnemonic = "ushl";
4326 break;
4327 case NEON_SSHL_scalar:
4328 mnemonic = "sshl";
4329 break;
4330 case NEON_UQSHL_scalar:
4331 mnemonic = "uqshl";
4332 break;
4333 case NEON_SQSHL_scalar:
4334 mnemonic = "sqshl";
4335 break;
4336 case NEON_URSHL_scalar:
4337 mnemonic = "urshl";
4338 break;
4339 case NEON_SRSHL_scalar:
4340 mnemonic = "srshl";
4341 break;
4342 case NEON_UQRSHL_scalar:
4343 mnemonic = "uqrshl";
4344 break;
4345 case NEON_SQRSHL_scalar:
4346 mnemonic = "sqrshl";
4347 break;
4348 case NEON_SQDMULH_scalar:
4349 mnemonic = "sqdmulh";
4350 break;
4351 case NEON_SQRDMULH_scalar:
4352 mnemonic = "sqrdmulh";
4353 break;
4354 default:
4355 form = "(NEONScalar3Same)";
4356 }
4357 }
4358 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4359 }
4360
VisitNEONScalar3SameFP16(const Instruction * instr)4361 void Disassembler::VisitNEONScalar3SameFP16(const Instruction *instr) {
4362 const char *mnemonic = NULL;
4363 const char *form = "'Hd, 'Hn, 'Hm";
4364
4365 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
4366 case NEON_FABD_H_scalar:
4367 mnemonic = "fabd";
4368 break;
4369 case NEON_FMULX_H_scalar:
4370 mnemonic = "fmulx";
4371 break;
4372 case NEON_FCMEQ_H_scalar:
4373 mnemonic = "fcmeq";
4374 break;
4375 case NEON_FCMGE_H_scalar:
4376 mnemonic = "fcmge";
4377 break;
4378 case NEON_FCMGT_H_scalar:
4379 mnemonic = "fcmgt";
4380 break;
4381 case NEON_FACGE_H_scalar:
4382 mnemonic = "facge";
4383 break;
4384 case NEON_FACGT_H_scalar:
4385 mnemonic = "facgt";
4386 break;
4387 case NEON_FRECPS_H_scalar:
4388 mnemonic = "frecps";
4389 break;
4390 case NEON_FRSQRTS_H_scalar:
4391 mnemonic = "frsqrts";
4392 break;
4393 default:
4394 VIXL_UNREACHABLE();
4395 }
4396 Format(instr, mnemonic, form);
4397 }
4398
VisitNEONScalar3SameExtra(const Instruction * instr)4399 void Disassembler::VisitNEONScalar3SameExtra(const Instruction *instr) {
4400 const char *mnemonic = "unimplemented";
4401 const char *form = "%sd, %sn, %sm";
4402 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4403
4404 switch (instr->Mask(NEONScalar3SameExtraMask)) {
4405 case NEON_SQRDMLAH_scalar:
4406 mnemonic = "sqrdmlah";
4407 break;
4408 case NEON_SQRDMLSH_scalar:
4409 mnemonic = "sqrdmlsh";
4410 break;
4411 default:
4412 form = "(NEONScalar3SameExtra)";
4413 }
4414 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4415 }
4416
4417
VisitNEONScalarByIndexedElement(const Instruction * instr)4418 void Disassembler::VisitNEONScalarByIndexedElement(const Instruction *instr) {
4419 const char *mnemonic = "unimplemented";
4420 const char *form = "%sd, %sn, 'Ve.%s['IVByElemIndex]";
4421 const char *form_half = "'Hd, 'Hn, 'Ve.h['IVByElemIndex]";
4422 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4423 bool long_instr = false;
4424
4425 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
4426 case NEON_SQDMULL_byelement_scalar:
4427 mnemonic = "sqdmull";
4428 long_instr = true;
4429 break;
4430 case NEON_SQDMLAL_byelement_scalar:
4431 mnemonic = "sqdmlal";
4432 long_instr = true;
4433 break;
4434 case NEON_SQDMLSL_byelement_scalar:
4435 mnemonic = "sqdmlsl";
4436 long_instr = true;
4437 break;
4438 case NEON_SQDMULH_byelement_scalar:
4439 mnemonic = "sqdmulh";
4440 break;
4441 case NEON_SQRDMULH_byelement_scalar:
4442 mnemonic = "sqrdmulh";
4443 break;
4444 case NEON_SQRDMLAH_byelement_scalar:
4445 mnemonic = "sqrdmlah";
4446 break;
4447 case NEON_SQRDMLSH_byelement_scalar:
4448 mnemonic = "sqrdmlsh";
4449 break;
4450 default:
4451 nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
4452 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
4453 case NEON_FMUL_byelement_scalar:
4454 mnemonic = "fmul";
4455 break;
4456 case NEON_FMLA_byelement_scalar:
4457 mnemonic = "fmla";
4458 break;
4459 case NEON_FMLS_byelement_scalar:
4460 mnemonic = "fmls";
4461 break;
4462 case NEON_FMULX_byelement_scalar:
4463 mnemonic = "fmulx";
4464 break;
4465 case NEON_FMLA_H_byelement_scalar:
4466 mnemonic = "fmla";
4467 form = form_half;
4468 break;
4469 case NEON_FMLS_H_byelement_scalar:
4470 mnemonic = "fmls";
4471 form = form_half;
4472 break;
4473 case NEON_FMUL_H_byelement_scalar:
4474 mnemonic = "fmul";
4475 form = form_half;
4476 break;
4477 case NEON_FMULX_H_byelement_scalar:
4478 mnemonic = "fmulx";
4479 form = form_half;
4480 break;
4481 default:
4482 form = "(NEONScalarByIndexedElement)";
4483 }
4484 }
4485
4486 if (long_instr) {
4487 nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
4488 }
4489
4490 Format(instr,
4491 mnemonic,
4492 nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
4493 }
4494
4495
VisitNEONScalarCopy(const Instruction * instr)4496 void Disassembler::VisitNEONScalarCopy(const Instruction *instr) {
4497 const char *mnemonic = "unimplemented";
4498 const char *form = "(NEONScalarCopy)";
4499
4500 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
4501
4502 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
4503 mnemonic = "mov";
4504 form = "%sd, 'Vn.%s['IVInsIndex1]";
4505 }
4506
4507 Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat));
4508 }
4509
4510
VisitNEONScalarPairwise(const Instruction * instr)4511 void Disassembler::VisitNEONScalarPairwise(const Instruction *instr) {
4512 const char *mnemonic = "unimplemented";
4513 const char *form = "%sd, 'Vn.%s";
4514 NEONFormatMap map = {{22}, {NF_2S, NF_2D}};
4515 NEONFormatDecoder nfd(instr,
4516 NEONFormatDecoder::FPScalarPairwiseFormatMap(),
4517 &map);
4518
4519 switch (instr->Mask(NEONScalarPairwiseMask)) {
4520 case NEON_ADDP_scalar:
4521 // All pairwise operations except ADDP use bit U to differentiate FP16
4522 // from FP32/FP64 variations.
4523 nfd.SetFormatMap(0, NEONFormatDecoder::FPScalarFormatMap());
4524 mnemonic = "addp";
4525 break;
4526 case NEON_FADDP_h_scalar:
4527 form = "%sd, 'Vn.2h";
4528 VIXL_FALLTHROUGH();
4529 case NEON_FADDP_scalar:
4530 mnemonic = "faddp";
4531 break;
4532 case NEON_FMAXP_h_scalar:
4533 form = "%sd, 'Vn.2h";
4534 VIXL_FALLTHROUGH();
4535 case NEON_FMAXP_scalar:
4536 mnemonic = "fmaxp";
4537 break;
4538 case NEON_FMAXNMP_h_scalar:
4539 form = "%sd, 'Vn.2h";
4540 VIXL_FALLTHROUGH();
4541 case NEON_FMAXNMP_scalar:
4542 mnemonic = "fmaxnmp";
4543 break;
4544 case NEON_FMINP_h_scalar:
4545 form = "%sd, 'Vn.2h";
4546 VIXL_FALLTHROUGH();
4547 case NEON_FMINP_scalar:
4548 mnemonic = "fminp";
4549 break;
4550 case NEON_FMINNMP_h_scalar:
4551 form = "%sd, 'Vn.2h";
4552 VIXL_FALLTHROUGH();
4553 case NEON_FMINNMP_scalar:
4554 mnemonic = "fminnmp";
4555 break;
4556 default:
4557 form = "(NEONScalarPairwise)";
4558 }
4559 Format(instr,
4560 mnemonic,
4561 nfd.Substitute(form,
4562 NEONFormatDecoder::kPlaceholder,
4563 NEONFormatDecoder::kFormat));
4564 }
4565
4566
VisitNEONScalarShiftImmediate(const Instruction * instr)4567 void Disassembler::VisitNEONScalarShiftImmediate(const Instruction *instr) {
4568 const char *mnemonic = "unimplemented";
4569 const char *form = "%sd, %sn, 'Is1";
4570 const char *form_2 = "%sd, %sn, 'Is2";
4571
4572 static const NEONFormatMap map_shift = {{22, 21, 20, 19},
4573 {NF_UNDEF,
4574 NF_B,
4575 NF_H,
4576 NF_H,
4577 NF_S,
4578 NF_S,
4579 NF_S,
4580 NF_S,
4581 NF_D,
4582 NF_D,
4583 NF_D,
4584 NF_D,
4585 NF_D,
4586 NF_D,
4587 NF_D,
4588 NF_D}};
4589 static const NEONFormatMap map_shift_narrow =
4590 {{21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}};
4591 NEONFormatDecoder nfd(instr, &map_shift);
4592
4593 if (instr->GetImmNEONImmh()) { // immh has to be non-zero.
4594 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
4595 case NEON_FCVTZU_imm_scalar:
4596 mnemonic = "fcvtzu";
4597 break;
4598 case NEON_FCVTZS_imm_scalar:
4599 mnemonic = "fcvtzs";
4600 break;
4601 case NEON_SCVTF_imm_scalar:
4602 mnemonic = "scvtf";
4603 break;
4604 case NEON_UCVTF_imm_scalar:
4605 mnemonic = "ucvtf";
4606 break;
4607 case NEON_SRI_scalar:
4608 mnemonic = "sri";
4609 break;
4610 case NEON_SSHR_scalar:
4611 mnemonic = "sshr";
4612 break;
4613 case NEON_USHR_scalar:
4614 mnemonic = "ushr";
4615 break;
4616 case NEON_SRSHR_scalar:
4617 mnemonic = "srshr";
4618 break;
4619 case NEON_URSHR_scalar:
4620 mnemonic = "urshr";
4621 break;
4622 case NEON_SSRA_scalar:
4623 mnemonic = "ssra";
4624 break;
4625 case NEON_USRA_scalar:
4626 mnemonic = "usra";
4627 break;
4628 case NEON_SRSRA_scalar:
4629 mnemonic = "srsra";
4630 break;
4631 case NEON_URSRA_scalar:
4632 mnemonic = "ursra";
4633 break;
4634 case NEON_SHL_scalar:
4635 mnemonic = "shl";
4636 form = form_2;
4637 break;
4638 case NEON_SLI_scalar:
4639 mnemonic = "sli";
4640 form = form_2;
4641 break;
4642 case NEON_SQSHLU_scalar:
4643 mnemonic = "sqshlu";
4644 form = form_2;
4645 break;
4646 case NEON_SQSHL_imm_scalar:
4647 mnemonic = "sqshl";
4648 form = form_2;
4649 break;
4650 case NEON_UQSHL_imm_scalar:
4651 mnemonic = "uqshl";
4652 form = form_2;
4653 break;
4654 case NEON_UQSHRN_scalar:
4655 mnemonic = "uqshrn";
4656 nfd.SetFormatMap(1, &map_shift_narrow);
4657 break;
4658 case NEON_UQRSHRN_scalar:
4659 mnemonic = "uqrshrn";
4660 nfd.SetFormatMap(1, &map_shift_narrow);
4661 break;
4662 case NEON_SQSHRN_scalar:
4663 mnemonic = "sqshrn";
4664 nfd.SetFormatMap(1, &map_shift_narrow);
4665 break;
4666 case NEON_SQRSHRN_scalar:
4667 mnemonic = "sqrshrn";
4668 nfd.SetFormatMap(1, &map_shift_narrow);
4669 break;
4670 case NEON_SQSHRUN_scalar:
4671 mnemonic = "sqshrun";
4672 nfd.SetFormatMap(1, &map_shift_narrow);
4673 break;
4674 case NEON_SQRSHRUN_scalar:
4675 mnemonic = "sqrshrun";
4676 nfd.SetFormatMap(1, &map_shift_narrow);
4677 break;
4678 default:
4679 form = "(NEONScalarShiftImmediate)";
4680 }
4681 } else {
4682 form = "(NEONScalarShiftImmediate)";
4683 }
4684 Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4685 }
4686
4687
VisitNEONShiftImmediate(const Instruction * instr)4688 void Disassembler::VisitNEONShiftImmediate(const Instruction *instr) {
4689 const char *mnemonic = "unimplemented";
4690 const char *form = "'Vd.%s, 'Vn.%s, 'Is1";
4691 const char *form_shift_2 = "'Vd.%s, 'Vn.%s, 'Is2";
4692 const char *form_xtl = "'Vd.%s, 'Vn.%s";
4693
4694 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
4695 static const NEONFormatMap map_shift_ta =
4696 {{22, 21, 20, 19},
4697 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
4698
4699 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
4700 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
4701 static const NEONFormatMap map_shift_tb =
4702 {{22, 21, 20, 19, 30},
4703 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H,
4704 NF_8H, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S,
4705 NF_2S, NF_4S, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF,
4706 NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
4707 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
4708
4709 NEONFormatDecoder nfd(instr, &map_shift_tb);
4710
4711 if (instr->GetImmNEONImmh()) { // immh has to be non-zero.
4712 switch (instr->Mask(NEONShiftImmediateMask)) {
4713 case NEON_SQSHLU:
4714 mnemonic = "sqshlu";
4715 form = form_shift_2;
4716 break;
4717 case NEON_SQSHL_imm:
4718 mnemonic = "sqshl";
4719 form = form_shift_2;
4720 break;
4721 case NEON_UQSHL_imm:
4722 mnemonic = "uqshl";
4723 form = form_shift_2;
4724 break;
4725 case NEON_SHL:
4726 mnemonic = "shl";
4727 form = form_shift_2;
4728 break;
4729 case NEON_SLI:
4730 mnemonic = "sli";
4731 form = form_shift_2;
4732 break;
4733 case NEON_SCVTF_imm:
4734 mnemonic = "scvtf";
4735 break;
4736 case NEON_UCVTF_imm:
4737 mnemonic = "ucvtf";
4738 break;
4739 case NEON_FCVTZU_imm:
4740 mnemonic = "fcvtzu";
4741 break;
4742 case NEON_FCVTZS_imm:
4743 mnemonic = "fcvtzs";
4744 break;
4745 case NEON_SRI:
4746 mnemonic = "sri";
4747 break;
4748 case NEON_SSHR:
4749 mnemonic = "sshr";
4750 break;
4751 case NEON_USHR:
4752 mnemonic = "ushr";
4753 break;
4754 case NEON_SRSHR:
4755 mnemonic = "srshr";
4756 break;
4757 case NEON_URSHR:
4758 mnemonic = "urshr";
4759 break;
4760 case NEON_SSRA:
4761 mnemonic = "ssra";
4762 break;
4763 case NEON_USRA:
4764 mnemonic = "usra";
4765 break;
4766 case NEON_SRSRA:
4767 mnemonic = "srsra";
4768 break;
4769 case NEON_URSRA:
4770 mnemonic = "ursra";
4771 break;
4772 case NEON_SHRN:
4773 mnemonic = instr->Mask(NEON_Q) ? "shrn2" : "shrn";
4774 nfd.SetFormatMap(1, &map_shift_ta);
4775 break;
4776 case NEON_RSHRN:
4777 mnemonic = instr->Mask(NEON_Q) ? "rshrn2" : "rshrn";
4778 nfd.SetFormatMap(1, &map_shift_ta);
4779 break;
4780 case NEON_UQSHRN:
4781 mnemonic = instr->Mask(NEON_Q) ? "uqshrn2" : "uqshrn";
4782 nfd.SetFormatMap(1, &map_shift_ta);
4783 break;
4784 case NEON_UQRSHRN:
4785 mnemonic = instr->Mask(NEON_Q) ? "uqrshrn2" : "uqrshrn";
4786 nfd.SetFormatMap(1, &map_shift_ta);
4787 break;
4788 case NEON_SQSHRN:
4789 mnemonic = instr->Mask(NEON_Q) ? "sqshrn2" : "sqshrn";
4790 nfd.SetFormatMap(1, &map_shift_ta);
4791 break;
4792 case NEON_SQRSHRN:
4793 mnemonic = instr->Mask(NEON_Q) ? "sqrshrn2" : "sqrshrn";
4794 nfd.SetFormatMap(1, &map_shift_ta);
4795 break;
4796 case NEON_SQSHRUN:
4797 mnemonic = instr->Mask(NEON_Q) ? "sqshrun2" : "sqshrun";
4798 nfd.SetFormatMap(1, &map_shift_ta);
4799 break;
4800 case NEON_SQRSHRUN:
4801 mnemonic = instr->Mask(NEON_Q) ? "sqrshrun2" : "sqrshrun";
4802 nfd.SetFormatMap(1, &map_shift_ta);
4803 break;
4804 case NEON_SSHLL:
4805 nfd.SetFormatMap(0, &map_shift_ta);
4806 if (instr->GetImmNEONImmb() == 0 &&
4807 CountSetBits(instr->GetImmNEONImmh(), 32) == 1) { // sxtl variant.
4808 form = form_xtl;
4809 mnemonic = instr->Mask(NEON_Q) ? "sxtl2" : "sxtl";
4810 } else { // sshll variant.
4811 form = form_shift_2;
4812 mnemonic = instr->Mask(NEON_Q) ? "sshll2" : "sshll";
4813 }
4814 break;
4815 case NEON_USHLL:
4816 nfd.SetFormatMap(0, &map_shift_ta);
4817 if (instr->GetImmNEONImmb() == 0 &&
4818 CountSetBits(instr->GetImmNEONImmh(), 32) == 1) { // uxtl variant.
4819 form = form_xtl;
4820 mnemonic = instr->Mask(NEON_Q) ? "uxtl2" : "uxtl";
4821 } else { // ushll variant.
4822 form = form_shift_2;
4823 mnemonic = instr->Mask(NEON_Q) ? "ushll2" : "ushll";
4824 }
4825 break;
4826 default:
4827 form = "(NEONShiftImmediate)";
4828 }
4829 } else {
4830 form = "(NEONShiftImmediate)";
4831 }
4832 Format(instr, mnemonic, nfd.Substitute(form));
4833 }
4834
4835
VisitNEONTable(const Instruction * instr)4836 void Disassembler::VisitNEONTable(const Instruction *instr) {
4837 const char *mnemonic = "unimplemented";
4838 const char *form = "(NEONTable)";
4839 const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s";
4840 const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s";
4841 const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
4842 const char form_4v[] =
4843 "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
4844 static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
4845 NEONFormatDecoder nfd(instr, &map_b);
4846
4847 switch (instr->Mask(NEONTableMask)) {
4848 case NEON_TBL_1v:
4849 mnemonic = "tbl";
4850 form = form_1v;
4851 break;
4852 case NEON_TBL_2v:
4853 mnemonic = "tbl";
4854 form = form_2v;
4855 break;
4856 case NEON_TBL_3v:
4857 mnemonic = "tbl";
4858 form = form_3v;
4859 break;
4860 case NEON_TBL_4v:
4861 mnemonic = "tbl";
4862 form = form_4v;
4863 break;
4864 case NEON_TBX_1v:
4865 mnemonic = "tbx";
4866 form = form_1v;
4867 break;
4868 case NEON_TBX_2v:
4869 mnemonic = "tbx";
4870 form = form_2v;
4871 break;
4872 case NEON_TBX_3v:
4873 mnemonic = "tbx";
4874 form = form_3v;
4875 break;
4876 case NEON_TBX_4v:
4877 mnemonic = "tbx";
4878 form = form_4v;
4879 break;
4880 default:
4881 break;
4882 }
4883
4884 char re_form[sizeof(form_4v) + 6];
4885 int reg_num = instr->GetRn();
4886 snprintf(re_form,
4887 sizeof(re_form),
4888 form,
4889 (reg_num + 1) % kNumberOfVRegisters,
4890 (reg_num + 2) % kNumberOfVRegisters,
4891 (reg_num + 3) % kNumberOfVRegisters);
4892
4893 Format(instr, mnemonic, nfd.Substitute(re_form));
4894 }
4895
4896
VisitNEONPerm(const Instruction * instr)4897 void Disassembler::VisitNEONPerm(const Instruction *instr) {
4898 const char *mnemonic = "unimplemented";
4899 const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
4900 NEONFormatDecoder nfd(instr);
4901
4902 switch (instr->Mask(NEONPermMask)) {
4903 case NEON_TRN1:
4904 mnemonic = "trn1";
4905 break;
4906 case NEON_TRN2:
4907 mnemonic = "trn2";
4908 break;
4909 case NEON_UZP1:
4910 mnemonic = "uzp1";
4911 break;
4912 case NEON_UZP2:
4913 mnemonic = "uzp2";
4914 break;
4915 case NEON_ZIP1:
4916 mnemonic = "zip1";
4917 break;
4918 case NEON_ZIP2:
4919 mnemonic = "zip2";
4920 break;
4921 default:
4922 form = "(NEONPerm)";
4923 }
4924 Format(instr, mnemonic, nfd.Substitute(form));
4925 }
4926
4927 void Disassembler::
VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(const Instruction * instr)4928 VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
4929 const Instruction *instr) {
4930 const char *mnemonic = "unimplemented";
4931 const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #1]";
4932
4933 switch (instr->Mask(
4934 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
4935 case LD1H_z_p_bz_s_x32_scaled:
4936 mnemonic = "ld1h";
4937 break;
4938 case LD1SH_z_p_bz_s_x32_scaled:
4939 mnemonic = "ld1sh";
4940 break;
4941 case LDFF1H_z_p_bz_s_x32_scaled:
4942 mnemonic = "ldff1h";
4943 break;
4944 case LDFF1SH_z_p_bz_s_x32_scaled:
4945 mnemonic = "ldff1sh";
4946 break;
4947 default:
4948 form = "(SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets)";
4949 break;
4950 }
4951 Format(instr, mnemonic, form);
4952 }
4953
VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(const Instruction * instr)4954 void Disassembler::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
4955 const Instruction *instr) {
4956 const char *mnemonic = "unimplemented";
4957 const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #2]";
4958
4959 switch (
4960 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
4961 case LD1W_z_p_bz_s_x32_scaled:
4962 mnemonic = "ld1w";
4963 break;
4964 case LDFF1W_z_p_bz_s_x32_scaled:
4965 mnemonic = "ldff1w";
4966 break;
4967 default:
4968 form = "(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets)";
4969 break;
4970 }
4971 Format(instr, mnemonic, form);
4972 }
4973
VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(const Instruction * instr)4974 void Disassembler::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
4975 const Instruction *instr) {
4976 const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw]";
4977
4978 const char *mnemonic = "unimplemented";
4979 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
4980 case LD1B_z_p_bz_s_x32_unscaled:
4981 mnemonic = "ld1b";
4982 break;
4983 case LD1H_z_p_bz_s_x32_unscaled:
4984 mnemonic = "ld1h";
4985 break;
4986 case LD1SB_z_p_bz_s_x32_unscaled:
4987 mnemonic = "ld1sb";
4988 break;
4989 case LD1SH_z_p_bz_s_x32_unscaled:
4990 mnemonic = "ld1sh";
4991 break;
4992 case LD1W_z_p_bz_s_x32_unscaled:
4993 mnemonic = "ld1w";
4994 break;
4995 case LDFF1B_z_p_bz_s_x32_unscaled:
4996 mnemonic = "ldff1b";
4997 break;
4998 case LDFF1H_z_p_bz_s_x32_unscaled:
4999 mnemonic = "ldff1h";
5000 break;
5001 case LDFF1SB_z_p_bz_s_x32_unscaled:
5002 mnemonic = "ldff1sb";
5003 break;
5004 case LDFF1SH_z_p_bz_s_x32_unscaled:
5005 mnemonic = "ldff1sh";
5006 break;
5007 case LDFF1W_z_p_bz_s_x32_unscaled:
5008 mnemonic = "ldff1w";
5009 break;
5010 default:
5011 form = "(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets)";
5012 break;
5013 }
5014 Format(instr, mnemonic, form);
5015 }
5016
VisitSVE32BitGatherLoad_VectorPlusImm(const Instruction * instr)5017 void Disassembler::VisitSVE32BitGatherLoad_VectorPlusImm(
5018 const Instruction *instr) {
5019 const char *form = "{'Zt.s}, 'Pgl/z, ['Zn.s]";
5020 const char *form_imm_b = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016]";
5021 const char *form_imm_h = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*2]";
5022 const char *form_imm_w = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*4]";
5023 const char *form_imm;
5024
5025 const char *mnemonic = "unimplemented";
5026 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
5027 case LD1B_z_p_ai_s:
5028 mnemonic = "ld1b";
5029 form_imm = form_imm_b;
5030 break;
5031 case LD1H_z_p_ai_s:
5032 mnemonic = "ld1h";
5033 form_imm = form_imm_h;
5034 break;
5035 case LD1SB_z_p_ai_s:
5036 mnemonic = "ld1sb";
5037 form_imm = form_imm_b;
5038 break;
5039 case LD1SH_z_p_ai_s:
5040 mnemonic = "ld1sh";
5041 form_imm = form_imm_h;
5042 break;
5043 case LD1W_z_p_ai_s:
5044 mnemonic = "ld1w";
5045 form_imm = form_imm_w;
5046 break;
5047 case LDFF1B_z_p_ai_s:
5048 mnemonic = "ldff1b";
5049 form_imm = form_imm_b;
5050 break;
5051 case LDFF1H_z_p_ai_s:
5052 mnemonic = "ldff1h";
5053 form_imm = form_imm_h;
5054 break;
5055 case LDFF1SB_z_p_ai_s:
5056 mnemonic = "ldff1sb";
5057 form_imm = form_imm_b;
5058 break;
5059 case LDFF1SH_z_p_ai_s:
5060 mnemonic = "ldff1sh";
5061 form_imm = form_imm_h;
5062 break;
5063 case LDFF1W_z_p_ai_s:
5064 mnemonic = "ldff1w";
5065 form_imm = form_imm_w;
5066 break;
5067 default:
5068 form = "(SVE32BitGatherLoad_VectorPlusImm)";
5069 form_imm = form;
5070 break;
5071 }
5072 if (instr->ExtractBits(20, 16) != 0) form = form_imm;
5073
5074 Format(instr, mnemonic, form);
5075 }
5076
VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(const Instruction * instr)5077 void Disassembler::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
5078 const Instruction *instr) {
5079 const char *mnemonic = "unimplemented";
5080 const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.s, '?22:suxtw";
5081 const char *suffix = NULL;
5082
5083 switch (
5084 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
5085 case PRFB_i_p_bz_s_x32_scaled:
5086 mnemonic = "prfb";
5087 suffix = "]";
5088 break;
5089 case PRFD_i_p_bz_s_x32_scaled:
5090 mnemonic = "prfd";
5091 suffix = " #3]";
5092 break;
5093 case PRFH_i_p_bz_s_x32_scaled:
5094 mnemonic = "prfh";
5095 suffix = " #1]";
5096 break;
5097 case PRFW_i_p_bz_s_x32_scaled:
5098 mnemonic = "prfw";
5099 suffix = " #2]";
5100 break;
5101 default:
5102 form = "(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets)";
5103 break;
5104 }
5105 Format(instr, mnemonic, form, suffix);
5106 }
5107
VisitSVE32BitGatherPrefetch_VectorPlusImm(const Instruction * instr)5108 void Disassembler::VisitSVE32BitGatherPrefetch_VectorPlusImm(
5109 const Instruction *instr) {
5110 const char *mnemonic = "unimplemented";
5111 const char *form = (instr->ExtractBits(20, 16) != 0)
5112 ? "'prefSVEOp, 'Pgl, ['Zn.s, #'u2016]"
5113 : "'prefSVEOp, 'Pgl, ['Zn.s]";
5114
5115 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
5116 case PRFB_i_p_ai_s:
5117 mnemonic = "prfb";
5118 break;
5119 case PRFD_i_p_ai_s:
5120 mnemonic = "prfd";
5121 break;
5122 case PRFH_i_p_ai_s:
5123 mnemonic = "prfh";
5124 break;
5125 case PRFW_i_p_ai_s:
5126 mnemonic = "prfw";
5127 break;
5128 default:
5129 break;
5130 }
5131 Format(instr, mnemonic, form);
5132 }
5133
VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(const Instruction * instr)5134 void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
5135 const Instruction *instr) {
5136 const char *mnemonic = "unimplemented";
5137 const char *form = "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw #'u2423]";
5138
5139 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
5140 case ST1H_z_p_bz_s_x32_scaled:
5141 mnemonic = "st1h";
5142 break;
5143 case ST1W_z_p_bz_s_x32_scaled:
5144 mnemonic = "st1w";
5145 break;
5146 default:
5147 form = "(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets)";
5148 break;
5149 }
5150 Format(instr, mnemonic, form);
5151 }
5152
VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(const Instruction * instr)5153 void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
5154 const Instruction *instr) {
5155 const char *mnemonic = "unimplemented";
5156 const char *form = "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw]";
5157
5158 switch (
5159 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
5160 case ST1B_z_p_bz_s_x32_unscaled:
5161 mnemonic = "st1b";
5162 break;
5163 case ST1H_z_p_bz_s_x32_unscaled:
5164 mnemonic = "st1h";
5165 break;
5166 case ST1W_z_p_bz_s_x32_unscaled:
5167 mnemonic = "st1w";
5168 break;
5169 default:
5170 form = "(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets)";
5171 break;
5172 }
5173 Format(instr, mnemonic, form);
5174 }
5175
VisitSVE32BitScatterStore_VectorPlusImm(const Instruction * instr)5176 void Disassembler::VisitSVE32BitScatterStore_VectorPlusImm(
5177 const Instruction *instr) {
5178 const char *mnemonic = "unimplemented";
5179 const char *form = "{'Zt.s}, 'Pgl, ['Zn.s";
5180 const char *suffix = NULL;
5181
5182 bool is_zero = instr->ExtractBits(20, 16) == 0;
5183
5184 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
5185 case ST1B_z_p_ai_s:
5186 mnemonic = "st1b";
5187 suffix = is_zero ? "]" : ", #'u2016]";
5188 break;
5189 case ST1H_z_p_ai_s:
5190 mnemonic = "st1h";
5191 suffix = is_zero ? "]" : ", #'u2016*2]";
5192 break;
5193 case ST1W_z_p_ai_s:
5194 mnemonic = "st1w";
5195 suffix = is_zero ? "]" : ", #'u2016*4]";
5196 break;
5197 default:
5198 form = "(SVE32BitScatterStore_VectorPlusImm)";
5199 break;
5200 }
5201 Format(instr, mnemonic, form, suffix);
5202 }
5203
VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(const Instruction * instr)5204 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
5205 const Instruction *instr) {
5206 const char *mnemonic = "unimplemented";
5207 const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw #'u2423]";
5208
5209 switch (instr->Mask(
5210 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
5211 case LD1D_z_p_bz_d_x32_scaled:
5212 mnemonic = "ld1d";
5213 break;
5214 case LD1H_z_p_bz_d_x32_scaled:
5215 mnemonic = "ld1h";
5216 break;
5217 case LD1SH_z_p_bz_d_x32_scaled:
5218 mnemonic = "ld1sh";
5219 break;
5220 case LD1SW_z_p_bz_d_x32_scaled:
5221 mnemonic = "ld1sw";
5222 break;
5223 case LD1W_z_p_bz_d_x32_scaled:
5224 mnemonic = "ld1w";
5225 break;
5226 case LDFF1D_z_p_bz_d_x32_scaled:
5227 mnemonic = "ldff1d";
5228 break;
5229 case LDFF1H_z_p_bz_d_x32_scaled:
5230 mnemonic = "ldff1h";
5231 break;
5232 case LDFF1SH_z_p_bz_d_x32_scaled:
5233 mnemonic = "ldff1sh";
5234 break;
5235 case LDFF1SW_z_p_bz_d_x32_scaled:
5236 mnemonic = "ldff1sw";
5237 break;
5238 case LDFF1W_z_p_bz_d_x32_scaled:
5239 mnemonic = "ldff1w";
5240 break;
5241 default:
5242 form = "(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)";
5243 break;
5244 }
5245 Format(instr, mnemonic, form);
5246 }
5247
VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(const Instruction * instr)5248 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
5249 const Instruction *instr) {
5250 const char *mnemonic = "unimplemented";
5251 const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, lsl #'u2423]";
5252
5253 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
5254 case LD1D_z_p_bz_d_64_scaled:
5255 mnemonic = "ld1d";
5256 break;
5257 case LD1H_z_p_bz_d_64_scaled:
5258 mnemonic = "ld1h";
5259 break;
5260 case LD1SH_z_p_bz_d_64_scaled:
5261 mnemonic = "ld1sh";
5262 break;
5263 case LD1SW_z_p_bz_d_64_scaled:
5264 mnemonic = "ld1sw";
5265 break;
5266 case LD1W_z_p_bz_d_64_scaled:
5267 mnemonic = "ld1w";
5268 break;
5269 case LDFF1D_z_p_bz_d_64_scaled:
5270 mnemonic = "ldff1d";
5271 break;
5272 case LDFF1H_z_p_bz_d_64_scaled:
5273 mnemonic = "ldff1h";
5274 break;
5275 case LDFF1SH_z_p_bz_d_64_scaled:
5276 mnemonic = "ldff1sh";
5277 break;
5278 case LDFF1SW_z_p_bz_d_64_scaled:
5279 mnemonic = "ldff1sw";
5280 break;
5281 case LDFF1W_z_p_bz_d_64_scaled:
5282 mnemonic = "ldff1w";
5283 break;
5284 default:
5285 form = "(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)";
5286 break;
5287 }
5288 Format(instr, mnemonic, form);
5289 }
5290
VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(const Instruction * instr)5291 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
5292 const Instruction *instr) {
5293 const char *mnemonic = "unimplemented";
5294 const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d]";
5295
5296 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
5297 case LD1B_z_p_bz_d_64_unscaled:
5298 mnemonic = "ld1b";
5299 break;
5300 case LD1D_z_p_bz_d_64_unscaled:
5301 mnemonic = "ld1d";
5302 break;
5303 case LD1H_z_p_bz_d_64_unscaled:
5304 mnemonic = "ld1h";
5305 break;
5306 case LD1SB_z_p_bz_d_64_unscaled:
5307 mnemonic = "ld1sb";
5308 break;
5309 case LD1SH_z_p_bz_d_64_unscaled:
5310 mnemonic = "ld1sh";
5311 break;
5312 case LD1SW_z_p_bz_d_64_unscaled:
5313 mnemonic = "ld1sw";
5314 break;
5315 case LD1W_z_p_bz_d_64_unscaled:
5316 mnemonic = "ld1w";
5317 break;
5318 case LDFF1B_z_p_bz_d_64_unscaled:
5319 mnemonic = "ldff1b";
5320 break;
5321 case LDFF1D_z_p_bz_d_64_unscaled:
5322 mnemonic = "ldff1d";
5323 break;
5324 case LDFF1H_z_p_bz_d_64_unscaled:
5325 mnemonic = "ldff1h";
5326 break;
5327 case LDFF1SB_z_p_bz_d_64_unscaled:
5328 mnemonic = "ldff1sb";
5329 break;
5330 case LDFF1SH_z_p_bz_d_64_unscaled:
5331 mnemonic = "ldff1sh";
5332 break;
5333 case LDFF1SW_z_p_bz_d_64_unscaled:
5334 mnemonic = "ldff1sw";
5335 break;
5336 case LDFF1W_z_p_bz_d_64_unscaled:
5337 mnemonic = "ldff1w";
5338 break;
5339 default:
5340 break;
5341 }
5342 Format(instr, mnemonic, form);
5343 }
5344
5345 void Disassembler::
VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(const Instruction * instr)5346 VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
5347 const Instruction *instr) {
5348 const char *mnemonic = "unimplemented";
5349 const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw]";
5350
5351 switch (instr->Mask(
5352 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
5353 case LD1B_z_p_bz_d_x32_unscaled:
5354 mnemonic = "ld1b";
5355 break;
5356 case LD1D_z_p_bz_d_x32_unscaled:
5357 mnemonic = "ld1d";
5358 break;
5359 case LD1H_z_p_bz_d_x32_unscaled:
5360 mnemonic = "ld1h";
5361 break;
5362 case LD1SB_z_p_bz_d_x32_unscaled:
5363 mnemonic = "ld1sb";
5364 break;
5365 case LD1SH_z_p_bz_d_x32_unscaled:
5366 mnemonic = "ld1sh";
5367 break;
5368 case LD1SW_z_p_bz_d_x32_unscaled:
5369 mnemonic = "ld1sw";
5370 break;
5371 case LD1W_z_p_bz_d_x32_unscaled:
5372 mnemonic = "ld1w";
5373 break;
5374 case LDFF1B_z_p_bz_d_x32_unscaled:
5375 mnemonic = "ldff1b";
5376 break;
5377 case LDFF1D_z_p_bz_d_x32_unscaled:
5378 mnemonic = "ldff1d";
5379 break;
5380 case LDFF1H_z_p_bz_d_x32_unscaled:
5381 mnemonic = "ldff1h";
5382 break;
5383 case LDFF1SB_z_p_bz_d_x32_unscaled:
5384 mnemonic = "ldff1sb";
5385 break;
5386 case LDFF1SH_z_p_bz_d_x32_unscaled:
5387 mnemonic = "ldff1sh";
5388 break;
5389 case LDFF1SW_z_p_bz_d_x32_unscaled:
5390 mnemonic = "ldff1sw";
5391 break;
5392 case LDFF1W_z_p_bz_d_x32_unscaled:
5393 mnemonic = "ldff1w";
5394 break;
5395 default:
5396 form = "(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)";
5397 break;
5398 }
5399 Format(instr, mnemonic, form);
5400 }
5401
VisitSVE64BitGatherLoad_VectorPlusImm(const Instruction * instr)5402 void Disassembler::VisitSVE64BitGatherLoad_VectorPlusImm(
5403 const Instruction *instr) {
5404 const char *form = "{'Zt.d}, 'Pgl/z, ['Zn.d]";
5405 const char *form_imm[4] = {"{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016]",
5406 "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*2]",
5407 "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*4]",
5408 "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*8]"};
5409
5410 if (instr->ExtractBits(20, 16) != 0) {
5411 unsigned msz = instr->ExtractBits(24, 23);
5412 bool sign_extend = instr->ExtractBit(14) == 0;
5413 if ((msz == kDRegSizeInBytesLog2) && sign_extend) {
5414 form = "(SVE64BitGatherLoad_VectorPlusImm)";
5415 } else {
5416 VIXL_ASSERT(msz < ArrayLength(form_imm));
5417 form = form_imm[msz];
5418 }
5419 }
5420
5421 const char *mnemonic = "unimplemented";
5422 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
5423 case LD1B_z_p_ai_d:
5424 mnemonic = "ld1b";
5425 break;
5426 case LD1D_z_p_ai_d:
5427 mnemonic = "ld1d";
5428 break;
5429 case LD1H_z_p_ai_d:
5430 mnemonic = "ld1h";
5431 break;
5432 case LD1SB_z_p_ai_d:
5433 mnemonic = "ld1sb";
5434 break;
5435 case LD1SH_z_p_ai_d:
5436 mnemonic = "ld1sh";
5437 break;
5438 case LD1SW_z_p_ai_d:
5439 mnemonic = "ld1sw";
5440 break;
5441 case LD1W_z_p_ai_d:
5442 mnemonic = "ld1w";
5443 break;
5444 case LDFF1B_z_p_ai_d:
5445 mnemonic = "ldff1b";
5446 break;
5447 case LDFF1D_z_p_ai_d:
5448 mnemonic = "ldff1d";
5449 break;
5450 case LDFF1H_z_p_ai_d:
5451 mnemonic = "ldff1h";
5452 break;
5453 case LDFF1SB_z_p_ai_d:
5454 mnemonic = "ldff1sb";
5455 break;
5456 case LDFF1SH_z_p_ai_d:
5457 mnemonic = "ldff1sh";
5458 break;
5459 case LDFF1SW_z_p_ai_d:
5460 mnemonic = "ldff1sw";
5461 break;
5462 case LDFF1W_z_p_ai_d:
5463 mnemonic = "ldff1w";
5464 break;
5465 default:
5466 break;
5467 }
5468 Format(instr, mnemonic, form);
5469 }
5470
VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(const Instruction * instr)5471 void Disassembler::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
5472 const Instruction *instr) {
5473 const char *mnemonic = "unimplemented";
5474 const char *form = "(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets)";
5475
5476 switch (
5477 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
5478 case PRFB_i_p_bz_d_64_scaled:
5479 mnemonic = "prfb";
5480 form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d]";
5481 break;
5482 case PRFD_i_p_bz_d_64_scaled:
5483 mnemonic = "prfd";
5484 form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #3]";
5485 break;
5486 case PRFH_i_p_bz_d_64_scaled:
5487 mnemonic = "prfh";
5488 form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #1]";
5489 break;
5490 case PRFW_i_p_bz_d_64_scaled:
5491 mnemonic = "prfw";
5492 form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #2]";
5493 break;
5494 default:
5495 break;
5496 }
5497 Format(instr, mnemonic, form);
5498 }
5499
5500 void Disassembler::
VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(const Instruction * instr)5501 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
5502 const Instruction *instr) {
5503 const char *mnemonic = "unimplemented";
5504 const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, '?22:suxtw";
5505 const char *suffix = NULL;
5506
5507 switch (instr->Mask(
5508 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
5509 case PRFB_i_p_bz_d_x32_scaled:
5510 mnemonic = "prfb";
5511 suffix = " ]";
5512 break;
5513 case PRFD_i_p_bz_d_x32_scaled:
5514 mnemonic = "prfd";
5515 suffix = " #3]";
5516 break;
5517 case PRFH_i_p_bz_d_x32_scaled:
5518 mnemonic = "prfh";
5519 suffix = " #1]";
5520 break;
5521 case PRFW_i_p_bz_d_x32_scaled:
5522 mnemonic = "prfw";
5523 suffix = " #2]";
5524 break;
5525 default:
5526 form = "(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets)";
5527 break;
5528 }
5529 Format(instr, mnemonic, form, suffix);
5530 }
5531
VisitSVE64BitGatherPrefetch_VectorPlusImm(const Instruction * instr)5532 void Disassembler::VisitSVE64BitGatherPrefetch_VectorPlusImm(
5533 const Instruction *instr) {
5534 const char *mnemonic = "unimplemented";
5535 const char *form = (instr->ExtractBits(20, 16) != 0)
5536 ? "'prefSVEOp, 'Pgl, ['Zn.d, #'u2016]"
5537 : "'prefSVEOp, 'Pgl, ['Zn.d]";
5538
5539 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
5540 case PRFB_i_p_ai_d:
5541 mnemonic = "prfb";
5542 break;
5543 case PRFD_i_p_ai_d:
5544 mnemonic = "prfd";
5545 break;
5546 case PRFH_i_p_ai_d:
5547 mnemonic = "prfh";
5548 break;
5549 case PRFW_i_p_ai_d:
5550 mnemonic = "prfw";
5551 break;
5552 default:
5553 break;
5554 }
5555 Format(instr, mnemonic, form);
5556 }
5557
VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(const Instruction * instr)5558 void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
5559 const Instruction *instr) {
5560 const char *mnemonic = "unimplemented";
5561 const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, lsl #'u2423]";
5562
5563 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
5564 case ST1D_z_p_bz_d_64_scaled:
5565 mnemonic = "st1d";
5566 break;
5567 case ST1H_z_p_bz_d_64_scaled:
5568 mnemonic = "st1h";
5569 break;
5570 case ST1W_z_p_bz_d_64_scaled:
5571 mnemonic = "st1w";
5572 break;
5573 default:
5574 form = "(SVE64BitScatterStore_ScalarPlus64BitScaledOffsets)";
5575 break;
5576 }
5577 Format(instr, mnemonic, form);
5578 }
5579
VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(const Instruction * instr)5580 void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
5581 const Instruction *instr) {
5582 const char *mnemonic = "unimplemented";
5583 const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d]";
5584
5585 switch (
5586 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
5587 case ST1B_z_p_bz_d_64_unscaled:
5588 mnemonic = "st1b";
5589 break;
5590 case ST1D_z_p_bz_d_64_unscaled:
5591 mnemonic = "st1d";
5592 break;
5593 case ST1H_z_p_bz_d_64_unscaled:
5594 mnemonic = "st1h";
5595 break;
5596 case ST1W_z_p_bz_d_64_unscaled:
5597 mnemonic = "st1w";
5598 break;
5599 default:
5600 form = "(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffset)";
5601 break;
5602 }
5603 Format(instr, mnemonic, form);
5604 }
5605
5606 void Disassembler::
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(const Instruction * instr)5607 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
5608 const Instruction *instr) {
5609 const char *mnemonic = "unimplemented";
5610 const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw #'u2423]";
5611
5612 switch (instr->Mask(
5613 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
5614 case ST1D_z_p_bz_d_x32_scaled:
5615 mnemonic = "st1d";
5616 break;
5617 case ST1H_z_p_bz_d_x32_scaled:
5618 mnemonic = "st1h";
5619 break;
5620 case ST1W_z_p_bz_d_x32_scaled:
5621 mnemonic = "st1w";
5622 break;
5623 default:
5624 form = "(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets)";
5625 break;
5626 }
5627 Format(instr, mnemonic, form);
5628 }
5629
5630 void Disassembler::
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(const Instruction * instr)5631 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
5632 const Instruction *instr) {
5633 const char *mnemonic = "unimplemented";
5634 const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw]";
5635
5636 switch (instr->Mask(
5637 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
5638 case ST1B_z_p_bz_d_x32_unscaled:
5639 mnemonic = "st1b";
5640 break;
5641 case ST1D_z_p_bz_d_x32_unscaled:
5642 mnemonic = "st1d";
5643 break;
5644 case ST1H_z_p_bz_d_x32_unscaled:
5645 mnemonic = "st1h";
5646 break;
5647 case ST1W_z_p_bz_d_x32_unscaled:
5648 mnemonic = "st1w";
5649 break;
5650 default:
5651 form = "(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets)";
5652 break;
5653 }
5654 Format(instr, mnemonic, form);
5655 }
5656
VisitSVE64BitScatterStore_VectorPlusImm(const Instruction * instr)5657 void Disassembler::VisitSVE64BitScatterStore_VectorPlusImm(
5658 const Instruction *instr) {
5659 const char *mnemonic = "unimplemented";
5660 const char *form = "{'Zt.d}, 'Pgl, ['Zn.d";
5661 const char *suffix = NULL;
5662
5663 bool is_zero = instr->ExtractBits(20, 16) == 0;
5664
5665 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
5666 case ST1B_z_p_ai_d:
5667 mnemonic = "st1b";
5668 suffix = is_zero ? "]" : ", #'u2016]";
5669 break;
5670 case ST1D_z_p_ai_d:
5671 mnemonic = "st1d";
5672 suffix = is_zero ? "]" : ", #'u2016*8]";
5673 break;
5674 case ST1H_z_p_ai_d:
5675 mnemonic = "st1h";
5676 suffix = is_zero ? "]" : ", #'u2016*2]";
5677 break;
5678 case ST1W_z_p_ai_d:
5679 mnemonic = "st1w";
5680 suffix = is_zero ? "]" : ", #'u2016*4]";
5681 break;
5682 default:
5683 form = "(SVE64BitScatterStore_VectorPlusImm)";
5684 break;
5685 }
5686 Format(instr, mnemonic, form, suffix);
5687 }
5688
VisitSVEBitwiseLogicalWithImm_Unpredicated(const Instruction * instr)5689 void Disassembler::VisitSVEBitwiseLogicalWithImm_Unpredicated(
5690 const Instruction *instr) {
5691 const char *mnemonic = "unimplemented";
5692 const char *form = "'Zd.'tl, 'Zd.'tl, 'ITriSvel";
5693
5694 if (instr->GetSVEImmLogical() == 0) {
5695 // The immediate encoded in the instruction is not in the expected format.
5696 Format(instr, "unallocated", "(SVEBitwiseImm)");
5697 return;
5698 }
5699
5700 switch (instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask)) {
5701 case AND_z_zi:
5702 mnemonic = "and";
5703 break;
5704 case EOR_z_zi:
5705 mnemonic = "eor";
5706 break;
5707 case ORR_z_zi:
5708 mnemonic = "orr";
5709 break;
5710 default:
5711 break;
5712 }
5713 Format(instr, mnemonic, form);
5714 }
5715
VisitSVEBitwiseLogical_Predicated(const Instruction * instr)5716 void Disassembler::VisitSVEBitwiseLogical_Predicated(const Instruction *instr) {
5717 const char *mnemonic = "unimplemented";
5718 const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
5719
5720 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
5721 case AND_z_p_zz:
5722 mnemonic = "and";
5723 break;
5724 case BIC_z_p_zz:
5725 mnemonic = "bic";
5726 break;
5727 case EOR_z_p_zz:
5728 mnemonic = "eor";
5729 break;
5730 case ORR_z_p_zz:
5731 mnemonic = "orr";
5732 break;
5733 default:
5734 break;
5735 }
5736 Format(instr, mnemonic, form);
5737 }
5738
VisitSVEBitwiseShiftByImm_Predicated(const Instruction * instr)5739 void Disassembler::VisitSVEBitwiseShiftByImm_Predicated(
5740 const Instruction *instr) {
5741 const char *mnemonic = "unimplemented";
5742 const char *form = "'Zd.'tszp, 'Pgl/m, 'Zd.'tszp, 'ITriSveq";
5743 unsigned tsize = (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(9, 8);
5744
5745 if (tsize == 0) {
5746 form = "(SVEBitwiseShiftByImm_Predicated)";
5747 } else {
5748 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
5749 case ASRD_z_p_zi:
5750 mnemonic = "asrd";
5751 break;
5752 case ASR_z_p_zi:
5753 mnemonic = "asr";
5754 break;
5755 case LSL_z_p_zi:
5756 mnemonic = "lsl";
5757 form = "'Zd.'tszp, p'u1210/m, 'Zd.'tszp, 'ITriSvep";
5758 break;
5759 case LSR_z_p_zi:
5760 mnemonic = "lsr";
5761 break;
5762 default:
5763 break;
5764 }
5765 }
5766 Format(instr, mnemonic, form);
5767 }
5768
VisitSVEBitwiseShiftByVector_Predicated(const Instruction * instr)5769 void Disassembler::VisitSVEBitwiseShiftByVector_Predicated(
5770 const Instruction *instr) {
5771 const char *mnemonic = "unimplemented";
5772 const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
5773
5774 switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
5775 case ASRR_z_p_zz:
5776 mnemonic = "asrr";
5777 break;
5778 case ASR_z_p_zz:
5779 mnemonic = "asr";
5780 break;
5781 case LSLR_z_p_zz:
5782 mnemonic = "lslr";
5783 break;
5784 case LSL_z_p_zz:
5785 mnemonic = "lsl";
5786 break;
5787 case LSRR_z_p_zz:
5788 mnemonic = "lsrr";
5789 break;
5790 case LSR_z_p_zz:
5791 mnemonic = "lsr";
5792 break;
5793 default:
5794 form = "(SVEBitwiseShiftByVector_Predicated)";
5795 break;
5796 }
5797 Format(instr, mnemonic, form);
5798 }
5799
VisitSVEBitwiseShiftByWideElements_Predicated(const Instruction * instr)5800 void Disassembler::VisitSVEBitwiseShiftByWideElements_Predicated(
5801 const Instruction *instr) {
5802 const char *mnemonic = "unimplemented";
5803 const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.d";
5804
5805 if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
5806 form = "(SVEBitwiseShiftByWideElements_Predicated)";
5807 } else {
5808 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
5809 case ASR_z_p_zw:
5810 mnemonic = "asr";
5811 break;
5812 case LSL_z_p_zw:
5813 mnemonic = "lsl";
5814 break;
5815 case LSR_z_p_zw:
5816 mnemonic = "lsr";
5817 break;
5818 default:
5819 form = "(SVEBitwiseShiftByWideElements_Predicated)";
5820 break;
5821 }
5822 }
5823 Format(instr, mnemonic, form);
5824 }
5825
SVEMoveMaskPreferred(uint64_t value,int lane_bytes_log2)5826 static bool SVEMoveMaskPreferred(uint64_t value, int lane_bytes_log2) {
5827 VIXL_ASSERT(IsUintN(8 << lane_bytes_log2, value));
5828
5829 // Duplicate lane-sized value across double word.
5830 switch (lane_bytes_log2) {
5831 case 0:
5832 value *= 0x0101010101010101;
5833 break;
5834 case 1:
5835 value *= 0x0001000100010001;
5836 break;
5837 case 2:
5838 value *= 0x0000000100000001;
5839 break;
5840 case 3: // Nothing to do
5841 break;
5842 default:
5843 VIXL_UNREACHABLE();
5844 }
5845
5846 if ((value & 0xff) == 0) {
5847 // Check for 16-bit patterns. Set least-significant 16 bits, to make tests
5848 // easier; we already checked least-significant byte is zero above.
5849 uint64_t generic_value = value | 0xffff;
5850
5851 // Check 0x00000000_0000pq00 or 0xffffffff_ffffpq00.
5852 if ((generic_value == 0xffff) || (generic_value == UINT64_MAX)) {
5853 return false;
5854 }
5855
5856 // Check 0x0000pq00_0000pq00 or 0xffffpq00_ffffpq00.
5857 uint64_t rotvalue = RotateRight(value, 32, 64);
5858 if (value == rotvalue) {
5859 generic_value &= 0xffffffff;
5860 if ((generic_value == 0xffff) || (generic_value == UINT32_MAX)) {
5861 return false;
5862 }
5863 }
5864
5865 // Check 0xpq00pq00_pq00pq00.
5866 rotvalue = RotateRight(value, 16, 64);
5867 if (value == rotvalue) {
5868 return false;
5869 }
5870 } else {
5871 // Check for 8-bit patterns. Set least-significant byte, to make tests
5872 // easier.
5873 uint64_t generic_value = value | 0xff;
5874
5875 // Check 0x00000000_000000pq or 0xffffffff_ffffffpq.
5876 if ((generic_value == 0xff) || (generic_value == UINT64_MAX)) {
5877 return false;
5878 }
5879
5880 // Check 0x000000pq_000000pq or 0xffffffpq_ffffffpq.
5881 uint64_t rotvalue = RotateRight(value, 32, 64);
5882 if (value == rotvalue) {
5883 generic_value &= 0xffffffff;
5884 if ((generic_value == 0xff) || (generic_value == UINT32_MAX)) {
5885 return false;
5886 }
5887 }
5888
5889 // Check 0x00pq00pq_00pq00pq or 0xffpqffpq_ffpqffpq.
5890 rotvalue = RotateRight(value, 16, 64);
5891 if (value == rotvalue) {
5892 generic_value &= 0xffff;
5893 if ((generic_value == 0xff) || (generic_value == UINT16_MAX)) {
5894 return false;
5895 }
5896 }
5897
5898 // Check 0xpqpqpqpq_pqpqpqpq.
5899 rotvalue = RotateRight(value, 8, 64);
5900 if (value == rotvalue) {
5901 return false;
5902 }
5903 }
5904 return true;
5905 }
5906
VisitSVEBroadcastBitmaskImm(const Instruction * instr)5907 void Disassembler::VisitSVEBroadcastBitmaskImm(const Instruction *instr) {
5908 const char *mnemonic = "unimplemented";
5909 const char *form = "(SVEBroadcastBitmaskImm)";
5910
5911 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
5912 case DUPM_z_i: {
5913 uint64_t imm = instr->GetSVEImmLogical();
5914 if (imm != 0) {
5915 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
5916 mnemonic = SVEMoveMaskPreferred(imm, lane_size) ? "mov" : "dupm";
5917 form = "'Zd.'tl, 'ITriSvel";
5918 }
5919 break;
5920 }
5921 default:
5922 break;
5923 }
5924 Format(instr, mnemonic, form);
5925 }
5926
VisitSVEBroadcastFPImm_Unpredicated(const Instruction * instr)5927 void Disassembler::VisitSVEBroadcastFPImm_Unpredicated(
5928 const Instruction *instr) {
5929 const char *mnemonic = "unimplemented";
5930 const char *form = "(SVEBroadcastFPImm_Unpredicated)";
5931
5932 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
5933 case FDUP_z_i:
5934 // The preferred disassembly for fdup is "fmov".
5935 mnemonic = "fmov";
5936 form = "'Zd.'t, 'IFPSve";
5937 break;
5938 default:
5939 break;
5940 }
5941 Format(instr, mnemonic, form);
5942 }
5943
VisitSVEBroadcastGeneralRegister(const Instruction * instr)5944 void Disassembler::VisitSVEBroadcastGeneralRegister(const Instruction *instr) {
5945 const char *mnemonic = "unimplemented";
5946 const char *form = "(SVEBroadcastGeneralRegister)";
5947
5948 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
5949 case DUP_z_r:
5950 // The preferred disassembly for dup is "mov".
5951 mnemonic = "mov";
5952 if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
5953 form = "'Zd.'t, 'Xns";
5954 } else {
5955 form = "'Zd.'t, 'Wns";
5956 }
5957 break;
5958 default:
5959 break;
5960 }
5961 Format(instr, mnemonic, form);
5962 }
5963
VisitSVEBroadcastIndexElement(const Instruction * instr)5964 void Disassembler::VisitSVEBroadcastIndexElement(const Instruction *instr) {
5965 const char *mnemonic = "unimplemented";
5966 const char *form = "(SVEBroadcastIndexElement)";
5967
5968 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
5969 case DUP_z_zi: {
5970 // The tsz field must not be zero.
5971 int tsz = instr->ExtractBits(20, 16);
5972 if (tsz != 0) {
5973 // The preferred disassembly for dup is "mov".
5974 mnemonic = "mov";
5975 int imm2 = instr->ExtractBits(23, 22);
5976 if ((CountSetBits(imm2) + CountSetBits(tsz)) == 1) {
5977 // If imm2:tsz has one set bit, the index is zero. This is
5978 // disassembled as a mov from a b/h/s/d/q scalar register.
5979 form = "'Zd.'tszx, 'tszx'u0905";
5980 } else {
5981 form = "'Zd.'tszx, 'Zn.'tszx['IVInsSVEIndex]";
5982 }
5983 }
5984 break;
5985 }
5986 default:
5987 break;
5988 }
5989 Format(instr, mnemonic, form);
5990 }
5991
VisitSVEBroadcastIntImm_Unpredicated(const Instruction * instr)5992 void Disassembler::VisitSVEBroadcastIntImm_Unpredicated(
5993 const Instruction *instr) {
5994 const char *mnemonic = "unimplemented";
5995 const char *form = "(SVEBroadcastIntImm_Unpredicated)";
5996
5997 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
5998 case DUP_z_i:
5999 // The encoding of byte-sized lanes with lsl #8 is undefined.
6000 if ((instr->GetSVEVectorFormat() == kFormatVnB) &&
6001 (instr->ExtractBit(13) == 1))
6002 break;
6003
6004 // The preferred disassembly for dup is "mov".
6005 mnemonic = "mov";
6006 form = (instr->ExtractBit(13) == 0) ? "'Zd.'t, #'s1205"
6007 : "'Zd.'t, #'s1205, lsl #8";
6008 break;
6009 default:
6010 break;
6011 }
6012 Format(instr, mnemonic, form);
6013 }
6014
VisitSVECompressActiveElements(const Instruction * instr)6015 void Disassembler::VisitSVECompressActiveElements(const Instruction *instr) {
6016 const char *mnemonic = "unimplemented";
6017 const char *form = "(SVECompressActiveElements)";
6018
6019 switch (instr->Mask(SVECompressActiveElementsMask)) {
6020 case COMPACT_z_p_z:
6021 // The top bit of size is always set for compact, so 't can only be
6022 // substituted with types S and D.
6023 VIXL_ASSERT(instr->ExtractBit(23) == 1);
6024 mnemonic = "compact";
6025 form = "'Zd.'t, 'Pgl, 'Zn.'t";
6026 break;
6027 default:
6028 break;
6029 }
6030 Format(instr, mnemonic, form);
6031 }
6032
VisitSVEConditionallyBroadcastElementToVector(const Instruction * instr)6033 void Disassembler::VisitSVEConditionallyBroadcastElementToVector(
6034 const Instruction *instr) {
6035 const char *mnemonic = "unimplemented";
6036 const char *form = "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t";
6037
6038 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
6039 case CLASTA_z_p_zz:
6040 mnemonic = "clasta";
6041 break;
6042 case CLASTB_z_p_zz:
6043 mnemonic = "clastb";
6044 break;
6045 default:
6046 break;
6047 }
6048 Format(instr, mnemonic, form);
6049 }
6050
VisitSVEConditionallyExtractElementToGeneralRegister(const Instruction * instr)6051 void Disassembler::VisitSVEConditionallyExtractElementToGeneralRegister(
6052 const Instruction *instr) {
6053 const char *mnemonic = "unimplemented";
6054 const char *form = "'Wd, 'Pgl, 'Wd, 'Zn.'t";
6055
6056 if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
6057 form = "'Xd, p'u1210, 'Xd, 'Zn.'t";
6058 }
6059
6060 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
6061 case CLASTA_r_p_z:
6062 mnemonic = "clasta";
6063 break;
6064 case CLASTB_r_p_z:
6065 mnemonic = "clastb";
6066 break;
6067 default:
6068 break;
6069 }
6070 Format(instr, mnemonic, form);
6071 }
6072
VisitSVEConditionallyExtractElementToSIMDFPScalar(const Instruction * instr)6073 void Disassembler::VisitSVEConditionallyExtractElementToSIMDFPScalar(
6074 const Instruction *instr) {
6075 const char *mnemonic = "unimplemented";
6076 const char *form = "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t";
6077
6078 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
6079 case CLASTA_v_p_z:
6080 mnemonic = "clasta";
6081 break;
6082 case CLASTB_v_p_z:
6083 mnemonic = "clastb";
6084 break;
6085 default:
6086 break;
6087 }
6088 Format(instr, mnemonic, form);
6089 }
6090
VisitSVEConditionallyTerminateScalars(const Instruction * instr)6091 void Disassembler::VisitSVEConditionallyTerminateScalars(
6092 const Instruction *instr) {
6093 const char *mnemonic = "unimplemented";
6094 const char *form = (instr->ExtractBit(22) == 0) ? "'Wn, 'Wm" : "'Xn, 'Xm";
6095
6096 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
6097 case CTERMEQ_rr:
6098 mnemonic = "ctermeq";
6099 break;
6100 case CTERMNE_rr:
6101 mnemonic = "ctermne";
6102 break;
6103 default:
6104 break;
6105 }
6106 Format(instr, mnemonic, form);
6107 }
6108
VisitSVEConstructivePrefix_Unpredicated(const Instruction * instr)6109 void Disassembler::VisitSVEConstructivePrefix_Unpredicated(
6110 const Instruction *instr) {
6111 const char *mnemonic = "unimplemented";
6112 const char *form = "(SVEConstructivePrefix_Unpredicated)";
6113
6114 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
6115 case MOVPRFX_z_z:
6116 mnemonic = "movprfx";
6117 form = "'Zd, 'Zn";
6118 break;
6119 default:
6120 break;
6121 }
6122 Format(instr, mnemonic, form);
6123 }
6124
VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(const Instruction * instr)6125 void Disassembler::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
6126 const Instruction *instr) {
6127 const char *mnemonic = "unimplemented";
6128
6129 bool rm_is_zr = instr->GetRm() == kZeroRegCode;
6130
6131 const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
6132 const char *suffix = NULL;
6133
6134 switch (instr->Mask(SVEContiguousFirstFaultLoad_ScalarPlusScalarMask)) {
6135 case LDFF1B_z_p_br_u16:
6136 case LDFF1B_z_p_br_u32:
6137 case LDFF1B_z_p_br_u64:
6138 case LDFF1B_z_p_br_u8:
6139 mnemonic = "ldff1b";
6140 suffix = rm_is_zr ? "]" : ", 'Xm]";
6141 break;
6142 case LDFF1D_z_p_br_u64:
6143 mnemonic = "ldff1d";
6144 suffix = rm_is_zr ? "]" : ", 'Xm, lsl #3]";
6145 break;
6146 case LDFF1H_z_p_br_u16:
6147 case LDFF1H_z_p_br_u32:
6148 case LDFF1H_z_p_br_u64:
6149 mnemonic = "ldff1h";
6150 suffix = rm_is_zr ? "]" : ", 'Xm, lsl #1]";
6151 break;
6152 case LDFF1SB_z_p_br_s16:
6153 case LDFF1SB_z_p_br_s32:
6154 case LDFF1SB_z_p_br_s64:
6155 mnemonic = "ldff1sb";
6156 suffix = rm_is_zr ? "]" : ", 'Xm]";
6157 break;
6158 case LDFF1SH_z_p_br_s32:
6159 case LDFF1SH_z_p_br_s64:
6160 mnemonic = "ldff1sh";
6161 suffix = rm_is_zr ? "]" : ", 'Xm, lsl #1]";
6162 break;
6163 case LDFF1SW_z_p_br_s64:
6164 mnemonic = "ldff1sw";
6165 suffix = rm_is_zr ? "]" : ", 'Xm, lsl #2]";
6166 break;
6167 case LDFF1W_z_p_br_u32:
6168 case LDFF1W_z_p_br_u64:
6169 mnemonic = "ldff1w";
6170 suffix = rm_is_zr ? "]" : ", 'Xm, lsl #2]";
6171 break;
6172 default:
6173 form = "(SVEContiguousFirstFaultLoad_ScalarPlusScalar)";
6174 break;
6175 }
6176
6177 Format(instr, mnemonic, form, suffix);
6178 }
6179
VisitSVEContiguousNonFaultLoad_ScalarPlusImm(const Instruction * instr)6180 void Disassembler::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
6181 const Instruction *instr) {
6182 const char *mnemonic = "unimplemented";
6183 const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
6184 const char *suffix =
6185 (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
6186
6187 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
6188 case LDNF1B_z_p_bi_u16:
6189 case LDNF1B_z_p_bi_u32:
6190 case LDNF1B_z_p_bi_u64:
6191 case LDNF1B_z_p_bi_u8:
6192 mnemonic = "ldnf1b";
6193 break;
6194 case LDNF1D_z_p_bi_u64:
6195 mnemonic = "ldnf1d";
6196 break;
6197 case LDNF1H_z_p_bi_u16:
6198 case LDNF1H_z_p_bi_u32:
6199 case LDNF1H_z_p_bi_u64:
6200 mnemonic = "ldnf1h";
6201 break;
6202 case LDNF1SB_z_p_bi_s16:
6203 case LDNF1SB_z_p_bi_s32:
6204 case LDNF1SB_z_p_bi_s64:
6205 mnemonic = "ldnf1sb";
6206 break;
6207 case LDNF1SH_z_p_bi_s32:
6208 case LDNF1SH_z_p_bi_s64:
6209 mnemonic = "ldnf1sh";
6210 break;
6211 case LDNF1SW_z_p_bi_s64:
6212 mnemonic = "ldnf1sw";
6213 break;
6214 case LDNF1W_z_p_bi_u32:
6215 case LDNF1W_z_p_bi_u64:
6216 mnemonic = "ldnf1w";
6217 break;
6218 default:
6219 form = "(SVEContiguousNonFaultLoad_ScalarPlusImm)";
6220 suffix = NULL;
6221 break;
6222 }
6223 Format(instr, mnemonic, form, suffix);
6224 }
6225
VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(const Instruction * instr)6226 void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
6227 const Instruction *instr) {
6228 const char *mnemonic = "unimplemented";
6229 const char *form = "(SVEContiguousNonTemporalLoad_ScalarPlusImm)";
6230
6231 const char *suffix =
6232 (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
6233 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
6234 case LDNT1B_z_p_bi_contiguous:
6235 mnemonic = "ldnt1b";
6236 form = "{'Zt.b}, 'Pgl/z, ['Xns";
6237 break;
6238 case LDNT1D_z_p_bi_contiguous:
6239 mnemonic = "ldnt1d";
6240 form = "{'Zt.d}, 'Pgl/z, ['Xns";
6241 break;
6242 case LDNT1H_z_p_bi_contiguous:
6243 mnemonic = "ldnt1h";
6244 form = "{'Zt.h}, 'Pgl/z, ['Xns";
6245 break;
6246 case LDNT1W_z_p_bi_contiguous:
6247 mnemonic = "ldnt1w";
6248 form = "{'Zt.s}, 'Pgl/z, ['Xns";
6249 break;
6250 default:
6251 suffix = NULL;
6252 break;
6253 }
6254 Format(instr, mnemonic, form, suffix);
6255 }
6256
VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(const Instruction * instr)6257 void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
6258 const Instruction *instr) {
6259 const char *mnemonic = "unimplemented";
6260 const char *form = "(SVEContiguousNonTemporalLoad_ScalarPlusScalar)";
6261
6262 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
6263 case LDNT1B_z_p_br_contiguous:
6264 mnemonic = "ldnt1b";
6265 form = "{'Zt.b}, 'Pgl/z, ['Xns, 'Rm]";
6266 break;
6267 case LDNT1D_z_p_br_contiguous:
6268 mnemonic = "ldnt1d";
6269 form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Rm, lsl #3]";
6270 break;
6271 case LDNT1H_z_p_br_contiguous:
6272 mnemonic = "ldnt1h";
6273 form = "{'Zt.h}, 'Pgl/z, ['Xns, 'Rm, lsl #1]";
6274 break;
6275 case LDNT1W_z_p_br_contiguous:
6276 mnemonic = "ldnt1w";
6277 form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Rm, lsl #2]";
6278 break;
6279 default:
6280 break;
6281 }
6282 Format(instr, mnemonic, form);
6283 }
6284
VisitSVEContiguousNonTemporalStore_ScalarPlusImm(const Instruction * instr)6285 void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
6286 const Instruction *instr) {
6287 const char *mnemonic = "unimplemented";
6288 const char *form = "(SVEContiguousNonTemporalStore_ScalarPlusImm)";
6289
6290 const char *suffix =
6291 (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
6292 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
6293 case STNT1B_z_p_bi_contiguous:
6294 mnemonic = "stnt1b";
6295 form = "{'Zt.b}, 'Pgl, ['Xns";
6296 break;
6297 case STNT1D_z_p_bi_contiguous:
6298 mnemonic = "stnt1d";
6299 form = "{'Zt.d}, 'Pgl, ['Xns";
6300 break;
6301 case STNT1H_z_p_bi_contiguous:
6302 mnemonic = "stnt1h";
6303 form = "{'Zt.h}, 'Pgl, ['Xns";
6304 break;
6305 case STNT1W_z_p_bi_contiguous:
6306 mnemonic = "stnt1w";
6307 form = "{'Zt.s}, 'Pgl, ['Xns";
6308 break;
6309 default:
6310 suffix = NULL;
6311 break;
6312 }
6313 Format(instr, mnemonic, form, suffix);
6314 }
6315
VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(const Instruction * instr)6316 void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
6317 const Instruction *instr) {
6318 const char *mnemonic = "unimplemented";
6319 const char *form = "(SVEContiguousNonTemporalStore_ScalarPlusScalar)";
6320
6321 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
6322 case STNT1B_z_p_br_contiguous:
6323 mnemonic = "stnt1b";
6324 form = "{'Zt.b}, 'Pgl, ['Xns, 'Rm]";
6325 break;
6326 case STNT1D_z_p_br_contiguous:
6327 mnemonic = "stnt1d";
6328 form = "{'Zt.d}, 'Pgl, ['Xns, 'Rm, lsl #3]";
6329 break;
6330 case STNT1H_z_p_br_contiguous:
6331 mnemonic = "stnt1h";
6332 form = "{'Zt.h}, 'Pgl, ['Xns, 'Rm, lsl #1]";
6333 break;
6334 case STNT1W_z_p_br_contiguous:
6335 mnemonic = "stnt1w";
6336 form = "{'Zt.s}, 'Pgl, ['Xns, 'Rm, lsl #2]";
6337 break;
6338 default:
6339 break;
6340 }
6341 Format(instr, mnemonic, form);
6342 }
6343
VisitSVEContiguousPrefetch_ScalarPlusImm(const Instruction * instr)6344 void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusImm(
6345 const Instruction *instr) {
6346 const char *mnemonic = "unimplemented";
6347 const char *form = (instr->ExtractBits(21, 16) != 0)
6348 ? "'prefSVEOp, 'Pgl, ['Xns, #'s2116, mul vl]"
6349 : "'prefSVEOp, 'Pgl, ['Xns]";
6350
6351 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
6352 case PRFB_i_p_bi_s:
6353 mnemonic = "prfb";
6354 break;
6355 case PRFD_i_p_bi_s:
6356 mnemonic = "prfd";
6357 break;
6358 case PRFH_i_p_bi_s:
6359 mnemonic = "prfh";
6360 break;
6361 case PRFW_i_p_bi_s:
6362 mnemonic = "prfw";
6363 break;
6364 default:
6365 break;
6366 }
6367 Format(instr, mnemonic, form);
6368 }
6369
VisitSVEContiguousPrefetch_ScalarPlusScalar(const Instruction * instr)6370 void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusScalar(
6371 const Instruction *instr) {
6372 const char *mnemonic = "unimplemented";
6373 const char *form = "(SVEContiguousPrefetch_ScalarPlusScalar)";
6374
6375 if (instr->GetRm() != kZeroRegCode) {
6376 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
6377 case PRFB_i_p_br_s:
6378 mnemonic = "prfb";
6379 form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm]";
6380 break;
6381 case PRFD_i_p_br_s:
6382 mnemonic = "prfd";
6383 form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #3]";
6384 break;
6385 case PRFH_i_p_br_s:
6386 mnemonic = "prfh";
6387 form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #1]";
6388 break;
6389 case PRFW_i_p_br_s:
6390 mnemonic = "prfw";
6391 form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #2]";
6392 break;
6393 default:
6394 break;
6395 }
6396 }
6397 Format(instr, mnemonic, form);
6398 }
6399
VisitSVEContiguousStore_ScalarPlusImm(const Instruction * instr)6400 void Disassembler::VisitSVEContiguousStore_ScalarPlusImm(
6401 const Instruction *instr) {
6402 const char *mnemonic = "unimplemented";
6403
6404 // The 'size' field isn't in the usual place here.
6405 const char *form = "{'Zt.'tls}, 'Pgl, ['Xns, #'s1916, mul vl]";
6406 if (instr->ExtractBits(19, 16) == 0) {
6407 form = "{'Zt.'tls}, 'Pgl, ['Xns]";
6408 }
6409
6410 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
6411 case ST1B_z_p_bi:
6412 mnemonic = "st1b";
6413 break;
6414 case ST1D_z_p_bi:
6415 mnemonic = "st1d";
6416 break;
6417 case ST1H_z_p_bi:
6418 mnemonic = "st1h";
6419 break;
6420 case ST1W_z_p_bi:
6421 mnemonic = "st1w";
6422 break;
6423 default:
6424 break;
6425 }
6426 Format(instr, mnemonic, form);
6427 }
6428
VisitSVEContiguousStore_ScalarPlusScalar(const Instruction * instr)6429 void Disassembler::VisitSVEContiguousStore_ScalarPlusScalar(
6430 const Instruction *instr) {
6431 const char *mnemonic = "unimplemented";
6432
6433 // The 'size' field isn't in the usual place here.
6434 const char *form = "{'Zt.'tls}, 'Pgl, ['Xns, 'Xm'NSveS]";
6435
6436 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
6437 case ST1B_z_p_br:
6438 mnemonic = "st1b";
6439 break;
6440 case ST1D_z_p_br:
6441 mnemonic = "st1d";
6442 break;
6443 case ST1H_z_p_br:
6444 mnemonic = "st1h";
6445 break;
6446 case ST1W_z_p_br:
6447 mnemonic = "st1w";
6448 break;
6449 default:
6450 break;
6451 }
6452 Format(instr, mnemonic, form);
6453 }
6454
VisitSVECopyFPImm_Predicated(const Instruction * instr)6455 void Disassembler::VisitSVECopyFPImm_Predicated(const Instruction *instr) {
6456 const char *mnemonic = "unimplemented";
6457 const char *form = "(SVECopyFPImm_Predicated)";
6458
6459 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
6460 case FCPY_z_p_i:
6461 // The preferred disassembly for fcpy is "fmov".
6462 mnemonic = "fmov";
6463 form = "'Zd.'t, 'Pm/m, 'IFPSve";
6464 break;
6465 default:
6466 break;
6467 }
6468 Format(instr, mnemonic, form);
6469 }
6470
VisitSVECopyGeneralRegisterToVector_Predicated(const Instruction * instr)6471 void Disassembler::VisitSVECopyGeneralRegisterToVector_Predicated(
6472 const Instruction *instr) {
6473 const char *mnemonic = "unimplemented";
6474 const char *form = "(SVECopyGeneralRegisterToVector_Predicated)";
6475
6476 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
6477 case CPY_z_p_r:
6478 // The preferred disassembly for cpy is "mov".
6479 mnemonic = "mov";
6480 form = "'Zd.'t, 'Pgl/m, 'Wns";
6481 if (instr->GetSVESize() == kXRegSizeInBytesLog2) {
6482 form = "'Zd.'t, 'Pgl/m, 'Xns";
6483 }
6484 break;
6485 default:
6486 break;
6487 }
6488 Format(instr, mnemonic, form);
6489 }
6490
VisitSVECopyIntImm_Predicated(const Instruction * instr)6491 void Disassembler::VisitSVECopyIntImm_Predicated(const Instruction *instr) {
6492 const char *mnemonic = "unimplemented";
6493 const char *form = "(SVECopyIntImm_Predicated)";
6494 const char *suffix = NULL;
6495
6496 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
6497 case CPY_z_p_i: {
6498 // The preferred disassembly for cpy is "mov".
6499 mnemonic = "mov";
6500 form = "'Zd.'t, 'Pm/'?14:mz, #'s1205";
6501 if (instr->ExtractBit(13) != 0) suffix = ", lsl #8";
6502 break;
6503 }
6504 default:
6505 break;
6506 }
6507 Format(instr, mnemonic, form, suffix);
6508 }
6509
VisitSVECopySIMDFPScalarRegisterToVector_Predicated(const Instruction * instr)6510 void Disassembler::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
6511 const Instruction *instr) {
6512 const char *mnemonic = "unimplemented";
6513 const char *form = "(SVECopySIMDFPScalarRegisterToVector_Predicated)";
6514
6515 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
6516 case CPY_z_p_v:
6517 // The preferred disassembly for cpy is "mov".
6518 mnemonic = "mov";
6519 form = "'Zd.'t, 'Pgl/m, 'Vnv";
6520 break;
6521 default:
6522 break;
6523 }
6524 Format(instr, mnemonic, form);
6525 }
6526
VisitSVEExtractElementToGeneralRegister(const Instruction * instr)6527 void Disassembler::VisitSVEExtractElementToGeneralRegister(
6528 const Instruction *instr) {
6529 const char *mnemonic = "unimplemented";
6530 const char *form = "'Wd, 'Pgl, 'Zn.'t";
6531
6532 if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
6533 form = "'Xd, p'u1210, 'Zn.'t";
6534 }
6535
6536 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
6537 case LASTA_r_p_z:
6538 mnemonic = "lasta";
6539 break;
6540 case LASTB_r_p_z:
6541 mnemonic = "lastb";
6542 break;
6543 default:
6544 break;
6545 }
6546 Format(instr, mnemonic, form);
6547 }
6548
VisitSVEExtractElementToSIMDFPScalarRegister(const Instruction * instr)6549 void Disassembler::VisitSVEExtractElementToSIMDFPScalarRegister(
6550 const Instruction *instr) {
6551 const char *mnemonic = "unimplemented";
6552 const char *form = "'t'u0400, 'Pgl, 'Zn.'t";
6553
6554 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
6555 case LASTA_v_p_z:
6556 mnemonic = "lasta";
6557 break;
6558 case LASTB_v_p_z:
6559 mnemonic = "lastb";
6560 break;
6561 default:
6562 break;
6563 }
6564 Format(instr, mnemonic, form);
6565 }
6566
VisitSVEFFRInitialise(const Instruction * instr)6567 void Disassembler::VisitSVEFFRInitialise(const Instruction *instr) {
6568 const char *mnemonic = "unimplemented";
6569 const char *form = "(SVEFFRInitialise)";
6570
6571 switch (instr->Mask(SVEFFRInitialiseMask)) {
6572 case SETFFR_f:
6573 mnemonic = "setffr";
6574 form = " ";
6575 break;
6576 default:
6577 break;
6578 }
6579 Format(instr, mnemonic, form);
6580 }
6581
VisitSVEFFRWriteFromPredicate(const Instruction * instr)6582 void Disassembler::VisitSVEFFRWriteFromPredicate(const Instruction *instr) {
6583 const char *mnemonic = "unimplemented";
6584 const char *form = "(SVEFFRWriteFromPredicate)";
6585
6586 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
6587 case WRFFR_f_p:
6588 mnemonic = "wrffr";
6589 form = "'Pn.b";
6590 break;
6591 default:
6592 break;
6593 }
6594 Format(instr, mnemonic, form);
6595 }
6596
VisitSVEFPArithmeticWithImm_Predicated(const Instruction * instr)6597 void Disassembler::VisitSVEFPArithmeticWithImm_Predicated(
6598 const Instruction *instr) {
6599 const char *mnemonic = "unimplemented";
6600 const char *form00 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #0.0";
6601 const char *form05 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #0.5";
6602 const char *form10 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #1.0";
6603 const char *form20 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #2.0";
6604 int i1 = instr->ExtractBit(5);
6605 const char *form = i1 ? form10 : form00;
6606
6607 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
6608 case FADD_z_p_zs:
6609 mnemonic = "fadd";
6610 form = i1 ? form10 : form05;
6611 break;
6612 case FMAXNM_z_p_zs:
6613 mnemonic = "fmaxnm";
6614 break;
6615 case FMAX_z_p_zs:
6616 mnemonic = "fmax";
6617 break;
6618 case FMINNM_z_p_zs:
6619 mnemonic = "fminnm";
6620 break;
6621 case FMIN_z_p_zs:
6622 mnemonic = "fmin";
6623 break;
6624 case FMUL_z_p_zs:
6625 mnemonic = "fmul";
6626 form = i1 ? form20 : form05;
6627 break;
6628 case FSUBR_z_p_zs:
6629 mnemonic = "fsubr";
6630 form = i1 ? form10 : form05;
6631 break;
6632 case FSUB_z_p_zs:
6633 mnemonic = "fsub";
6634 form = i1 ? form10 : form05;
6635 break;
6636 default:
6637 form = "(SVEFPArithmeticWithImm_Predicated)";
6638 break;
6639 }
6640 Format(instr, mnemonic, form);
6641 }
6642
VisitSVEFPArithmetic_Predicated(const Instruction * instr)6643 void Disassembler::VisitSVEFPArithmetic_Predicated(const Instruction *instr) {
6644 const char *mnemonic = "unimplemented";
6645 const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
6646
6647 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
6648 case FABD_z_p_zz:
6649 mnemonic = "fabd";
6650 break;
6651 case FADD_z_p_zz:
6652 mnemonic = "fadd";
6653 break;
6654 case FDIVR_z_p_zz:
6655 mnemonic = "fdivr";
6656 break;
6657 case FDIV_z_p_zz:
6658 mnemonic = "fdiv";
6659 break;
6660 case FMAXNM_z_p_zz:
6661 mnemonic = "fmaxnm";
6662 break;
6663 case FMAX_z_p_zz:
6664 mnemonic = "fmax";
6665 break;
6666 case FMINNM_z_p_zz:
6667 mnemonic = "fminnm";
6668 break;
6669 case FMIN_z_p_zz:
6670 mnemonic = "fmin";
6671 break;
6672 case FMULX_z_p_zz:
6673 mnemonic = "fmulx";
6674 break;
6675 case FMUL_z_p_zz:
6676 mnemonic = "fmul";
6677 break;
6678 case FSCALE_z_p_zz:
6679 mnemonic = "fscale";
6680 break;
6681 case FSUBR_z_p_zz:
6682 mnemonic = "fsubr";
6683 break;
6684 case FSUB_z_p_zz:
6685 mnemonic = "fsub";
6686 break;
6687 default:
6688 break;
6689 }
6690 Format(instr, mnemonic, form);
6691 }
6692
VisitSVEFPConvertPrecision(const Instruction * instr)6693 void Disassembler::VisitSVEFPConvertPrecision(const Instruction *instr) {
6694 const char *mnemonic = "unimplemented";
6695 const char *form = "(SVEFPConvertPrecision)";
6696
6697 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
6698 case FCVT_z_p_z_d2h:
6699 mnemonic = "fcvt";
6700 form = "'Zd.h, 'Pgl/m, 'Zn.d";
6701 break;
6702 case FCVT_z_p_z_d2s:
6703 mnemonic = "fcvt";
6704 form = "'Zd.s, 'Pgl/m, 'Zn.d";
6705 break;
6706 case FCVT_z_p_z_h2d:
6707 mnemonic = "fcvt";
6708 form = "'Zd.d, 'Pgl/m, 'Zn.h";
6709 break;
6710 case FCVT_z_p_z_h2s:
6711 mnemonic = "fcvt";
6712 form = "'Zd.s, 'Pgl/m, 'Zn.h";
6713 break;
6714 case FCVT_z_p_z_s2d:
6715 mnemonic = "fcvt";
6716 form = "'Zd.d, 'Pgl/m, 'Zn.s";
6717 break;
6718 case FCVT_z_p_z_s2h:
6719 mnemonic = "fcvt";
6720 form = "'Zd.h, 'Pgl/m, 'Zn.s";
6721 break;
6722 default:
6723 break;
6724 }
6725 Format(instr, mnemonic, form);
6726 }
6727
VisitSVEFPConvertToInt(const Instruction * instr)6728 void Disassembler::VisitSVEFPConvertToInt(const Instruction *instr) {
6729 const char *mnemonic = "unimplemented";
6730 const char *form = "(SVEFPConvertToInt)";
6731
6732 switch (instr->Mask(SVEFPConvertToIntMask)) {
6733 case FCVTZS_z_p_z_d2w:
6734 mnemonic = "fcvtzs";
6735 form = "'Zd.s, 'Pgl/m, 'Zn.d";
6736 break;
6737 case FCVTZS_z_p_z_d2x:
6738 mnemonic = "fcvtzs";
6739 form = "'Zd.d, 'Pgl/m, 'Zn.d";
6740 break;
6741 case FCVTZS_z_p_z_fp162h:
6742 mnemonic = "fcvtzs";
6743 form = "'Zd.h, 'Pgl/m, 'Zn.h";
6744 break;
6745 case FCVTZS_z_p_z_fp162w:
6746 mnemonic = "fcvtzs";
6747 form = "'Zd.s, 'Pgl/m, 'Zn.h";
6748 break;
6749 case FCVTZS_z_p_z_fp162x:
6750 mnemonic = "fcvtzs";
6751 form = "'Zd.d, 'Pgl/m, 'Zn.h";
6752 break;
6753 case FCVTZS_z_p_z_s2w:
6754 mnemonic = "fcvtzs";
6755 form = "'Zd.s, 'Pgl/m, 'Zn.s";
6756 break;
6757 case FCVTZS_z_p_z_s2x:
6758 mnemonic = "fcvtzs";
6759 form = "'Zd.d, 'Pgl/m, 'Zn.s";
6760 break;
6761 case FCVTZU_z_p_z_d2w:
6762 mnemonic = "fcvtzu";
6763 form = "'Zd.s, 'Pgl/m, 'Zn.d";
6764 break;
6765 case FCVTZU_z_p_z_d2x:
6766 mnemonic = "fcvtzu";
6767 form = "'Zd.d, 'Pgl/m, 'Zn.d";
6768 break;
6769 case FCVTZU_z_p_z_fp162h:
6770 mnemonic = "fcvtzu";
6771 form = "'Zd.h, 'Pgl/m, 'Zn.h";
6772 break;
6773 case FCVTZU_z_p_z_fp162w:
6774 mnemonic = "fcvtzu";
6775 form = "'Zd.s, 'Pgl/m, 'Zn.h";
6776 break;
6777 case FCVTZU_z_p_z_fp162x:
6778 mnemonic = "fcvtzu";
6779 form = "'Zd.d, 'Pgl/m, 'Zn.h";
6780 break;
6781 case FCVTZU_z_p_z_s2w:
6782 mnemonic = "fcvtzu";
6783 form = "'Zd.s, 'Pgl/m, 'Zn.s";
6784 break;
6785 case FCVTZU_z_p_z_s2x:
6786 mnemonic = "fcvtzu";
6787 form = "'Zd.d, 'Pgl/m, 'Zn.s";
6788 break;
6789 default:
6790 break;
6791 }
6792 Format(instr, mnemonic, form);
6793 }
6794
VisitSVEFPExponentialAccelerator(const Instruction * instr)6795 void Disassembler::VisitSVEFPExponentialAccelerator(const Instruction *instr) {
6796 const char *mnemonic = "unimplemented";
6797 const char *form = "(SVEFPExponentialAccelerator)";
6798
6799 unsigned size = instr->GetSVESize();
6800 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
6801 case FEXPA_z_z:
6802 if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6803 (size == kDRegSizeInBytesLog2)) {
6804 mnemonic = "fexpa";
6805 form = "'Zd.'t, 'Zn.'t";
6806 }
6807 break;
6808 default:
6809 break;
6810 }
6811 Format(instr, mnemonic, form);
6812 }
6813
VisitSVEFPRoundToIntegralValue(const Instruction * instr)6814 void Disassembler::VisitSVEFPRoundToIntegralValue(const Instruction *instr) {
6815 const char *mnemonic = "unimplemented";
6816 const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
6817
6818 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
6819 case FRINTA_z_p_z:
6820 mnemonic = "frinta";
6821 break;
6822 case FRINTI_z_p_z:
6823 mnemonic = "frinti";
6824 break;
6825 case FRINTM_z_p_z:
6826 mnemonic = "frintm";
6827 break;
6828 case FRINTN_z_p_z:
6829 mnemonic = "frintn";
6830 break;
6831 case FRINTP_z_p_z:
6832 mnemonic = "frintp";
6833 break;
6834 case FRINTX_z_p_z:
6835 mnemonic = "frintx";
6836 break;
6837 case FRINTZ_z_p_z:
6838 mnemonic = "frintz";
6839 break;
6840 default:
6841 break;
6842 }
6843 Format(instr, mnemonic, form);
6844 }
6845
VisitSVEFPTrigMulAddCoefficient(const Instruction * instr)6846 void Disassembler::VisitSVEFPTrigMulAddCoefficient(const Instruction *instr) {
6847 const char *mnemonic = "unimplemented";
6848 const char *form = "(SVEFPTrigMulAddCoefficient)";
6849
6850 unsigned size = instr->GetSVESize();
6851 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
6852 case FTMAD_z_zzi:
6853 if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6854 (size == kDRegSizeInBytesLog2)) {
6855 mnemonic = "ftmad";
6856 form = "'Zd.'t, 'Zd.'t, 'Zn.'t, #'u1816";
6857 }
6858 break;
6859 default:
6860 break;
6861 }
6862 Format(instr, mnemonic, form);
6863 }
6864
VisitSVEFPTrigSelectCoefficient(const Instruction * instr)6865 void Disassembler::VisitSVEFPTrigSelectCoefficient(const Instruction *instr) {
6866 const char *mnemonic = "unimplemented";
6867 const char *form = "(SVEFPTrigSelectCoefficient)";
6868
6869 unsigned size = instr->GetSVESize();
6870 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
6871 case FTSSEL_z_zz:
6872 if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6873 (size == kDRegSizeInBytesLog2)) {
6874 mnemonic = "ftssel";
6875 form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
6876 }
6877 break;
6878 default:
6879 break;
6880 }
6881 Format(instr, mnemonic, form);
6882 }
6883
VisitSVEFPUnaryOp(const Instruction * instr)6884 void Disassembler::VisitSVEFPUnaryOp(const Instruction *instr) {
6885 const char *mnemonic = "unimplemented";
6886 const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
6887
6888 if (instr->GetSVESize() == kBRegSizeInBytesLog2) {
6889 form = "(SVEFPUnaryOp)";
6890 } else {
6891 switch (instr->Mask(SVEFPUnaryOpMask)) {
6892 case FRECPX_z_p_z:
6893 mnemonic = "frecpx";
6894 break;
6895 case FSQRT_z_p_z:
6896 mnemonic = "fsqrt";
6897 break;
6898 default:
6899 form = "(SVEFPUnaryOp)";
6900 break;
6901 }
6902 }
6903 Format(instr, mnemonic, form);
6904 }
6905
IncDecFormHelper(const Instruction * instr,const char * reg_pat_mul_form,const char * reg_pat_form,const char * reg_form)6906 static const char *IncDecFormHelper(const Instruction *instr,
6907 const char *reg_pat_mul_form,
6908 const char *reg_pat_form,
6909 const char *reg_form) {
6910 if (instr->ExtractBits(19, 16) == 0) {
6911 if (instr->ExtractBits(9, 5) == SVE_ALL) {
6912 // Use the register only form if the multiplier is one (encoded as zero)
6913 // and the pattern is SVE_ALL.
6914 return reg_form;
6915 }
6916 // Use the register and pattern form if the multiplier is one.
6917 return reg_pat_form;
6918 }
6919 return reg_pat_mul_form;
6920 }
6921
VisitSVEIncDecRegisterByElementCount(const Instruction * instr)6922 void Disassembler::VisitSVEIncDecRegisterByElementCount(
6923 const Instruction *instr) {
6924 const char *mnemonic = "unimplemented";
6925 const char *form =
6926 IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd");
6927
6928 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
6929 case DECB_r_rs:
6930 mnemonic = "decb";
6931 break;
6932 case DECD_r_rs:
6933 mnemonic = "decd";
6934 break;
6935 case DECH_r_rs:
6936 mnemonic = "dech";
6937 break;
6938 case DECW_r_rs:
6939 mnemonic = "decw";
6940 break;
6941 case INCB_r_rs:
6942 mnemonic = "incb";
6943 break;
6944 case INCD_r_rs:
6945 mnemonic = "incd";
6946 break;
6947 case INCH_r_rs:
6948 mnemonic = "inch";
6949 break;
6950 case INCW_r_rs:
6951 mnemonic = "incw";
6952 break;
6953 default:
6954 form = "(SVEIncDecRegisterByElementCount)";
6955 break;
6956 }
6957 Format(instr, mnemonic, form);
6958 }
6959
VisitSVEIncDecVectorByElementCount(const Instruction * instr)6960 void Disassembler::VisitSVEIncDecVectorByElementCount(
6961 const Instruction *instr) {
6962 const char *mnemonic = "unimplemented";
6963 const char *form = IncDecFormHelper(instr,
6964 "'Zd.'t, 'Ipc, mul #'u1916+1",
6965 "'Zd.'t, 'Ipc",
6966 "'Zd.'t");
6967
6968 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
6969 case DECD_z_zs:
6970 mnemonic = "decd";
6971 break;
6972 case DECH_z_zs:
6973 mnemonic = "dech";
6974 break;
6975 case DECW_z_zs:
6976 mnemonic = "decw";
6977 break;
6978 case INCD_z_zs:
6979 mnemonic = "incd";
6980 break;
6981 case INCH_z_zs:
6982 mnemonic = "inch";
6983 break;
6984 case INCW_z_zs:
6985 mnemonic = "incw";
6986 break;
6987 default:
6988 form = "(SVEIncDecVectorByElementCount)";
6989 break;
6990 }
6991 Format(instr, mnemonic, form);
6992 }
6993
VisitSVEInsertGeneralRegister(const Instruction * instr)6994 void Disassembler::VisitSVEInsertGeneralRegister(const Instruction *instr) {
6995 const char *mnemonic = "unimplemented";
6996 const char *form = "(SVEInsertGeneralRegister)";
6997
6998 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
6999 case INSR_z_r:
7000 mnemonic = "insr";
7001 if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
7002 form = "'Zd.'t, 'Xn";
7003 } else {
7004 form = "'Zd.'t, 'Wn";
7005 }
7006 break;
7007 default:
7008 break;
7009 }
7010 Format(instr, mnemonic, form);
7011 }
7012
VisitSVEInsertSIMDFPScalarRegister(const Instruction * instr)7013 void Disassembler::VisitSVEInsertSIMDFPScalarRegister(
7014 const Instruction *instr) {
7015 const char *mnemonic = "unimplemented";
7016 const char *form = "(SVEInsertSIMDFPScalarRegister)";
7017
7018 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
7019 case INSR_z_v:
7020 mnemonic = "insr";
7021 form = "'Zd.'t, 'Vnv";
7022 break;
7023 default:
7024 break;
7025 }
7026 Format(instr, mnemonic, form);
7027 }
7028
VisitSVEIntAddSubtractImm_Unpredicated(const Instruction * instr)7029 void Disassembler::VisitSVEIntAddSubtractImm_Unpredicated(
7030 const Instruction *instr) {
7031 const char *mnemonic = "unimplemented";
7032 const char *form = (instr->ExtractBit(13) == 0)
7033 ? "'Zd.'t, 'Zd.'t, #'u1205"
7034 : "'Zd.'t, 'Zd.'t, #'u1205, lsl #8";
7035
7036 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
7037 case ADD_z_zi:
7038 mnemonic = "add";
7039 break;
7040 case SQADD_z_zi:
7041 mnemonic = "sqadd";
7042 break;
7043 case SQSUB_z_zi:
7044 mnemonic = "sqsub";
7045 break;
7046 case SUBR_z_zi:
7047 mnemonic = "subr";
7048 break;
7049 case SUB_z_zi:
7050 mnemonic = "sub";
7051 break;
7052 case UQADD_z_zi:
7053 mnemonic = "uqadd";
7054 break;
7055 case UQSUB_z_zi:
7056 mnemonic = "uqsub";
7057 break;
7058 default:
7059 form = "(SVEIntAddSubtractImm_Unpredicated)";
7060 break;
7061 }
7062 Format(instr, mnemonic, form);
7063 }
7064
VisitSVEIntAddSubtractVectors_Predicated(const Instruction * instr)7065 void Disassembler::VisitSVEIntAddSubtractVectors_Predicated(
7066 const Instruction *instr) {
7067 const char *mnemonic = "unimplemented";
7068 const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
7069
7070 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
7071 case ADD_z_p_zz:
7072 mnemonic = "add";
7073 break;
7074 case SUBR_z_p_zz:
7075 mnemonic = "subr";
7076 break;
7077 case SUB_z_p_zz:
7078 mnemonic = "sub";
7079 break;
7080 default:
7081 break;
7082 }
7083 Format(instr, mnemonic, form);
7084 }
7085
VisitSVEIntCompareScalarCountAndLimit(const Instruction * instr)7086 void Disassembler::VisitSVEIntCompareScalarCountAndLimit(
7087 const Instruction *instr) {
7088 const char *mnemonic = "unimplemented";
7089 const char *form =
7090 (instr->ExtractBit(12) == 0) ? "'Pd.'t, 'Wn, 'Wm" : "'Pd.'t, 'Xn, 'Xm";
7091
7092 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
7093 case WHILELE_p_p_rr:
7094 mnemonic = "whilele";
7095 break;
7096 case WHILELO_p_p_rr:
7097 mnemonic = "whilelo";
7098 break;
7099 case WHILELS_p_p_rr:
7100 mnemonic = "whilels";
7101 break;
7102 case WHILELT_p_p_rr:
7103 mnemonic = "whilelt";
7104 break;
7105 default:
7106 break;
7107 }
7108 Format(instr, mnemonic, form);
7109 }
7110
VisitSVEIntConvertToFP(const Instruction * instr)7111 void Disassembler::VisitSVEIntConvertToFP(const Instruction *instr) {
7112 const char *mnemonic = "unimplemented";
7113 const char *form = "(SVEIntConvertToFP)";
7114
7115 switch (instr->Mask(SVEIntConvertToFPMask)) {
7116 case SCVTF_z_p_z_h2fp16:
7117 mnemonic = "scvtf";
7118 form = "'Zd.h, 'Pgl/m, 'Zn.h";
7119 break;
7120 case SCVTF_z_p_z_w2d:
7121 mnemonic = "scvtf";
7122 form = "'Zd.d, 'Pgl/m, 'Zn.s";
7123 break;
7124 case SCVTF_z_p_z_w2fp16:
7125 mnemonic = "scvtf";
7126 form = "'Zd.h, 'Pgl/m, 'Zn.s";
7127 break;
7128 case SCVTF_z_p_z_w2s:
7129 mnemonic = "scvtf";
7130 form = "'Zd.s, 'Pgl/m, 'Zn.s";
7131 break;
7132 case SCVTF_z_p_z_x2d:
7133 mnemonic = "scvtf";
7134 form = "'Zd.d, 'Pgl/m, 'Zn.d";
7135 break;
7136 case SCVTF_z_p_z_x2fp16:
7137 mnemonic = "scvtf";
7138 form = "'Zd.h, 'Pgl/m, 'Zn.d";
7139 break;
7140 case SCVTF_z_p_z_x2s:
7141 mnemonic = "scvtf";
7142 form = "'Zd.s, 'Pgl/m, 'Zn.d";
7143 break;
7144 case UCVTF_z_p_z_h2fp16:
7145 mnemonic = "ucvtf";
7146 form = "'Zd.h, 'Pgl/m, 'Zn.h";
7147 break;
7148 case UCVTF_z_p_z_w2d:
7149 mnemonic = "ucvtf";
7150 form = "'Zd.d, 'Pgl/m, 'Zn.s";
7151 break;
7152 case UCVTF_z_p_z_w2fp16:
7153 mnemonic = "ucvtf";
7154 form = "'Zd.h, 'Pgl/m, 'Zn.s";
7155 break;
7156 case UCVTF_z_p_z_w2s:
7157 mnemonic = "ucvtf";
7158 form = "'Zd.s, 'Pgl/m, 'Zn.s";
7159 break;
7160 case UCVTF_z_p_z_x2d:
7161 mnemonic = "ucvtf";
7162 form = "'Zd.d, 'Pgl/m, 'Zn.d";
7163 break;
7164 case UCVTF_z_p_z_x2fp16:
7165 mnemonic = "ucvtf";
7166 form = "'Zd.h, 'Pgl/m, 'Zn.d";
7167 break;
7168 case UCVTF_z_p_z_x2s:
7169 mnemonic = "ucvtf";
7170 form = "'Zd.s, 'Pgl/m, 'Zn.d";
7171 break;
7172 default:
7173 break;
7174 }
7175 Format(instr, mnemonic, form);
7176 }
7177
VisitSVEIntDivideVectors_Predicated(const Instruction * instr)7178 void Disassembler::VisitSVEIntDivideVectors_Predicated(
7179 const Instruction *instr) {
7180 const char *mnemonic = "unimplemented";
7181 const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
7182
7183 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
7184 case SDIVR_z_p_zz:
7185 mnemonic = "sdivr";
7186 break;
7187 case SDIV_z_p_zz:
7188 mnemonic = "sdiv";
7189 break;
7190 case UDIVR_z_p_zz:
7191 mnemonic = "udivr";
7192 break;
7193 case UDIV_z_p_zz:
7194 mnemonic = "udiv";
7195 break;
7196 default:
7197 break;
7198 }
7199
7200 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
7201 case SDIVR_z_p_zz:
7202 case SDIV_z_p_zz:
7203 case UDIVR_z_p_zz:
7204 case UDIV_z_p_zz:
7205 switch (instr->GetSVESize()) {
7206 case kBRegSizeInBytesLog2:
7207 case kHRegSizeInBytesLog2:
7208 mnemonic = "unimplemented";
7209 form = "(SVEIntBinaryArithmeticPredicated)";
7210 break;
7211 case kSRegSizeInBytesLog2:
7212 case kDRegSizeInBytesLog2:
7213 // The default form works for these instructions.
7214 break;
7215 default:
7216 // GetSVESize() should never return other values.
7217 VIXL_UNREACHABLE();
7218 break;
7219 }
7220 }
7221
7222 Format(instr, mnemonic, form);
7223 }
7224
VisitSVEIntMinMaxDifference_Predicated(const Instruction * instr)7225 void Disassembler::VisitSVEIntMinMaxDifference_Predicated(
7226 const Instruction *instr) {
7227 const char *mnemonic = "unimplemented";
7228 const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
7229
7230 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
7231 case SABD_z_p_zz:
7232 mnemonic = "sabd";
7233 break;
7234 case SMAX_z_p_zz:
7235 mnemonic = "smax";
7236 break;
7237 case SMIN_z_p_zz:
7238 mnemonic = "smin";
7239 break;
7240 case UABD_z_p_zz:
7241 mnemonic = "uabd";
7242 break;
7243 case UMAX_z_p_zz:
7244 mnemonic = "umax";
7245 break;
7246 case UMIN_z_p_zz:
7247 mnemonic = "umin";
7248 break;
7249 default:
7250 break;
7251 }
7252 Format(instr, mnemonic, form);
7253 }
7254
VisitSVEIntMinMaxImm_Unpredicated(const Instruction * instr)7255 void Disassembler::VisitSVEIntMinMaxImm_Unpredicated(const Instruction *instr) {
7256 const char *mnemonic = "unimplemented";
7257 const char *form = "'Zd.'t, 'Zd.'t, #'u1205";
7258
7259 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
7260 case SMAX_z_zi:
7261 mnemonic = "smax";
7262 form = "'Zd.'t, 'Zd.'t, #'s1205";
7263 break;
7264 case SMIN_z_zi:
7265 mnemonic = "smin";
7266 form = "'Zd.'t, 'Zd.'t, #'s1205";
7267 break;
7268 case UMAX_z_zi:
7269 mnemonic = "umax";
7270 break;
7271 case UMIN_z_zi:
7272 mnemonic = "umin";
7273 break;
7274 default:
7275 break;
7276 }
7277 Format(instr, mnemonic, form);
7278 }
7279
VisitSVEIntMulImm_Unpredicated(const Instruction * instr)7280 void Disassembler::VisitSVEIntMulImm_Unpredicated(const Instruction *instr) {
7281 const char *mnemonic = "unimplemented";
7282 const char *form = "(SVEIntMulImm_Unpredicated)";
7283
7284 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
7285 case MUL_z_zi:
7286 mnemonic = "mul";
7287 form = "'Zd.'t, 'Zd.'t, #'s1205";
7288 break;
7289 default:
7290 break;
7291 }
7292 Format(instr, mnemonic, form);
7293 }
7294
VisitSVEIntMulVectors_Predicated(const Instruction * instr)7295 void Disassembler::VisitSVEIntMulVectors_Predicated(const Instruction *instr) {
7296 const char *mnemonic = "unimplemented";
7297 const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
7298
7299 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
7300 case MUL_z_p_zz:
7301 mnemonic = "mul";
7302 break;
7303 case SMULH_z_p_zz:
7304 mnemonic = "smulh";
7305 break;
7306 case UMULH_z_p_zz:
7307 mnemonic = "umulh";
7308 break;
7309 default:
7310 break;
7311 }
7312 Format(instr, mnemonic, form);
7313 }
7314
VisitSVELoadAndBroadcastElement(const Instruction * instr)7315 void Disassembler::VisitSVELoadAndBroadcastElement(const Instruction *instr) {
7316 const char *mnemonic = "unimplemented";
7317 const char *form = "(SVELoadAndBroadcastElement)";
7318 const char *suffix_b = ", #'u2116]";
7319 const char *suffix_h = ", #'u2116*2]";
7320 const char *suffix_w = ", #'u2116*4]";
7321 const char *suffix_d = ", #'u2116*8]";
7322 const char *suffix = NULL;
7323
7324 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
7325 case LD1RB_z_p_bi_u16:
7326 mnemonic = "ld1rb";
7327 form = "{'Zt.h}, 'Pgl/z, ['Xns";
7328 suffix = suffix_b;
7329 break;
7330 case LD1RB_z_p_bi_u32:
7331 mnemonic = "ld1rb";
7332 form = "{'Zt.s}, 'Pgl/z, ['Xns";
7333 suffix = suffix_b;
7334 break;
7335 case LD1RB_z_p_bi_u64:
7336 mnemonic = "ld1rb";
7337 form = "{'Zt.d}, 'Pgl/z, ['Xns";
7338 suffix = suffix_b;
7339 break;
7340 case LD1RB_z_p_bi_u8:
7341 mnemonic = "ld1rb";
7342 form = "{'Zt.b}, 'Pgl/z, ['Xns";
7343 suffix = suffix_b;
7344 break;
7345 case LD1RD_z_p_bi_u64:
7346 mnemonic = "ld1rd";
7347 form = "{'Zt.d}, 'Pgl/z, ['Xns";
7348 suffix = suffix_d;
7349 break;
7350 case LD1RH_z_p_bi_u16:
7351 mnemonic = "ld1rh";
7352 form = "{'Zt.h}, 'Pgl/z, ['Xns";
7353 suffix = suffix_h;
7354 break;
7355 case LD1RH_z_p_bi_u32:
7356 mnemonic = "ld1rh";
7357 form = "{'Zt.s}, 'Pgl/z, ['Xns";
7358 suffix = suffix_h;
7359 break;
7360 case LD1RH_z_p_bi_u64:
7361 mnemonic = "ld1rh";
7362 form = "{'Zt.d}, 'Pgl/z, ['Xns";
7363 suffix = suffix_h;
7364 break;
7365 case LD1RSB_z_p_bi_s16:
7366 mnemonic = "ld1rsb";
7367 form = "{'Zt.h}, 'Pgl/z, ['Xns";
7368 suffix = suffix_b;
7369 break;
7370 case LD1RSB_z_p_bi_s32:
7371 mnemonic = "ld1rsb";
7372 form = "{'Zt.s}, 'Pgl/z, ['Xns";
7373 suffix = suffix_b;
7374 break;
7375 case LD1RSB_z_p_bi_s64:
7376 mnemonic = "ld1rsb";
7377 form = "{'Zt.d}, 'Pgl/z, ['Xns";
7378 suffix = suffix_b;
7379 break;
7380 case LD1RSH_z_p_bi_s32:
7381 mnemonic = "ld1rsh";
7382 form = "{'Zt.s}, 'Pgl/z, ['Xns";
7383 suffix = suffix_h;
7384 break;
7385 case LD1RSH_z_p_bi_s64:
7386 mnemonic = "ld1rsh";
7387 form = "{'Zt.d}, 'Pgl/z, ['Xns";
7388 suffix = suffix_h;
7389 break;
7390 case LD1RSW_z_p_bi_s64:
7391 mnemonic = "ld1rsw";
7392 form = "{'Zt.d}, 'Pgl/z, ['Xns";
7393 suffix = suffix_w;
7394 break;
7395 case LD1RW_z_p_bi_u32:
7396 mnemonic = "ld1rw";
7397 form = "{'Zt.s}, 'Pgl/z, ['Xns";
7398 suffix = suffix_w;
7399 break;
7400 case LD1RW_z_p_bi_u64:
7401 mnemonic = "ld1rw";
7402 form = "{'Zt.d}, 'Pgl/z, ['Xns";
7403 suffix = suffix_w;
7404 break;
7405 default:
7406 break;
7407 }
7408
7409 // Hide curly brackets if immediate is zero.
7410 if (instr->ExtractBits(21, 16) == 0) {
7411 suffix = "]";
7412 }
7413
7414 Format(instr, mnemonic, form, suffix);
7415 }
7416
VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(const Instruction * instr)7417 void Disassembler::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
7418 const Instruction *instr) {
7419 const char *mnemonic = "unimplemented";
7420 const char *form = "(SVELoadAndBroadcastQuadword_ScalarPlusImm)";
7421
7422 const char *suffix =
7423 (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916*16]";
7424
7425 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
7426 case LD1RQB_z_p_bi_u8:
7427 mnemonic = "ld1rqb";
7428 form = "{'Zt.b}, 'Pgl/z, ['Xns";
7429 break;
7430 case LD1RQD_z_p_bi_u64:
7431 mnemonic = "ld1rqd";
7432 form = "{'Zt.d}, 'Pgl/z, ['Xns";
7433 break;
7434 case LD1RQH_z_p_bi_u16:
7435 mnemonic = "ld1rqh";
7436 form = "{'Zt.h}, 'Pgl/z, ['Xns";
7437 break;
7438 case LD1RQW_z_p_bi_u32:
7439 mnemonic = "ld1rqw";
7440 form = "{'Zt.s}, 'Pgl/z, ['Xns";
7441 break;
7442 default:
7443 suffix = NULL;
7444 break;
7445 }
7446 Format(instr, mnemonic, form, suffix);
7447 }
7448
VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(const Instruction * instr)7449 void Disassembler::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
7450 const Instruction *instr) {
7451 const char *mnemonic = "unimplemented";
7452 const char *form = "(SVELoadAndBroadcastQuadword_ScalarPlusScalar)";
7453
7454 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
7455 case LD1RQB_z_p_br_contiguous:
7456 mnemonic = "ld1rqb";
7457 form = "{'Zt.b}, 'Pgl/z, ['Xns, 'Rm]";
7458 break;
7459 case LD1RQD_z_p_br_contiguous:
7460 mnemonic = "ld1rqd";
7461 form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Rm, lsl #3]";
7462 break;
7463 case LD1RQH_z_p_br_contiguous:
7464 mnemonic = "ld1rqh";
7465 form = "{'Zt.h}, 'Pgl/z, ['Xns, 'Rm, lsl #1]";
7466 break;
7467 case LD1RQW_z_p_br_contiguous:
7468 mnemonic = "ld1rqw";
7469 form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Rm, lsl #2]";
7470 break;
7471 default:
7472 break;
7473 }
7474 Format(instr, mnemonic, form);
7475 }
7476
VisitSVELoadMultipleStructures_ScalarPlusImm(const Instruction * instr)7477 void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusImm(
7478 const Instruction *instr) {
7479 const char *mnemonic = "unimplemented";
7480 const char *form = "(SVELoadMultipleStructures_ScalarPlusImm)";
7481
7482 const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl/z, ['Xns'ISveSvl]";
7483 const char *form_3 =
7484 "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl/z, ['Xns'ISveSvl]";
7485 const char *form_4 =
7486 "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
7487 "'Pgl/z, ['Xns'ISveSvl]";
7488
7489 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
7490 case LD2B_z_p_bi_contiguous:
7491 mnemonic = "ld2b";
7492 form = form_2;
7493 break;
7494 case LD2D_z_p_bi_contiguous:
7495 mnemonic = "ld2d";
7496 form = form_2;
7497 break;
7498 case LD2H_z_p_bi_contiguous:
7499 mnemonic = "ld2h";
7500 form = form_2;
7501 break;
7502 case LD2W_z_p_bi_contiguous:
7503 mnemonic = "ld2w";
7504 form = form_2;
7505 break;
7506 case LD3B_z_p_bi_contiguous:
7507 mnemonic = "ld3b";
7508 form = form_3;
7509 break;
7510 case LD3D_z_p_bi_contiguous:
7511 mnemonic = "ld3d";
7512 form = form_3;
7513 break;
7514 case LD3H_z_p_bi_contiguous:
7515 mnemonic = "ld3h";
7516 form = form_3;
7517 break;
7518 case LD3W_z_p_bi_contiguous:
7519 mnemonic = "ld3w";
7520 form = form_3;
7521 break;
7522 case LD4B_z_p_bi_contiguous:
7523 mnemonic = "ld4b";
7524 form = form_4;
7525 break;
7526 case LD4D_z_p_bi_contiguous:
7527 mnemonic = "ld4d";
7528 form = form_4;
7529 break;
7530 case LD4H_z_p_bi_contiguous:
7531 mnemonic = "ld4h";
7532 form = form_4;
7533 break;
7534 case LD4W_z_p_bi_contiguous:
7535 mnemonic = "ld4w";
7536 form = form_4;
7537 break;
7538 default:
7539 break;
7540 }
7541 Format(instr, mnemonic, form);
7542 }
7543
VisitSVELoadMultipleStructures_ScalarPlusScalar(const Instruction * instr)7544 void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusScalar(
7545 const Instruction *instr) {
7546 const char *mnemonic = "unimplemented";
7547 const char *form = "(SVELoadMultipleStructures_ScalarPlusScalar)";
7548
7549 const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl/z, ['Xns, 'Xm'NSveS]";
7550 const char *form_3 =
7551 "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl/z, ['Xns, 'Xm'NSveS]";
7552 const char *form_4 =
7553 "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
7554 "'Pgl/z, ['Xns, 'Xm'NSveS]";
7555
7556 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
7557 case LD2B_z_p_br_contiguous:
7558 mnemonic = "ld2b";
7559 form = form_2;
7560 break;
7561 case LD2D_z_p_br_contiguous:
7562 mnemonic = "ld2d";
7563 form = form_2;
7564 break;
7565 case LD2H_z_p_br_contiguous:
7566 mnemonic = "ld2h";
7567 form = form_2;
7568 break;
7569 case LD2W_z_p_br_contiguous:
7570 mnemonic = "ld2w";
7571 form = form_2;
7572 break;
7573 case LD3B_z_p_br_contiguous:
7574 mnemonic = "ld3b";
7575 form = form_3;
7576 break;
7577 case LD3D_z_p_br_contiguous:
7578 mnemonic = "ld3d";
7579 form = form_3;
7580 break;
7581 case LD3H_z_p_br_contiguous:
7582 mnemonic = "ld3h";
7583 form = form_3;
7584 break;
7585 case LD3W_z_p_br_contiguous:
7586 mnemonic = "ld3w";
7587 form = form_3;
7588 break;
7589 case LD4B_z_p_br_contiguous:
7590 mnemonic = "ld4b";
7591 form = form_4;
7592 break;
7593 case LD4D_z_p_br_contiguous:
7594 mnemonic = "ld4d";
7595 form = form_4;
7596 break;
7597 case LD4H_z_p_br_contiguous:
7598 mnemonic = "ld4h";
7599 form = form_4;
7600 break;
7601 case LD4W_z_p_br_contiguous:
7602 mnemonic = "ld4w";
7603 form = form_4;
7604 break;
7605 default:
7606 break;
7607 }
7608 Format(instr, mnemonic, form);
7609 }
7610
VisitSVELoadPredicateRegister(const Instruction * instr)7611 void Disassembler::VisitSVELoadPredicateRegister(const Instruction *instr) {
7612 const char *mnemonic = "unimplemented";
7613 const char *form = "(SVELoadPredicateRegister)";
7614
7615 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
7616 case LDR_p_bi:
7617 mnemonic = "ldr";
7618 if (instr->Mask(0x003f1c00) == 0) {
7619 form = "'Pd, ['Xns]";
7620 } else {
7621 form = "'Pd, ['Xns, #'s2116:1210, mul vl]";
7622 }
7623 break;
7624 default:
7625 break;
7626 }
7627 Format(instr, mnemonic, form);
7628 }
7629
VisitSVELoadVectorRegister(const Instruction * instr)7630 void Disassembler::VisitSVELoadVectorRegister(const Instruction *instr) {
7631 const char *mnemonic = "unimplemented";
7632 const char *form = "(SVELoadVectorRegister)";
7633
7634 switch (instr->Mask(SVELoadVectorRegisterMask)) {
7635 case LDR_z_bi:
7636 mnemonic = "ldr";
7637 if (instr->Mask(0x003f1c00) == 0) {
7638 form = "'Zd, ['Xns]";
7639 } else {
7640 form = "'Zt, ['Xns, #'s2116:1210, mul vl]";
7641 }
7642 break;
7643 default:
7644 break;
7645 }
7646 Format(instr, mnemonic, form);
7647 }
7648
VisitSVEPartitionBreakCondition(const Instruction * instr)7649 void Disassembler::VisitSVEPartitionBreakCondition(const Instruction *instr) {
7650 const char *mnemonic = "unimplemented";
7651 const char *form = "'Pd.b, p'u1310/'?04:mz, 'Pn.b";
7652
7653 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
7654 case BRKAS_p_p_p_z:
7655 mnemonic = "brkas";
7656 break;
7657 case BRKA_p_p_p:
7658 mnemonic = "brka";
7659 break;
7660 case BRKBS_p_p_p_z:
7661 mnemonic = "brkbs";
7662 break;
7663 case BRKB_p_p_p:
7664 mnemonic = "brkb";
7665 break;
7666 default:
7667 form = "(SVEPartitionBreakCondition)";
7668 break;
7669 }
7670 Format(instr, mnemonic, form);
7671 }
7672
VisitSVEPermutePredicateElements(const Instruction * instr)7673 void Disassembler::VisitSVEPermutePredicateElements(const Instruction *instr) {
7674 const char *mnemonic = "unimplemented";
7675 const char *form = "'Pd.'t, 'Pn.'t, 'Pm.'t";
7676
7677 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
7678 case TRN1_p_pp:
7679 mnemonic = "trn1";
7680 break;
7681 case TRN2_p_pp:
7682 mnemonic = "trn2";
7683 break;
7684 case UZP1_p_pp:
7685 mnemonic = "uzp1";
7686 break;
7687 case UZP2_p_pp:
7688 mnemonic = "uzp2";
7689 break;
7690 case ZIP1_p_pp:
7691 mnemonic = "zip1";
7692 break;
7693 case ZIP2_p_pp:
7694 mnemonic = "zip2";
7695 break;
7696 default:
7697 break;
7698 }
7699 Format(instr, mnemonic, form);
7700 }
7701
VisitSVEPredicateFirstActive(const Instruction * instr)7702 void Disassembler::VisitSVEPredicateFirstActive(const Instruction *instr) {
7703 const char *mnemonic = "unimplemented";
7704 const char *form = "(SVEPredicateFirstActive)";
7705
7706 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
7707 case PFIRST_p_p_p:
7708 mnemonic = "pfirst";
7709 form = "'Pd.b, 'Pn, 'Pd.b";
7710 break;
7711 default:
7712 break;
7713 }
7714 Format(instr, mnemonic, form);
7715 }
7716
VisitSVEPredicateReadFromFFR_Unpredicated(const Instruction * instr)7717 void Disassembler::VisitSVEPredicateReadFromFFR_Unpredicated(
7718 const Instruction *instr) {
7719 const char *mnemonic = "unimplemented";
7720 const char *form = "(SVEPredicateReadFromFFR_Unpredicated)";
7721
7722 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
7723 case RDFFR_p_f:
7724 mnemonic = "rdffr";
7725 form = "'Pd.b";
7726 break;
7727 default:
7728 break;
7729 }
7730 Format(instr, mnemonic, form);
7731 }
7732
VisitSVEPredicateTest(const Instruction * instr)7733 void Disassembler::VisitSVEPredicateTest(const Instruction *instr) {
7734 const char *mnemonic = "unimplemented";
7735 const char *form = "(SVEPredicateTest)";
7736
7737 switch (instr->Mask(SVEPredicateTestMask)) {
7738 case PTEST_p_p:
7739 mnemonic = "ptest";
7740 form = "p'u1310, 'Pn.b";
7741 break;
7742 default:
7743 break;
7744 }
7745 Format(instr, mnemonic, form);
7746 }
7747
VisitSVEPredicateZero(const Instruction * instr)7748 void Disassembler::VisitSVEPredicateZero(const Instruction *instr) {
7749 const char *mnemonic = "unimplemented";
7750 const char *form = "(SVEPredicateZero)";
7751
7752 switch (instr->Mask(SVEPredicateZeroMask)) {
7753 case PFALSE_p:
7754 mnemonic = "pfalse";
7755 form = "'Pd.b";
7756 break;
7757 default:
7758 break;
7759 }
7760 Format(instr, mnemonic, form);
7761 }
7762
VisitSVEPropagateBreakToNextPartition(const Instruction * instr)7763 void Disassembler::VisitSVEPropagateBreakToNextPartition(
7764 const Instruction *instr) {
7765 const char *mnemonic = "unimplemented";
7766 const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pd.b";
7767
7768 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
7769 case BRKNS_p_p_pp:
7770 mnemonic = "brkns";
7771 break;
7772 case BRKN_p_p_pp:
7773 mnemonic = "brkn";
7774 break;
7775 default:
7776 break;
7777 }
7778 Format(instr, mnemonic, form);
7779 }
7780
VisitSVEReversePredicateElements(const Instruction * instr)7781 void Disassembler::VisitSVEReversePredicateElements(const Instruction *instr) {
7782 const char *mnemonic = "unimplemented";
7783 const char *form = "(SVEReversePredicateElements)";
7784
7785 switch (instr->Mask(SVEReversePredicateElementsMask)) {
7786 case REV_p_p:
7787 mnemonic = "rev";
7788 form = "'Pd.'t, 'Pn.'t";
7789 break;
7790 default:
7791 break;
7792 }
7793 Format(instr, mnemonic, form);
7794 }
7795
VisitSVEReverseVectorElements(const Instruction * instr)7796 void Disassembler::VisitSVEReverseVectorElements(const Instruction *instr) {
7797 const char *mnemonic = "unimplemented";
7798 const char *form = "(SVEReverseVectorElements)";
7799
7800 switch (instr->Mask(SVEReverseVectorElementsMask)) {
7801 case REV_z_z:
7802 mnemonic = "rev";
7803 form = "'Zd.'t, 'Zn.'t";
7804 break;
7805 default:
7806 break;
7807 }
7808 Format(instr, mnemonic, form);
7809 }
7810
VisitSVEReverseWithinElements(const Instruction * instr)7811 void Disassembler::VisitSVEReverseWithinElements(const Instruction *instr) {
7812 const char *mnemonic = "unimplemented";
7813 const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
7814
7815 unsigned size = instr->GetSVESize();
7816 switch (instr->Mask(SVEReverseWithinElementsMask)) {
7817 case RBIT_z_p_z:
7818 mnemonic = "rbit";
7819 break;
7820 case REVB_z_z:
7821 if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
7822 (size == kDRegSizeInBytesLog2)) {
7823 mnemonic = "revb";
7824 } else {
7825 form = "(SVEReverseWithinElements)";
7826 }
7827 break;
7828 case REVH_z_z:
7829 if ((size == kSRegSizeInBytesLog2) || (size == kDRegSizeInBytesLog2)) {
7830 mnemonic = "revh";
7831 } else {
7832 form = "(SVEReverseWithinElements)";
7833 }
7834 break;
7835 case REVW_z_z:
7836 if (size == kDRegSizeInBytesLog2) {
7837 mnemonic = "revw";
7838 } else {
7839 form = "(SVEReverseWithinElements)";
7840 }
7841 break;
7842 default:
7843 break;
7844 }
7845 Format(instr, mnemonic, form);
7846 }
7847
VisitSVESaturatingIncDecRegisterByElementCount(const Instruction * instr)7848 void Disassembler::VisitSVESaturatingIncDecRegisterByElementCount(
7849 const Instruction *instr) {
7850 const char *mnemonic = "unimplemented";
7851 const char *form = IncDecFormHelper(instr,
7852 "'R20d, 'Ipc, mul #'u1916+1",
7853 "'R20d, 'Ipc",
7854 "'R20d");
7855 const char *form_sx = IncDecFormHelper(instr,
7856 "'Xd, 'Wd, 'Ipc, mul #'u1916+1",
7857 "'Xd, 'Wd, 'Ipc",
7858 "'Xd, 'Wd");
7859
7860 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
7861 case SQDECB_r_rs_sx:
7862 mnemonic = "sqdecb";
7863 form = form_sx;
7864 break;
7865 case SQDECD_r_rs_sx:
7866 mnemonic = "sqdecd";
7867 form = form_sx;
7868 break;
7869 case SQDECH_r_rs_sx:
7870 mnemonic = "sqdech";
7871 form = form_sx;
7872 break;
7873 case SQDECW_r_rs_sx:
7874 mnemonic = "sqdecw";
7875 form = form_sx;
7876 break;
7877 case SQINCB_r_rs_sx:
7878 mnemonic = "sqincb";
7879 form = form_sx;
7880 break;
7881 case SQINCD_r_rs_sx:
7882 mnemonic = "sqincd";
7883 form = form_sx;
7884 break;
7885 case SQINCH_r_rs_sx:
7886 mnemonic = "sqinch";
7887 form = form_sx;
7888 break;
7889 case SQINCW_r_rs_sx:
7890 mnemonic = "sqincw";
7891 form = form_sx;
7892 break;
7893 case SQDECB_r_rs_x:
7894 mnemonic = "sqdecb";
7895 break;
7896 case SQDECD_r_rs_x:
7897 mnemonic = "sqdecd";
7898 break;
7899 case SQDECH_r_rs_x:
7900 mnemonic = "sqdech";
7901 break;
7902 case SQDECW_r_rs_x:
7903 mnemonic = "sqdecw";
7904 break;
7905 case SQINCB_r_rs_x:
7906 mnemonic = "sqincb";
7907 break;
7908 case SQINCD_r_rs_x:
7909 mnemonic = "sqincd";
7910 break;
7911 case SQINCH_r_rs_x:
7912 mnemonic = "sqinch";
7913 break;
7914 case SQINCW_r_rs_x:
7915 mnemonic = "sqincw";
7916 break;
7917 case UQDECB_r_rs_uw:
7918 case UQDECB_r_rs_x:
7919 mnemonic = "uqdecb";
7920 break;
7921 case UQDECD_r_rs_uw:
7922 case UQDECD_r_rs_x:
7923 mnemonic = "uqdecd";
7924 break;
7925 case UQDECH_r_rs_uw:
7926 case UQDECH_r_rs_x:
7927 mnemonic = "uqdech";
7928 break;
7929 case UQDECW_r_rs_uw:
7930 case UQDECW_r_rs_x:
7931 mnemonic = "uqdecw";
7932 break;
7933 case UQINCB_r_rs_uw:
7934 case UQINCB_r_rs_x:
7935 mnemonic = "uqincb";
7936 break;
7937 case UQINCD_r_rs_uw:
7938 case UQINCD_r_rs_x:
7939 mnemonic = "uqincd";
7940 break;
7941 case UQINCH_r_rs_uw:
7942 case UQINCH_r_rs_x:
7943 mnemonic = "uqinch";
7944 break;
7945 case UQINCW_r_rs_uw:
7946 case UQINCW_r_rs_x:
7947 mnemonic = "uqincw";
7948 break;
7949 default:
7950 break;
7951 }
7952 Format(instr, mnemonic, form);
7953 }
7954
VisitSVESaturatingIncDecVectorByElementCount(const Instruction * instr)7955 void Disassembler::VisitSVESaturatingIncDecVectorByElementCount(
7956 const Instruction *instr) {
7957 const char *mnemonic = "unimplemented";
7958 const char *form = IncDecFormHelper(instr,
7959 "'Zd.'t, 'Ipc, mul #'u1916+1",
7960 "'Zd.'t, 'Ipc",
7961 "'Zd.'t");
7962
7963 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7964 case SQDECD_z_zs:
7965 mnemonic = "sqdecd";
7966 break;
7967 case SQDECH_z_zs:
7968 mnemonic = "sqdech";
7969 break;
7970 case SQDECW_z_zs:
7971 mnemonic = "sqdecw";
7972 break;
7973 case SQINCD_z_zs:
7974 mnemonic = "sqincd";
7975 break;
7976 case SQINCH_z_zs:
7977 mnemonic = "sqinch";
7978 break;
7979 case SQINCW_z_zs:
7980 mnemonic = "sqincw";
7981 break;
7982 case UQDECD_z_zs:
7983 mnemonic = "uqdecd";
7984 break;
7985 case UQDECH_z_zs:
7986 mnemonic = "uqdech";
7987 break;
7988 case UQDECW_z_zs:
7989 mnemonic = "uqdecw";
7990 break;
7991 case UQINCD_z_zs:
7992 mnemonic = "uqincd";
7993 break;
7994 case UQINCH_z_zs:
7995 mnemonic = "uqinch";
7996 break;
7997 case UQINCW_z_zs:
7998 mnemonic = "uqincw";
7999 break;
8000 default:
8001 form = "(SVEElementCount)";
8002 break;
8003 }
8004 Format(instr, mnemonic, form);
8005 }
8006
VisitSVEStoreMultipleStructures_ScalarPlusImm(const Instruction * instr)8007 void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusImm(
8008 const Instruction *instr) {
8009 const char *mnemonic = "unimplemented";
8010 const char *form = "(SVEStoreMultipleStructures_ScalarPlusImm)";
8011
8012 const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl, ['Xns'ISveSvl]";
8013 const char *form_3 =
8014 "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl, ['Xns'ISveSvl]";
8015 const char *form_4 =
8016 "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
8017 "'Pgl, ['Xns'ISveSvl]";
8018
8019 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
8020 case ST2B_z_p_bi_contiguous:
8021 mnemonic = "st2b";
8022 form = form_2;
8023 break;
8024 case ST2H_z_p_bi_contiguous:
8025 mnemonic = "st2h";
8026 form = form_2;
8027 break;
8028 case ST2W_z_p_bi_contiguous:
8029 mnemonic = "st2w";
8030 form = form_2;
8031 break;
8032 case ST2D_z_p_bi_contiguous:
8033 mnemonic = "st2d";
8034 form = form_2;
8035 break;
8036 case ST3B_z_p_bi_contiguous:
8037 mnemonic = "st3b";
8038 form = form_3;
8039 break;
8040 case ST3H_z_p_bi_contiguous:
8041 mnemonic = "st3h";
8042 form = form_3;
8043 break;
8044 case ST3W_z_p_bi_contiguous:
8045 mnemonic = "st3w";
8046 form = form_3;
8047 break;
8048 case ST3D_z_p_bi_contiguous:
8049 mnemonic = "st3d";
8050 form = form_3;
8051 break;
8052 case ST4B_z_p_bi_contiguous:
8053 mnemonic = "st4b";
8054 form = form_4;
8055 break;
8056 case ST4H_z_p_bi_contiguous:
8057 mnemonic = "st4h";
8058 form = form_4;
8059 break;
8060 case ST4W_z_p_bi_contiguous:
8061 mnemonic = "st4w";
8062 form = form_4;
8063 break;
8064 case ST4D_z_p_bi_contiguous:
8065 mnemonic = "st4d";
8066 form = form_4;
8067 break;
8068 default:
8069 break;
8070 }
8071 Format(instr, mnemonic, form);
8072 }
8073
VisitSVEStoreMultipleStructures_ScalarPlusScalar(const Instruction * instr)8074 void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
8075 const Instruction *instr) {
8076 const char *mnemonic = "unimplemented";
8077 const char *form = "(SVEStoreMultipleStructures_ScalarPlusScalar)";
8078
8079 const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl, ['Xns, 'Xm'NSveS]";
8080 const char *form_3 =
8081 "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl, ['Xns, 'Xm'NSveS]";
8082 const char *form_4 =
8083 "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
8084 "'Pgl, ['Xns, 'Xm'NSveS]";
8085
8086 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
8087 case ST2B_z_p_br_contiguous:
8088 mnemonic = "st2b";
8089 form = form_2;
8090 break;
8091 case ST2D_z_p_br_contiguous:
8092 mnemonic = "st2d";
8093 form = form_2;
8094 break;
8095 case ST2H_z_p_br_contiguous:
8096 mnemonic = "st2h";
8097 form = form_2;
8098 break;
8099 case ST2W_z_p_br_contiguous:
8100 mnemonic = "st2w";
8101 form = form_2;
8102 break;
8103 case ST3B_z_p_br_contiguous:
8104 mnemonic = "st3b";
8105 form = form_3;
8106 break;
8107 case ST3D_z_p_br_contiguous:
8108 mnemonic = "st3d";
8109 form = form_3;
8110 break;
8111 case ST3H_z_p_br_contiguous:
8112 mnemonic = "st3h";
8113 form = form_3;
8114 break;
8115 case ST3W_z_p_br_contiguous:
8116 mnemonic = "st3w";
8117 form = form_3;
8118 break;
8119 case ST4B_z_p_br_contiguous:
8120 mnemonic = "st4b";
8121 form = form_4;
8122 break;
8123 case ST4D_z_p_br_contiguous:
8124 mnemonic = "st4d";
8125 form = form_4;
8126 break;
8127 case ST4H_z_p_br_contiguous:
8128 mnemonic = "st4h";
8129 form = form_4;
8130 break;
8131 case ST4W_z_p_br_contiguous:
8132 mnemonic = "st4w";
8133 form = form_4;
8134 break;
8135 default:
8136 break;
8137 }
8138 Format(instr, mnemonic, form);
8139 }
8140
VisitSVEStorePredicateRegister(const Instruction * instr)8141 void Disassembler::VisitSVEStorePredicateRegister(const Instruction *instr) {
8142 const char *mnemonic = "unimplemented";
8143 const char *form = "(SVEStorePredicateRegister)";
8144
8145 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
8146 case STR_p_bi:
8147 mnemonic = "str";
8148 if (instr->Mask(0x003f1c00) == 0) {
8149 form = "'Pd, ['Xns]";
8150 } else {
8151 form = "'Pd, ['Xns, #'s2116:1210, mul vl]";
8152 }
8153 break;
8154 default:
8155 break;
8156 }
8157 Format(instr, mnemonic, form);
8158 }
8159
VisitSVEStoreVectorRegister(const Instruction * instr)8160 void Disassembler::VisitSVEStoreVectorRegister(const Instruction *instr) {
8161 const char *mnemonic = "unimplemented";
8162 const char *form = "(SVEStoreVectorRegister)";
8163
8164 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
8165 case STR_z_bi:
8166 mnemonic = "str";
8167 if (instr->Mask(0x003f1c00) == 0) {
8168 form = "'Zd, ['Xns]";
8169 } else {
8170 form = "'Zt, ['Xns, #'s2116:1210, mul vl]";
8171 }
8172 break;
8173 default:
8174 break;
8175 }
8176 Format(instr, mnemonic, form);
8177 }
8178
VisitSVETableLookup(const Instruction * instr)8179 void Disassembler::VisitSVETableLookup(const Instruction *instr) {
8180 const char *mnemonic = "unimplemented";
8181 const char *form = "(SVETableLookup)";
8182
8183 switch (instr->Mask(SVETableLookupMask)) {
8184 case TBL_z_zz_1:
8185 mnemonic = "tbl";
8186 form = "'Zd.'t, {'Zn.'t}, 'Zm.'t";
8187 break;
8188 default:
8189 break;
8190 }
8191 Format(instr, mnemonic, form);
8192 }
8193
VisitSVEUnpackPredicateElements(const Instruction * instr)8194 void Disassembler::VisitSVEUnpackPredicateElements(const Instruction *instr) {
8195 const char *mnemonic = "unimplemented";
8196 const char *form = "'Pd.h, 'Pn.b";
8197
8198 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
8199 case PUNPKHI_p_p:
8200 mnemonic = "punpkhi";
8201 break;
8202 case PUNPKLO_p_p:
8203 mnemonic = "punpklo";
8204 break;
8205 default:
8206 break;
8207 }
8208 Format(instr, mnemonic, form);
8209 }
8210
VisitSVEUnpackVectorElements(const Instruction * instr)8211 void Disassembler::VisitSVEUnpackVectorElements(const Instruction *instr) {
8212 const char *mnemonic = "unimplemented";
8213 const char *form = "'Zd.'t, 'Zn.'th";
8214
8215 if (instr->GetSVESize() == 0) {
8216 // The lowest lane size of the destination vector is H-sized lane.
8217 Format(instr, "unallocated", "(SVEUnpackVectorElements)");
8218 return;
8219 }
8220
8221 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
8222 case SUNPKHI_z_z:
8223 mnemonic = "sunpkhi";
8224 break;
8225 case SUNPKLO_z_z:
8226 mnemonic = "sunpklo";
8227 break;
8228 case UUNPKHI_z_z:
8229 mnemonic = "uunpkhi";
8230 break;
8231 case UUNPKLO_z_z:
8232 mnemonic = "uunpklo";
8233 break;
8234 default:
8235 break;
8236 }
8237 Format(instr, mnemonic, form);
8238 }
8239
VisitSVEVectorSplice_Destructive(const Instruction * instr)8240 void Disassembler::VisitSVEVectorSplice_Destructive(const Instruction *instr) {
8241 const char *mnemonic = "unimplemented";
8242 const char *form = "(SVEVectorSplice_Destructive)";
8243
8244 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
8245 case SPLICE_z_p_zz_des:
8246 mnemonic = "splice";
8247 form = "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t";
8248 break;
8249 default:
8250 break;
8251 }
8252 Format(instr, mnemonic, form);
8253 }
8254
VisitSVEAddressGeneration(const Instruction * instr)8255 void Disassembler::VisitSVEAddressGeneration(const Instruction *instr) {
8256 const char *mnemonic = "adr";
8257 const char *form = "'Zd.d, ['Zn.d, 'Zm.d";
8258 const char *suffix = NULL;
8259
8260 bool msz_is_zero = (instr->ExtractBits(11, 10) == 0);
8261
8262 switch (instr->Mask(SVEAddressGenerationMask)) {
8263 case ADR_z_az_d_s32_scaled:
8264 suffix = msz_is_zero ? ", sxtw]" : ", sxtw #'u1110]";
8265 break;
8266 case ADR_z_az_d_u32_scaled:
8267 suffix = msz_is_zero ? ", uxtw]" : ", uxtw #'u1110]";
8268 break;
8269 case ADR_z_az_s_same_scaled:
8270 case ADR_z_az_d_same_scaled:
8271 form = "'Zd.'t, ['Zn.'t, 'Zm.'t";
8272 suffix = msz_is_zero ? "]" : ", lsl #'u1110]";
8273 break;
8274 default:
8275 mnemonic = "unimplemented";
8276 form = "(SVEAddressGeneration)";
8277 break;
8278 }
8279 Format(instr, mnemonic, form, suffix);
8280 }
8281
VisitSVEBitwiseLogicalUnpredicated(const Instruction * instr)8282 void Disassembler::VisitSVEBitwiseLogicalUnpredicated(
8283 const Instruction *instr) {
8284 const char *mnemonic = "unimplemented";
8285 const char *form = "'Zd.d, 'Zn.d, 'Zm.d";
8286
8287 switch (instr->Mask(SVEBitwiseLogicalUnpredicatedMask)) {
8288 case AND_z_zz:
8289 mnemonic = "and";
8290 break;
8291 case BIC_z_zz:
8292 mnemonic = "bic";
8293 break;
8294 case EOR_z_zz:
8295 mnemonic = "eor";
8296 break;
8297 case ORR_z_zz:
8298 mnemonic = "orr";
8299 if (instr->GetRn() == instr->GetRm()) {
8300 mnemonic = "mov";
8301 form = "'Zd.d, 'Zn.d";
8302 }
8303 break;
8304 default:
8305 break;
8306 }
8307 Format(instr, mnemonic, form);
8308 }
8309
VisitSVEBitwiseShiftUnpredicated(const Instruction * instr)8310 void Disassembler::VisitSVEBitwiseShiftUnpredicated(const Instruction *instr) {
8311 const char *mnemonic = "unimplemented";
8312 const char *form = "(SVEBitwiseShiftUnpredicated)";
8313 unsigned tsize =
8314 (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(20, 19);
8315 unsigned lane_size = instr->GetSVESize();
8316
8317 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
8318 case ASR_z_zi:
8319 if (tsize != 0) {
8320 // The tsz field must not be zero.
8321 mnemonic = "asr";
8322 form = "'Zd.'tszs, 'Zn.'tszs, 'ITriSves";
8323 }
8324 break;
8325 case ASR_z_zw:
8326 if (lane_size <= kSRegSizeInBytesLog2) {
8327 mnemonic = "asr";
8328 form = "'Zd.'t, 'Zn.'t, 'Zm.d";
8329 }
8330 break;
8331 case LSL_z_zi:
8332 if (tsize != 0) {
8333 // The tsz field must not be zero.
8334 mnemonic = "lsl";
8335 form = "'Zd.'tszs, 'Zn.'tszs, 'ITriSver";
8336 }
8337 break;
8338 case LSL_z_zw:
8339 if (lane_size <= kSRegSizeInBytesLog2) {
8340 mnemonic = "lsl";
8341 form = "'Zd.'t, 'Zn.'t, 'Zm.d";
8342 }
8343 break;
8344 case LSR_z_zi:
8345 if (tsize != 0) {
8346 // The tsz field must not be zero.
8347 mnemonic = "lsr";
8348 form = "'Zd.'tszs, 'Zn.'tszs, 'ITriSves";
8349 }
8350 break;
8351 case LSR_z_zw:
8352 if (lane_size <= kSRegSizeInBytesLog2) {
8353 mnemonic = "lsr";
8354 form = "'Zd.'t, 'Zn.'t, 'Zm.d";
8355 }
8356 break;
8357 default:
8358 break;
8359 }
8360
8361 Format(instr, mnemonic, form);
8362 }
8363
VisitSVEElementCount(const Instruction * instr)8364 void Disassembler::VisitSVEElementCount(const Instruction *instr) {
8365 const char *mnemonic = "unimplemented";
8366 const char *form =
8367 IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd");
8368
8369 switch (instr->Mask(SVEElementCountMask)) {
8370 case CNTB_r_s:
8371 mnemonic = "cntb";
8372 break;
8373 case CNTD_r_s:
8374 mnemonic = "cntd";
8375 break;
8376 case CNTH_r_s:
8377 mnemonic = "cnth";
8378 break;
8379 case CNTW_r_s:
8380 mnemonic = "cntw";
8381 break;
8382 default:
8383 break;
8384 }
8385 Format(instr, mnemonic, form);
8386 }
8387
VisitSVEFPAccumulatingReduction(const Instruction * instr)8388 void Disassembler::VisitSVEFPAccumulatingReduction(const Instruction *instr) {
8389 const char *mnemonic = "unimplemented";
8390 const char *form = "(SVEFPAccumulatingReduction)";
8391
8392 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
8393 case FADDA_v_p_z:
8394 mnemonic = "fadda";
8395 form = "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t";
8396 break;
8397 default:
8398 break;
8399 }
8400 Format(instr, mnemonic, form);
8401 }
8402
VisitSVEFPArithmeticUnpredicated(const Instruction * instr)8403 void Disassembler::VisitSVEFPArithmeticUnpredicated(const Instruction *instr) {
8404 const char *mnemonic = "unimplemented";
8405 const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
8406
8407 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
8408 case FADD_z_zz:
8409 mnemonic = "fadd";
8410 break;
8411 case FMUL_z_zz:
8412 mnemonic = "fmul";
8413 break;
8414 case FRECPS_z_zz:
8415 mnemonic = "frecps";
8416 break;
8417 case FRSQRTS_z_zz:
8418 mnemonic = "frsqrts";
8419 break;
8420 case FSUB_z_zz:
8421 mnemonic = "fsub";
8422 break;
8423 case FTSMUL_z_zz:
8424 mnemonic = "ftsmul";
8425 break;
8426 default:
8427 break;
8428 }
8429 Format(instr, mnemonic, form);
8430 }
8431
VisitSVEFPCompareVectors(const Instruction * instr)8432 void Disassembler::VisitSVEFPCompareVectors(const Instruction *instr) {
8433 const char *mnemonic = "unimplemented";
8434 const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8435
8436 switch (instr->Mask(SVEFPCompareVectorsMask)) {
8437 case FACGE_p_p_zz:
8438 mnemonic = "facge";
8439 break;
8440 case FACGT_p_p_zz:
8441 mnemonic = "facgt";
8442 break;
8443 case FCMEQ_p_p_zz:
8444 mnemonic = "fcmeq";
8445 break;
8446 case FCMGE_p_p_zz:
8447 mnemonic = "fcmge";
8448 break;
8449 case FCMGT_p_p_zz:
8450 mnemonic = "fcmgt";
8451 break;
8452 case FCMNE_p_p_zz:
8453 mnemonic = "fcmne";
8454 break;
8455 case FCMUO_p_p_zz:
8456 mnemonic = "fcmuo";
8457 break;
8458 default:
8459 break;
8460 }
8461 Format(instr, mnemonic, form);
8462 }
8463
VisitSVEFPCompareWithZero(const Instruction * instr)8464 void Disassembler::VisitSVEFPCompareWithZero(const Instruction *instr) {
8465 const char *mnemonic = "unimplemented";
8466 const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #0.0";
8467
8468 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
8469 case FCMEQ_p_p_z0:
8470 mnemonic = "fcmeq";
8471 break;
8472 case FCMGE_p_p_z0:
8473 mnemonic = "fcmge";
8474 break;
8475 case FCMGT_p_p_z0:
8476 mnemonic = "fcmgt";
8477 break;
8478 case FCMLE_p_p_z0:
8479 mnemonic = "fcmle";
8480 break;
8481 case FCMLT_p_p_z0:
8482 mnemonic = "fcmlt";
8483 break;
8484 case FCMNE_p_p_z0:
8485 mnemonic = "fcmne";
8486 break;
8487 default:
8488 break;
8489 }
8490 Format(instr, mnemonic, form);
8491 }
8492
VisitSVEFPComplexAddition(const Instruction * instr)8493 void Disassembler::VisitSVEFPComplexAddition(const Instruction *instr) {
8494 const char *mnemonic = "unimplemented";
8495 const char *form = "(SVEFPComplexAddition)";
8496
8497 switch (instr->Mask(SVEFPComplexAdditionMask)) {
8498 case FCADD_z_p_zz:
8499 mnemonic = "fcadd";
8500 if (instr->ExtractBit(16) == 0) {
8501 form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t, #90";
8502 } else {
8503 form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t, #270";
8504 }
8505 break;
8506 default:
8507 break;
8508 }
8509 Format(instr, mnemonic, form);
8510 }
8511
VisitSVEFPComplexMulAdd(const Instruction * instr)8512 void Disassembler::VisitSVEFPComplexMulAdd(const Instruction *instr) {
8513 const char *mnemonic = "unimplemented";
8514 const char *form = "(SVEFPComplexMulAdd)";
8515 const char *suffix = NULL;
8516
8517 const char *fcmla_constants[] = {"0", "90", "180", "270"};
8518
8519 switch (instr->Mask(SVEFPComplexMulAddMask)) {
8520 case FCMLA_z_p_zzz:
8521 mnemonic = "fcmla";
8522 form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t, #";
8523 suffix = fcmla_constants[instr->ExtractBits(14, 13)];
8524 break;
8525 default:
8526 break;
8527 }
8528 Format(instr, mnemonic, form, suffix);
8529 }
8530
VisitSVEFPComplexMulAddIndex(const Instruction * instr)8531 void Disassembler::VisitSVEFPComplexMulAddIndex(const Instruction *instr) {
8532 const char *mnemonic = "unimplemented";
8533 const char *form = "(SVEFPComplexMulAddIndex)";
8534
8535 const char *fcmla_constants[] = {"0", "90", "180", "270"};
8536 const char *suffix = fcmla_constants[instr->ExtractBits(11, 10)];
8537
8538 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
8539 case FCMLA_z_zzzi_h:
8540 mnemonic = "fcmla";
8541 form = "'Zd.h, 'Zn.h, z'u1816.h['u2019], #";
8542 break;
8543 case FCMLA_z_zzzi_s:
8544 mnemonic = "fcmla";
8545 form = "'Zd.s, 'Zn.s, z'u1916.s['u2020], #";
8546 break;
8547 default:
8548 suffix = NULL;
8549 break;
8550 }
8551 Format(instr, mnemonic, form, suffix);
8552 }
8553
VisitSVEFPFastReduction(const Instruction * instr)8554 void Disassembler::VisitSVEFPFastReduction(const Instruction *instr) {
8555 const char *mnemonic = "unimplemented";
8556 const char *form = "'t'u0400, 'Pgl, 'Zn.'t";
8557
8558 switch (instr->Mask(SVEFPFastReductionMask)) {
8559 case FADDV_v_p_z:
8560 mnemonic = "faddv";
8561 break;
8562 case FMAXNMV_v_p_z:
8563 mnemonic = "fmaxnmv";
8564 break;
8565 case FMAXV_v_p_z:
8566 mnemonic = "fmaxv";
8567 break;
8568 case FMINNMV_v_p_z:
8569 mnemonic = "fminnmv";
8570 break;
8571 case FMINV_v_p_z:
8572 mnemonic = "fminv";
8573 break;
8574 default:
8575 break;
8576 }
8577 Format(instr, mnemonic, form);
8578 }
8579
VisitSVEFPMulIndex(const Instruction * instr)8580 void Disassembler::VisitSVEFPMulIndex(const Instruction *instr) {
8581 const char *mnemonic = "unimplemented";
8582 const char *form = "(SVEFPMulIndex)";
8583
8584 switch (instr->Mask(SVEFPMulIndexMask)) {
8585 case FMUL_z_zzi_d:
8586 mnemonic = "fmul";
8587 form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
8588 break;
8589 case FMUL_z_zzi_h:
8590 case FMUL_z_zzi_h_i3h:
8591 mnemonic = "fmul";
8592 form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
8593 break;
8594 case FMUL_z_zzi_s:
8595 mnemonic = "fmul";
8596 form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
8597 break;
8598 default:
8599 break;
8600 }
8601 Format(instr, mnemonic, form);
8602 }
8603
VisitSVEFPMulAdd(const Instruction * instr)8604 void Disassembler::VisitSVEFPMulAdd(const Instruction *instr) {
8605 const char *mnemonic = "unimplemented";
8606 const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
8607
8608 switch (instr->Mask(SVEFPMulAddMask)) {
8609 case FMAD_z_p_zzz:
8610 mnemonic = "fmad";
8611 break;
8612 case FMLA_z_p_zzz:
8613 mnemonic = "fmla";
8614 break;
8615 case FMLS_z_p_zzz:
8616 mnemonic = "fmls";
8617 break;
8618 case FMSB_z_p_zzz:
8619 mnemonic = "fmsb";
8620 break;
8621 case FNMAD_z_p_zzz:
8622 mnemonic = "fnmad";
8623 break;
8624 case FNMLA_z_p_zzz:
8625 mnemonic = "fnmla";
8626 break;
8627 case FNMLS_z_p_zzz:
8628 mnemonic = "fnmls";
8629 break;
8630 case FNMSB_z_p_zzz:
8631 mnemonic = "fnmsb";
8632 break;
8633 default:
8634 break;
8635 }
8636 Format(instr, mnemonic, form);
8637 }
8638
VisitSVEFPMulAddIndex(const Instruction * instr)8639 void Disassembler::VisitSVEFPMulAddIndex(const Instruction *instr) {
8640 const char *mnemonic = "unimplemented";
8641 const char *form = "(SVEFPMulAddIndex)";
8642
8643 switch (instr->Mask(SVEFPMulAddIndexMask)) {
8644 case FMLA_z_zzzi_d:
8645 mnemonic = "fmla";
8646 form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
8647 break;
8648 case FMLA_z_zzzi_s:
8649 mnemonic = "fmla";
8650 form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
8651 break;
8652 case FMLS_z_zzzi_d:
8653 mnemonic = "fmls";
8654 form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
8655 break;
8656 case FMLS_z_zzzi_s:
8657 mnemonic = "fmls";
8658 form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
8659 break;
8660 case FMLA_z_zzzi_h:
8661 case FMLA_z_zzzi_h_i3h:
8662 mnemonic = "fmla";
8663 form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
8664 break;
8665 case FMLS_z_zzzi_h:
8666 case FMLS_z_zzzi_h_i3h:
8667 mnemonic = "fmls";
8668 form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
8669 break;
8670 default:
8671 break;
8672 }
8673
8674 Format(instr, mnemonic, form);
8675 }
8676
VisitSVEFPUnaryOpUnpredicated(const Instruction * instr)8677 void Disassembler::VisitSVEFPUnaryOpUnpredicated(const Instruction *instr) {
8678 const char *mnemonic = "unimplemented";
8679 const char *form = "'Zd.'t, 'Zn.'t";
8680
8681 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8682 case FRECPE_z_z:
8683 mnemonic = "frecpe";
8684 break;
8685 case FRSQRTE_z_z:
8686 mnemonic = "frsqrte";
8687 break;
8688 default:
8689 break;
8690 }
8691 Format(instr, mnemonic, form);
8692 }
8693
VisitSVEIncDecByPredicateCount(const Instruction * instr)8694 void Disassembler::VisitSVEIncDecByPredicateCount(const Instruction *instr) {
8695 const char *mnemonic = "unimplemented";
8696 const char *form = "(SVEIncDecByPredicateCount)";
8697
8698 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8699 case DECP_r_p_r:
8700 case DECP_z_p_z:
8701 mnemonic = "decp";
8702 break;
8703 case INCP_r_p_r:
8704 case INCP_z_p_z:
8705 mnemonic = "incp";
8706 break;
8707 case SQDECP_r_p_r_sx:
8708 case SQDECP_r_p_r_x:
8709 case SQDECP_z_p_z:
8710 mnemonic = "sqdecp";
8711 break;
8712 case SQINCP_r_p_r_sx:
8713 case SQINCP_r_p_r_x:
8714 case SQINCP_z_p_z:
8715 mnemonic = "sqincp";
8716 break;
8717 case UQDECP_r_p_r_uw:
8718 case UQDECP_r_p_r_x:
8719 case UQDECP_z_p_z:
8720 mnemonic = "uqdecp";
8721 break;
8722 case UQINCP_r_p_r_uw:
8723 case UQINCP_r_p_r_x:
8724 case UQINCP_z_p_z:
8725 mnemonic = "uqincp";
8726 break;
8727 default:
8728 break;
8729 }
8730
8731 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8732 // <Xdn>, <Pg>.<T>
8733 case DECP_r_p_r:
8734 case INCP_r_p_r:
8735 form = "'Xd, 'Pn.'t";
8736 break;
8737 // <Zdn>.<T>, <Pg>
8738 case DECP_z_p_z:
8739 case INCP_z_p_z:
8740 case SQDECP_z_p_z:
8741 case SQINCP_z_p_z:
8742 case UQDECP_z_p_z:
8743 case UQINCP_z_p_z:
8744 form = "'Zd.'t, 'Pn";
8745 break;
8746 // <Xdn>, <Pg>.<T>, <Wdn>
8747 case SQDECP_r_p_r_sx:
8748 case SQINCP_r_p_r_sx:
8749 form = "'Xd, 'Pn.'t, 'Wd";
8750 break;
8751 // <Xdn>, <Pg>.<T>
8752 case SQDECP_r_p_r_x:
8753 case SQINCP_r_p_r_x:
8754 case UQDECP_r_p_r_x:
8755 case UQINCP_r_p_r_x:
8756 form = "'Xd, 'Pn.'t";
8757 break;
8758 // <Wdn>, <Pg>.<T>
8759 case UQDECP_r_p_r_uw:
8760 case UQINCP_r_p_r_uw:
8761 form = "'Wd, 'Pn.'t";
8762 break;
8763 default:
8764 break;
8765 }
8766 Format(instr, mnemonic, form);
8767 }
8768
VisitSVEIndexGeneration(const Instruction * instr)8769 void Disassembler::VisitSVEIndexGeneration(const Instruction *instr) {
8770 const char *mnemonic = "unimplemented";
8771 const char *form = "(SVEIndexGeneration)";
8772
8773 bool w_inputs =
8774 static_cast<unsigned>(instr->GetSVESize()) <= kWRegSizeInBytesLog2;
8775
8776 switch (instr->Mask(SVEIndexGenerationMask)) {
8777 case INDEX_z_ii:
8778 mnemonic = "index";
8779 form = "'Zd.'t, #'s0905, #'s2016";
8780 break;
8781 case INDEX_z_ir:
8782 mnemonic = "index";
8783 form = w_inputs ? "'Zd.'t, #'s0905, 'Wm" : "'Zd.'t, #'s0905, 'Xm";
8784 break;
8785 case INDEX_z_ri:
8786 mnemonic = "index";
8787 form = w_inputs ? "'Zd.'t, 'Wn, #'s2016" : "'Zd.'t, 'Xn, #'s2016";
8788 break;
8789 case INDEX_z_rr:
8790 mnemonic = "index";
8791 form = w_inputs ? "'Zd.'t, 'Wn, 'Wm" : "'Zd.'t, 'Xn, 'Xm";
8792 break;
8793 default:
8794 break;
8795 }
8796 Format(instr, mnemonic, form);
8797 }
8798
VisitSVEIntArithmeticUnpredicated(const Instruction * instr)8799 void Disassembler::VisitSVEIntArithmeticUnpredicated(const Instruction *instr) {
8800 const char *mnemonic = "unimplemented";
8801 const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
8802
8803 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8804 case ADD_z_zz:
8805 mnemonic = "add";
8806 break;
8807 case SQADD_z_zz:
8808 mnemonic = "sqadd";
8809 break;
8810 case SQSUB_z_zz:
8811 mnemonic = "sqsub";
8812 break;
8813 case SUB_z_zz:
8814 mnemonic = "sub";
8815 break;
8816 case UQADD_z_zz:
8817 mnemonic = "uqadd";
8818 break;
8819 case UQSUB_z_zz:
8820 mnemonic = "uqsub";
8821 break;
8822 default:
8823 break;
8824 }
8825 Format(instr, mnemonic, form);
8826 }
8827
VisitSVEIntCompareSignedImm(const Instruction * instr)8828 void Disassembler::VisitSVEIntCompareSignedImm(const Instruction *instr) {
8829 const char *mnemonic = "unimplemented";
8830 const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #'s2016";
8831
8832 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
8833 case CMPEQ_p_p_zi:
8834 mnemonic = "cmpeq";
8835 break;
8836 case CMPGE_p_p_zi:
8837 mnemonic = "cmpge";
8838 break;
8839 case CMPGT_p_p_zi:
8840 mnemonic = "cmpgt";
8841 break;
8842 case CMPLE_p_p_zi:
8843 mnemonic = "cmple";
8844 break;
8845 case CMPLT_p_p_zi:
8846 mnemonic = "cmplt";
8847 break;
8848 case CMPNE_p_p_zi:
8849 mnemonic = "cmpne";
8850 break;
8851 default:
8852 break;
8853 }
8854 Format(instr, mnemonic, form);
8855 }
8856
VisitSVEIntCompareUnsignedImm(const Instruction * instr)8857 void Disassembler::VisitSVEIntCompareUnsignedImm(const Instruction *instr) {
8858 const char *mnemonic = "unimplemented";
8859 const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #'u2014";
8860
8861 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8862 case CMPHI_p_p_zi:
8863 mnemonic = "cmphi";
8864 break;
8865 case CMPHS_p_p_zi:
8866 mnemonic = "cmphs";
8867 break;
8868 case CMPLO_p_p_zi:
8869 mnemonic = "cmplo";
8870 break;
8871 case CMPLS_p_p_zi:
8872 mnemonic = "cmpls";
8873 break;
8874 default:
8875 break;
8876 }
8877 Format(instr, mnemonic, form);
8878 }
8879
VisitSVEIntCompareVectors(const Instruction * instr)8880 void Disassembler::VisitSVEIntCompareVectors(const Instruction *instr) {
8881 const char *mnemonic = "unimplemented";
8882 const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.d";
8883
8884 switch (instr->Mask(SVEIntCompareVectorsMask)) {
8885 case CMPEQ_p_p_zw:
8886 mnemonic = "cmpeq";
8887 break;
8888 case CMPEQ_p_p_zz:
8889 mnemonic = "cmpeq";
8890 form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8891 break;
8892 case CMPGE_p_p_zw:
8893 mnemonic = "cmpge";
8894 break;
8895 case CMPGE_p_p_zz:
8896 mnemonic = "cmpge";
8897 form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8898 break;
8899 case CMPGT_p_p_zw:
8900 mnemonic = "cmpgt";
8901 break;
8902 case CMPGT_p_p_zz:
8903 mnemonic = "cmpgt";
8904 form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8905 break;
8906 case CMPHI_p_p_zw:
8907 mnemonic = "cmphi";
8908 break;
8909 case CMPHI_p_p_zz:
8910 mnemonic = "cmphi";
8911 form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8912 break;
8913 case CMPHS_p_p_zw:
8914 mnemonic = "cmphs";
8915 break;
8916 case CMPHS_p_p_zz:
8917 mnemonic = "cmphs";
8918 form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8919 break;
8920 case CMPLE_p_p_zw:
8921 mnemonic = "cmple";
8922 break;
8923 case CMPLO_p_p_zw:
8924 mnemonic = "cmplo";
8925 break;
8926 case CMPLS_p_p_zw:
8927 mnemonic = "cmpls";
8928 break;
8929 case CMPLT_p_p_zw:
8930 mnemonic = "cmplt";
8931 break;
8932 case CMPNE_p_p_zw:
8933 mnemonic = "cmpne";
8934 break;
8935 case CMPNE_p_p_zz:
8936 mnemonic = "cmpne";
8937 form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8938 break;
8939 default:
8940 break;
8941 }
8942 Format(instr, mnemonic, form);
8943 }
8944
VisitSVEIntMulAddPredicated(const Instruction * instr)8945 void Disassembler::VisitSVEIntMulAddPredicated(const Instruction *instr) {
8946 const char *mnemonic = "unimplemented";
8947 const char *form = "(SVEIntMulAddPredicated)";
8948
8949 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
8950 case MAD_z_p_zzz:
8951 mnemonic = "mad";
8952 form = "'Zd.'t, 'Pgl/m, 'Zm.'t, 'Zn.'t";
8953 break;
8954 case MLA_z_p_zzz:
8955 mnemonic = "mla";
8956 form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
8957 break;
8958 case MLS_z_p_zzz:
8959 mnemonic = "mls";
8960 form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
8961 break;
8962 case MSB_z_p_zzz:
8963 mnemonic = "msb";
8964 form = "'Zd.'t, 'Pgl/m, 'Zm.'t, 'Zn.'t";
8965 break;
8966 default:
8967 break;
8968 }
8969 Format(instr, mnemonic, form);
8970 }
8971
VisitSVEIntMulAddUnpredicated(const Instruction * instr)8972 void Disassembler::VisitSVEIntMulAddUnpredicated(const Instruction *instr) {
8973 const char *mnemonic = "unimplemented";
8974 const char *form = "(SVEIntMulAddUnpredicated)";
8975
8976 if (static_cast<unsigned>(instr->GetSVESize()) >= kSRegSizeInBytesLog2) {
8977 form = "'Zd.'t, 'Zn.'tq, 'Zm.'tq";
8978 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
8979 case SDOT_z_zzz:
8980 mnemonic = "sdot";
8981 break;
8982 case UDOT_z_zzz:
8983 mnemonic = "udot";
8984 break;
8985 default:
8986 break;
8987 }
8988 }
8989
8990 Format(instr, mnemonic, form);
8991 }
8992
VisitSVEMovprfx(const Instruction * instr)8993 void Disassembler::VisitSVEMovprfx(const Instruction *instr) {
8994 const char *mnemonic = "unimplemented";
8995 const char *form = "(SVEMovprfx)";
8996
8997 if (instr->Mask(SVEMovprfxMask) == MOVPRFX_z_p_z) {
8998 mnemonic = "movprfx";
8999 form = "'Zd.'t, 'Pgl/'?16:mz, 'Zn.'t";
9000 }
9001
9002 Format(instr, mnemonic, form);
9003 }
9004
VisitSVEIntReduction(const Instruction * instr)9005 void Disassembler::VisitSVEIntReduction(const Instruction *instr) {
9006 const char *mnemonic = "unimplemented";
9007 const char *form = "'Vdv, 'Pgl, 'Zn.'t";
9008
9009 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
9010 switch (instr->Mask(SVEIntReductionLogicalMask)) {
9011 case ANDV_r_p_z:
9012 mnemonic = "andv";
9013 break;
9014 case EORV_r_p_z:
9015 mnemonic = "eorv";
9016 break;
9017 case ORV_r_p_z:
9018 mnemonic = "orv";
9019 break;
9020 default:
9021 break;
9022 }
9023 } else {
9024 switch (instr->Mask(SVEIntReductionMask)) {
9025 case SADDV_r_p_z:
9026 mnemonic = "saddv";
9027 form = "'Dd, 'Pgl, 'Zn.'t";
9028 break;
9029 case SMAXV_r_p_z:
9030 mnemonic = "smaxv";
9031 break;
9032 case SMINV_r_p_z:
9033 mnemonic = "sminv";
9034 break;
9035 case UADDV_r_p_z:
9036 mnemonic = "uaddv";
9037 form = "'Dd, 'Pgl, 'Zn.'t";
9038 break;
9039 case UMAXV_r_p_z:
9040 mnemonic = "umaxv";
9041 break;
9042 case UMINV_r_p_z:
9043 mnemonic = "uminv";
9044 break;
9045 default:
9046 break;
9047 }
9048 }
9049 Format(instr, mnemonic, form);
9050 }
9051
VisitSVEIntUnaryArithmeticPredicated(const Instruction * instr)9052 void Disassembler::VisitSVEIntUnaryArithmeticPredicated(
9053 const Instruction *instr) {
9054 const char *mnemonic = "unimplemented";
9055 const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
9056
9057 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
9058 case ABS_z_p_z:
9059 mnemonic = "abs";
9060 break;
9061 case CLS_z_p_z:
9062 mnemonic = "cls";
9063 break;
9064 case CLZ_z_p_z:
9065 mnemonic = "clz";
9066 break;
9067 case CNOT_z_p_z:
9068 mnemonic = "cnot";
9069 break;
9070 case CNT_z_p_z:
9071 mnemonic = "cnt";
9072 break;
9073 case FABS_z_p_z:
9074 mnemonic = "fabs";
9075 break;
9076 case FNEG_z_p_z:
9077 mnemonic = "fneg";
9078 break;
9079 case NEG_z_p_z:
9080 mnemonic = "neg";
9081 break;
9082 case NOT_z_p_z:
9083 mnemonic = "not";
9084 break;
9085 case SXTB_z_p_z:
9086 mnemonic = "sxtb";
9087 break;
9088 case SXTH_z_p_z:
9089 mnemonic = "sxth";
9090 break;
9091 case SXTW_z_p_z:
9092 mnemonic = "sxtw";
9093 break;
9094 case UXTB_z_p_z:
9095 mnemonic = "uxtb";
9096 break;
9097 case UXTH_z_p_z:
9098 mnemonic = "uxth";
9099 break;
9100 case UXTW_z_p_z:
9101 mnemonic = "uxtw";
9102 break;
9103 default:
9104 break;
9105 }
9106 Format(instr, mnemonic, form);
9107 }
9108
VisitSVEMulIndex(const Instruction * instr)9109 void Disassembler::VisitSVEMulIndex(const Instruction *instr) {
9110 const char *mnemonic = "unimplemented";
9111 const char *form = "(SVEMulIndex)";
9112
9113 switch (instr->Mask(SVEMulIndexMask)) {
9114 case SDOT_z_zzzi_d:
9115 mnemonic = "sdot";
9116 form = "'Zd.d, 'Zn.h, z'u1916.h['u2020]";
9117 break;
9118 case SDOT_z_zzzi_s:
9119 mnemonic = "sdot";
9120 form = "'Zd.s, 'Zn.b, z'u1816.b['u2019]";
9121 break;
9122 case UDOT_z_zzzi_d:
9123 mnemonic = "udot";
9124 form = "'Zd.d, 'Zn.h, z'u1916.h['u2020]";
9125 break;
9126 case UDOT_z_zzzi_s:
9127 mnemonic = "udot";
9128 form = "'Zd.s, 'Zn.b, z'u1816.b['u2019]";
9129 break;
9130 default:
9131 break;
9132 }
9133 Format(instr, mnemonic, form);
9134 }
9135
VisitSVEPermuteVectorExtract(const Instruction * instr)9136 void Disassembler::VisitSVEPermuteVectorExtract(const Instruction *instr) {
9137 const char *mnemonic = "unimplemented";
9138 const char *form = "(SVEPermuteVectorExtract)";
9139
9140 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
9141 case EXT_z_zi_des:
9142 mnemonic = "ext";
9143 form = "'Zd.b, 'Zd.b, 'Zn.b, #'u2016:1210";
9144 break;
9145 default:
9146 break;
9147 }
9148 Format(instr, mnemonic, form);
9149 }
9150
VisitSVEPermuteVectorInterleaving(const Instruction * instr)9151 void Disassembler::VisitSVEPermuteVectorInterleaving(const Instruction *instr) {
9152 const char *mnemonic = "unimplemented";
9153 const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
9154
9155 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
9156 case TRN1_z_zz:
9157 mnemonic = "trn1";
9158 break;
9159 case TRN2_z_zz:
9160 mnemonic = "trn2";
9161 break;
9162 case UZP1_z_zz:
9163 mnemonic = "uzp1";
9164 break;
9165 case UZP2_z_zz:
9166 mnemonic = "uzp2";
9167 break;
9168 case ZIP1_z_zz:
9169 mnemonic = "zip1";
9170 break;
9171 case ZIP2_z_zz:
9172 mnemonic = "zip2";
9173 break;
9174 default:
9175 break;
9176 }
9177 Format(instr, mnemonic, form);
9178 }
9179
VisitSVEPredicateCount(const Instruction * instr)9180 void Disassembler::VisitSVEPredicateCount(const Instruction *instr) {
9181 const char *mnemonic = "unimplemented";
9182 const char *form = "(SVEPredicateCount)";
9183
9184 switch (instr->Mask(SVEPredicateCountMask)) {
9185 case CNTP_r_p_p:
9186 mnemonic = "cntp";
9187 form = "'Xd, p'u1310, 'Pn.'t";
9188 break;
9189 default:
9190 break;
9191 }
9192 Format(instr, mnemonic, form);
9193 }
9194
VisitSVEPredicateLogical(const Instruction * instr)9195 void Disassembler::VisitSVEPredicateLogical(const Instruction *instr) {
9196 const char *mnemonic = "unimplemented";
9197 const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b";
9198
9199 int pd = instr->GetPd();
9200 int pn = instr->GetPn();
9201 int pm = instr->GetPm();
9202 int pg = instr->ExtractBits(13, 10);
9203
9204 switch (instr->Mask(SVEPredicateLogicalMask)) {
9205 case ANDS_p_p_pp_z:
9206 mnemonic = "ands";
9207 if (pn == pm) {
9208 mnemonic = "movs";
9209 form = "'Pd.b, p'u1310/z, 'Pn.b";
9210 }
9211 break;
9212 case AND_p_p_pp_z:
9213 mnemonic = "and";
9214 if (pn == pm) {
9215 mnemonic = "mov";
9216 form = "'Pd.b, p'u1310/z, 'Pn.b";
9217 }
9218 break;
9219 case BICS_p_p_pp_z:
9220 mnemonic = "bics";
9221 break;
9222 case BIC_p_p_pp_z:
9223 mnemonic = "bic";
9224 break;
9225 case EORS_p_p_pp_z:
9226 mnemonic = "eors";
9227 if (pm == pg) {
9228 mnemonic = "nots";
9229 form = "'Pd.b, 'Pm/z, 'Pn.b";
9230 }
9231 break;
9232 case EOR_p_p_pp_z:
9233 mnemonic = "eor";
9234 if (pm == pg) {
9235 mnemonic = "not";
9236 form = "'Pd.b, 'Pm/z, 'Pn.b";
9237 }
9238 break;
9239 case NANDS_p_p_pp_z:
9240 mnemonic = "nands";
9241 break;
9242 case NAND_p_p_pp_z:
9243 mnemonic = "nand";
9244 break;
9245 case NORS_p_p_pp_z:
9246 mnemonic = "nors";
9247 break;
9248 case NOR_p_p_pp_z:
9249 mnemonic = "nor";
9250 break;
9251 case ORNS_p_p_pp_z:
9252 mnemonic = "orns";
9253 break;
9254 case ORN_p_p_pp_z:
9255 mnemonic = "orn";
9256 break;
9257 case ORRS_p_p_pp_z:
9258 mnemonic = "orrs";
9259 if ((pn == pm) && (pn == pg)) {
9260 mnemonic = "movs";
9261 form = "'Pd.b, 'Pn.b";
9262 }
9263 break;
9264 case ORR_p_p_pp_z:
9265 mnemonic = "orr";
9266 if ((pn == pm) && (pn == pg)) {
9267 mnemonic = "mov";
9268 form = "'Pd.b, 'Pn.b";
9269 }
9270 break;
9271 case SEL_p_p_pp:
9272 if (pd == pm) {
9273 mnemonic = "mov";
9274 form = "'Pd.b, p'u1310/m, 'Pn.b";
9275 } else {
9276 mnemonic = "sel";
9277 form = "'Pd.b, p'u1310, 'Pn.b, 'Pm.b";
9278 }
9279 break;
9280 default:
9281 form = "(SVEPredicateLogical)";
9282 break;
9283 }
9284 Format(instr, mnemonic, form);
9285 }
9286
VisitSVEPredicateInitialize(const Instruction * instr)9287 void Disassembler::VisitSVEPredicateInitialize(const Instruction *instr) {
9288 // This group only contains PTRUE{S}, and there are no unallocated encodings.
9289 VIXL_STATIC_ASSERT(
9290 SVEPredicateInitializeMask ==
9291 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
9292 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
9293 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
9294
9295 const char *mnemonic = instr->ExtractBit(16) ? "ptrues" : "ptrue";
9296 const char *form = "'Pd.'t, 'Ipc";
9297 // Omit the pattern if it is the default ('ALL').
9298 if (instr->ExtractBits(9, 5) == SVE_ALL) form = "'Pd.'t";
9299 Format(instr, mnemonic, form);
9300 }
9301
VisitSVEPredicateNextActive(const Instruction * instr)9302 void Disassembler::VisitSVEPredicateNextActive(const Instruction *instr) {
9303 // This group only contains PNEXT, and there are no unallocated encodings.
9304 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
9305 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
9306
9307 Format(instr, "pnext", "'Pd.'t, 'Pn, 'Pd.'t");
9308 }
9309
VisitSVEPredicateReadFromFFR_Predicated(const Instruction * instr)9310 void Disassembler::VisitSVEPredicateReadFromFFR_Predicated(
9311 const Instruction *instr) {
9312 const char *mnemonic = "unimplemented";
9313 const char *form = "(SVEPredicateReadFromFFR_Predicated)";
9314 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
9315 case RDFFR_p_p_f:
9316 case RDFFRS_p_p_f:
9317 mnemonic = instr->ExtractBit(22) ? "rdffrs" : "rdffr";
9318 form = "'Pd.b, 'Pn/z";
9319 break;
9320 default:
9321 break;
9322 }
9323 Format(instr, mnemonic, form);
9324 }
9325
VisitSVEPropagateBreak(const Instruction * instr)9326 void Disassembler::VisitSVEPropagateBreak(const Instruction *instr) {
9327 const char *mnemonic = "unimplemented";
9328 const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b";
9329
9330 switch (instr->Mask(SVEPropagateBreakMask)) {
9331 case BRKPAS_p_p_pp:
9332 mnemonic = "brkpas";
9333 break;
9334 case BRKPA_p_p_pp:
9335 mnemonic = "brkpa";
9336 break;
9337 case BRKPBS_p_p_pp:
9338 mnemonic = "brkpbs";
9339 break;
9340 case BRKPB_p_p_pp:
9341 mnemonic = "brkpb";
9342 break;
9343 default:
9344 break;
9345 }
9346 Format(instr, mnemonic, form);
9347 }
9348
VisitSVEStackFrameAdjustment(const Instruction * instr)9349 void Disassembler::VisitSVEStackFrameAdjustment(const Instruction *instr) {
9350 const char *mnemonic = "unimplemented";
9351 const char *form = "'Xds, 'Xms, #'s1005";
9352
9353 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
9354 case ADDPL_r_ri:
9355 mnemonic = "addpl";
9356 break;
9357 case ADDVL_r_ri:
9358 mnemonic = "addvl";
9359 break;
9360 default:
9361 form = "(SVEStackFrameAdjustment)";
9362 break;
9363 }
9364
9365 Format(instr, mnemonic, form);
9366 }
9367
VisitSVEStackFrameSize(const Instruction * instr)9368 void Disassembler::VisitSVEStackFrameSize(const Instruction *instr) {
9369 const char *mnemonic = "unimplemented";
9370 const char *form = "(SVEStackFrameSize)";
9371
9372 switch (instr->Mask(SVEStackFrameSizeMask)) {
9373 case RDVL_r_i:
9374 mnemonic = "rdvl";
9375 form = "'Xd, #'s1005";
9376 break;
9377 default:
9378 break;
9379 }
9380
9381 Format(instr, mnemonic, form);
9382 }
9383
VisitSVEVectorSelect(const Instruction * instr)9384 void Disassembler::VisitSVEVectorSelect(const Instruction *instr) {
9385 const char *mnemonic = "unimplemented";
9386 const char *form = "(SVEVectorSelect)";
9387
9388 switch (instr->Mask(SVEVectorSelectMask)) {
9389 case SEL_z_p_zz:
9390 if (instr->GetRd() == instr->GetRm()) {
9391 mnemonic = "mov";
9392 form = "'Zd.'t, p'u1310/m, 'Zn.'t";
9393 } else {
9394 mnemonic = "sel";
9395 form = "'Zd.'t, p'u1310, 'Zn.'t, 'Zm.'t";
9396 }
9397 break;
9398 default:
9399 break;
9400 }
9401 Format(instr, mnemonic, form);
9402 }
9403
VisitSVEContiguousLoad_ScalarPlusImm(const Instruction * instr)9404 void Disassembler::VisitSVEContiguousLoad_ScalarPlusImm(
9405 const Instruction *instr) {
9406 const char *mnemonic = "unimplemented";
9407 const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
9408 const char *suffix =
9409 (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
9410
9411 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
9412 case LD1B_z_p_bi_u16:
9413 case LD1B_z_p_bi_u32:
9414 case LD1B_z_p_bi_u64:
9415 case LD1B_z_p_bi_u8:
9416 mnemonic = "ld1b";
9417 break;
9418 case LD1D_z_p_bi_u64:
9419 mnemonic = "ld1d";
9420 break;
9421 case LD1H_z_p_bi_u16:
9422 case LD1H_z_p_bi_u32:
9423 case LD1H_z_p_bi_u64:
9424 mnemonic = "ld1h";
9425 break;
9426 case LD1SB_z_p_bi_s16:
9427 case LD1SB_z_p_bi_s32:
9428 case LD1SB_z_p_bi_s64:
9429 mnemonic = "ld1sb";
9430 break;
9431 case LD1SH_z_p_bi_s32:
9432 case LD1SH_z_p_bi_s64:
9433 mnemonic = "ld1sh";
9434 break;
9435 case LD1SW_z_p_bi_s64:
9436 mnemonic = "ld1sw";
9437 break;
9438 case LD1W_z_p_bi_u32:
9439 case LD1W_z_p_bi_u64:
9440 mnemonic = "ld1w";
9441 break;
9442 default:
9443 form = "(SVEContiguousLoad_ScalarPlusImm)";
9444 suffix = NULL;
9445 break;
9446 }
9447
9448 Format(instr, mnemonic, form, suffix);
9449 }
9450
VisitSVEContiguousLoad_ScalarPlusScalar(const Instruction * instr)9451 void Disassembler::VisitSVEContiguousLoad_ScalarPlusScalar(
9452 const Instruction *instr) {
9453 const char *mnemonic = "unimplemented";
9454 const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns, 'Xm";
9455 const char *suffix = NULL;
9456
9457 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
9458 case LD1B_z_p_br_u16:
9459 case LD1B_z_p_br_u32:
9460 case LD1B_z_p_br_u64:
9461 case LD1B_z_p_br_u8:
9462 mnemonic = "ld1b";
9463 suffix = "]";
9464 break;
9465 case LD1D_z_p_br_u64:
9466 mnemonic = "ld1d";
9467 suffix = ", lsl #'u2423]";
9468 break;
9469 case LD1H_z_p_br_u16:
9470 case LD1H_z_p_br_u32:
9471 case LD1H_z_p_br_u64:
9472 mnemonic = "ld1h";
9473 suffix = ", lsl #'u2423]";
9474 break;
9475 case LD1SB_z_p_br_s16:
9476 case LD1SB_z_p_br_s32:
9477 case LD1SB_z_p_br_s64:
9478 mnemonic = "ld1sb";
9479 suffix = "]";
9480 break;
9481 case LD1SH_z_p_br_s32:
9482 case LD1SH_z_p_br_s64:
9483 mnemonic = "ld1sh";
9484 suffix = ", lsl #1]";
9485 break;
9486 case LD1SW_z_p_br_s64:
9487 mnemonic = "ld1sw";
9488 suffix = ", lsl #2]";
9489 break;
9490 case LD1W_z_p_br_u32:
9491 case LD1W_z_p_br_u64:
9492 mnemonic = "ld1w";
9493 suffix = ", lsl #'u2423]";
9494 break;
9495 default:
9496 form = "(SVEContiguousLoad_ScalarPlusScalar)";
9497 suffix = NULL;
9498 break;
9499 }
9500
9501 Format(instr, mnemonic, form, suffix);
9502 }
9503
VisitReserved(const Instruction * instr)9504 void Disassembler::VisitReserved(const Instruction *instr) {
9505 // UDF is the only instruction in this group, and the Decoder is precise.
9506 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
9507 Format(instr, "udf", "'IUdf");
9508 }
9509
9510
VisitUnimplemented(const Instruction * instr)9511 void Disassembler::VisitUnimplemented(const Instruction *instr) {
9512 Format(instr, "unimplemented", "(Unimplemented)");
9513 }
9514
9515
VisitUnallocated(const Instruction * instr)9516 void Disassembler::VisitUnallocated(const Instruction *instr) {
9517 Format(instr, "unallocated", "(Unallocated)");
9518 }
9519
9520
ProcessOutput(const Instruction *)9521 void Disassembler::ProcessOutput(const Instruction * /*instr*/) {
9522 // The base disasm does nothing more than disassembling into a buffer.
9523 }
9524
9525
AppendRegisterNameToOutput(const Instruction * instr,const CPURegister & reg)9526 void Disassembler::AppendRegisterNameToOutput(const Instruction *instr,
9527 const CPURegister ®) {
9528 USE(instr);
9529 VIXL_ASSERT(reg.IsValid());
9530 char reg_char;
9531
9532 if (reg.IsRegister()) {
9533 reg_char = reg.Is64Bits() ? 'x' : 'w';
9534 } else {
9535 VIXL_ASSERT(reg.IsVRegister());
9536 switch (reg.GetSizeInBits()) {
9537 case kBRegSize:
9538 reg_char = 'b';
9539 break;
9540 case kHRegSize:
9541 reg_char = 'h';
9542 break;
9543 case kSRegSize:
9544 reg_char = 's';
9545 break;
9546 case kDRegSize:
9547 reg_char = 'd';
9548 break;
9549 default:
9550 VIXL_ASSERT(reg.Is128Bits());
9551 reg_char = 'q';
9552 }
9553 }
9554
9555 if (reg.IsVRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
9556 // A core or scalar/vector register: [wx]0 - 30, [bhsdq]0 - 31.
9557 AppendToOutput("%c%d", reg_char, reg.GetCode());
9558 } else if (reg.Aliases(sp)) {
9559 // Disassemble w31/x31 as stack pointer wsp/sp.
9560 AppendToOutput("%s", reg.Is64Bits() ? "sp" : "wsp");
9561 } else {
9562 // Disassemble w31/x31 as zero register wzr/xzr.
9563 AppendToOutput("%czr", reg_char);
9564 }
9565 }
9566
9567
AppendPCRelativeOffsetToOutput(const Instruction * instr,int64_t offset)9568 void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction *instr,
9569 int64_t offset) {
9570 USE(instr);
9571 if (offset < 0) {
9572 // Cast to uint64_t so that INT64_MIN is handled in a well-defined way.
9573 uint64_t abs_offset = -static_cast<uint64_t>(offset);
9574 AppendToOutput("#-0x%" PRIx64, abs_offset);
9575 } else {
9576 AppendToOutput("#+0x%" PRIx64, offset);
9577 }
9578 }
9579
9580
AppendAddressToOutput(const Instruction * instr,const void * addr)9581 void Disassembler::AppendAddressToOutput(const Instruction *instr,
9582 const void *addr) {
9583 USE(instr);
9584 AppendToOutput("(addr 0x%" PRIxPTR ")", reinterpret_cast<uintptr_t>(addr));
9585 }
9586
9587
AppendCodeAddressToOutput(const Instruction * instr,const void * addr)9588 void Disassembler::AppendCodeAddressToOutput(const Instruction *instr,
9589 const void *addr) {
9590 AppendAddressToOutput(instr, addr);
9591 }
9592
9593
AppendDataAddressToOutput(const Instruction * instr,const void * addr)9594 void Disassembler::AppendDataAddressToOutput(const Instruction *instr,
9595 const void *addr) {
9596 AppendAddressToOutput(instr, addr);
9597 }
9598
9599
AppendCodeRelativeAddressToOutput(const Instruction * instr,const void * addr)9600 void Disassembler::AppendCodeRelativeAddressToOutput(const Instruction *instr,
9601 const void *addr) {
9602 USE(instr);
9603 int64_t rel_addr = CodeRelativeAddress(addr);
9604 if (rel_addr >= 0) {
9605 AppendToOutput("(addr 0x%" PRIx64 ")", rel_addr);
9606 } else {
9607 AppendToOutput("(addr -0x%" PRIx64 ")", -rel_addr);
9608 }
9609 }
9610
9611
AppendCodeRelativeCodeAddressToOutput(const Instruction * instr,const void * addr)9612 void Disassembler::AppendCodeRelativeCodeAddressToOutput(
9613 const Instruction *instr, const void *addr) {
9614 AppendCodeRelativeAddressToOutput(instr, addr);
9615 }
9616
9617
AppendCodeRelativeDataAddressToOutput(const Instruction * instr,const void * addr)9618 void Disassembler::AppendCodeRelativeDataAddressToOutput(
9619 const Instruction *instr, const void *addr) {
9620 AppendCodeRelativeAddressToOutput(instr, addr);
9621 }
9622
9623
MapCodeAddress(int64_t base_address,const Instruction * instr_address)9624 void Disassembler::MapCodeAddress(int64_t base_address,
9625 const Instruction *instr_address) {
9626 set_code_address_offset(base_address -
9627 reinterpret_cast<intptr_t>(instr_address));
9628 }
CodeRelativeAddress(const void * addr)9629 int64_t Disassembler::CodeRelativeAddress(const void *addr) {
9630 return reinterpret_cast<intptr_t>(addr) + code_address_offset();
9631 }
9632
9633
Format(const Instruction * instr,const char * mnemonic,const char * format0,const char * format1)9634 void Disassembler::Format(const Instruction *instr,
9635 const char *mnemonic,
9636 const char *format0,
9637 const char *format1) {
9638 VIXL_ASSERT(mnemonic != NULL);
9639 ResetOutput();
9640 Substitute(instr, mnemonic);
9641 if (format0 != NULL) {
9642 VIXL_ASSERT(buffer_pos_ < buffer_size_);
9643 buffer_[buffer_pos_++] = ' ';
9644 Substitute(instr, format0);
9645 if (format1 != NULL) {
9646 Substitute(instr, format1);
9647 }
9648 }
9649 VIXL_ASSERT(buffer_pos_ < buffer_size_);
9650 buffer_[buffer_pos_] = 0;
9651 ProcessOutput(instr);
9652 }
9653
9654
Substitute(const Instruction * instr,const char * string)9655 void Disassembler::Substitute(const Instruction *instr, const char *string) {
9656 char chr = *string++;
9657 while (chr != '\0') {
9658 if (chr == '\'') {
9659 string += SubstituteField(instr, string);
9660 } else {
9661 VIXL_ASSERT(buffer_pos_ < buffer_size_);
9662 buffer_[buffer_pos_++] = chr;
9663 }
9664 chr = *string++;
9665 }
9666 }
9667
9668
SubstituteField(const Instruction * instr,const char * format)9669 int Disassembler::SubstituteField(const Instruction *instr,
9670 const char *format) {
9671 switch (format[0]) {
9672 // NB. The remaining substitution prefix upper-case characters are: JU.
9673 case 'R': // Register. X or W, selected by sf (or alternative) bit.
9674 case 'F': // FP register. S or D, selected by type field.
9675 case 'V': // Vector register, V, vector format.
9676 case 'Z': // Scalable vector register.
9677 case 'W':
9678 case 'X':
9679 case 'B':
9680 case 'H':
9681 case 'S':
9682 case 'D':
9683 case 'Q':
9684 return SubstituteRegisterField(instr, format);
9685 case 'P':
9686 return SubstitutePredicateRegisterField(instr, format);
9687 case 'I':
9688 return SubstituteImmediateField(instr, format);
9689 case 'L':
9690 return SubstituteLiteralField(instr, format);
9691 case 'N':
9692 return SubstituteShiftField(instr, format);
9693 case 'C':
9694 return SubstituteConditionField(instr, format);
9695 case 'E':
9696 return SubstituteExtendField(instr, format);
9697 case 'A':
9698 return SubstitutePCRelAddressField(instr, format);
9699 case 'T':
9700 return SubstituteBranchTargetField(instr, format);
9701 case 'O':
9702 return SubstituteLSRegOffsetField(instr, format);
9703 case 'M':
9704 return SubstituteBarrierField(instr, format);
9705 case 'K':
9706 return SubstituteCrField(instr, format);
9707 case 'G':
9708 return SubstituteSysOpField(instr, format);
9709 case 'p':
9710 return SubstitutePrefetchField(instr, format);
9711 case 'u':
9712 case 's':
9713 return SubstituteIntField(instr, format);
9714 case 't':
9715 return SubstituteSVESize(instr, format);
9716 case '?':
9717 return SubstituteTernary(instr, format);
9718 default: {
9719 VIXL_UNREACHABLE();
9720 return 1;
9721 }
9722 }
9723 }
9724
GetRegNumForField(const Instruction * instr,char reg_prefix,const char * field)9725 std::pair<unsigned, unsigned> Disassembler::GetRegNumForField(
9726 const Instruction *instr, char reg_prefix, const char *field) {
9727 unsigned reg_num = UINT_MAX;
9728 unsigned field_len = 1;
9729
9730 switch (field[0]) {
9731 case 'd':
9732 reg_num = instr->GetRd();
9733 break;
9734 case 'n':
9735 reg_num = instr->GetRn();
9736 break;
9737 case 'm':
9738 reg_num = instr->GetRm();
9739 break;
9740 case 'e':
9741 // This is register Rm, but using a 4-bit specifier. Used in NEON
9742 // by-element instructions.
9743 reg_num = instr->GetRmLow16();
9744 break;
9745 case 'a':
9746 reg_num = instr->GetRa();
9747 break;
9748 case 's':
9749 reg_num = instr->GetRs();
9750 break;
9751 case 't':
9752 reg_num = instr->GetRt();
9753 break;
9754 default:
9755 VIXL_UNREACHABLE();
9756 }
9757
9758 switch (field[1]) {
9759 case '2':
9760 case '3':
9761 case '4':
9762 if ((reg_prefix == 'V') || (reg_prefix == 'Z')) { // Vt2/3/4, Zt2/3/4
9763 VIXL_ASSERT(field[0] == 't');
9764 reg_num = (reg_num + field[1] - '1') % 32;
9765 field_len++;
9766 } else {
9767 VIXL_ASSERT((field[0] == 't') && (field[1] == '2'));
9768 reg_num = instr->GetRt2();
9769 field_len++;
9770 }
9771 break;
9772 case '+': // Rt+, Rs+ (ie. Rt + 1, Rs + 1)
9773 VIXL_ASSERT((reg_prefix == 'W') || (reg_prefix == 'X'));
9774 VIXL_ASSERT((field[0] == 's') || (field[0] == 't'));
9775 reg_num++;
9776 field_len++;
9777 break;
9778 case 's': // Core registers that are (w)sp rather than zr.
9779 VIXL_ASSERT((reg_prefix == 'W') || (reg_prefix == 'X'));
9780 reg_num = (reg_num == kZeroRegCode) ? kSPRegInternalCode : reg_num;
9781 field_len++;
9782 break;
9783 }
9784
9785 VIXL_ASSERT(reg_num != UINT_MAX);
9786 return std::make_pair(reg_num, field_len);
9787 }
9788
SubstituteRegisterField(const Instruction * instr,const char * format)9789 int Disassembler::SubstituteRegisterField(const Instruction *instr,
9790 const char *format) {
9791 unsigned field_len = 1; // Initially, count only the first character.
9792
9793 // The first character of the register format field, eg R, X, S, etc.
9794 char reg_prefix = format[0];
9795
9796 // Pointer to the character after the prefix. This may be one of the standard
9797 // symbols representing a register encoding, or a two digit bit position,
9798 // handled by the following code.
9799 const char *reg_field = &format[1];
9800
9801 if (reg_prefix == 'R') {
9802 bool is_x = instr->GetSixtyFourBits();
9803 if (strspn(reg_field, "0123456789") == 2) { // r20d, r31n, etc.
9804 // Core W or X registers where the type is determined by a specified bit
9805 // position, eg. 'R20d, 'R05n. This is like the 'Rd syntax, where bit 31
9806 // is implicitly used to select between W and X.
9807 int bitpos = ((reg_field[0] - '0') * 10) + (reg_field[1] - '0');
9808 VIXL_ASSERT(bitpos <= 31);
9809 is_x = (instr->ExtractBit(bitpos) == 1);
9810 reg_field = &format[3];
9811 field_len += 2;
9812 }
9813 reg_prefix = is_x ? 'X' : 'W';
9814 }
9815
9816 std::pair<unsigned, unsigned> rn =
9817 GetRegNumForField(instr, reg_prefix, reg_field);
9818 unsigned reg_num = rn.first;
9819 field_len += rn.second;
9820
9821 if (reg_field[0] == 'm') {
9822 switch (reg_field[1]) {
9823 // Handle registers tagged with b (bytes), z (instruction), or
9824 // r (registers), used for address updates in NEON load/store
9825 // instructions.
9826 case 'r':
9827 case 'b':
9828 case 'z': {
9829 VIXL_ASSERT(reg_prefix == 'X');
9830 field_len = 3;
9831 char *eimm;
9832 int imm = static_cast<int>(strtol(®_field[2], &eimm, 10));
9833 field_len += eimm - ®_field[2];
9834 if (reg_num == 31) {
9835 switch (reg_field[1]) {
9836 case 'z':
9837 imm *= (1 << instr->GetNEONLSSize());
9838 break;
9839 case 'r':
9840 imm *= (instr->GetNEONQ() == 0) ? kDRegSizeInBytes
9841 : kQRegSizeInBytes;
9842 break;
9843 case 'b':
9844 break;
9845 }
9846 AppendToOutput("#%d", imm);
9847 return field_len;
9848 }
9849 break;
9850 }
9851 }
9852 }
9853
9854 CPURegister::RegisterType reg_type = CPURegister::kRegister;
9855 unsigned reg_size = kXRegSize;
9856
9857 if (reg_prefix == 'F') {
9858 switch (instr->GetFPType()) {
9859 case 3:
9860 reg_prefix = 'H';
9861 break;
9862 case 0:
9863 reg_prefix = 'S';
9864 break;
9865 default:
9866 reg_prefix = 'D';
9867 }
9868 }
9869
9870 switch (reg_prefix) {
9871 case 'W':
9872 reg_type = CPURegister::kRegister;
9873 reg_size = kWRegSize;
9874 break;
9875 case 'X':
9876 reg_type = CPURegister::kRegister;
9877 reg_size = kXRegSize;
9878 break;
9879 case 'B':
9880 reg_type = CPURegister::kVRegister;
9881 reg_size = kBRegSize;
9882 break;
9883 case 'H':
9884 reg_type = CPURegister::kVRegister;
9885 reg_size = kHRegSize;
9886 break;
9887 case 'S':
9888 reg_type = CPURegister::kVRegister;
9889 reg_size = kSRegSize;
9890 break;
9891 case 'D':
9892 reg_type = CPURegister::kVRegister;
9893 reg_size = kDRegSize;
9894 break;
9895 case 'Q':
9896 reg_type = CPURegister::kVRegister;
9897 reg_size = kQRegSize;
9898 break;
9899 case 'V':
9900 if (reg_field[1] == 'v') {
9901 reg_type = CPURegister::kVRegister;
9902 reg_size = 1 << (instr->GetSVESize() + 3);
9903 field_len++;
9904 break;
9905 }
9906 AppendToOutput("v%d", reg_num);
9907 return field_len;
9908 case 'Z':
9909 AppendToOutput("z%d", reg_num);
9910 return field_len;
9911 default:
9912 VIXL_UNREACHABLE();
9913 }
9914
9915 AppendRegisterNameToOutput(instr, CPURegister(reg_num, reg_size, reg_type));
9916
9917 return field_len;
9918 }
9919
SubstitutePredicateRegisterField(const Instruction * instr,const char * format)9920 int Disassembler::SubstitutePredicateRegisterField(const Instruction *instr,
9921 const char *format) {
9922 VIXL_ASSERT(format[0] == 'P');
9923 switch (format[1]) {
9924 // This field only supports P register that are always encoded in the same
9925 // position.
9926 case 'd':
9927 case 't':
9928 AppendToOutput("p%u", instr->GetPt());
9929 break;
9930 case 'n':
9931 AppendToOutput("p%u", instr->GetPn());
9932 break;
9933 case 'm':
9934 AppendToOutput("p%u", instr->GetPm());
9935 break;
9936 case 'g':
9937 VIXL_ASSERT(format[2] == 'l');
9938 AppendToOutput("p%u", instr->GetPgLow8());
9939 return 3;
9940 default:
9941 VIXL_UNREACHABLE();
9942 }
9943 return 2;
9944 }
9945
SubstituteImmediateField(const Instruction * instr,const char * format)9946 int Disassembler::SubstituteImmediateField(const Instruction *instr,
9947 const char *format) {
9948 VIXL_ASSERT(format[0] == 'I');
9949
9950 switch (format[1]) {
9951 case 'M': { // IMoveImm, IMoveNeg or IMoveLSL.
9952 if (format[5] == 'L') {
9953 AppendToOutput("#0x%" PRIx32, instr->GetImmMoveWide());
9954 if (instr->GetShiftMoveWide() > 0) {
9955 AppendToOutput(", lsl #%" PRId32, 16 * instr->GetShiftMoveWide());
9956 }
9957 } else {
9958 VIXL_ASSERT((format[5] == 'I') || (format[5] == 'N'));
9959 uint64_t imm = static_cast<uint64_t>(instr->GetImmMoveWide())
9960 << (16 * instr->GetShiftMoveWide());
9961 if (format[5] == 'N') imm = ~imm;
9962 if (!instr->GetSixtyFourBits()) imm &= UINT64_C(0xffffffff);
9963 AppendToOutput("#0x%" PRIx64, imm);
9964 }
9965 return 8;
9966 }
9967 case 'L': {
9968 switch (format[2]) {
9969 case 'L': { // ILLiteral - Immediate Load Literal.
9970 AppendToOutput("pc%+" PRId32,
9971 instr->GetImmLLiteral() *
9972 static_cast<int>(kLiteralEntrySize));
9973 return 9;
9974 }
9975 case 'S': { // ILS - Immediate Load/Store.
9976 // ILSi - As above, but an index field which must not be
9977 // omitted even if it is zero.
9978 bool is_index = format[3] == 'i';
9979 if (is_index || (instr->GetImmLS() != 0)) {
9980 AppendToOutput(", #%" PRId32, instr->GetImmLS());
9981 }
9982 return is_index ? 4 : 3;
9983 }
9984 case 'P': { // ILPx - Immediate Load/Store Pair, x = access size.
9985 // ILPxi - As above, but an index field which must not be
9986 // omitted even if it is zero.
9987 VIXL_ASSERT((format[3] >= '0') && (format[3] <= '9'));
9988 bool is_index = format[4] == 'i';
9989 if (is_index || (instr->GetImmLSPair() != 0)) {
9990 // format[3] is the scale value. Convert to a number.
9991 int scale = 1 << (format[3] - '0');
9992 AppendToOutput(", #%" PRId32, instr->GetImmLSPair() * scale);
9993 }
9994 return is_index ? 5 : 4;
9995 }
9996 case 'U': { // ILU - Immediate Load/Store Unsigned.
9997 if (instr->GetImmLSUnsigned() != 0) {
9998 int shift = instr->GetSizeLS();
9999 AppendToOutput(", #%" PRId32, instr->GetImmLSUnsigned() << shift);
10000 }
10001 return 3;
10002 }
10003 case 'F': { // ILF(CNR) - Immediate Rotation Value for Complex Numbers
10004 AppendToOutput("#%" PRId32, instr->GetImmRotFcmlaSca() * 90);
10005 return strlen("ILFCNR");
10006 }
10007 case 'A': { // ILA - Immediate Load with pointer authentication.
10008 if (instr->GetImmLSPAC() != 0) {
10009 AppendToOutput(", #%" PRId32, instr->GetImmLSPAC());
10010 }
10011 return 3;
10012 }
10013 default: {
10014 VIXL_UNIMPLEMENTED();
10015 return 0;
10016 }
10017 }
10018 }
10019 case 'C': { // ICondB - Immediate Conditional Branch.
10020 int64_t offset = instr->GetImmCondBranch() << 2;
10021 AppendPCRelativeOffsetToOutput(instr, offset);
10022 return 6;
10023 }
10024 case 'A': { // IAddSub.
10025 int64_t imm = instr->GetImmAddSub() << (12 * instr->GetImmAddSubShift());
10026 AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
10027 return 7;
10028 }
10029 case 'F': { // IFP, IFPNeon, IFPSve or IFPFBits.
10030 int imm8 = 0;
10031 int len = strlen("IFP");
10032 switch (format[3]) {
10033 case 'F':
10034 VIXL_ASSERT(strncmp(format, "IFPFBits", strlen("IFPFBits")) == 0);
10035 AppendToOutput("#%" PRId32, 64 - instr->GetFPScale());
10036 return strlen("IFPFBits");
10037 case 'N':
10038 VIXL_ASSERT(strncmp(format, "IFPNeon", strlen("IFPNeon")) == 0);
10039 imm8 = instr->GetImmNEONabcdefgh();
10040 len += strlen("Neon");
10041 break;
10042 case 'S':
10043 VIXL_ASSERT(strncmp(format, "IFPSve", strlen("IFPSve")) == 0);
10044 imm8 = instr->ExtractBits(12, 5);
10045 len += strlen("Sve");
10046 break;
10047 default:
10048 VIXL_ASSERT(strncmp(format, "IFP", strlen("IFP")) == 0);
10049 imm8 = instr->GetImmFP();
10050 break;
10051 }
10052 AppendToOutput("#0x%" PRIx32 " (%.4f)",
10053 imm8,
10054 Instruction::Imm8ToFP32(imm8));
10055 return len;
10056 }
10057 case 'H': { // IH - ImmHint
10058 AppendToOutput("#%" PRId32, instr->GetImmHint());
10059 return 2;
10060 }
10061 case 'T': { // ITri - Immediate Triangular Encoded.
10062 if (format[4] == 'S') {
10063 VIXL_ASSERT((format[5] == 'v') && (format[6] == 'e'));
10064 switch (format[7]) {
10065 case 'l':
10066 // SVE logical immediate encoding.
10067 AppendToOutput("#0x%" PRIx64, instr->GetSVEImmLogical());
10068 return 8;
10069 case 'p': {
10070 // SVE predicated shift immediate encoding, lsl.
10071 std::pair<int, int> shift_and_lane_size =
10072 instr->GetSVEImmShiftAndLaneSizeLog2(
10073 /* is_predicated = */ true);
10074 int lane_bits = 8 << shift_and_lane_size.second;
10075 AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first);
10076 return 8;
10077 }
10078 case 'q': {
10079 // SVE predicated shift immediate encoding, asr and lsr.
10080 std::pair<int, int> shift_and_lane_size =
10081 instr->GetSVEImmShiftAndLaneSizeLog2(
10082 /* is_predicated = */ true);
10083 AppendToOutput("#%" PRId32, shift_and_lane_size.first);
10084 return 8;
10085 }
10086 case 'r': {
10087 // SVE unpredicated shift immediate encoding, lsl.
10088 std::pair<int, int> shift_and_lane_size =
10089 instr->GetSVEImmShiftAndLaneSizeLog2(
10090 /* is_predicated = */ false);
10091 int lane_bits = 8 << shift_and_lane_size.second;
10092 AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first);
10093 return 8;
10094 }
10095 case 's': {
10096 // SVE unpredicated shift immediate encoding, asr and lsr.
10097 std::pair<int, int> shift_and_lane_size =
10098 instr->GetSVEImmShiftAndLaneSizeLog2(
10099 /* is_predicated = */ false);
10100 AppendToOutput("#%" PRId32, shift_and_lane_size.first);
10101 return 8;
10102 }
10103 default:
10104 VIXL_UNREACHABLE();
10105 return 0;
10106 }
10107 } else {
10108 AppendToOutput("#0x%" PRIx64, instr->GetImmLogical());
10109 return 4;
10110 }
10111 }
10112 case 'N': { // INzcv.
10113 int nzcv = (instr->GetNzcv() << Flags_offset);
10114 AppendToOutput("#%c%c%c%c",
10115 ((nzcv & NFlag) == 0) ? 'n' : 'N',
10116 ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
10117 ((nzcv & CFlag) == 0) ? 'c' : 'C',
10118 ((nzcv & VFlag) == 0) ? 'v' : 'V');
10119 return 5;
10120 }
10121 case 'P': { // IP - Conditional compare.
10122 AppendToOutput("#%" PRId32, instr->GetImmCondCmp());
10123 return 2;
10124 }
10125 case 'B': { // Bitfields.
10126 return SubstituteBitfieldImmediateField(instr, format);
10127 }
10128 case 'E': { // IExtract.
10129 AppendToOutput("#%" PRId32, instr->GetImmS());
10130 return 8;
10131 }
10132 case 't': { // It - Test and branch bit.
10133 AppendToOutput("#%" PRId32,
10134 (instr->GetImmTestBranchBit5() << 5) |
10135 instr->GetImmTestBranchBit40());
10136 return 2;
10137 }
10138 case 'S': { // ISveSvl - SVE 'mul vl' immediate for structured ld/st.
10139 VIXL_ASSERT(strncmp(format, "ISveSvl", 7) == 0);
10140 int imm = instr->ExtractSignedBits(19, 16);
10141 if (imm != 0) {
10142 int reg_count = instr->ExtractBits(22, 21) + 1;
10143 AppendToOutput(", #%d, mul vl", imm * reg_count);
10144 }
10145 return 7;
10146 }
10147 case 's': { // Is - Shift (immediate).
10148 switch (format[2]) {
10149 case '1': { // Is1 - SSHR.
10150 int shift = 16 << HighestSetBitPosition(instr->GetImmNEONImmh());
10151 shift -= instr->GetImmNEONImmhImmb();
10152 AppendToOutput("#%d", shift);
10153 return 3;
10154 }
10155 case '2': { // Is2 - SLI.
10156 int shift = instr->GetImmNEONImmhImmb();
10157 shift -= 8 << HighestSetBitPosition(instr->GetImmNEONImmh());
10158 AppendToOutput("#%d", shift);
10159 return 3;
10160 }
10161 default: {
10162 VIXL_UNIMPLEMENTED();
10163 return 0;
10164 }
10165 }
10166 }
10167 case 'D': { // IDebug - HLT and BRK instructions.
10168 AppendToOutput("#0x%" PRIx32, instr->GetImmException());
10169 return 6;
10170 }
10171 case 'U': { // IUdf - UDF immediate.
10172 AppendToOutput("#0x%" PRIx32, instr->GetImmUdf());
10173 return 4;
10174 }
10175 case 'V': { // Immediate Vector.
10176 switch (format[2]) {
10177 case 'F': {
10178 switch (format[5]) {
10179 // Convert 'rot' bit encodings into equivalent angle rotation
10180 case 'A':
10181 AppendToOutput("#%" PRId32,
10182 instr->GetImmRotFcadd() == 1 ? 270 : 90);
10183 break;
10184 case 'M':
10185 AppendToOutput("#%" PRId32, instr->GetImmRotFcmlaVec() * 90);
10186 break;
10187 }
10188 return strlen("IVFCN") + 1;
10189 }
10190 case 'E': { // IVExtract.
10191 AppendToOutput("#%" PRId32, instr->GetImmNEONExt());
10192 return 9;
10193 }
10194 case 'B': { // IVByElemIndex.
10195 int ret = strlen("IVByElemIndex");
10196 int vm_index = (instr->GetNEONH() << 1) | instr->GetNEONL();
10197 static const char *format_rot = "IVByElemIndexRot";
10198 static const char *format_fhm = "IVByElemIndexFHM";
10199 bool is_fhm = strncmp(format, format_fhm, strlen(format_fhm)) == 0;
10200 if (strncmp(format, format_rot, strlen(format_rot)) == 0) {
10201 // FCMLA uses 'H' bit index when SIZE is 2, else H:L
10202 if (instr->GetNEONSize() == 2) {
10203 vm_index = instr->GetNEONH();
10204 }
10205 ret = static_cast<int>(strlen(format_rot));
10206 } else if (is_fhm || (instr->GetNEONSize() == 0)) {
10207 // Half-precision FP ops use H:L:M bit index
10208 // Widening operations with H-sized operands also use H:L:M.
10209 vm_index = (instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) |
10210 instr->GetNEONM();
10211 if (is_fhm) ret = static_cast<int>(strlen(format_fhm));
10212 } else if (instr->GetNEONSize() == 1) {
10213 vm_index = (vm_index << 1) | instr->GetNEONM();
10214 }
10215 AppendToOutput("%d", vm_index);
10216 return ret;
10217 }
10218 case 'I': { // INS element.
10219 if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) {
10220 unsigned rd_index, rn_index;
10221 unsigned imm5 = instr->GetImmNEON5();
10222 unsigned imm4 = instr->GetImmNEON4();
10223 int tz = CountTrailingZeros(imm5, 32);
10224 if (tz <= 3) { // Defined for tz = 0 to 3 only.
10225 rd_index = imm5 >> (tz + 1);
10226 rn_index = imm4 >> tz;
10227 if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) {
10228 AppendToOutput("%d", rd_index);
10229 return strlen("IVInsIndex1");
10230 } else if (strncmp(format,
10231 "IVInsIndex2",
10232 strlen("IVInsIndex2")) == 0) {
10233 AppendToOutput("%d", rn_index);
10234 return strlen("IVInsIndex2");
10235 }
10236 }
10237 return 0;
10238 } else if (strncmp(format,
10239 "IVInsSVEIndex",
10240 strlen("IVInsSVEIndex")) == 0) {
10241 std::pair<int, int> index_and_lane_size =
10242 instr->GetSVEPermuteIndexAndLaneSizeLog2();
10243 AppendToOutput("%d", index_and_lane_size.first);
10244 return strlen("IVInsSVEIndex");
10245 }
10246 VIXL_FALLTHROUGH();
10247 }
10248 case 'L': { // IVLSLane[0123] - suffix indicates access size shift.
10249 AppendToOutput("%d", instr->GetNEONLSIndex(format[8] - '0'));
10250 return 9;
10251 }
10252 case 'M': { // Modified Immediate cases.
10253 if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) {
10254 uint64_t imm8 = instr->GetImmNEONabcdefgh();
10255 AppendToOutput("#0x%" PRIx64, imm8);
10256 return strlen("IVMIImm8");
10257 } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) {
10258 uint64_t imm8 = instr->GetImmNEONabcdefgh();
10259 uint64_t imm = 0;
10260 for (int i = 0; i < 8; ++i) {
10261 if (imm8 & (1 << i)) {
10262 imm |= (UINT64_C(0xff) << (8 * i));
10263 }
10264 }
10265 AppendToOutput("#0x%" PRIx64, imm);
10266 return strlen("IVMIImm");
10267 } else if (strncmp(format,
10268 "IVMIShiftAmt1",
10269 strlen("IVMIShiftAmt1")) == 0) {
10270 int cmode = instr->GetNEONCmode();
10271 int shift_amount = 8 * ((cmode >> 1) & 3);
10272 AppendToOutput("#%d", shift_amount);
10273 return strlen("IVMIShiftAmt1");
10274 } else if (strncmp(format,
10275 "IVMIShiftAmt2",
10276 strlen("IVMIShiftAmt2")) == 0) {
10277 int cmode = instr->GetNEONCmode();
10278 int shift_amount = 8 << (cmode & 1);
10279 AppendToOutput("#%d", shift_amount);
10280 return strlen("IVMIShiftAmt2");
10281 } else {
10282 VIXL_UNIMPLEMENTED();
10283 return 0;
10284 }
10285 }
10286 default: {
10287 VIXL_UNIMPLEMENTED();
10288 return 0;
10289 }
10290 }
10291 }
10292 case 'X': { // IX - CLREX instruction.
10293 AppendToOutput("#0x%" PRIx32, instr->GetCRm());
10294 return 2;
10295 }
10296 case 'Y': { // IY - system register immediate.
10297 switch (instr->GetImmSystemRegister()) {
10298 case NZCV:
10299 AppendToOutput("nzcv");
10300 break;
10301 case FPCR:
10302 AppendToOutput("fpcr");
10303 break;
10304 case RNDR:
10305 AppendToOutput("rndr");
10306 break;
10307 case RNDRRS:
10308 AppendToOutput("rndrrs");
10309 break;
10310 default:
10311 AppendToOutput("S%d_%d_c%d_c%d_%d",
10312 instr->GetSysOp0(),
10313 instr->GetSysOp1(),
10314 instr->GetCRn(),
10315 instr->GetCRm(),
10316 instr->GetSysOp2());
10317 break;
10318 }
10319 return 2;
10320 }
10321 case 'R': { // IR - Rotate right into flags.
10322 switch (format[2]) {
10323 case 'r': { // IRr - Rotate amount.
10324 AppendToOutput("#%d", instr->GetImmRMIFRotation());
10325 return 3;
10326 }
10327 default: {
10328 VIXL_UNIMPLEMENTED();
10329 return 0;
10330 }
10331 }
10332 }
10333 case 'p': { // Ipc - SVE predicate constraint specifier.
10334 VIXL_ASSERT(format[2] == 'c');
10335 unsigned pattern = instr->GetImmSVEPredicateConstraint();
10336 switch (pattern) {
10337 // VL1-VL8 are encoded directly.
10338 case SVE_VL1:
10339 case SVE_VL2:
10340 case SVE_VL3:
10341 case SVE_VL4:
10342 case SVE_VL5:
10343 case SVE_VL6:
10344 case SVE_VL7:
10345 case SVE_VL8:
10346 AppendToOutput("vl%u", pattern);
10347 break;
10348 // VL16-VL256 are encoded as log2(N) + c.
10349 case SVE_VL16:
10350 case SVE_VL32:
10351 case SVE_VL64:
10352 case SVE_VL128:
10353 case SVE_VL256:
10354 AppendToOutput("vl%u", 16 << (pattern - SVE_VL16));
10355 break;
10356 // Special cases.
10357 case SVE_POW2:
10358 AppendToOutput("pow2");
10359 break;
10360 case SVE_MUL4:
10361 AppendToOutput("mul4");
10362 break;
10363 case SVE_MUL3:
10364 AppendToOutput("mul3");
10365 break;
10366 case SVE_ALL:
10367 AppendToOutput("all");
10368 break;
10369 default:
10370 AppendToOutput("#0x%x", pattern);
10371 break;
10372 }
10373 return 3;
10374 }
10375 default: {
10376 VIXL_UNIMPLEMENTED();
10377 return 0;
10378 }
10379 }
10380 }
10381
10382
SubstituteBitfieldImmediateField(const Instruction * instr,const char * format)10383 int Disassembler::SubstituteBitfieldImmediateField(const Instruction *instr,
10384 const char *format) {
10385 VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
10386 unsigned r = instr->GetImmR();
10387 unsigned s = instr->GetImmS();
10388
10389 switch (format[2]) {
10390 case 'r': { // IBr.
10391 AppendToOutput("#%d", r);
10392 return 3;
10393 }
10394 case 's': { // IBs+1 or IBs-r+1.
10395 if (format[3] == '+') {
10396 AppendToOutput("#%d", s + 1);
10397 return 5;
10398 } else {
10399 VIXL_ASSERT(format[3] == '-');
10400 AppendToOutput("#%d", s - r + 1);
10401 return 7;
10402 }
10403 }
10404 case 'Z': { // IBZ-r.
10405 VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
10406 unsigned reg_size =
10407 (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
10408 AppendToOutput("#%d", reg_size - r);
10409 return 5;
10410 }
10411 default: {
10412 VIXL_UNREACHABLE();
10413 return 0;
10414 }
10415 }
10416 }
10417
10418
SubstituteLiteralField(const Instruction * instr,const char * format)10419 int Disassembler::SubstituteLiteralField(const Instruction *instr,
10420 const char *format) {
10421 VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
10422 USE(format);
10423
10424 const void *address = instr->GetLiteralAddress<const void *>();
10425 switch (instr->Mask(LoadLiteralMask)) {
10426 case LDR_w_lit:
10427 case LDR_x_lit:
10428 case LDRSW_x_lit:
10429 case LDR_s_lit:
10430 case LDR_d_lit:
10431 case LDR_q_lit:
10432 AppendCodeRelativeDataAddressToOutput(instr, address);
10433 break;
10434 case PRFM_lit: {
10435 // Use the prefetch hint to decide how to print the address.
10436 switch (instr->GetPrefetchHint()) {
10437 case 0x0: // PLD: prefetch for load.
10438 case 0x2: // PST: prepare for store.
10439 AppendCodeRelativeDataAddressToOutput(instr, address);
10440 break;
10441 case 0x1: // PLI: preload instructions.
10442 AppendCodeRelativeCodeAddressToOutput(instr, address);
10443 break;
10444 case 0x3: // Unallocated hint.
10445 AppendCodeRelativeAddressToOutput(instr, address);
10446 break;
10447 }
10448 break;
10449 }
10450 default:
10451 VIXL_UNREACHABLE();
10452 }
10453
10454 return 6;
10455 }
10456
10457
SubstituteShiftField(const Instruction * instr,const char * format)10458 int Disassembler::SubstituteShiftField(const Instruction *instr,
10459 const char *format) {
10460 VIXL_ASSERT(format[0] == 'N');
10461 VIXL_ASSERT(instr->GetShiftDP() <= 0x3);
10462
10463 switch (format[1]) {
10464 case 'D': { // NDP.
10465 VIXL_ASSERT(instr->GetShiftDP() != ROR);
10466 VIXL_FALLTHROUGH();
10467 }
10468 case 'L': { // NLo.
10469 if (instr->GetImmDPShift() != 0) {
10470 const char *shift_type[] = {"lsl", "lsr", "asr", "ror"};
10471 AppendToOutput(", %s #%" PRId32,
10472 shift_type[instr->GetShiftDP()],
10473 instr->GetImmDPShift());
10474 }
10475 return 3;
10476 }
10477 case 'S': { // NSveS (SVE structured load/store indexing shift).
10478 VIXL_ASSERT(strncmp(format, "NSveS", 5) == 0);
10479 int msz = instr->ExtractBits(24, 23);
10480 if (msz > 0) {
10481 AppendToOutput(", lsl #%d", msz);
10482 }
10483 return 5;
10484 }
10485 default:
10486 VIXL_UNIMPLEMENTED();
10487 return 0;
10488 }
10489 }
10490
10491
SubstituteConditionField(const Instruction * instr,const char * format)10492 int Disassembler::SubstituteConditionField(const Instruction *instr,
10493 const char *format) {
10494 VIXL_ASSERT(format[0] == 'C');
10495 const char *condition_code[] = {"eq",
10496 "ne",
10497 "hs",
10498 "lo",
10499 "mi",
10500 "pl",
10501 "vs",
10502 "vc",
10503 "hi",
10504 "ls",
10505 "ge",
10506 "lt",
10507 "gt",
10508 "le",
10509 "al",
10510 "nv"};
10511 int cond;
10512 switch (format[1]) {
10513 case 'B':
10514 cond = instr->GetConditionBranch();
10515 break;
10516 case 'I': {
10517 cond = InvertCondition(static_cast<Condition>(instr->GetCondition()));
10518 break;
10519 }
10520 default:
10521 cond = instr->GetCondition();
10522 }
10523 AppendToOutput("%s", condition_code[cond]);
10524 return 4;
10525 }
10526
10527
SubstitutePCRelAddressField(const Instruction * instr,const char * format)10528 int Disassembler::SubstitutePCRelAddressField(const Instruction *instr,
10529 const char *format) {
10530 VIXL_ASSERT((strcmp(format, "AddrPCRelByte") == 0) || // Used by `adr`.
10531 (strcmp(format, "AddrPCRelPage") == 0)); // Used by `adrp`.
10532
10533 int64_t offset = instr->GetImmPCRel();
10534
10535 // Compute the target address based on the effective address (after applying
10536 // code_address_offset). This is required for correct behaviour of adrp.
10537 const Instruction *base = instr + code_address_offset();
10538 if (format[9] == 'P') {
10539 offset *= kPageSize;
10540 base = AlignDown(base, kPageSize);
10541 }
10542 // Strip code_address_offset before printing, so we can use the
10543 // semantically-correct AppendCodeRelativeAddressToOutput.
10544 const void *target =
10545 reinterpret_cast<const void *>(base + offset - code_address_offset());
10546
10547 AppendPCRelativeOffsetToOutput(instr, offset);
10548 AppendToOutput(" ");
10549 AppendCodeRelativeAddressToOutput(instr, target);
10550 return 13;
10551 }
10552
10553
SubstituteBranchTargetField(const Instruction * instr,const char * format)10554 int Disassembler::SubstituteBranchTargetField(const Instruction *instr,
10555 const char *format) {
10556 VIXL_ASSERT(strncmp(format, "TImm", 4) == 0);
10557
10558 int64_t offset = 0;
10559 switch (format[5]) {
10560 // BImmUncn - unconditional branch immediate.
10561 case 'n':
10562 offset = instr->GetImmUncondBranch();
10563 break;
10564 // BImmCond - conditional branch immediate.
10565 case 'o':
10566 offset = instr->GetImmCondBranch();
10567 break;
10568 // BImmCmpa - compare and branch immediate.
10569 case 'm':
10570 offset = instr->GetImmCmpBranch();
10571 break;
10572 // BImmTest - test and branch immediate.
10573 case 'e':
10574 offset = instr->GetImmTestBranch();
10575 break;
10576 default:
10577 VIXL_UNIMPLEMENTED();
10578 }
10579 offset *= static_cast<int>(kInstructionSize);
10580 const void *target_address = reinterpret_cast<const void *>(instr + offset);
10581 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
10582
10583 AppendPCRelativeOffsetToOutput(instr, offset);
10584 AppendToOutput(" ");
10585 AppendCodeRelativeCodeAddressToOutput(instr, target_address);
10586
10587 return 8;
10588 }
10589
10590
SubstituteExtendField(const Instruction * instr,const char * format)10591 int Disassembler::SubstituteExtendField(const Instruction *instr,
10592 const char *format) {
10593 VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
10594 VIXL_ASSERT(instr->GetExtendMode() <= 7);
10595 USE(format);
10596
10597 const char *extend_mode[] =
10598 {"uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"};
10599
10600 // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
10601 // registers becomes lsl.
10602 if (((instr->GetRd() == kZeroRegCode) || (instr->GetRn() == kZeroRegCode)) &&
10603 (((instr->GetExtendMode() == UXTW) && (instr->GetSixtyFourBits() == 0)) ||
10604 (instr->GetExtendMode() == UXTX))) {
10605 if (instr->GetImmExtendShift() > 0) {
10606 AppendToOutput(", lsl #%" PRId32, instr->GetImmExtendShift());
10607 }
10608 } else {
10609 AppendToOutput(", %s", extend_mode[instr->GetExtendMode()]);
10610 if (instr->GetImmExtendShift() > 0) {
10611 AppendToOutput(" #%" PRId32, instr->GetImmExtendShift());
10612 }
10613 }
10614 return 3;
10615 }
10616
10617
SubstituteLSRegOffsetField(const Instruction * instr,const char * format)10618 int Disassembler::SubstituteLSRegOffsetField(const Instruction *instr,
10619 const char *format) {
10620 VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
10621 const char *extend_mode[] = {"undefined",
10622 "undefined",
10623 "uxtw",
10624 "lsl",
10625 "undefined",
10626 "undefined",
10627 "sxtw",
10628 "sxtx"};
10629 USE(format);
10630
10631 unsigned shift = instr->GetImmShiftLS();
10632 Extend ext = static_cast<Extend>(instr->GetExtendMode());
10633 char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
10634
10635 unsigned rm = instr->GetRm();
10636 if (rm == kZeroRegCode) {
10637 AppendToOutput("%czr", reg_type);
10638 } else {
10639 AppendToOutput("%c%d", reg_type, rm);
10640 }
10641
10642 // Extend mode UXTX is an alias for shift mode LSL here.
10643 if (!((ext == UXTX) && (shift == 0))) {
10644 AppendToOutput(", %s", extend_mode[ext]);
10645 if (shift != 0) {
10646 AppendToOutput(" #%d", instr->GetSizeLS());
10647 }
10648 }
10649 return 9;
10650 }
10651
10652
SubstitutePrefetchField(const Instruction * instr,const char * format)10653 int Disassembler::SubstitutePrefetchField(const Instruction *instr,
10654 const char *format) {
10655 VIXL_ASSERT(format[0] == 'p');
10656 USE(format);
10657
10658 bool is_sve =
10659 (strncmp(format, "prefSVEOp", strlen("prefSVEOp")) == 0) ? true : false;
10660 int placeholder_length = is_sve ? 9 : 6;
10661 static const char *stream_options[] = {"keep", "strm"};
10662
10663 auto get_hints = [](bool is_sve) -> std::vector<std::string> {
10664 static const std::vector<std::string> sve_hints = {"ld", "st"};
10665 static const std::vector<std::string> core_hints = {"ld", "li", "st"};
10666 return (is_sve) ? sve_hints : core_hints;
10667 };
10668
10669 std::vector<std::string> hints = get_hints(is_sve);
10670 unsigned hint =
10671 is_sve ? instr->GetSVEPrefetchHint() : instr->GetPrefetchHint();
10672 unsigned target = instr->GetPrefetchTarget() + 1;
10673 unsigned stream = instr->GetPrefetchStream();
10674
10675 if ((hint >= hints.size()) || (target > 3)) {
10676 // Unallocated prefetch operations.
10677 if (is_sve) {
10678 std::bitset<4> prefetch_mode(instr->GetSVEImmPrefetchOperation());
10679 AppendToOutput("#0b%s", prefetch_mode.to_string().c_str());
10680 } else {
10681 std::bitset<5> prefetch_mode(instr->GetImmPrefetchOperation());
10682 AppendToOutput("#0b%s", prefetch_mode.to_string().c_str());
10683 }
10684 } else {
10685 VIXL_ASSERT(stream < ArrayLength(stream_options));
10686 AppendToOutput("p%sl%d%s",
10687 hints[hint].c_str(),
10688 target,
10689 stream_options[stream]);
10690 }
10691 return placeholder_length;
10692 }
10693
SubstituteBarrierField(const Instruction * instr,const char * format)10694 int Disassembler::SubstituteBarrierField(const Instruction *instr,
10695 const char *format) {
10696 VIXL_ASSERT(format[0] == 'M');
10697 USE(format);
10698
10699 static const char *options[4][4] = {{"sy (0b0000)", "oshld", "oshst", "osh"},
10700 {"sy (0b0100)", "nshld", "nshst", "nsh"},
10701 {"sy (0b1000)", "ishld", "ishst", "ish"},
10702 {"sy (0b1100)", "ld", "st", "sy"}};
10703 int domain = instr->GetImmBarrierDomain();
10704 int type = instr->GetImmBarrierType();
10705
10706 AppendToOutput("%s", options[domain][type]);
10707 return 1;
10708 }
10709
SubstituteSysOpField(const Instruction * instr,const char * format)10710 int Disassembler::SubstituteSysOpField(const Instruction *instr,
10711 const char *format) {
10712 VIXL_ASSERT(format[0] == 'G');
10713 int op = -1;
10714 switch (format[1]) {
10715 case '1':
10716 op = instr->GetSysOp1();
10717 break;
10718 case '2':
10719 op = instr->GetSysOp2();
10720 break;
10721 default:
10722 VIXL_UNREACHABLE();
10723 }
10724 AppendToOutput("#%d", op);
10725 return 2;
10726 }
10727
SubstituteCrField(const Instruction * instr,const char * format)10728 int Disassembler::SubstituteCrField(const Instruction *instr,
10729 const char *format) {
10730 VIXL_ASSERT(format[0] == 'K');
10731 int cr = -1;
10732 switch (format[1]) {
10733 case 'n':
10734 cr = instr->GetCRn();
10735 break;
10736 case 'm':
10737 cr = instr->GetCRm();
10738 break;
10739 default:
10740 VIXL_UNREACHABLE();
10741 }
10742 AppendToOutput("C%d", cr);
10743 return 2;
10744 }
10745
SubstituteIntField(const Instruction * instr,const char * format)10746 int Disassembler::SubstituteIntField(const Instruction *instr,
10747 const char *format) {
10748 VIXL_ASSERT((format[0] == 'u') || (format[0] == 's'));
10749
10750 // A generic signed or unsigned int field uses a placeholder of the form
10751 // 'sAABB and 'uAABB respectively where AA and BB are two digit bit positions
10752 // between 00 and 31, and AA >= BB. The placeholder is substituted with the
10753 // decimal integer represented by the bits in the instruction between
10754 // positions AA and BB inclusive.
10755 //
10756 // In addition, split fields can be represented using 'sAABB:CCDD, where CCDD
10757 // become the least-significant bits of the result, and bit AA is the sign bit
10758 // (if 's is used).
10759 int32_t bits = 0;
10760 int width = 0;
10761 const char *c = format;
10762 do {
10763 c++; // Skip the 'u', 's' or ':'.
10764 VIXL_ASSERT(strspn(c, "0123456789") == 4);
10765 int msb = ((c[0] - '0') * 10) + (c[1] - '0');
10766 int lsb = ((c[2] - '0') * 10) + (c[3] - '0');
10767 c += 4; // Skip the characters we just read.
10768 int chunk_width = msb - lsb + 1;
10769 VIXL_ASSERT((chunk_width > 0) && (chunk_width < 32));
10770 bits = (bits << chunk_width) | (instr->ExtractBits(msb, lsb));
10771 width += chunk_width;
10772 } while (*c == ':');
10773 VIXL_ASSERT(IsUintN(width, bits));
10774
10775 if (format[0] == 's') {
10776 bits = ExtractSignedBitfield32(width - 1, 0, bits);
10777 }
10778
10779 if (*c == '+') {
10780 // A "+n" trailing the format specifier indicates the extracted value should
10781 // be incremented by n. This is for cases where the encoding is zero-based,
10782 // but range of values is not, eg. values [1, 16] encoded as [0, 15]
10783 char *new_c;
10784 uint64_t value = strtoul(c + 1, &new_c, 10);
10785 c = new_c;
10786 VIXL_ASSERT(IsInt32(value));
10787 bits += value;
10788 } else if (*c == '*') {
10789 // Similarly, a "*n" trailing the format specifier indicates the extracted
10790 // value should be multiplied by n. This is for cases where the encoded
10791 // immediate is scaled, for example by access size.
10792 char *new_c;
10793 uint64_t value = strtoul(c + 1, &new_c, 10);
10794 c = new_c;
10795 VIXL_ASSERT(IsInt32(value));
10796 bits *= value;
10797 }
10798
10799 AppendToOutput("%d", bits);
10800
10801 return static_cast<int>(c - format);
10802 }
10803
SubstituteSVESize(const Instruction * instr,const char * format)10804 int Disassembler::SubstituteSVESize(const Instruction *instr,
10805 const char *format) {
10806 USE(format);
10807 VIXL_ASSERT(format[0] == 't');
10808
10809 static const char sizes[] = {'b', 'h', 's', 'd', 'q'};
10810 // TODO: only the most common case for <size> is supported at the moment,
10811 // and even then, the RESERVED values are handled as if they're not
10812 // reserved.
10813 unsigned size_in_bytes_log2 = instr->GetSVESize();
10814 int placeholder_length = 1;
10815 switch (format[1]) {
10816 case 'l':
10817 placeholder_length++;
10818 if (format[2] == 's') {
10819 // 'tls: Loads and stores
10820 size_in_bytes_log2 = instr->ExtractBits(22, 21);
10821 placeholder_length++;
10822 if (format[3] == 's') {
10823 // Sign extension load.
10824 unsigned msize = instr->ExtractBits(24, 23);
10825 if (msize > size_in_bytes_log2) size_in_bytes_log2 ^= 0x3;
10826 placeholder_length++;
10827 }
10828 } else {
10829 // 'tl: Logical operations
10830 size_in_bytes_log2 = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
10831 }
10832 break;
10833 case 'm': // 'tmsz
10834 VIXL_ASSERT(strncmp(format, "tmsz", 4) == 0);
10835 placeholder_length += 3;
10836 size_in_bytes_log2 = instr->ExtractBits(24, 23);
10837 break;
10838 case 's':
10839 if (format[2] == 'z') {
10840 VIXL_ASSERT((format[3] == 'x') || (format[3] == 's') ||
10841 (format[3] == 'p'));
10842 if (format[3] == 'x') {
10843 // 'tszx: Indexes.
10844 std::pair<int, int> index_and_lane_size =
10845 instr->GetSVEPermuteIndexAndLaneSizeLog2();
10846 size_in_bytes_log2 = index_and_lane_size.second;
10847 } else if (format[3] == 'p') {
10848 // 'tszp: Predicated shifts.
10849 std::pair<int, int> shift_and_lane_size =
10850 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
10851 size_in_bytes_log2 = shift_and_lane_size.second;
10852 } else {
10853 // 'tszs: Unpredicated shifts.
10854 std::pair<int, int> shift_and_lane_size =
10855 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
10856 size_in_bytes_log2 = shift_and_lane_size.second;
10857 }
10858 placeholder_length += 3; // skip `sz[x|s]`
10859 }
10860 break;
10861 case 'h':
10862 // Half size of the lane size field.
10863 size_in_bytes_log2 -= 1;
10864 placeholder_length++;
10865 break;
10866 case 'q':
10867 // Quarter size of the lane size field.
10868 size_in_bytes_log2 -= 2;
10869 placeholder_length++;
10870 break;
10871 default:
10872 break;
10873 }
10874
10875 VIXL_ASSERT(size_in_bytes_log2 < ArrayLength(sizes));
10876 AppendToOutput("%c", sizes[size_in_bytes_log2]);
10877
10878 return placeholder_length;
10879 }
10880
SubstituteTernary(const Instruction * instr,const char * format)10881 int Disassembler::SubstituteTernary(const Instruction *instr,
10882 const char *format) {
10883 VIXL_ASSERT((format[0] == '?') && (format[3] == ':'));
10884
10885 // The ternary substitution of the format "'?bb:TF" is replaced by a single
10886 // character, either T or F, depending on the value of the bit at position
10887 // bb in the instruction. For example, "'?31:xw" is substituted with "x" if
10888 // bit 31 is true, and "w" otherwise.
10889 VIXL_ASSERT(strspn(&format[1], "0123456789") == 2);
10890 char *c;
10891 uint64_t value = strtoul(&format[1], &c, 10);
10892 VIXL_ASSERT(value < (kInstructionSize * kBitsPerByte));
10893 VIXL_ASSERT((*c == ':') && (strlen(c) >= 3)); // Minimum of ":TF"
10894 c++;
10895 AppendToOutput("%c", c[1 - instr->ExtractBit(static_cast<int>(value))]);
10896 return 6;
10897 }
10898
ResetOutput()10899 void Disassembler::ResetOutput() {
10900 buffer_pos_ = 0;
10901 buffer_[buffer_pos_] = 0;
10902 }
10903
10904
AppendToOutput(const char * format,...)10905 void Disassembler::AppendToOutput(const char *format, ...) {
10906 va_list args;
10907 va_start(args, format);
10908 buffer_pos_ += vsnprintf(&buffer_[buffer_pos_],
10909 buffer_size_ - buffer_pos_,
10910 format,
10911 args);
10912 va_end(args);
10913 }
10914
10915
Disassemble(const Instruction * instr)10916 void PrintDisassembler::Disassemble(const Instruction *instr) {
10917 Decoder decoder;
10918 if (cpu_features_auditor_ != NULL) {
10919 decoder.AppendVisitor(cpu_features_auditor_);
10920 }
10921 decoder.AppendVisitor(this);
10922 decoder.Decode(instr);
10923 }
10924
DisassembleBuffer(const Instruction * start,const Instruction * end)10925 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
10926 const Instruction *end) {
10927 Decoder decoder;
10928 if (cpu_features_auditor_ != NULL) {
10929 decoder.AppendVisitor(cpu_features_auditor_);
10930 }
10931 decoder.AppendVisitor(this);
10932 decoder.Decode(start, end);
10933 }
10934
DisassembleBuffer(const Instruction * start,uint64_t size)10935 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
10936 uint64_t size) {
10937 DisassembleBuffer(start, start + size);
10938 }
10939
10940
ProcessOutput(const Instruction * instr)10941 void PrintDisassembler::ProcessOutput(const Instruction *instr) {
10942 int64_t address = CodeRelativeAddress(instr);
10943
10944 uint64_t abs_address;
10945 const char *sign;
10946 if (signed_addresses_) {
10947 if (address < 0) {
10948 sign = "-";
10949 abs_address = -static_cast<uint64_t>(address);
10950 } else {
10951 // Leave a leading space, to maintain alignment.
10952 sign = " ";
10953 abs_address = address;
10954 }
10955 } else {
10956 sign = "";
10957 abs_address = address;
10958 }
10959
10960 int bytes_printed = fprintf(stream_,
10961 "%s0x%016" PRIx64 " %08" PRIx32 "\t\t%s",
10962 sign,
10963 abs_address,
10964 instr->GetInstructionBits(),
10965 GetOutput());
10966 if (cpu_features_auditor_ != NULL) {
10967 CPUFeatures needs = cpu_features_auditor_->GetInstructionFeatures();
10968 needs.Remove(cpu_features_auditor_->GetAvailableFeatures());
10969 if (needs != CPUFeatures::None()) {
10970 // Try to align annotations. This value is arbitrary, but based on looking
10971 // good with most instructions. Note that, for historical reasons, the
10972 // disassembly itself is printed with tab characters, so bytes_printed is
10973 // _not_ equivalent to the number of occupied screen columns. However, the
10974 // prefix before the tabs is always the same length, so the annotation
10975 // indentation does not change from one line to the next.
10976 const int indent_to = 70;
10977 // Always allow some space between the instruction and the annotation.
10978 const int min_pad = 2;
10979
10980 int pad = std::max(min_pad, (indent_to - bytes_printed));
10981 fprintf(stream_, "%*s", pad, "");
10982
10983 std::stringstream features;
10984 features << needs;
10985 fprintf(stream_,
10986 "%s%s%s",
10987 cpu_features_prefix_,
10988 features.str().c_str(),
10989 cpu_features_suffix_);
10990 }
10991 }
10992 fprintf(stream_, "\n");
10993 }
10994
10995 } // namespace aarch64
10996 } // namespace vixl
10997