V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
disasm-arm64.cc
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <assert.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <string.h>
9 
10 #if V8_TARGET_ARCH_ARM64
11 
12 #include "src/arm64/decoder-arm64-inl.h"
13 #include "src/arm64/disasm-arm64.h"
14 #include "src/arm64/utils-arm64.h"
15 #include "src/base/platform/platform.h"
16 #include "src/disasm.h"
17 #include "src/macro-assembler.h"
18 
19 namespace v8 {
20 namespace internal {
21 
22 
23 DisassemblingDecoder::DisassemblingDecoder() {
24  buffer_size_ = 256;
25  buffer_ = reinterpret_cast<char*>(malloc(buffer_size_));
26  buffer_pos_ = 0;
27  own_buffer_ = true;
28 }
29 
30 
31 DisassemblingDecoder::DisassemblingDecoder(char* text_buffer, int buffer_size) {
32  buffer_size_ = buffer_size;
33  buffer_ = text_buffer;
34  buffer_pos_ = 0;
35  own_buffer_ = false;
36 }
37 
38 
39 DisassemblingDecoder::~DisassemblingDecoder() {
40  if (own_buffer_) {
41  free(buffer_);
42  }
43 }
44 
45 
46 char* DisassemblingDecoder::GetOutput() { return buffer_; }
47 
48 
49 void DisassemblingDecoder::VisitAddSubImmediate(Instruction* instr) {
50  bool rd_is_zr = RdIsZROrSP(instr);
51  bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
52  (instr->ImmAddSub() == 0) ? true : false;
53  const char *mnemonic = "";
54  const char *form = "'Rds, 'Rns, 'IAddSub";
55  const char *form_cmp = "'Rns, 'IAddSub";
56  const char *form_mov = "'Rds, 'Rns";
57 
58  switch (instr->Mask(AddSubImmediateMask)) {
59  case ADD_w_imm:
60  case ADD_x_imm: {
61  mnemonic = "add";
62  if (stack_op) {
63  mnemonic = "mov";
64  form = form_mov;
65  }
66  break;
67  }
68  case ADDS_w_imm:
69  case ADDS_x_imm: {
70  mnemonic = "adds";
71  if (rd_is_zr) {
72  mnemonic = "cmn";
73  form = form_cmp;
74  }
75  break;
76  }
77  case SUB_w_imm:
78  case SUB_x_imm: mnemonic = "sub"; break;
79  case SUBS_w_imm:
80  case SUBS_x_imm: {
81  mnemonic = "subs";
82  if (rd_is_zr) {
83  mnemonic = "cmp";
84  form = form_cmp;
85  }
86  break;
87  }
88  default: UNREACHABLE();
89  }
90  Format(instr, mnemonic, form);
91 }
92 
93 
94 void DisassemblingDecoder::VisitAddSubShifted(Instruction* instr) {
95  bool rd_is_zr = RdIsZROrSP(instr);
96  bool rn_is_zr = RnIsZROrSP(instr);
97  const char *mnemonic = "";
98  const char* form = "'Rd, 'Rn, 'Rm'NDP";
99  const char* form_cmp = "'Rn, 'Rm'NDP";
100  const char* form_neg = "'Rd, 'Rm'NDP";
101 
102  switch (instr->Mask(AddSubShiftedMask)) {
103  case ADD_w_shift:
104  case ADD_x_shift: mnemonic = "add"; break;
105  case ADDS_w_shift:
106  case ADDS_x_shift: {
107  mnemonic = "adds";
108  if (rd_is_zr) {
109  mnemonic = "cmn";
110  form = form_cmp;
111  }
112  break;
113  }
114  case SUB_w_shift:
115  case SUB_x_shift: {
116  mnemonic = "sub";
117  if (rn_is_zr) {
118  mnemonic = "neg";
119  form = form_neg;
120  }
121  break;
122  }
123  case SUBS_w_shift:
124  case SUBS_x_shift: {
125  mnemonic = "subs";
126  if (rd_is_zr) {
127  mnemonic = "cmp";
128  form = form_cmp;
129  } else if (rn_is_zr) {
130  mnemonic = "negs";
131  form = form_neg;
132  }
133  break;
134  }
135  default: UNREACHABLE();
136  }
137  Format(instr, mnemonic, form);
138 }
139 
140 
141 void DisassemblingDecoder::VisitAddSubExtended(Instruction* instr) {
142  bool rd_is_zr = RdIsZROrSP(instr);
143  const char *mnemonic = "";
144  Extend mode = static_cast<Extend>(instr->ExtendMode());
145  const char *form = ((mode == UXTX) || (mode == SXTX)) ?
146  "'Rds, 'Rns, 'Xm'Ext" : "'Rds, 'Rns, 'Wm'Ext";
147  const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ?
148  "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
149 
150  switch (instr->Mask(AddSubExtendedMask)) {
151  case ADD_w_ext:
152  case ADD_x_ext: mnemonic = "add"; break;
153  case ADDS_w_ext:
154  case ADDS_x_ext: {
155  mnemonic = "adds";
156  if (rd_is_zr) {
157  mnemonic = "cmn";
158  form = form_cmp;
159  }
160  break;
161  }
162  case SUB_w_ext:
163  case SUB_x_ext: mnemonic = "sub"; break;
164  case SUBS_w_ext:
165  case SUBS_x_ext: {
166  mnemonic = "subs";
167  if (rd_is_zr) {
168  mnemonic = "cmp";
169  form = form_cmp;
170  }
171  break;
172  }
173  default: UNREACHABLE();
174  }
175  Format(instr, mnemonic, form);
176 }
177 
178 
179 void DisassemblingDecoder::VisitAddSubWithCarry(Instruction* instr) {
180  bool rn_is_zr = RnIsZROrSP(instr);
181  const char *mnemonic = "";
182  const char *form = "'Rd, 'Rn, 'Rm";
183  const char *form_neg = "'Rd, 'Rm";
184 
185  switch (instr->Mask(AddSubWithCarryMask)) {
186  case ADC_w:
187  case ADC_x: mnemonic = "adc"; break;
188  case ADCS_w:
189  case ADCS_x: mnemonic = "adcs"; break;
190  case SBC_w:
191  case SBC_x: {
192  mnemonic = "sbc";
193  if (rn_is_zr) {
194  mnemonic = "ngc";
195  form = form_neg;
196  }
197  break;
198  }
199  case SBCS_w:
200  case SBCS_x: {
201  mnemonic = "sbcs";
202  if (rn_is_zr) {
203  mnemonic = "ngcs";
204  form = form_neg;
205  }
206  break;
207  }
208  default: UNREACHABLE();
209  }
210  Format(instr, mnemonic, form);
211 }
212 
213 
214 void DisassemblingDecoder::VisitLogicalImmediate(Instruction* instr) {
215  bool rd_is_zr = RdIsZROrSP(instr);
216  bool rn_is_zr = RnIsZROrSP(instr);
217  const char *mnemonic = "";
218  const char *form = "'Rds, 'Rn, 'ITri";
219 
220  if (instr->ImmLogical() == 0) {
221  // The immediate encoded in the instruction is not in the expected format.
222  Format(instr, "unallocated", "(LogicalImmediate)");
223  return;
224  }
225 
226  switch (instr->Mask(LogicalImmediateMask)) {
227  case AND_w_imm:
228  case AND_x_imm: mnemonic = "and"; break;
229  case ORR_w_imm:
230  case ORR_x_imm: {
231  mnemonic = "orr";
232  unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
233  : kWRegSizeInBits;
234  if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) {
235  mnemonic = "mov";
236  form = "'Rds, 'ITri";
237  }
238  break;
239  }
240  case EOR_w_imm:
241  case EOR_x_imm: mnemonic = "eor"; break;
242  case ANDS_w_imm:
243  case ANDS_x_imm: {
244  mnemonic = "ands";
245  if (rd_is_zr) {
246  mnemonic = "tst";
247  form = "'Rn, 'ITri";
248  }
249  break;
250  }
251  default: UNREACHABLE();
252  }
253  Format(instr, mnemonic, form);
254 }
255 
256 
257 bool DisassemblingDecoder::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
258  DCHECK((reg_size == kXRegSizeInBits) ||
259  ((reg_size == kWRegSizeInBits) && (value <= 0xFFFFFFFF)));
260 
261  // Test for movz: 16-bits set at positions 0, 16, 32 or 48.
262  if (((value & 0xFFFFFFFFFFFF0000UL) == 0UL) ||
263  ((value & 0xFFFFFFFF0000FFFFUL) == 0UL) ||
264  ((value & 0xFFFF0000FFFFFFFFUL) == 0UL) ||
265  ((value & 0x0000FFFFFFFFFFFFUL) == 0UL)) {
266  return true;
267  }
268 
269  // Test for movn: NOT(16-bits set at positions 0, 16, 32 or 48).
270  if ((reg_size == kXRegSizeInBits) &&
271  (((value & 0xFFFFFFFFFFFF0000UL) == 0xFFFFFFFFFFFF0000UL) ||
272  ((value & 0xFFFFFFFF0000FFFFUL) == 0xFFFFFFFF0000FFFFUL) ||
273  ((value & 0xFFFF0000FFFFFFFFUL) == 0xFFFF0000FFFFFFFFUL) ||
274  ((value & 0x0000FFFFFFFFFFFFUL) == 0x0000FFFFFFFFFFFFUL))) {
275  return true;
276  }
277  if ((reg_size == kWRegSizeInBits) && (((value & 0xFFFF0000) == 0xFFFF0000) ||
278  ((value & 0x0000FFFF) == 0x0000FFFF))) {
279  return true;
280  }
281  return false;
282 }
283 
284 
285 void DisassemblingDecoder::VisitLogicalShifted(Instruction* instr) {
286  bool rd_is_zr = RdIsZROrSP(instr);
287  bool rn_is_zr = RnIsZROrSP(instr);
288  const char *mnemonic = "";
289  const char* form = "'Rd, 'Rn, 'Rm'NLo";
290 
291  switch (instr->Mask(LogicalShiftedMask)) {
292  case AND_w:
293  case AND_x: mnemonic = "and"; break;
294  case BIC_w:
295  case BIC_x: mnemonic = "bic"; break;
296  case EOR_w:
297  case EOR_x: mnemonic = "eor"; break;
298  case EON_w:
299  case EON_x: mnemonic = "eon"; break;
300  case BICS_w:
301  case BICS_x: mnemonic = "bics"; break;
302  case ANDS_w:
303  case ANDS_x: {
304  mnemonic = "ands";
305  if (rd_is_zr) {
306  mnemonic = "tst";
307  form = "'Rn, 'Rm'NLo";
308  }
309  break;
310  }
311  case ORR_w:
312  case ORR_x: {
313  mnemonic = "orr";
314  if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) {
315  mnemonic = "mov";
316  form = "'Rd, 'Rm";
317  }
318  break;
319  }
320  case ORN_w:
321  case ORN_x: {
322  mnemonic = "orn";
323  if (rn_is_zr) {
324  mnemonic = "mvn";
325  form = "'Rd, 'Rm'NLo";
326  }
327  break;
328  }
329  default: UNREACHABLE();
330  }
331 
332  Format(instr, mnemonic, form);
333 }
334 
335 
336 void DisassemblingDecoder::VisitConditionalCompareRegister(Instruction* instr) {
337  const char *mnemonic = "";
338  const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
339 
340  switch (instr->Mask(ConditionalCompareRegisterMask)) {
341  case CCMN_w:
342  case CCMN_x: mnemonic = "ccmn"; break;
343  case CCMP_w:
344  case CCMP_x: mnemonic = "ccmp"; break;
345  default: UNREACHABLE();
346  }
347  Format(instr, mnemonic, form);
348 }
349 
350 
351 void DisassemblingDecoder::VisitConditionalCompareImmediate(
352  Instruction* instr) {
353  const char *mnemonic = "";
354  const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
355 
356  switch (instr->Mask(ConditionalCompareImmediateMask)) {
357  case CCMN_w_imm:
358  case CCMN_x_imm: mnemonic = "ccmn"; break;
359  case CCMP_w_imm:
360  case CCMP_x_imm: mnemonic = "ccmp"; break;
361  default: UNREACHABLE();
362  }
363  Format(instr, mnemonic, form);
364 }
365 
366 
367 void DisassemblingDecoder::VisitConditionalSelect(Instruction* instr) {
368  bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
369  bool rn_is_rm = (instr->Rn() == instr->Rm());
370  const char *mnemonic = "";
371  const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
372  const char *form_test = "'Rd, 'CInv";
373  const char *form_update = "'Rd, 'Rn, 'CInv";
374 
375  Condition cond = static_cast<Condition>(instr->Condition());
376  bool invertible_cond = (cond != al) && (cond != nv);
377 
378  switch (instr->Mask(ConditionalSelectMask)) {
379  case CSEL_w:
380  case CSEL_x: mnemonic = "csel"; break;
381  case CSINC_w:
382  case CSINC_x: {
383  mnemonic = "csinc";
384  if (rnm_is_zr && invertible_cond) {
385  mnemonic = "cset";
386  form = form_test;
387  } else if (rn_is_rm && invertible_cond) {
388  mnemonic = "cinc";
389  form = form_update;
390  }
391  break;
392  }
393  case CSINV_w:
394  case CSINV_x: {
395  mnemonic = "csinv";
396  if (rnm_is_zr && invertible_cond) {
397  mnemonic = "csetm";
398  form = form_test;
399  } else if (rn_is_rm && invertible_cond) {
400  mnemonic = "cinv";
401  form = form_update;
402  }
403  break;
404  }
405  case CSNEG_w:
406  case CSNEG_x: {
407  mnemonic = "csneg";
408  if (rn_is_rm && invertible_cond) {
409  mnemonic = "cneg";
410  form = form_update;
411  }
412  break;
413  }
414  default: UNREACHABLE();
415  }
416  Format(instr, mnemonic, form);
417 }
418 
419 
420 void DisassemblingDecoder::VisitBitfield(Instruction* instr) {
421  unsigned s = instr->ImmS();
422  unsigned r = instr->ImmR();
423  unsigned rd_size_minus_1 =
424  ((instr->SixtyFourBits() == 1) ? kXRegSizeInBits : kWRegSizeInBits) - 1;
425  const char *mnemonic = "";
426  const char *form = "";
427  const char *form_shift_right = "'Rd, 'Rn, 'IBr";
428  const char *form_extend = "'Rd, 'Wn";
429  const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
430  const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
431  const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
432 
433  switch (instr->Mask(BitfieldMask)) {
434  case SBFM_w:
435  case SBFM_x: {
436  mnemonic = "sbfx";
437  form = form_bfx;
438  if (r == 0) {
439  form = form_extend;
440  if (s == 7) {
441  mnemonic = "sxtb";
442  } else if (s == 15) {
443  mnemonic = "sxth";
444  } else if ((s == 31) && (instr->SixtyFourBits() == 1)) {
445  mnemonic = "sxtw";
446  } else {
447  form = form_bfx;
448  }
449  } else if (s == rd_size_minus_1) {
450  mnemonic = "asr";
451  form = form_shift_right;
452  } else if (s < r) {
453  mnemonic = "sbfiz";
454  form = form_bfiz;
455  }
456  break;
457  }
458  case UBFM_w:
459  case UBFM_x: {
460  mnemonic = "ubfx";
461  form = form_bfx;
462  if (r == 0) {
463  form = form_extend;
464  if (s == 7) {
465  mnemonic = "uxtb";
466  } else if (s == 15) {
467  mnemonic = "uxth";
468  } else {
469  form = form_bfx;
470  }
471  }
472  if (s == rd_size_minus_1) {
473  mnemonic = "lsr";
474  form = form_shift_right;
475  } else if (r == s + 1) {
476  mnemonic = "lsl";
477  form = form_lsl;
478  } else if (s < r) {
479  mnemonic = "ubfiz";
480  form = form_bfiz;
481  }
482  break;
483  }
484  case BFM_w:
485  case BFM_x: {
486  mnemonic = "bfxil";
487  form = form_bfx;
488  if (s < r) {
489  mnemonic = "bfi";
490  form = form_bfiz;
491  }
492  }
493  }
494  Format(instr, mnemonic, form);
495 }
496 
497 
498 void DisassemblingDecoder::VisitExtract(Instruction* instr) {
499  const char *mnemonic = "";
500  const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
501 
502  switch (instr->Mask(ExtractMask)) {
503  case EXTR_w:
504  case EXTR_x: {
505  if (instr->Rn() == instr->Rm()) {
506  mnemonic = "ror";
507  form = "'Rd, 'Rn, 'IExtract";
508  } else {
509  mnemonic = "extr";
510  }
511  break;
512  }
513  default: UNREACHABLE();
514  }
515  Format(instr, mnemonic, form);
516 }
517 
518 
519 void DisassemblingDecoder::VisitPCRelAddressing(Instruction* instr) {
520  switch (instr->Mask(PCRelAddressingMask)) {
521  case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break;
522  // ADRP is not implemented.
523  default: Format(instr, "unimplemented", "(PCRelAddressing)");
524  }
525 }
526 
527 
528 void DisassemblingDecoder::VisitConditionalBranch(Instruction* instr) {
529  switch (instr->Mask(ConditionalBranchMask)) {
530  case B_cond:
531  Format(instr, "b.'CBrn", "'TImmCond");
532  break;
533  default: UNREACHABLE();
534  }
535 }
536 
537 
538 void DisassemblingDecoder::VisitUnconditionalBranchToRegister(
539  Instruction* instr) {
540  const char *mnemonic = "unimplemented";
541  const char *form = "'Xn";
542 
543  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
544  case BR: mnemonic = "br"; break;
545  case BLR: mnemonic = "blr"; break;
546  case RET: {
547  mnemonic = "ret";
548  if (instr->Rn() == kLinkRegCode) {
549  form = nullptr;
550  }
551  break;
552  }
553  default: form = "(UnconditionalBranchToRegister)";
554  }
555  Format(instr, mnemonic, form);
556 }
557 
558 
559 void DisassemblingDecoder::VisitUnconditionalBranch(Instruction* instr) {
560  const char *mnemonic = "";
561  const char* form = "'TImmUncn";
562 
563  switch (instr->Mask(UnconditionalBranchMask)) {
564  case B: mnemonic = "b"; break;
565  case BL: mnemonic = "bl"; break;
566  default: UNREACHABLE();
567  }
568  Format(instr, mnemonic, form);
569 }
570 
571 
572 void DisassemblingDecoder::VisitDataProcessing1Source(Instruction* instr) {
573  const char *mnemonic = "";
574  const char *form = "'Rd, 'Rn";
575 
576  switch (instr->Mask(DataProcessing1SourceMask)) {
577  #define FORMAT(A, B) \
578  case A##_w: \
579  case A##_x: mnemonic = B; break;
580  FORMAT(RBIT, "rbit");
581  FORMAT(REV16, "rev16");
582  FORMAT(REV, "rev");
583  FORMAT(CLZ, "clz");
584  FORMAT(CLS, "cls");
585  #undef FORMAT
586  case REV32_x: mnemonic = "rev32"; break;
587  default: UNREACHABLE();
588  }
589  Format(instr, mnemonic, form);
590 }
591 
592 
593 void DisassemblingDecoder::VisitDataProcessing2Source(Instruction* instr) {
594  const char *mnemonic = "unimplemented";
595  const char *form = "'Rd, 'Rn, 'Rm";
596 
597  switch (instr->Mask(DataProcessing2SourceMask)) {
598  #define FORMAT(A, B) \
599  case A##_w: \
600  case A##_x: mnemonic = B; break;
601  FORMAT(UDIV, "udiv");
602  FORMAT(SDIV, "sdiv");
603  FORMAT(LSLV, "lsl");
604  FORMAT(LSRV, "lsr");
605  FORMAT(ASRV, "asr");
606  FORMAT(RORV, "ror");
607  #undef FORMAT
608  default: form = "(DataProcessing2Source)";
609  }
610  Format(instr, mnemonic, form);
611 }
612 
613 
614 void DisassemblingDecoder::VisitDataProcessing3Source(Instruction* instr) {
615  bool ra_is_zr = RaIsZROrSP(instr);
616  const char *mnemonic = "";
617  const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
618  const char *form_rrr = "'Rd, 'Rn, 'Rm";
619  const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
620  const char *form_xww = "'Xd, 'Wn, 'Wm";
621  const char *form_xxx = "'Xd, 'Xn, 'Xm";
622 
623  switch (instr->Mask(DataProcessing3SourceMask)) {
624  case MADD_w:
625  case MADD_x: {
626  mnemonic = "madd";
627  form = form_rrrr;
628  if (ra_is_zr) {
629  mnemonic = "mul";
630  form = form_rrr;
631  }
632  break;
633  }
634  case MSUB_w:
635  case MSUB_x: {
636  mnemonic = "msub";
637  form = form_rrrr;
638  if (ra_is_zr) {
639  mnemonic = "mneg";
640  form = form_rrr;
641  }
642  break;
643  }
644  case SMADDL_x: {
645  mnemonic = "smaddl";
646  if (ra_is_zr) {
647  mnemonic = "smull";
648  form = form_xww;
649  }
650  break;
651  }
652  case SMSUBL_x: {
653  mnemonic = "smsubl";
654  if (ra_is_zr) {
655  mnemonic = "smnegl";
656  form = form_xww;
657  }
658  break;
659  }
660  case UMADDL_x: {
661  mnemonic = "umaddl";
662  if (ra_is_zr) {
663  mnemonic = "umull";
664  form = form_xww;
665  }
666  break;
667  }
668  case UMSUBL_x: {
669  mnemonic = "umsubl";
670  if (ra_is_zr) {
671  mnemonic = "umnegl";
672  form = form_xww;
673  }
674  break;
675  }
676  case SMULH_x: {
677  mnemonic = "smulh";
678  form = form_xxx;
679  break;
680  }
681  case UMULH_x: {
682  mnemonic = "umulh";
683  form = form_xxx;
684  break;
685  }
686  default: UNREACHABLE();
687  }
688  Format(instr, mnemonic, form);
689 }
690 
691 
692 void DisassemblingDecoder::VisitCompareBranch(Instruction* instr) {
693  const char *mnemonic = "";
694  const char* form = "'Rt, 'TImmCmpa";
695 
696  switch (instr->Mask(CompareBranchMask)) {
697  case CBZ_w:
698  case CBZ_x: mnemonic = "cbz"; break;
699  case CBNZ_w:
700  case CBNZ_x: mnemonic = "cbnz"; break;
701  default: UNREACHABLE();
702  }
703  Format(instr, mnemonic, form);
704 }
705 
706 
707 void DisassemblingDecoder::VisitTestBranch(Instruction* instr) {
708  const char *mnemonic = "";
709  // If the top bit of the immediate is clear, the tested register is
710  // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
711  // encoded in bit 31 of the instruction, we can reuse the Rt form, which
712  // uses bit 31 (normally "sf") to choose the register size.
713  const char* form = "'Rt, 'IS, 'TImmTest";
714 
715  switch (instr->Mask(TestBranchMask)) {
716  case TBZ: mnemonic = "tbz"; break;
717  case TBNZ: mnemonic = "tbnz"; break;
718  default: UNREACHABLE();
719  }
720  Format(instr, mnemonic, form);
721 }
722 
723 
724 void DisassemblingDecoder::VisitMoveWideImmediate(Instruction* instr) {
725  const char *mnemonic = "";
726  const char *form = "'Rd, 'IMoveImm";
727 
728  // Print the shift separately for movk, to make it clear which half word will
729  // be overwritten. Movn and movz print the computed immediate, which includes
730  // shift calculation.
731  switch (instr->Mask(MoveWideImmediateMask)) {
732  case MOVN_w:
733  case MOVN_x: mnemonic = "movn"; break;
734  case MOVZ_w:
735  case MOVZ_x: mnemonic = "movz"; break;
736  case MOVK_w:
737  case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
738  default: UNREACHABLE();
739  }
740  Format(instr, mnemonic, form);
741 }
742 
743 #define LOAD_STORE_LIST(V) \
744  V(STRB_w, "strb", "'Wt") \
745  V(STRH_w, "strh", "'Wt") \
746  V(STR_w, "str", "'Wt") \
747  V(STR_x, "str", "'Xt") \
748  V(LDRB_w, "ldrb", "'Wt") \
749  V(LDRH_w, "ldrh", "'Wt") \
750  V(LDR_w, "ldr", "'Wt") \
751  V(LDR_x, "ldr", "'Xt") \
752  V(LDRSB_x, "ldrsb", "'Xt") \
753  V(LDRSH_x, "ldrsh", "'Xt") \
754  V(LDRSW_x, "ldrsw", "'Xt") \
755  V(LDRSB_w, "ldrsb", "'Wt") \
756  V(LDRSH_w, "ldrsh", "'Wt") \
757  V(STR_b, "str", "'Bt") \
758  V(STR_h, "str", "'Ht") \
759  V(STR_s, "str", "'St") \
760  V(STR_d, "str", "'Dt") \
761  V(LDR_b, "ldr", "'Bt") \
762  V(LDR_h, "ldr", "'Ht") \
763  V(LDR_s, "ldr", "'St") \
764  V(LDR_d, "ldr", "'Dt") \
765  V(STR_q, "str", "'Qt") \
766  V(LDR_q, "ldr", "'Qt")
767 
768 void DisassemblingDecoder::VisitLoadStorePreIndex(Instruction* instr) {
769  const char *mnemonic = "unimplemented";
770  const char *form = "(LoadStorePreIndex)";
771 
772  switch (instr->Mask(LoadStorePreIndexMask)) {
773  #define LS_PREINDEX(A, B, C) \
774  case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break;
775  LOAD_STORE_LIST(LS_PREINDEX)
776  #undef LS_PREINDEX
777  }
778  Format(instr, mnemonic, form);
779 }
780 
781 
782 void DisassemblingDecoder::VisitLoadStorePostIndex(Instruction* instr) {
783  const char *mnemonic = "unimplemented";
784  const char *form = "(LoadStorePostIndex)";
785 
786  switch (instr->Mask(LoadStorePostIndexMask)) {
787  #define LS_POSTINDEX(A, B, C) \
788  case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break;
789  LOAD_STORE_LIST(LS_POSTINDEX)
790  #undef LS_POSTINDEX
791  }
792  Format(instr, mnemonic, form);
793 }
794 
795 
796 void DisassemblingDecoder::VisitLoadStoreUnsignedOffset(Instruction* instr) {
797  const char *mnemonic = "unimplemented";
798  const char *form = "(LoadStoreUnsignedOffset)";
799 
800  switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
801  #define LS_UNSIGNEDOFFSET(A, B, C) \
802  case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break;
803  LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
804  #undef LS_UNSIGNEDOFFSET
805  case PRFM_unsigned: mnemonic = "prfm"; form = "'PrefOp, ['Xn'ILU]";
806  }
807  Format(instr, mnemonic, form);
808 }
809 
810 
811 void DisassemblingDecoder::VisitLoadStoreRegisterOffset(Instruction* instr) {
812  const char *mnemonic = "unimplemented";
813  const char *form = "(LoadStoreRegisterOffset)";
814 
815  switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
816  #define LS_REGISTEROFFSET(A, B, C) \
817  case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break;
818  LOAD_STORE_LIST(LS_REGISTEROFFSET)
819  #undef LS_REGISTEROFFSET
820  case PRFM_reg: mnemonic = "prfm"; form = "'PrefOp, ['Xns, 'Offsetreg]";
821  }
822  Format(instr, mnemonic, form);
823 }
824 
825 #define LOAD_STORE_UNSCALED_LIST(V) \
826  V(STURB_w, "sturb", "'Wt") \
827  V(STURH_w, "sturh", "'Wt") \
828  V(STUR_w, "stur", "'Wt") \
829  V(STUR_x, "stur", "'Xt") \
830  V(LDURB_w, "ldurb", "'Wt") \
831  V(LDURH_w, "ldurh", "'Wt") \
832  V(LDUR_w, "ldur", "'Wt") \
833  V(LDUR_x, "ldur", "'Xt") \
834  V(LDURSB_x, "ldursb", "'Xt") \
835  V(LDURSH_x, "ldursh", "'Xt") \
836  V(LDURSW_x, "ldursw", "'Xt") \
837  V(LDURSB_w, "ldursb", "'Wt") \
838  V(LDURSH_w, "ldursh", "'Wt") \
839  V(STUR_b, "stur", "'Bt") \
840  V(STUR_h, "stur", "'Ht") \
841  V(STUR_s, "stur", "'St") \
842  V(STUR_d, "stur", "'Dt") \
843  V(LDUR_b, "ldur", "'Bt") \
844  V(LDUR_h, "ldur", "'Ht") \
845  V(LDUR_s, "ldur", "'St") \
846  V(LDUR_d, "ldur", "'Dt") \
847  V(STUR_q, "stur", "'Qt") \
848  V(LDUR_q, "ldur", "'Qt")
849 
850 void DisassemblingDecoder::VisitLoadStoreUnscaledOffset(Instruction* instr) {
851  const char* mnemonic = "unimplemented";
852  const char* form = "(LoadStoreUnscaledOffset)";
853 
854  switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
855 #define LS_UNSCALEDOFFSET(A, B, C) \
856  case A: \
857  mnemonic = B; \
858  form = C ", ['Xns'ILS]"; \
859  break;
860  LOAD_STORE_UNSCALED_LIST(LS_UNSCALEDOFFSET)
861 #undef LS_UNSCALEDOFFSET
862  }
863  Format(instr, mnemonic, form);
864 }
865 
866 void DisassemblingDecoder::VisitLoadLiteral(Instruction* instr) {
867  const char *mnemonic = "ldr";
868  const char *form = "(LoadLiteral)";
869 
870  switch (instr->Mask(LoadLiteralMask)) {
871  case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break;
872  case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break;
873  case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break;
874  case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break;
875  default: mnemonic = "unimplemented";
876  }
877  Format(instr, mnemonic, form);
878 }
879 
880 #define LOAD_STORE_PAIR_LIST(V) \
881  V(STP_w, "stp", "'Wt, 'Wt2", "2") \
882  V(LDP_w, "ldp", "'Wt, 'Wt2", "2") \
883  V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "2") \
884  V(STP_x, "stp", "'Xt, 'Xt2", "3") \
885  V(LDP_x, "ldp", "'Xt, 'Xt2", "3") \
886  V(STP_s, "stp", "'St, 'St2", "2") \
887  V(LDP_s, "ldp", "'St, 'St2", "2") \
888  V(STP_d, "stp", "'Dt, 'Dt2", "3") \
889  V(LDP_d, "ldp", "'Dt, 'Dt2", "3") \
890  V(LDP_q, "ldp", "'Qt, 'Qt2", "4") \
891  V(STP_q, "stp", "'Qt, 'Qt2", "4")
892 
893 void DisassemblingDecoder::VisitLoadStorePairPostIndex(Instruction* instr) {
894  const char *mnemonic = "unimplemented";
895  const char *form = "(LoadStorePairPostIndex)";
896 
897  switch (instr->Mask(LoadStorePairPostIndexMask)) {
898  #define LSP_POSTINDEX(A, B, C, D) \
899  case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break;
900  LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
901  #undef LSP_POSTINDEX
902  }
903  Format(instr, mnemonic, form);
904 }
905 
906 
907 void DisassemblingDecoder::VisitLoadStorePairPreIndex(Instruction* instr) {
908  const char *mnemonic = "unimplemented";
909  const char *form = "(LoadStorePairPreIndex)";
910 
911  switch (instr->Mask(LoadStorePairPreIndexMask)) {
912  #define LSP_PREINDEX(A, B, C, D) \
913  case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break;
914  LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
915  #undef LSP_PREINDEX
916  }
917  Format(instr, mnemonic, form);
918 }
919 
920 
921 void DisassemblingDecoder::VisitLoadStorePairOffset(Instruction* instr) {
922  const char *mnemonic = "unimplemented";
923  const char *form = "(LoadStorePairOffset)";
924 
925  switch (instr->Mask(LoadStorePairOffsetMask)) {
926  #define LSP_OFFSET(A, B, C, D) \
927  case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break;
928  LOAD_STORE_PAIR_LIST(LSP_OFFSET)
929  #undef LSP_OFFSET
930  }
931  Format(instr, mnemonic, form);
932 }
933 
934 void DisassemblingDecoder::VisitLoadStoreAcquireRelease(Instruction *instr) {
935  const char *mnemonic = "unimplemented";
936  const char* form = "'Wt, ['Xns]";
937  const char* form_x = "'Xt, ['Xns]";
938  const char* form_stlx = "'Ws, 'Wt, ['Xns]";
939  const char* form_stlx_x = "'Ws, 'Xt, ['Xns]";
940 
941  switch (instr->Mask(LoadStoreAcquireReleaseMask)) {
942  case LDAXR_b: mnemonic = "ldaxrb"; break;
943  case STLR_b: mnemonic = "stlrb"; break;
944  case LDAR_b: mnemonic = "ldarb"; break;
945  case LDAXR_h: mnemonic = "ldaxrh"; break;
946  case STLR_h: mnemonic = "stlrh"; break;
947  case LDAR_h: mnemonic = "ldarh"; break;
948  case LDAXR_w: mnemonic = "ldaxr"; break;
949  case STLR_w: mnemonic = "stlr"; break;
950  case LDAR_w: mnemonic = "ldar"; break;
951  case LDAXR_x: mnemonic = "ldaxr"; form = form_x; break;
952  case STLR_x: mnemonic = "stlr"; form = form_x; break;
953  case LDAR_x: mnemonic = "ldar"; form = form_x; break;
954  case STLXR_h: mnemonic = "stlxrh"; form = form_stlx; break;
955  case STLXR_b: mnemonic = "stlxrb"; form = form_stlx; break;
956  case STLXR_w: mnemonic = "stlxr"; form = form_stlx; break;
957  case STLXR_x: mnemonic = "stlxr"; form = form_stlx_x; break;
958  default:
959  form = "(LoadStoreAcquireRelease)";
960  }
961  Format(instr, mnemonic, form);
962 }
963 
964 void DisassemblingDecoder::VisitFPCompare(Instruction* instr) {
965  const char *mnemonic = "unimplemented";
966  const char *form = "'Fn, 'Fm";
967  const char *form_zero = "'Fn, #0.0";
968 
969  switch (instr->Mask(FPCompareMask)) {
970  case FCMP_s_zero:
971  case FCMP_d_zero: form = form_zero; V8_FALLTHROUGH;
972  case FCMP_s:
973  case FCMP_d: mnemonic = "fcmp"; break;
974  default: form = "(FPCompare)";
975  }
976  Format(instr, mnemonic, form);
977 }
978 
979 
980 void DisassemblingDecoder::VisitFPConditionalCompare(Instruction* instr) {
981  const char *mnemonic = "unimplemented";
982  const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
983 
984  switch (instr->Mask(FPConditionalCompareMask)) {
985  case FCCMP_s:
986  case FCCMP_d: mnemonic = "fccmp"; break;
987  case FCCMPE_s:
988  case FCCMPE_d: mnemonic = "fccmpe"; break;
989  default: form = "(FPConditionalCompare)";
990  }
991  Format(instr, mnemonic, form);
992 }
993 
994 
995 void DisassemblingDecoder::VisitFPConditionalSelect(Instruction* instr) {
996  const char *mnemonic = "";
997  const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
998 
999  switch (instr->Mask(FPConditionalSelectMask)) {
1000  case FCSEL_s:
1001  case FCSEL_d: mnemonic = "fcsel"; break;
1002  default: UNREACHABLE();
1003  }
1004  Format(instr, mnemonic, form);
1005 }
1006 
1007 
1008 void DisassemblingDecoder::VisitFPDataProcessing1Source(Instruction* instr) {
1009  const char *mnemonic = "unimplemented";
1010  const char *form = "'Fd, 'Fn";
1011 
1012  switch (instr->Mask(FPDataProcessing1SourceMask)) {
1013  #define FORMAT(A, B) \
1014  case A##_s: \
1015  case A##_d: mnemonic = B; break;
1016  FORMAT(FMOV, "fmov");
1017  FORMAT(FABS, "fabs");
1018  FORMAT(FNEG, "fneg");
1019  FORMAT(FSQRT, "fsqrt");
1020  FORMAT(FRINTN, "frintn");
1021  FORMAT(FRINTP, "frintp");
1022  FORMAT(FRINTM, "frintm");
1023  FORMAT(FRINTZ, "frintz");
1024  FORMAT(FRINTA, "frinta");
1025  FORMAT(FRINTX, "frintx");
1026  FORMAT(FRINTI, "frinti");
1027  #undef FORMAT
1028  case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break;
1029  case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break;
1030  case FCVT_hs:
1031  mnemonic = "fcvt";
1032  form = "'Hd, 'Sn";
1033  break;
1034  case FCVT_sh:
1035  mnemonic = "fcvt";
1036  form = "'Sd, 'Hn";
1037  break;
1038  case FCVT_dh:
1039  mnemonic = "fcvt";
1040  form = "'Dd, 'Hn";
1041  break;
1042  case FCVT_hd:
1043  mnemonic = "fcvt";
1044  form = "'Hd, 'Dn";
1045  break;
1046  default: form = "(FPDataProcessing1Source)";
1047  }
1048  Format(instr, mnemonic, form);
1049 }
1050 
1051 
1052 void DisassemblingDecoder::VisitFPDataProcessing2Source(Instruction* instr) {
1053  const char *mnemonic = "";
1054  const char *form = "'Fd, 'Fn, 'Fm";
1055 
1056  switch (instr->Mask(FPDataProcessing2SourceMask)) {
1057  #define FORMAT(A, B) \
1058  case A##_s: \
1059  case A##_d: mnemonic = B; break;
1060  FORMAT(FMUL, "fmul");
1061  FORMAT(FDIV, "fdiv");
1062  FORMAT(FADD, "fadd");
1063  FORMAT(FSUB, "fsub");
1064  FORMAT(FMAX, "fmax");
1065  FORMAT(FMIN, "fmin");
1066  FORMAT(FMAXNM, "fmaxnm");
1067  FORMAT(FMINNM, "fminnm");
1068  FORMAT(FNMUL, "fnmul");
1069  #undef FORMAT
1070  default: UNREACHABLE();
1071  }
1072  Format(instr, mnemonic, form);
1073 }
1074 
1075 
1076 void DisassemblingDecoder::VisitFPDataProcessing3Source(Instruction* instr) {
1077  const char *mnemonic = "";
1078  const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
1079 
1080  switch (instr->Mask(FPDataProcessing3SourceMask)) {
1081  #define FORMAT(A, B) \
1082  case A##_s: \
1083  case A##_d: mnemonic = B; break;
1084  FORMAT(FMADD, "fmadd");
1085  FORMAT(FMSUB, "fmsub");
1086  FORMAT(FNMADD, "fnmadd");
1087  FORMAT(FNMSUB, "fnmsub");
1088  #undef FORMAT
1089  default: UNREACHABLE();
1090  }
1091  Format(instr, mnemonic, form);
1092 }
1093 
1094 
1095 void DisassemblingDecoder::VisitFPImmediate(Instruction* instr) {
1096  const char *mnemonic = "";
1097  const char *form = "(FPImmediate)";
1098 
1099  switch (instr->Mask(FPImmediateMask)) {
1100  case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
1101  case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
1102  default: UNREACHABLE();
1103  }
1104  Format(instr, mnemonic, form);
1105 }
1106 
1107 
1108 void DisassemblingDecoder::VisitFPIntegerConvert(Instruction* instr) {
1109  const char *mnemonic = "unimplemented";
1110  const char *form = "(FPIntegerConvert)";
1111  const char *form_rf = "'Rd, 'Fn";
1112  const char *form_fr = "'Fd, 'Rn";
1113 
1114  switch (instr->Mask(FPIntegerConvertMask)) {
1115  case FMOV_ws:
1116  case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
1117  case FMOV_sw:
1118  case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
1119  case FMOV_d1_x:
1120  mnemonic = "fmov";
1121  form = "'Vd.D[1], 'Rn";
1122  break;
1123  case FMOV_x_d1:
1124  mnemonic = "fmov";
1125  form = "'Rd, 'Vn.D[1]";
1126  break;
1127  case FCVTAS_ws:
1128  case FCVTAS_xs:
1129  case FCVTAS_wd:
1130  case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break;
1131  case FCVTAU_ws:
1132  case FCVTAU_xs:
1133  case FCVTAU_wd:
1134  case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break;
1135  case FCVTMS_ws:
1136  case FCVTMS_xs:
1137  case FCVTMS_wd:
1138  case FCVTMS_xd: mnemonic = "fcvtms"; form = form_rf; break;
1139  case FCVTMU_ws:
1140  case FCVTMU_xs:
1141  case FCVTMU_wd:
1142  case FCVTMU_xd: mnemonic = "fcvtmu"; form = form_rf; break;
1143  case FCVTNS_ws:
1144  case FCVTNS_xs:
1145  case FCVTNS_wd:
1146  case FCVTNS_xd: mnemonic = "fcvtns"; form = form_rf; break;
1147  case FCVTNU_ws:
1148  case FCVTNU_xs:
1149  case FCVTNU_wd:
1150  case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break;
1151  case FCVTZU_xd:
1152  case FCVTZU_ws:
1153  case FCVTZU_wd:
1154  case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break;
1155  case FCVTZS_xd:
1156  case FCVTZS_wd:
1157  case FCVTZS_xs:
1158  case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break;
1159  case FCVTPU_xd:
1160  case FCVTPU_ws:
1161  case FCVTPU_wd:
1162  case FCVTPU_xs:
1163  mnemonic = "fcvtpu";
1164  form = form_rf;
1165  break;
1166  case FCVTPS_xd:
1167  case FCVTPS_wd:
1168  case FCVTPS_xs:
1169  case FCVTPS_ws:
1170  mnemonic = "fcvtps";
1171  form = form_rf;
1172  break;
1173  case SCVTF_sw:
1174  case SCVTF_sx:
1175  case SCVTF_dw:
1176  case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break;
1177  case UCVTF_sw:
1178  case UCVTF_sx:
1179  case UCVTF_dw:
1180  case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break;
1181  }
1182  Format(instr, mnemonic, form);
1183 }
1184 
1185 
1186 void DisassemblingDecoder::VisitFPFixedPointConvert(Instruction* instr) {
1187  const char *mnemonic = "";
1188  const char *form = "'Rd, 'Fn, 'IFPFBits";
1189  const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
1190 
1191  switch (instr->Mask(FPFixedPointConvertMask)) {
1192  case FCVTZS_ws_fixed:
1193  case FCVTZS_xs_fixed:
1194  case FCVTZS_wd_fixed:
1195  case FCVTZS_xd_fixed: mnemonic = "fcvtzs"; break;
1196  case FCVTZU_ws_fixed:
1197  case FCVTZU_xs_fixed:
1198  case FCVTZU_wd_fixed:
1199  case FCVTZU_xd_fixed: mnemonic = "fcvtzu"; break;
1200  case SCVTF_sw_fixed:
1201  case SCVTF_sx_fixed:
1202  case SCVTF_dw_fixed:
1203  case SCVTF_dx_fixed: mnemonic = "scvtf"; form = form_fr; break;
1204  case UCVTF_sw_fixed:
1205  case UCVTF_sx_fixed:
1206  case UCVTF_dw_fixed:
1207  case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
1208  }
1209  Format(instr, mnemonic, form);
1210 }
1211 
1212 
1213 void DisassemblingDecoder::VisitSystem(Instruction* instr) {
1214  // Some system instructions hijack their Op and Cp fields to represent a
1215  // range of immediates instead of indicating a different instruction. This
1216  // makes the decoding tricky.
1217  const char *mnemonic = "unimplemented";
1218  const char *form = "(System)";
1219 
1220  if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
1221  switch (instr->Mask(SystemSysRegMask)) {
1222  case MRS: {
1223  mnemonic = "mrs";
1224  switch (instr->ImmSystemRegister()) {
1225  case NZCV: form = "'Xt, nzcv"; break;
1226  case FPCR: form = "'Xt, fpcr"; break;
1227  default: form = "'Xt, (unknown)"; break;
1228  }
1229  break;
1230  }
1231  case MSR: {
1232  mnemonic = "msr";
1233  switch (instr->ImmSystemRegister()) {
1234  case NZCV: form = "nzcv, 'Xt"; break;
1235  case FPCR: form = "fpcr, 'Xt"; break;
1236  default: form = "(unknown), 'Xt"; break;
1237  }
1238  break;
1239  }
1240  }
1241  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
1242  DCHECK(instr->Mask(SystemHintMask) == HINT);
1243  switch (instr->ImmHint()) {
1244  case NOP: {
1245  mnemonic = "nop";
1246  form = nullptr;
1247  break;
1248  }
1249  case CSDB: {
1250  mnemonic = "csdb";
1251  form = nullptr;
1252  break;
1253  }
1254  }
1255  } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
1256  switch (instr->Mask(MemBarrierMask)) {
1257  case DMB: {
1258  mnemonic = "dmb";
1259  form = "'M";
1260  break;
1261  }
1262  case DSB: {
1263  mnemonic = "dsb";
1264  form = "'M";
1265  break;
1266  }
1267  case ISB: {
1268  mnemonic = "isb";
1269  form = nullptr;
1270  break;
1271  }
1272  }
1273  }
1274 
1275  Format(instr, mnemonic, form);
1276 }
1277 
1278 
1279 void DisassemblingDecoder::VisitException(Instruction* instr) {
1280  const char *mnemonic = "unimplemented";
1281  const char *form = "'IDebug";
1282 
1283  switch (instr->Mask(ExceptionMask)) {
1284  case HLT: mnemonic = "hlt"; break;
1285  case BRK: mnemonic = "brk"; break;
1286  case SVC: mnemonic = "svc"; break;
1287  case HVC: mnemonic = "hvc"; break;
1288  case SMC: mnemonic = "smc"; break;
1289  case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break;
1290  case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break;
1291  case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break;
1292  default: form = "(Exception)";
1293  }
1294  Format(instr, mnemonic, form);
1295 }
1296 
1297 void DisassemblingDecoder::VisitNEON3Same(Instruction* instr) {
1298  const char* mnemonic = "unimplemented";
1299  const char* form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
1300  NEONFormatDecoder nfd(instr);
1301 
1302  if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
1303  switch (instr->Mask(NEON3SameLogicalMask)) {
1304  case NEON_AND:
1305  mnemonic = "and";
1306  break;
1307  case NEON_ORR:
1308  mnemonic = "orr";
1309  if (instr->Rm() == instr->Rn()) {
1310  mnemonic = "mov";
1311  form = "'Vd.%s, 'Vn.%s";
1312  }
1313  break;
1314  case NEON_ORN:
1315  mnemonic = "orn";
1316  break;
1317  case NEON_EOR:
1318  mnemonic = "eor";
1319  break;
1320  case NEON_BIC:
1321  mnemonic = "bic";
1322  break;
1323  case NEON_BIF:
1324  mnemonic = "bif";
1325  break;
1326  case NEON_BIT:
1327  mnemonic = "bit";
1328  break;
1329  case NEON_BSL:
1330  mnemonic = "bsl";
1331  break;
1332  default:
1333  form = "(NEON3Same)";
1334  }
1335  nfd.SetFormatMaps(nfd.LogicalFormatMap());
1336  } else {
1337  static const char* mnemonics[] = {
1338  "shadd", "uhadd", "shadd", "uhadd",
1339  "sqadd", "uqadd", "sqadd", "uqadd",
1340  "srhadd", "urhadd", "srhadd", "urhadd",
1341  nullptr, nullptr, nullptr,
1342  nullptr, // Handled by logical cases above.
1343  "shsub", "uhsub", "shsub", "uhsub",
1344  "sqsub", "uqsub", "sqsub", "uqsub",
1345  "cmgt", "cmhi", "cmgt", "cmhi",
1346  "cmge", "cmhs", "cmge", "cmhs",
1347  "sshl", "ushl", "sshl", "ushl",
1348  "sqshl", "uqshl", "sqshl", "uqshl",
1349  "srshl", "urshl", "srshl", "urshl",
1350  "sqrshl", "uqrshl", "sqrshl", "uqrshl",
1351  "smax", "umax", "smax", "umax",
1352  "smin", "umin", "smin", "umin",
1353  "sabd", "uabd", "sabd", "uabd",
1354  "saba", "uaba", "saba", "uaba",
1355  "add", "sub", "add", "sub",
1356  "cmtst", "cmeq", "cmtst", "cmeq",
1357  "mla", "mls", "mla", "mls",
1358  "mul", "pmul", "mul", "pmul",
1359  "smaxp", "umaxp", "smaxp", "umaxp",
1360  "sminp", "uminp", "sminp", "uminp",
1361  "sqdmulh", "sqrdmulh", "sqdmulh", "sqrdmulh",
1362  "addp", "unallocated", "addp", "unallocated",
1363  "fmaxnm", "fmaxnmp", "fminnm", "fminnmp",
1364  "fmla", "unallocated", "fmls", "unallocated",
1365  "fadd", "faddp", "fsub", "fabd",
1366  "fmulx", "fmul", "unallocated", "unallocated",
1367  "fcmeq", "fcmge", "unallocated", "fcmgt",
1368  "unallocated", "facge", "unallocated", "facgt",
1369  "fmax", "fmaxp", "fmin", "fminp",
1370  "frecps", "fdiv", "frsqrts", "unallocated"};
1371 
1372  // Operation is determined by the opcode bits (15-11), the top bit of
1373  // size (23) and the U bit (29).
1374  unsigned index =
1375  (instr->Bits(15, 11) << 2) | (instr->Bit(23) << 1) | instr->Bit(29);
1376  DCHECK_LT(index, arraysize(mnemonics));
1377  mnemonic = mnemonics[index];
1378  // Assert that index is not one of the previously handled logical
1379  // instructions.
1380  DCHECK_NOT_NULL(mnemonic);
1381 
1382  if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
1383  nfd.SetFormatMaps(nfd.FPFormatMap());
1384  }
1385  }
1386  Format(instr, mnemonic, nfd.Substitute(form));
1387 }
1388 
1389 void DisassemblingDecoder::VisitNEON2RegMisc(Instruction* instr) {
1390  const char* mnemonic = "unimplemented";
1391  const char* form = "'Vd.%s, 'Vn.%s";
1392  const char* form_cmp_zero = "'Vd.%s, 'Vn.%s, #0";
1393  const char* form_fcmp_zero = "'Vd.%s, 'Vn.%s, #0.0";
1394  NEONFormatDecoder nfd(instr);
1395 
1396  static const NEONFormatMap map_lp_ta = {
1397  {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
1398 
1399  static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}};
1400 
1401  static const NEONFormatMap map_cvt_tb = {{22, 30},
1402  {NF_4H, NF_8H, NF_2S, NF_4S}};
1403 
1404  if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
1405  // These instructions all use a two bit size field, except NOT and RBIT,
1406  // which use the field to encode the operation.
1407  switch (instr->Mask(NEON2RegMiscMask)) {
1408  case NEON_REV64:
1409  mnemonic = "rev64";
1410  break;
1411  case NEON_REV32:
1412  mnemonic = "rev32";
1413  break;
1414  case NEON_REV16:
1415  mnemonic = "rev16";
1416  break;
1417  case NEON_SADDLP:
1418  mnemonic = "saddlp";
1419  nfd.SetFormatMap(0, &map_lp_ta);
1420  break;
1421  case NEON_UADDLP:
1422  mnemonic = "uaddlp";
1423  nfd.SetFormatMap(0, &map_lp_ta);
1424  break;
1425  case NEON_SUQADD:
1426  mnemonic = "suqadd";
1427  break;
1428  case NEON_USQADD:
1429  mnemonic = "usqadd";
1430  break;
1431  case NEON_CLS:
1432  mnemonic = "cls";
1433  break;
1434  case NEON_CLZ:
1435  mnemonic = "clz";
1436  break;
1437  case NEON_CNT:
1438  mnemonic = "cnt";
1439  break;
1440  case NEON_SADALP:
1441  mnemonic = "sadalp";
1442  nfd.SetFormatMap(0, &map_lp_ta);
1443  break;
1444  case NEON_UADALP:
1445  mnemonic = "uadalp";
1446  nfd.SetFormatMap(0, &map_lp_ta);
1447  break;
1448  case NEON_SQABS:
1449  mnemonic = "sqabs";
1450  break;
1451  case NEON_SQNEG:
1452  mnemonic = "sqneg";
1453  break;
1454  case NEON_CMGT_zero:
1455  mnemonic = "cmgt";
1456  form = form_cmp_zero;
1457  break;
1458  case NEON_CMGE_zero:
1459  mnemonic = "cmge";
1460  form = form_cmp_zero;
1461  break;
1462  case NEON_CMEQ_zero:
1463  mnemonic = "cmeq";
1464  form = form_cmp_zero;
1465  break;
1466  case NEON_CMLE_zero:
1467  mnemonic = "cmle";
1468  form = form_cmp_zero;
1469  break;
1470  case NEON_CMLT_zero:
1471  mnemonic = "cmlt";
1472  form = form_cmp_zero;
1473  break;
1474  case NEON_ABS:
1475  mnemonic = "abs";
1476  break;
1477  case NEON_NEG:
1478  mnemonic = "neg";
1479  break;
1480  case NEON_RBIT_NOT:
1481  switch (instr->FPType()) {
1482  case 0:
1483  mnemonic = "mvn";
1484  break;
1485  case 1:
1486  mnemonic = "rbit";
1487  break;
1488  default:
1489  form = "(NEON2RegMisc)";
1490  }
1491  nfd.SetFormatMaps(nfd.LogicalFormatMap());
1492  break;
1493  }
1494  } else {
1495  // These instructions all use a one bit size field, except XTN, SQXTUN,
1496  // SHLL, SQXTN and UQXTN, which use a two bit size field.
1497  nfd.SetFormatMaps(nfd.FPFormatMap());
1498  switch (instr->Mask(NEON2RegMiscFPMask)) {
1499  case NEON_FABS:
1500  mnemonic = "fabs";
1501  break;
1502  case NEON_FNEG:
1503  mnemonic = "fneg";
1504  break;
1505  case NEON_FCVTN:
1506  mnemonic = instr->Mask(NEON_Q) ? "fcvtn2" : "fcvtn";
1507  nfd.SetFormatMap(0, &map_cvt_tb);
1508  nfd.SetFormatMap(1, &map_cvt_ta);
1509  break;
1510  case NEON_FCVTXN:
1511  mnemonic = instr->Mask(NEON_Q) ? "fcvtxn2" : "fcvtxn";
1512  nfd.SetFormatMap(0, &map_cvt_tb);
1513  nfd.SetFormatMap(1, &map_cvt_ta);
1514  break;
1515  case NEON_FCVTL:
1516  mnemonic = instr->Mask(NEON_Q) ? "fcvtl2" : "fcvtl";
1517  nfd.SetFormatMap(0, &map_cvt_ta);
1518  nfd.SetFormatMap(1, &map_cvt_tb);
1519  break;
1520  case NEON_FRINTN:
1521  mnemonic = "frintn";
1522  break;
1523  case NEON_FRINTA:
1524  mnemonic = "frinta";
1525  break;
1526  case NEON_FRINTP:
1527  mnemonic = "frintp";
1528  break;
1529  case NEON_FRINTM:
1530  mnemonic = "frintm";
1531  break;
1532  case NEON_FRINTX:
1533  mnemonic = "frintx";
1534  break;
1535  case NEON_FRINTZ:
1536  mnemonic = "frintz";
1537  break;
1538  case NEON_FRINTI:
1539  mnemonic = "frinti";
1540  break;
1541  case NEON_FCVTNS:
1542  mnemonic = "fcvtns";
1543  break;
1544  case NEON_FCVTNU:
1545  mnemonic = "fcvtnu";
1546  break;
1547  case NEON_FCVTPS:
1548  mnemonic = "fcvtps";
1549  break;
1550  case NEON_FCVTPU:
1551  mnemonic = "fcvtpu";
1552  break;
1553  case NEON_FCVTMS:
1554  mnemonic = "fcvtms";
1555  break;
1556  case NEON_FCVTMU:
1557  mnemonic = "fcvtmu";
1558  break;
1559  case NEON_FCVTZS:
1560  mnemonic = "fcvtzs";
1561  break;
1562  case NEON_FCVTZU:
1563  mnemonic = "fcvtzu";
1564  break;
1565  case NEON_FCVTAS:
1566  mnemonic = "fcvtas";
1567  break;
1568  case NEON_FCVTAU:
1569  mnemonic = "fcvtau";
1570  break;
1571  case NEON_FSQRT:
1572  mnemonic = "fsqrt";
1573  break;
1574  case NEON_SCVTF:
1575  mnemonic = "scvtf";
1576  break;
1577  case NEON_UCVTF:
1578  mnemonic = "ucvtf";
1579  break;
1580  case NEON_URSQRTE:
1581  mnemonic = "ursqrte";
1582  break;
1583  case NEON_URECPE:
1584  mnemonic = "urecpe";
1585  break;
1586  case NEON_FRSQRTE:
1587  mnemonic = "frsqrte";
1588  break;
1589  case NEON_FRECPE:
1590  mnemonic = "frecpe";
1591  break;
1592  case NEON_FCMGT_zero:
1593  mnemonic = "fcmgt";
1594  form = form_fcmp_zero;
1595  break;
1596  case NEON_FCMGE_zero:
1597  mnemonic = "fcmge";
1598  form = form_fcmp_zero;
1599  break;
1600  case NEON_FCMEQ_zero:
1601  mnemonic = "fcmeq";
1602  form = form_fcmp_zero;
1603  break;
1604  case NEON_FCMLE_zero:
1605  mnemonic = "fcmle";
1606  form = form_fcmp_zero;
1607  break;
1608  case NEON_FCMLT_zero:
1609  mnemonic = "fcmlt";
1610  form = form_fcmp_zero;
1611  break;
1612  default:
1613  if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
1614  (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
1615  nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1616  nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1617 
1618  switch (instr->Mask(NEON2RegMiscMask)) {
1619  case NEON_XTN:
1620  mnemonic = "xtn";
1621  break;
1622  case NEON_SQXTN:
1623  mnemonic = "sqxtn";
1624  break;
1625  case NEON_UQXTN:
1626  mnemonic = "uqxtn";
1627  break;
1628  case NEON_SQXTUN:
1629  mnemonic = "sqxtun";
1630  break;
1631  case NEON_SHLL:
1632  mnemonic = "shll";
1633  nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
1634  nfd.SetFormatMap(1, nfd.IntegerFormatMap());
1635  switch (instr->NEONSize()) {
1636  case 0:
1637  form = "'Vd.%s, 'Vn.%s, #8";
1638  break;
1639  case 1:
1640  form = "'Vd.%s, 'Vn.%s, #16";
1641  break;
1642  case 2:
1643  form = "'Vd.%s, 'Vn.%s, #32";
1644  break;
1645  default:
1646  Format(instr, "unallocated", "(NEON2RegMisc)");
1647  return;
1648  }
1649  }
1650  Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1651  return;
1652  } else {
1653  form = "(NEON2RegMisc)";
1654  }
1655  }
1656  }
1657  Format(instr, mnemonic, nfd.Substitute(form));
1658 }
1659 
1660 void DisassemblingDecoder::VisitNEON3Different(Instruction* instr) {
1661  const char* mnemonic = "unimplemented";
1662  const char* form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
1663 
1664  NEONFormatDecoder nfd(instr);
1665  nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
1666 
1667  // Ignore the Q bit. Appending a "2" suffix is handled later.
1668  switch (instr->Mask(NEON3DifferentMask) & ~NEON_Q) {
1669  case NEON_PMULL:
1670  mnemonic = "pmull";
1671  break;
1672  case NEON_SABAL:
1673  mnemonic = "sabal";
1674  break;
1675  case NEON_SABDL:
1676  mnemonic = "sabdl";
1677  break;
1678  case NEON_SADDL:
1679  mnemonic = "saddl";
1680  break;
1681  case NEON_SMLAL:
1682  mnemonic = "smlal";
1683  break;
1684  case NEON_SMLSL:
1685  mnemonic = "smlsl";
1686  break;
1687  case NEON_SMULL:
1688  mnemonic = "smull";
1689  break;
1690  case NEON_SSUBL:
1691  mnemonic = "ssubl";
1692  break;
1693  case NEON_SQDMLAL:
1694  mnemonic = "sqdmlal";
1695  break;
1696  case NEON_SQDMLSL:
1697  mnemonic = "sqdmlsl";
1698  break;
1699  case NEON_SQDMULL:
1700  mnemonic = "sqdmull";
1701  break;
1702  case NEON_UABAL:
1703  mnemonic = "uabal";
1704  break;
1705  case NEON_UABDL:
1706  mnemonic = "uabdl";
1707  break;
1708  case NEON_UADDL:
1709  mnemonic = "uaddl";
1710  break;
1711  case NEON_UMLAL:
1712  mnemonic = "umlal";
1713  break;
1714  case NEON_UMLSL:
1715  mnemonic = "umlsl";
1716  break;
1717  case NEON_UMULL:
1718  mnemonic = "umull";
1719  break;
1720  case NEON_USUBL:
1721  mnemonic = "usubl";
1722  break;
1723  case NEON_SADDW:
1724  mnemonic = "saddw";
1725  nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1726  break;
1727  case NEON_SSUBW:
1728  mnemonic = "ssubw";
1729  nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1730  break;
1731  case NEON_UADDW:
1732  mnemonic = "uaddw";
1733  nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1734  break;
1735  case NEON_USUBW:
1736  mnemonic = "usubw";
1737  nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
1738  break;
1739  case NEON_ADDHN:
1740  mnemonic = "addhn";
1741  nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1742  nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1743  break;
1744  case NEON_RADDHN:
1745  mnemonic = "raddhn";
1746  nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1747  nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1748  break;
1749  case NEON_RSUBHN:
1750  mnemonic = "rsubhn";
1751  nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1752  nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1753  break;
1754  case NEON_SUBHN:
1755  mnemonic = "subhn";
1756  nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
1757  nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1758  break;
1759  default:
1760  form = "(NEON3Different)";
1761  }
1762  Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1763 }
1764 
1765 void DisassemblingDecoder::VisitNEONAcrossLanes(Instruction* instr) {
1766  const char* mnemonic = "unimplemented";
1767  const char* form = "%sd, 'Vn.%s";
1768 
1769  NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap(),
1770  NEONFormatDecoder::IntegerFormatMap());
1771 
1772  if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
1773  nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
1774  nfd.SetFormatMap(1, nfd.FPFormatMap());
1775  switch (instr->Mask(NEONAcrossLanesFPMask)) {
1776  case NEON_FMAXV:
1777  mnemonic = "fmaxv";
1778  break;
1779  case NEON_FMINV:
1780  mnemonic = "fminv";
1781  break;
1782  case NEON_FMAXNMV:
1783  mnemonic = "fmaxnmv";
1784  break;
1785  case NEON_FMINNMV:
1786  mnemonic = "fminnmv";
1787  break;
1788  default:
1789  form = "(NEONAcrossLanes)";
1790  break;
1791  }
1792  } else if (instr->Mask(NEONAcrossLanesFMask) == NEONAcrossLanesFixed) {
1793  switch (instr->Mask(NEONAcrossLanesMask)) {
1794  case NEON_ADDV:
1795  mnemonic = "addv";
1796  break;
1797  case NEON_SMAXV:
1798  mnemonic = "smaxv";
1799  break;
1800  case NEON_SMINV:
1801  mnemonic = "sminv";
1802  break;
1803  case NEON_UMAXV:
1804  mnemonic = "umaxv";
1805  break;
1806  case NEON_UMINV:
1807  mnemonic = "uminv";
1808  break;
1809  case NEON_SADDLV:
1810  mnemonic = "saddlv";
1811  nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
1812  break;
1813  case NEON_UADDLV:
1814  mnemonic = "uaddlv";
1815  nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
1816  break;
1817  default:
1818  form = "(NEONAcrossLanes)";
1819  break;
1820  }
1821  }
1822  Format(instr, mnemonic,
1823  nfd.Substitute(form, NEONFormatDecoder::kPlaceholder,
1824  NEONFormatDecoder::kFormat));
1825 }
1826 
1827 void DisassemblingDecoder::VisitNEONByIndexedElement(Instruction* instr) {
1828  const char* mnemonic = "unimplemented";
1829  bool l_instr = false;
1830  bool fp_instr = false;
1831 
1832  const char* form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
1833 
1834  static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}};
1835  NEONFormatDecoder nfd(instr, &map_ta, NEONFormatDecoder::IntegerFormatMap(),
1836  NEONFormatDecoder::ScalarFormatMap());
1837 
1838  switch (instr->Mask(NEONByIndexedElementMask)) {
1839  case NEON_SMULL_byelement:
1840  mnemonic = "smull";
1841  l_instr = true;
1842  break;
1843  case NEON_UMULL_byelement:
1844  mnemonic = "umull";
1845  l_instr = true;
1846  break;
1847  case NEON_SMLAL_byelement:
1848  mnemonic = "smlal";
1849  l_instr = true;
1850  break;
1851  case NEON_UMLAL_byelement:
1852  mnemonic = "umlal";
1853  l_instr = true;
1854  break;
1855  case NEON_SMLSL_byelement:
1856  mnemonic = "smlsl";
1857  l_instr = true;
1858  break;
1859  case NEON_UMLSL_byelement:
1860  mnemonic = "umlsl";
1861  l_instr = true;
1862  break;
1863  case NEON_SQDMULL_byelement:
1864  mnemonic = "sqdmull";
1865  l_instr = true;
1866  break;
1867  case NEON_SQDMLAL_byelement:
1868  mnemonic = "sqdmlal";
1869  l_instr = true;
1870  break;
1871  case NEON_SQDMLSL_byelement:
1872  mnemonic = "sqdmlsl";
1873  l_instr = true;
1874  break;
1875  case NEON_MUL_byelement:
1876  mnemonic = "mul";
1877  break;
1878  case NEON_MLA_byelement:
1879  mnemonic = "mla";
1880  break;
1881  case NEON_MLS_byelement:
1882  mnemonic = "mls";
1883  break;
1884  case NEON_SQDMULH_byelement:
1885  mnemonic = "sqdmulh";
1886  break;
1887  case NEON_SQRDMULH_byelement:
1888  mnemonic = "sqrdmulh";
1889  break;
1890  default:
1891  switch (instr->Mask(NEONByIndexedElementFPMask)) {
1892  case NEON_FMUL_byelement:
1893  mnemonic = "fmul";
1894  fp_instr = true;
1895  break;
1896  case NEON_FMLA_byelement:
1897  mnemonic = "fmla";
1898  fp_instr = true;
1899  break;
1900  case NEON_FMLS_byelement:
1901  mnemonic = "fmls";
1902  fp_instr = true;
1903  break;
1904  case NEON_FMULX_byelement:
1905  mnemonic = "fmulx";
1906  fp_instr = true;
1907  break;
1908  }
1909  }
1910 
1911  if (l_instr) {
1912  Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
1913  } else if (fp_instr) {
1914  nfd.SetFormatMap(0, nfd.FPFormatMap());
1915  Format(instr, mnemonic, nfd.Substitute(form));
1916  } else {
1917  nfd.SetFormatMap(0, nfd.IntegerFormatMap());
1918  Format(instr, mnemonic, nfd.Substitute(form));
1919  }
1920 }
1921 
1922 void DisassemblingDecoder::VisitNEONCopy(Instruction* instr) {
1923  const char* mnemonic = "unimplemented";
1924  const char* form = "(NEONCopy)";
1925 
1926  NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap(),
1927  NEONFormatDecoder::TriangularScalarFormatMap());
1928 
1929  if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
1930  mnemonic = "mov";
1931  nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1932  form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]";
1933  } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
1934  mnemonic = "mov";
1935  nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1936  if (nfd.GetVectorFormat() == kFormatD) {
1937  form = "'Vd.%s['IVInsIndex1], 'Xn";
1938  } else {
1939  form = "'Vd.%s['IVInsIndex1], 'Wn";
1940  }
1941  } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
1942  if (instr->Mask(NEON_Q) || ((instr->ImmNEON5() & 7) == 4)) {
1943  mnemonic = "mov";
1944  } else {
1945  mnemonic = "umov";
1946  }
1947  nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1948  if (nfd.GetVectorFormat() == kFormatD) {
1949  form = "'Xd, 'Vn.%s['IVInsIndex1]";
1950  } else {
1951  form = "'Wd, 'Vn.%s['IVInsIndex1]";
1952  }
1953  } else if (instr->Mask(NEONCopySmovMask) == NEON_SMOV) {
1954  mnemonic = "smov";
1955  nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
1956  form = "'Rdq, 'Vn.%s['IVInsIndex1]";
1957  } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
1958  mnemonic = "dup";
1959  form = "'Vd.%s, 'Vn.%s['IVInsIndex1]";
1960  } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
1961  mnemonic = "dup";
1962  if (nfd.GetVectorFormat() == kFormat2D) {
1963  form = "'Vd.%s, 'Xn";
1964  } else {
1965  form = "'Vd.%s, 'Wn";
1966  }
1967  }
1968  Format(instr, mnemonic, nfd.Substitute(form));
1969 }
1970 
1971 void DisassemblingDecoder::VisitNEONExtract(Instruction* instr) {
1972  const char* mnemonic = "unimplemented";
1973  const char* form = "(NEONExtract)";
1974  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
1975  if (instr->Mask(NEONExtractMask) == NEON_EXT) {
1976  mnemonic = "ext";
1977  form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract";
1978  }
1979  Format(instr, mnemonic, nfd.Substitute(form));
1980 }
1981 
1982 void DisassemblingDecoder::VisitNEONLoadStoreMultiStruct(Instruction* instr) {
1983  const char* mnemonic = nullptr;
1984  const char* form = nullptr;
1985  const char* form_1v = "{'Vt.%1$s}, ['Xns]";
1986  const char* form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]";
1987  const char* form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]";
1988  const char* form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
1989  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
1990 
1991  switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
1992  case NEON_LD1_1v:
1993  mnemonic = "ld1";
1994  form = form_1v;
1995  break;
1996  case NEON_LD1_2v:
1997  mnemonic = "ld1";
1998  form = form_2v;
1999  break;
2000  case NEON_LD1_3v:
2001  mnemonic = "ld1";
2002  form = form_3v;
2003  break;
2004  case NEON_LD1_4v:
2005  mnemonic = "ld1";
2006  form = form_4v;
2007  break;
2008  case NEON_LD2:
2009  mnemonic = "ld2";
2010  form = form_2v;
2011  break;
2012  case NEON_LD3:
2013  mnemonic = "ld3";
2014  form = form_3v;
2015  break;
2016  case NEON_LD4:
2017  mnemonic = "ld4";
2018  form = form_4v;
2019  break;
2020  case NEON_ST1_1v:
2021  mnemonic = "st1";
2022  form = form_1v;
2023  break;
2024  case NEON_ST1_2v:
2025  mnemonic = "st1";
2026  form = form_2v;
2027  break;
2028  case NEON_ST1_3v:
2029  mnemonic = "st1";
2030  form = form_3v;
2031  break;
2032  case NEON_ST1_4v:
2033  mnemonic = "st1";
2034  form = form_4v;
2035  break;
2036  case NEON_ST2:
2037  mnemonic = "st2";
2038  form = form_2v;
2039  break;
2040  case NEON_ST3:
2041  mnemonic = "st3";
2042  form = form_3v;
2043  break;
2044  case NEON_ST4:
2045  mnemonic = "st4";
2046  form = form_4v;
2047  break;
2048  default:
2049  break;
2050  }
2051 
2052  // Work out unallocated encodings.
2053  bool allocated = (mnemonic != nullptr);
2054  switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
2055  case NEON_LD2:
2056  case NEON_LD3:
2057  case NEON_LD4:
2058  case NEON_ST2:
2059  case NEON_ST3:
2060  case NEON_ST4:
2061  // LD[2-4] and ST[2-4] cannot use .1d format.
2062  allocated = (instr->NEONQ() != 0) || (instr->NEONLSSize() != 3);
2063  break;
2064  default:
2065  break;
2066  }
2067  if (allocated) {
2068  DCHECK_NOT_NULL(mnemonic);
2069  DCHECK_NOT_NULL(form);
2070  } else {
2071  mnemonic = "unallocated";
2072  form = "(NEONLoadStoreMultiStruct)";
2073  }
2074 
2075  Format(instr, mnemonic, nfd.Substitute(form));
2076 }
2077 
2078 void DisassemblingDecoder::VisitNEONLoadStoreMultiStructPostIndex(
2079  Instruction* instr) {
2080  const char* mnemonic = nullptr;
2081  const char* form = nullptr;
2082  const char* form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1";
2083  const char* form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2";
2084  const char* form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3";
2085  const char* form_4v =
2086  "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4";
2087  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2088 
2089  switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
2090  case NEON_LD1_1v_post:
2091  mnemonic = "ld1";
2092  form = form_1v;
2093  break;
2094  case NEON_LD1_2v_post:
2095  mnemonic = "ld1";
2096  form = form_2v;
2097  break;
2098  case NEON_LD1_3v_post:
2099  mnemonic = "ld1";
2100  form = form_3v;
2101  break;
2102  case NEON_LD1_4v_post:
2103  mnemonic = "ld1";
2104  form = form_4v;
2105  break;
2106  case NEON_LD2_post:
2107  mnemonic = "ld2";
2108  form = form_2v;
2109  break;
2110  case NEON_LD3_post:
2111  mnemonic = "ld3";
2112  form = form_3v;
2113  break;
2114  case NEON_LD4_post:
2115  mnemonic = "ld4";
2116  form = form_4v;
2117  break;
2118  case NEON_ST1_1v_post:
2119  mnemonic = "st1";
2120  form = form_1v;
2121  break;
2122  case NEON_ST1_2v_post:
2123  mnemonic = "st1";
2124  form = form_2v;
2125  break;
2126  case NEON_ST1_3v_post:
2127  mnemonic = "st1";
2128  form = form_3v;
2129  break;
2130  case NEON_ST1_4v_post:
2131  mnemonic = "st1";
2132  form = form_4v;
2133  break;
2134  case NEON_ST2_post:
2135  mnemonic = "st2";
2136  form = form_2v;
2137  break;
2138  case NEON_ST3_post:
2139  mnemonic = "st3";
2140  form = form_3v;
2141  break;
2142  case NEON_ST4_post:
2143  mnemonic = "st4";
2144  form = form_4v;
2145  break;
2146  default:
2147  break;
2148  }
2149 
2150  // Work out unallocated encodings.
2151  bool allocated = (mnemonic != nullptr);
2152  switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
2153  case NEON_LD2_post:
2154  case NEON_LD3_post:
2155  case NEON_LD4_post:
2156  case NEON_ST2_post:
2157  case NEON_ST3_post:
2158  case NEON_ST4_post:
2159  // LD[2-4] and ST[2-4] cannot use .1d format.
2160  allocated = (instr->NEONQ() != 0) || (instr->NEONLSSize() != 3);
2161  break;
2162  default:
2163  break;
2164  }
2165  if (allocated) {
2166  DCHECK_NOT_NULL(mnemonic);
2167  DCHECK_NOT_NULL(form);
2168  } else {
2169  mnemonic = "unallocated";
2170  form = "(NEONLoadStoreMultiStructPostIndex)";
2171  }
2172 
2173  Format(instr, mnemonic, nfd.Substitute(form));
2174 }
2175 
2176 void DisassemblingDecoder::VisitNEONLoadStoreSingleStruct(Instruction* instr) {
2177  const char* mnemonic = nullptr;
2178  const char* form = nullptr;
2179 
2180  const char* form_1b = "{'Vt.b}['IVLSLane0], ['Xns]";
2181  const char* form_1h = "{'Vt.h}['IVLSLane1], ['Xns]";
2182  const char* form_1s = "{'Vt.s}['IVLSLane2], ['Xns]";
2183  const char* form_1d = "{'Vt.d}['IVLSLane3], ['Xns]";
2184  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2185 
2186  switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
2187  case NEON_LD1_b:
2188  mnemonic = "ld1";
2189  form = form_1b;
2190  break;
2191  case NEON_LD1_h:
2192  mnemonic = "ld1";
2193  form = form_1h;
2194  break;
2195  case NEON_LD1_s:
2196  mnemonic = "ld1";
2197  static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
2198  "LSB of size distinguishes S and D registers.");
2199  form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2200  break;
2201  case NEON_ST1_b:
2202  mnemonic = "st1";
2203  form = form_1b;
2204  break;
2205  case NEON_ST1_h:
2206  mnemonic = "st1";
2207  form = form_1h;
2208  break;
2209  case NEON_ST1_s:
2210  mnemonic = "st1";
2211  static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
2212  "LSB of size distinguishes S and D registers.");
2213  form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2214  break;
2215  case NEON_LD1R:
2216  mnemonic = "ld1r";
2217  form = "{'Vt.%s}, ['Xns]";
2218  break;
2219  case NEON_LD2_b:
2220  case NEON_ST2_b:
2221  mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2222  form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]";
2223  break;
2224  case NEON_LD2_h:
2225  case NEON_ST2_h:
2226  mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2227  form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]";
2228  break;
2229  case NEON_LD2_s:
2230  case NEON_ST2_s:
2231  static_assert((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d,
2232  "LSB of size distinguishes S and D registers.");
2233  static_assert((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d,
2234  "LSB of size distinguishes S and D registers.");
2235  mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2236  if ((instr->NEONLSSize() & 1) == 0) {
2237  form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]";
2238  } else {
2239  form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]";
2240  }
2241  break;
2242  case NEON_LD2R:
2243  mnemonic = "ld2r";
2244  form = "{'Vt.%s, 'Vt2.%s}, ['Xns]";
2245  break;
2246  case NEON_LD3_b:
2247  case NEON_ST3_b:
2248  mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2249  form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]";
2250  break;
2251  case NEON_LD3_h:
2252  case NEON_ST3_h:
2253  mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2254  form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]";
2255  break;
2256  case NEON_LD3_s:
2257  case NEON_ST3_s:
2258  mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2259  if ((instr->NEONLSSize() & 1) == 0) {
2260  form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]";
2261  } else {
2262  form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]";
2263  }
2264  break;
2265  case NEON_LD3R:
2266  mnemonic = "ld3r";
2267  form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]";
2268  break;
2269  case NEON_LD4_b:
2270  case NEON_ST4_b:
2271  mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2272  form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]";
2273  break;
2274  case NEON_LD4_h:
2275  case NEON_ST4_h:
2276  mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2277  form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]";
2278  break;
2279  case NEON_LD4_s:
2280  case NEON_ST4_s:
2281  static_assert((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d,
2282  "LSB of size distinguishes S and D registers.");
2283  static_assert((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d,
2284  "LSB of size distinguishes S and D registers.");
2285  mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2286  if ((instr->NEONLSSize() & 1) == 0) {
2287  form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]";
2288  } else {
2289  form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]";
2290  }
2291  break;
2292  case NEON_LD4R:
2293  mnemonic = "ld4r";
2294  form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
2295  break;
2296  default:
2297  break;
2298  }
2299 
2300  // Work out unallocated encodings.
2301  bool allocated = (mnemonic != nullptr);
2302  switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
2303  case NEON_LD1_h:
2304  case NEON_LD2_h:
2305  case NEON_LD3_h:
2306  case NEON_LD4_h:
2307  case NEON_ST1_h:
2308  case NEON_ST2_h:
2309  case NEON_ST3_h:
2310  case NEON_ST4_h:
2311  DCHECK(allocated);
2312  allocated = ((instr->NEONLSSize() & 1) == 0);
2313  break;
2314  case NEON_LD1_s:
2315  case NEON_LD2_s:
2316  case NEON_LD3_s:
2317  case NEON_LD4_s:
2318  case NEON_ST1_s:
2319  case NEON_ST2_s:
2320  case NEON_ST3_s:
2321  case NEON_ST4_s:
2322  DCHECK(allocated);
2323  allocated = (instr->NEONLSSize() <= 1) &&
2324  ((instr->NEONLSSize() == 0) || (instr->NEONS() == 0));
2325  break;
2326  case NEON_LD1R:
2327  case NEON_LD2R:
2328  case NEON_LD3R:
2329  case NEON_LD4R:
2330  DCHECK(allocated);
2331  allocated = (instr->NEONS() == 0);
2332  break;
2333  default:
2334  break;
2335  }
2336  if (allocated) {
2337  DCHECK_NOT_NULL(mnemonic);
2338  DCHECK_NOT_NULL(form);
2339  } else {
2340  mnemonic = "unallocated";
2341  form = "(NEONLoadStoreSingleStruct)";
2342  }
2343 
2344  Format(instr, mnemonic, nfd.Substitute(form));
2345 }
2346 
2347 void DisassemblingDecoder::VisitNEONLoadStoreSingleStructPostIndex(
2348  Instruction* instr) {
2349  const char* mnemonic = nullptr;
2350  const char* form = nullptr;
2351 
2352  const char* form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1";
2353  const char* form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2";
2354  const char* form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4";
2355  const char* form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8";
2356  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2357 
2358  switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
2359  case NEON_LD1_b_post:
2360  mnemonic = "ld1";
2361  form = form_1b;
2362  break;
2363  case NEON_LD1_h_post:
2364  mnemonic = "ld1";
2365  form = form_1h;
2366  break;
2367  case NEON_LD1_s_post:
2368  mnemonic = "ld1";
2369  static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
2370  "LSB of size distinguishes S and D registers.");
2371  form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2372  break;
2373  case NEON_ST1_b_post:
2374  mnemonic = "st1";
2375  form = form_1b;
2376  break;
2377  case NEON_ST1_h_post:
2378  mnemonic = "st1";
2379  form = form_1h;
2380  break;
2381  case NEON_ST1_s_post:
2382  mnemonic = "st1";
2383  static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
2384  "LSB of size distinguishes S and D registers.");
2385  form = ((instr->NEONLSSize() & 1) == 0) ? form_1s : form_1d;
2386  break;
2387  case NEON_LD1R_post:
2388  mnemonic = "ld1r";
2389  form = "{'Vt.%s}, ['Xns], 'Xmz1";
2390  break;
2391  case NEON_LD2_b_post:
2392  case NEON_ST2_b_post:
2393  mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2394  form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2";
2395  break;
2396  case NEON_ST2_h_post:
2397  case NEON_LD2_h_post:
2398  mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2399  form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4";
2400  break;
2401  case NEON_LD2_s_post:
2402  case NEON_ST2_s_post:
2403  mnemonic = (instr->NEONLoad() == 1) ? "ld2" : "st2";
2404  if ((instr->NEONLSSize() & 1) == 0)
2405  form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8";
2406  else
2407  form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16";
2408  break;
2409  case NEON_LD2R_post:
2410  mnemonic = "ld2r";
2411  form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2";
2412  break;
2413  case NEON_LD3_b_post:
2414  case NEON_ST3_b_post:
2415  mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2416  form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3";
2417  break;
2418  case NEON_LD3_h_post:
2419  case NEON_ST3_h_post:
2420  mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2421  form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6";
2422  break;
2423  case NEON_LD3_s_post:
2424  case NEON_ST3_s_post:
2425  mnemonic = (instr->NEONLoad() == 1) ? "ld3" : "st3";
2426  if ((instr->NEONLSSize() & 1) == 0)
2427  form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12";
2428  else
2429  form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24";
2430  break;
2431  case NEON_LD3R_post:
2432  mnemonic = "ld3r";
2433  form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3";
2434  break;
2435  case NEON_LD4_b_post:
2436  case NEON_ST4_b_post:
2437  mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2438  form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4";
2439  break;
2440  case NEON_LD4_h_post:
2441  case NEON_ST4_h_post:
2442  mnemonic = (instr->NEONLoad()) == 1 ? "ld4" : "st4";
2443  form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8";
2444  break;
2445  case NEON_LD4_s_post:
2446  case NEON_ST4_s_post:
2447  mnemonic = (instr->NEONLoad() == 1) ? "ld4" : "st4";
2448  if ((instr->NEONLSSize() & 1) == 0)
2449  form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16";
2450  else
2451  form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32";
2452  break;
2453  case NEON_LD4R_post:
2454  mnemonic = "ld4r";
2455  form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4";
2456  break;
2457  default:
2458  break;
2459  }
2460 
2461  // Work out unallocated encodings.
2462  bool allocated = (mnemonic != nullptr);
2463  switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
2464  case NEON_LD1_h_post:
2465  case NEON_LD2_h_post:
2466  case NEON_LD3_h_post:
2467  case NEON_LD4_h_post:
2468  case NEON_ST1_h_post:
2469  case NEON_ST2_h_post:
2470  case NEON_ST3_h_post:
2471  case NEON_ST4_h_post:
2472  DCHECK(allocated);
2473  allocated = ((instr->NEONLSSize() & 1) == 0);
2474  break;
2475  case NEON_LD1_s_post:
2476  case NEON_LD2_s_post:
2477  case NEON_LD3_s_post:
2478  case NEON_LD4_s_post:
2479  case NEON_ST1_s_post:
2480  case NEON_ST2_s_post:
2481  case NEON_ST3_s_post:
2482  case NEON_ST4_s_post:
2483  DCHECK(allocated);
2484  allocated = (instr->NEONLSSize() <= 1) &&
2485  ((instr->NEONLSSize() == 0) || (instr->NEONS() == 0));
2486  break;
2487  case NEON_LD1R_post:
2488  case NEON_LD2R_post:
2489  case NEON_LD3R_post:
2490  case NEON_LD4R_post:
2491  DCHECK(allocated);
2492  allocated = (instr->NEONS() == 0);
2493  break;
2494  default:
2495  break;
2496  }
2497  if (allocated) {
2498  DCHECK_NOT_NULL(mnemonic);
2499  DCHECK_NOT_NULL(form);
2500  } else {
2501  mnemonic = "unallocated";
2502  form = "(NEONLoadStoreSingleStructPostIndex)";
2503  }
2504 
2505  Format(instr, mnemonic, nfd.Substitute(form));
2506 }
2507 
2508 void DisassemblingDecoder::VisitNEONModifiedImmediate(Instruction* instr) {
2509  const char* mnemonic = "unimplemented";
2510  const char* form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1";
2511 
2512  int cmode = instr->NEONCmode();
2513  int cmode_3 = (cmode >> 3) & 1;
2514  int cmode_2 = (cmode >> 2) & 1;
2515  int cmode_1 = (cmode >> 1) & 1;
2516  int cmode_0 = cmode & 1;
2517  int q = instr->NEONQ();
2518  int op = instr->NEONModImmOp();
2519 
2520  static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
2521  static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}};
2522  static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}};
2523  NEONFormatDecoder nfd(instr, &map_b);
2524 
2525  if (cmode_3 == 0) {
2526  if (cmode_0 == 0) {
2527  mnemonic = (op == 1) ? "mvni" : "movi";
2528  } else { // cmode<0> == '1'.
2529  mnemonic = (op == 1) ? "bic" : "orr";
2530  }
2531  nfd.SetFormatMap(0, &map_s);
2532  } else { // cmode<3> == '1'.
2533  if (cmode_2 == 0) {
2534  if (cmode_0 == 0) {
2535  mnemonic = (op == 1) ? "mvni" : "movi";
2536  } else { // cmode<0> == '1'.
2537  mnemonic = (op == 1) ? "bic" : "orr";
2538  }
2539  nfd.SetFormatMap(0, &map_h);
2540  } else { // cmode<2> == '1'.
2541  if (cmode_1 == 0) {
2542  mnemonic = (op == 1) ? "mvni" : "movi";
2543  form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2";
2544  nfd.SetFormatMap(0, &map_s);
2545  } else { // cmode<1> == '1'.
2546  if (cmode_0 == 0) {
2547  mnemonic = "movi";
2548  if (op == 0) {
2549  form = "'Vt.%s, 'IVMIImm8";
2550  } else {
2551  form = (q == 0) ? "'Dd, 'IVMIImm" : "'Vt.2d, 'IVMIImm";
2552  }
2553  } else { // cmode<0> == '1'
2554  mnemonic = "fmov";
2555  if (op == 0) {
2556  form = "'Vt.%s, 'IVMIImmFPSingle";
2557  nfd.SetFormatMap(0, &map_s);
2558  } else {
2559  if (q == 1) {
2560  form = "'Vt.2d, 'IVMIImmFPDouble";
2561  } else {
2562  mnemonic = "unallocated";
2563  form = "(NEONModifiedImmediate)";
2564  }
2565  }
2566  }
2567  }
2568  }
2569  }
2570  Format(instr, mnemonic, nfd.Substitute(form));
2571 }
2572 
2573 void DisassemblingDecoder::VisitNEONPerm(Instruction* instr) {
2574  const char* mnemonic = "unimplemented";
2575  const char* form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2576  NEONFormatDecoder nfd(instr);
2577 
2578  switch (instr->Mask(NEONPermMask)) {
2579  case NEON_TRN1:
2580  mnemonic = "trn1";
2581  break;
2582  case NEON_TRN2:
2583  mnemonic = "trn2";
2584  break;
2585  case NEON_UZP1:
2586  mnemonic = "uzp1";
2587  break;
2588  case NEON_UZP2:
2589  mnemonic = "uzp2";
2590  break;
2591  case NEON_ZIP1:
2592  mnemonic = "zip1";
2593  break;
2594  case NEON_ZIP2:
2595  mnemonic = "zip2";
2596  break;
2597  default:
2598  form = "(NEONPerm)";
2599  }
2600  Format(instr, mnemonic, nfd.Substitute(form));
2601 }
2602 
2603 void DisassemblingDecoder::VisitNEONScalar2RegMisc(Instruction* instr) {
2604  const char* mnemonic = "unimplemented";
2605  const char* form = "%sd, %sn";
2606  const char* form_0 = "%sd, %sn, #0";
2607  const char* form_fp0 = "%sd, %sn, #0.0";
2608 
2609  NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2610 
2611  if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
2612  // These instructions all use a two bit size field, except NOT and RBIT,
2613  // which use the field to encode the operation.
2614  switch (instr->Mask(NEONScalar2RegMiscMask)) {
2615  case NEON_CMGT_zero_scalar:
2616  mnemonic = "cmgt";
2617  form = form_0;
2618  break;
2619  case NEON_CMGE_zero_scalar:
2620  mnemonic = "cmge";
2621  form = form_0;
2622  break;
2623  case NEON_CMLE_zero_scalar:
2624  mnemonic = "cmle";
2625  form = form_0;
2626  break;
2627  case NEON_CMLT_zero_scalar:
2628  mnemonic = "cmlt";
2629  form = form_0;
2630  break;
2631  case NEON_CMEQ_zero_scalar:
2632  mnemonic = "cmeq";
2633  form = form_0;
2634  break;
2635  case NEON_NEG_scalar:
2636  mnemonic = "neg";
2637  break;
2638  case NEON_SQNEG_scalar:
2639  mnemonic = "sqneg";
2640  break;
2641  case NEON_ABS_scalar:
2642  mnemonic = "abs";
2643  break;
2644  case NEON_SQABS_scalar:
2645  mnemonic = "sqabs";
2646  break;
2647  case NEON_SUQADD_scalar:
2648  mnemonic = "suqadd";
2649  break;
2650  case NEON_USQADD_scalar:
2651  mnemonic = "usqadd";
2652  break;
2653  default:
2654  form = "(NEONScalar2RegMisc)";
2655  }
2656  } else {
2657  // These instructions all use a one bit size field, except SQXTUN, SQXTN
2658  // and UQXTN, which use a two bit size field.
2659  nfd.SetFormatMaps(nfd.FPScalarFormatMap());
2660  switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
2661  case NEON_FRSQRTE_scalar:
2662  mnemonic = "frsqrte";
2663  break;
2664  case NEON_FRECPE_scalar:
2665  mnemonic = "frecpe";
2666  break;
2667  case NEON_SCVTF_scalar:
2668  mnemonic = "scvtf";
2669  break;
2670  case NEON_UCVTF_scalar:
2671  mnemonic = "ucvtf";
2672  break;
2673  case NEON_FCMGT_zero_scalar:
2674  mnemonic = "fcmgt";
2675  form = form_fp0;
2676  break;
2677  case NEON_FCMGE_zero_scalar:
2678  mnemonic = "fcmge";
2679  form = form_fp0;
2680  break;
2681  case NEON_FCMLE_zero_scalar:
2682  mnemonic = "fcmle";
2683  form = form_fp0;
2684  break;
2685  case NEON_FCMLT_zero_scalar:
2686  mnemonic = "fcmlt";
2687  form = form_fp0;
2688  break;
2689  case NEON_FCMEQ_zero_scalar:
2690  mnemonic = "fcmeq";
2691  form = form_fp0;
2692  break;
2693  case NEON_FRECPX_scalar:
2694  mnemonic = "frecpx";
2695  break;
2696  case NEON_FCVTNS_scalar:
2697  mnemonic = "fcvtns";
2698  break;
2699  case NEON_FCVTNU_scalar:
2700  mnemonic = "fcvtnu";
2701  break;
2702  case NEON_FCVTPS_scalar:
2703  mnemonic = "fcvtps";
2704  break;
2705  case NEON_FCVTPU_scalar:
2706  mnemonic = "fcvtpu";
2707  break;
2708  case NEON_FCVTMS_scalar:
2709  mnemonic = "fcvtms";
2710  break;
2711  case NEON_FCVTMU_scalar:
2712  mnemonic = "fcvtmu";
2713  break;
2714  case NEON_FCVTZS_scalar:
2715  mnemonic = "fcvtzs";
2716  break;
2717  case NEON_FCVTZU_scalar:
2718  mnemonic = "fcvtzu";
2719  break;
2720  case NEON_FCVTAS_scalar:
2721  mnemonic = "fcvtas";
2722  break;
2723  case NEON_FCVTAU_scalar:
2724  mnemonic = "fcvtau";
2725  break;
2726  case NEON_FCVTXN_scalar:
2727  nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
2728  mnemonic = "fcvtxn";
2729  break;
2730  default:
2731  nfd.SetFormatMap(0, nfd.ScalarFormatMap());
2732  nfd.SetFormatMap(1, nfd.LongScalarFormatMap());
2733  switch (instr->Mask(NEONScalar2RegMiscMask)) {
2734  case NEON_SQXTN_scalar:
2735  mnemonic = "sqxtn";
2736  break;
2737  case NEON_UQXTN_scalar:
2738  mnemonic = "uqxtn";
2739  break;
2740  case NEON_SQXTUN_scalar:
2741  mnemonic = "sqxtun";
2742  break;
2743  default:
2744  form = "(NEONScalar2RegMisc)";
2745  }
2746  }
2747  }
2748  Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2749 }
2750 
2751 void DisassemblingDecoder::VisitNEONScalar3Diff(Instruction* instr) {
2752  const char* mnemonic = "unimplemented";
2753  const char* form = "%sd, %sn, %sm";
2754  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap(),
2755  NEONFormatDecoder::ScalarFormatMap());
2756 
2757  switch (instr->Mask(NEONScalar3DiffMask)) {
2758  case NEON_SQDMLAL_scalar:
2759  mnemonic = "sqdmlal";
2760  break;
2761  case NEON_SQDMLSL_scalar:
2762  mnemonic = "sqdmlsl";
2763  break;
2764  case NEON_SQDMULL_scalar:
2765  mnemonic = "sqdmull";
2766  break;
2767  default:
2768  form = "(NEONScalar3Diff)";
2769  }
2770  Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2771 }
2772 
2773 void DisassemblingDecoder::VisitNEONScalar3Same(Instruction* instr) {
2774  const char* mnemonic = "unimplemented";
2775  const char* form = "%sd, %sn, %sm";
2776  NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2777 
2778  if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
2779  nfd.SetFormatMaps(nfd.FPScalarFormatMap());
2780  switch (instr->Mask(NEONScalar3SameFPMask)) {
2781  case NEON_FACGE_scalar:
2782  mnemonic = "facge";
2783  break;
2784  case NEON_FACGT_scalar:
2785  mnemonic = "facgt";
2786  break;
2787  case NEON_FCMEQ_scalar:
2788  mnemonic = "fcmeq";
2789  break;
2790  case NEON_FCMGE_scalar:
2791  mnemonic = "fcmge";
2792  break;
2793  case NEON_FCMGT_scalar:
2794  mnemonic = "fcmgt";
2795  break;
2796  case NEON_FMULX_scalar:
2797  mnemonic = "fmulx";
2798  break;
2799  case NEON_FRECPS_scalar:
2800  mnemonic = "frecps";
2801  break;
2802  case NEON_FRSQRTS_scalar:
2803  mnemonic = "frsqrts";
2804  break;
2805  case NEON_FABD_scalar:
2806  mnemonic = "fabd";
2807  break;
2808  default:
2809  form = "(NEONScalar3Same)";
2810  }
2811  } else {
2812  switch (instr->Mask(NEONScalar3SameMask)) {
2813  case NEON_ADD_scalar:
2814  mnemonic = "add";
2815  break;
2816  case NEON_SUB_scalar:
2817  mnemonic = "sub";
2818  break;
2819  case NEON_CMEQ_scalar:
2820  mnemonic = "cmeq";
2821  break;
2822  case NEON_CMGE_scalar:
2823  mnemonic = "cmge";
2824  break;
2825  case NEON_CMGT_scalar:
2826  mnemonic = "cmgt";
2827  break;
2828  case NEON_CMHI_scalar:
2829  mnemonic = "cmhi";
2830  break;
2831  case NEON_CMHS_scalar:
2832  mnemonic = "cmhs";
2833  break;
2834  case NEON_CMTST_scalar:
2835  mnemonic = "cmtst";
2836  break;
2837  case NEON_UQADD_scalar:
2838  mnemonic = "uqadd";
2839  break;
2840  case NEON_SQADD_scalar:
2841  mnemonic = "sqadd";
2842  break;
2843  case NEON_UQSUB_scalar:
2844  mnemonic = "uqsub";
2845  break;
2846  case NEON_SQSUB_scalar:
2847  mnemonic = "sqsub";
2848  break;
2849  case NEON_USHL_scalar:
2850  mnemonic = "ushl";
2851  break;
2852  case NEON_SSHL_scalar:
2853  mnemonic = "sshl";
2854  break;
2855  case NEON_UQSHL_scalar:
2856  mnemonic = "uqshl";
2857  break;
2858  case NEON_SQSHL_scalar:
2859  mnemonic = "sqshl";
2860  break;
2861  case NEON_URSHL_scalar:
2862  mnemonic = "urshl";
2863  break;
2864  case NEON_SRSHL_scalar:
2865  mnemonic = "srshl";
2866  break;
2867  case NEON_UQRSHL_scalar:
2868  mnemonic = "uqrshl";
2869  break;
2870  case NEON_SQRSHL_scalar:
2871  mnemonic = "sqrshl";
2872  break;
2873  case NEON_SQDMULH_scalar:
2874  mnemonic = "sqdmulh";
2875  break;
2876  case NEON_SQRDMULH_scalar:
2877  mnemonic = "sqrdmulh";
2878  break;
2879  default:
2880  form = "(NEONScalar3Same)";
2881  }
2882  }
2883  Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
2884 }
2885 
2886 void DisassemblingDecoder::VisitNEONScalarByIndexedElement(Instruction* instr) {
2887  const char* mnemonic = "unimplemented";
2888  const char* form = "%sd, %sn, 'Ve.%s['IVByElemIndex]";
2889  NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
2890  bool long_instr = false;
2891 
2892  switch (instr->Mask(NEONScalarByIndexedElementMask)) {
2893  case NEON_SQDMULL_byelement_scalar:
2894  mnemonic = "sqdmull";
2895  long_instr = true;
2896  break;
2897  case NEON_SQDMLAL_byelement_scalar:
2898  mnemonic = "sqdmlal";
2899  long_instr = true;
2900  break;
2901  case NEON_SQDMLSL_byelement_scalar:
2902  mnemonic = "sqdmlsl";
2903  long_instr = true;
2904  break;
2905  case NEON_SQDMULH_byelement_scalar:
2906  mnemonic = "sqdmulh";
2907  break;
2908  case NEON_SQRDMULH_byelement_scalar:
2909  mnemonic = "sqrdmulh";
2910  break;
2911  default:
2912  nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
2913  switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
2914  case NEON_FMUL_byelement_scalar:
2915  mnemonic = "fmul";
2916  break;
2917  case NEON_FMLA_byelement_scalar:
2918  mnemonic = "fmla";
2919  break;
2920  case NEON_FMLS_byelement_scalar:
2921  mnemonic = "fmls";
2922  break;
2923  case NEON_FMULX_byelement_scalar:
2924  mnemonic = "fmulx";
2925  break;
2926  default:
2927  form = "(NEONScalarByIndexedElement)";
2928  }
2929  }
2930 
2931  if (long_instr) {
2932  nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
2933  }
2934 
2935  Format(instr, mnemonic,
2936  nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
2937 }
2938 
2939 void DisassemblingDecoder::VisitNEONScalarCopy(Instruction* instr) {
2940  const char* mnemonic = "unimplemented";
2941  const char* form = "(NEONScalarCopy)";
2942 
2943  NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
2944 
2945  if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
2946  mnemonic = "mov";
2947  form = "%sd, 'Vn.%s['IVInsIndex1]";
2948  }
2949 
2950  Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat));
2951 }
2952 
2953 void DisassemblingDecoder::VisitNEONScalarPairwise(Instruction* instr) {
2954  const char* mnemonic = "unimplemented";
2955  const char* form = "%sd, 'Vn.%s";
2956  NEONFormatMap map = {{22}, {NF_2S, NF_2D}};
2957  NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap(), &map);
2958 
2959  switch (instr->Mask(NEONScalarPairwiseMask)) {
2960  case NEON_ADDP_scalar:
2961  mnemonic = "addp";
2962  break;
2963  case NEON_FADDP_scalar:
2964  mnemonic = "faddp";
2965  break;
2966  case NEON_FMAXP_scalar:
2967  mnemonic = "fmaxp";
2968  break;
2969  case NEON_FMAXNMP_scalar:
2970  mnemonic = "fmaxnmp";
2971  break;
2972  case NEON_FMINP_scalar:
2973  mnemonic = "fminp";
2974  break;
2975  case NEON_FMINNMP_scalar:
2976  mnemonic = "fminnmp";
2977  break;
2978  default:
2979  form = "(NEONScalarPairwise)";
2980  }
2981  Format(instr, mnemonic,
2982  nfd.Substitute(form, NEONFormatDecoder::kPlaceholder,
2983  NEONFormatDecoder::kFormat));
2984 }
2985 
2986 void DisassemblingDecoder::VisitNEONScalarShiftImmediate(Instruction* instr) {
2987  const char* mnemonic = "unimplemented";
2988  const char* form = "%sd, %sn, 'Is1";
2989  const char* form_2 = "%sd, %sn, 'Is2";
2990 
2991  static const NEONFormatMap map_shift = {
2992  {22, 21, 20, 19},
2993  {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S, NF_D, NF_D, NF_D,
2994  NF_D, NF_D, NF_D, NF_D, NF_D}};
2995  static const NEONFormatMap map_shift_narrow = {
2996  {21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}};
2997  NEONFormatDecoder nfd(instr, &map_shift);
2998 
2999  if (instr->ImmNEONImmh()) { // immh has to be non-zero.
3000  switch (instr->Mask(NEONScalarShiftImmediateMask)) {
3001  case NEON_FCVTZU_imm_scalar:
3002  mnemonic = "fcvtzu";
3003  break;
3004  case NEON_FCVTZS_imm_scalar:
3005  mnemonic = "fcvtzs";
3006  break;
3007  case NEON_SCVTF_imm_scalar:
3008  mnemonic = "scvtf";
3009  break;
3010  case NEON_UCVTF_imm_scalar:
3011  mnemonic = "ucvtf";
3012  break;
3013  case NEON_SRI_scalar:
3014  mnemonic = "sri";
3015  break;
3016  case NEON_SSHR_scalar:
3017  mnemonic = "sshr";
3018  break;
3019  case NEON_USHR_scalar:
3020  mnemonic = "ushr";
3021  break;
3022  case NEON_SRSHR_scalar:
3023  mnemonic = "srshr";
3024  break;
3025  case NEON_URSHR_scalar:
3026  mnemonic = "urshr";
3027  break;
3028  case NEON_SSRA_scalar:
3029  mnemonic = "ssra";
3030  break;
3031  case NEON_USRA_scalar:
3032  mnemonic = "usra";
3033  break;
3034  case NEON_SRSRA_scalar:
3035  mnemonic = "srsra";
3036  break;
3037  case NEON_URSRA_scalar:
3038  mnemonic = "ursra";
3039  break;
3040  case NEON_SHL_scalar:
3041  mnemonic = "shl";
3042  form = form_2;
3043  break;
3044  case NEON_SLI_scalar:
3045  mnemonic = "sli";
3046  form = form_2;
3047  break;
3048  case NEON_SQSHLU_scalar:
3049  mnemonic = "sqshlu";
3050  form = form_2;
3051  break;
3052  case NEON_SQSHL_imm_scalar:
3053  mnemonic = "sqshl";
3054  form = form_2;
3055  break;
3056  case NEON_UQSHL_imm_scalar:
3057  mnemonic = "uqshl";
3058  form = form_2;
3059  break;
3060  case NEON_UQSHRN_scalar:
3061  mnemonic = "uqshrn";
3062  nfd.SetFormatMap(1, &map_shift_narrow);
3063  break;
3064  case NEON_UQRSHRN_scalar:
3065  mnemonic = "uqrshrn";
3066  nfd.SetFormatMap(1, &map_shift_narrow);
3067  break;
3068  case NEON_SQSHRN_scalar:
3069  mnemonic = "sqshrn";
3070  nfd.SetFormatMap(1, &map_shift_narrow);
3071  break;
3072  case NEON_SQRSHRN_scalar:
3073  mnemonic = "sqrshrn";
3074  nfd.SetFormatMap(1, &map_shift_narrow);
3075  break;
3076  case NEON_SQSHRUN_scalar:
3077  mnemonic = "sqshrun";
3078  nfd.SetFormatMap(1, &map_shift_narrow);
3079  break;
3080  case NEON_SQRSHRUN_scalar:
3081  mnemonic = "sqrshrun";
3082  nfd.SetFormatMap(1, &map_shift_narrow);
3083  break;
3084  default:
3085  form = "(NEONScalarShiftImmediate)";
3086  }
3087  } else {
3088  form = "(NEONScalarShiftImmediate)";
3089  }
3090  Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
3091 }
3092 
3093 void DisassemblingDecoder::VisitNEONShiftImmediate(Instruction* instr) {
3094  const char* mnemonic = "unimplemented";
3095  const char* form = "'Vd.%s, 'Vn.%s, 'Is1";
3096  const char* form_shift_2 = "'Vd.%s, 'Vn.%s, 'Is2";
3097  const char* form_xtl = "'Vd.%s, 'Vn.%s";
3098 
3099  // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
3100  static const NEONFormatMap map_shift_ta = {
3101  {22, 21, 20, 19},
3102  {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
3103 
3104  // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
3105  // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
3106  static const NEONFormatMap map_shift_tb = {
3107  {22, 21, 20, 19, 30},
3108  {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H, NF_8H,
3109  NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S,
3110  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
3111  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
3112 
3113  NEONFormatDecoder nfd(instr, &map_shift_tb);
3114 
3115  if (instr->ImmNEONImmh()) { // immh has to be non-zero.
3116  switch (instr->Mask(NEONShiftImmediateMask)) {
3117  case NEON_SQSHLU:
3118  mnemonic = "sqshlu";
3119  form = form_shift_2;
3120  break;
3121  case NEON_SQSHL_imm:
3122  mnemonic = "sqshl";
3123  form = form_shift_2;
3124  break;
3125  case NEON_UQSHL_imm:
3126  mnemonic = "uqshl";
3127  form = form_shift_2;
3128  break;
3129  case NEON_SHL:
3130  mnemonic = "shl";
3131  form = form_shift_2;
3132  break;
3133  case NEON_SLI:
3134  mnemonic = "sli";
3135  form = form_shift_2;
3136  break;
3137  case NEON_SCVTF_imm:
3138  mnemonic = "scvtf";
3139  break;
3140  case NEON_UCVTF_imm:
3141  mnemonic = "ucvtf";
3142  break;
3143  case NEON_FCVTZU_imm:
3144  mnemonic = "fcvtzu";
3145  break;
3146  case NEON_FCVTZS_imm:
3147  mnemonic = "fcvtzs";
3148  break;
3149  case NEON_SRI:
3150  mnemonic = "sri";
3151  break;
3152  case NEON_SSHR:
3153  mnemonic = "sshr";
3154  break;
3155  case NEON_USHR:
3156  mnemonic = "ushr";
3157  break;
3158  case NEON_SRSHR:
3159  mnemonic = "srshr";
3160  break;
3161  case NEON_URSHR:
3162  mnemonic = "urshr";
3163  break;
3164  case NEON_SSRA:
3165  mnemonic = "ssra";
3166  break;
3167  case NEON_USRA:
3168  mnemonic = "usra";
3169  break;
3170  case NEON_SRSRA:
3171  mnemonic = "srsra";
3172  break;
3173  case NEON_URSRA:
3174  mnemonic = "ursra";
3175  break;
3176  case NEON_SHRN:
3177  mnemonic = instr->Mask(NEON_Q) ? "shrn2" : "shrn";
3178  nfd.SetFormatMap(1, &map_shift_ta);
3179  break;
3180  case NEON_RSHRN:
3181  mnemonic = instr->Mask(NEON_Q) ? "rshrn2" : "rshrn";
3182  nfd.SetFormatMap(1, &map_shift_ta);
3183  break;
3184  case NEON_UQSHRN:
3185  mnemonic = instr->Mask(NEON_Q) ? "uqshrn2" : "uqshrn";
3186  nfd.SetFormatMap(1, &map_shift_ta);
3187  break;
3188  case NEON_UQRSHRN:
3189  mnemonic = instr->Mask(NEON_Q) ? "uqrshrn2" : "uqrshrn";
3190  nfd.SetFormatMap(1, &map_shift_ta);
3191  break;
3192  case NEON_SQSHRN:
3193  mnemonic = instr->Mask(NEON_Q) ? "sqshrn2" : "sqshrn";
3194  nfd.SetFormatMap(1, &map_shift_ta);
3195  break;
3196  case NEON_SQRSHRN:
3197  mnemonic = instr->Mask(NEON_Q) ? "sqrshrn2" : "sqrshrn";
3198  nfd.SetFormatMap(1, &map_shift_ta);
3199  break;
3200  case NEON_SQSHRUN:
3201  mnemonic = instr->Mask(NEON_Q) ? "sqshrun2" : "sqshrun";
3202  nfd.SetFormatMap(1, &map_shift_ta);
3203  break;
3204  case NEON_SQRSHRUN:
3205  mnemonic = instr->Mask(NEON_Q) ? "sqrshrun2" : "sqrshrun";
3206  nfd.SetFormatMap(1, &map_shift_ta);
3207  break;
3208  case NEON_SSHLL:
3209  nfd.SetFormatMap(0, &map_shift_ta);
3210  if (instr->ImmNEONImmb() == 0 &&
3211  CountSetBits(instr->ImmNEONImmh(), 32) == 1) { // sxtl variant.
3212  form = form_xtl;
3213  mnemonic = instr->Mask(NEON_Q) ? "sxtl2" : "sxtl";
3214  } else { // sshll variant.
3215  form = form_shift_2;
3216  mnemonic = instr->Mask(NEON_Q) ? "sshll2" : "sshll";
3217  }
3218  break;
3219  case NEON_USHLL:
3220  nfd.SetFormatMap(0, &map_shift_ta);
3221  if (instr->ImmNEONImmb() == 0 &&
3222  CountSetBits(instr->ImmNEONImmh(), 32) == 1) { // uxtl variant.
3223  form = form_xtl;
3224  mnemonic = instr->Mask(NEON_Q) ? "uxtl2" : "uxtl";
3225  } else { // ushll variant.
3226  form = form_shift_2;
3227  mnemonic = instr->Mask(NEON_Q) ? "ushll2" : "ushll";
3228  }
3229  break;
3230  default:
3231  form = "(NEONShiftImmediate)";
3232  }
3233  } else {
3234  form = "(NEONShiftImmediate)";
3235  }
3236  Format(instr, mnemonic, nfd.Substitute(form));
3237 }
3238 
3239 void DisassemblingDecoder::VisitNEONTable(Instruction* instr) {
3240  const char* mnemonic = "unimplemented";
3241  const char* form = "(NEONTable)";
3242  const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s";
3243  const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s";
3244  const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
3245  const char form_4v[] =
3246  "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
3247  static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
3248  NEONFormatDecoder nfd(instr, &map_b);
3249 
3250  switch (instr->Mask(NEONTableMask)) {
3251  case NEON_TBL_1v:
3252  mnemonic = "tbl";
3253  form = form_1v;
3254  break;
3255  case NEON_TBL_2v:
3256  mnemonic = "tbl";
3257  form = form_2v;
3258  break;
3259  case NEON_TBL_3v:
3260  mnemonic = "tbl";
3261  form = form_3v;
3262  break;
3263  case NEON_TBL_4v:
3264  mnemonic = "tbl";
3265  form = form_4v;
3266  break;
3267  case NEON_TBX_1v:
3268  mnemonic = "tbx";
3269  form = form_1v;
3270  break;
3271  case NEON_TBX_2v:
3272  mnemonic = "tbx";
3273  form = form_2v;
3274  break;
3275  case NEON_TBX_3v:
3276  mnemonic = "tbx";
3277  form = form_3v;
3278  break;
3279  case NEON_TBX_4v:
3280  mnemonic = "tbx";
3281  form = form_4v;
3282  break;
3283  default:
3284  break;
3285  }
3286 
3287  char re_form[sizeof(form_4v)];
3288  int reg_num = instr->Rn();
3289  snprintf(re_form, sizeof(re_form), form, (reg_num + 1) % kNumberOfVRegisters,
3290  (reg_num + 2) % kNumberOfVRegisters,
3291  (reg_num + 3) % kNumberOfVRegisters);
3292 
3293  Format(instr, mnemonic, nfd.Substitute(re_form));
3294 }
3295 
3296 void DisassemblingDecoder::VisitUnimplemented(Instruction* instr) {
3297  Format(instr, "unimplemented", "(Unimplemented)");
3298 }
3299 
3300 void DisassemblingDecoder::VisitUnallocated(Instruction* instr) {
3301  Format(instr, "unallocated", "(Unallocated)");
3302 }
3303 
3304 void DisassemblingDecoder::ProcessOutput(Instruction* /*instr*/) {
3305  // The base disasm does nothing more than disassembling into a buffer.
3306 }
3307 
3308 void DisassemblingDecoder::AppendRegisterNameToOutput(const CPURegister& reg) {
3309  DCHECK(reg.IsValid());
3310  char reg_char;
3311 
3312  if (reg.IsRegister()) {
3313  reg_char = reg.Is64Bits() ? 'x' : 'w';
3314  } else {
3315  DCHECK(reg.IsVRegister());
3316  switch (reg.SizeInBits()) {
3317  case kBRegSizeInBits:
3318  reg_char = 'b';
3319  break;
3320  case kHRegSizeInBits:
3321  reg_char = 'h';
3322  break;
3323  case kSRegSizeInBits:
3324  reg_char = 's';
3325  break;
3326  case kDRegSizeInBits:
3327  reg_char = 'd';
3328  break;
3329  default:
3330  DCHECK(reg.Is128Bits());
3331  reg_char = 'q';
3332  }
3333  }
3334 
3335  if (reg.IsVRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
3336  // Filter special registers
3337  if (reg.IsX() && (reg.code() == 27)) {
3338  AppendToOutput("cp");
3339  } else if (reg.IsX() && (reg.code() == 29)) {
3340  AppendToOutput("fp");
3341  } else if (reg.IsX() && (reg.code() == 30)) {
3342  AppendToOutput("lr");
3343  } else {
3344  // A core or scalar/vector register: [wx]0 - 30, [bhsdq]0 - 31.
3345  AppendToOutput("%c%d", reg_char, reg.code());
3346  }
3347  } else if (reg.Aliases(sp)) {
3348  // Disassemble w31/x31 as stack pointer wsp/sp.
3349  AppendToOutput("%s", reg.Is64Bits() ? "sp" : "wsp");
3350  } else {
3351  // Disassemble w31/x31 as zero register wzr/xzr.
3352  AppendToOutput("%czr", reg_char);
3353  }
3354 }
3355 
3356 void DisassemblingDecoder::Format(Instruction* instr, const char* mnemonic,
3357  const char* format) {
3358  // TODO(mcapewel) don't think I can use the instr address here - there needs
3359  // to be a base address too
3360  DCHECK_NOT_NULL(mnemonic);
3361  ResetOutput();
3362  Substitute(instr, mnemonic);
3363  if (format != nullptr) {
3364  buffer_[buffer_pos_++] = ' ';
3365  Substitute(instr, format);
3366  }
3367  buffer_[buffer_pos_] = 0;
3368  ProcessOutput(instr);
3369 }
3370 
3371 void DisassemblingDecoder::Substitute(Instruction* instr, const char* string) {
3372  char chr = *string++;
3373  while (chr != '\0') {
3374  if (chr == '\'') {
3375  string += SubstituteField(instr, string);
3376  } else {
3377  buffer_[buffer_pos_++] = chr;
3378  }
3379  chr = *string++;
3380  }
3381 }
3382 
3383 int DisassemblingDecoder::SubstituteField(Instruction* instr,
3384  const char* format) {
3385  switch (format[0]) {
3386  // NB. The remaining substitution prefix characters are: GJKUZ.
3387  case 'R': // Register. X or W, selected by sf bit.
3388  case 'F': // FP register. S or D, selected by type field.
3389  case 'V': // Vector register, V, vector format.
3390  case 'W':
3391  case 'X':
3392  case 'B':
3393  case 'H':
3394  case 'S':
3395  case 'D':
3396  case 'Q':
3397  return SubstituteRegisterField(instr, format);
3398  case 'I':
3399  return SubstituteImmediateField(instr, format);
3400  case 'L':
3401  return SubstituteLiteralField(instr, format);
3402  case 'N':
3403  return SubstituteShiftField(instr, format);
3404  case 'P':
3405  return SubstitutePrefetchField(instr, format);
3406  case 'C':
3407  return SubstituteConditionField(instr, format);
3408  case 'E':
3409  return SubstituteExtendField(instr, format);
3410  case 'A':
3411  return SubstitutePCRelAddressField(instr, format);
3412  case 'T':
3413  return SubstituteBranchTargetField(instr, format);
3414  case 'O':
3415  return SubstituteLSRegOffsetField(instr, format);
3416  case 'M':
3417  return SubstituteBarrierField(instr, format);
3418  default:
3419  UNREACHABLE();
3420  }
3421 }
3422 
3423 int DisassemblingDecoder::SubstituteRegisterField(Instruction* instr,
3424  const char* format) {
3425  char reg_prefix = format[0];
3426  unsigned reg_num = 0;
3427  unsigned field_len = 2;
3428 
3429  switch (format[1]) {
3430  case 'd':
3431  reg_num = instr->Rd();
3432  if (format[2] == 'q') {
3433  reg_prefix = instr->NEONQ() ? 'X' : 'W';
3434  field_len = 3;
3435  }
3436  break;
3437  case 'n':
3438  reg_num = instr->Rn();
3439  break;
3440  case 'm':
3441  reg_num = instr->Rm();
3442  switch (format[2]) {
3443  // Handle registers tagged with b (bytes), z (instruction), or
3444  // r (registers), used for address updates in
3445  // NEON load/store instructions.
3446  case 'r':
3447  case 'b':
3448  case 'z': {
3449  field_len = 3;
3450  char* eimm;
3451  int imm = static_cast<int>(strtol(&format[3], &eimm, 10));
3452  field_len += eimm - &format[3];
3453  if (reg_num == 31) {
3454  switch (format[2]) {
3455  case 'z':
3456  imm *= (1 << instr->NEONLSSize());
3457  break;
3458  case 'r':
3459  imm *= (instr->NEONQ() == 0) ? kDRegSize : kQRegSize;
3460  break;
3461  case 'b':
3462  break;
3463  }
3464  AppendToOutput("#%d", imm);
3465  return field_len;
3466  }
3467  break;
3468  }
3469  }
3470  break;
3471  case 'e':
3472  // This is register Rm, but using a 4-bit specifier. Used in NEON
3473  // by-element instructions.
3474  reg_num = (instr->Rm() & 0xF);
3475  break;
3476  case 'a':
3477  reg_num = instr->Ra();
3478  break;
3479  case 't':
3480  reg_num = instr->Rt();
3481  if (format[0] == 'V') {
3482  if ((format[2] >= '2') && (format[2] <= '4')) {
3483  // Handle consecutive vector register specifiers Vt2, Vt3 and Vt4.
3484  reg_num = (reg_num + format[2] - '1') % 32;
3485  field_len = 3;
3486  }
3487  } else {
3488  if (format[2] == '2') {
3489  // Handle register specifier Rt2.
3490  reg_num = instr->Rt2();
3491  field_len = 3;
3492  }
3493  }
3494  break;
3495  case 's':
3496  reg_num = instr->Rs();
3497  break;
3498  default:
3499  UNREACHABLE();
3500  }
3501 
3502  // Increase field length for registers tagged as stack.
3503  if (format[2] == 's') {
3504  field_len = 3;
3505  }
3506 
3507  CPURegister::RegisterType reg_type;
3508  unsigned reg_size;
3509 
3510  if (reg_prefix == 'R') {
3511  reg_prefix = instr->SixtyFourBits() ? 'X' : 'W';
3512  } else if (reg_prefix == 'F') {
3513  reg_prefix = ((instr->FPType() & 1) == 0) ? 'S' : 'D';
3514  }
3515 
3516  switch (reg_prefix) {
3517  case 'W':
3518  reg_type = CPURegister::kRegister;
3519  reg_size = kWRegSizeInBits;
3520  break;
3521  case 'X':
3522  reg_type = CPURegister::kRegister;
3523  reg_size = kXRegSizeInBits;
3524  break;
3525  case 'B':
3526  reg_type = CPURegister::kVRegister;
3527  reg_size = kBRegSizeInBits;
3528  break;
3529  case 'H':
3530  reg_type = CPURegister::kVRegister;
3531  reg_size = kHRegSizeInBits;
3532  break;
3533  case 'S':
3534  reg_type = CPURegister::kVRegister;
3535  reg_size = kSRegSizeInBits;
3536  break;
3537  case 'D':
3538  reg_type = CPURegister::kVRegister;
3539  reg_size = kDRegSizeInBits;
3540  break;
3541  case 'Q':
3542  reg_type = CPURegister::kVRegister;
3543  reg_size = kQRegSizeInBits;
3544  break;
3545  case 'V':
3546  AppendToOutput("v%d", reg_num);
3547  return field_len;
3548  default:
3549  UNREACHABLE();
3550  }
3551 
3552  if ((reg_type == CPURegister::kRegister) && (reg_num == kZeroRegCode) &&
3553  (format[2] == 's')) {
3554  reg_num = kSPRegInternalCode;
3555  }
3556 
3557  AppendRegisterNameToOutput(CPURegister::Create(reg_num, reg_size, reg_type));
3558 
3559  return field_len;
3560 }
3561 
3562 int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr,
3563  const char* format) {
3564  DCHECK_EQ(format[0], 'I');
3565 
3566  switch (format[1]) {
3567  case 'M': { // IMoveImm or IMoveLSL.
3568  if (format[5] == 'I' || format[5] == 'N') {
3569  uint64_t imm = static_cast<uint64_t>(instr->ImmMoveWide())
3570  << (16 * instr->ShiftMoveWide());
3571  if (format[5] == 'N') imm = ~imm;
3572  if (!instr->SixtyFourBits()) imm &= UINT64_C(0xFFFFFFFF);
3573  AppendToOutput("#0x%" PRIx64, imm);
3574  } else {
3575  DCHECK_EQ(format[5], 'L');
3576  AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
3577  if (instr->ShiftMoveWide() > 0) {
3578  AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
3579  }
3580  }
3581  return 8;
3582  }
3583  case 'L': {
3584  switch (format[2]) {
3585  case 'L': { // ILLiteral - Immediate Load Literal.
3586  AppendToOutput("pc%+" PRId32, instr->ImmLLiteral()
3587  << kLoadLiteralScaleLog2);
3588  return 9;
3589  }
3590  case 'S': { // ILS - Immediate Load/Store.
3591  if (instr->ImmLS() != 0) {
3592  AppendToOutput(", #%" PRId32, instr->ImmLS());
3593  }
3594  return 3;
3595  }
3596  case 'P': { // ILPx - Immediate Load/Store Pair, x = access size.
3597  if (instr->ImmLSPair() != 0) {
3598  // format[3] is the scale value. Convert to a number.
3599  int scale = 1 << (format[3] - '0');
3600  AppendToOutput(", #%" PRId32, instr->ImmLSPair() * scale);
3601  }
3602  return 4;
3603  }
3604  case 'U': { // ILU - Immediate Load/Store Unsigned.
3605  if (instr->ImmLSUnsigned() != 0) {
3606  int shift = instr->SizeLS();
3607  AppendToOutput(", #%" PRId32, instr->ImmLSUnsigned() << shift);
3608  }
3609  return 3;
3610  }
3611  }
3612  }
3613  case 'C': { // ICondB - Immediate Conditional Branch.
3614  int64_t offset = instr->ImmCondBranch() << 2;
3615  char sign = (offset >= 0) ? '+' : '-';
3616  AppendToOutput("#%c0x%" PRIx64, sign, offset);
3617  return 6;
3618  }
3619  case 'A': { // IAddSub.
3620  DCHECK_LE(instr->ShiftAddSub(), 1);
3621  int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
3622  AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
3623  return 7;
3624  }
3625  case 'F': { // IFPSingle, IFPDouble or IFPFBits.
3626  if (format[3] == 'F') { // IFPFBits.
3627  AppendToOutput("#%d", 64 - instr->FPScale());
3628  return 8;
3629  } else {
3630  AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmFP(),
3631  format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64());
3632  return 9;
3633  }
3634  }
3635  case 'T': { // ITri - Immediate Triangular Encoded.
3636  AppendToOutput("#0x%" PRIx64, instr->ImmLogical());
3637  return 4;
3638  }
3639  case 'N': { // INzcv.
3640  int nzcv = (instr->Nzcv() << Flags_offset);
3641  AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N',
3642  ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
3643  ((nzcv & CFlag) == 0) ? 'c' : 'C',
3644  ((nzcv & VFlag) == 0) ? 'v' : 'V');
3645  return 5;
3646  }
3647  case 'P': { // IP - Conditional compare.
3648  AppendToOutput("#%d", instr->ImmCondCmp());
3649  return 2;
3650  }
3651  case 'B': { // Bitfields.
3652  return SubstituteBitfieldImmediateField(instr, format);
3653  }
3654  case 'E': { // IExtract.
3655  AppendToOutput("#%d", instr->ImmS());
3656  return 8;
3657  }
3658  case 'S': { // IS - Test and branch bit.
3659  AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
3660  instr->ImmTestBranchBit40());
3661  return 2;
3662  }
3663  case 's': { // Is - Shift (immediate).
3664  switch (format[2]) {
3665  case '1': { // Is1 - SSHR.
3666  int shift = 16 << HighestSetBitPosition(instr->ImmNEONImmh());
3667  shift -= instr->ImmNEONImmhImmb();
3668  AppendToOutput("#%d", shift);
3669  return 3;
3670  }
3671  case '2': { // Is2 - SLI.
3672  int shift = instr->ImmNEONImmhImmb();
3673  shift -= 8 << HighestSetBitPosition(instr->ImmNEONImmh());
3674  AppendToOutput("#%d", shift);
3675  return 3;
3676  }
3677  default: {
3678  UNIMPLEMENTED();
3679  return 0;
3680  }
3681  }
3682  }
3683  case 'D': { // IDebug - HLT and BRK instructions.
3684  AppendToOutput("#0x%x", instr->ImmException());
3685  return 6;
3686  }
3687  case 'V': { // Immediate Vector.
3688  switch (format[2]) {
3689  case 'E': { // IVExtract.
3690  AppendToOutput("#%" PRId64, instr->ImmNEONExt());
3691  return 9;
3692  }
3693  case 'B': { // IVByElemIndex.
3694  int vm_index = (instr->NEONH() << 1) | instr->NEONL();
3695  if (instr->NEONSize() == 1) {
3696  vm_index = (vm_index << 1) | instr->NEONM();
3697  }
3698  AppendToOutput("%d", vm_index);
3699  return static_cast<int>(strlen("IVByElemIndex"));
3700  }
3701  case 'I': { // INS element.
3702  if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) {
3703  unsigned rd_index, rn_index;
3704  unsigned imm5 = instr->ImmNEON5();
3705  unsigned imm4 = instr->ImmNEON4();
3706  int tz = CountTrailingZeros(imm5, 32);
3707  if (tz <= 3) { // Defined for 0 <= tz <= 3 only.
3708  rd_index = imm5 >> (tz + 1);
3709  rn_index = imm4 >> tz;
3710  if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) {
3711  AppendToOutput("%d", rd_index);
3712  return static_cast<int>(strlen("IVInsIndex1"));
3713  } else if (strncmp(format, "IVInsIndex2",
3714  strlen("IVInsIndex2")) == 0) {
3715  AppendToOutput("%d", rn_index);
3716  return static_cast<int>(strlen("IVInsIndex2"));
3717  }
3718  }
3719  return 0;
3720  }
3721  UNIMPLEMENTED();
3722  return 0;
3723  }
3724  case 'L': { // IVLSLane[0123] - suffix indicates access size shift.
3725  AppendToOutput("%d", instr->NEONLSIndex(format[8] - '0'));
3726  return 9;
3727  }
3728  case 'M': { // Modified Immediate cases.
3729  if (strncmp(format, "IVMIImmFPSingle", strlen("IVMIImmFPSingle")) ==
3730  0) {
3731  AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmNEONabcdefgh(),
3732  instr->ImmNEONFP32());
3733  return static_cast<int>(strlen("IVMIImmFPSingle"));
3734  } else if (strncmp(format, "IVMIImmFPDouble",
3735  strlen("IVMIImmFPDouble")) == 0) {
3736  AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmNEONabcdefgh(),
3737  instr->ImmNEONFP64());
3738  return static_cast<int>(strlen("IVMIImmFPDouble"));
3739  } else if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) {
3740  uint64_t imm8 = instr->ImmNEONabcdefgh();
3741  AppendToOutput("#0x%" PRIx64, imm8);
3742  return static_cast<int>(strlen("IVMIImm8"));
3743  } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) {
3744  uint64_t imm8 = instr->ImmNEONabcdefgh();
3745  uint64_t imm = 0;
3746  for (int i = 0; i < 8; ++i) {
3747  if (imm8 & (1ULL << i)) {
3748  imm |= (UINT64_C(0xFF) << (8 * i));
3749  }
3750  }
3751  AppendToOutput("#0x%" PRIx64, imm);
3752  return static_cast<int>(strlen("IVMIImm"));
3753  } else if (strncmp(format, "IVMIShiftAmt1",
3754  strlen("IVMIShiftAmt1")) == 0) {
3755  int cmode = instr->NEONCmode();
3756  int shift_amount = 8 * ((cmode >> 1) & 3);
3757  AppendToOutput("#%d", shift_amount);
3758  return static_cast<int>(strlen("IVMIShiftAmt1"));
3759  } else if (strncmp(format, "IVMIShiftAmt2",
3760  strlen("IVMIShiftAmt2")) == 0) {
3761  int cmode = instr->NEONCmode();
3762  int shift_amount = 8 << (cmode & 1);
3763  AppendToOutput("#%d", shift_amount);
3764  return static_cast<int>(strlen("IVMIShiftAmt2"));
3765  } else {
3766  UNIMPLEMENTED();
3767  return 0;
3768  }
3769  }
3770  default: {
3771  UNIMPLEMENTED();
3772  return 0;
3773  }
3774  }
3775  }
3776  default: {
3777  printf("%s", format);
3778  UNREACHABLE();
3779  }
3780  }
3781 }
3782 
3783 
3784 int DisassemblingDecoder::SubstituteBitfieldImmediateField(Instruction* instr,
3785  const char* format) {
3786  DCHECK((format[0] == 'I') && (format[1] == 'B'));
3787  unsigned r = instr->ImmR();
3788  unsigned s = instr->ImmS();
3789 
3790  switch (format[2]) {
3791  case 'r': { // IBr.
3792  AppendToOutput("#%d", r);
3793  return 3;
3794  }
3795  case 's': { // IBs+1 or IBs-r+1.
3796  if (format[3] == '+') {
3797  AppendToOutput("#%d", s + 1);
3798  return 5;
3799  } else {
3800  DCHECK_EQ(format[3], '-');
3801  AppendToOutput("#%d", s - r + 1);
3802  return 7;
3803  }
3804  }
3805  case 'Z': { // IBZ-r.
3806  DCHECK((format[3] == '-') && (format[4] == 'r'));
3807  unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
3808  : kWRegSizeInBits;
3809  AppendToOutput("#%d", reg_size - r);
3810  return 5;
3811  }
3812  default: {
3813  UNREACHABLE();
3814  }
3815  }
3816 }
3817 
3818 
3819 int DisassemblingDecoder::SubstituteLiteralField(Instruction* instr,
3820  const char* format) {
3821  DCHECK_EQ(strncmp(format, "LValue", 6), 0);
3822  USE(format);
3823 
3824  switch (instr->Mask(LoadLiteralMask)) {
3825  case LDR_w_lit:
3826  case LDR_x_lit:
3827  case LDR_s_lit:
3828  case LDR_d_lit:
3829  AppendToOutput("(addr 0x%016" PRIxPTR ")", instr->LiteralAddress());
3830  break;
3831  default: UNREACHABLE();
3832  }
3833 
3834  return 6;
3835 }
3836 
3837 
3838 int DisassemblingDecoder::SubstituteShiftField(Instruction* instr,
3839  const char* format) {
3840  DCHECK_EQ(format[0], 'N');
3841  DCHECK_LE(instr->ShiftDP(), 0x3);
3842 
3843  switch (format[1]) {
3844  case 'D': { // NDP.
3845  DCHECK(instr->ShiftDP() != ROR);
3846  V8_FALLTHROUGH;
3847  }
3848  case 'L': { // NLo.
3849  if (instr->ImmDPShift() != 0) {
3850  const char* shift_type[] = {"lsl", "lsr", "asr", "ror"};
3851  AppendToOutput(", %s #%" PRId32, shift_type[instr->ShiftDP()],
3852  instr->ImmDPShift());
3853  }
3854  return 3;
3855  }
3856  default:
3857  UNREACHABLE();
3858  }
3859 }
3860 
3861 
3862 int DisassemblingDecoder::SubstituteConditionField(Instruction* instr,
3863  const char* format) {
3864  DCHECK_EQ(format[0], 'C');
3865  const char* condition_code[] = { "eq", "ne", "hs", "lo",
3866  "mi", "pl", "vs", "vc",
3867  "hi", "ls", "ge", "lt",
3868  "gt", "le", "al", "nv" };
3869  int cond;
3870  switch (format[1]) {
3871  case 'B': cond = instr->ConditionBranch(); break;
3872  case 'I': {
3873  cond = NegateCondition(static_cast<Condition>(instr->Condition()));
3874  break;
3875  }
3876  default: cond = instr->Condition();
3877  }
3878  AppendToOutput("%s", condition_code[cond]);
3879  return 4;
3880 }
3881 
3882 
3883 int DisassemblingDecoder::SubstitutePCRelAddressField(Instruction* instr,
3884  const char* format) {
3885  USE(format);
3886  DCHECK_EQ(strncmp(format, "AddrPCRel", 9), 0);
3887 
3888  int offset = instr->ImmPCRel();
3889 
3890  // Only ADR (AddrPCRelByte) is supported.
3891  DCHECK_EQ(strcmp(format, "AddrPCRelByte"), 0);
3892 
3893  char sign = '+';
3894  if (offset < 0) {
3895  sign = '-';
3896  }
3897  AppendToOutput("#%c0x%x (addr %p)", sign, Abs(offset),
3898  instr->InstructionAtOffset(offset, Instruction::NO_CHECK));
3899  return 13;
3900 }
3901 
3902 
3903 int DisassemblingDecoder::SubstituteBranchTargetField(Instruction* instr,
3904  const char* format) {
3905  DCHECK_EQ(strncmp(format, "TImm", 4), 0);
3906 
3907  int64_t offset = 0;
3908  switch (format[5]) {
3909  // TImmUncn - unconditional branch immediate.
3910  case 'n': offset = instr->ImmUncondBranch(); break;
3911  // TImmCond - conditional branch immediate.
3912  case 'o': offset = instr->ImmCondBranch(); break;
3913  // TImmCmpa - compare and branch immediate.
3914  case 'm': offset = instr->ImmCmpBranch(); break;
3915  // TImmTest - test and branch immediate.
3916  case 'e': offset = instr->ImmTestBranch(); break;
3917  default: UNREACHABLE();
3918  }
3919  offset <<= kInstrSizeLog2;
3920  char sign = '+';
3921  if (offset < 0) {
3922  sign = '-';
3923  }
3924  AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset),
3925  instr->InstructionAtOffset(offset), Instruction::NO_CHECK);
3926  return 8;
3927 }
3928 
3929 
3930 int DisassemblingDecoder::SubstituteExtendField(Instruction* instr,
3931  const char* format) {
3932  DCHECK_EQ(strncmp(format, "Ext", 3), 0);
3933  DCHECK_LE(instr->ExtendMode(), 7);
3934  USE(format);
3935 
3936  const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
3937  "sxtb", "sxth", "sxtw", "sxtx" };
3938 
3939  // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
3940  // registers becomes lsl.
3941  if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
3942  (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
3943  (instr->ExtendMode() == UXTX))) {
3944  if (instr->ImmExtendShift() > 0) {
3945  AppendToOutput(", lsl #%d", instr->ImmExtendShift());
3946  }
3947  } else {
3948  AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
3949  if (instr->ImmExtendShift() > 0) {
3950  AppendToOutput(" #%d", instr->ImmExtendShift());
3951  }
3952  }
3953  return 3;
3954 }
3955 
3956 
3957 int DisassemblingDecoder::SubstituteLSRegOffsetField(Instruction* instr,
3958  const char* format) {
3959  DCHECK_EQ(strncmp(format, "Offsetreg", 9), 0);
3960  const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
3961  "undefined", "undefined", "sxtw", "sxtx" };
3962  USE(format);
3963 
3964  unsigned shift = instr->ImmShiftLS();
3965  Extend ext = static_cast<Extend>(instr->ExtendMode());
3966  char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
3967 
3968  unsigned rm = instr->Rm();
3969  if (rm == kZeroRegCode) {
3970  AppendToOutput("%czr", reg_type);
3971  } else {
3972  AppendToOutput("%c%d", reg_type, rm);
3973  }
3974 
3975  // Extend mode UXTX is an alias for shift mode LSL here.
3976  if (!((ext == UXTX) && (shift == 0))) {
3977  AppendToOutput(", %s", extend_mode[ext]);
3978  if (shift != 0) {
3979  AppendToOutput(" #%d", instr->SizeLS());
3980  }
3981  }
3982  return 9;
3983 }
3984 
3985 
3986 int DisassemblingDecoder::SubstitutePrefetchField(Instruction* instr,
3987  const char* format) {
3988  DCHECK_EQ(format[0], 'P');
3989  USE(format);
3990 
3991  int prefetch_mode = instr->PrefetchMode();
3992 
3993  const char* ls = (prefetch_mode & 0x10) ? "st" : "ld";
3994  int level = (prefetch_mode >> 1) + 1;
3995  const char* ks = (prefetch_mode & 1) ? "strm" : "keep";
3996 
3997  AppendToOutput("p%sl%d%s", ls, level, ks);
3998  return 6;
3999 }
4000 
4001 int DisassemblingDecoder::SubstituteBarrierField(Instruction* instr,
4002  const char* format) {
4003  DCHECK_EQ(format[0], 'M');
4004  USE(format);
4005 
4006  static const char* const options[4][4] = {
4007  { "sy (0b0000)", "oshld", "oshst", "osh" },
4008  { "sy (0b0100)", "nshld", "nshst", "nsh" },
4009  { "sy (0b1000)", "ishld", "ishst", "ish" },
4010  { "sy (0b1100)", "ld", "st", "sy" }
4011  };
4012  int domain = instr->ImmBarrierDomain();
4013  int type = instr->ImmBarrierType();
4014 
4015  AppendToOutput("%s", options[domain][type]);
4016  return 1;
4017 }
4018 
4019 
4020 void DisassemblingDecoder::ResetOutput() {
4021  buffer_pos_ = 0;
4022  buffer_[buffer_pos_] = 0;
4023 }
4024 
4025 
4026 void DisassemblingDecoder::AppendToOutput(const char* format, ...) {
4027  va_list args;
4028  va_start(args, format);
4029  buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args);
4030  va_end(args);
4031 }
4032 
4033 
4034 void PrintDisassembler::ProcessOutput(Instruction* instr) {
4035  fprintf(stream_, "0x%016" PRIx64 " %08" PRIx32 "\t\t%s\n",
4036  reinterpret_cast<uint64_t>(instr), instr->InstructionBits(),
4037  GetOutput());
4038 }
4039 
4040 } // namespace internal
4041 } // namespace v8
4042 
4043 
4044 namespace disasm {
4045 
4046 
4047 const char* NameConverter::NameOfAddress(byte* addr) const {
4048  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void *>(addr));
4049  return tmp_buffer_.start();
4050 }
4051 
4052 
4053 const char* NameConverter::NameOfConstant(byte* addr) const {
4054  return NameOfAddress(addr);
4055 }
4056 
4057 
4058 const char* NameConverter::NameOfCPURegister(int reg) const {
4059  unsigned ureg = reg; // Avoid warnings about signed/unsigned comparisons.
4060  if (ureg >= v8::internal::kNumberOfRegisters) {
4061  return "noreg";
4062  }
4063  if (ureg == v8::internal::kZeroRegCode) {
4064  return "xzr";
4065  }
4066  v8::internal::SNPrintF(tmp_buffer_, "x%u", ureg);
4067  return tmp_buffer_.start();
4068 }
4069 
4070 
4071 const char* NameConverter::NameOfByteCPURegister(int reg) const {
4072  UNREACHABLE(); // ARM64 does not have the concept of a byte register
4073  return "nobytereg";
4074 }
4075 
4076 
4077 const char* NameConverter::NameOfXMMRegister(int reg) const {
4078  UNREACHABLE(); // ARM64 does not have any XMM registers
4079  return "noxmmreg";
4080 }
4081 
4082 
4083 const char* NameConverter::NameInCode(byte* addr) const {
4084  // The default name converter is called for unknown code, so we will not try
4085  // to access any memory.
4086  return "";
4087 }
4088 
4089 
4090 //------------------------------------------------------------------------------
4091 
4092 class BufferDisassembler : public v8::internal::DisassemblingDecoder {
4093  public:
4094  explicit BufferDisassembler(v8::internal::Vector<char> out_buffer)
4095  : out_buffer_(out_buffer) { }
4096 
4097  ~BufferDisassembler() { }
4098 
4099  virtual void ProcessOutput(v8::internal::Instruction* instr) {
4100  v8::internal::SNPrintF(out_buffer_, "%08" PRIx32 " %s",
4101  instr->InstructionBits(), GetOutput());
4102  }
4103 
4104  private:
4105  v8::internal::Vector<char> out_buffer_;
4106 };
4107 
4108 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
4109  byte* instr) {
4110  USE(converter_); // avoid unused field warning
4112  BufferDisassembler disasm(buffer);
4113  decoder.AppendVisitor(&disasm);
4114 
4115  decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(instr));
4116  return v8::internal::kInstrSize;
4117 }
4118 
4119 
4120 int Disassembler::ConstantPoolSizeAt(byte* instr) {
4121  return v8::internal::Assembler::ConstantPoolSizeAt(
4122  reinterpret_cast<v8::internal::Instruction*>(instr));
4123 }
4124 
4125 void Disassembler::Disassemble(FILE* file, byte* start, byte* end,
4126  UnimplementedOpcodeAction) {
4129  decoder.AppendVisitor(&disasm);
4130 
4131  for (byte* pc = start; pc < end; pc += v8::internal::kInstrSize) {
4132  decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc));
4133  }
4134 }
4135 
4136 } // namespace disasm
4137 
4138 #endif // V8_TARGET_ARCH_ARM64
Definition: libplatform.h:13
Definition: disasm.h:10