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 // SBFM/UBFM should print to a nicer aliased form if possible.
73 if (Opcode
== AArch64::SBFMXri
|| Opcode
== AArch64::SBFMWri
||
74 Opcode
== AArch64::UBFMXri
|| Opcode
== AArch64::UBFMWri
) {
75 const MCOperand
&Op0
= MI
->getOperand(0);
76 const MCOperand
&Op1
= MI
->getOperand(1);
77 const MCOperand
&Op2
= MI
->getOperand(2);
78 const MCOperand
&Op3
= MI
->getOperand(3);
80 bool IsSigned
= (Opcode
== AArch64::SBFMXri
|| Opcode
== AArch64::SBFMWri
);
81 bool Is64Bit
= (Opcode
== AArch64::SBFMXri
|| Opcode
== AArch64::UBFMXri
);
82 if (Op2
.isImm() && Op2
.getImm() == 0 && Op3
.isImm()) {
83 const char *AsmMnemonic
= nullptr;
85 switch (Op3
.getImm()) {
101 // *xtw is only valid for signed 64-bit operations.
102 if (Is64Bit
&& IsSigned
)
103 AsmMnemonic
= "sxtw";
108 O
<< '\t' << AsmMnemonic
<< '\t' << getRegisterName(Op0
.getReg())
109 << ", " << getRegisterName(getWRegFromXReg(Op1
.getReg()));
110 printAnnotation(O
, Annot
);
115 // All immediate shifts are aliases, implemented using the Bitfield
116 // instruction. In all cases the immediate shift amount shift must be in
117 // the range 0 to (reg.size -1).
118 if (Op2
.isImm() && Op3
.isImm()) {
119 const char *AsmMnemonic
= nullptr;
121 int64_t immr
= Op2
.getImm();
122 int64_t imms
= Op3
.getImm();
123 if (Opcode
== AArch64::UBFMWri
&& imms
!= 0x1F && ((imms
+ 1) == immr
)) {
126 } else if (Opcode
== AArch64::UBFMXri
&& imms
!= 0x3f &&
127 ((imms
+ 1 == immr
))) {
130 } else if (Opcode
== AArch64::UBFMWri
&& imms
== 0x1f) {
133 } else if (Opcode
== AArch64::UBFMXri
&& imms
== 0x3f) {
136 } else if (Opcode
== AArch64::SBFMWri
&& imms
== 0x1f) {
139 } else if (Opcode
== AArch64::SBFMXri
&& imms
== 0x3f) {
144 O
<< '\t' << AsmMnemonic
<< '\t' << getRegisterName(Op0
.getReg())
145 << ", " << getRegisterName(Op1
.getReg()) << ", #" << shift
;
146 printAnnotation(O
, Annot
);
151 // SBFIZ/UBFIZ aliases
152 if (Op2
.getImm() > Op3
.getImm()) {
153 O
<< '\t' << (IsSigned
? "sbfiz" : "ubfiz") << '\t'
154 << getRegisterName(Op0
.getReg()) << ", " << getRegisterName(Op1
.getReg())
155 << ", #" << (Is64Bit
? 64 : 32) - Op2
.getImm() << ", #" << Op3
.getImm() + 1;
156 printAnnotation(O
, Annot
);
160 // Otherwise SBFX/UBFX is the preferred form
161 O
<< '\t' << (IsSigned
? "sbfx" : "ubfx") << '\t'
162 << getRegisterName(Op0
.getReg()) << ", " << getRegisterName(Op1
.getReg())
163 << ", #" << Op2
.getImm() << ", #" << Op3
.getImm() - Op2
.getImm() + 1;
164 printAnnotation(O
, Annot
);
168 if (Opcode
== AArch64::BFMXri
|| Opcode
== AArch64::BFMWri
) {
169 const MCOperand
&Op0
= MI
->getOperand(0); // Op1 == Op0
170 const MCOperand
&Op2
= MI
->getOperand(2);
171 int ImmR
= MI
->getOperand(3).getImm();
172 int ImmS
= MI
->getOperand(4).getImm();
174 if ((Op2
.getReg() == AArch64::WZR
|| Op2
.getReg() == AArch64::XZR
) &&
175 (ImmR
== 0 || ImmS
< ImmR
) &&
176 STI
.getFeatureBits()[AArch64::HasV8_2aOps
]) {
177 // BFC takes precedence over its entire range, sligtly differently to BFI.
178 int BitWidth
= Opcode
== AArch64::BFMXri
? 64 : 32;
179 int LSB
= (BitWidth
- ImmR
) % BitWidth
;
180 int Width
= ImmS
+ 1;
182 O
<< "\tbfc\t" << getRegisterName(Op0
.getReg())
183 << ", #" << LSB
<< ", #" << Width
;
184 printAnnotation(O
, Annot
);
186 } else if (ImmS
< ImmR
) {
188 int BitWidth
= Opcode
== AArch64::BFMXri
? 64 : 32;
189 int LSB
= (BitWidth
- ImmR
) % BitWidth
;
190 int Width
= ImmS
+ 1;
192 O
<< "\tbfi\t" << getRegisterName(Op0
.getReg()) << ", "
193 << getRegisterName(Op2
.getReg()) << ", #" << LSB
<< ", #" << Width
;
194 printAnnotation(O
, Annot
);
199 int Width
= ImmS
- ImmR
+ 1;
200 // Otherwise BFXIL the preferred form
202 << getRegisterName(Op0
.getReg()) << ", " << getRegisterName(Op2
.getReg())
203 << ", #" << LSB
<< ", #" << Width
;
204 printAnnotation(O
, Annot
);
208 // Symbolic operands for MOVZ, MOVN and MOVK already imply a shift
209 // (e.g. :gottprel_g1: is always going to be "lsl #16") so it should not be
211 if ((Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
||
212 Opcode
== AArch64::MOVNXi
|| Opcode
== AArch64::MOVNWi
) &&
213 MI
->getOperand(1).isExpr()) {
214 if (Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
)
219 O
<< getRegisterName(MI
->getOperand(0).getReg()) << ", #";
220 MI
->getOperand(1).getExpr()->print(O
, &MAI
);
224 if ((Opcode
== AArch64::MOVKXi
|| Opcode
== AArch64::MOVKWi
) &&
225 MI
->getOperand(2).isExpr()) {
226 O
<< "\tmovk\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #";
227 MI
->getOperand(2).getExpr()->print(O
, &MAI
);
231 // MOVZ, MOVN and "ORR wzr, #imm" instructions are aliases for MOV, but their
232 // domains overlap so they need to be prioritized. The chain is "MOVZ lsl #0 >
233 // MOVZ lsl #N > MOVN lsl #0 > MOVN lsl #N > ORR". The highest instruction
234 // that can represent the move is the MOV alias, and the rest get printed
236 if ((Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
) &&
237 MI
->getOperand(1).isImm() && MI
->getOperand(2).isImm()) {
238 int RegWidth
= Opcode
== AArch64::MOVZXi
? 64 : 32;
239 int Shift
= MI
->getOperand(2).getImm();
240 uint64_t Value
= (uint64_t)MI
->getOperand(1).getImm() << Shift
;
242 if (AArch64_AM::isMOVZMovAlias(Value
, Shift
,
243 Opcode
== AArch64::MOVZXi
? 64 : 32)) {
244 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
245 << formatImm(SignExtend64(Value
, RegWidth
));
250 if ((Opcode
== AArch64::MOVNXi
|| Opcode
== AArch64::MOVNWi
) &&
251 MI
->getOperand(1).isImm() && MI
->getOperand(2).isImm()) {
252 int RegWidth
= Opcode
== AArch64::MOVNXi
? 64 : 32;
253 int Shift
= MI
->getOperand(2).getImm();
254 uint64_t Value
= ~((uint64_t)MI
->getOperand(1).getImm() << Shift
);
256 Value
= Value
& 0xffffffff;
258 if (AArch64_AM::isMOVNMovAlias(Value
, Shift
, RegWidth
)) {
259 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
260 << formatImm(SignExtend64(Value
, RegWidth
));
265 if ((Opcode
== AArch64::ORRXri
|| Opcode
== AArch64::ORRWri
) &&
266 (MI
->getOperand(1).getReg() == AArch64::XZR
||
267 MI
->getOperand(1).getReg() == AArch64::WZR
) &&
268 MI
->getOperand(2).isImm()) {
269 int RegWidth
= Opcode
== AArch64::ORRXri
? 64 : 32;
270 uint64_t Value
= AArch64_AM::decodeLogicalImmediate(
271 MI
->getOperand(2).getImm(), RegWidth
);
272 if (!AArch64_AM::isAnyMOVWMovAlias(Value
, RegWidth
)) {
273 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
274 << formatImm(SignExtend64(Value
, RegWidth
));
279 if (Opcode
== AArch64::CompilerBarrier
) {
280 O
<< '\t' << MAI
.getCommentString() << " COMPILER BARRIER";
281 printAnnotation(O
, Annot
);
285 // Instruction TSB is specified as a one operand instruction, but 'csync' is
286 // not encoded, so for printing it is treated as a special case here:
287 if (Opcode
== AArch64::TSB
) {
292 if (!printAliasInstr(MI
, STI
, O
))
293 printInstruction(MI
, STI
, O
);
295 printAnnotation(O
, Annot
);
297 if (atomicBarrierDroppedOnZero(Opcode
) &&
298 (MI
->getOperand(0).getReg() == AArch64::XZR
||
299 MI
->getOperand(0).getReg() == AArch64::WZR
)) {
300 printAnnotation(O
, "acquire semantics dropped since destination is zero");
304 static bool isTblTbxInstruction(unsigned Opcode
, StringRef
&Layout
,
307 case AArch64::TBXv8i8One
:
308 case AArch64::TBXv8i8Two
:
309 case AArch64::TBXv8i8Three
:
310 case AArch64::TBXv8i8Four
:
314 case AArch64::TBLv8i8One
:
315 case AArch64::TBLv8i8Two
:
316 case AArch64::TBLv8i8Three
:
317 case AArch64::TBLv8i8Four
:
321 case AArch64::TBXv16i8One
:
322 case AArch64::TBXv16i8Two
:
323 case AArch64::TBXv16i8Three
:
324 case AArch64::TBXv16i8Four
:
328 case AArch64::TBLv16i8One
:
329 case AArch64::TBLv16i8Two
:
330 case AArch64::TBLv16i8Three
:
331 case AArch64::TBLv16i8Four
:
340 struct LdStNInstrDesc
{
342 const char *Mnemonic
;
349 static const LdStNInstrDesc LdStNInstInfo
[] = {
350 { AArch64::LD1i8
, "ld1", ".b", 1, true, 0 },
351 { AArch64::LD1i16
, "ld1", ".h", 1, true, 0 },
352 { AArch64::LD1i32
, "ld1", ".s", 1, true, 0 },
353 { AArch64::LD1i64
, "ld1", ".d", 1, true, 0 },
354 { AArch64::LD1i8_POST
, "ld1", ".b", 2, true, 1 },
355 { AArch64::LD1i16_POST
, "ld1", ".h", 2, true, 2 },
356 { AArch64::LD1i32_POST
, "ld1", ".s", 2, true, 4 },
357 { AArch64::LD1i64_POST
, "ld1", ".d", 2, true, 8 },
358 { AArch64::LD1Rv16b
, "ld1r", ".16b", 0, false, 0 },
359 { AArch64::LD1Rv8h
, "ld1r", ".8h", 0, false, 0 },
360 { AArch64::LD1Rv4s
, "ld1r", ".4s", 0, false, 0 },
361 { AArch64::LD1Rv2d
, "ld1r", ".2d", 0, false, 0 },
362 { AArch64::LD1Rv8b
, "ld1r", ".8b", 0, false, 0 },
363 { AArch64::LD1Rv4h
, "ld1r", ".4h", 0, false, 0 },
364 { AArch64::LD1Rv2s
, "ld1r", ".2s", 0, false, 0 },
365 { AArch64::LD1Rv1d
, "ld1r", ".1d", 0, false, 0 },
366 { AArch64::LD1Rv16b_POST
, "ld1r", ".16b", 1, false, 1 },
367 { AArch64::LD1Rv8h_POST
, "ld1r", ".8h", 1, false, 2 },
368 { AArch64::LD1Rv4s_POST
, "ld1r", ".4s", 1, false, 4 },
369 { AArch64::LD1Rv2d_POST
, "ld1r", ".2d", 1, false, 8 },
370 { AArch64::LD1Rv8b_POST
, "ld1r", ".8b", 1, false, 1 },
371 { AArch64::LD1Rv4h_POST
, "ld1r", ".4h", 1, false, 2 },
372 { AArch64::LD1Rv2s_POST
, "ld1r", ".2s", 1, false, 4 },
373 { AArch64::LD1Rv1d_POST
, "ld1r", ".1d", 1, false, 8 },
374 { AArch64::LD1Onev16b
, "ld1", ".16b", 0, false, 0 },
375 { AArch64::LD1Onev8h
, "ld1", ".8h", 0, false, 0 },
376 { AArch64::LD1Onev4s
, "ld1", ".4s", 0, false, 0 },
377 { AArch64::LD1Onev2d
, "ld1", ".2d", 0, false, 0 },
378 { AArch64::LD1Onev8b
, "ld1", ".8b", 0, false, 0 },
379 { AArch64::LD1Onev4h
, "ld1", ".4h", 0, false, 0 },
380 { AArch64::LD1Onev2s
, "ld1", ".2s", 0, false, 0 },
381 { AArch64::LD1Onev1d
, "ld1", ".1d", 0, false, 0 },
382 { AArch64::LD1Onev16b_POST
, "ld1", ".16b", 1, false, 16 },
383 { AArch64::LD1Onev8h_POST
, "ld1", ".8h", 1, false, 16 },
384 { AArch64::LD1Onev4s_POST
, "ld1", ".4s", 1, false, 16 },
385 { AArch64::LD1Onev2d_POST
, "ld1", ".2d", 1, false, 16 },
386 { AArch64::LD1Onev8b_POST
, "ld1", ".8b", 1, false, 8 },
387 { AArch64::LD1Onev4h_POST
, "ld1", ".4h", 1, false, 8 },
388 { AArch64::LD1Onev2s_POST
, "ld1", ".2s", 1, false, 8 },
389 { AArch64::LD1Onev1d_POST
, "ld1", ".1d", 1, false, 8 },
390 { AArch64::LD1Twov16b
, "ld1", ".16b", 0, false, 0 },
391 { AArch64::LD1Twov8h
, "ld1", ".8h", 0, false, 0 },
392 { AArch64::LD1Twov4s
, "ld1", ".4s", 0, false, 0 },
393 { AArch64::LD1Twov2d
, "ld1", ".2d", 0, false, 0 },
394 { AArch64::LD1Twov8b
, "ld1", ".8b", 0, false, 0 },
395 { AArch64::LD1Twov4h
, "ld1", ".4h", 0, false, 0 },
396 { AArch64::LD1Twov2s
, "ld1", ".2s", 0, false, 0 },
397 { AArch64::LD1Twov1d
, "ld1", ".1d", 0, false, 0 },
398 { AArch64::LD1Twov16b_POST
, "ld1", ".16b", 1, false, 32 },
399 { AArch64::LD1Twov8h_POST
, "ld1", ".8h", 1, false, 32 },
400 { AArch64::LD1Twov4s_POST
, "ld1", ".4s", 1, false, 32 },
401 { AArch64::LD1Twov2d_POST
, "ld1", ".2d", 1, false, 32 },
402 { AArch64::LD1Twov8b_POST
, "ld1", ".8b", 1, false, 16 },
403 { AArch64::LD1Twov4h_POST
, "ld1", ".4h", 1, false, 16 },
404 { AArch64::LD1Twov2s_POST
, "ld1", ".2s", 1, false, 16 },
405 { AArch64::LD1Twov1d_POST
, "ld1", ".1d", 1, false, 16 },
406 { AArch64::LD1Threev16b
, "ld1", ".16b", 0, false, 0 },
407 { AArch64::LD1Threev8h
, "ld1", ".8h", 0, false, 0 },
408 { AArch64::LD1Threev4s
, "ld1", ".4s", 0, false, 0 },
409 { AArch64::LD1Threev2d
, "ld1", ".2d", 0, false, 0 },
410 { AArch64::LD1Threev8b
, "ld1", ".8b", 0, false, 0 },
411 { AArch64::LD1Threev4h
, "ld1", ".4h", 0, false, 0 },
412 { AArch64::LD1Threev2s
, "ld1", ".2s", 0, false, 0 },
413 { AArch64::LD1Threev1d
, "ld1", ".1d", 0, false, 0 },
414 { AArch64::LD1Threev16b_POST
, "ld1", ".16b", 1, false, 48 },
415 { AArch64::LD1Threev8h_POST
, "ld1", ".8h", 1, false, 48 },
416 { AArch64::LD1Threev4s_POST
, "ld1", ".4s", 1, false, 48 },
417 { AArch64::LD1Threev2d_POST
, "ld1", ".2d", 1, false, 48 },
418 { AArch64::LD1Threev8b_POST
, "ld1", ".8b", 1, false, 24 },
419 { AArch64::LD1Threev4h_POST
, "ld1", ".4h", 1, false, 24 },
420 { AArch64::LD1Threev2s_POST
, "ld1", ".2s", 1, false, 24 },
421 { AArch64::LD1Threev1d_POST
, "ld1", ".1d", 1, false, 24 },
422 { AArch64::LD1Fourv16b
, "ld1", ".16b", 0, false, 0 },
423 { AArch64::LD1Fourv8h
, "ld1", ".8h", 0, false, 0 },
424 { AArch64::LD1Fourv4s
, "ld1", ".4s", 0, false, 0 },
425 { AArch64::LD1Fourv2d
, "ld1", ".2d", 0, false, 0 },
426 { AArch64::LD1Fourv8b
, "ld1", ".8b", 0, false, 0 },
427 { AArch64::LD1Fourv4h
, "ld1", ".4h", 0, false, 0 },
428 { AArch64::LD1Fourv2s
, "ld1", ".2s", 0, false, 0 },
429 { AArch64::LD1Fourv1d
, "ld1", ".1d", 0, false, 0 },
430 { AArch64::LD1Fourv16b_POST
, "ld1", ".16b", 1, false, 64 },
431 { AArch64::LD1Fourv8h_POST
, "ld1", ".8h", 1, false, 64 },
432 { AArch64::LD1Fourv4s_POST
, "ld1", ".4s", 1, false, 64 },
433 { AArch64::LD1Fourv2d_POST
, "ld1", ".2d", 1, false, 64 },
434 { AArch64::LD1Fourv8b_POST
, "ld1", ".8b", 1, false, 32 },
435 { AArch64::LD1Fourv4h_POST
, "ld1", ".4h", 1, false, 32 },
436 { AArch64::LD1Fourv2s_POST
, "ld1", ".2s", 1, false, 32 },
437 { AArch64::LD1Fourv1d_POST
, "ld1", ".1d", 1, false, 32 },
438 { AArch64::LD2i8
, "ld2", ".b", 1, true, 0 },
439 { AArch64::LD2i16
, "ld2", ".h", 1, true, 0 },
440 { AArch64::LD2i32
, "ld2", ".s", 1, true, 0 },
441 { AArch64::LD2i64
, "ld2", ".d", 1, true, 0 },
442 { AArch64::LD2i8_POST
, "ld2", ".b", 2, true, 2 },
443 { AArch64::LD2i16_POST
, "ld2", ".h", 2, true, 4 },
444 { AArch64::LD2i32_POST
, "ld2", ".s", 2, true, 8 },
445 { AArch64::LD2i64_POST
, "ld2", ".d", 2, true, 16 },
446 { AArch64::LD2Rv16b
, "ld2r", ".16b", 0, false, 0 },
447 { AArch64::LD2Rv8h
, "ld2r", ".8h", 0, false, 0 },
448 { AArch64::LD2Rv4s
, "ld2r", ".4s", 0, false, 0 },
449 { AArch64::LD2Rv2d
, "ld2r", ".2d", 0, false, 0 },
450 { AArch64::LD2Rv8b
, "ld2r", ".8b", 0, false, 0 },
451 { AArch64::LD2Rv4h
, "ld2r", ".4h", 0, false, 0 },
452 { AArch64::LD2Rv2s
, "ld2r", ".2s", 0, false, 0 },
453 { AArch64::LD2Rv1d
, "ld2r", ".1d", 0, false, 0 },
454 { AArch64::LD2Rv16b_POST
, "ld2r", ".16b", 1, false, 2 },
455 { AArch64::LD2Rv8h_POST
, "ld2r", ".8h", 1, false, 4 },
456 { AArch64::LD2Rv4s_POST
, "ld2r", ".4s", 1, false, 8 },
457 { AArch64::LD2Rv2d_POST
, "ld2r", ".2d", 1, false, 16 },
458 { AArch64::LD2Rv8b_POST
, "ld2r", ".8b", 1, false, 2 },
459 { AArch64::LD2Rv4h_POST
, "ld2r", ".4h", 1, false, 4 },
460 { AArch64::LD2Rv2s_POST
, "ld2r", ".2s", 1, false, 8 },
461 { AArch64::LD2Rv1d_POST
, "ld2r", ".1d", 1, false, 16 },
462 { AArch64::LD2Twov16b
, "ld2", ".16b", 0, false, 0 },
463 { AArch64::LD2Twov8h
, "ld2", ".8h", 0, false, 0 },
464 { AArch64::LD2Twov4s
, "ld2", ".4s", 0, false, 0 },
465 { AArch64::LD2Twov2d
, "ld2", ".2d", 0, false, 0 },
466 { AArch64::LD2Twov8b
, "ld2", ".8b", 0, false, 0 },
467 { AArch64::LD2Twov4h
, "ld2", ".4h", 0, false, 0 },
468 { AArch64::LD2Twov2s
, "ld2", ".2s", 0, false, 0 },
469 { AArch64::LD2Twov16b_POST
, "ld2", ".16b", 1, false, 32 },
470 { AArch64::LD2Twov8h_POST
, "ld2", ".8h", 1, false, 32 },
471 { AArch64::LD2Twov4s_POST
, "ld2", ".4s", 1, false, 32 },
472 { AArch64::LD2Twov2d_POST
, "ld2", ".2d", 1, false, 32 },
473 { AArch64::LD2Twov8b_POST
, "ld2", ".8b", 1, false, 16 },
474 { AArch64::LD2Twov4h_POST
, "ld2", ".4h", 1, false, 16 },
475 { AArch64::LD2Twov2s_POST
, "ld2", ".2s", 1, false, 16 },
476 { AArch64::LD3i8
, "ld3", ".b", 1, true, 0 },
477 { AArch64::LD3i16
, "ld3", ".h", 1, true, 0 },
478 { AArch64::LD3i32
, "ld3", ".s", 1, true, 0 },
479 { AArch64::LD3i64
, "ld3", ".d", 1, true, 0 },
480 { AArch64::LD3i8_POST
, "ld3", ".b", 2, true, 3 },
481 { AArch64::LD3i16_POST
, "ld3", ".h", 2, true, 6 },
482 { AArch64::LD3i32_POST
, "ld3", ".s", 2, true, 12 },
483 { AArch64::LD3i64_POST
, "ld3", ".d", 2, true, 24 },
484 { AArch64::LD3Rv16b
, "ld3r", ".16b", 0, false, 0 },
485 { AArch64::LD3Rv8h
, "ld3r", ".8h", 0, false, 0 },
486 { AArch64::LD3Rv4s
, "ld3r", ".4s", 0, false, 0 },
487 { AArch64::LD3Rv2d
, "ld3r", ".2d", 0, false, 0 },
488 { AArch64::LD3Rv8b
, "ld3r", ".8b", 0, false, 0 },
489 { AArch64::LD3Rv4h
, "ld3r", ".4h", 0, false, 0 },
490 { AArch64::LD3Rv2s
, "ld3r", ".2s", 0, false, 0 },
491 { AArch64::LD3Rv1d
, "ld3r", ".1d", 0, false, 0 },
492 { AArch64::LD3Rv16b_POST
, "ld3r", ".16b", 1, false, 3 },
493 { AArch64::LD3Rv8h_POST
, "ld3r", ".8h", 1, false, 6 },
494 { AArch64::LD3Rv4s_POST
, "ld3r", ".4s", 1, false, 12 },
495 { AArch64::LD3Rv2d_POST
, "ld3r", ".2d", 1, false, 24 },
496 { AArch64::LD3Rv8b_POST
, "ld3r", ".8b", 1, false, 3 },
497 { AArch64::LD3Rv4h_POST
, "ld3r", ".4h", 1, false, 6 },
498 { AArch64::LD3Rv2s_POST
, "ld3r", ".2s", 1, false, 12 },
499 { AArch64::LD3Rv1d_POST
, "ld3r", ".1d", 1, false, 24 },
500 { AArch64::LD3Threev16b
, "ld3", ".16b", 0, false, 0 },
501 { AArch64::LD3Threev8h
, "ld3", ".8h", 0, false, 0 },
502 { AArch64::LD3Threev4s
, "ld3", ".4s", 0, false, 0 },
503 { AArch64::LD3Threev2d
, "ld3", ".2d", 0, false, 0 },
504 { AArch64::LD3Threev8b
, "ld3", ".8b", 0, false, 0 },
505 { AArch64::LD3Threev4h
, "ld3", ".4h", 0, false, 0 },
506 { AArch64::LD3Threev2s
, "ld3", ".2s", 0, false, 0 },
507 { AArch64::LD3Threev16b_POST
, "ld3", ".16b", 1, false, 48 },
508 { AArch64::LD3Threev8h_POST
, "ld3", ".8h", 1, false, 48 },
509 { AArch64::LD3Threev4s_POST
, "ld3", ".4s", 1, false, 48 },
510 { AArch64::LD3Threev2d_POST
, "ld3", ".2d", 1, false, 48 },
511 { AArch64::LD3Threev8b_POST
, "ld3", ".8b", 1, false, 24 },
512 { AArch64::LD3Threev4h_POST
, "ld3", ".4h", 1, false, 24 },
513 { AArch64::LD3Threev2s_POST
, "ld3", ".2s", 1, false, 24 },
514 { AArch64::LD4i8
, "ld4", ".b", 1, true, 0 },
515 { AArch64::LD4i16
, "ld4", ".h", 1, true, 0 },
516 { AArch64::LD4i32
, "ld4", ".s", 1, true, 0 },
517 { AArch64::LD4i64
, "ld4", ".d", 1, true, 0 },
518 { AArch64::LD4i8_POST
, "ld4", ".b", 2, true, 4 },
519 { AArch64::LD4i16_POST
, "ld4", ".h", 2, true, 8 },
520 { AArch64::LD4i32_POST
, "ld4", ".s", 2, true, 16 },
521 { AArch64::LD4i64_POST
, "ld4", ".d", 2, true, 32 },
522 { AArch64::LD4Rv16b
, "ld4r", ".16b", 0, false, 0 },
523 { AArch64::LD4Rv8h
, "ld4r", ".8h", 0, false, 0 },
524 { AArch64::LD4Rv4s
, "ld4r", ".4s", 0, false, 0 },
525 { AArch64::LD4Rv2d
, "ld4r", ".2d", 0, false, 0 },
526 { AArch64::LD4Rv8b
, "ld4r", ".8b", 0, false, 0 },
527 { AArch64::LD4Rv4h
, "ld4r", ".4h", 0, false, 0 },
528 { AArch64::LD4Rv2s
, "ld4r", ".2s", 0, false, 0 },
529 { AArch64::LD4Rv1d
, "ld4r", ".1d", 0, false, 0 },
530 { AArch64::LD4Rv16b_POST
, "ld4r", ".16b", 1, false, 4 },
531 { AArch64::LD4Rv8h_POST
, "ld4r", ".8h", 1, false, 8 },
532 { AArch64::LD4Rv4s_POST
, "ld4r", ".4s", 1, false, 16 },
533 { AArch64::LD4Rv2d_POST
, "ld4r", ".2d", 1, false, 32 },
534 { AArch64::LD4Rv8b_POST
, "ld4r", ".8b", 1, false, 4 },
535 { AArch64::LD4Rv4h_POST
, "ld4r", ".4h", 1, false, 8 },
536 { AArch64::LD4Rv2s_POST
, "ld4r", ".2s", 1, false, 16 },
537 { AArch64::LD4Rv1d_POST
, "ld4r", ".1d", 1, false, 32 },
538 { AArch64::LD4Fourv16b
, "ld4", ".16b", 0, false, 0 },
539 { AArch64::LD4Fourv8h
, "ld4", ".8h", 0, false, 0 },
540 { AArch64::LD4Fourv4s
, "ld4", ".4s", 0, false, 0 },
541 { AArch64::LD4Fourv2d
, "ld4", ".2d", 0, false, 0 },
542 { AArch64::LD4Fourv8b
, "ld4", ".8b", 0, false, 0 },
543 { AArch64::LD4Fourv4h
, "ld4", ".4h", 0, false, 0 },
544 { AArch64::LD4Fourv2s
, "ld4", ".2s", 0, false, 0 },
545 { AArch64::LD4Fourv16b_POST
, "ld4", ".16b", 1, false, 64 },
546 { AArch64::LD4Fourv8h_POST
, "ld4", ".8h", 1, false, 64 },
547 { AArch64::LD4Fourv4s_POST
, "ld4", ".4s", 1, false, 64 },
548 { AArch64::LD4Fourv2d_POST
, "ld4", ".2d", 1, false, 64 },
549 { AArch64::LD4Fourv8b_POST
, "ld4", ".8b", 1, false, 32 },
550 { AArch64::LD4Fourv4h_POST
, "ld4", ".4h", 1, false, 32 },
551 { AArch64::LD4Fourv2s_POST
, "ld4", ".2s", 1, false, 32 },
552 { AArch64::ST1i8
, "st1", ".b", 0, true, 0 },
553 { AArch64::ST1i16
, "st1", ".h", 0, true, 0 },
554 { AArch64::ST1i32
, "st1", ".s", 0, true, 0 },
555 { AArch64::ST1i64
, "st1", ".d", 0, true, 0 },
556 { AArch64::ST1i8_POST
, "st1", ".b", 1, true, 1 },
557 { AArch64::ST1i16_POST
, "st1", ".h", 1, true, 2 },
558 { AArch64::ST1i32_POST
, "st1", ".s", 1, true, 4 },
559 { AArch64::ST1i64_POST
, "st1", ".d", 1, true, 8 },
560 { AArch64::ST1Onev16b
, "st1", ".16b", 0, false, 0 },
561 { AArch64::ST1Onev8h
, "st1", ".8h", 0, false, 0 },
562 { AArch64::ST1Onev4s
, "st1", ".4s", 0, false, 0 },
563 { AArch64::ST1Onev2d
, "st1", ".2d", 0, false, 0 },
564 { AArch64::ST1Onev8b
, "st1", ".8b", 0, false, 0 },
565 { AArch64::ST1Onev4h
, "st1", ".4h", 0, false, 0 },
566 { AArch64::ST1Onev2s
, "st1", ".2s", 0, false, 0 },
567 { AArch64::ST1Onev1d
, "st1", ".1d", 0, false, 0 },
568 { AArch64::ST1Onev16b_POST
, "st1", ".16b", 1, false, 16 },
569 { AArch64::ST1Onev8h_POST
, "st1", ".8h", 1, false, 16 },
570 { AArch64::ST1Onev4s_POST
, "st1", ".4s", 1, false, 16 },
571 { AArch64::ST1Onev2d_POST
, "st1", ".2d", 1, false, 16 },
572 { AArch64::ST1Onev8b_POST
, "st1", ".8b", 1, false, 8 },
573 { AArch64::ST1Onev4h_POST
, "st1", ".4h", 1, false, 8 },
574 { AArch64::ST1Onev2s_POST
, "st1", ".2s", 1, false, 8 },
575 { AArch64::ST1Onev1d_POST
, "st1", ".1d", 1, false, 8 },
576 { AArch64::ST1Twov16b
, "st1", ".16b", 0, false, 0 },
577 { AArch64::ST1Twov8h
, "st1", ".8h", 0, false, 0 },
578 { AArch64::ST1Twov4s
, "st1", ".4s", 0, false, 0 },
579 { AArch64::ST1Twov2d
, "st1", ".2d", 0, false, 0 },
580 { AArch64::ST1Twov8b
, "st1", ".8b", 0, false, 0 },
581 { AArch64::ST1Twov4h
, "st1", ".4h", 0, false, 0 },
582 { AArch64::ST1Twov2s
, "st1", ".2s", 0, false, 0 },
583 { AArch64::ST1Twov1d
, "st1", ".1d", 0, false, 0 },
584 { AArch64::ST1Twov16b_POST
, "st1", ".16b", 1, false, 32 },
585 { AArch64::ST1Twov8h_POST
, "st1", ".8h", 1, false, 32 },
586 { AArch64::ST1Twov4s_POST
, "st1", ".4s", 1, false, 32 },
587 { AArch64::ST1Twov2d_POST
, "st1", ".2d", 1, false, 32 },
588 { AArch64::ST1Twov8b_POST
, "st1", ".8b", 1, false, 16 },
589 { AArch64::ST1Twov4h_POST
, "st1", ".4h", 1, false, 16 },
590 { AArch64::ST1Twov2s_POST
, "st1", ".2s", 1, false, 16 },
591 { AArch64::ST1Twov1d_POST
, "st1", ".1d", 1, false, 16 },
592 { AArch64::ST1Threev16b
, "st1", ".16b", 0, false, 0 },
593 { AArch64::ST1Threev8h
, "st1", ".8h", 0, false, 0 },
594 { AArch64::ST1Threev4s
, "st1", ".4s", 0, false, 0 },
595 { AArch64::ST1Threev2d
, "st1", ".2d", 0, false, 0 },
596 { AArch64::ST1Threev8b
, "st1", ".8b", 0, false, 0 },
597 { AArch64::ST1Threev4h
, "st1", ".4h", 0, false, 0 },
598 { AArch64::ST1Threev2s
, "st1", ".2s", 0, false, 0 },
599 { AArch64::ST1Threev1d
, "st1", ".1d", 0, false, 0 },
600 { AArch64::ST1Threev16b_POST
, "st1", ".16b", 1, false, 48 },
601 { AArch64::ST1Threev8h_POST
, "st1", ".8h", 1, false, 48 },
602 { AArch64::ST1Threev4s_POST
, "st1", ".4s", 1, false, 48 },
603 { AArch64::ST1Threev2d_POST
, "st1", ".2d", 1, false, 48 },
604 { AArch64::ST1Threev8b_POST
, "st1", ".8b", 1, false, 24 },
605 { AArch64::ST1Threev4h_POST
, "st1", ".4h", 1, false, 24 },
606 { AArch64::ST1Threev2s_POST
, "st1", ".2s", 1, false, 24 },
607 { AArch64::ST1Threev1d_POST
, "st1", ".1d", 1, false, 24 },
608 { AArch64::ST1Fourv16b
, "st1", ".16b", 0, false, 0 },
609 { AArch64::ST1Fourv8h
, "st1", ".8h", 0, false, 0 },
610 { AArch64::ST1Fourv4s
, "st1", ".4s", 0, false, 0 },
611 { AArch64::ST1Fourv2d
, "st1", ".2d", 0, false, 0 },
612 { AArch64::ST1Fourv8b
, "st1", ".8b", 0, false, 0 },
613 { AArch64::ST1Fourv4h
, "st1", ".4h", 0, false, 0 },
614 { AArch64::ST1Fourv2s
, "st1", ".2s", 0, false, 0 },
615 { AArch64::ST1Fourv1d
, "st1", ".1d", 0, false, 0 },
616 { AArch64::ST1Fourv16b_POST
, "st1", ".16b", 1, false, 64 },
617 { AArch64::ST1Fourv8h_POST
, "st1", ".8h", 1, false, 64 },
618 { AArch64::ST1Fourv4s_POST
, "st1", ".4s", 1, false, 64 },
619 { AArch64::ST1Fourv2d_POST
, "st1", ".2d", 1, false, 64 },
620 { AArch64::ST1Fourv8b_POST
, "st1", ".8b", 1, false, 32 },
621 { AArch64::ST1Fourv4h_POST
, "st1", ".4h", 1, false, 32 },
622 { AArch64::ST1Fourv2s_POST
, "st1", ".2s", 1, false, 32 },
623 { AArch64::ST1Fourv1d_POST
, "st1", ".1d", 1, false, 32 },
624 { AArch64::ST2i8
, "st2", ".b", 0, true, 0 },
625 { AArch64::ST2i16
, "st2", ".h", 0, true, 0 },
626 { AArch64::ST2i32
, "st2", ".s", 0, true, 0 },
627 { AArch64::ST2i64
, "st2", ".d", 0, true, 0 },
628 { AArch64::ST2i8_POST
, "st2", ".b", 1, true, 2 },
629 { AArch64::ST2i16_POST
, "st2", ".h", 1, true, 4 },
630 { AArch64::ST2i32_POST
, "st2", ".s", 1, true, 8 },
631 { AArch64::ST2i64_POST
, "st2", ".d", 1, true, 16 },
632 { AArch64::ST2Twov16b
, "st2", ".16b", 0, false, 0 },
633 { AArch64::ST2Twov8h
, "st2", ".8h", 0, false, 0 },
634 { AArch64::ST2Twov4s
, "st2", ".4s", 0, false, 0 },
635 { AArch64::ST2Twov2d
, "st2", ".2d", 0, false, 0 },
636 { AArch64::ST2Twov8b
, "st2", ".8b", 0, false, 0 },
637 { AArch64::ST2Twov4h
, "st2", ".4h", 0, false, 0 },
638 { AArch64::ST2Twov2s
, "st2", ".2s", 0, false, 0 },
639 { AArch64::ST2Twov16b_POST
, "st2", ".16b", 1, false, 32 },
640 { AArch64::ST2Twov8h_POST
, "st2", ".8h", 1, false, 32 },
641 { AArch64::ST2Twov4s_POST
, "st2", ".4s", 1, false, 32 },
642 { AArch64::ST2Twov2d_POST
, "st2", ".2d", 1, false, 32 },
643 { AArch64::ST2Twov8b_POST
, "st2", ".8b", 1, false, 16 },
644 { AArch64::ST2Twov4h_POST
, "st2", ".4h", 1, false, 16 },
645 { AArch64::ST2Twov2s_POST
, "st2", ".2s", 1, false, 16 },
646 { AArch64::ST3i8
, "st3", ".b", 0, true, 0 },
647 { AArch64::ST3i16
, "st3", ".h", 0, true, 0 },
648 { AArch64::ST3i32
, "st3", ".s", 0, true, 0 },
649 { AArch64::ST3i64
, "st3", ".d", 0, true, 0 },
650 { AArch64::ST3i8_POST
, "st3", ".b", 1, true, 3 },
651 { AArch64::ST3i16_POST
, "st3", ".h", 1, true, 6 },
652 { AArch64::ST3i32_POST
, "st3", ".s", 1, true, 12 },
653 { AArch64::ST3i64_POST
, "st3", ".d", 1, true, 24 },
654 { AArch64::ST3Threev16b
, "st3", ".16b", 0, false, 0 },
655 { AArch64::ST3Threev8h
, "st3", ".8h", 0, false, 0 },
656 { AArch64::ST3Threev4s
, "st3", ".4s", 0, false, 0 },
657 { AArch64::ST3Threev2d
, "st3", ".2d", 0, false, 0 },
658 { AArch64::ST3Threev8b
, "st3", ".8b", 0, false, 0 },
659 { AArch64::ST3Threev4h
, "st3", ".4h", 0, false, 0 },
660 { AArch64::ST3Threev2s
, "st3", ".2s", 0, false, 0 },
661 { AArch64::ST3Threev16b_POST
, "st3", ".16b", 1, false, 48 },
662 { AArch64::ST3Threev8h_POST
, "st3", ".8h", 1, false, 48 },
663 { AArch64::ST3Threev4s_POST
, "st3", ".4s", 1, false, 48 },
664 { AArch64::ST3Threev2d_POST
, "st3", ".2d", 1, false, 48 },
665 { AArch64::ST3Threev8b_POST
, "st3", ".8b", 1, false, 24 },
666 { AArch64::ST3Threev4h_POST
, "st3", ".4h", 1, false, 24 },
667 { AArch64::ST3Threev2s_POST
, "st3", ".2s", 1, false, 24 },
668 { AArch64::ST4i8
, "st4", ".b", 0, true, 0 },
669 { AArch64::ST4i16
, "st4", ".h", 0, true, 0 },
670 { AArch64::ST4i32
, "st4", ".s", 0, true, 0 },
671 { AArch64::ST4i64
, "st4", ".d", 0, true, 0 },
672 { AArch64::ST4i8_POST
, "st4", ".b", 1, true, 4 },
673 { AArch64::ST4i16_POST
, "st4", ".h", 1, true, 8 },
674 { AArch64::ST4i32_POST
, "st4", ".s", 1, true, 16 },
675 { AArch64::ST4i64_POST
, "st4", ".d", 1, true, 32 },
676 { AArch64::ST4Fourv16b
, "st4", ".16b", 0, false, 0 },
677 { AArch64::ST4Fourv8h
, "st4", ".8h", 0, false, 0 },
678 { AArch64::ST4Fourv4s
, "st4", ".4s", 0, false, 0 },
679 { AArch64::ST4Fourv2d
, "st4", ".2d", 0, false, 0 },
680 { AArch64::ST4Fourv8b
, "st4", ".8b", 0, false, 0 },
681 { AArch64::ST4Fourv4h
, "st4", ".4h", 0, false, 0 },
682 { AArch64::ST4Fourv2s
, "st4", ".2s", 0, false, 0 },
683 { AArch64::ST4Fourv16b_POST
, "st4", ".16b", 1, false, 64 },
684 { AArch64::ST4Fourv8h_POST
, "st4", ".8h", 1, false, 64 },
685 { AArch64::ST4Fourv4s_POST
, "st4", ".4s", 1, false, 64 },
686 { AArch64::ST4Fourv2d_POST
, "st4", ".2d", 1, false, 64 },
687 { AArch64::ST4Fourv8b_POST
, "st4", ".8b", 1, false, 32 },
688 { AArch64::ST4Fourv4h_POST
, "st4", ".4h", 1, false, 32 },
689 { AArch64::ST4Fourv2s_POST
, "st4", ".2s", 1, false, 32 },
692 static const LdStNInstrDesc
*getLdStNInstrDesc(unsigned Opcode
) {
694 for (Idx
= 0; Idx
!= array_lengthof(LdStNInstInfo
); ++Idx
)
695 if (LdStNInstInfo
[Idx
].Opcode
== Opcode
)
696 return &LdStNInstInfo
[Idx
];
701 void AArch64AppleInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&O
,
703 const MCSubtargetInfo
&STI
) {
704 unsigned Opcode
= MI
->getOpcode();
708 if (isTblTbxInstruction(MI
->getOpcode(), Layout
, IsTbx
)) {
709 O
<< "\t" << (IsTbx
? "tbx" : "tbl") << Layout
<< '\t'
710 << getRegisterName(MI
->getOperand(0).getReg(), AArch64::vreg
) << ", ";
712 unsigned ListOpNum
= IsTbx
? 2 : 1;
713 printVectorList(MI
, ListOpNum
, STI
, O
, "");
716 << getRegisterName(MI
->getOperand(ListOpNum
+ 1).getReg(), AArch64::vreg
);
717 printAnnotation(O
, Annot
);
721 if (const LdStNInstrDesc
*LdStDesc
= getLdStNInstrDesc(Opcode
)) {
722 O
<< "\t" << LdStDesc
->Mnemonic
<< LdStDesc
->Layout
<< '\t';
724 // Now onto the operands: first a vector list with possible lane
725 // specifier. E.g. { v0 }[2]
726 int OpNum
= LdStDesc
->ListOperand
;
727 printVectorList(MI
, OpNum
++, STI
, O
, "");
729 if (LdStDesc
->HasLane
)
730 O
<< '[' << MI
->getOperand(OpNum
++).getImm() << ']';
732 // Next the address: [xN]
733 unsigned AddrReg
= MI
->getOperand(OpNum
++).getReg();
734 O
<< ", [" << getRegisterName(AddrReg
) << ']';
736 // Finally, there might be a post-indexed offset.
737 if (LdStDesc
->NaturalOffset
!= 0) {
738 unsigned Reg
= MI
->getOperand(OpNum
++).getReg();
739 if (Reg
!= AArch64::XZR
)
740 O
<< ", " << getRegisterName(Reg
);
742 assert(LdStDesc
->NaturalOffset
&& "no offset on post-inc instruction?");
743 O
<< ", #" << LdStDesc
->NaturalOffset
;
747 printAnnotation(O
, Annot
);
751 AArch64InstPrinter::printInst(MI
, O
, Annot
, STI
);
754 bool AArch64InstPrinter::printSysAlias(const MCInst
*MI
,
755 const MCSubtargetInfo
&STI
,
758 unsigned Opcode
= MI
->getOpcode();
759 assert(Opcode
== AArch64::SYSxt
&& "Invalid opcode for SYS alias!");
762 const MCOperand
&Op1
= MI
->getOperand(0);
763 const MCOperand
&Cn
= MI
->getOperand(1);
764 const MCOperand
&Cm
= MI
->getOperand(2);
765 const MCOperand
&Op2
= MI
->getOperand(3);
767 unsigned Op1Val
= Op1
.getImm();
768 unsigned CnVal
= Cn
.getImm();
769 unsigned CmVal
= Cm
.getImm();
770 unsigned Op2Val
= Op2
.getImm();
772 uint16_t Encoding
= Op2Val
;
773 Encoding
|= CmVal
<< 3;
774 Encoding
|= CnVal
<< 7;
775 Encoding
|= Op1Val
<< 11;
783 default: return false;
784 // Maybe IC, maybe Prediction Restriction
787 default: return false;
788 case 0: goto Search_IC
;
789 case 3: goto Search_PRCTX
;
791 // Prediction Restriction aliases
794 const AArch64PRCTX::PRCTX
*PRCTX
= AArch64PRCTX::lookupPRCTXByEncoding(Encoding
>> 3);
795 if (!PRCTX
|| !PRCTX
->haveFeatures(STI
.getFeatureBits()))
798 NeedsReg
= PRCTX
->NeedsReg
;
800 default: return false;
801 case 4: Ins
= "cfp\t"; break;
802 case 5: Ins
= "dvp\t"; break;
803 case 7: Ins
= "cpp\t"; break;
805 Name
= std::string(PRCTX
->Name
);
811 const AArch64IC::IC
*IC
= AArch64IC::lookupICByEncoding(Encoding
);
812 if (!IC
|| !IC
->haveFeatures(STI
.getFeatureBits()))
815 NeedsReg
= IC
->NeedsReg
;
817 Name
= std::string(IC
->Name
);
821 case 4: case 6: case 10: case 11: case 12: case 13: case 14:
823 const AArch64DC::DC
*DC
= AArch64DC::lookupDCByEncoding(Encoding
);
824 if (!DC
|| !DC
->haveFeatures(STI
.getFeatureBits()))
829 Name
= std::string(DC
->Name
);
834 const AArch64AT::AT
*AT
= AArch64AT::lookupATByEncoding(Encoding
);
835 if (!AT
|| !AT
->haveFeatures(STI
.getFeatureBits()))
840 Name
= std::string(AT
->Name
);
844 } else if (CnVal
== 8) {
846 const AArch64TLBI::TLBI
*TLBI
= AArch64TLBI::lookupTLBIByEncoding(Encoding
);
847 if (!TLBI
|| !TLBI
->haveFeatures(STI
.getFeatureBits()))
850 NeedsReg
= TLBI
->NeedsReg
;
852 Name
= std::string(TLBI
->Name
);
857 std::string Str
= Ins
+ Name
;
858 std::transform(Str
.begin(), Str
.end(), Str
.begin(), ::tolower
);
862 O
<< ", " << getRegisterName(MI
->getOperand(4).getReg());
867 void AArch64InstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
868 const MCSubtargetInfo
&STI
,
870 const MCOperand
&Op
= MI
->getOperand(OpNo
);
872 unsigned Reg
= Op
.getReg();
873 O
<< getRegisterName(Reg
);
874 } else if (Op
.isImm()) {
875 printImm(MI
, OpNo
, STI
, O
);
877 assert(Op
.isExpr() && "unknown operand kind in printOperand");
878 Op
.getExpr()->print(O
, &MAI
);
882 void AArch64InstPrinter::printImm(const MCInst
*MI
, unsigned OpNo
,
883 const MCSubtargetInfo
&STI
,
885 const MCOperand
&Op
= MI
->getOperand(OpNo
);
886 O
<< "#" << formatImm(Op
.getImm());
889 void AArch64InstPrinter::printImmHex(const MCInst
*MI
, unsigned OpNo
,
890 const MCSubtargetInfo
&STI
,
892 const MCOperand
&Op
= MI
->getOperand(OpNo
);
893 O
<< format("#%#llx", Op
.getImm());
896 void AArch64InstPrinter::printPostIncOperand(const MCInst
*MI
, unsigned OpNo
,
897 unsigned Imm
, raw_ostream
&O
) {
898 const MCOperand
&Op
= MI
->getOperand(OpNo
);
900 unsigned Reg
= Op
.getReg();
901 if (Reg
== AArch64::XZR
)
904 O
<< getRegisterName(Reg
);
906 llvm_unreachable("unknown operand kind in printPostIncOperand64");
909 void AArch64InstPrinter::printVRegOperand(const MCInst
*MI
, unsigned OpNo
,
910 const MCSubtargetInfo
&STI
,
912 const MCOperand
&Op
= MI
->getOperand(OpNo
);
913 assert(Op
.isReg() && "Non-register vreg operand!");
914 unsigned Reg
= Op
.getReg();
915 O
<< getRegisterName(Reg
, AArch64::vreg
);
918 void AArch64InstPrinter::printSysCROperand(const MCInst
*MI
, unsigned OpNo
,
919 const MCSubtargetInfo
&STI
,
921 const MCOperand
&Op
= MI
->getOperand(OpNo
);
922 assert(Op
.isImm() && "System instruction C[nm] operands must be immediates!");
923 O
<< "c" << Op
.getImm();
926 void AArch64InstPrinter::printAddSubImm(const MCInst
*MI
, unsigned OpNum
,
927 const MCSubtargetInfo
&STI
,
929 const MCOperand
&MO
= MI
->getOperand(OpNum
);
931 unsigned Val
= (MO
.getImm() & 0xfff);
932 assert(Val
== MO
.getImm() && "Add/sub immediate out of range!");
934 AArch64_AM::getShiftValue(MI
->getOperand(OpNum
+ 1).getImm());
935 O
<< '#' << formatImm(Val
);
937 printShifter(MI
, OpNum
+ 1, STI
, O
);
940 *CommentStream
<< '=' << formatImm(Val
<< Shift
) << '\n';
942 assert(MO
.isExpr() && "Unexpected operand type!");
943 MO
.getExpr()->print(O
, &MAI
);
944 printShifter(MI
, OpNum
+ 1, STI
, O
);
948 template <typename T
>
949 void AArch64InstPrinter::printLogicalImm(const MCInst
*MI
, unsigned OpNum
,
950 const MCSubtargetInfo
&STI
,
952 uint64_t Val
= MI
->getOperand(OpNum
).getImm();
954 O
.write_hex(AArch64_AM::decodeLogicalImmediate(Val
, 8 * sizeof(T
)));
957 void AArch64InstPrinter::printShifter(const MCInst
*MI
, unsigned OpNum
,
958 const MCSubtargetInfo
&STI
,
960 unsigned Val
= MI
->getOperand(OpNum
).getImm();
961 // LSL #0 should not be printed.
962 if (AArch64_AM::getShiftType(Val
) == AArch64_AM::LSL
&&
963 AArch64_AM::getShiftValue(Val
) == 0)
965 O
<< ", " << AArch64_AM::getShiftExtendName(AArch64_AM::getShiftType(Val
))
966 << " #" << AArch64_AM::getShiftValue(Val
);
969 void AArch64InstPrinter::printShiftedRegister(const MCInst
*MI
, unsigned OpNum
,
970 const MCSubtargetInfo
&STI
,
972 O
<< getRegisterName(MI
->getOperand(OpNum
).getReg());
973 printShifter(MI
, OpNum
+ 1, STI
, O
);
976 void AArch64InstPrinter::printExtendedRegister(const MCInst
*MI
, unsigned OpNum
,
977 const MCSubtargetInfo
&STI
,
979 O
<< getRegisterName(MI
->getOperand(OpNum
).getReg());
980 printArithExtend(MI
, OpNum
+ 1, STI
, O
);
983 void AArch64InstPrinter::printArithExtend(const MCInst
*MI
, unsigned OpNum
,
984 const MCSubtargetInfo
&STI
,
986 unsigned Val
= MI
->getOperand(OpNum
).getImm();
987 AArch64_AM::ShiftExtendType ExtType
= AArch64_AM::getArithExtendType(Val
);
988 unsigned ShiftVal
= AArch64_AM::getArithShiftValue(Val
);
990 // If the destination or first source register operand is [W]SP, print
991 // UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
993 if (ExtType
== AArch64_AM::UXTW
|| ExtType
== AArch64_AM::UXTX
) {
994 unsigned Dest
= MI
->getOperand(0).getReg();
995 unsigned Src1
= MI
->getOperand(1).getReg();
996 if ( ((Dest
== AArch64::SP
|| Src1
== AArch64::SP
) &&
997 ExtType
== AArch64_AM::UXTX
) ||
998 ((Dest
== AArch64::WSP
|| Src1
== AArch64::WSP
) &&
999 ExtType
== AArch64_AM::UXTW
) ) {
1001 O
<< ", lsl #" << ShiftVal
;
1005 O
<< ", " << AArch64_AM::getShiftExtendName(ExtType
);
1007 O
<< " #" << ShiftVal
;
1010 static void printMemExtendImpl(bool SignExtend
, bool DoShift
,
1011 unsigned Width
, char SrcRegKind
,
1013 // sxtw, sxtx, uxtw or lsl (== uxtx)
1014 bool IsLSL
= !SignExtend
&& SrcRegKind
== 'x';
1018 O
<< (SignExtend
? 's' : 'u') << "xt" << SrcRegKind
;
1020 if (DoShift
|| IsLSL
)
1021 O
<< " #" << Log2_32(Width
/ 8);
1024 void AArch64InstPrinter::printMemExtend(const MCInst
*MI
, unsigned OpNum
,
1025 raw_ostream
&O
, char SrcRegKind
,
1027 bool SignExtend
= MI
->getOperand(OpNum
).getImm();
1028 bool DoShift
= MI
->getOperand(OpNum
+ 1).getImm();
1029 printMemExtendImpl(SignExtend
, DoShift
, Width
, SrcRegKind
, O
);
1032 template <bool SignExtend
, int ExtWidth
, char SrcRegKind
, char Suffix
>
1033 void AArch64InstPrinter::printRegWithShiftExtend(const MCInst
*MI
,
1035 const MCSubtargetInfo
&STI
,
1037 printOperand(MI
, OpNum
, STI
, O
);
1038 if (Suffix
== 's' || Suffix
== 'd')
1041 assert(Suffix
== 0 && "Unsupported suffix size");
1043 bool DoShift
= ExtWidth
!= 8;
1044 if (SignExtend
|| DoShift
|| SrcRegKind
== 'w') {
1046 printMemExtendImpl(SignExtend
, DoShift
, ExtWidth
, SrcRegKind
, O
);
1050 void AArch64InstPrinter::printCondCode(const MCInst
*MI
, unsigned OpNum
,
1051 const MCSubtargetInfo
&STI
,
1053 AArch64CC::CondCode CC
= (AArch64CC::CondCode
)MI
->getOperand(OpNum
).getImm();
1054 O
<< AArch64CC::getCondCodeName(CC
);
1057 void AArch64InstPrinter::printInverseCondCode(const MCInst
*MI
, unsigned OpNum
,
1058 const MCSubtargetInfo
&STI
,
1060 AArch64CC::CondCode CC
= (AArch64CC::CondCode
)MI
->getOperand(OpNum
).getImm();
1061 O
<< AArch64CC::getCondCodeName(AArch64CC::getInvertedCondCode(CC
));
1064 void AArch64InstPrinter::printAMNoIndex(const MCInst
*MI
, unsigned OpNum
,
1065 const MCSubtargetInfo
&STI
,
1067 O
<< '[' << getRegisterName(MI
->getOperand(OpNum
).getReg()) << ']';
1071 void AArch64InstPrinter::printImmScale(const MCInst
*MI
, unsigned OpNum
,
1072 const MCSubtargetInfo
&STI
,
1074 O
<< '#' << formatImm(Scale
* MI
->getOperand(OpNum
).getImm());
1077 void AArch64InstPrinter::printUImm12Offset(const MCInst
*MI
, unsigned OpNum
,
1078 unsigned Scale
, raw_ostream
&O
) {
1079 const MCOperand MO
= MI
->getOperand(OpNum
);
1081 O
<< "#" << formatImm(MO
.getImm() * Scale
);
1083 assert(MO
.isExpr() && "Unexpected operand type!");
1084 MO
.getExpr()->print(O
, &MAI
);
1088 void AArch64InstPrinter::printAMIndexedWB(const MCInst
*MI
, unsigned OpNum
,
1089 unsigned Scale
, raw_ostream
&O
) {
1090 const MCOperand MO1
= MI
->getOperand(OpNum
+ 1);
1091 O
<< '[' << getRegisterName(MI
->getOperand(OpNum
).getReg());
1093 O
<< ", #" << formatImm(MO1
.getImm() * Scale
);
1095 assert(MO1
.isExpr() && "Unexpected operand type!");
1097 MO1
.getExpr()->print(O
, &MAI
);
1102 template <bool IsSVEPrefetch
>
1103 void AArch64InstPrinter::printPrefetchOp(const MCInst
*MI
, unsigned OpNum
,
1104 const MCSubtargetInfo
&STI
,
1106 unsigned prfop
= MI
->getOperand(OpNum
).getImm();
1107 if (IsSVEPrefetch
) {
1108 if (auto PRFM
= AArch64SVEPRFM::lookupSVEPRFMByEncoding(prfop
)) {
1112 } else if (auto PRFM
= AArch64PRFM::lookupPRFMByEncoding(prfop
)) {
1117 O
<< '#' << formatImm(prfop
);
1120 void AArch64InstPrinter::printPSBHintOp(const MCInst
*MI
, unsigned OpNum
,
1121 const MCSubtargetInfo
&STI
,
1123 unsigned psbhintop
= MI
->getOperand(OpNum
).getImm();
1124 auto PSB
= AArch64PSBHint::lookupPSBByEncoding(psbhintop
);
1128 O
<< '#' << formatImm(psbhintop
);
1131 void AArch64InstPrinter::printBTIHintOp(const MCInst
*MI
, unsigned OpNum
,
1132 const MCSubtargetInfo
&STI
,
1134 unsigned btihintop
= (MI
->getOperand(OpNum
).getImm() ^ 32) >> 1;
1135 auto BTI
= AArch64BTIHint::lookupBTIByEncoding(btihintop
);
1139 O
<< '#' << formatImm(btihintop
);
1142 void AArch64InstPrinter::printFPImmOperand(const MCInst
*MI
, unsigned OpNum
,
1143 const MCSubtargetInfo
&STI
,
1145 const MCOperand
&MO
= MI
->getOperand(OpNum
);
1147 MO
.isFPImm() ? MO
.getFPImm() : AArch64_AM::getFPImmFloat(MO
.getImm());
1149 // 8 decimal places are enough to perfectly represent permitted floats.
1150 O
<< format("#%.8f", FPImm
);
1153 static unsigned getNextVectorRegister(unsigned Reg
, unsigned Stride
= 1) {
1157 llvm_unreachable("Vector register expected!");
1158 case AArch64::Q0
: Reg
= AArch64::Q1
; break;
1159 case AArch64::Q1
: Reg
= AArch64::Q2
; break;
1160 case AArch64::Q2
: Reg
= AArch64::Q3
; break;
1161 case AArch64::Q3
: Reg
= AArch64::Q4
; break;
1162 case AArch64::Q4
: Reg
= AArch64::Q5
; break;
1163 case AArch64::Q5
: Reg
= AArch64::Q6
; break;
1164 case AArch64::Q6
: Reg
= AArch64::Q7
; break;
1165 case AArch64::Q7
: Reg
= AArch64::Q8
; break;
1166 case AArch64::Q8
: Reg
= AArch64::Q9
; break;
1167 case AArch64::Q9
: Reg
= AArch64::Q10
; break;
1168 case AArch64::Q10
: Reg
= AArch64::Q11
; break;
1169 case AArch64::Q11
: Reg
= AArch64::Q12
; break;
1170 case AArch64::Q12
: Reg
= AArch64::Q13
; break;
1171 case AArch64::Q13
: Reg
= AArch64::Q14
; break;
1172 case AArch64::Q14
: Reg
= AArch64::Q15
; break;
1173 case AArch64::Q15
: Reg
= AArch64::Q16
; break;
1174 case AArch64::Q16
: Reg
= AArch64::Q17
; break;
1175 case AArch64::Q17
: Reg
= AArch64::Q18
; break;
1176 case AArch64::Q18
: Reg
= AArch64::Q19
; break;
1177 case AArch64::Q19
: Reg
= AArch64::Q20
; break;
1178 case AArch64::Q20
: Reg
= AArch64::Q21
; break;
1179 case AArch64::Q21
: Reg
= AArch64::Q22
; break;
1180 case AArch64::Q22
: Reg
= AArch64::Q23
; break;
1181 case AArch64::Q23
: Reg
= AArch64::Q24
; break;
1182 case AArch64::Q24
: Reg
= AArch64::Q25
; break;
1183 case AArch64::Q25
: Reg
= AArch64::Q26
; break;
1184 case AArch64::Q26
: Reg
= AArch64::Q27
; break;
1185 case AArch64::Q27
: Reg
= AArch64::Q28
; break;
1186 case AArch64::Q28
: Reg
= AArch64::Q29
; break;
1187 case AArch64::Q29
: Reg
= AArch64::Q30
; break;
1188 case AArch64::Q30
: Reg
= AArch64::Q31
; break;
1189 // Vector lists can wrap around.
1193 case AArch64::Z0
: Reg
= AArch64::Z1
; break;
1194 case AArch64::Z1
: Reg
= AArch64::Z2
; break;
1195 case AArch64::Z2
: Reg
= AArch64::Z3
; break;
1196 case AArch64::Z3
: Reg
= AArch64::Z4
; break;
1197 case AArch64::Z4
: Reg
= AArch64::Z5
; break;
1198 case AArch64::Z5
: Reg
= AArch64::Z6
; break;
1199 case AArch64::Z6
: Reg
= AArch64::Z7
; break;
1200 case AArch64::Z7
: Reg
= AArch64::Z8
; break;
1201 case AArch64::Z8
: Reg
= AArch64::Z9
; break;
1202 case AArch64::Z9
: Reg
= AArch64::Z10
; break;
1203 case AArch64::Z10
: Reg
= AArch64::Z11
; break;
1204 case AArch64::Z11
: Reg
= AArch64::Z12
; break;
1205 case AArch64::Z12
: Reg
= AArch64::Z13
; break;
1206 case AArch64::Z13
: Reg
= AArch64::Z14
; break;
1207 case AArch64::Z14
: Reg
= AArch64::Z15
; break;
1208 case AArch64::Z15
: Reg
= AArch64::Z16
; break;
1209 case AArch64::Z16
: Reg
= AArch64::Z17
; break;
1210 case AArch64::Z17
: Reg
= AArch64::Z18
; break;
1211 case AArch64::Z18
: Reg
= AArch64::Z19
; break;
1212 case AArch64::Z19
: Reg
= AArch64::Z20
; break;
1213 case AArch64::Z20
: Reg
= AArch64::Z21
; break;
1214 case AArch64::Z21
: Reg
= AArch64::Z22
; break;
1215 case AArch64::Z22
: Reg
= AArch64::Z23
; break;
1216 case AArch64::Z23
: Reg
= AArch64::Z24
; break;
1217 case AArch64::Z24
: Reg
= AArch64::Z25
; break;
1218 case AArch64::Z25
: Reg
= AArch64::Z26
; break;
1219 case AArch64::Z26
: Reg
= AArch64::Z27
; break;
1220 case AArch64::Z27
: Reg
= AArch64::Z28
; break;
1221 case AArch64::Z28
: Reg
= AArch64::Z29
; break;
1222 case AArch64::Z29
: Reg
= AArch64::Z30
; break;
1223 case AArch64::Z30
: Reg
= AArch64::Z31
; break;
1224 // Vector lists can wrap around.
1233 template<unsigned size
>
1234 void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst
*MI
,
1236 const MCSubtargetInfo
&STI
,
1238 static_assert(size
== 64 || size
== 32,
1239 "Template parameter must be either 32 or 64");
1240 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1242 unsigned Sube
= (size
== 32) ? AArch64::sube32
: AArch64::sube64
;
1243 unsigned Subo
= (size
== 32) ? AArch64::subo32
: AArch64::subo64
;
1245 unsigned Even
= MRI
.getSubReg(Reg
, Sube
);
1246 unsigned Odd
= MRI
.getSubReg(Reg
, Subo
);
1247 O
<< getRegisterName(Even
) << ", " << getRegisterName(Odd
);
1250 void AArch64InstPrinter::printVectorList(const MCInst
*MI
, unsigned OpNum
,
1251 const MCSubtargetInfo
&STI
,
1253 StringRef LayoutSuffix
) {
1254 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1258 // Work out how many registers there are in the list (if there is an actual
1260 unsigned NumRegs
= 1;
1261 if (MRI
.getRegClass(AArch64::DDRegClassID
).contains(Reg
) ||
1262 MRI
.getRegClass(AArch64::ZPR2RegClassID
).contains(Reg
) ||
1263 MRI
.getRegClass(AArch64::QQRegClassID
).contains(Reg
))
1265 else if (MRI
.getRegClass(AArch64::DDDRegClassID
).contains(Reg
) ||
1266 MRI
.getRegClass(AArch64::ZPR3RegClassID
).contains(Reg
) ||
1267 MRI
.getRegClass(AArch64::QQQRegClassID
).contains(Reg
))
1269 else if (MRI
.getRegClass(AArch64::DDDDRegClassID
).contains(Reg
) ||
1270 MRI
.getRegClass(AArch64::ZPR4RegClassID
).contains(Reg
) ||
1271 MRI
.getRegClass(AArch64::QQQQRegClassID
).contains(Reg
))
1274 // Now forget about the list and find out what the first register is.
1275 if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::dsub0
))
1277 else if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::qsub0
))
1279 else if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::zsub0
))
1282 // If it's a D-reg, we need to promote it to the equivalent Q-reg before
1283 // printing (otherwise getRegisterName fails).
1284 if (MRI
.getRegClass(AArch64::FPR64RegClassID
).contains(Reg
)) {
1285 const MCRegisterClass
&FPR128RC
=
1286 MRI
.getRegClass(AArch64::FPR128RegClassID
);
1287 Reg
= MRI
.getMatchingSuperReg(Reg
, AArch64::dsub
, &FPR128RC
);
1290 for (unsigned i
= 0; i
< NumRegs
; ++i
, Reg
= getNextVectorRegister(Reg
)) {
1291 if (MRI
.getRegClass(AArch64::ZPRRegClassID
).contains(Reg
))
1292 O
<< getRegisterName(Reg
) << LayoutSuffix
;
1294 O
<< getRegisterName(Reg
, AArch64::vreg
) << LayoutSuffix
;
1296 if (i
+ 1 != NumRegs
)
1304 AArch64InstPrinter::printImplicitlyTypedVectorList(const MCInst
*MI
,
1306 const MCSubtargetInfo
&STI
,
1308 printVectorList(MI
, OpNum
, STI
, O
, "");
1311 template <unsigned NumLanes
, char LaneKind
>
1312 void AArch64InstPrinter::printTypedVectorList(const MCInst
*MI
, unsigned OpNum
,
1313 const MCSubtargetInfo
&STI
,
1315 std::string
Suffix(".");
1317 Suffix
+= itostr(NumLanes
) + LaneKind
;
1321 printVectorList(MI
, OpNum
, STI
, O
, Suffix
);
1324 void AArch64InstPrinter::printVectorIndex(const MCInst
*MI
, unsigned OpNum
,
1325 const MCSubtargetInfo
&STI
,
1327 O
<< "[" << MI
->getOperand(OpNum
).getImm() << "]";
1330 void AArch64InstPrinter::printAlignedLabel(const MCInst
*MI
, unsigned OpNum
,
1331 const MCSubtargetInfo
&STI
,
1333 const MCOperand
&Op
= MI
->getOperand(OpNum
);
1335 // If the label has already been resolved to an immediate offset (say, when
1336 // we're running the disassembler), just print the immediate.
1338 O
<< "#" << formatImm(Op
.getImm() * 4);
1342 // If the branch target is simply an address then print it in hex.
1343 const MCConstantExpr
*BranchTarget
=
1344 dyn_cast
<MCConstantExpr
>(MI
->getOperand(OpNum
).getExpr());
1346 if (BranchTarget
&& BranchTarget
->evaluateAsAbsolute(Address
)) {
1348 O
.write_hex(Address
);
1350 // Otherwise, just print the expression.
1351 MI
->getOperand(OpNum
).getExpr()->print(O
, &MAI
);
1355 void AArch64InstPrinter::printAdrpLabel(const MCInst
*MI
, unsigned OpNum
,
1356 const MCSubtargetInfo
&STI
,
1358 const MCOperand
&Op
= MI
->getOperand(OpNum
);
1360 // If the label has already been resolved to an immediate offset (say, when
1361 // we're running the disassembler), just print the immediate.
1363 O
<< "#" << formatImm(Op
.getImm() * (1 << 12));
1367 // Otherwise, just print the expression.
1368 MI
->getOperand(OpNum
).getExpr()->print(O
, &MAI
);
1371 void AArch64InstPrinter::printBarrierOption(const MCInst
*MI
, unsigned OpNo
,
1372 const MCSubtargetInfo
&STI
,
1374 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1375 unsigned Opcode
= MI
->getOpcode();
1378 if (Opcode
== AArch64::ISB
) {
1379 auto ISB
= AArch64ISB::lookupISBByEncoding(Val
);
1380 Name
= ISB
? ISB
->Name
: "";
1381 } else if (Opcode
== AArch64::TSB
) {
1382 auto TSB
= AArch64TSB::lookupTSBByEncoding(Val
);
1383 Name
= TSB
? TSB
->Name
: "";
1385 auto DB
= AArch64DB::lookupDBByEncoding(Val
);
1386 Name
= DB
? DB
->Name
: "";
1394 void AArch64InstPrinter::printMRSSystemRegister(const MCInst
*MI
, unsigned OpNo
,
1395 const MCSubtargetInfo
&STI
,
1397 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1399 // Horrible hack for the one register that has identical encodings but
1400 // different names in MSR and MRS. Because of this, one of MRS and MSR is
1401 // going to get the wrong entry
1402 if (Val
== AArch64SysReg::DBGDTRRX_EL0
) {
1403 O
<< "DBGDTRRX_EL0";
1407 const AArch64SysReg::SysReg
*Reg
= AArch64SysReg::lookupSysRegByEncoding(Val
);
1408 if (Reg
&& Reg
->Readable
&& Reg
->haveFeatures(STI
.getFeatureBits()))
1411 O
<< AArch64SysReg::genericRegisterString(Val
);
1414 void AArch64InstPrinter::printMSRSystemRegister(const MCInst
*MI
, unsigned OpNo
,
1415 const MCSubtargetInfo
&STI
,
1417 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1419 // Horrible hack for the one register that has identical encodings but
1420 // different names in MSR and MRS. Because of this, one of MRS and MSR is
1421 // going to get the wrong entry
1422 if (Val
== AArch64SysReg::DBGDTRTX_EL0
) {
1423 O
<< "DBGDTRTX_EL0";
1427 const AArch64SysReg::SysReg
*Reg
= AArch64SysReg::lookupSysRegByEncoding(Val
);
1428 if (Reg
&& Reg
->Writeable
&& Reg
->haveFeatures(STI
.getFeatureBits()))
1431 O
<< AArch64SysReg::genericRegisterString(Val
);
1434 void AArch64InstPrinter::printSystemPStateField(const MCInst
*MI
, unsigned OpNo
,
1435 const MCSubtargetInfo
&STI
,
1437 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1439 auto PState
= AArch64PState::lookupPStateByEncoding(Val
);
1440 if (PState
&& PState
->haveFeatures(STI
.getFeatureBits()))
1443 O
<< "#" << formatImm(Val
);
1446 void AArch64InstPrinter::printSIMDType10Operand(const MCInst
*MI
, unsigned OpNo
,
1447 const MCSubtargetInfo
&STI
,
1449 unsigned RawVal
= MI
->getOperand(OpNo
).getImm();
1450 uint64_t Val
= AArch64_AM::decodeAdvSIMDModImmType10(RawVal
);
1451 O
<< format("#%#016llx", Val
);
1454 template<int64_t Angle
, int64_t Remainder
>
1455 void AArch64InstPrinter::printComplexRotationOp(const MCInst
*MI
, unsigned OpNo
,
1456 const MCSubtargetInfo
&STI
,
1458 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1459 O
<< "#" << (Val
* Angle
) + Remainder
;
1462 void AArch64InstPrinter::printSVEPattern(const MCInst
*MI
, unsigned OpNum
,
1463 const MCSubtargetInfo
&STI
,
1465 unsigned Val
= MI
->getOperand(OpNum
).getImm();
1466 if (auto Pat
= AArch64SVEPredPattern::lookupSVEPREDPATByEncoding(Val
))
1469 O
<< '#' << formatImm(Val
);
1472 template <char suffix
>
1473 void AArch64InstPrinter::printSVERegOp(const MCInst
*MI
, unsigned OpNum
,
1474 const MCSubtargetInfo
&STI
,
1484 default: llvm_unreachable("Invalid kind specifier.");
1487 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1488 O
<< getRegisterName(Reg
);
1493 template <typename T
>
1494 void AArch64InstPrinter::printImmSVE(T Value
, raw_ostream
&O
) {
1495 typename
std::make_unsigned
<T
>::type HexValue
= Value
;
1497 if (getPrintImmHex())
1498 O
<< '#' << formatHex((uint64_t)HexValue
);
1500 O
<< '#' << formatDec(Value
);
1502 if (CommentStream
) {
1503 // Do the opposite to that used for instruction operands.
1504 if (getPrintImmHex())
1505 *CommentStream
<< '=' << formatDec(HexValue
) << '\n';
1507 *CommentStream
<< '=' << formatHex((uint64_t)Value
) << '\n';
1511 template <typename T
>
1512 void AArch64InstPrinter::printImm8OptLsl(const MCInst
*MI
, unsigned OpNum
,
1513 const MCSubtargetInfo
&STI
,
1515 unsigned UnscaledVal
= MI
->getOperand(OpNum
).getImm();
1516 unsigned Shift
= MI
->getOperand(OpNum
+ 1).getImm();
1517 assert(AArch64_AM::getShiftType(Shift
) == AArch64_AM::LSL
&&
1518 "Unexepected shift type!");
1520 // #0 lsl #8 is never pretty printed
1521 if ((UnscaledVal
== 0) && (AArch64_AM::getShiftValue(Shift
) != 0)) {
1522 O
<< '#' << formatImm(UnscaledVal
);
1523 printShifter(MI
, OpNum
+ 1, STI
, O
);
1528 if (std::is_signed
<T
>())
1529 Val
= (int8_t)UnscaledVal
* (1 << AArch64_AM::getShiftValue(Shift
));
1531 Val
= (uint8_t)UnscaledVal
* (1 << AArch64_AM::getShiftValue(Shift
));
1533 printImmSVE(Val
, O
);
1536 template <typename T
>
1537 void AArch64InstPrinter::printSVELogicalImm(const MCInst
*MI
, unsigned OpNum
,
1538 const MCSubtargetInfo
&STI
,
1540 typedef typename
std::make_signed
<T
>::type SignedT
;
1541 typedef typename
std::make_unsigned
<T
>::type UnsignedT
;
1543 uint64_t Val
= MI
->getOperand(OpNum
).getImm();
1544 UnsignedT PrintVal
= AArch64_AM::decodeLogicalImmediate(Val
, 64);
1546 // Prefer the default format for 16bit values, hex otherwise.
1547 if ((int16_t)PrintVal
== (SignedT
)PrintVal
)
1548 printImmSVE((T
)PrintVal
, O
);
1549 else if ((uint16_t)PrintVal
== PrintVal
)
1550 printImmSVE(PrintVal
, O
);
1552 O
<< '#' << formatHex((uint64_t)PrintVal
);
1555 template <int Width
>
1556 void AArch64InstPrinter::printZPRasFPR(const MCInst
*MI
, unsigned OpNum
,
1557 const MCSubtargetInfo
&STI
,
1561 case 8: Base
= AArch64::B0
; break;
1562 case 16: Base
= AArch64::H0
; break;
1563 case 32: Base
= AArch64::S0
; break;
1564 case 64: Base
= AArch64::D0
; break;
1565 case 128: Base
= AArch64::Q0
; break;
1567 llvm_unreachable("Unsupported width");
1569 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1570 O
<< getRegisterName(Reg
- AArch64::Z0
+ Base
);
1573 template <unsigned ImmIs0
, unsigned ImmIs1
>
1574 void AArch64InstPrinter::printExactFPImm(const MCInst
*MI
, unsigned OpNum
,
1575 const MCSubtargetInfo
&STI
,
1577 auto *Imm0Desc
= AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs0
);
1578 auto *Imm1Desc
= AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs1
);
1579 unsigned Val
= MI
->getOperand(OpNum
).getImm();
1580 O
<< "#" << (Val
? Imm1Desc
->Repr
: Imm0Desc
->Repr
);
1583 void AArch64InstPrinter::printGPR64as32(const MCInst
*MI
, unsigned OpNum
,
1584 const MCSubtargetInfo
&STI
,
1586 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1587 O
<< getRegisterName(getWRegFromXReg(Reg
));