1 //==-- AArch64InstPrinter.cpp - Convert AArch64 MCInst to assembly syntax --==//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This class prints an AArch64 MCInst to a .s file.
11 //===----------------------------------------------------------------------===//
13 #include "AArch64InstPrinter.h"
14 #include "MCTargetDesc/AArch64AddressingModes.h"
15 #include "Utils/AArch64BaseInfo.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/MC/MCAsmInfo.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/Format.h"
27 #include "llvm/Support/MathExtras.h"
28 #include "llvm/Support/raw_ostream.h"
35 #define DEBUG_TYPE "asm-printer"
37 #define GET_INSTRUCTION_NAME
38 #define PRINT_ALIAS_INSTR
39 #include "AArch64GenAsmWriter.inc"
40 #define GET_INSTRUCTION_NAME
41 #define PRINT_ALIAS_INSTR
42 #include "AArch64GenAsmWriter1.inc"
44 AArch64InstPrinter::AArch64InstPrinter(const MCAsmInfo
&MAI
,
45 const MCInstrInfo
&MII
,
46 const MCRegisterInfo
&MRI
)
47 : MCInstPrinter(MAI
, MII
, MRI
) {}
49 AArch64AppleInstPrinter::AArch64AppleInstPrinter(const MCAsmInfo
&MAI
,
50 const MCInstrInfo
&MII
,
51 const MCRegisterInfo
&MRI
)
52 : AArch64InstPrinter(MAI
, MII
, MRI
) {}
54 void AArch64InstPrinter::printRegName(raw_ostream
&OS
, unsigned RegNo
) const {
55 // This is for .cfi directives.
56 OS
<< getRegisterName(RegNo
);
59 void AArch64InstPrinter::printInst(const MCInst
*MI
, raw_ostream
&O
,
61 const MCSubtargetInfo
&STI
) {
62 // Check for special encodings and print the canonical alias instead.
64 unsigned Opcode
= MI
->getOpcode();
66 if (Opcode
== AArch64::SYSxt
)
67 if (printSysAlias(MI
, STI
, O
)) {
68 printAnnotation(O
, Annot
);
72 if (atomicBarrierDroppedOnZero(Opcode
) &&
73 (MI
->getOperand(0).getReg() == AArch64::XZR
||
74 MI
->getOperand(0).getReg() == AArch64::WZR
))
75 printAnnotation(O
, "acquire semantics dropped since destination is zero");
77 // SBFM/UBFM should print to a nicer aliased form if possible.
78 if (Opcode
== AArch64::SBFMXri
|| Opcode
== AArch64::SBFMWri
||
79 Opcode
== AArch64::UBFMXri
|| Opcode
== AArch64::UBFMWri
) {
80 const MCOperand
&Op0
= MI
->getOperand(0);
81 const MCOperand
&Op1
= MI
->getOperand(1);
82 const MCOperand
&Op2
= MI
->getOperand(2);
83 const MCOperand
&Op3
= MI
->getOperand(3);
85 bool IsSigned
= (Opcode
== AArch64::SBFMXri
|| Opcode
== AArch64::SBFMWri
);
86 bool Is64Bit
= (Opcode
== AArch64::SBFMXri
|| Opcode
== AArch64::UBFMXri
);
87 if (Op2
.isImm() && Op2
.getImm() == 0 && Op3
.isImm()) {
88 const char *AsmMnemonic
= nullptr;
90 switch (Op3
.getImm()) {
101 AsmMnemonic
= "sxth";
103 AsmMnemonic
= "uxth";
106 // *xtw is only valid for signed 64-bit operations.
107 if (Is64Bit
&& IsSigned
)
108 AsmMnemonic
= "sxtw";
113 O
<< '\t' << AsmMnemonic
<< '\t' << getRegisterName(Op0
.getReg())
114 << ", " << getRegisterName(getWRegFromXReg(Op1
.getReg()));
115 printAnnotation(O
, Annot
);
120 // All immediate shifts are aliases, implemented using the Bitfield
121 // instruction. In all cases the immediate shift amount shift must be in
122 // the range 0 to (reg.size -1).
123 if (Op2
.isImm() && Op3
.isImm()) {
124 const char *AsmMnemonic
= nullptr;
126 int64_t immr
= Op2
.getImm();
127 int64_t imms
= Op3
.getImm();
128 if (Opcode
== AArch64::UBFMWri
&& imms
!= 0x1F && ((imms
+ 1) == immr
)) {
131 } else if (Opcode
== AArch64::UBFMXri
&& imms
!= 0x3f &&
132 ((imms
+ 1 == immr
))) {
135 } else if (Opcode
== AArch64::UBFMWri
&& imms
== 0x1f) {
138 } else if (Opcode
== AArch64::UBFMXri
&& imms
== 0x3f) {
141 } else if (Opcode
== AArch64::SBFMWri
&& imms
== 0x1f) {
144 } else if (Opcode
== AArch64::SBFMXri
&& imms
== 0x3f) {
149 O
<< '\t' << AsmMnemonic
<< '\t' << getRegisterName(Op0
.getReg())
150 << ", " << getRegisterName(Op1
.getReg()) << ", #" << shift
;
151 printAnnotation(O
, Annot
);
156 // SBFIZ/UBFIZ aliases
157 if (Op2
.getImm() > Op3
.getImm()) {
158 O
<< '\t' << (IsSigned
? "sbfiz" : "ubfiz") << '\t'
159 << getRegisterName(Op0
.getReg()) << ", " << getRegisterName(Op1
.getReg())
160 << ", #" << (Is64Bit
? 64 : 32) - Op2
.getImm() << ", #" << Op3
.getImm() + 1;
161 printAnnotation(O
, Annot
);
165 // Otherwise SBFX/UBFX is the preferred form
166 O
<< '\t' << (IsSigned
? "sbfx" : "ubfx") << '\t'
167 << getRegisterName(Op0
.getReg()) << ", " << getRegisterName(Op1
.getReg())
168 << ", #" << Op2
.getImm() << ", #" << Op3
.getImm() - Op2
.getImm() + 1;
169 printAnnotation(O
, Annot
);
173 if (Opcode
== AArch64::BFMXri
|| Opcode
== AArch64::BFMWri
) {
174 const MCOperand
&Op0
= MI
->getOperand(0); // Op1 == Op0
175 const MCOperand
&Op2
= MI
->getOperand(2);
176 int ImmR
= MI
->getOperand(3).getImm();
177 int ImmS
= MI
->getOperand(4).getImm();
179 if ((Op2
.getReg() == AArch64::WZR
|| Op2
.getReg() == AArch64::XZR
) &&
180 (ImmR
== 0 || ImmS
< ImmR
)) {
181 // BFC takes precedence over its entire range, sligtly differently to BFI.
182 int BitWidth
= Opcode
== AArch64::BFMXri
? 64 : 32;
183 int LSB
= (BitWidth
- ImmR
) % BitWidth
;
184 int Width
= ImmS
+ 1;
186 O
<< "\tbfc\t" << getRegisterName(Op0
.getReg())
187 << ", #" << LSB
<< ", #" << Width
;
188 printAnnotation(O
, Annot
);
190 } else if (ImmS
< ImmR
) {
192 int BitWidth
= Opcode
== AArch64::BFMXri
? 64 : 32;
193 int LSB
= (BitWidth
- ImmR
) % BitWidth
;
194 int Width
= ImmS
+ 1;
196 O
<< "\tbfi\t" << getRegisterName(Op0
.getReg()) << ", "
197 << getRegisterName(Op2
.getReg()) << ", #" << LSB
<< ", #" << Width
;
198 printAnnotation(O
, Annot
);
203 int Width
= ImmS
- ImmR
+ 1;
204 // Otherwise BFXIL the preferred form
206 << getRegisterName(Op0
.getReg()) << ", " << getRegisterName(Op2
.getReg())
207 << ", #" << LSB
<< ", #" << Width
;
208 printAnnotation(O
, Annot
);
212 // Symbolic operands for MOVZ, MOVN and MOVK already imply a shift
213 // (e.g. :gottprel_g1: is always going to be "lsl #16") so it should not be
215 if ((Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
||
216 Opcode
== AArch64::MOVNXi
|| Opcode
== AArch64::MOVNWi
) &&
217 MI
->getOperand(1).isExpr()) {
218 if (Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
)
223 O
<< getRegisterName(MI
->getOperand(0).getReg()) << ", #";
224 MI
->getOperand(1).getExpr()->print(O
, &MAI
);
228 if ((Opcode
== AArch64::MOVKXi
|| Opcode
== AArch64::MOVKWi
) &&
229 MI
->getOperand(2).isExpr()) {
230 O
<< "\tmovk\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #";
231 MI
->getOperand(2).getExpr()->print(O
, &MAI
);
235 // MOVZ, MOVN and "ORR wzr, #imm" instructions are aliases for MOV, but their
236 // domains overlap so they need to be prioritized. The chain is "MOVZ lsl #0 >
237 // MOVZ lsl #N > MOVN lsl #0 > MOVN lsl #N > ORR". The highest instruction
238 // that can represent the move is the MOV alias, and the rest get printed
240 if ((Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
) &&
241 MI
->getOperand(1).isImm() && MI
->getOperand(2).isImm()) {
242 int RegWidth
= Opcode
== AArch64::MOVZXi
? 64 : 32;
243 int Shift
= MI
->getOperand(2).getImm();
244 uint64_t Value
= (uint64_t)MI
->getOperand(1).getImm() << Shift
;
246 if (AArch64_AM::isMOVZMovAlias(Value
, Shift
,
247 Opcode
== AArch64::MOVZXi
? 64 : 32)) {
248 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
249 << formatImm(SignExtend64(Value
, RegWidth
));
254 if ((Opcode
== AArch64::MOVNXi
|| Opcode
== AArch64::MOVNWi
) &&
255 MI
->getOperand(1).isImm() && MI
->getOperand(2).isImm()) {
256 int RegWidth
= Opcode
== AArch64::MOVNXi
? 64 : 32;
257 int Shift
= MI
->getOperand(2).getImm();
258 uint64_t Value
= ~((uint64_t)MI
->getOperand(1).getImm() << Shift
);
260 Value
= Value
& 0xffffffff;
262 if (AArch64_AM::isMOVNMovAlias(Value
, Shift
, RegWidth
)) {
263 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
264 << formatImm(SignExtend64(Value
, RegWidth
));
269 if ((Opcode
== AArch64::ORRXri
|| Opcode
== AArch64::ORRWri
) &&
270 (MI
->getOperand(1).getReg() == AArch64::XZR
||
271 MI
->getOperand(1).getReg() == AArch64::WZR
) &&
272 MI
->getOperand(2).isImm()) {
273 int RegWidth
= Opcode
== AArch64::ORRXri
? 64 : 32;
274 uint64_t Value
= AArch64_AM::decodeLogicalImmediate(
275 MI
->getOperand(2).getImm(), RegWidth
);
276 if (!AArch64_AM::isAnyMOVWMovAlias(Value
, RegWidth
)) {
277 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
278 << formatImm(SignExtend64(Value
, RegWidth
));
283 if (Opcode
== AArch64::CompilerBarrier
) {
284 O
<< '\t' << MAI
.getCommentString() << " COMPILER BARRIER";
285 printAnnotation(O
, Annot
);
289 // Instruction TSB is specified as a one operand instruction, but 'csync' is
290 // not encoded, so for printing it is treated as a special case here:
291 if (Opcode
== AArch64::TSB
) {
296 if (!printAliasInstr(MI
, STI
, O
))
297 printInstruction(MI
, STI
, O
);
299 printAnnotation(O
, Annot
);
302 static bool isTblTbxInstruction(unsigned Opcode
, StringRef
&Layout
,
305 case AArch64::TBXv8i8One
:
306 case AArch64::TBXv8i8Two
:
307 case AArch64::TBXv8i8Three
:
308 case AArch64::TBXv8i8Four
:
312 case AArch64::TBLv8i8One
:
313 case AArch64::TBLv8i8Two
:
314 case AArch64::TBLv8i8Three
:
315 case AArch64::TBLv8i8Four
:
319 case AArch64::TBXv16i8One
:
320 case AArch64::TBXv16i8Two
:
321 case AArch64::TBXv16i8Three
:
322 case AArch64::TBXv16i8Four
:
326 case AArch64::TBLv16i8One
:
327 case AArch64::TBLv16i8Two
:
328 case AArch64::TBLv16i8Three
:
329 case AArch64::TBLv16i8Four
:
338 struct LdStNInstrDesc
{
340 const char *Mnemonic
;
347 static const LdStNInstrDesc LdStNInstInfo
[] = {
348 { AArch64::LD1i8
, "ld1", ".b", 1, true, 0 },
349 { AArch64::LD1i16
, "ld1", ".h", 1, true, 0 },
350 { AArch64::LD1i32
, "ld1", ".s", 1, true, 0 },
351 { AArch64::LD1i64
, "ld1", ".d", 1, true, 0 },
352 { AArch64::LD1i8_POST
, "ld1", ".b", 2, true, 1 },
353 { AArch64::LD1i16_POST
, "ld1", ".h", 2, true, 2 },
354 { AArch64::LD1i32_POST
, "ld1", ".s", 2, true, 4 },
355 { AArch64::LD1i64_POST
, "ld1", ".d", 2, true, 8 },
356 { AArch64::LD1Rv16b
, "ld1r", ".16b", 0, false, 0 },
357 { AArch64::LD1Rv8h
, "ld1r", ".8h", 0, false, 0 },
358 { AArch64::LD1Rv4s
, "ld1r", ".4s", 0, false, 0 },
359 { AArch64::LD1Rv2d
, "ld1r", ".2d", 0, false, 0 },
360 { AArch64::LD1Rv8b
, "ld1r", ".8b", 0, false, 0 },
361 { AArch64::LD1Rv4h
, "ld1r", ".4h", 0, false, 0 },
362 { AArch64::LD1Rv2s
, "ld1r", ".2s", 0, false, 0 },
363 { AArch64::LD1Rv1d
, "ld1r", ".1d", 0, false, 0 },
364 { AArch64::LD1Rv16b_POST
, "ld1r", ".16b", 1, false, 1 },
365 { AArch64::LD1Rv8h_POST
, "ld1r", ".8h", 1, false, 2 },
366 { AArch64::LD1Rv4s_POST
, "ld1r", ".4s", 1, false, 4 },
367 { AArch64::LD1Rv2d_POST
, "ld1r", ".2d", 1, false, 8 },
368 { AArch64::LD1Rv8b_POST
, "ld1r", ".8b", 1, false, 1 },
369 { AArch64::LD1Rv4h_POST
, "ld1r", ".4h", 1, false, 2 },
370 { AArch64::LD1Rv2s_POST
, "ld1r", ".2s", 1, false, 4 },
371 { AArch64::LD1Rv1d_POST
, "ld1r", ".1d", 1, false, 8 },
372 { AArch64::LD1Onev16b
, "ld1", ".16b", 0, false, 0 },
373 { AArch64::LD1Onev8h
, "ld1", ".8h", 0, false, 0 },
374 { AArch64::LD1Onev4s
, "ld1", ".4s", 0, false, 0 },
375 { AArch64::LD1Onev2d
, "ld1", ".2d", 0, false, 0 },
376 { AArch64::LD1Onev8b
, "ld1", ".8b", 0, false, 0 },
377 { AArch64::LD1Onev4h
, "ld1", ".4h", 0, false, 0 },
378 { AArch64::LD1Onev2s
, "ld1", ".2s", 0, false, 0 },
379 { AArch64::LD1Onev1d
, "ld1", ".1d", 0, false, 0 },
380 { AArch64::LD1Onev16b_POST
, "ld1", ".16b", 1, false, 16 },
381 { AArch64::LD1Onev8h_POST
, "ld1", ".8h", 1, false, 16 },
382 { AArch64::LD1Onev4s_POST
, "ld1", ".4s", 1, false, 16 },
383 { AArch64::LD1Onev2d_POST
, "ld1", ".2d", 1, false, 16 },
384 { AArch64::LD1Onev8b_POST
, "ld1", ".8b", 1, false, 8 },
385 { AArch64::LD1Onev4h_POST
, "ld1", ".4h", 1, false, 8 },
386 { AArch64::LD1Onev2s_POST
, "ld1", ".2s", 1, false, 8 },
387 { AArch64::LD1Onev1d_POST
, "ld1", ".1d", 1, false, 8 },
388 { AArch64::LD1Twov16b
, "ld1", ".16b", 0, false, 0 },
389 { AArch64::LD1Twov8h
, "ld1", ".8h", 0, false, 0 },
390 { AArch64::LD1Twov4s
, "ld1", ".4s", 0, false, 0 },
391 { AArch64::LD1Twov2d
, "ld1", ".2d", 0, false, 0 },
392 { AArch64::LD1Twov8b
, "ld1", ".8b", 0, false, 0 },
393 { AArch64::LD1Twov4h
, "ld1", ".4h", 0, false, 0 },
394 { AArch64::LD1Twov2s
, "ld1", ".2s", 0, false, 0 },
395 { AArch64::LD1Twov1d
, "ld1", ".1d", 0, false, 0 },
396 { AArch64::LD1Twov16b_POST
, "ld1", ".16b", 1, false, 32 },
397 { AArch64::LD1Twov8h_POST
, "ld1", ".8h", 1, false, 32 },
398 { AArch64::LD1Twov4s_POST
, "ld1", ".4s", 1, false, 32 },
399 { AArch64::LD1Twov2d_POST
, "ld1", ".2d", 1, false, 32 },
400 { AArch64::LD1Twov8b_POST
, "ld1", ".8b", 1, false, 16 },
401 { AArch64::LD1Twov4h_POST
, "ld1", ".4h", 1, false, 16 },
402 { AArch64::LD1Twov2s_POST
, "ld1", ".2s", 1, false, 16 },
403 { AArch64::LD1Twov1d_POST
, "ld1", ".1d", 1, false, 16 },
404 { AArch64::LD1Threev16b
, "ld1", ".16b", 0, false, 0 },
405 { AArch64::LD1Threev8h
, "ld1", ".8h", 0, false, 0 },
406 { AArch64::LD1Threev4s
, "ld1", ".4s", 0, false, 0 },
407 { AArch64::LD1Threev2d
, "ld1", ".2d", 0, false, 0 },
408 { AArch64::LD1Threev8b
, "ld1", ".8b", 0, false, 0 },
409 { AArch64::LD1Threev4h
, "ld1", ".4h", 0, false, 0 },
410 { AArch64::LD1Threev2s
, "ld1", ".2s", 0, false, 0 },
411 { AArch64::LD1Threev1d
, "ld1", ".1d", 0, false, 0 },
412 { AArch64::LD1Threev16b_POST
, "ld1", ".16b", 1, false, 48 },
413 { AArch64::LD1Threev8h_POST
, "ld1", ".8h", 1, false, 48 },
414 { AArch64::LD1Threev4s_POST
, "ld1", ".4s", 1, false, 48 },
415 { AArch64::LD1Threev2d_POST
, "ld1", ".2d", 1, false, 48 },
416 { AArch64::LD1Threev8b_POST
, "ld1", ".8b", 1, false, 24 },
417 { AArch64::LD1Threev4h_POST
, "ld1", ".4h", 1, false, 24 },
418 { AArch64::LD1Threev2s_POST
, "ld1", ".2s", 1, false, 24 },
419 { AArch64::LD1Threev1d_POST
, "ld1", ".1d", 1, false, 24 },
420 { AArch64::LD1Fourv16b
, "ld1", ".16b", 0, false, 0 },
421 { AArch64::LD1Fourv8h
, "ld1", ".8h", 0, false, 0 },
422 { AArch64::LD1Fourv4s
, "ld1", ".4s", 0, false, 0 },
423 { AArch64::LD1Fourv2d
, "ld1", ".2d", 0, false, 0 },
424 { AArch64::LD1Fourv8b
, "ld1", ".8b", 0, false, 0 },
425 { AArch64::LD1Fourv4h
, "ld1", ".4h", 0, false, 0 },
426 { AArch64::LD1Fourv2s
, "ld1", ".2s", 0, false, 0 },
427 { AArch64::LD1Fourv1d
, "ld1", ".1d", 0, false, 0 },
428 { AArch64::LD1Fourv16b_POST
, "ld1", ".16b", 1, false, 64 },
429 { AArch64::LD1Fourv8h_POST
, "ld1", ".8h", 1, false, 64 },
430 { AArch64::LD1Fourv4s_POST
, "ld1", ".4s", 1, false, 64 },
431 { AArch64::LD1Fourv2d_POST
, "ld1", ".2d", 1, false, 64 },
432 { AArch64::LD1Fourv8b_POST
, "ld1", ".8b", 1, false, 32 },
433 { AArch64::LD1Fourv4h_POST
, "ld1", ".4h", 1, false, 32 },
434 { AArch64::LD1Fourv2s_POST
, "ld1", ".2s", 1, false, 32 },
435 { AArch64::LD1Fourv1d_POST
, "ld1", ".1d", 1, false, 32 },
436 { AArch64::LD2i8
, "ld2", ".b", 1, true, 0 },
437 { AArch64::LD2i16
, "ld2", ".h", 1, true, 0 },
438 { AArch64::LD2i32
, "ld2", ".s", 1, true, 0 },
439 { AArch64::LD2i64
, "ld2", ".d", 1, true, 0 },
440 { AArch64::LD2i8_POST
, "ld2", ".b", 2, true, 2 },
441 { AArch64::LD2i16_POST
, "ld2", ".h", 2, true, 4 },
442 { AArch64::LD2i32_POST
, "ld2", ".s", 2, true, 8 },
443 { AArch64::LD2i64_POST
, "ld2", ".d", 2, true, 16 },
444 { AArch64::LD2Rv16b
, "ld2r", ".16b", 0, false, 0 },
445 { AArch64::LD2Rv8h
, "ld2r", ".8h", 0, false, 0 },
446 { AArch64::LD2Rv4s
, "ld2r", ".4s", 0, false, 0 },
447 { AArch64::LD2Rv2d
, "ld2r", ".2d", 0, false, 0 },
448 { AArch64::LD2Rv8b
, "ld2r", ".8b", 0, false, 0 },
449 { AArch64::LD2Rv4h
, "ld2r", ".4h", 0, false, 0 },
450 { AArch64::LD2Rv2s
, "ld2r", ".2s", 0, false, 0 },
451 { AArch64::LD2Rv1d
, "ld2r", ".1d", 0, false, 0 },
452 { AArch64::LD2Rv16b_POST
, "ld2r", ".16b", 1, false, 2 },
453 { AArch64::LD2Rv8h_POST
, "ld2r", ".8h", 1, false, 4 },
454 { AArch64::LD2Rv4s_POST
, "ld2r", ".4s", 1, false, 8 },
455 { AArch64::LD2Rv2d_POST
, "ld2r", ".2d", 1, false, 16 },
456 { AArch64::LD2Rv8b_POST
, "ld2r", ".8b", 1, false, 2 },
457 { AArch64::LD2Rv4h_POST
, "ld2r", ".4h", 1, false, 4 },
458 { AArch64::LD2Rv2s_POST
, "ld2r", ".2s", 1, false, 8 },
459 { AArch64::LD2Rv1d_POST
, "ld2r", ".1d", 1, false, 16 },
460 { AArch64::LD2Twov16b
, "ld2", ".16b", 0, false, 0 },
461 { AArch64::LD2Twov8h
, "ld2", ".8h", 0, false, 0 },
462 { AArch64::LD2Twov4s
, "ld2", ".4s", 0, false, 0 },
463 { AArch64::LD2Twov2d
, "ld2", ".2d", 0, false, 0 },
464 { AArch64::LD2Twov8b
, "ld2", ".8b", 0, false, 0 },
465 { AArch64::LD2Twov4h
, "ld2", ".4h", 0, false, 0 },
466 { AArch64::LD2Twov2s
, "ld2", ".2s", 0, false, 0 },
467 { AArch64::LD2Twov16b_POST
, "ld2", ".16b", 1, false, 32 },
468 { AArch64::LD2Twov8h_POST
, "ld2", ".8h", 1, false, 32 },
469 { AArch64::LD2Twov4s_POST
, "ld2", ".4s", 1, false, 32 },
470 { AArch64::LD2Twov2d_POST
, "ld2", ".2d", 1, false, 32 },
471 { AArch64::LD2Twov8b_POST
, "ld2", ".8b", 1, false, 16 },
472 { AArch64::LD2Twov4h_POST
, "ld2", ".4h", 1, false, 16 },
473 { AArch64::LD2Twov2s_POST
, "ld2", ".2s", 1, false, 16 },
474 { AArch64::LD3i8
, "ld3", ".b", 1, true, 0 },
475 { AArch64::LD3i16
, "ld3", ".h", 1, true, 0 },
476 { AArch64::LD3i32
, "ld3", ".s", 1, true, 0 },
477 { AArch64::LD3i64
, "ld3", ".d", 1, true, 0 },
478 { AArch64::LD3i8_POST
, "ld3", ".b", 2, true, 3 },
479 { AArch64::LD3i16_POST
, "ld3", ".h", 2, true, 6 },
480 { AArch64::LD3i32_POST
, "ld3", ".s", 2, true, 12 },
481 { AArch64::LD3i64_POST
, "ld3", ".d", 2, true, 24 },
482 { AArch64::LD3Rv16b
, "ld3r", ".16b", 0, false, 0 },
483 { AArch64::LD3Rv8h
, "ld3r", ".8h", 0, false, 0 },
484 { AArch64::LD3Rv4s
, "ld3r", ".4s", 0, false, 0 },
485 { AArch64::LD3Rv2d
, "ld3r", ".2d", 0, false, 0 },
486 { AArch64::LD3Rv8b
, "ld3r", ".8b", 0, false, 0 },
487 { AArch64::LD3Rv4h
, "ld3r", ".4h", 0, false, 0 },
488 { AArch64::LD3Rv2s
, "ld3r", ".2s", 0, false, 0 },
489 { AArch64::LD3Rv1d
, "ld3r", ".1d", 0, false, 0 },
490 { AArch64::LD3Rv16b_POST
, "ld3r", ".16b", 1, false, 3 },
491 { AArch64::LD3Rv8h_POST
, "ld3r", ".8h", 1, false, 6 },
492 { AArch64::LD3Rv4s_POST
, "ld3r", ".4s", 1, false, 12 },
493 { AArch64::LD3Rv2d_POST
, "ld3r", ".2d", 1, false, 24 },
494 { AArch64::LD3Rv8b_POST
, "ld3r", ".8b", 1, false, 3 },
495 { AArch64::LD3Rv4h_POST
, "ld3r", ".4h", 1, false, 6 },
496 { AArch64::LD3Rv2s_POST
, "ld3r", ".2s", 1, false, 12 },
497 { AArch64::LD3Rv1d_POST
, "ld3r", ".1d", 1, false, 24 },
498 { AArch64::LD3Threev16b
, "ld3", ".16b", 0, false, 0 },
499 { AArch64::LD3Threev8h
, "ld3", ".8h", 0, false, 0 },
500 { AArch64::LD3Threev4s
, "ld3", ".4s", 0, false, 0 },
501 { AArch64::LD3Threev2d
, "ld3", ".2d", 0, false, 0 },
502 { AArch64::LD3Threev8b
, "ld3", ".8b", 0, false, 0 },
503 { AArch64::LD3Threev4h
, "ld3", ".4h", 0, false, 0 },
504 { AArch64::LD3Threev2s
, "ld3", ".2s", 0, false, 0 },
505 { AArch64::LD3Threev16b_POST
, "ld3", ".16b", 1, false, 48 },
506 { AArch64::LD3Threev8h_POST
, "ld3", ".8h", 1, false, 48 },
507 { AArch64::LD3Threev4s_POST
, "ld3", ".4s", 1, false, 48 },
508 { AArch64::LD3Threev2d_POST
, "ld3", ".2d", 1, false, 48 },
509 { AArch64::LD3Threev8b_POST
, "ld3", ".8b", 1, false, 24 },
510 { AArch64::LD3Threev4h_POST
, "ld3", ".4h", 1, false, 24 },
511 { AArch64::LD3Threev2s_POST
, "ld3", ".2s", 1, false, 24 },
512 { AArch64::LD4i8
, "ld4", ".b", 1, true, 0 },
513 { AArch64::LD4i16
, "ld4", ".h", 1, true, 0 },
514 { AArch64::LD4i32
, "ld4", ".s", 1, true, 0 },
515 { AArch64::LD4i64
, "ld4", ".d", 1, true, 0 },
516 { AArch64::LD4i8_POST
, "ld4", ".b", 2, true, 4 },
517 { AArch64::LD4i16_POST
, "ld4", ".h", 2, true, 8 },
518 { AArch64::LD4i32_POST
, "ld4", ".s", 2, true, 16 },
519 { AArch64::LD4i64_POST
, "ld4", ".d", 2, true, 32 },
520 { AArch64::LD4Rv16b
, "ld4r", ".16b", 0, false, 0 },
521 { AArch64::LD4Rv8h
, "ld4r", ".8h", 0, false, 0 },
522 { AArch64::LD4Rv4s
, "ld4r", ".4s", 0, false, 0 },
523 { AArch64::LD4Rv2d
, "ld4r", ".2d", 0, false, 0 },
524 { AArch64::LD4Rv8b
, "ld4r", ".8b", 0, false, 0 },
525 { AArch64::LD4Rv4h
, "ld4r", ".4h", 0, false, 0 },
526 { AArch64::LD4Rv2s
, "ld4r", ".2s", 0, false, 0 },
527 { AArch64::LD4Rv1d
, "ld4r", ".1d", 0, false, 0 },
528 { AArch64::LD4Rv16b_POST
, "ld4r", ".16b", 1, false, 4 },
529 { AArch64::LD4Rv8h_POST
, "ld4r", ".8h", 1, false, 8 },
530 { AArch64::LD4Rv4s_POST
, "ld4r", ".4s", 1, false, 16 },
531 { AArch64::LD4Rv2d_POST
, "ld4r", ".2d", 1, false, 32 },
532 { AArch64::LD4Rv8b_POST
, "ld4r", ".8b", 1, false, 4 },
533 { AArch64::LD4Rv4h_POST
, "ld4r", ".4h", 1, false, 8 },
534 { AArch64::LD4Rv2s_POST
, "ld4r", ".2s", 1, false, 16 },
535 { AArch64::LD4Rv1d_POST
, "ld4r", ".1d", 1, false, 32 },
536 { AArch64::LD4Fourv16b
, "ld4", ".16b", 0, false, 0 },
537 { AArch64::LD4Fourv8h
, "ld4", ".8h", 0, false, 0 },
538 { AArch64::LD4Fourv4s
, "ld4", ".4s", 0, false, 0 },
539 { AArch64::LD4Fourv2d
, "ld4", ".2d", 0, false, 0 },
540 { AArch64::LD4Fourv8b
, "ld4", ".8b", 0, false, 0 },
541 { AArch64::LD4Fourv4h
, "ld4", ".4h", 0, false, 0 },
542 { AArch64::LD4Fourv2s
, "ld4", ".2s", 0, false, 0 },
543 { AArch64::LD4Fourv16b_POST
, "ld4", ".16b", 1, false, 64 },
544 { AArch64::LD4Fourv8h_POST
, "ld4", ".8h", 1, false, 64 },
545 { AArch64::LD4Fourv4s_POST
, "ld4", ".4s", 1, false, 64 },
546 { AArch64::LD4Fourv2d_POST
, "ld4", ".2d", 1, false, 64 },
547 { AArch64::LD4Fourv8b_POST
, "ld4", ".8b", 1, false, 32 },
548 { AArch64::LD4Fourv4h_POST
, "ld4", ".4h", 1, false, 32 },
549 { AArch64::LD4Fourv2s_POST
, "ld4", ".2s", 1, false, 32 },
550 { AArch64::ST1i8
, "st1", ".b", 0, true, 0 },
551 { AArch64::ST1i16
, "st1", ".h", 0, true, 0 },
552 { AArch64::ST1i32
, "st1", ".s", 0, true, 0 },
553 { AArch64::ST1i64
, "st1", ".d", 0, true, 0 },
554 { AArch64::ST1i8_POST
, "st1", ".b", 1, true, 1 },
555 { AArch64::ST1i16_POST
, "st1", ".h", 1, true, 2 },
556 { AArch64::ST1i32_POST
, "st1", ".s", 1, true, 4 },
557 { AArch64::ST1i64_POST
, "st1", ".d", 1, true, 8 },
558 { AArch64::ST1Onev16b
, "st1", ".16b", 0, false, 0 },
559 { AArch64::ST1Onev8h
, "st1", ".8h", 0, false, 0 },
560 { AArch64::ST1Onev4s
, "st1", ".4s", 0, false, 0 },
561 { AArch64::ST1Onev2d
, "st1", ".2d", 0, false, 0 },
562 { AArch64::ST1Onev8b
, "st1", ".8b", 0, false, 0 },
563 { AArch64::ST1Onev4h
, "st1", ".4h", 0, false, 0 },
564 { AArch64::ST1Onev2s
, "st1", ".2s", 0, false, 0 },
565 { AArch64::ST1Onev1d
, "st1", ".1d", 0, false, 0 },
566 { AArch64::ST1Onev16b_POST
, "st1", ".16b", 1, false, 16 },
567 { AArch64::ST1Onev8h_POST
, "st1", ".8h", 1, false, 16 },
568 { AArch64::ST1Onev4s_POST
, "st1", ".4s", 1, false, 16 },
569 { AArch64::ST1Onev2d_POST
, "st1", ".2d", 1, false, 16 },
570 { AArch64::ST1Onev8b_POST
, "st1", ".8b", 1, false, 8 },
571 { AArch64::ST1Onev4h_POST
, "st1", ".4h", 1, false, 8 },
572 { AArch64::ST1Onev2s_POST
, "st1", ".2s", 1, false, 8 },
573 { AArch64::ST1Onev1d_POST
, "st1", ".1d", 1, false, 8 },
574 { AArch64::ST1Twov16b
, "st1", ".16b", 0, false, 0 },
575 { AArch64::ST1Twov8h
, "st1", ".8h", 0, false, 0 },
576 { AArch64::ST1Twov4s
, "st1", ".4s", 0, false, 0 },
577 { AArch64::ST1Twov2d
, "st1", ".2d", 0, false, 0 },
578 { AArch64::ST1Twov8b
, "st1", ".8b", 0, false, 0 },
579 { AArch64::ST1Twov4h
, "st1", ".4h", 0, false, 0 },
580 { AArch64::ST1Twov2s
, "st1", ".2s", 0, false, 0 },
581 { AArch64::ST1Twov1d
, "st1", ".1d", 0, false, 0 },
582 { AArch64::ST1Twov16b_POST
, "st1", ".16b", 1, false, 32 },
583 { AArch64::ST1Twov8h_POST
, "st1", ".8h", 1, false, 32 },
584 { AArch64::ST1Twov4s_POST
, "st1", ".4s", 1, false, 32 },
585 { AArch64::ST1Twov2d_POST
, "st1", ".2d", 1, false, 32 },
586 { AArch64::ST1Twov8b_POST
, "st1", ".8b", 1, false, 16 },
587 { AArch64::ST1Twov4h_POST
, "st1", ".4h", 1, false, 16 },
588 { AArch64::ST1Twov2s_POST
, "st1", ".2s", 1, false, 16 },
589 { AArch64::ST1Twov1d_POST
, "st1", ".1d", 1, false, 16 },
590 { AArch64::ST1Threev16b
, "st1", ".16b", 0, false, 0 },
591 { AArch64::ST1Threev8h
, "st1", ".8h", 0, false, 0 },
592 { AArch64::ST1Threev4s
, "st1", ".4s", 0, false, 0 },
593 { AArch64::ST1Threev2d
, "st1", ".2d", 0, false, 0 },
594 { AArch64::ST1Threev8b
, "st1", ".8b", 0, false, 0 },
595 { AArch64::ST1Threev4h
, "st1", ".4h", 0, false, 0 },
596 { AArch64::ST1Threev2s
, "st1", ".2s", 0, false, 0 },
597 { AArch64::ST1Threev1d
, "st1", ".1d", 0, false, 0 },
598 { AArch64::ST1Threev16b_POST
, "st1", ".16b", 1, false, 48 },
599 { AArch64::ST1Threev8h_POST
, "st1", ".8h", 1, false, 48 },
600 { AArch64::ST1Threev4s_POST
, "st1", ".4s", 1, false, 48 },
601 { AArch64::ST1Threev2d_POST
, "st1", ".2d", 1, false, 48 },
602 { AArch64::ST1Threev8b_POST
, "st1", ".8b", 1, false, 24 },
603 { AArch64::ST1Threev4h_POST
, "st1", ".4h", 1, false, 24 },
604 { AArch64::ST1Threev2s_POST
, "st1", ".2s", 1, false, 24 },
605 { AArch64::ST1Threev1d_POST
, "st1", ".1d", 1, false, 24 },
606 { AArch64::ST1Fourv16b
, "st1", ".16b", 0, false, 0 },
607 { AArch64::ST1Fourv8h
, "st1", ".8h", 0, false, 0 },
608 { AArch64::ST1Fourv4s
, "st1", ".4s", 0, false, 0 },
609 { AArch64::ST1Fourv2d
, "st1", ".2d", 0, false, 0 },
610 { AArch64::ST1Fourv8b
, "st1", ".8b", 0, false, 0 },
611 { AArch64::ST1Fourv4h
, "st1", ".4h", 0, false, 0 },
612 { AArch64::ST1Fourv2s
, "st1", ".2s", 0, false, 0 },
613 { AArch64::ST1Fourv1d
, "st1", ".1d", 0, false, 0 },
614 { AArch64::ST1Fourv16b_POST
, "st1", ".16b", 1, false, 64 },
615 { AArch64::ST1Fourv8h_POST
, "st1", ".8h", 1, false, 64 },
616 { AArch64::ST1Fourv4s_POST
, "st1", ".4s", 1, false, 64 },
617 { AArch64::ST1Fourv2d_POST
, "st1", ".2d", 1, false, 64 },
618 { AArch64::ST1Fourv8b_POST
, "st1", ".8b", 1, false, 32 },
619 { AArch64::ST1Fourv4h_POST
, "st1", ".4h", 1, false, 32 },
620 { AArch64::ST1Fourv2s_POST
, "st1", ".2s", 1, false, 32 },
621 { AArch64::ST1Fourv1d_POST
, "st1", ".1d", 1, false, 32 },
622 { AArch64::ST2i8
, "st2", ".b", 0, true, 0 },
623 { AArch64::ST2i16
, "st2", ".h", 0, true, 0 },
624 { AArch64::ST2i32
, "st2", ".s", 0, true, 0 },
625 { AArch64::ST2i64
, "st2", ".d", 0, true, 0 },
626 { AArch64::ST2i8_POST
, "st2", ".b", 1, true, 2 },
627 { AArch64::ST2i16_POST
, "st2", ".h", 1, true, 4 },
628 { AArch64::ST2i32_POST
, "st2", ".s", 1, true, 8 },
629 { AArch64::ST2i64_POST
, "st2", ".d", 1, true, 16 },
630 { AArch64::ST2Twov16b
, "st2", ".16b", 0, false, 0 },
631 { AArch64::ST2Twov8h
, "st2", ".8h", 0, false, 0 },
632 { AArch64::ST2Twov4s
, "st2", ".4s", 0, false, 0 },
633 { AArch64::ST2Twov2d
, "st2", ".2d", 0, false, 0 },
634 { AArch64::ST2Twov8b
, "st2", ".8b", 0, false, 0 },
635 { AArch64::ST2Twov4h
, "st2", ".4h", 0, false, 0 },
636 { AArch64::ST2Twov2s
, "st2", ".2s", 0, false, 0 },
637 { AArch64::ST2Twov16b_POST
, "st2", ".16b", 1, false, 32 },
638 { AArch64::ST2Twov8h_POST
, "st2", ".8h", 1, false, 32 },
639 { AArch64::ST2Twov4s_POST
, "st2", ".4s", 1, false, 32 },
640 { AArch64::ST2Twov2d_POST
, "st2", ".2d", 1, false, 32 },
641 { AArch64::ST2Twov8b_POST
, "st2", ".8b", 1, false, 16 },
642 { AArch64::ST2Twov4h_POST
, "st2", ".4h", 1, false, 16 },
643 { AArch64::ST2Twov2s_POST
, "st2", ".2s", 1, false, 16 },
644 { AArch64::ST3i8
, "st3", ".b", 0, true, 0 },
645 { AArch64::ST3i16
, "st3", ".h", 0, true, 0 },
646 { AArch64::ST3i32
, "st3", ".s", 0, true, 0 },
647 { AArch64::ST3i64
, "st3", ".d", 0, true, 0 },
648 { AArch64::ST3i8_POST
, "st3", ".b", 1, true, 3 },
649 { AArch64::ST3i16_POST
, "st3", ".h", 1, true, 6 },
650 { AArch64::ST3i32_POST
, "st3", ".s", 1, true, 12 },
651 { AArch64::ST3i64_POST
, "st3", ".d", 1, true, 24 },
652 { AArch64::ST3Threev16b
, "st3", ".16b", 0, false, 0 },
653 { AArch64::ST3Threev8h
, "st3", ".8h", 0, false, 0 },
654 { AArch64::ST3Threev4s
, "st3", ".4s", 0, false, 0 },
655 { AArch64::ST3Threev2d
, "st3", ".2d", 0, false, 0 },
656 { AArch64::ST3Threev8b
, "st3", ".8b", 0, false, 0 },
657 { AArch64::ST3Threev4h
, "st3", ".4h", 0, false, 0 },
658 { AArch64::ST3Threev2s
, "st3", ".2s", 0, false, 0 },
659 { AArch64::ST3Threev16b_POST
, "st3", ".16b", 1, false, 48 },
660 { AArch64::ST3Threev8h_POST
, "st3", ".8h", 1, false, 48 },
661 { AArch64::ST3Threev4s_POST
, "st3", ".4s", 1, false, 48 },
662 { AArch64::ST3Threev2d_POST
, "st3", ".2d", 1, false, 48 },
663 { AArch64::ST3Threev8b_POST
, "st3", ".8b", 1, false, 24 },
664 { AArch64::ST3Threev4h_POST
, "st3", ".4h", 1, false, 24 },
665 { AArch64::ST3Threev2s_POST
, "st3", ".2s", 1, false, 24 },
666 { AArch64::ST4i8
, "st4", ".b", 0, true, 0 },
667 { AArch64::ST4i16
, "st4", ".h", 0, true, 0 },
668 { AArch64::ST4i32
, "st4", ".s", 0, true, 0 },
669 { AArch64::ST4i64
, "st4", ".d", 0, true, 0 },
670 { AArch64::ST4i8_POST
, "st4", ".b", 1, true, 4 },
671 { AArch64::ST4i16_POST
, "st4", ".h", 1, true, 8 },
672 { AArch64::ST4i32_POST
, "st4", ".s", 1, true, 16 },
673 { AArch64::ST4i64_POST
, "st4", ".d", 1, true, 32 },
674 { AArch64::ST4Fourv16b
, "st4", ".16b", 0, false, 0 },
675 { AArch64::ST4Fourv8h
, "st4", ".8h", 0, false, 0 },
676 { AArch64::ST4Fourv4s
, "st4", ".4s", 0, false, 0 },
677 { AArch64::ST4Fourv2d
, "st4", ".2d", 0, false, 0 },
678 { AArch64::ST4Fourv8b
, "st4", ".8b", 0, false, 0 },
679 { AArch64::ST4Fourv4h
, "st4", ".4h", 0, false, 0 },
680 { AArch64::ST4Fourv2s
, "st4", ".2s", 0, false, 0 },
681 { AArch64::ST4Fourv16b_POST
, "st4", ".16b", 1, false, 64 },
682 { AArch64::ST4Fourv8h_POST
, "st4", ".8h", 1, false, 64 },
683 { AArch64::ST4Fourv4s_POST
, "st4", ".4s", 1, false, 64 },
684 { AArch64::ST4Fourv2d_POST
, "st4", ".2d", 1, false, 64 },
685 { AArch64::ST4Fourv8b_POST
, "st4", ".8b", 1, false, 32 },
686 { AArch64::ST4Fourv4h_POST
, "st4", ".4h", 1, false, 32 },
687 { AArch64::ST4Fourv2s_POST
, "st4", ".2s", 1, false, 32 },
690 static const LdStNInstrDesc
*getLdStNInstrDesc(unsigned Opcode
) {
692 for (Idx
= 0; Idx
!= array_lengthof(LdStNInstInfo
); ++Idx
)
693 if (LdStNInstInfo
[Idx
].Opcode
== Opcode
)
694 return &LdStNInstInfo
[Idx
];
699 void AArch64AppleInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&O
,
701 const MCSubtargetInfo
&STI
) {
702 unsigned Opcode
= MI
->getOpcode();
706 if (isTblTbxInstruction(MI
->getOpcode(), Layout
, IsTbx
)) {
707 O
<< "\t" << (IsTbx
? "tbx" : "tbl") << Layout
<< '\t'
708 << getRegisterName(MI
->getOperand(0).getReg(), AArch64::vreg
) << ", ";
710 unsigned ListOpNum
= IsTbx
? 2 : 1;
711 printVectorList(MI
, ListOpNum
, STI
, O
, "");
714 << getRegisterName(MI
->getOperand(ListOpNum
+ 1).getReg(), AArch64::vreg
);
715 printAnnotation(O
, Annot
);
719 if (const LdStNInstrDesc
*LdStDesc
= getLdStNInstrDesc(Opcode
)) {
720 O
<< "\t" << LdStDesc
->Mnemonic
<< LdStDesc
->Layout
<< '\t';
722 // Now onto the operands: first a vector list with possible lane
723 // specifier. E.g. { v0 }[2]
724 int OpNum
= LdStDesc
->ListOperand
;
725 printVectorList(MI
, OpNum
++, STI
, O
, "");
727 if (LdStDesc
->HasLane
)
728 O
<< '[' << MI
->getOperand(OpNum
++).getImm() << ']';
730 // Next the address: [xN]
731 unsigned AddrReg
= MI
->getOperand(OpNum
++).getReg();
732 O
<< ", [" << getRegisterName(AddrReg
) << ']';
734 // Finally, there might be a post-indexed offset.
735 if (LdStDesc
->NaturalOffset
!= 0) {
736 unsigned Reg
= MI
->getOperand(OpNum
++).getReg();
737 if (Reg
!= AArch64::XZR
)
738 O
<< ", " << getRegisterName(Reg
);
740 assert(LdStDesc
->NaturalOffset
&& "no offset on post-inc instruction?");
741 O
<< ", #" << LdStDesc
->NaturalOffset
;
745 printAnnotation(O
, Annot
);
749 AArch64InstPrinter::printInst(MI
, O
, Annot
, STI
);
752 bool AArch64InstPrinter::printSysAlias(const MCInst
*MI
,
753 const MCSubtargetInfo
&STI
,
756 unsigned Opcode
= MI
->getOpcode();
757 assert(Opcode
== AArch64::SYSxt
&& "Invalid opcode for SYS alias!");
760 const MCOperand
&Op1
= MI
->getOperand(0);
761 const MCOperand
&Cn
= MI
->getOperand(1);
762 const MCOperand
&Cm
= MI
->getOperand(2);
763 const MCOperand
&Op2
= MI
->getOperand(3);
765 unsigned Op1Val
= Op1
.getImm();
766 unsigned CnVal
= Cn
.getImm();
767 unsigned CmVal
= Cm
.getImm();
768 unsigned Op2Val
= Op2
.getImm();
770 uint16_t Encoding
= Op2Val
;
771 Encoding
|= CmVal
<< 3;
772 Encoding
|= CnVal
<< 7;
773 Encoding
|= Op1Val
<< 11;
781 default: return false;
782 // Maybe IC, maybe Prediction Restriction
785 default: return false;
786 case 0: goto Search_IC
;
787 case 3: goto Search_PRCTX
;
789 // Prediction Restriction aliases
792 const AArch64PRCTX::PRCTX
*PRCTX
= AArch64PRCTX::lookupPRCTXByEncoding(Encoding
>> 3);
793 if (!PRCTX
|| !PRCTX
->haveFeatures(STI
.getFeatureBits()))
796 NeedsReg
= PRCTX
->NeedsReg
;
798 default: return false;
799 case 4: Ins
= "cfp\t"; break;
800 case 5: Ins
= "dvp\t"; break;
801 case 7: Ins
= "cpp\t"; break;
803 Name
= std::string(PRCTX
->Name
);
809 const AArch64IC::IC
*IC
= AArch64IC::lookupICByEncoding(Encoding
);
810 if (!IC
|| !IC
->haveFeatures(STI
.getFeatureBits()))
813 NeedsReg
= IC
->NeedsReg
;
815 Name
= std::string(IC
->Name
);
819 case 4: case 6: case 10: case 11: case 12: case 13: case 14:
821 const AArch64DC::DC
*DC
= AArch64DC::lookupDCByEncoding(Encoding
);
822 if (!DC
|| !DC
->haveFeatures(STI
.getFeatureBits()))
827 Name
= std::string(DC
->Name
);
832 const AArch64AT::AT
*AT
= AArch64AT::lookupATByEncoding(Encoding
);
833 if (!AT
|| !AT
->haveFeatures(STI
.getFeatureBits()))
838 Name
= std::string(AT
->Name
);
842 } else if (CnVal
== 8) {
844 const AArch64TLBI::TLBI
*TLBI
= AArch64TLBI::lookupTLBIByEncoding(Encoding
);
845 if (!TLBI
|| !TLBI
->haveFeatures(STI
.getFeatureBits()))
848 NeedsReg
= TLBI
->NeedsReg
;
850 Name
= std::string(TLBI
->Name
);
855 std::string Str
= Ins
+ Name
;
856 std::transform(Str
.begin(), Str
.end(), Str
.begin(), ::tolower
);
860 O
<< ", " << getRegisterName(MI
->getOperand(4).getReg());
865 void AArch64InstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
866 const MCSubtargetInfo
&STI
,
868 const MCOperand
&Op
= MI
->getOperand(OpNo
);
870 unsigned Reg
= Op
.getReg();
871 O
<< getRegisterName(Reg
);
872 } else if (Op
.isImm()) {
873 printImm(MI
, OpNo
, STI
, O
);
875 assert(Op
.isExpr() && "unknown operand kind in printOperand");
876 Op
.getExpr()->print(O
, &MAI
);
880 void AArch64InstPrinter::printImm(const MCInst
*MI
, unsigned OpNo
,
881 const MCSubtargetInfo
&STI
,
883 const MCOperand
&Op
= MI
->getOperand(OpNo
);
884 O
<< "#" << formatImm(Op
.getImm());
887 void AArch64InstPrinter::printImmHex(const MCInst
*MI
, unsigned OpNo
,
888 const MCSubtargetInfo
&STI
,
890 const MCOperand
&Op
= MI
->getOperand(OpNo
);
891 O
<< format("#%#llx", Op
.getImm());
894 void AArch64InstPrinter::printPostIncOperand(const MCInst
*MI
, unsigned OpNo
,
895 unsigned Imm
, raw_ostream
&O
) {
896 const MCOperand
&Op
= MI
->getOperand(OpNo
);
898 unsigned Reg
= Op
.getReg();
899 if (Reg
== AArch64::XZR
)
902 O
<< getRegisterName(Reg
);
904 llvm_unreachable("unknown operand kind in printPostIncOperand64");
907 void AArch64InstPrinter::printVRegOperand(const MCInst
*MI
, unsigned OpNo
,
908 const MCSubtargetInfo
&STI
,
910 const MCOperand
&Op
= MI
->getOperand(OpNo
);
911 assert(Op
.isReg() && "Non-register vreg operand!");
912 unsigned Reg
= Op
.getReg();
913 O
<< getRegisterName(Reg
, AArch64::vreg
);
916 void AArch64InstPrinter::printSysCROperand(const MCInst
*MI
, unsigned OpNo
,
917 const MCSubtargetInfo
&STI
,
919 const MCOperand
&Op
= MI
->getOperand(OpNo
);
920 assert(Op
.isImm() && "System instruction C[nm] operands must be immediates!");
921 O
<< "c" << Op
.getImm();
924 void AArch64InstPrinter::printAddSubImm(const MCInst
*MI
, unsigned OpNum
,
925 const MCSubtargetInfo
&STI
,
927 const MCOperand
&MO
= MI
->getOperand(OpNum
);
929 unsigned Val
= (MO
.getImm() & 0xfff);
930 assert(Val
== MO
.getImm() && "Add/sub immediate out of range!");
932 AArch64_AM::getShiftValue(MI
->getOperand(OpNum
+ 1).getImm());
933 O
<< '#' << formatImm(Val
);
935 printShifter(MI
, OpNum
+ 1, STI
, O
);
938 *CommentStream
<< '=' << formatImm(Val
<< Shift
) << '\n';
940 assert(MO
.isExpr() && "Unexpected operand type!");
941 MO
.getExpr()->print(O
, &MAI
);
942 printShifter(MI
, OpNum
+ 1, STI
, O
);
946 template <typename T
>
947 void AArch64InstPrinter::printLogicalImm(const MCInst
*MI
, unsigned OpNum
,
948 const MCSubtargetInfo
&STI
,
950 uint64_t Val
= MI
->getOperand(OpNum
).getImm();
952 O
.write_hex(AArch64_AM::decodeLogicalImmediate(Val
, 8 * sizeof(T
)));
955 void AArch64InstPrinter::printShifter(const MCInst
*MI
, unsigned OpNum
,
956 const MCSubtargetInfo
&STI
,
958 unsigned Val
= MI
->getOperand(OpNum
).getImm();
959 // LSL #0 should not be printed.
960 if (AArch64_AM::getShiftType(Val
) == AArch64_AM::LSL
&&
961 AArch64_AM::getShiftValue(Val
) == 0)
963 O
<< ", " << AArch64_AM::getShiftExtendName(AArch64_AM::getShiftType(Val
))
964 << " #" << AArch64_AM::getShiftValue(Val
);
967 void AArch64InstPrinter::printShiftedRegister(const MCInst
*MI
, unsigned OpNum
,
968 const MCSubtargetInfo
&STI
,
970 O
<< getRegisterName(MI
->getOperand(OpNum
).getReg());
971 printShifter(MI
, OpNum
+ 1, STI
, O
);
974 void AArch64InstPrinter::printExtendedRegister(const MCInst
*MI
, unsigned OpNum
,
975 const MCSubtargetInfo
&STI
,
977 O
<< getRegisterName(MI
->getOperand(OpNum
).getReg());
978 printArithExtend(MI
, OpNum
+ 1, STI
, O
);
981 void AArch64InstPrinter::printArithExtend(const MCInst
*MI
, unsigned OpNum
,
982 const MCSubtargetInfo
&STI
,
984 unsigned Val
= MI
->getOperand(OpNum
).getImm();
985 AArch64_AM::ShiftExtendType ExtType
= AArch64_AM::getArithExtendType(Val
);
986 unsigned ShiftVal
= AArch64_AM::getArithShiftValue(Val
);
988 // If the destination or first source register operand is [W]SP, print
989 // UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
991 if (ExtType
== AArch64_AM::UXTW
|| ExtType
== AArch64_AM::UXTX
) {
992 unsigned Dest
= MI
->getOperand(0).getReg();
993 unsigned Src1
= MI
->getOperand(1).getReg();
994 if ( ((Dest
== AArch64::SP
|| Src1
== AArch64::SP
) &&
995 ExtType
== AArch64_AM::UXTX
) ||
996 ((Dest
== AArch64::WSP
|| Src1
== AArch64::WSP
) &&
997 ExtType
== AArch64_AM::UXTW
) ) {
999 O
<< ", lsl #" << ShiftVal
;
1003 O
<< ", " << AArch64_AM::getShiftExtendName(ExtType
);
1005 O
<< " #" << ShiftVal
;
1008 static void printMemExtendImpl(bool SignExtend
, bool DoShift
,
1009 unsigned Width
, char SrcRegKind
,
1011 // sxtw, sxtx, uxtw or lsl (== uxtx)
1012 bool IsLSL
= !SignExtend
&& SrcRegKind
== 'x';
1016 O
<< (SignExtend
? 's' : 'u') << "xt" << SrcRegKind
;
1018 if (DoShift
|| IsLSL
)
1019 O
<< " #" << Log2_32(Width
/ 8);
1022 void AArch64InstPrinter::printMemExtend(const MCInst
*MI
, unsigned OpNum
,
1023 raw_ostream
&O
, char SrcRegKind
,
1025 bool SignExtend
= MI
->getOperand(OpNum
).getImm();
1026 bool DoShift
= MI
->getOperand(OpNum
+ 1).getImm();
1027 printMemExtendImpl(SignExtend
, DoShift
, Width
, SrcRegKind
, O
);
1030 template <bool SignExtend
, int ExtWidth
, char SrcRegKind
, char Suffix
>
1031 void AArch64InstPrinter::printRegWithShiftExtend(const MCInst
*MI
,
1033 const MCSubtargetInfo
&STI
,
1035 printOperand(MI
, OpNum
, STI
, O
);
1036 if (Suffix
== 's' || Suffix
== 'd')
1039 assert(Suffix
== 0 && "Unsupported suffix size");
1041 bool DoShift
= ExtWidth
!= 8;
1042 if (SignExtend
|| DoShift
|| SrcRegKind
== 'w') {
1044 printMemExtendImpl(SignExtend
, DoShift
, ExtWidth
, SrcRegKind
, O
);
1048 void AArch64InstPrinter::printCondCode(const MCInst
*MI
, unsigned OpNum
,
1049 const MCSubtargetInfo
&STI
,
1051 AArch64CC::CondCode CC
= (AArch64CC::CondCode
)MI
->getOperand(OpNum
).getImm();
1052 O
<< AArch64CC::getCondCodeName(CC
);
1055 void AArch64InstPrinter::printInverseCondCode(const MCInst
*MI
, unsigned OpNum
,
1056 const MCSubtargetInfo
&STI
,
1058 AArch64CC::CondCode CC
= (AArch64CC::CondCode
)MI
->getOperand(OpNum
).getImm();
1059 O
<< AArch64CC::getCondCodeName(AArch64CC::getInvertedCondCode(CC
));
1062 void AArch64InstPrinter::printAMNoIndex(const MCInst
*MI
, unsigned OpNum
,
1063 const MCSubtargetInfo
&STI
,
1065 O
<< '[' << getRegisterName(MI
->getOperand(OpNum
).getReg()) << ']';
1069 void AArch64InstPrinter::printImmScale(const MCInst
*MI
, unsigned OpNum
,
1070 const MCSubtargetInfo
&STI
,
1072 O
<< '#' << formatImm(Scale
* MI
->getOperand(OpNum
).getImm());
1075 void AArch64InstPrinter::printUImm12Offset(const MCInst
*MI
, unsigned OpNum
,
1076 unsigned Scale
, raw_ostream
&O
) {
1077 const MCOperand MO
= MI
->getOperand(OpNum
);
1079 O
<< "#" << formatImm(MO
.getImm() * Scale
);
1081 assert(MO
.isExpr() && "Unexpected operand type!");
1082 MO
.getExpr()->print(O
, &MAI
);
1086 void AArch64InstPrinter::printAMIndexedWB(const MCInst
*MI
, unsigned OpNum
,
1087 unsigned Scale
, raw_ostream
&O
) {
1088 const MCOperand MO1
= MI
->getOperand(OpNum
+ 1);
1089 O
<< '[' << getRegisterName(MI
->getOperand(OpNum
).getReg());
1091 O
<< ", #" << formatImm(MO1
.getImm() * Scale
);
1093 assert(MO1
.isExpr() && "Unexpected operand type!");
1095 MO1
.getExpr()->print(O
, &MAI
);
1100 template <bool IsSVEPrefetch
>
1101 void AArch64InstPrinter::printPrefetchOp(const MCInst
*MI
, unsigned OpNum
,
1102 const MCSubtargetInfo
&STI
,
1104 unsigned prfop
= MI
->getOperand(OpNum
).getImm();
1105 if (IsSVEPrefetch
) {
1106 if (auto PRFM
= AArch64SVEPRFM::lookupSVEPRFMByEncoding(prfop
)) {
1110 } else if (auto PRFM
= AArch64PRFM::lookupPRFMByEncoding(prfop
)) {
1115 O
<< '#' << formatImm(prfop
);
1118 void AArch64InstPrinter::printPSBHintOp(const MCInst
*MI
, unsigned OpNum
,
1119 const MCSubtargetInfo
&STI
,
1121 unsigned psbhintop
= MI
->getOperand(OpNum
).getImm();
1122 auto PSB
= AArch64PSBHint::lookupPSBByEncoding(psbhintop
);
1126 O
<< '#' << formatImm(psbhintop
);
1129 void AArch64InstPrinter::printBTIHintOp(const MCInst
*MI
, unsigned OpNum
,
1130 const MCSubtargetInfo
&STI
,
1132 unsigned btihintop
= (MI
->getOperand(OpNum
).getImm() ^ 32) >> 1;
1133 auto BTI
= AArch64BTIHint::lookupBTIByEncoding(btihintop
);
1137 O
<< '#' << formatImm(btihintop
);
1140 void AArch64InstPrinter::printFPImmOperand(const MCInst
*MI
, unsigned OpNum
,
1141 const MCSubtargetInfo
&STI
,
1143 const MCOperand
&MO
= MI
->getOperand(OpNum
);
1145 MO
.isFPImm() ? MO
.getFPImm() : AArch64_AM::getFPImmFloat(MO
.getImm());
1147 // 8 decimal places are enough to perfectly represent permitted floats.
1148 O
<< format("#%.8f", FPImm
);
1151 static unsigned getNextVectorRegister(unsigned Reg
, unsigned Stride
= 1) {
1155 llvm_unreachable("Vector register expected!");
1156 case AArch64::Q0
: Reg
= AArch64::Q1
; break;
1157 case AArch64::Q1
: Reg
= AArch64::Q2
; break;
1158 case AArch64::Q2
: Reg
= AArch64::Q3
; break;
1159 case AArch64::Q3
: Reg
= AArch64::Q4
; break;
1160 case AArch64::Q4
: Reg
= AArch64::Q5
; break;
1161 case AArch64::Q5
: Reg
= AArch64::Q6
; break;
1162 case AArch64::Q6
: Reg
= AArch64::Q7
; break;
1163 case AArch64::Q7
: Reg
= AArch64::Q8
; break;
1164 case AArch64::Q8
: Reg
= AArch64::Q9
; break;
1165 case AArch64::Q9
: Reg
= AArch64::Q10
; break;
1166 case AArch64::Q10
: Reg
= AArch64::Q11
; break;
1167 case AArch64::Q11
: Reg
= AArch64::Q12
; break;
1168 case AArch64::Q12
: Reg
= AArch64::Q13
; break;
1169 case AArch64::Q13
: Reg
= AArch64::Q14
; break;
1170 case AArch64::Q14
: Reg
= AArch64::Q15
; break;
1171 case AArch64::Q15
: Reg
= AArch64::Q16
; break;
1172 case AArch64::Q16
: Reg
= AArch64::Q17
; break;
1173 case AArch64::Q17
: Reg
= AArch64::Q18
; break;
1174 case AArch64::Q18
: Reg
= AArch64::Q19
; break;
1175 case AArch64::Q19
: Reg
= AArch64::Q20
; break;
1176 case AArch64::Q20
: Reg
= AArch64::Q21
; break;
1177 case AArch64::Q21
: Reg
= AArch64::Q22
; break;
1178 case AArch64::Q22
: Reg
= AArch64::Q23
; break;
1179 case AArch64::Q23
: Reg
= AArch64::Q24
; break;
1180 case AArch64::Q24
: Reg
= AArch64::Q25
; break;
1181 case AArch64::Q25
: Reg
= AArch64::Q26
; break;
1182 case AArch64::Q26
: Reg
= AArch64::Q27
; break;
1183 case AArch64::Q27
: Reg
= AArch64::Q28
; break;
1184 case AArch64::Q28
: Reg
= AArch64::Q29
; break;
1185 case AArch64::Q29
: Reg
= AArch64::Q30
; break;
1186 case AArch64::Q30
: Reg
= AArch64::Q31
; break;
1187 // Vector lists can wrap around.
1191 case AArch64::Z0
: Reg
= AArch64::Z1
; break;
1192 case AArch64::Z1
: Reg
= AArch64::Z2
; break;
1193 case AArch64::Z2
: Reg
= AArch64::Z3
; break;
1194 case AArch64::Z3
: Reg
= AArch64::Z4
; break;
1195 case AArch64::Z4
: Reg
= AArch64::Z5
; break;
1196 case AArch64::Z5
: Reg
= AArch64::Z6
; break;
1197 case AArch64::Z6
: Reg
= AArch64::Z7
; break;
1198 case AArch64::Z7
: Reg
= AArch64::Z8
; break;
1199 case AArch64::Z8
: Reg
= AArch64::Z9
; break;
1200 case AArch64::Z9
: Reg
= AArch64::Z10
; break;
1201 case AArch64::Z10
: Reg
= AArch64::Z11
; break;
1202 case AArch64::Z11
: Reg
= AArch64::Z12
; break;
1203 case AArch64::Z12
: Reg
= AArch64::Z13
; break;
1204 case AArch64::Z13
: Reg
= AArch64::Z14
; break;
1205 case AArch64::Z14
: Reg
= AArch64::Z15
; break;
1206 case AArch64::Z15
: Reg
= AArch64::Z16
; break;
1207 case AArch64::Z16
: Reg
= AArch64::Z17
; break;
1208 case AArch64::Z17
: Reg
= AArch64::Z18
; break;
1209 case AArch64::Z18
: Reg
= AArch64::Z19
; break;
1210 case AArch64::Z19
: Reg
= AArch64::Z20
; break;
1211 case AArch64::Z20
: Reg
= AArch64::Z21
; break;
1212 case AArch64::Z21
: Reg
= AArch64::Z22
; break;
1213 case AArch64::Z22
: Reg
= AArch64::Z23
; break;
1214 case AArch64::Z23
: Reg
= AArch64::Z24
; break;
1215 case AArch64::Z24
: Reg
= AArch64::Z25
; break;
1216 case AArch64::Z25
: Reg
= AArch64::Z26
; break;
1217 case AArch64::Z26
: Reg
= AArch64::Z27
; break;
1218 case AArch64::Z27
: Reg
= AArch64::Z28
; break;
1219 case AArch64::Z28
: Reg
= AArch64::Z29
; break;
1220 case AArch64::Z29
: Reg
= AArch64::Z30
; break;
1221 case AArch64::Z30
: Reg
= AArch64::Z31
; break;
1222 // Vector lists can wrap around.
1231 template<unsigned size
>
1232 void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst
*MI
,
1234 const MCSubtargetInfo
&STI
,
1236 static_assert(size
== 64 || size
== 32,
1237 "Template parameter must be either 32 or 64");
1238 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1240 unsigned Sube
= (size
== 32) ? AArch64::sube32
: AArch64::sube64
;
1241 unsigned Subo
= (size
== 32) ? AArch64::subo32
: AArch64::subo64
;
1243 unsigned Even
= MRI
.getSubReg(Reg
, Sube
);
1244 unsigned Odd
= MRI
.getSubReg(Reg
, Subo
);
1245 O
<< getRegisterName(Even
) << ", " << getRegisterName(Odd
);
1248 void AArch64InstPrinter::printVectorList(const MCInst
*MI
, unsigned OpNum
,
1249 const MCSubtargetInfo
&STI
,
1251 StringRef LayoutSuffix
) {
1252 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1256 // Work out how many registers there are in the list (if there is an actual
1258 unsigned NumRegs
= 1;
1259 if (MRI
.getRegClass(AArch64::DDRegClassID
).contains(Reg
) ||
1260 MRI
.getRegClass(AArch64::ZPR2RegClassID
).contains(Reg
) ||
1261 MRI
.getRegClass(AArch64::QQRegClassID
).contains(Reg
))
1263 else if (MRI
.getRegClass(AArch64::DDDRegClassID
).contains(Reg
) ||
1264 MRI
.getRegClass(AArch64::ZPR3RegClassID
).contains(Reg
) ||
1265 MRI
.getRegClass(AArch64::QQQRegClassID
).contains(Reg
))
1267 else if (MRI
.getRegClass(AArch64::DDDDRegClassID
).contains(Reg
) ||
1268 MRI
.getRegClass(AArch64::ZPR4RegClassID
).contains(Reg
) ||
1269 MRI
.getRegClass(AArch64::QQQQRegClassID
).contains(Reg
))
1272 // Now forget about the list and find out what the first register is.
1273 if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::dsub0
))
1275 else if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::qsub0
))
1277 else if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::zsub0
))
1280 // If it's a D-reg, we need to promote it to the equivalent Q-reg before
1281 // printing (otherwise getRegisterName fails).
1282 if (MRI
.getRegClass(AArch64::FPR64RegClassID
).contains(Reg
)) {
1283 const MCRegisterClass
&FPR128RC
=
1284 MRI
.getRegClass(AArch64::FPR128RegClassID
);
1285 Reg
= MRI
.getMatchingSuperReg(Reg
, AArch64::dsub
, &FPR128RC
);
1288 for (unsigned i
= 0; i
< NumRegs
; ++i
, Reg
= getNextVectorRegister(Reg
)) {
1289 if (MRI
.getRegClass(AArch64::ZPRRegClassID
).contains(Reg
))
1290 O
<< getRegisterName(Reg
) << LayoutSuffix
;
1292 O
<< getRegisterName(Reg
, AArch64::vreg
) << LayoutSuffix
;
1294 if (i
+ 1 != NumRegs
)
1302 AArch64InstPrinter::printImplicitlyTypedVectorList(const MCInst
*MI
,
1304 const MCSubtargetInfo
&STI
,
1306 printVectorList(MI
, OpNum
, STI
, O
, "");
1309 template <unsigned NumLanes
, char LaneKind
>
1310 void AArch64InstPrinter::printTypedVectorList(const MCInst
*MI
, unsigned OpNum
,
1311 const MCSubtargetInfo
&STI
,
1313 std::string
Suffix(".");
1315 Suffix
+= itostr(NumLanes
) + LaneKind
;
1319 printVectorList(MI
, OpNum
, STI
, O
, Suffix
);
1322 void AArch64InstPrinter::printVectorIndex(const MCInst
*MI
, unsigned OpNum
,
1323 const MCSubtargetInfo
&STI
,
1325 O
<< "[" << MI
->getOperand(OpNum
).getImm() << "]";
1328 void AArch64InstPrinter::printAlignedLabel(const MCInst
*MI
, unsigned OpNum
,
1329 const MCSubtargetInfo
&STI
,
1331 const MCOperand
&Op
= MI
->getOperand(OpNum
);
1333 // If the label has already been resolved to an immediate offset (say, when
1334 // we're running the disassembler), just print the immediate.
1336 O
<< "#" << formatImm(Op
.getImm() * 4);
1340 // If the branch target is simply an address then print it in hex.
1341 const MCConstantExpr
*BranchTarget
=
1342 dyn_cast
<MCConstantExpr
>(MI
->getOperand(OpNum
).getExpr());
1344 if (BranchTarget
&& BranchTarget
->evaluateAsAbsolute(Address
)) {
1346 O
.write_hex(Address
);
1348 // Otherwise, just print the expression.
1349 MI
->getOperand(OpNum
).getExpr()->print(O
, &MAI
);
1353 void AArch64InstPrinter::printAdrpLabel(const MCInst
*MI
, unsigned OpNum
,
1354 const MCSubtargetInfo
&STI
,
1356 const MCOperand
&Op
= MI
->getOperand(OpNum
);
1358 // If the label has already been resolved to an immediate offset (say, when
1359 // we're running the disassembler), just print the immediate.
1361 O
<< "#" << formatImm(Op
.getImm() * (1 << 12));
1365 // Otherwise, just print the expression.
1366 MI
->getOperand(OpNum
).getExpr()->print(O
, &MAI
);
1369 void AArch64InstPrinter::printBarrierOption(const MCInst
*MI
, unsigned OpNo
,
1370 const MCSubtargetInfo
&STI
,
1372 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1373 unsigned Opcode
= MI
->getOpcode();
1376 if (Opcode
== AArch64::ISB
) {
1377 auto ISB
= AArch64ISB::lookupISBByEncoding(Val
);
1378 Name
= ISB
? ISB
->Name
: "";
1379 } else if (Opcode
== AArch64::TSB
) {
1380 auto TSB
= AArch64TSB::lookupTSBByEncoding(Val
);
1381 Name
= TSB
? TSB
->Name
: "";
1383 auto DB
= AArch64DB::lookupDBByEncoding(Val
);
1384 Name
= DB
? DB
->Name
: "";
1392 void AArch64InstPrinter::printMRSSystemRegister(const MCInst
*MI
, unsigned OpNo
,
1393 const MCSubtargetInfo
&STI
,
1395 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1397 // Horrible hack for the one register that has identical encodings but
1398 // different names in MSR and MRS. Because of this, one of MRS and MSR is
1399 // going to get the wrong entry
1400 if (Val
== AArch64SysReg::DBGDTRRX_EL0
) {
1401 O
<< "DBGDTRRX_EL0";
1405 const AArch64SysReg::SysReg
*Reg
= AArch64SysReg::lookupSysRegByEncoding(Val
);
1406 if (Reg
&& Reg
->Readable
&& Reg
->haveFeatures(STI
.getFeatureBits()))
1409 O
<< AArch64SysReg::genericRegisterString(Val
);
1412 void AArch64InstPrinter::printMSRSystemRegister(const MCInst
*MI
, unsigned OpNo
,
1413 const MCSubtargetInfo
&STI
,
1415 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1417 // Horrible hack for the one register that has identical encodings but
1418 // different names in MSR and MRS. Because of this, one of MRS and MSR is
1419 // going to get the wrong entry
1420 if (Val
== AArch64SysReg::DBGDTRTX_EL0
) {
1421 O
<< "DBGDTRTX_EL0";
1425 const AArch64SysReg::SysReg
*Reg
= AArch64SysReg::lookupSysRegByEncoding(Val
);
1426 if (Reg
&& Reg
->Writeable
&& Reg
->haveFeatures(STI
.getFeatureBits()))
1429 O
<< AArch64SysReg::genericRegisterString(Val
);
1432 void AArch64InstPrinter::printSystemPStateField(const MCInst
*MI
, unsigned OpNo
,
1433 const MCSubtargetInfo
&STI
,
1435 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1437 auto PState
= AArch64PState::lookupPStateByEncoding(Val
);
1438 if (PState
&& PState
->haveFeatures(STI
.getFeatureBits()))
1441 O
<< "#" << formatImm(Val
);
1444 void AArch64InstPrinter::printSIMDType10Operand(const MCInst
*MI
, unsigned OpNo
,
1445 const MCSubtargetInfo
&STI
,
1447 unsigned RawVal
= MI
->getOperand(OpNo
).getImm();
1448 uint64_t Val
= AArch64_AM::decodeAdvSIMDModImmType10(RawVal
);
1449 O
<< format("#%#016llx", Val
);
1452 template<int64_t Angle
, int64_t Remainder
>
1453 void AArch64InstPrinter::printComplexRotationOp(const MCInst
*MI
, unsigned OpNo
,
1454 const MCSubtargetInfo
&STI
,
1456 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1457 O
<< "#" << (Val
* Angle
) + Remainder
;
1460 void AArch64InstPrinter::printSVEPattern(const MCInst
*MI
, unsigned OpNum
,
1461 const MCSubtargetInfo
&STI
,
1463 unsigned Val
= MI
->getOperand(OpNum
).getImm();
1464 if (auto Pat
= AArch64SVEPredPattern::lookupSVEPREDPATByEncoding(Val
))
1467 O
<< '#' << formatImm(Val
);
1470 template <char suffix
>
1471 void AArch64InstPrinter::printSVERegOp(const MCInst
*MI
, unsigned OpNum
,
1472 const MCSubtargetInfo
&STI
,
1482 default: llvm_unreachable("Invalid kind specifier.");
1485 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1486 O
<< getRegisterName(Reg
);
1491 template <typename T
>
1492 void AArch64InstPrinter::printImmSVE(T Value
, raw_ostream
&O
) {
1493 typename
std::make_unsigned
<T
>::type HexValue
= Value
;
1495 if (getPrintImmHex())
1496 O
<< '#' << formatHex((uint64_t)HexValue
);
1498 O
<< '#' << formatDec(Value
);
1500 if (CommentStream
) {
1501 // Do the opposite to that used for instruction operands.
1502 if (getPrintImmHex())
1503 *CommentStream
<< '=' << formatDec(HexValue
) << '\n';
1505 *CommentStream
<< '=' << formatHex((uint64_t)Value
) << '\n';
1509 template <typename T
>
1510 void AArch64InstPrinter::printImm8OptLsl(const MCInst
*MI
, unsigned OpNum
,
1511 const MCSubtargetInfo
&STI
,
1513 unsigned UnscaledVal
= MI
->getOperand(OpNum
).getImm();
1514 unsigned Shift
= MI
->getOperand(OpNum
+ 1).getImm();
1515 assert(AArch64_AM::getShiftType(Shift
) == AArch64_AM::LSL
&&
1516 "Unexepected shift type!");
1518 // #0 lsl #8 is never pretty printed
1519 if ((UnscaledVal
== 0) && (AArch64_AM::getShiftValue(Shift
) != 0)) {
1520 O
<< '#' << formatImm(UnscaledVal
);
1521 printShifter(MI
, OpNum
+ 1, STI
, O
);
1526 if (std::is_signed
<T
>())
1527 Val
= (int8_t)UnscaledVal
* (1 << AArch64_AM::getShiftValue(Shift
));
1529 Val
= (uint8_t)UnscaledVal
* (1 << AArch64_AM::getShiftValue(Shift
));
1531 printImmSVE(Val
, O
);
1534 template <typename T
>
1535 void AArch64InstPrinter::printSVELogicalImm(const MCInst
*MI
, unsigned OpNum
,
1536 const MCSubtargetInfo
&STI
,
1538 typedef typename
std::make_signed
<T
>::type SignedT
;
1539 typedef typename
std::make_unsigned
<T
>::type UnsignedT
;
1541 uint64_t Val
= MI
->getOperand(OpNum
).getImm();
1542 UnsignedT PrintVal
= AArch64_AM::decodeLogicalImmediate(Val
, 64);
1544 // Prefer the default format for 16bit values, hex otherwise.
1545 if ((int16_t)PrintVal
== (SignedT
)PrintVal
)
1546 printImmSVE((T
)PrintVal
, O
);
1547 else if ((uint16_t)PrintVal
== PrintVal
)
1548 printImmSVE(PrintVal
, O
);
1550 O
<< '#' << formatHex((uint64_t)PrintVal
);
1553 template <int Width
>
1554 void AArch64InstPrinter::printZPRasFPR(const MCInst
*MI
, unsigned OpNum
,
1555 const MCSubtargetInfo
&STI
,
1559 case 8: Base
= AArch64::B0
; break;
1560 case 16: Base
= AArch64::H0
; break;
1561 case 32: Base
= AArch64::S0
; break;
1562 case 64: Base
= AArch64::D0
; break;
1563 case 128: Base
= AArch64::Q0
; break;
1565 llvm_unreachable("Unsupported width");
1567 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1568 O
<< getRegisterName(Reg
- AArch64::Z0
+ Base
);
1571 template <unsigned ImmIs0
, unsigned ImmIs1
>
1572 void AArch64InstPrinter::printExactFPImm(const MCInst
*MI
, unsigned OpNum
,
1573 const MCSubtargetInfo
&STI
,
1575 auto *Imm0Desc
= AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs0
);
1576 auto *Imm1Desc
= AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs1
);
1577 unsigned Val
= MI
->getOperand(OpNum
).getImm();
1578 O
<< "#" << (Val
? Imm1Desc
->Repr
: Imm0Desc
->Repr
);
1581 void AArch64InstPrinter::printGPR64as32(const MCInst
*MI
, unsigned OpNum
,
1582 const MCSubtargetInfo
&STI
,
1584 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1585 O
<< getRegisterName(getWRegFromXReg(Reg
));