LLVM  3.7.0
AArch64InstPrinter.cpp
Go to the documentation of this file.
1 //==-- AArch64InstPrinter.cpp - Convert AArch64 MCInst to assembly syntax --==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class prints an AArch64 MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "AArch64InstPrinter.h"
16 #include "Utils/AArch64BaseInfo.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/Support/Format.h"
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "asm-printer"
27 
28 #define GET_INSTRUCTION_NAME
29 #define PRINT_ALIAS_INSTR
30 #include "AArch64GenAsmWriter.inc"
31 #define GET_INSTRUCTION_NAME
32 #define PRINT_ALIAS_INSTR
33 #include "AArch64GenAsmWriter1.inc"
34 
36  const MCInstrInfo &MII,
37  const MCRegisterInfo &MRI)
38  : MCInstPrinter(MAI, MII, MRI) {}
39 
41  const MCInstrInfo &MII,
42  const MCRegisterInfo &MRI)
43  : AArch64InstPrinter(MAI, MII, MRI) {}
44 
45 void AArch64InstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
46  // This is for .cfi directives.
47  OS << getRegisterName(RegNo);
48 }
49 
51  StringRef Annot,
52  const MCSubtargetInfo &STI) {
53  // Check for special encodings and print the canonical alias instead.
54 
55  unsigned Opcode = MI->getOpcode();
56 
57  if (Opcode == AArch64::SYSxt)
58  if (printSysAlias(MI, O)) {
59  printAnnotation(O, Annot);
60  return;
61  }
62 
63  // SBFM/UBFM should print to a nicer aliased form if possible.
64  if (Opcode == AArch64::SBFMXri || Opcode == AArch64::SBFMWri ||
65  Opcode == AArch64::UBFMXri || Opcode == AArch64::UBFMWri) {
66  const MCOperand &Op0 = MI->getOperand(0);
67  const MCOperand &Op1 = MI->getOperand(1);
68  const MCOperand &Op2 = MI->getOperand(2);
69  const MCOperand &Op3 = MI->getOperand(3);
70 
71  bool IsSigned = (Opcode == AArch64::SBFMXri || Opcode == AArch64::SBFMWri);
72  bool Is64Bit = (Opcode == AArch64::SBFMXri || Opcode == AArch64::UBFMXri);
73  if (Op2.isImm() && Op2.getImm() == 0 && Op3.isImm()) {
74  const char *AsmMnemonic = nullptr;
75 
76  switch (Op3.getImm()) {
77  default:
78  break;
79  case 7:
80  if (IsSigned)
81  AsmMnemonic = "sxtb";
82  else if (!Is64Bit)
83  AsmMnemonic = "uxtb";
84  break;
85  case 15:
86  if (IsSigned)
87  AsmMnemonic = "sxth";
88  else if (!Is64Bit)
89  AsmMnemonic = "uxth";
90  break;
91  case 31:
92  // *xtw is only valid for signed 64-bit operations.
93  if (Is64Bit && IsSigned)
94  AsmMnemonic = "sxtw";
95  break;
96  }
97 
98  if (AsmMnemonic) {
99  O << '\t' << AsmMnemonic << '\t' << getRegisterName(Op0.getReg())
100  << ", " << getRegisterName(getWRegFromXReg(Op1.getReg()));
101  printAnnotation(O, Annot);
102  return;
103  }
104  }
105 
106  // All immediate shifts are aliases, implemented using the Bitfield
107  // instruction. In all cases the immediate shift amount shift must be in
108  // the range 0 to (reg.size -1).
109  if (Op2.isImm() && Op3.isImm()) {
110  const char *AsmMnemonic = nullptr;
111  int shift = 0;
112  int64_t immr = Op2.getImm();
113  int64_t imms = Op3.getImm();
114  if (Opcode == AArch64::UBFMWri && imms != 0x1F && ((imms + 1) == immr)) {
115  AsmMnemonic = "lsl";
116  shift = 31 - imms;
117  } else if (Opcode == AArch64::UBFMXri && imms != 0x3f &&
118  ((imms + 1 == immr))) {
119  AsmMnemonic = "lsl";
120  shift = 63 - imms;
121  } else if (Opcode == AArch64::UBFMWri && imms == 0x1f) {
122  AsmMnemonic = "lsr";
123  shift = immr;
124  } else if (Opcode == AArch64::UBFMXri && imms == 0x3f) {
125  AsmMnemonic = "lsr";
126  shift = immr;
127  } else if (Opcode == AArch64::SBFMWri && imms == 0x1f) {
128  AsmMnemonic = "asr";
129  shift = immr;
130  } else if (Opcode == AArch64::SBFMXri && imms == 0x3f) {
131  AsmMnemonic = "asr";
132  shift = immr;
133  }
134  if (AsmMnemonic) {
135  O << '\t' << AsmMnemonic << '\t' << getRegisterName(Op0.getReg())
136  << ", " << getRegisterName(Op1.getReg()) << ", #" << shift;
137  printAnnotation(O, Annot);
138  return;
139  }
140  }
141 
142  // SBFIZ/UBFIZ aliases
143  if (Op2.getImm() > Op3.getImm()) {
144  O << '\t' << (IsSigned ? "sbfiz" : "ubfiz") << '\t'
145  << getRegisterName(Op0.getReg()) << ", " << getRegisterName(Op1.getReg())
146  << ", #" << (Is64Bit ? 64 : 32) - Op2.getImm() << ", #" << Op3.getImm() + 1;
147  printAnnotation(O, Annot);
148  return;
149  }
150 
151  // Otherwise SBFX/UBFX is the preferred form
152  O << '\t' << (IsSigned ? "sbfx" : "ubfx") << '\t'
153  << getRegisterName(Op0.getReg()) << ", " << getRegisterName(Op1.getReg())
154  << ", #" << Op2.getImm() << ", #" << Op3.getImm() - Op2.getImm() + 1;
155  printAnnotation(O, Annot);
156  return;
157  }
158 
159  if (Opcode == AArch64::BFMXri || Opcode == AArch64::BFMWri) {
160  const MCOperand &Op0 = MI->getOperand(0); // Op1 == Op0
161  const MCOperand &Op2 = MI->getOperand(2);
162  int ImmR = MI->getOperand(3).getImm();
163  int ImmS = MI->getOperand(4).getImm();
164 
165  if ((Op2.getReg() == AArch64::WZR || Op2.getReg() == AArch64::XZR) &&
166  (ImmR == 0 || ImmS < ImmR)) {
167  // BFC takes precedence over its entire range, sligtly differently to BFI.
168  int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32;
169  int LSB = (BitWidth - ImmR) % BitWidth;
170  int Width = ImmS + 1;
171 
172  O << "\tbfc\t" << getRegisterName(Op0.getReg())
173  << ", #" << LSB << ", #" << Width;
174  printAnnotation(O, Annot);
175  return;
176  } else if (ImmS < ImmR) {
177  // BFI alias
178  int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32;
179  int LSB = (BitWidth - ImmR) % BitWidth;
180  int Width = ImmS + 1;
181 
182  O << "\tbfi\t" << getRegisterName(Op0.getReg()) << ", "
183  << getRegisterName(Op2.getReg()) << ", #" << LSB << ", #" << Width;
184  printAnnotation(O, Annot);
185  return;
186  }
187 
188  int LSB = ImmR;
189  int Width = ImmS - ImmR + 1;
190  // Otherwise BFXIL the preferred form
191  O << "\tbfxil\t"
192  << getRegisterName(Op0.getReg()) << ", " << getRegisterName(Op2.getReg())
193  << ", #" << LSB << ", #" << Width;
194  printAnnotation(O, Annot);
195  return;
196  }
197 
198  // Symbolic operands for MOVZ, MOVN and MOVK already imply a shift
199  // (e.g. :gottprel_g1: is always going to be "lsl #16") so it should not be
200  // printed.
201  if ((Opcode == AArch64::MOVZXi || Opcode == AArch64::MOVZWi ||
202  Opcode == AArch64::MOVNXi || Opcode == AArch64::MOVNWi) &&
203  MI->getOperand(1).isExpr()) {
204  if (Opcode == AArch64::MOVZXi || Opcode == AArch64::MOVZWi)
205  O << "\tmovz\t";
206  else
207  O << "\tmovn\t";
208 
209  O << getRegisterName(MI->getOperand(0).getReg()) << ", #";
210  MI->getOperand(1).getExpr()->print(O, &MAI);
211  return;
212  }
213 
214  if ((Opcode == AArch64::MOVKXi || Opcode == AArch64::MOVKWi) &&
215  MI->getOperand(2).isExpr()) {
216  O << "\tmovk\t" << getRegisterName(MI->getOperand(0).getReg()) << ", #";
217  MI->getOperand(2).getExpr()->print(O, &MAI);
218  return;
219  }
220 
221  if (!printAliasInstr(MI, STI, O))
222  printInstruction(MI, STI, O);
223 
224  printAnnotation(O, Annot);
225 }
226 
227 static bool isTblTbxInstruction(unsigned Opcode, StringRef &Layout,
228  bool &IsTbx) {
229  switch (Opcode) {
230  case AArch64::TBXv8i8One:
231  case AArch64::TBXv8i8Two:
232  case AArch64::TBXv8i8Three:
233  case AArch64::TBXv8i8Four:
234  IsTbx = true;
235  Layout = ".8b";
236  return true;
237  case AArch64::TBLv8i8One:
238  case AArch64::TBLv8i8Two:
239  case AArch64::TBLv8i8Three:
240  case AArch64::TBLv8i8Four:
241  IsTbx = false;
242  Layout = ".8b";
243  return true;
244  case AArch64::TBXv16i8One:
245  case AArch64::TBXv16i8Two:
246  case AArch64::TBXv16i8Three:
247  case AArch64::TBXv16i8Four:
248  IsTbx = true;
249  Layout = ".16b";
250  return true;
251  case AArch64::TBLv16i8One:
252  case AArch64::TBLv16i8Two:
253  case AArch64::TBLv16i8Three:
254  case AArch64::TBLv16i8Four:
255  IsTbx = false;
256  Layout = ".16b";
257  return true;
258  default:
259  return false;
260  }
261 }
262 
264  unsigned Opcode;
265  const char *Mnemonic;
266  const char *Layout;
268  bool HasLane;
270 };
271 
273  { AArch64::LD1i8, "ld1", ".b", 1, true, 0 },
274  { AArch64::LD1i16, "ld1", ".h", 1, true, 0 },
275  { AArch64::LD1i32, "ld1", ".s", 1, true, 0 },
276  { AArch64::LD1i64, "ld1", ".d", 1, true, 0 },
277  { AArch64::LD1i8_POST, "ld1", ".b", 2, true, 1 },
278  { AArch64::LD1i16_POST, "ld1", ".h", 2, true, 2 },
279  { AArch64::LD1i32_POST, "ld1", ".s", 2, true, 4 },
280  { AArch64::LD1i64_POST, "ld1", ".d", 2, true, 8 },
281  { AArch64::LD1Rv16b, "ld1r", ".16b", 0, false, 0 },
282  { AArch64::LD1Rv8h, "ld1r", ".8h", 0, false, 0 },
283  { AArch64::LD1Rv4s, "ld1r", ".4s", 0, false, 0 },
284  { AArch64::LD1Rv2d, "ld1r", ".2d", 0, false, 0 },
285  { AArch64::LD1Rv8b, "ld1r", ".8b", 0, false, 0 },
286  { AArch64::LD1Rv4h, "ld1r", ".4h", 0, false, 0 },
287  { AArch64::LD1Rv2s, "ld1r", ".2s", 0, false, 0 },
288  { AArch64::LD1Rv1d, "ld1r", ".1d", 0, false, 0 },
289  { AArch64::LD1Rv16b_POST, "ld1r", ".16b", 1, false, 1 },
290  { AArch64::LD1Rv8h_POST, "ld1r", ".8h", 1, false, 2 },
291  { AArch64::LD1Rv4s_POST, "ld1r", ".4s", 1, false, 4 },
292  { AArch64::LD1Rv2d_POST, "ld1r", ".2d", 1, false, 8 },
293  { AArch64::LD1Rv8b_POST, "ld1r", ".8b", 1, false, 1 },
294  { AArch64::LD1Rv4h_POST, "ld1r", ".4h", 1, false, 2 },
295  { AArch64::LD1Rv2s_POST, "ld1r", ".2s", 1, false, 4 },
296  { AArch64::LD1Rv1d_POST, "ld1r", ".1d", 1, false, 8 },
297  { AArch64::LD1Onev16b, "ld1", ".16b", 0, false, 0 },
298  { AArch64::LD1Onev8h, "ld1", ".8h", 0, false, 0 },
299  { AArch64::LD1Onev4s, "ld1", ".4s", 0, false, 0 },
300  { AArch64::LD1Onev2d, "ld1", ".2d", 0, false, 0 },
301  { AArch64::LD1Onev8b, "ld1", ".8b", 0, false, 0 },
302  { AArch64::LD1Onev4h, "ld1", ".4h", 0, false, 0 },
303  { AArch64::LD1Onev2s, "ld1", ".2s", 0, false, 0 },
304  { AArch64::LD1Onev1d, "ld1", ".1d", 0, false, 0 },
305  { AArch64::LD1Onev16b_POST, "ld1", ".16b", 1, false, 16 },
306  { AArch64::LD1Onev8h_POST, "ld1", ".8h", 1, false, 16 },
307  { AArch64::LD1Onev4s_POST, "ld1", ".4s", 1, false, 16 },
308  { AArch64::LD1Onev2d_POST, "ld1", ".2d", 1, false, 16 },
309  { AArch64::LD1Onev8b_POST, "ld1", ".8b", 1, false, 8 },
310  { AArch64::LD1Onev4h_POST, "ld1", ".4h", 1, false, 8 },
311  { AArch64::LD1Onev2s_POST, "ld1", ".2s", 1, false, 8 },
312  { AArch64::LD1Onev1d_POST, "ld1", ".1d", 1, false, 8 },
313  { AArch64::LD1Twov16b, "ld1", ".16b", 0, false, 0 },
314  { AArch64::LD1Twov8h, "ld1", ".8h", 0, false, 0 },
315  { AArch64::LD1Twov4s, "ld1", ".4s", 0, false, 0 },
316  { AArch64::LD1Twov2d, "ld1", ".2d", 0, false, 0 },
317  { AArch64::LD1Twov8b, "ld1", ".8b", 0, false, 0 },
318  { AArch64::LD1Twov4h, "ld1", ".4h", 0, false, 0 },
319  { AArch64::LD1Twov2s, "ld1", ".2s", 0, false, 0 },
320  { AArch64::LD1Twov1d, "ld1", ".1d", 0, false, 0 },
321  { AArch64::LD1Twov16b_POST, "ld1", ".16b", 1, false, 32 },
322  { AArch64::LD1Twov8h_POST, "ld1", ".8h", 1, false, 32 },
323  { AArch64::LD1Twov4s_POST, "ld1", ".4s", 1, false, 32 },
324  { AArch64::LD1Twov2d_POST, "ld1", ".2d", 1, false, 32 },
325  { AArch64::LD1Twov8b_POST, "ld1", ".8b", 1, false, 16 },
326  { AArch64::LD1Twov4h_POST, "ld1", ".4h", 1, false, 16 },
327  { AArch64::LD1Twov2s_POST, "ld1", ".2s", 1, false, 16 },
328  { AArch64::LD1Twov1d_POST, "ld1", ".1d", 1, false, 16 },
329  { AArch64::LD1Threev16b, "ld1", ".16b", 0, false, 0 },
330  { AArch64::LD1Threev8h, "ld1", ".8h", 0, false, 0 },
331  { AArch64::LD1Threev4s, "ld1", ".4s", 0, false, 0 },
332  { AArch64::LD1Threev2d, "ld1", ".2d", 0, false, 0 },
333  { AArch64::LD1Threev8b, "ld1", ".8b", 0, false, 0 },
334  { AArch64::LD1Threev4h, "ld1", ".4h", 0, false, 0 },
335  { AArch64::LD1Threev2s, "ld1", ".2s", 0, false, 0 },
336  { AArch64::LD1Threev1d, "ld1", ".1d", 0, false, 0 },
337  { AArch64::LD1Threev16b_POST, "ld1", ".16b", 1, false, 48 },
338  { AArch64::LD1Threev8h_POST, "ld1", ".8h", 1, false, 48 },
339  { AArch64::LD1Threev4s_POST, "ld1", ".4s", 1, false, 48 },
340  { AArch64::LD1Threev2d_POST, "ld1", ".2d", 1, false, 48 },
341  { AArch64::LD1Threev8b_POST, "ld1", ".8b", 1, false, 24 },
342  { AArch64::LD1Threev4h_POST, "ld1", ".4h", 1, false, 24 },
343  { AArch64::LD1Threev2s_POST, "ld1", ".2s", 1, false, 24 },
344  { AArch64::LD1Threev1d_POST, "ld1", ".1d", 1, false, 24 },
345  { AArch64::LD1Fourv16b, "ld1", ".16b", 0, false, 0 },
346  { AArch64::LD1Fourv8h, "ld1", ".8h", 0, false, 0 },
347  { AArch64::LD1Fourv4s, "ld1", ".4s", 0, false, 0 },
348  { AArch64::LD1Fourv2d, "ld1", ".2d", 0, false, 0 },
349  { AArch64::LD1Fourv8b, "ld1", ".8b", 0, false, 0 },
350  { AArch64::LD1Fourv4h, "ld1", ".4h", 0, false, 0 },
351  { AArch64::LD1Fourv2s, "ld1", ".2s", 0, false, 0 },
352  { AArch64::LD1Fourv1d, "ld1", ".1d", 0, false, 0 },
353  { AArch64::LD1Fourv16b_POST, "ld1", ".16b", 1, false, 64 },
354  { AArch64::LD1Fourv8h_POST, "ld1", ".8h", 1, false, 64 },
355  { AArch64::LD1Fourv4s_POST, "ld1", ".4s", 1, false, 64 },
356  { AArch64::LD1Fourv2d_POST, "ld1", ".2d", 1, false, 64 },
357  { AArch64::LD1Fourv8b_POST, "ld1", ".8b", 1, false, 32 },
358  { AArch64::LD1Fourv4h_POST, "ld1", ".4h", 1, false, 32 },
359  { AArch64::LD1Fourv2s_POST, "ld1", ".2s", 1, false, 32 },
360  { AArch64::LD1Fourv1d_POST, "ld1", ".1d", 1, false, 32 },
361  { AArch64::LD2i8, "ld2", ".b", 1, true, 0 },
362  { AArch64::LD2i16, "ld2", ".h", 1, true, 0 },
363  { AArch64::LD2i32, "ld2", ".s", 1, true, 0 },
364  { AArch64::LD2i64, "ld2", ".d", 1, true, 0 },
365  { AArch64::LD2i8_POST, "ld2", ".b", 2, true, 2 },
366  { AArch64::LD2i16_POST, "ld2", ".h", 2, true, 4 },
367  { AArch64::LD2i32_POST, "ld2", ".s", 2, true, 8 },
368  { AArch64::LD2i64_POST, "ld2", ".d", 2, true, 16 },
369  { AArch64::LD2Rv16b, "ld2r", ".16b", 0, false, 0 },
370  { AArch64::LD2Rv8h, "ld2r", ".8h", 0, false, 0 },
371  { AArch64::LD2Rv4s, "ld2r", ".4s", 0, false, 0 },
372  { AArch64::LD2Rv2d, "ld2r", ".2d", 0, false, 0 },
373  { AArch64::LD2Rv8b, "ld2r", ".8b", 0, false, 0 },
374  { AArch64::LD2Rv4h, "ld2r", ".4h", 0, false, 0 },
375  { AArch64::LD2Rv2s, "ld2r", ".2s", 0, false, 0 },
376  { AArch64::LD2Rv1d, "ld2r", ".1d", 0, false, 0 },
377  { AArch64::LD2Rv16b_POST, "ld2r", ".16b", 1, false, 2 },
378  { AArch64::LD2Rv8h_POST, "ld2r", ".8h", 1, false, 4 },
379  { AArch64::LD2Rv4s_POST, "ld2r", ".4s", 1, false, 8 },
380  { AArch64::LD2Rv2d_POST, "ld2r", ".2d", 1, false, 16 },
381  { AArch64::LD2Rv8b_POST, "ld2r", ".8b", 1, false, 2 },
382  { AArch64::LD2Rv4h_POST, "ld2r", ".4h", 1, false, 4 },
383  { AArch64::LD2Rv2s_POST, "ld2r", ".2s", 1, false, 8 },
384  { AArch64::LD2Rv1d_POST, "ld2r", ".1d", 1, false, 16 },
385  { AArch64::LD2Twov16b, "ld2", ".16b", 0, false, 0 },
386  { AArch64::LD2Twov8h, "ld2", ".8h", 0, false, 0 },
387  { AArch64::LD2Twov4s, "ld2", ".4s", 0, false, 0 },
388  { AArch64::LD2Twov2d, "ld2", ".2d", 0, false, 0 },
389  { AArch64::LD2Twov8b, "ld2", ".8b", 0, false, 0 },
390  { AArch64::LD2Twov4h, "ld2", ".4h", 0, false, 0 },
391  { AArch64::LD2Twov2s, "ld2", ".2s", 0, false, 0 },
392  { AArch64::LD2Twov16b_POST, "ld2", ".16b", 1, false, 32 },
393  { AArch64::LD2Twov8h_POST, "ld2", ".8h", 1, false, 32 },
394  { AArch64::LD2Twov4s_POST, "ld2", ".4s", 1, false, 32 },
395  { AArch64::LD2Twov2d_POST, "ld2", ".2d", 1, false, 32 },
396  { AArch64::LD2Twov8b_POST, "ld2", ".8b", 1, false, 16 },
397  { AArch64::LD2Twov4h_POST, "ld2", ".4h", 1, false, 16 },
398  { AArch64::LD2Twov2s_POST, "ld2", ".2s", 1, false, 16 },
399  { AArch64::LD3i8, "ld3", ".b", 1, true, 0 },
400  { AArch64::LD3i16, "ld3", ".h", 1, true, 0 },
401  { AArch64::LD3i32, "ld3", ".s", 1, true, 0 },
402  { AArch64::LD3i64, "ld3", ".d", 1, true, 0 },
403  { AArch64::LD3i8_POST, "ld3", ".b", 2, true, 3 },
404  { AArch64::LD3i16_POST, "ld3", ".h", 2, true, 6 },
405  { AArch64::LD3i32_POST, "ld3", ".s", 2, true, 12 },
406  { AArch64::LD3i64_POST, "ld3", ".d", 2, true, 24 },
407  { AArch64::LD3Rv16b, "ld3r", ".16b", 0, false, 0 },
408  { AArch64::LD3Rv8h, "ld3r", ".8h", 0, false, 0 },
409  { AArch64::LD3Rv4s, "ld3r", ".4s", 0, false, 0 },
410  { AArch64::LD3Rv2d, "ld3r", ".2d", 0, false, 0 },
411  { AArch64::LD3Rv8b, "ld3r", ".8b", 0, false, 0 },
412  { AArch64::LD3Rv4h, "ld3r", ".4h", 0, false, 0 },
413  { AArch64::LD3Rv2s, "ld3r", ".2s", 0, false, 0 },
414  { AArch64::LD3Rv1d, "ld3r", ".1d", 0, false, 0 },
415  { AArch64::LD3Rv16b_POST, "ld3r", ".16b", 1, false, 3 },
416  { AArch64::LD3Rv8h_POST, "ld3r", ".8h", 1, false, 6 },
417  { AArch64::LD3Rv4s_POST, "ld3r", ".4s", 1, false, 12 },
418  { AArch64::LD3Rv2d_POST, "ld3r", ".2d", 1, false, 24 },
419  { AArch64::LD3Rv8b_POST, "ld3r", ".8b", 1, false, 3 },
420  { AArch64::LD3Rv4h_POST, "ld3r", ".4h", 1, false, 6 },
421  { AArch64::LD3Rv2s_POST, "ld3r", ".2s", 1, false, 12 },
422  { AArch64::LD3Rv1d_POST, "ld3r", ".1d", 1, false, 24 },
423  { AArch64::LD3Threev16b, "ld3", ".16b", 0, false, 0 },
424  { AArch64::LD3Threev8h, "ld3", ".8h", 0, false, 0 },
425  { AArch64::LD3Threev4s, "ld3", ".4s", 0, false, 0 },
426  { AArch64::LD3Threev2d, "ld3", ".2d", 0, false, 0 },
427  { AArch64::LD3Threev8b, "ld3", ".8b", 0, false, 0 },
428  { AArch64::LD3Threev4h, "ld3", ".4h", 0, false, 0 },
429  { AArch64::LD3Threev2s, "ld3", ".2s", 0, false, 0 },
430  { AArch64::LD3Threev16b_POST, "ld3", ".16b", 1, false, 48 },
431  { AArch64::LD3Threev8h_POST, "ld3", ".8h", 1, false, 48 },
432  { AArch64::LD3Threev4s_POST, "ld3", ".4s", 1, false, 48 },
433  { AArch64::LD3Threev2d_POST, "ld3", ".2d", 1, false, 48 },
434  { AArch64::LD3Threev8b_POST, "ld3", ".8b", 1, false, 24 },
435  { AArch64::LD3Threev4h_POST, "ld3", ".4h", 1, false, 24 },
436  { AArch64::LD3Threev2s_POST, "ld3", ".2s", 1, false, 24 },
437  { AArch64::LD4i8, "ld4", ".b", 1, true, 0 },
438  { AArch64::LD4i16, "ld4", ".h", 1, true, 0 },
439  { AArch64::LD4i32, "ld4", ".s", 1, true, 0 },
440  { AArch64::LD4i64, "ld4", ".d", 1, true, 0 },
441  { AArch64::LD4i8_POST, "ld4", ".b", 2, true, 4 },
442  { AArch64::LD4i16_POST, "ld4", ".h", 2, true, 8 },
443  { AArch64::LD4i32_POST, "ld4", ".s", 2, true, 16 },
444  { AArch64::LD4i64_POST, "ld4", ".d", 2, true, 32 },
445  { AArch64::LD4Rv16b, "ld4r", ".16b", 0, false, 0 },
446  { AArch64::LD4Rv8h, "ld4r", ".8h", 0, false, 0 },
447  { AArch64::LD4Rv4s, "ld4r", ".4s", 0, false, 0 },
448  { AArch64::LD4Rv2d, "ld4r", ".2d", 0, false, 0 },
449  { AArch64::LD4Rv8b, "ld4r", ".8b", 0, false, 0 },
450  { AArch64::LD4Rv4h, "ld4r", ".4h", 0, false, 0 },
451  { AArch64::LD4Rv2s, "ld4r", ".2s", 0, false, 0 },
452  { AArch64::LD4Rv1d, "ld4r", ".1d", 0, false, 0 },
453  { AArch64::LD4Rv16b_POST, "ld4r", ".16b", 1, false, 4 },
454  { AArch64::LD4Rv8h_POST, "ld4r", ".8h", 1, false, 8 },
455  { AArch64::LD4Rv4s_POST, "ld4r", ".4s", 1, false, 16 },
456  { AArch64::LD4Rv2d_POST, "ld4r", ".2d", 1, false, 32 },
457  { AArch64::LD4Rv8b_POST, "ld4r", ".8b", 1, false, 4 },
458  { AArch64::LD4Rv4h_POST, "ld4r", ".4h", 1, false, 8 },
459  { AArch64::LD4Rv2s_POST, "ld4r", ".2s", 1, false, 16 },
460  { AArch64::LD4Rv1d_POST, "ld4r", ".1d", 1, false, 32 },
461  { AArch64::LD4Fourv16b, "ld4", ".16b", 0, false, 0 },
462  { AArch64::LD4Fourv8h, "ld4", ".8h", 0, false, 0 },
463  { AArch64::LD4Fourv4s, "ld4", ".4s", 0, false, 0 },
464  { AArch64::LD4Fourv2d, "ld4", ".2d", 0, false, 0 },
465  { AArch64::LD4Fourv8b, "ld4", ".8b", 0, false, 0 },
466  { AArch64::LD4Fourv4h, "ld4", ".4h", 0, false, 0 },
467  { AArch64::LD4Fourv2s, "ld4", ".2s", 0, false, 0 },
468  { AArch64::LD4Fourv16b_POST, "ld4", ".16b", 1, false, 64 },
469  { AArch64::LD4Fourv8h_POST, "ld4", ".8h", 1, false, 64 },
470  { AArch64::LD4Fourv4s_POST, "ld4", ".4s", 1, false, 64 },
471  { AArch64::LD4Fourv2d_POST, "ld4", ".2d", 1, false, 64 },
472  { AArch64::LD4Fourv8b_POST, "ld4", ".8b", 1, false, 32 },
473  { AArch64::LD4Fourv4h_POST, "ld4", ".4h", 1, false, 32 },
474  { AArch64::LD4Fourv2s_POST, "ld4", ".2s", 1, false, 32 },
475  { AArch64::ST1i8, "st1", ".b", 0, true, 0 },
476  { AArch64::ST1i16, "st1", ".h", 0, true, 0 },
477  { AArch64::ST1i32, "st1", ".s", 0, true, 0 },
478  { AArch64::ST1i64, "st1", ".d", 0, true, 0 },
479  { AArch64::ST1i8_POST, "st1", ".b", 1, true, 1 },
480  { AArch64::ST1i16_POST, "st1", ".h", 1, true, 2 },
481  { AArch64::ST1i32_POST, "st1", ".s", 1, true, 4 },
482  { AArch64::ST1i64_POST, "st1", ".d", 1, true, 8 },
483  { AArch64::ST1Onev16b, "st1", ".16b", 0, false, 0 },
484  { AArch64::ST1Onev8h, "st1", ".8h", 0, false, 0 },
485  { AArch64::ST1Onev4s, "st1", ".4s", 0, false, 0 },
486  { AArch64::ST1Onev2d, "st1", ".2d", 0, false, 0 },
487  { AArch64::ST1Onev8b, "st1", ".8b", 0, false, 0 },
488  { AArch64::ST1Onev4h, "st1", ".4h", 0, false, 0 },
489  { AArch64::ST1Onev2s, "st1", ".2s", 0, false, 0 },
490  { AArch64::ST1Onev1d, "st1", ".1d", 0, false, 0 },
491  { AArch64::ST1Onev16b_POST, "st1", ".16b", 1, false, 16 },
492  { AArch64::ST1Onev8h_POST, "st1", ".8h", 1, false, 16 },
493  { AArch64::ST1Onev4s_POST, "st1", ".4s", 1, false, 16 },
494  { AArch64::ST1Onev2d_POST, "st1", ".2d", 1, false, 16 },
495  { AArch64::ST1Onev8b_POST, "st1", ".8b", 1, false, 8 },
496  { AArch64::ST1Onev4h_POST, "st1", ".4h", 1, false, 8 },
497  { AArch64::ST1Onev2s_POST, "st1", ".2s", 1, false, 8 },
498  { AArch64::ST1Onev1d_POST, "st1", ".1d", 1, false, 8 },
499  { AArch64::ST1Twov16b, "st1", ".16b", 0, false, 0 },
500  { AArch64::ST1Twov8h, "st1", ".8h", 0, false, 0 },
501  { AArch64::ST1Twov4s, "st1", ".4s", 0, false, 0 },
502  { AArch64::ST1Twov2d, "st1", ".2d", 0, false, 0 },
503  { AArch64::ST1Twov8b, "st1", ".8b", 0, false, 0 },
504  { AArch64::ST1Twov4h, "st1", ".4h", 0, false, 0 },
505  { AArch64::ST1Twov2s, "st1", ".2s", 0, false, 0 },
506  { AArch64::ST1Twov1d, "st1", ".1d", 0, false, 0 },
507  { AArch64::ST1Twov16b_POST, "st1", ".16b", 1, false, 32 },
508  { AArch64::ST1Twov8h_POST, "st1", ".8h", 1, false, 32 },
509  { AArch64::ST1Twov4s_POST, "st1", ".4s", 1, false, 32 },
510  { AArch64::ST1Twov2d_POST, "st1", ".2d", 1, false, 32 },
511  { AArch64::ST1Twov8b_POST, "st1", ".8b", 1, false, 16 },
512  { AArch64::ST1Twov4h_POST, "st1", ".4h", 1, false, 16 },
513  { AArch64::ST1Twov2s_POST, "st1", ".2s", 1, false, 16 },
514  { AArch64::ST1Twov1d_POST, "st1", ".1d", 1, false, 16 },
515  { AArch64::ST1Threev16b, "st1", ".16b", 0, false, 0 },
516  { AArch64::ST1Threev8h, "st1", ".8h", 0, false, 0 },
517  { AArch64::ST1Threev4s, "st1", ".4s", 0, false, 0 },
518  { AArch64::ST1Threev2d, "st1", ".2d", 0, false, 0 },
519  { AArch64::ST1Threev8b, "st1", ".8b", 0, false, 0 },
520  { AArch64::ST1Threev4h, "st1", ".4h", 0, false, 0 },
521  { AArch64::ST1Threev2s, "st1", ".2s", 0, false, 0 },
522  { AArch64::ST1Threev1d, "st1", ".1d", 0, false, 0 },
523  { AArch64::ST1Threev16b_POST, "st1", ".16b", 1, false, 48 },
524  { AArch64::ST1Threev8h_POST, "st1", ".8h", 1, false, 48 },
525  { AArch64::ST1Threev4s_POST, "st1", ".4s", 1, false, 48 },
526  { AArch64::ST1Threev2d_POST, "st1", ".2d", 1, false, 48 },
527  { AArch64::ST1Threev8b_POST, "st1", ".8b", 1, false, 24 },
528  { AArch64::ST1Threev4h_POST, "st1", ".4h", 1, false, 24 },
529  { AArch64::ST1Threev2s_POST, "st1", ".2s", 1, false, 24 },
530  { AArch64::ST1Threev1d_POST, "st1", ".1d", 1, false, 24 },
531  { AArch64::ST1Fourv16b, "st1", ".16b", 0, false, 0 },
532  { AArch64::ST1Fourv8h, "st1", ".8h", 0, false, 0 },
533  { AArch64::ST1Fourv4s, "st1", ".4s", 0, false, 0 },
534  { AArch64::ST1Fourv2d, "st1", ".2d", 0, false, 0 },
535  { AArch64::ST1Fourv8b, "st1", ".8b", 0, false, 0 },
536  { AArch64::ST1Fourv4h, "st1", ".4h", 0, false, 0 },
537  { AArch64::ST1Fourv2s, "st1", ".2s", 0, false, 0 },
538  { AArch64::ST1Fourv1d, "st1", ".1d", 0, false, 0 },
539  { AArch64::ST1Fourv16b_POST, "st1", ".16b", 1, false, 64 },
540  { AArch64::ST1Fourv8h_POST, "st1", ".8h", 1, false, 64 },
541  { AArch64::ST1Fourv4s_POST, "st1", ".4s", 1, false, 64 },
542  { AArch64::ST1Fourv2d_POST, "st1", ".2d", 1, false, 64 },
543  { AArch64::ST1Fourv8b_POST, "st1", ".8b", 1, false, 32 },
544  { AArch64::ST1Fourv4h_POST, "st1", ".4h", 1, false, 32 },
545  { AArch64::ST1Fourv2s_POST, "st1", ".2s", 1, false, 32 },
546  { AArch64::ST1Fourv1d_POST, "st1", ".1d", 1, false, 32 },
547  { AArch64::ST2i8, "st2", ".b", 0, true, 0 },
548  { AArch64::ST2i16, "st2", ".h", 0, true, 0 },
549  { AArch64::ST2i32, "st2", ".s", 0, true, 0 },
550  { AArch64::ST2i64, "st2", ".d", 0, true, 0 },
551  { AArch64::ST2i8_POST, "st2", ".b", 1, true, 2 },
552  { AArch64::ST2i16_POST, "st2", ".h", 1, true, 4 },
553  { AArch64::ST2i32_POST, "st2", ".s", 1, true, 8 },
554  { AArch64::ST2i64_POST, "st2", ".d", 1, true, 16 },
555  { AArch64::ST2Twov16b, "st2", ".16b", 0, false, 0 },
556  { AArch64::ST2Twov8h, "st2", ".8h", 0, false, 0 },
557  { AArch64::ST2Twov4s, "st2", ".4s", 0, false, 0 },
558  { AArch64::ST2Twov2d, "st2", ".2d", 0, false, 0 },
559  { AArch64::ST2Twov8b, "st2", ".8b", 0, false, 0 },
560  { AArch64::ST2Twov4h, "st2", ".4h", 0, false, 0 },
561  { AArch64::ST2Twov2s, "st2", ".2s", 0, false, 0 },
562  { AArch64::ST2Twov16b_POST, "st2", ".16b", 1, false, 32 },
563  { AArch64::ST2Twov8h_POST, "st2", ".8h", 1, false, 32 },
564  { AArch64::ST2Twov4s_POST, "st2", ".4s", 1, false, 32 },
565  { AArch64::ST2Twov2d_POST, "st2", ".2d", 1, false, 32 },
566  { AArch64::ST2Twov8b_POST, "st2", ".8b", 1, false, 16 },
567  { AArch64::ST2Twov4h_POST, "st2", ".4h", 1, false, 16 },
568  { AArch64::ST2Twov2s_POST, "st2", ".2s", 1, false, 16 },
569  { AArch64::ST3i8, "st3", ".b", 0, true, 0 },
570  { AArch64::ST3i16, "st3", ".h", 0, true, 0 },
571  { AArch64::ST3i32, "st3", ".s", 0, true, 0 },
572  { AArch64::ST3i64, "st3", ".d", 0, true, 0 },
573  { AArch64::ST3i8_POST, "st3", ".b", 1, true, 3 },
574  { AArch64::ST3i16_POST, "st3", ".h", 1, true, 6 },
575  { AArch64::ST3i32_POST, "st3", ".s", 1, true, 12 },
576  { AArch64::ST3i64_POST, "st3", ".d", 1, true, 24 },
577  { AArch64::ST3Threev16b, "st3", ".16b", 0, false, 0 },
578  { AArch64::ST3Threev8h, "st3", ".8h", 0, false, 0 },
579  { AArch64::ST3Threev4s, "st3", ".4s", 0, false, 0 },
580  { AArch64::ST3Threev2d, "st3", ".2d", 0, false, 0 },
581  { AArch64::ST3Threev8b, "st3", ".8b", 0, false, 0 },
582  { AArch64::ST3Threev4h, "st3", ".4h", 0, false, 0 },
583  { AArch64::ST3Threev2s, "st3", ".2s", 0, false, 0 },
584  { AArch64::ST3Threev16b_POST, "st3", ".16b", 1, false, 48 },
585  { AArch64::ST3Threev8h_POST, "st3", ".8h", 1, false, 48 },
586  { AArch64::ST3Threev4s_POST, "st3", ".4s", 1, false, 48 },
587  { AArch64::ST3Threev2d_POST, "st3", ".2d", 1, false, 48 },
588  { AArch64::ST3Threev8b_POST, "st3", ".8b", 1, false, 24 },
589  { AArch64::ST3Threev4h_POST, "st3", ".4h", 1, false, 24 },
590  { AArch64::ST3Threev2s_POST, "st3", ".2s", 1, false, 24 },
591  { AArch64::ST4i8, "st4", ".b", 0, true, 0 },
592  { AArch64::ST4i16, "st4", ".h", 0, true, 0 },
593  { AArch64::ST4i32, "st4", ".s", 0, true, 0 },
594  { AArch64::ST4i64, "st4", ".d", 0, true, 0 },
595  { AArch64::ST4i8_POST, "st4", ".b", 1, true, 4 },
596  { AArch64::ST4i16_POST, "st4", ".h", 1, true, 8 },
597  { AArch64::ST4i32_POST, "st4", ".s", 1, true, 16 },
598  { AArch64::ST4i64_POST, "st4", ".d", 1, true, 32 },
599  { AArch64::ST4Fourv16b, "st4", ".16b", 0, false, 0 },
600  { AArch64::ST4Fourv8h, "st4", ".8h", 0, false, 0 },
601  { AArch64::ST4Fourv4s, "st4", ".4s", 0, false, 0 },
602  { AArch64::ST4Fourv2d, "st4", ".2d", 0, false, 0 },
603  { AArch64::ST4Fourv8b, "st4", ".8b", 0, false, 0 },
604  { AArch64::ST4Fourv4h, "st4", ".4h", 0, false, 0 },
605  { AArch64::ST4Fourv2s, "st4", ".2s", 0, false, 0 },
606  { AArch64::ST4Fourv16b_POST, "st4", ".16b", 1, false, 64 },
607  { AArch64::ST4Fourv8h_POST, "st4", ".8h", 1, false, 64 },
608  { AArch64::ST4Fourv4s_POST, "st4", ".4s", 1, false, 64 },
609  { AArch64::ST4Fourv2d_POST, "st4", ".2d", 1, false, 64 },
610  { AArch64::ST4Fourv8b_POST, "st4", ".8b", 1, false, 32 },
611  { AArch64::ST4Fourv4h_POST, "st4", ".4h", 1, false, 32 },
612  { AArch64::ST4Fourv2s_POST, "st4", ".2s", 1, false, 32 },
613 };
614 
615 static LdStNInstrDesc *getLdStNInstrDesc(unsigned Opcode) {
616  unsigned Idx;
617  for (Idx = 0; Idx != array_lengthof(LdStNInstInfo); ++Idx)
618  if (LdStNInstInfo[Idx].Opcode == Opcode)
619  return &LdStNInstInfo[Idx];
620 
621  return nullptr;
622 }
623 
625  StringRef Annot,
626  const MCSubtargetInfo &STI) {
627  unsigned Opcode = MI->getOpcode();
628  StringRef Layout, Mnemonic;
629 
630  bool IsTbx;
631  if (isTblTbxInstruction(MI->getOpcode(), Layout, IsTbx)) {
632  O << "\t" << (IsTbx ? "tbx" : "tbl") << Layout << '\t'
633  << getRegisterName(MI->getOperand(0).getReg(), AArch64::vreg) << ", ";
634 
635  unsigned ListOpNum = IsTbx ? 2 : 1;
636  printVectorList(MI, ListOpNum, STI, O, "");
637 
638  O << ", "
639  << getRegisterName(MI->getOperand(ListOpNum + 1).getReg(), AArch64::vreg);
640  printAnnotation(O, Annot);
641  return;
642  }
643 
644  if (LdStNInstrDesc *LdStDesc = getLdStNInstrDesc(Opcode)) {
645  O << "\t" << LdStDesc->Mnemonic << LdStDesc->Layout << '\t';
646 
647  // Now onto the operands: first a vector list with possible lane
648  // specifier. E.g. { v0 }[2]
649  int OpNum = LdStDesc->ListOperand;
650  printVectorList(MI, OpNum++, STI, O, "");
651 
652  if (LdStDesc->HasLane)
653  O << '[' << MI->getOperand(OpNum++).getImm() << ']';
654 
655  // Next the address: [xN]
656  unsigned AddrReg = MI->getOperand(OpNum++).getReg();
657  O << ", [" << getRegisterName(AddrReg) << ']';
658 
659  // Finally, there might be a post-indexed offset.
660  if (LdStDesc->NaturalOffset != 0) {
661  unsigned Reg = MI->getOperand(OpNum++).getReg();
662  if (Reg != AArch64::XZR)
663  O << ", " << getRegisterName(Reg);
664  else {
665  assert(LdStDesc->NaturalOffset && "no offset on post-inc instruction?");
666  O << ", #" << LdStDesc->NaturalOffset;
667  }
668  }
669 
670  printAnnotation(O, Annot);
671  return;
672  }
673 
674  AArch64InstPrinter::printInst(MI, O, Annot, STI);
675 }
676 
678 #ifndef NDEBUG
679  unsigned Opcode = MI->getOpcode();
680  assert(Opcode == AArch64::SYSxt && "Invalid opcode for SYS alias!");
681 #endif
682 
683  const char *Asm = nullptr;
684  const MCOperand &Op1 = MI->getOperand(0);
685  const MCOperand &Cn = MI->getOperand(1);
686  const MCOperand &Cm = MI->getOperand(2);
687  const MCOperand &Op2 = MI->getOperand(3);
688 
689  unsigned Op1Val = Op1.getImm();
690  unsigned CnVal = Cn.getImm();
691  unsigned CmVal = Cm.getImm();
692  unsigned Op2Val = Op2.getImm();
693 
694  if (CnVal == 7) {
695  switch (CmVal) {
696  default:
697  break;
698 
699  // IC aliases
700  case 1:
701  if (Op1Val == 0 && Op2Val == 0)
702  Asm = "ic\tialluis";
703  break;
704  case 5:
705  if (Op1Val == 0 && Op2Val == 0)
706  Asm = "ic\tiallu";
707  else if (Op1Val == 3 && Op2Val == 1)
708  Asm = "ic\tivau";
709  break;
710 
711  // DC aliases
712  case 4:
713  if (Op1Val == 3 && Op2Val == 1)
714  Asm = "dc\tzva";
715  break;
716  case 6:
717  if (Op1Val == 0 && Op2Val == 1)
718  Asm = "dc\tivac";
719  if (Op1Val == 0 && Op2Val == 2)
720  Asm = "dc\tisw";
721  break;
722  case 10:
723  if (Op1Val == 3 && Op2Val == 1)
724  Asm = "dc\tcvac";
725  else if (Op1Val == 0 && Op2Val == 2)
726  Asm = "dc\tcsw";
727  break;
728  case 11:
729  if (Op1Val == 3 && Op2Val == 1)
730  Asm = "dc\tcvau";
731  break;
732  case 14:
733  if (Op1Val == 3 && Op2Val == 1)
734  Asm = "dc\tcivac";
735  else if (Op1Val == 0 && Op2Val == 2)
736  Asm = "dc\tcisw";
737  break;
738 
739  // AT aliases
740  case 8:
741  switch (Op1Val) {
742  default:
743  break;
744  case 0:
745  switch (Op2Val) {
746  default:
747  break;
748  case 0: Asm = "at\ts1e1r"; break;
749  case 1: Asm = "at\ts1e1w"; break;
750  case 2: Asm = "at\ts1e0r"; break;
751  case 3: Asm = "at\ts1e0w"; break;
752  }
753  break;
754  case 4:
755  switch (Op2Val) {
756  default:
757  break;
758  case 0: Asm = "at\ts1e2r"; break;
759  case 1: Asm = "at\ts1e2w"; break;
760  case 4: Asm = "at\ts12e1r"; break;
761  case 5: Asm = "at\ts12e1w"; break;
762  case 6: Asm = "at\ts12e0r"; break;
763  case 7: Asm = "at\ts12e0w"; break;
764  }
765  break;
766  case 6:
767  switch (Op2Val) {
768  default:
769  break;
770  case 0: Asm = "at\ts1e3r"; break;
771  case 1: Asm = "at\ts1e3w"; break;
772  }
773  break;
774  }
775  break;
776  }
777  } else if (CnVal == 8) {
778  // TLBI aliases
779  switch (CmVal) {
780  default:
781  break;
782  case 3:
783  switch (Op1Val) {
784  default:
785  break;
786  case 0:
787  switch (Op2Val) {
788  default:
789  break;
790  case 0: Asm = "tlbi\tvmalle1is"; break;
791  case 1: Asm = "tlbi\tvae1is"; break;
792  case 2: Asm = "tlbi\taside1is"; break;
793  case 3: Asm = "tlbi\tvaae1is"; break;
794  case 5: Asm = "tlbi\tvale1is"; break;
795  case 7: Asm = "tlbi\tvaale1is"; break;
796  }
797  break;
798  case 4:
799  switch (Op2Val) {
800  default:
801  break;
802  case 0: Asm = "tlbi\talle2is"; break;
803  case 1: Asm = "tlbi\tvae2is"; break;
804  case 4: Asm = "tlbi\talle1is"; break;
805  case 5: Asm = "tlbi\tvale2is"; break;
806  case 6: Asm = "tlbi\tvmalls12e1is"; break;
807  }
808  break;
809  case 6:
810  switch (Op2Val) {
811  default:
812  break;
813  case 0: Asm = "tlbi\talle3is"; break;
814  case 1: Asm = "tlbi\tvae3is"; break;
815  case 5: Asm = "tlbi\tvale3is"; break;
816  }
817  break;
818  }
819  break;
820  case 0:
821  switch (Op1Val) {
822  default:
823  break;
824  case 4:
825  switch (Op2Val) {
826  default:
827  break;
828  case 1: Asm = "tlbi\tipas2e1is"; break;
829  case 5: Asm = "tlbi\tipas2le1is"; break;
830  }
831  break;
832  }
833  break;
834  case 4:
835  switch (Op1Val) {
836  default:
837  break;
838  case 4:
839  switch (Op2Val) {
840  default:
841  break;
842  case 1: Asm = "tlbi\tipas2e1"; break;
843  case 5: Asm = "tlbi\tipas2le1"; break;
844  }
845  break;
846  }
847  break;
848  case 7:
849  switch (Op1Val) {
850  default:
851  break;
852  case 0:
853  switch (Op2Val) {
854  default:
855  break;
856  case 0: Asm = "tlbi\tvmalle1"; break;
857  case 1: Asm = "tlbi\tvae1"; break;
858  case 2: Asm = "tlbi\taside1"; break;
859  case 3: Asm = "tlbi\tvaae1"; break;
860  case 5: Asm = "tlbi\tvale1"; break;
861  case 7: Asm = "tlbi\tvaale1"; break;
862  }
863  break;
864  case 4:
865  switch (Op2Val) {
866  default:
867  break;
868  case 0: Asm = "tlbi\talle2"; break;
869  case 1: Asm = "tlbi\tvae2"; break;
870  case 4: Asm = "tlbi\talle1"; break;
871  case 5: Asm = "tlbi\tvale2"; break;
872  case 6: Asm = "tlbi\tvmalls12e1"; break;
873  }
874  break;
875  case 6:
876  switch (Op2Val) {
877  default:
878  break;
879  case 0: Asm = "tlbi\talle3"; break;
880  case 1: Asm = "tlbi\tvae3"; break;
881  case 5: Asm = "tlbi\tvale3"; break;
882  }
883  break;
884  }
885  break;
886  }
887  }
888 
889  if (Asm) {
890  unsigned Reg = MI->getOperand(4).getReg();
891 
892  O << '\t' << Asm;
893  if (StringRef(Asm).lower().find("all") == StringRef::npos)
894  O << ", " << getRegisterName(Reg);
895  }
896 
897  return Asm != nullptr;
898 }
899 
900 void AArch64InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
901  const MCSubtargetInfo &STI,
902  raw_ostream &O) {
903  const MCOperand &Op = MI->getOperand(OpNo);
904  if (Op.isReg()) {
905  unsigned Reg = Op.getReg();
906  O << getRegisterName(Reg);
907  } else if (Op.isImm()) {
908  O << '#' << Op.getImm();
909  } else {
910  assert(Op.isExpr() && "unknown operand kind in printOperand");
911  Op.getExpr()->print(O, &MAI);
912  }
913 }
914 
915 void AArch64InstPrinter::printHexImm(const MCInst *MI, unsigned OpNo,
916  const MCSubtargetInfo &STI,
917  raw_ostream &O) {
918  const MCOperand &Op = MI->getOperand(OpNo);
919  O << format("#%#llx", Op.getImm());
920 }
921 
923  unsigned Imm, raw_ostream &O) {
924  const MCOperand &Op = MI->getOperand(OpNo);
925  if (Op.isReg()) {
926  unsigned Reg = Op.getReg();
927  if (Reg == AArch64::XZR)
928  O << "#" << Imm;
929  else
930  O << getRegisterName(Reg);
931  } else
932  llvm_unreachable("unknown operand kind in printPostIncOperand64");
933 }
934 
935 void AArch64InstPrinter::printVRegOperand(const MCInst *MI, unsigned OpNo,
936  const MCSubtargetInfo &STI,
937  raw_ostream &O) {
938  const MCOperand &Op = MI->getOperand(OpNo);
939  assert(Op.isReg() && "Non-register vreg operand!");
940  unsigned Reg = Op.getReg();
941  O << getRegisterName(Reg, AArch64::vreg);
942 }
943 
945  const MCSubtargetInfo &STI,
946  raw_ostream &O) {
947  const MCOperand &Op = MI->getOperand(OpNo);
948  assert(Op.isImm() && "System instruction C[nm] operands must be immediates!");
949  O << "c" << Op.getImm();
950 }
951 
952 void AArch64InstPrinter::printAddSubImm(const MCInst *MI, unsigned OpNum,
953  const MCSubtargetInfo &STI,
954  raw_ostream &O) {
955  const MCOperand &MO = MI->getOperand(OpNum);
956  if (MO.isImm()) {
957  unsigned Val = (MO.getImm() & 0xfff);
958  assert(Val == MO.getImm() && "Add/sub immediate out of range!");
959  unsigned Shift =
960  AArch64_AM::getShiftValue(MI->getOperand(OpNum + 1).getImm());
961  O << '#' << Val;
962  if (Shift != 0)
963  printShifter(MI, OpNum + 1, STI, O);
964 
965  if (CommentStream)
966  *CommentStream << '=' << (Val << Shift) << '\n';
967  } else {
968  assert(MO.isExpr() && "Unexpected operand type!");
969  MO.getExpr()->print(O, &MAI);
970  printShifter(MI, OpNum + 1, STI, O);
971  }
972 }
973 
974 void AArch64InstPrinter::printLogicalImm32(const MCInst *MI, unsigned OpNum,
975  const MCSubtargetInfo &STI,
976  raw_ostream &O) {
977  uint64_t Val = MI->getOperand(OpNum).getImm();
978  O << "#0x";
980 }
981 
982 void AArch64InstPrinter::printLogicalImm64(const MCInst *MI, unsigned OpNum,
983  const MCSubtargetInfo &STI,
984  raw_ostream &O) {
985  uint64_t Val = MI->getOperand(OpNum).getImm();
986  O << "#0x";
988 }
989 
990 void AArch64InstPrinter::printShifter(const MCInst *MI, unsigned OpNum,
991  const MCSubtargetInfo &STI,
992  raw_ostream &O) {
993  unsigned Val = MI->getOperand(OpNum).getImm();
994  // LSL #0 should not be printed.
996  AArch64_AM::getShiftValue(Val) == 0)
997  return;
999  << " #" << AArch64_AM::getShiftValue(Val);
1000 }
1001 
1003  const MCSubtargetInfo &STI,
1004  raw_ostream &O) {
1005  O << getRegisterName(MI->getOperand(OpNum).getReg());
1006  printShifter(MI, OpNum + 1, STI, O);
1007 }
1008 
1010  const MCSubtargetInfo &STI,
1011  raw_ostream &O) {
1012  O << getRegisterName(MI->getOperand(OpNum).getReg());
1013  printArithExtend(MI, OpNum + 1, STI, O);
1014 }
1015 
1016 void AArch64InstPrinter::printArithExtend(const MCInst *MI, unsigned OpNum,
1017  const MCSubtargetInfo &STI,
1018  raw_ostream &O) {
1019  unsigned Val = MI->getOperand(OpNum).getImm();
1021  unsigned ShiftVal = AArch64_AM::getArithShiftValue(Val);
1022 
1023  // If the destination or first source register operand is [W]SP, print
1024  // UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
1025  // all.
1026  if (ExtType == AArch64_AM::UXTW || ExtType == AArch64_AM::UXTX) {
1027  unsigned Dest = MI->getOperand(0).getReg();
1028  unsigned Src1 = MI->getOperand(1).getReg();
1029  if ( ((Dest == AArch64::SP || Src1 == AArch64::SP) &&
1030  ExtType == AArch64_AM::UXTX) ||
1031  ((Dest == AArch64::WSP || Src1 == AArch64::WSP) &&
1032  ExtType == AArch64_AM::UXTW) ) {
1033  if (ShiftVal != 0)
1034  O << ", lsl #" << ShiftVal;
1035  return;
1036  }
1037  }
1038  O << ", " << AArch64_AM::getShiftExtendName(ExtType);
1039  if (ShiftVal != 0)
1040  O << " #" << ShiftVal;
1041 }
1042 
1043 void AArch64InstPrinter::printMemExtend(const MCInst *MI, unsigned OpNum,
1044  raw_ostream &O, char SrcRegKind,
1045  unsigned Width) {
1046  unsigned SignExtend = MI->getOperand(OpNum).getImm();
1047  unsigned DoShift = MI->getOperand(OpNum + 1).getImm();
1048 
1049  // sxtw, sxtx, uxtw or lsl (== uxtx)
1050  bool IsLSL = !SignExtend && SrcRegKind == 'x';
1051  if (IsLSL)
1052  O << "lsl";
1053  else
1054  O << (SignExtend ? 's' : 'u') << "xt" << SrcRegKind;
1055 
1056  if (DoShift || IsLSL)
1057  O << " #" << Log2_32(Width / 8);
1058 }
1059 
1060 void AArch64InstPrinter::printCondCode(const MCInst *MI, unsigned OpNum,
1061  const MCSubtargetInfo &STI,
1062  raw_ostream &O) {
1064  O << AArch64CC::getCondCodeName(CC);
1065 }
1066 
1068  const MCSubtargetInfo &STI,
1069  raw_ostream &O) {
1072 }
1073 
1074 void AArch64InstPrinter::printAMNoIndex(const MCInst *MI, unsigned OpNum,
1075  const MCSubtargetInfo &STI,
1076  raw_ostream &O) {
1077  O << '[' << getRegisterName(MI->getOperand(OpNum).getReg()) << ']';
1078 }
1079 
1080 template<int Scale>
1081 void AArch64InstPrinter::printImmScale(const MCInst *MI, unsigned OpNum,
1082  const MCSubtargetInfo &STI,
1083  raw_ostream &O) {
1084  O << '#' << Scale * MI->getOperand(OpNum).getImm();
1085 }
1086 
1088  unsigned Scale, raw_ostream &O) {
1089  const MCOperand MO = MI->getOperand(OpNum);
1090  if (MO.isImm()) {
1091  O << "#" << (MO.getImm() * Scale);
1092  } else {
1093  assert(MO.isExpr() && "Unexpected operand type!");
1094  MO.getExpr()->print(O, &MAI);
1095  }
1096 }
1097 
1098 void AArch64InstPrinter::printAMIndexedWB(const MCInst *MI, unsigned OpNum,
1099  unsigned Scale, raw_ostream &O) {
1100  const MCOperand MO1 = MI->getOperand(OpNum + 1);
1101  O << '[' << getRegisterName(MI->getOperand(OpNum).getReg());
1102  if (MO1.isImm()) {
1103  O << ", #" << (MO1.getImm() * Scale);
1104  } else {
1105  assert(MO1.isExpr() && "Unexpected operand type!");
1106  O << ", ";
1107  MO1.getExpr()->print(O, &MAI);
1108  }
1109  O << ']';
1110 }
1111 
1112 void AArch64InstPrinter::printPrefetchOp(const MCInst *MI, unsigned OpNum,
1113  const MCSubtargetInfo &STI,
1114  raw_ostream &O) {
1115  unsigned prfop = MI->getOperand(OpNum).getImm();
1116  bool Valid;
1117  StringRef Name =
1118  AArch64PRFM::PRFMMapper().toString(prfop, STI.getFeatureBits(), Valid);
1119  if (Valid)
1120  O << Name;
1121  else
1122  O << '#' << prfop;
1123 }
1124 
1126  const MCSubtargetInfo &STI,
1127  raw_ostream &O) {
1128  const MCOperand &MO = MI->getOperand(OpNum);
1129  float FPImm =
1130  MO.isFPImm() ? MO.getFPImm() : AArch64_AM::getFPImmFloat(MO.getImm());
1131 
1132  // 8 decimal places are enough to perfectly represent permitted floats.
1133  O << format("#%.8f", FPImm);
1134 }
1135 
1136 static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride = 1) {
1137  while (Stride--) {
1138  switch (Reg) {
1139  default:
1140  llvm_unreachable("Vector register expected!");
1141  case AArch64::Q0: Reg = AArch64::Q1; break;
1142  case AArch64::Q1: Reg = AArch64::Q2; break;
1143  case AArch64::Q2: Reg = AArch64::Q3; break;
1144  case AArch64::Q3: Reg = AArch64::Q4; break;
1145  case AArch64::Q4: Reg = AArch64::Q5; break;
1146  case AArch64::Q5: Reg = AArch64::Q6; break;
1147  case AArch64::Q6: Reg = AArch64::Q7; break;
1148  case AArch64::Q7: Reg = AArch64::Q8; break;
1149  case AArch64::Q8: Reg = AArch64::Q9; break;
1150  case AArch64::Q9: Reg = AArch64::Q10; break;
1151  case AArch64::Q10: Reg = AArch64::Q11; break;
1152  case AArch64::Q11: Reg = AArch64::Q12; break;
1153  case AArch64::Q12: Reg = AArch64::Q13; break;
1154  case AArch64::Q13: Reg = AArch64::Q14; break;
1155  case AArch64::Q14: Reg = AArch64::Q15; break;
1156  case AArch64::Q15: Reg = AArch64::Q16; break;
1157  case AArch64::Q16: Reg = AArch64::Q17; break;
1158  case AArch64::Q17: Reg = AArch64::Q18; break;
1159  case AArch64::Q18: Reg = AArch64::Q19; break;
1160  case AArch64::Q19: Reg = AArch64::Q20; break;
1161  case AArch64::Q20: Reg = AArch64::Q21; break;
1162  case AArch64::Q21: Reg = AArch64::Q22; break;
1163  case AArch64::Q22: Reg = AArch64::Q23; break;
1164  case AArch64::Q23: Reg = AArch64::Q24; break;
1165  case AArch64::Q24: Reg = AArch64::Q25; break;
1166  case AArch64::Q25: Reg = AArch64::Q26; break;
1167  case AArch64::Q26: Reg = AArch64::Q27; break;
1168  case AArch64::Q27: Reg = AArch64::Q28; break;
1169  case AArch64::Q28: Reg = AArch64::Q29; break;
1170  case AArch64::Q29: Reg = AArch64::Q30; break;
1171  case AArch64::Q30: Reg = AArch64::Q31; break;
1172  // Vector lists can wrap around.
1173  case AArch64::Q31:
1174  Reg = AArch64::Q0;
1175  break;
1176  }
1177  }
1178  return Reg;
1179 }
1180 
1181 template<unsigned size>
1183  unsigned OpNum,
1184  const MCSubtargetInfo &STI,
1185  raw_ostream &O) {
1186  static_assert(size == 64 || size == 32,
1187  "Template parameter must be either 32 or 64");
1188  unsigned Reg = MI->getOperand(OpNum).getReg();
1189 
1190  unsigned Sube = (size == 32) ? AArch64::sube32 : AArch64::sube64;
1191  unsigned Subo = (size == 32) ? AArch64::subo32 : AArch64::subo64;
1192 
1193  unsigned Even = MRI.getSubReg(Reg, Sube);
1194  unsigned Odd = MRI.getSubReg(Reg, Subo);
1195  O << getRegisterName(Even) << ", " << getRegisterName(Odd);
1196 }
1197 
1198 void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum,
1199  const MCSubtargetInfo &STI,
1200  raw_ostream &O,
1201  StringRef LayoutSuffix) {
1202  unsigned Reg = MI->getOperand(OpNum).getReg();
1203 
1204  O << "{ ";
1205 
1206  // Work out how many registers there are in the list (if there is an actual
1207  // list).
1208  unsigned NumRegs = 1;
1209  if (MRI.getRegClass(AArch64::DDRegClassID).contains(Reg) ||
1210  MRI.getRegClass(AArch64::QQRegClassID).contains(Reg))
1211  NumRegs = 2;
1212  else if (MRI.getRegClass(AArch64::DDDRegClassID).contains(Reg) ||
1213  MRI.getRegClass(AArch64::QQQRegClassID).contains(Reg))
1214  NumRegs = 3;
1215  else if (MRI.getRegClass(AArch64::DDDDRegClassID).contains(Reg) ||
1216  MRI.getRegClass(AArch64::QQQQRegClassID).contains(Reg))
1217  NumRegs = 4;
1218 
1219  // Now forget about the list and find out what the first register is.
1220  if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::dsub0))
1221  Reg = FirstReg;
1222  else if (unsigned FirstReg = MRI.getSubReg(Reg, AArch64::qsub0))
1223  Reg = FirstReg;
1224 
1225  // If it's a D-reg, we need to promote it to the equivalent Q-reg before
1226  // printing (otherwise getRegisterName fails).
1227  if (MRI.getRegClass(AArch64::FPR64RegClassID).contains(Reg)) {
1228  const MCRegisterClass &FPR128RC =
1229  MRI.getRegClass(AArch64::FPR128RegClassID);
1230  Reg = MRI.getMatchingSuperReg(Reg, AArch64::dsub, &FPR128RC);
1231  }
1232 
1233  for (unsigned i = 0; i < NumRegs; ++i, Reg = getNextVectorRegister(Reg)) {
1234  O << getRegisterName(Reg, AArch64::vreg) << LayoutSuffix;
1235  if (i + 1 != NumRegs)
1236  O << ", ";
1237  }
1238 
1239  O << " }";
1240 }
1241 
1242 void
1244  unsigned OpNum,
1245  const MCSubtargetInfo &STI,
1246  raw_ostream &O) {
1247  printVectorList(MI, OpNum, STI, O, "");
1248 }
1249 
1250 template <unsigned NumLanes, char LaneKind>
1252  const MCSubtargetInfo &STI,
1253  raw_ostream &O) {
1254  std::string Suffix(".");
1255  if (NumLanes)
1256  Suffix += itostr(NumLanes) + LaneKind;
1257  else
1258  Suffix += LaneKind;
1259 
1260  printVectorList(MI, OpNum, STI, O, Suffix);
1261 }
1262 
1263 void AArch64InstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
1264  const MCSubtargetInfo &STI,
1265  raw_ostream &O) {
1266  O << "[" << MI->getOperand(OpNum).getImm() << "]";
1267 }
1268 
1270  const MCSubtargetInfo &STI,
1271  raw_ostream &O) {
1272  const MCOperand &Op = MI->getOperand(OpNum);
1273 
1274  // If the label has already been resolved to an immediate offset (say, when
1275  // we're running the disassembler), just print the immediate.
1276  if (Op.isImm()) {
1277  O << "#" << (Op.getImm() * 4);
1278  return;
1279  }
1280 
1281  // If the branch target is simply an address then print it in hex.
1282  const MCConstantExpr *BranchTarget =
1283  dyn_cast<MCConstantExpr>(MI->getOperand(OpNum).getExpr());
1284  int64_t Address;
1285  if (BranchTarget && BranchTarget->evaluateAsAbsolute(Address)) {
1286  O << "0x";
1287  O.write_hex(Address);
1288  } else {
1289  // Otherwise, just print the expression.
1290  MI->getOperand(OpNum).getExpr()->print(O, &MAI);
1291  }
1292 }
1293 
1294 void AArch64InstPrinter::printAdrpLabel(const MCInst *MI, unsigned OpNum,
1295  const MCSubtargetInfo &STI,
1296  raw_ostream &O) {
1297  const MCOperand &Op = MI->getOperand(OpNum);
1298 
1299  // If the label has already been resolved to an immediate offset (say, when
1300  // we're running the disassembler), just print the immediate.
1301  if (Op.isImm()) {
1302  O << "#" << (Op.getImm() * (1 << 12));
1303  return;
1304  }
1305 
1306  // Otherwise, just print the expression.
1307  MI->getOperand(OpNum).getExpr()->print(O, &MAI);
1308 }
1309 
1311  const MCSubtargetInfo &STI,
1312  raw_ostream &O) {
1313  unsigned Val = MI->getOperand(OpNo).getImm();
1314  unsigned Opcode = MI->getOpcode();
1315 
1316  bool Valid;
1317  StringRef Name;
1318  if (Opcode == AArch64::ISB)
1319  Name = AArch64ISB::ISBMapper().toString(Val, STI.getFeatureBits(),
1320  Valid);
1321  else
1323  Valid);
1324  if (Valid)
1325  O << Name;
1326  else
1327  O << "#" << Val;
1328 }
1329 
1331  const MCSubtargetInfo &STI,
1332  raw_ostream &O) {
1333  unsigned Val = MI->getOperand(OpNo).getImm();
1334 
1335  auto Mapper = AArch64SysReg::MRSMapper();
1336  std::string Name = Mapper.toString(Val, STI.getFeatureBits());
1337 
1338  O << StringRef(Name).upper();
1339 }
1340 
1342  const MCSubtargetInfo &STI,
1343  raw_ostream &O) {
1344  unsigned Val = MI->getOperand(OpNo).getImm();
1345 
1346  auto Mapper = AArch64SysReg::MSRMapper();
1347  std::string Name = Mapper.toString(Val, STI.getFeatureBits());
1348 
1349  O << StringRef(Name).upper();
1350 }
1351 
1353  const MCSubtargetInfo &STI,
1354  raw_ostream &O) {
1355  unsigned Val = MI->getOperand(OpNo).getImm();
1356 
1357  bool Valid;
1358  StringRef Name =
1360  if (Valid)
1361  O << Name.upper();
1362  else
1363  O << "#" << Val;
1364 }
1365 
1367  const MCSubtargetInfo &STI,
1368  raw_ostream &O) {
1369  unsigned RawVal = MI->getOperand(OpNo).getImm();
1370  uint64_t Val = AArch64_AM::decodeAdvSIMDModImmType10(RawVal);
1371  O << format("#%#016llx", Val);
1372 }
void printAMIndexedWB(const MCInst *MI, unsigned OpNum, unsigned Scale, raw_ostream &O)
static float getFPImmFloat(unsigned Imm)
void printRegName(raw_ostream &OS, unsigned RegNo) const override
Print the assembler register name.
void printShifter(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
static unsigned getArithShiftValue(unsigned Imm)
getArithShiftValue - get the arithmetic shift value.
void printVectorIndex(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
static const char * getRegisterName(unsigned RegNo, unsigned AltIdx=AArch64::NoRegAltName)
void printSysCROperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
double getFPImm() const
Definition: MCInst.h:83
bool isReg() const
Definition: MCInst.h:56
void printSystemPStateField(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
static CondCode getInvertedCondCode(CondCode Code)
void printLogicalImm32(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printPrefetchOp(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
bool printSysAlias(const MCInst *MI, raw_ostream &O)
void printFPImmOperand(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printGPRSeqPairsClassOperand(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printMemExtend(const MCInst *MI, unsigned OpNum, raw_ostream &O, char SrcRegKind, unsigned Width)
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) override
Print the specified MCInst to the specified raw_ostream.
void printUImm12Offset(const MCInst *MI, unsigned OpNum, unsigned Scale, raw_ostream &O)
void printLogicalImm64(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printImplicitlyTypedVectorList(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
Print a list of vector registers where the type suffix is implicit (i.e.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
Reg
All possible values of the reg field in the ModR/M byte.
static LdStNInstrDesc LdStNInstInfo[]
void printVRegOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
static const char * getCondCodeName(CondCode Code)
static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride=1)
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:63
void printInverseCondCode(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
StringRef toString(uint32_t Value, const FeatureBitset &FeatureBits, bool &Valid) const
AArch64InstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
void printAlignedLabel(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
MCRegisterClass - Base class of TargetRegisterClass.
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) override
Print the specified MCInst to the specified raw_ostream.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:150
static const char * getRegisterName(unsigned RegNo, unsigned AltIdx=AArch64::NoRegAltName)
static unsigned getWRegFromXReg(unsigned Reg)
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:111
bool isImm() const
Definition: MCInst.h:57
LLVM_CONSTEXPR size_t array_lengthof(T(&)[N])
Find the length of an array.
Definition: STLExtras.h:247
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:58
void printHexImm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
const MCExpr * getExpr() const
Definition: MCInst.h:93
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
Definition: MCExpr.cpp:33
static const char * getShiftExtendName(AArch64_AM::ShiftExtendType ST)
getShiftName - Get the string encoding for the shift type.
const MCRegisterClass & getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
static AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm)
bool isFPImm() const
Definition: MCInst.h:58
unsigned getSubReg(unsigned Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo...
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
bool isExpr() const
Definition: MCInst.h:59
void printSIMDType10Operand(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printArithExtend(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printMSRSystemRegister(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
static std::string itostr(int64_t X)
Definition: StringExtras.h:109
void printAdrpLabel(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC) const
Return a super-register of the specified register Reg so its sub-register of index SubIdx is Reg...
void printPostIncOperand(const MCInst *MI, unsigned OpNo, unsigned Imm, raw_ostream &O)
void printBarrierOption(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printAMNoIndex(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
bool contains(unsigned Reg) const
contains - Return true if the specified register is included in this register class.
void printMRSSystemRegister(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
std::string upper() const
Convert the given ASCII string to uppercase.
Definition: StringRef.cpp:125
const FeatureBitset & getFeatureBits() const
getFeatureBits - Return the feature bits.
raw_ostream * CommentStream
A stream that comments can be emitted to if desired.
Definition: MCInstPrinter.h:43
void printTypedVectorList(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printShiftedRegister(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
unsigned Log2_32(uint32_t Value)
Log2_32 - This function returns the floor log base 2 of the specified value, -1 if the value is zero...
Definition: MathExtras.h:468
unsigned getOpcode() const
Definition: MCInst.h:159
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:285
int64_t getImm() const
Definition: MCInst.h:74
virtual void printInstruction(const MCInst *MI, const MCSubtargetInfo &STI, raw_ostream &O)
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:44
void printExtendedRegister(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printVectorList(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O, StringRef LayoutSuffix)
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:38
void printAddSubImm(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static const size_t npos
Definition: StringRef.h:44
virtual bool printAliasInstr(const MCInst *MI, const MCSubtargetInfo &STI, raw_ostream &O)
void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
static uint64_t decodeAdvSIMDModImmType10(uint8_t Imm)
MCSubtargetInfo - Generic base class for all target subtargets.
AArch64AppleInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
void size_t size
bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, const SectionAddrMap &Addrs) const
Try to evaluate the expression to an absolute value.
Definition: MCExpr.cpp:418
void printImmScale(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:38
static bool isTblTbxInstruction(unsigned Opcode, StringRef &Layout, bool &IsTbx)
static LdStNInstrDesc * getLdStNInstrDesc(unsigned Opcode)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:33
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:164
const MCRegisterInfo & MRI
Definition: MCInstPrinter.h:46
void printCondCode(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O)