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 // BFC takes precedence over its entire range, sligtly differently to BFI.
177 int BitWidth
= Opcode
== AArch64::BFMXri
? 64 : 32;
178 int LSB
= (BitWidth
- ImmR
) % BitWidth
;
179 int Width
= ImmS
+ 1;
181 O
<< "\tbfc\t" << getRegisterName(Op0
.getReg())
182 << ", #" << LSB
<< ", #" << Width
;
183 printAnnotation(O
, Annot
);
185 } else if (ImmS
< ImmR
) {
187 int BitWidth
= Opcode
== AArch64::BFMXri
? 64 : 32;
188 int LSB
= (BitWidth
- ImmR
) % BitWidth
;
189 int Width
= ImmS
+ 1;
191 O
<< "\tbfi\t" << getRegisterName(Op0
.getReg()) << ", "
192 << getRegisterName(Op2
.getReg()) << ", #" << LSB
<< ", #" << Width
;
193 printAnnotation(O
, Annot
);
198 int Width
= ImmS
- ImmR
+ 1;
199 // Otherwise BFXIL the preferred form
201 << getRegisterName(Op0
.getReg()) << ", " << getRegisterName(Op2
.getReg())
202 << ", #" << LSB
<< ", #" << Width
;
203 printAnnotation(O
, Annot
);
207 // Symbolic operands for MOVZ, MOVN and MOVK already imply a shift
208 // (e.g. :gottprel_g1: is always going to be "lsl #16") so it should not be
210 if ((Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
||
211 Opcode
== AArch64::MOVNXi
|| Opcode
== AArch64::MOVNWi
) &&
212 MI
->getOperand(1).isExpr()) {
213 if (Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
)
218 O
<< getRegisterName(MI
->getOperand(0).getReg()) << ", #";
219 MI
->getOperand(1).getExpr()->print(O
, &MAI
);
223 if ((Opcode
== AArch64::MOVKXi
|| Opcode
== AArch64::MOVKWi
) &&
224 MI
->getOperand(2).isExpr()) {
225 O
<< "\tmovk\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #";
226 MI
->getOperand(2).getExpr()->print(O
, &MAI
);
230 // MOVZ, MOVN and "ORR wzr, #imm" instructions are aliases for MOV, but their
231 // domains overlap so they need to be prioritized. The chain is "MOVZ lsl #0 >
232 // MOVZ lsl #N > MOVN lsl #0 > MOVN lsl #N > ORR". The highest instruction
233 // that can represent the move is the MOV alias, and the rest get printed
235 if ((Opcode
== AArch64::MOVZXi
|| Opcode
== AArch64::MOVZWi
) &&
236 MI
->getOperand(1).isImm() && MI
->getOperand(2).isImm()) {
237 int RegWidth
= Opcode
== AArch64::MOVZXi
? 64 : 32;
238 int Shift
= MI
->getOperand(2).getImm();
239 uint64_t Value
= (uint64_t)MI
->getOperand(1).getImm() << Shift
;
241 if (AArch64_AM::isMOVZMovAlias(Value
, Shift
,
242 Opcode
== AArch64::MOVZXi
? 64 : 32)) {
243 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
244 << formatImm(SignExtend64(Value
, RegWidth
));
249 if ((Opcode
== AArch64::MOVNXi
|| Opcode
== AArch64::MOVNWi
) &&
250 MI
->getOperand(1).isImm() && MI
->getOperand(2).isImm()) {
251 int RegWidth
= Opcode
== AArch64::MOVNXi
? 64 : 32;
252 int Shift
= MI
->getOperand(2).getImm();
253 uint64_t Value
= ~((uint64_t)MI
->getOperand(1).getImm() << Shift
);
255 Value
= Value
& 0xffffffff;
257 if (AArch64_AM::isMOVNMovAlias(Value
, Shift
, RegWidth
)) {
258 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
259 << formatImm(SignExtend64(Value
, RegWidth
));
264 if ((Opcode
== AArch64::ORRXri
|| Opcode
== AArch64::ORRWri
) &&
265 (MI
->getOperand(1).getReg() == AArch64::XZR
||
266 MI
->getOperand(1).getReg() == AArch64::WZR
) &&
267 MI
->getOperand(2).isImm()) {
268 int RegWidth
= Opcode
== AArch64::ORRXri
? 64 : 32;
269 uint64_t Value
= AArch64_AM::decodeLogicalImmediate(
270 MI
->getOperand(2).getImm(), RegWidth
);
271 if (!AArch64_AM::isAnyMOVWMovAlias(Value
, RegWidth
)) {
272 O
<< "\tmov\t" << getRegisterName(MI
->getOperand(0).getReg()) << ", #"
273 << formatImm(SignExtend64(Value
, RegWidth
));
278 if (Opcode
== AArch64::CompilerBarrier
) {
279 O
<< '\t' << MAI
.getCommentString() << " COMPILER BARRIER";
280 printAnnotation(O
, Annot
);
284 // Instruction TSB is specified as a one operand instruction, but 'csync' is
285 // not encoded, so for printing it is treated as a special case here:
286 if (Opcode
== AArch64::TSB
) {
291 if (!printAliasInstr(MI
, STI
, O
))
292 printInstruction(MI
, STI
, O
);
294 printAnnotation(O
, Annot
);
296 if (atomicBarrierDroppedOnZero(Opcode
) &&
297 (MI
->getOperand(0).getReg() == AArch64::XZR
||
298 MI
->getOperand(0).getReg() == AArch64::WZR
)) {
299 printAnnotation(O
, "acquire semantics dropped since destination is zero");
303 static bool isTblTbxInstruction(unsigned Opcode
, StringRef
&Layout
,
306 case AArch64::TBXv8i8One
:
307 case AArch64::TBXv8i8Two
:
308 case AArch64::TBXv8i8Three
:
309 case AArch64::TBXv8i8Four
:
313 case AArch64::TBLv8i8One
:
314 case AArch64::TBLv8i8Two
:
315 case AArch64::TBLv8i8Three
:
316 case AArch64::TBLv8i8Four
:
320 case AArch64::TBXv16i8One
:
321 case AArch64::TBXv16i8Two
:
322 case AArch64::TBXv16i8Three
:
323 case AArch64::TBXv16i8Four
:
327 case AArch64::TBLv16i8One
:
328 case AArch64::TBLv16i8Two
:
329 case AArch64::TBLv16i8Three
:
330 case AArch64::TBLv16i8Four
:
339 struct LdStNInstrDesc
{
341 const char *Mnemonic
;
348 static const LdStNInstrDesc LdStNInstInfo
[] = {
349 { AArch64::LD1i8
, "ld1", ".b", 1, true, 0 },
350 { AArch64::LD1i16
, "ld1", ".h", 1, true, 0 },
351 { AArch64::LD1i32
, "ld1", ".s", 1, true, 0 },
352 { AArch64::LD1i64
, "ld1", ".d", 1, true, 0 },
353 { AArch64::LD1i8_POST
, "ld1", ".b", 2, true, 1 },
354 { AArch64::LD1i16_POST
, "ld1", ".h", 2, true, 2 },
355 { AArch64::LD1i32_POST
, "ld1", ".s", 2, true, 4 },
356 { AArch64::LD1i64_POST
, "ld1", ".d", 2, true, 8 },
357 { AArch64::LD1Rv16b
, "ld1r", ".16b", 0, false, 0 },
358 { AArch64::LD1Rv8h
, "ld1r", ".8h", 0, false, 0 },
359 { AArch64::LD1Rv4s
, "ld1r", ".4s", 0, false, 0 },
360 { AArch64::LD1Rv2d
, "ld1r", ".2d", 0, false, 0 },
361 { AArch64::LD1Rv8b
, "ld1r", ".8b", 0, false, 0 },
362 { AArch64::LD1Rv4h
, "ld1r", ".4h", 0, false, 0 },
363 { AArch64::LD1Rv2s
, "ld1r", ".2s", 0, false, 0 },
364 { AArch64::LD1Rv1d
, "ld1r", ".1d", 0, false, 0 },
365 { AArch64::LD1Rv16b_POST
, "ld1r", ".16b", 1, false, 1 },
366 { AArch64::LD1Rv8h_POST
, "ld1r", ".8h", 1, false, 2 },
367 { AArch64::LD1Rv4s_POST
, "ld1r", ".4s", 1, false, 4 },
368 { AArch64::LD1Rv2d_POST
, "ld1r", ".2d", 1, false, 8 },
369 { AArch64::LD1Rv8b_POST
, "ld1r", ".8b", 1, false, 1 },
370 { AArch64::LD1Rv4h_POST
, "ld1r", ".4h", 1, false, 2 },
371 { AArch64::LD1Rv2s_POST
, "ld1r", ".2s", 1, false, 4 },
372 { AArch64::LD1Rv1d_POST
, "ld1r", ".1d", 1, false, 8 },
373 { AArch64::LD1Onev16b
, "ld1", ".16b", 0, false, 0 },
374 { AArch64::LD1Onev8h
, "ld1", ".8h", 0, false, 0 },
375 { AArch64::LD1Onev4s
, "ld1", ".4s", 0, false, 0 },
376 { AArch64::LD1Onev2d
, "ld1", ".2d", 0, false, 0 },
377 { AArch64::LD1Onev8b
, "ld1", ".8b", 0, false, 0 },
378 { AArch64::LD1Onev4h
, "ld1", ".4h", 0, false, 0 },
379 { AArch64::LD1Onev2s
, "ld1", ".2s", 0, false, 0 },
380 { AArch64::LD1Onev1d
, "ld1", ".1d", 0, false, 0 },
381 { AArch64::LD1Onev16b_POST
, "ld1", ".16b", 1, false, 16 },
382 { AArch64::LD1Onev8h_POST
, "ld1", ".8h", 1, false, 16 },
383 { AArch64::LD1Onev4s_POST
, "ld1", ".4s", 1, false, 16 },
384 { AArch64::LD1Onev2d_POST
, "ld1", ".2d", 1, false, 16 },
385 { AArch64::LD1Onev8b_POST
, "ld1", ".8b", 1, false, 8 },
386 { AArch64::LD1Onev4h_POST
, "ld1", ".4h", 1, false, 8 },
387 { AArch64::LD1Onev2s_POST
, "ld1", ".2s", 1, false, 8 },
388 { AArch64::LD1Onev1d_POST
, "ld1", ".1d", 1, false, 8 },
389 { AArch64::LD1Twov16b
, "ld1", ".16b", 0, false, 0 },
390 { AArch64::LD1Twov8h
, "ld1", ".8h", 0, false, 0 },
391 { AArch64::LD1Twov4s
, "ld1", ".4s", 0, false, 0 },
392 { AArch64::LD1Twov2d
, "ld1", ".2d", 0, false, 0 },
393 { AArch64::LD1Twov8b
, "ld1", ".8b", 0, false, 0 },
394 { AArch64::LD1Twov4h
, "ld1", ".4h", 0, false, 0 },
395 { AArch64::LD1Twov2s
, "ld1", ".2s", 0, false, 0 },
396 { AArch64::LD1Twov1d
, "ld1", ".1d", 0, false, 0 },
397 { AArch64::LD1Twov16b_POST
, "ld1", ".16b", 1, false, 32 },
398 { AArch64::LD1Twov8h_POST
, "ld1", ".8h", 1, false, 32 },
399 { AArch64::LD1Twov4s_POST
, "ld1", ".4s", 1, false, 32 },
400 { AArch64::LD1Twov2d_POST
, "ld1", ".2d", 1, false, 32 },
401 { AArch64::LD1Twov8b_POST
, "ld1", ".8b", 1, false, 16 },
402 { AArch64::LD1Twov4h_POST
, "ld1", ".4h", 1, false, 16 },
403 { AArch64::LD1Twov2s_POST
, "ld1", ".2s", 1, false, 16 },
404 { AArch64::LD1Twov1d_POST
, "ld1", ".1d", 1, false, 16 },
405 { AArch64::LD1Threev16b
, "ld1", ".16b", 0, false, 0 },
406 { AArch64::LD1Threev8h
, "ld1", ".8h", 0, false, 0 },
407 { AArch64::LD1Threev4s
, "ld1", ".4s", 0, false, 0 },
408 { AArch64::LD1Threev2d
, "ld1", ".2d", 0, false, 0 },
409 { AArch64::LD1Threev8b
, "ld1", ".8b", 0, false, 0 },
410 { AArch64::LD1Threev4h
, "ld1", ".4h", 0, false, 0 },
411 { AArch64::LD1Threev2s
, "ld1", ".2s", 0, false, 0 },
412 { AArch64::LD1Threev1d
, "ld1", ".1d", 0, false, 0 },
413 { AArch64::LD1Threev16b_POST
, "ld1", ".16b", 1, false, 48 },
414 { AArch64::LD1Threev8h_POST
, "ld1", ".8h", 1, false, 48 },
415 { AArch64::LD1Threev4s_POST
, "ld1", ".4s", 1, false, 48 },
416 { AArch64::LD1Threev2d_POST
, "ld1", ".2d", 1, false, 48 },
417 { AArch64::LD1Threev8b_POST
, "ld1", ".8b", 1, false, 24 },
418 { AArch64::LD1Threev4h_POST
, "ld1", ".4h", 1, false, 24 },
419 { AArch64::LD1Threev2s_POST
, "ld1", ".2s", 1, false, 24 },
420 { AArch64::LD1Threev1d_POST
, "ld1", ".1d", 1, false, 24 },
421 { AArch64::LD1Fourv16b
, "ld1", ".16b", 0, false, 0 },
422 { AArch64::LD1Fourv8h
, "ld1", ".8h", 0, false, 0 },
423 { AArch64::LD1Fourv4s
, "ld1", ".4s", 0, false, 0 },
424 { AArch64::LD1Fourv2d
, "ld1", ".2d", 0, false, 0 },
425 { AArch64::LD1Fourv8b
, "ld1", ".8b", 0, false, 0 },
426 { AArch64::LD1Fourv4h
, "ld1", ".4h", 0, false, 0 },
427 { AArch64::LD1Fourv2s
, "ld1", ".2s", 0, false, 0 },
428 { AArch64::LD1Fourv1d
, "ld1", ".1d", 0, false, 0 },
429 { AArch64::LD1Fourv16b_POST
, "ld1", ".16b", 1, false, 64 },
430 { AArch64::LD1Fourv8h_POST
, "ld1", ".8h", 1, false, 64 },
431 { AArch64::LD1Fourv4s_POST
, "ld1", ".4s", 1, false, 64 },
432 { AArch64::LD1Fourv2d_POST
, "ld1", ".2d", 1, false, 64 },
433 { AArch64::LD1Fourv8b_POST
, "ld1", ".8b", 1, false, 32 },
434 { AArch64::LD1Fourv4h_POST
, "ld1", ".4h", 1, false, 32 },
435 { AArch64::LD1Fourv2s_POST
, "ld1", ".2s", 1, false, 32 },
436 { AArch64::LD1Fourv1d_POST
, "ld1", ".1d", 1, false, 32 },
437 { AArch64::LD2i8
, "ld2", ".b", 1, true, 0 },
438 { AArch64::LD2i16
, "ld2", ".h", 1, true, 0 },
439 { AArch64::LD2i32
, "ld2", ".s", 1, true, 0 },
440 { AArch64::LD2i64
, "ld2", ".d", 1, true, 0 },
441 { AArch64::LD2i8_POST
, "ld2", ".b", 2, true, 2 },
442 { AArch64::LD2i16_POST
, "ld2", ".h", 2, true, 4 },
443 { AArch64::LD2i32_POST
, "ld2", ".s", 2, true, 8 },
444 { AArch64::LD2i64_POST
, "ld2", ".d", 2, true, 16 },
445 { AArch64::LD2Rv16b
, "ld2r", ".16b", 0, false, 0 },
446 { AArch64::LD2Rv8h
, "ld2r", ".8h", 0, false, 0 },
447 { AArch64::LD2Rv4s
, "ld2r", ".4s", 0, false, 0 },
448 { AArch64::LD2Rv2d
, "ld2r", ".2d", 0, false, 0 },
449 { AArch64::LD2Rv8b
, "ld2r", ".8b", 0, false, 0 },
450 { AArch64::LD2Rv4h
, "ld2r", ".4h", 0, false, 0 },
451 { AArch64::LD2Rv2s
, "ld2r", ".2s", 0, false, 0 },
452 { AArch64::LD2Rv1d
, "ld2r", ".1d", 0, false, 0 },
453 { AArch64::LD2Rv16b_POST
, "ld2r", ".16b", 1, false, 2 },
454 { AArch64::LD2Rv8h_POST
, "ld2r", ".8h", 1, false, 4 },
455 { AArch64::LD2Rv4s_POST
, "ld2r", ".4s", 1, false, 8 },
456 { AArch64::LD2Rv2d_POST
, "ld2r", ".2d", 1, false, 16 },
457 { AArch64::LD2Rv8b_POST
, "ld2r", ".8b", 1, false, 2 },
458 { AArch64::LD2Rv4h_POST
, "ld2r", ".4h", 1, false, 4 },
459 { AArch64::LD2Rv2s_POST
, "ld2r", ".2s", 1, false, 8 },
460 { AArch64::LD2Rv1d_POST
, "ld2r", ".1d", 1, false, 16 },
461 { AArch64::LD2Twov16b
, "ld2", ".16b", 0, false, 0 },
462 { AArch64::LD2Twov8h
, "ld2", ".8h", 0, false, 0 },
463 { AArch64::LD2Twov4s
, "ld2", ".4s", 0, false, 0 },
464 { AArch64::LD2Twov2d
, "ld2", ".2d", 0, false, 0 },
465 { AArch64::LD2Twov8b
, "ld2", ".8b", 0, false, 0 },
466 { AArch64::LD2Twov4h
, "ld2", ".4h", 0, false, 0 },
467 { AArch64::LD2Twov2s
, "ld2", ".2s", 0, false, 0 },
468 { AArch64::LD2Twov16b_POST
, "ld2", ".16b", 1, false, 32 },
469 { AArch64::LD2Twov8h_POST
, "ld2", ".8h", 1, false, 32 },
470 { AArch64::LD2Twov4s_POST
, "ld2", ".4s", 1, false, 32 },
471 { AArch64::LD2Twov2d_POST
, "ld2", ".2d", 1, false, 32 },
472 { AArch64::LD2Twov8b_POST
, "ld2", ".8b", 1, false, 16 },
473 { AArch64::LD2Twov4h_POST
, "ld2", ".4h", 1, false, 16 },
474 { AArch64::LD2Twov2s_POST
, "ld2", ".2s", 1, false, 16 },
475 { AArch64::LD3i8
, "ld3", ".b", 1, true, 0 },
476 { AArch64::LD3i16
, "ld3", ".h", 1, true, 0 },
477 { AArch64::LD3i32
, "ld3", ".s", 1, true, 0 },
478 { AArch64::LD3i64
, "ld3", ".d", 1, true, 0 },
479 { AArch64::LD3i8_POST
, "ld3", ".b", 2, true, 3 },
480 { AArch64::LD3i16_POST
, "ld3", ".h", 2, true, 6 },
481 { AArch64::LD3i32_POST
, "ld3", ".s", 2, true, 12 },
482 { AArch64::LD3i64_POST
, "ld3", ".d", 2, true, 24 },
483 { AArch64::LD3Rv16b
, "ld3r", ".16b", 0, false, 0 },
484 { AArch64::LD3Rv8h
, "ld3r", ".8h", 0, false, 0 },
485 { AArch64::LD3Rv4s
, "ld3r", ".4s", 0, false, 0 },
486 { AArch64::LD3Rv2d
, "ld3r", ".2d", 0, false, 0 },
487 { AArch64::LD3Rv8b
, "ld3r", ".8b", 0, false, 0 },
488 { AArch64::LD3Rv4h
, "ld3r", ".4h", 0, false, 0 },
489 { AArch64::LD3Rv2s
, "ld3r", ".2s", 0, false, 0 },
490 { AArch64::LD3Rv1d
, "ld3r", ".1d", 0, false, 0 },
491 { AArch64::LD3Rv16b_POST
, "ld3r", ".16b", 1, false, 3 },
492 { AArch64::LD3Rv8h_POST
, "ld3r", ".8h", 1, false, 6 },
493 { AArch64::LD3Rv4s_POST
, "ld3r", ".4s", 1, false, 12 },
494 { AArch64::LD3Rv2d_POST
, "ld3r", ".2d", 1, false, 24 },
495 { AArch64::LD3Rv8b_POST
, "ld3r", ".8b", 1, false, 3 },
496 { AArch64::LD3Rv4h_POST
, "ld3r", ".4h", 1, false, 6 },
497 { AArch64::LD3Rv2s_POST
, "ld3r", ".2s", 1, false, 12 },
498 { AArch64::LD3Rv1d_POST
, "ld3r", ".1d", 1, false, 24 },
499 { AArch64::LD3Threev16b
, "ld3", ".16b", 0, false, 0 },
500 { AArch64::LD3Threev8h
, "ld3", ".8h", 0, false, 0 },
501 { AArch64::LD3Threev4s
, "ld3", ".4s", 0, false, 0 },
502 { AArch64::LD3Threev2d
, "ld3", ".2d", 0, false, 0 },
503 { AArch64::LD3Threev8b
, "ld3", ".8b", 0, false, 0 },
504 { AArch64::LD3Threev4h
, "ld3", ".4h", 0, false, 0 },
505 { AArch64::LD3Threev2s
, "ld3", ".2s", 0, false, 0 },
506 { AArch64::LD3Threev16b_POST
, "ld3", ".16b", 1, false, 48 },
507 { AArch64::LD3Threev8h_POST
, "ld3", ".8h", 1, false, 48 },
508 { AArch64::LD3Threev4s_POST
, "ld3", ".4s", 1, false, 48 },
509 { AArch64::LD3Threev2d_POST
, "ld3", ".2d", 1, false, 48 },
510 { AArch64::LD3Threev8b_POST
, "ld3", ".8b", 1, false, 24 },
511 { AArch64::LD3Threev4h_POST
, "ld3", ".4h", 1, false, 24 },
512 { AArch64::LD3Threev2s_POST
, "ld3", ".2s", 1, false, 24 },
513 { AArch64::LD4i8
, "ld4", ".b", 1, true, 0 },
514 { AArch64::LD4i16
, "ld4", ".h", 1, true, 0 },
515 { AArch64::LD4i32
, "ld4", ".s", 1, true, 0 },
516 { AArch64::LD4i64
, "ld4", ".d", 1, true, 0 },
517 { AArch64::LD4i8_POST
, "ld4", ".b", 2, true, 4 },
518 { AArch64::LD4i16_POST
, "ld4", ".h", 2, true, 8 },
519 { AArch64::LD4i32_POST
, "ld4", ".s", 2, true, 16 },
520 { AArch64::LD4i64_POST
, "ld4", ".d", 2, true, 32 },
521 { AArch64::LD4Rv16b
, "ld4r", ".16b", 0, false, 0 },
522 { AArch64::LD4Rv8h
, "ld4r", ".8h", 0, false, 0 },
523 { AArch64::LD4Rv4s
, "ld4r", ".4s", 0, false, 0 },
524 { AArch64::LD4Rv2d
, "ld4r", ".2d", 0, false, 0 },
525 { AArch64::LD4Rv8b
, "ld4r", ".8b", 0, false, 0 },
526 { AArch64::LD4Rv4h
, "ld4r", ".4h", 0, false, 0 },
527 { AArch64::LD4Rv2s
, "ld4r", ".2s", 0, false, 0 },
528 { AArch64::LD4Rv1d
, "ld4r", ".1d", 0, false, 0 },
529 { AArch64::LD4Rv16b_POST
, "ld4r", ".16b", 1, false, 4 },
530 { AArch64::LD4Rv8h_POST
, "ld4r", ".8h", 1, false, 8 },
531 { AArch64::LD4Rv4s_POST
, "ld4r", ".4s", 1, false, 16 },
532 { AArch64::LD4Rv2d_POST
, "ld4r", ".2d", 1, false, 32 },
533 { AArch64::LD4Rv8b_POST
, "ld4r", ".8b", 1, false, 4 },
534 { AArch64::LD4Rv4h_POST
, "ld4r", ".4h", 1, false, 8 },
535 { AArch64::LD4Rv2s_POST
, "ld4r", ".2s", 1, false, 16 },
536 { AArch64::LD4Rv1d_POST
, "ld4r", ".1d", 1, false, 32 },
537 { AArch64::LD4Fourv16b
, "ld4", ".16b", 0, false, 0 },
538 { AArch64::LD4Fourv8h
, "ld4", ".8h", 0, false, 0 },
539 { AArch64::LD4Fourv4s
, "ld4", ".4s", 0, false, 0 },
540 { AArch64::LD4Fourv2d
, "ld4", ".2d", 0, false, 0 },
541 { AArch64::LD4Fourv8b
, "ld4", ".8b", 0, false, 0 },
542 { AArch64::LD4Fourv4h
, "ld4", ".4h", 0, false, 0 },
543 { AArch64::LD4Fourv2s
, "ld4", ".2s", 0, false, 0 },
544 { AArch64::LD4Fourv16b_POST
, "ld4", ".16b", 1, false, 64 },
545 { AArch64::LD4Fourv8h_POST
, "ld4", ".8h", 1, false, 64 },
546 { AArch64::LD4Fourv4s_POST
, "ld4", ".4s", 1, false, 64 },
547 { AArch64::LD4Fourv2d_POST
, "ld4", ".2d", 1, false, 64 },
548 { AArch64::LD4Fourv8b_POST
, "ld4", ".8b", 1, false, 32 },
549 { AArch64::LD4Fourv4h_POST
, "ld4", ".4h", 1, false, 32 },
550 { AArch64::LD4Fourv2s_POST
, "ld4", ".2s", 1, false, 32 },
551 { AArch64::ST1i8
, "st1", ".b", 0, true, 0 },
552 { AArch64::ST1i16
, "st1", ".h", 0, true, 0 },
553 { AArch64::ST1i32
, "st1", ".s", 0, true, 0 },
554 { AArch64::ST1i64
, "st1", ".d", 0, true, 0 },
555 { AArch64::ST1i8_POST
, "st1", ".b", 1, true, 1 },
556 { AArch64::ST1i16_POST
, "st1", ".h", 1, true, 2 },
557 { AArch64::ST1i32_POST
, "st1", ".s", 1, true, 4 },
558 { AArch64::ST1i64_POST
, "st1", ".d", 1, true, 8 },
559 { AArch64::ST1Onev16b
, "st1", ".16b", 0, false, 0 },
560 { AArch64::ST1Onev8h
, "st1", ".8h", 0, false, 0 },
561 { AArch64::ST1Onev4s
, "st1", ".4s", 0, false, 0 },
562 { AArch64::ST1Onev2d
, "st1", ".2d", 0, false, 0 },
563 { AArch64::ST1Onev8b
, "st1", ".8b", 0, false, 0 },
564 { AArch64::ST1Onev4h
, "st1", ".4h", 0, false, 0 },
565 { AArch64::ST1Onev2s
, "st1", ".2s", 0, false, 0 },
566 { AArch64::ST1Onev1d
, "st1", ".1d", 0, false, 0 },
567 { AArch64::ST1Onev16b_POST
, "st1", ".16b", 1, false, 16 },
568 { AArch64::ST1Onev8h_POST
, "st1", ".8h", 1, false, 16 },
569 { AArch64::ST1Onev4s_POST
, "st1", ".4s", 1, false, 16 },
570 { AArch64::ST1Onev2d_POST
, "st1", ".2d", 1, false, 16 },
571 { AArch64::ST1Onev8b_POST
, "st1", ".8b", 1, false, 8 },
572 { AArch64::ST1Onev4h_POST
, "st1", ".4h", 1, false, 8 },
573 { AArch64::ST1Onev2s_POST
, "st1", ".2s", 1, false, 8 },
574 { AArch64::ST1Onev1d_POST
, "st1", ".1d", 1, false, 8 },
575 { AArch64::ST1Twov16b
, "st1", ".16b", 0, false, 0 },
576 { AArch64::ST1Twov8h
, "st1", ".8h", 0, false, 0 },
577 { AArch64::ST1Twov4s
, "st1", ".4s", 0, false, 0 },
578 { AArch64::ST1Twov2d
, "st1", ".2d", 0, false, 0 },
579 { AArch64::ST1Twov8b
, "st1", ".8b", 0, false, 0 },
580 { AArch64::ST1Twov4h
, "st1", ".4h", 0, false, 0 },
581 { AArch64::ST1Twov2s
, "st1", ".2s", 0, false, 0 },
582 { AArch64::ST1Twov1d
, "st1", ".1d", 0, false, 0 },
583 { AArch64::ST1Twov16b_POST
, "st1", ".16b", 1, false, 32 },
584 { AArch64::ST1Twov8h_POST
, "st1", ".8h", 1, false, 32 },
585 { AArch64::ST1Twov4s_POST
, "st1", ".4s", 1, false, 32 },
586 { AArch64::ST1Twov2d_POST
, "st1", ".2d", 1, false, 32 },
587 { AArch64::ST1Twov8b_POST
, "st1", ".8b", 1, false, 16 },
588 { AArch64::ST1Twov4h_POST
, "st1", ".4h", 1, false, 16 },
589 { AArch64::ST1Twov2s_POST
, "st1", ".2s", 1, false, 16 },
590 { AArch64::ST1Twov1d_POST
, "st1", ".1d", 1, false, 16 },
591 { AArch64::ST1Threev16b
, "st1", ".16b", 0, false, 0 },
592 { AArch64::ST1Threev8h
, "st1", ".8h", 0, false, 0 },
593 { AArch64::ST1Threev4s
, "st1", ".4s", 0, false, 0 },
594 { AArch64::ST1Threev2d
, "st1", ".2d", 0, false, 0 },
595 { AArch64::ST1Threev8b
, "st1", ".8b", 0, false, 0 },
596 { AArch64::ST1Threev4h
, "st1", ".4h", 0, false, 0 },
597 { AArch64::ST1Threev2s
, "st1", ".2s", 0, false, 0 },
598 { AArch64::ST1Threev1d
, "st1", ".1d", 0, false, 0 },
599 { AArch64::ST1Threev16b_POST
, "st1", ".16b", 1, false, 48 },
600 { AArch64::ST1Threev8h_POST
, "st1", ".8h", 1, false, 48 },
601 { AArch64::ST1Threev4s_POST
, "st1", ".4s", 1, false, 48 },
602 { AArch64::ST1Threev2d_POST
, "st1", ".2d", 1, false, 48 },
603 { AArch64::ST1Threev8b_POST
, "st1", ".8b", 1, false, 24 },
604 { AArch64::ST1Threev4h_POST
, "st1", ".4h", 1, false, 24 },
605 { AArch64::ST1Threev2s_POST
, "st1", ".2s", 1, false, 24 },
606 { AArch64::ST1Threev1d_POST
, "st1", ".1d", 1, false, 24 },
607 { AArch64::ST1Fourv16b
, "st1", ".16b", 0, false, 0 },
608 { AArch64::ST1Fourv8h
, "st1", ".8h", 0, false, 0 },
609 { AArch64::ST1Fourv4s
, "st1", ".4s", 0, false, 0 },
610 { AArch64::ST1Fourv2d
, "st1", ".2d", 0, false, 0 },
611 { AArch64::ST1Fourv8b
, "st1", ".8b", 0, false, 0 },
612 { AArch64::ST1Fourv4h
, "st1", ".4h", 0, false, 0 },
613 { AArch64::ST1Fourv2s
, "st1", ".2s", 0, false, 0 },
614 { AArch64::ST1Fourv1d
, "st1", ".1d", 0, false, 0 },
615 { AArch64::ST1Fourv16b_POST
, "st1", ".16b", 1, false, 64 },
616 { AArch64::ST1Fourv8h_POST
, "st1", ".8h", 1, false, 64 },
617 { AArch64::ST1Fourv4s_POST
, "st1", ".4s", 1, false, 64 },
618 { AArch64::ST1Fourv2d_POST
, "st1", ".2d", 1, false, 64 },
619 { AArch64::ST1Fourv8b_POST
, "st1", ".8b", 1, false, 32 },
620 { AArch64::ST1Fourv4h_POST
, "st1", ".4h", 1, false, 32 },
621 { AArch64::ST1Fourv2s_POST
, "st1", ".2s", 1, false, 32 },
622 { AArch64::ST1Fourv1d_POST
, "st1", ".1d", 1, false, 32 },
623 { AArch64::ST2i8
, "st2", ".b", 0, true, 0 },
624 { AArch64::ST2i16
, "st2", ".h", 0, true, 0 },
625 { AArch64::ST2i32
, "st2", ".s", 0, true, 0 },
626 { AArch64::ST2i64
, "st2", ".d", 0, true, 0 },
627 { AArch64::ST2i8_POST
, "st2", ".b", 1, true, 2 },
628 { AArch64::ST2i16_POST
, "st2", ".h", 1, true, 4 },
629 { AArch64::ST2i32_POST
, "st2", ".s", 1, true, 8 },
630 { AArch64::ST2i64_POST
, "st2", ".d", 1, true, 16 },
631 { AArch64::ST2Twov16b
, "st2", ".16b", 0, false, 0 },
632 { AArch64::ST2Twov8h
, "st2", ".8h", 0, false, 0 },
633 { AArch64::ST2Twov4s
, "st2", ".4s", 0, false, 0 },
634 { AArch64::ST2Twov2d
, "st2", ".2d", 0, false, 0 },
635 { AArch64::ST2Twov8b
, "st2", ".8b", 0, false, 0 },
636 { AArch64::ST2Twov4h
, "st2", ".4h", 0, false, 0 },
637 { AArch64::ST2Twov2s
, "st2", ".2s", 0, false, 0 },
638 { AArch64::ST2Twov16b_POST
, "st2", ".16b", 1, false, 32 },
639 { AArch64::ST2Twov8h_POST
, "st2", ".8h", 1, false, 32 },
640 { AArch64::ST2Twov4s_POST
, "st2", ".4s", 1, false, 32 },
641 { AArch64::ST2Twov2d_POST
, "st2", ".2d", 1, false, 32 },
642 { AArch64::ST2Twov8b_POST
, "st2", ".8b", 1, false, 16 },
643 { AArch64::ST2Twov4h_POST
, "st2", ".4h", 1, false, 16 },
644 { AArch64::ST2Twov2s_POST
, "st2", ".2s", 1, false, 16 },
645 { AArch64::ST3i8
, "st3", ".b", 0, true, 0 },
646 { AArch64::ST3i16
, "st3", ".h", 0, true, 0 },
647 { AArch64::ST3i32
, "st3", ".s", 0, true, 0 },
648 { AArch64::ST3i64
, "st3", ".d", 0, true, 0 },
649 { AArch64::ST3i8_POST
, "st3", ".b", 1, true, 3 },
650 { AArch64::ST3i16_POST
, "st3", ".h", 1, true, 6 },
651 { AArch64::ST3i32_POST
, "st3", ".s", 1, true, 12 },
652 { AArch64::ST3i64_POST
, "st3", ".d", 1, true, 24 },
653 { AArch64::ST3Threev16b
, "st3", ".16b", 0, false, 0 },
654 { AArch64::ST3Threev8h
, "st3", ".8h", 0, false, 0 },
655 { AArch64::ST3Threev4s
, "st3", ".4s", 0, false, 0 },
656 { AArch64::ST3Threev2d
, "st3", ".2d", 0, false, 0 },
657 { AArch64::ST3Threev8b
, "st3", ".8b", 0, false, 0 },
658 { AArch64::ST3Threev4h
, "st3", ".4h", 0, false, 0 },
659 { AArch64::ST3Threev2s
, "st3", ".2s", 0, false, 0 },
660 { AArch64::ST3Threev16b_POST
, "st3", ".16b", 1, false, 48 },
661 { AArch64::ST3Threev8h_POST
, "st3", ".8h", 1, false, 48 },
662 { AArch64::ST3Threev4s_POST
, "st3", ".4s", 1, false, 48 },
663 { AArch64::ST3Threev2d_POST
, "st3", ".2d", 1, false, 48 },
664 { AArch64::ST3Threev8b_POST
, "st3", ".8b", 1, false, 24 },
665 { AArch64::ST3Threev4h_POST
, "st3", ".4h", 1, false, 24 },
666 { AArch64::ST3Threev2s_POST
, "st3", ".2s", 1, false, 24 },
667 { AArch64::ST4i8
, "st4", ".b", 0, true, 0 },
668 { AArch64::ST4i16
, "st4", ".h", 0, true, 0 },
669 { AArch64::ST4i32
, "st4", ".s", 0, true, 0 },
670 { AArch64::ST4i64
, "st4", ".d", 0, true, 0 },
671 { AArch64::ST4i8_POST
, "st4", ".b", 1, true, 4 },
672 { AArch64::ST4i16_POST
, "st4", ".h", 1, true, 8 },
673 { AArch64::ST4i32_POST
, "st4", ".s", 1, true, 16 },
674 { AArch64::ST4i64_POST
, "st4", ".d", 1, true, 32 },
675 { AArch64::ST4Fourv16b
, "st4", ".16b", 0, false, 0 },
676 { AArch64::ST4Fourv8h
, "st4", ".8h", 0, false, 0 },
677 { AArch64::ST4Fourv4s
, "st4", ".4s", 0, false, 0 },
678 { AArch64::ST4Fourv2d
, "st4", ".2d", 0, false, 0 },
679 { AArch64::ST4Fourv8b
, "st4", ".8b", 0, false, 0 },
680 { AArch64::ST4Fourv4h
, "st4", ".4h", 0, false, 0 },
681 { AArch64::ST4Fourv2s
, "st4", ".2s", 0, false, 0 },
682 { AArch64::ST4Fourv16b_POST
, "st4", ".16b", 1, false, 64 },
683 { AArch64::ST4Fourv8h_POST
, "st4", ".8h", 1, false, 64 },
684 { AArch64::ST4Fourv4s_POST
, "st4", ".4s", 1, false, 64 },
685 { AArch64::ST4Fourv2d_POST
, "st4", ".2d", 1, false, 64 },
686 { AArch64::ST4Fourv8b_POST
, "st4", ".8b", 1, false, 32 },
687 { AArch64::ST4Fourv4h_POST
, "st4", ".4h", 1, false, 32 },
688 { AArch64::ST4Fourv2s_POST
, "st4", ".2s", 1, false, 32 },
691 static const LdStNInstrDesc
*getLdStNInstrDesc(unsigned Opcode
) {
693 for (Idx
= 0; Idx
!= array_lengthof(LdStNInstInfo
); ++Idx
)
694 if (LdStNInstInfo
[Idx
].Opcode
== Opcode
)
695 return &LdStNInstInfo
[Idx
];
700 void AArch64AppleInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&O
,
702 const MCSubtargetInfo
&STI
) {
703 unsigned Opcode
= MI
->getOpcode();
707 if (isTblTbxInstruction(MI
->getOpcode(), Layout
, IsTbx
)) {
708 O
<< "\t" << (IsTbx
? "tbx" : "tbl") << Layout
<< '\t'
709 << getRegisterName(MI
->getOperand(0).getReg(), AArch64::vreg
) << ", ";
711 unsigned ListOpNum
= IsTbx
? 2 : 1;
712 printVectorList(MI
, ListOpNum
, STI
, O
, "");
715 << getRegisterName(MI
->getOperand(ListOpNum
+ 1).getReg(), AArch64::vreg
);
716 printAnnotation(O
, Annot
);
720 if (const LdStNInstrDesc
*LdStDesc
= getLdStNInstrDesc(Opcode
)) {
721 O
<< "\t" << LdStDesc
->Mnemonic
<< LdStDesc
->Layout
<< '\t';
723 // Now onto the operands: first a vector list with possible lane
724 // specifier. E.g. { v0 }[2]
725 int OpNum
= LdStDesc
->ListOperand
;
726 printVectorList(MI
, OpNum
++, STI
, O
, "");
728 if (LdStDesc
->HasLane
)
729 O
<< '[' << MI
->getOperand(OpNum
++).getImm() << ']';
731 // Next the address: [xN]
732 unsigned AddrReg
= MI
->getOperand(OpNum
++).getReg();
733 O
<< ", [" << getRegisterName(AddrReg
) << ']';
735 // Finally, there might be a post-indexed offset.
736 if (LdStDesc
->NaturalOffset
!= 0) {
737 unsigned Reg
= MI
->getOperand(OpNum
++).getReg();
738 if (Reg
!= AArch64::XZR
)
739 O
<< ", " << getRegisterName(Reg
);
741 assert(LdStDesc
->NaturalOffset
&& "no offset on post-inc instruction?");
742 O
<< ", #" << LdStDesc
->NaturalOffset
;
746 printAnnotation(O
, Annot
);
750 AArch64InstPrinter::printInst(MI
, O
, Annot
, STI
);
753 bool AArch64InstPrinter::printSysAlias(const MCInst
*MI
,
754 const MCSubtargetInfo
&STI
,
757 unsigned Opcode
= MI
->getOpcode();
758 assert(Opcode
== AArch64::SYSxt
&& "Invalid opcode for SYS alias!");
761 const MCOperand
&Op1
= MI
->getOperand(0);
762 const MCOperand
&Cn
= MI
->getOperand(1);
763 const MCOperand
&Cm
= MI
->getOperand(2);
764 const MCOperand
&Op2
= MI
->getOperand(3);
766 unsigned Op1Val
= Op1
.getImm();
767 unsigned CnVal
= Cn
.getImm();
768 unsigned CmVal
= Cm
.getImm();
769 unsigned Op2Val
= Op2
.getImm();
771 uint16_t Encoding
= Op2Val
;
772 Encoding
|= CmVal
<< 3;
773 Encoding
|= CnVal
<< 7;
774 Encoding
|= Op1Val
<< 11;
782 default: return false;
783 // Maybe IC, maybe Prediction Restriction
786 default: return false;
787 case 0: goto Search_IC
;
788 case 3: goto Search_PRCTX
;
790 // Prediction Restriction aliases
793 const AArch64PRCTX::PRCTX
*PRCTX
= AArch64PRCTX::lookupPRCTXByEncoding(Encoding
>> 3);
794 if (!PRCTX
|| !PRCTX
->haveFeatures(STI
.getFeatureBits()))
797 NeedsReg
= PRCTX
->NeedsReg
;
799 default: return false;
800 case 4: Ins
= "cfp\t"; break;
801 case 5: Ins
= "dvp\t"; break;
802 case 7: Ins
= "cpp\t"; break;
804 Name
= std::string(PRCTX
->Name
);
810 const AArch64IC::IC
*IC
= AArch64IC::lookupICByEncoding(Encoding
);
811 if (!IC
|| !IC
->haveFeatures(STI
.getFeatureBits()))
814 NeedsReg
= IC
->NeedsReg
;
816 Name
= std::string(IC
->Name
);
820 case 4: case 6: case 10: case 11: case 12: case 13: case 14:
822 const AArch64DC::DC
*DC
= AArch64DC::lookupDCByEncoding(Encoding
);
823 if (!DC
|| !DC
->haveFeatures(STI
.getFeatureBits()))
828 Name
= std::string(DC
->Name
);
833 const AArch64AT::AT
*AT
= AArch64AT::lookupATByEncoding(Encoding
);
834 if (!AT
|| !AT
->haveFeatures(STI
.getFeatureBits()))
839 Name
= std::string(AT
->Name
);
843 } else if (CnVal
== 8) {
845 const AArch64TLBI::TLBI
*TLBI
= AArch64TLBI::lookupTLBIByEncoding(Encoding
);
846 if (!TLBI
|| !TLBI
->haveFeatures(STI
.getFeatureBits()))
849 NeedsReg
= TLBI
->NeedsReg
;
851 Name
= std::string(TLBI
->Name
);
856 std::string Str
= Ins
+ Name
;
857 std::transform(Str
.begin(), Str
.end(), Str
.begin(), ::tolower
);
861 O
<< ", " << getRegisterName(MI
->getOperand(4).getReg());
866 void AArch64InstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
867 const MCSubtargetInfo
&STI
,
869 const MCOperand
&Op
= MI
->getOperand(OpNo
);
871 unsigned Reg
= Op
.getReg();
872 O
<< getRegisterName(Reg
);
873 } else if (Op
.isImm()) {
874 printImm(MI
, OpNo
, STI
, O
);
876 assert(Op
.isExpr() && "unknown operand kind in printOperand");
877 Op
.getExpr()->print(O
, &MAI
);
881 void AArch64InstPrinter::printImm(const MCInst
*MI
, unsigned OpNo
,
882 const MCSubtargetInfo
&STI
,
884 const MCOperand
&Op
= MI
->getOperand(OpNo
);
885 O
<< "#" << formatImm(Op
.getImm());
888 void AArch64InstPrinter::printImmHex(const MCInst
*MI
, unsigned OpNo
,
889 const MCSubtargetInfo
&STI
,
891 const MCOperand
&Op
= MI
->getOperand(OpNo
);
892 O
<< format("#%#llx", Op
.getImm());
895 void AArch64InstPrinter::printPostIncOperand(const MCInst
*MI
, unsigned OpNo
,
896 unsigned Imm
, raw_ostream
&O
) {
897 const MCOperand
&Op
= MI
->getOperand(OpNo
);
899 unsigned Reg
= Op
.getReg();
900 if (Reg
== AArch64::XZR
)
903 O
<< getRegisterName(Reg
);
905 llvm_unreachable("unknown operand kind in printPostIncOperand64");
908 void AArch64InstPrinter::printVRegOperand(const MCInst
*MI
, unsigned OpNo
,
909 const MCSubtargetInfo
&STI
,
911 const MCOperand
&Op
= MI
->getOperand(OpNo
);
912 assert(Op
.isReg() && "Non-register vreg operand!");
913 unsigned Reg
= Op
.getReg();
914 O
<< getRegisterName(Reg
, AArch64::vreg
);
917 void AArch64InstPrinter::printSysCROperand(const MCInst
*MI
, unsigned OpNo
,
918 const MCSubtargetInfo
&STI
,
920 const MCOperand
&Op
= MI
->getOperand(OpNo
);
921 assert(Op
.isImm() && "System instruction C[nm] operands must be immediates!");
922 O
<< "c" << Op
.getImm();
925 void AArch64InstPrinter::printAddSubImm(const MCInst
*MI
, unsigned OpNum
,
926 const MCSubtargetInfo
&STI
,
928 const MCOperand
&MO
= MI
->getOperand(OpNum
);
930 unsigned Val
= (MO
.getImm() & 0xfff);
931 assert(Val
== MO
.getImm() && "Add/sub immediate out of range!");
933 AArch64_AM::getShiftValue(MI
->getOperand(OpNum
+ 1).getImm());
934 O
<< '#' << formatImm(Val
);
936 printShifter(MI
, OpNum
+ 1, STI
, O
);
939 *CommentStream
<< '=' << formatImm(Val
<< Shift
) << '\n';
941 assert(MO
.isExpr() && "Unexpected operand type!");
942 MO
.getExpr()->print(O
, &MAI
);
943 printShifter(MI
, OpNum
+ 1, STI
, O
);
947 template <typename T
>
948 void AArch64InstPrinter::printLogicalImm(const MCInst
*MI
, unsigned OpNum
,
949 const MCSubtargetInfo
&STI
,
951 uint64_t Val
= MI
->getOperand(OpNum
).getImm();
953 O
.write_hex(AArch64_AM::decodeLogicalImmediate(Val
, 8 * sizeof(T
)));
956 void AArch64InstPrinter::printShifter(const MCInst
*MI
, unsigned OpNum
,
957 const MCSubtargetInfo
&STI
,
959 unsigned Val
= MI
->getOperand(OpNum
).getImm();
960 // LSL #0 should not be printed.
961 if (AArch64_AM::getShiftType(Val
) == AArch64_AM::LSL
&&
962 AArch64_AM::getShiftValue(Val
) == 0)
964 O
<< ", " << AArch64_AM::getShiftExtendName(AArch64_AM::getShiftType(Val
))
965 << " #" << AArch64_AM::getShiftValue(Val
);
968 void AArch64InstPrinter::printShiftedRegister(const MCInst
*MI
, unsigned OpNum
,
969 const MCSubtargetInfo
&STI
,
971 O
<< getRegisterName(MI
->getOperand(OpNum
).getReg());
972 printShifter(MI
, OpNum
+ 1, STI
, O
);
975 void AArch64InstPrinter::printExtendedRegister(const MCInst
*MI
, unsigned OpNum
,
976 const MCSubtargetInfo
&STI
,
978 O
<< getRegisterName(MI
->getOperand(OpNum
).getReg());
979 printArithExtend(MI
, OpNum
+ 1, STI
, O
);
982 void AArch64InstPrinter::printArithExtend(const MCInst
*MI
, unsigned OpNum
,
983 const MCSubtargetInfo
&STI
,
985 unsigned Val
= MI
->getOperand(OpNum
).getImm();
986 AArch64_AM::ShiftExtendType ExtType
= AArch64_AM::getArithExtendType(Val
);
987 unsigned ShiftVal
= AArch64_AM::getArithShiftValue(Val
);
989 // If the destination or first source register operand is [W]SP, print
990 // UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
992 if (ExtType
== AArch64_AM::UXTW
|| ExtType
== AArch64_AM::UXTX
) {
993 unsigned Dest
= MI
->getOperand(0).getReg();
994 unsigned Src1
= MI
->getOperand(1).getReg();
995 if ( ((Dest
== AArch64::SP
|| Src1
== AArch64::SP
) &&
996 ExtType
== AArch64_AM::UXTX
) ||
997 ((Dest
== AArch64::WSP
|| Src1
== AArch64::WSP
) &&
998 ExtType
== AArch64_AM::UXTW
) ) {
1000 O
<< ", lsl #" << ShiftVal
;
1004 O
<< ", " << AArch64_AM::getShiftExtendName(ExtType
);
1006 O
<< " #" << ShiftVal
;
1009 static void printMemExtendImpl(bool SignExtend
, bool DoShift
,
1010 unsigned Width
, char SrcRegKind
,
1012 // sxtw, sxtx, uxtw or lsl (== uxtx)
1013 bool IsLSL
= !SignExtend
&& SrcRegKind
== 'x';
1017 O
<< (SignExtend
? 's' : 'u') << "xt" << SrcRegKind
;
1019 if (DoShift
|| IsLSL
)
1020 O
<< " #" << Log2_32(Width
/ 8);
1023 void AArch64InstPrinter::printMemExtend(const MCInst
*MI
, unsigned OpNum
,
1024 raw_ostream
&O
, char SrcRegKind
,
1026 bool SignExtend
= MI
->getOperand(OpNum
).getImm();
1027 bool DoShift
= MI
->getOperand(OpNum
+ 1).getImm();
1028 printMemExtendImpl(SignExtend
, DoShift
, Width
, SrcRegKind
, O
);
1031 template <bool SignExtend
, int ExtWidth
, char SrcRegKind
, char Suffix
>
1032 void AArch64InstPrinter::printRegWithShiftExtend(const MCInst
*MI
,
1034 const MCSubtargetInfo
&STI
,
1036 printOperand(MI
, OpNum
, STI
, O
);
1037 if (Suffix
== 's' || Suffix
== 'd')
1040 assert(Suffix
== 0 && "Unsupported suffix size");
1042 bool DoShift
= ExtWidth
!= 8;
1043 if (SignExtend
|| DoShift
|| SrcRegKind
== 'w') {
1045 printMemExtendImpl(SignExtend
, DoShift
, ExtWidth
, SrcRegKind
, O
);
1049 void AArch64InstPrinter::printCondCode(const MCInst
*MI
, unsigned OpNum
,
1050 const MCSubtargetInfo
&STI
,
1052 AArch64CC::CondCode CC
= (AArch64CC::CondCode
)MI
->getOperand(OpNum
).getImm();
1053 O
<< AArch64CC::getCondCodeName(CC
);
1056 void AArch64InstPrinter::printInverseCondCode(const MCInst
*MI
, unsigned OpNum
,
1057 const MCSubtargetInfo
&STI
,
1059 AArch64CC::CondCode CC
= (AArch64CC::CondCode
)MI
->getOperand(OpNum
).getImm();
1060 O
<< AArch64CC::getCondCodeName(AArch64CC::getInvertedCondCode(CC
));
1063 void AArch64InstPrinter::printAMNoIndex(const MCInst
*MI
, unsigned OpNum
,
1064 const MCSubtargetInfo
&STI
,
1066 O
<< '[' << getRegisterName(MI
->getOperand(OpNum
).getReg()) << ']';
1070 void AArch64InstPrinter::printImmScale(const MCInst
*MI
, unsigned OpNum
,
1071 const MCSubtargetInfo
&STI
,
1073 O
<< '#' << formatImm(Scale
* MI
->getOperand(OpNum
).getImm());
1076 void AArch64InstPrinter::printUImm12Offset(const MCInst
*MI
, unsigned OpNum
,
1077 unsigned Scale
, raw_ostream
&O
) {
1078 const MCOperand MO
= MI
->getOperand(OpNum
);
1080 O
<< "#" << formatImm(MO
.getImm() * Scale
);
1082 assert(MO
.isExpr() && "Unexpected operand type!");
1083 MO
.getExpr()->print(O
, &MAI
);
1087 void AArch64InstPrinter::printAMIndexedWB(const MCInst
*MI
, unsigned OpNum
,
1088 unsigned Scale
, raw_ostream
&O
) {
1089 const MCOperand MO1
= MI
->getOperand(OpNum
+ 1);
1090 O
<< '[' << getRegisterName(MI
->getOperand(OpNum
).getReg());
1092 O
<< ", #" << formatImm(MO1
.getImm() * Scale
);
1094 assert(MO1
.isExpr() && "Unexpected operand type!");
1096 MO1
.getExpr()->print(O
, &MAI
);
1101 template <bool IsSVEPrefetch
>
1102 void AArch64InstPrinter::printPrefetchOp(const MCInst
*MI
, unsigned OpNum
,
1103 const MCSubtargetInfo
&STI
,
1105 unsigned prfop
= MI
->getOperand(OpNum
).getImm();
1106 if (IsSVEPrefetch
) {
1107 if (auto PRFM
= AArch64SVEPRFM::lookupSVEPRFMByEncoding(prfop
)) {
1111 } else if (auto PRFM
= AArch64PRFM::lookupPRFMByEncoding(prfop
)) {
1116 O
<< '#' << formatImm(prfop
);
1119 void AArch64InstPrinter::printPSBHintOp(const MCInst
*MI
, unsigned OpNum
,
1120 const MCSubtargetInfo
&STI
,
1122 unsigned psbhintop
= MI
->getOperand(OpNum
).getImm();
1123 auto PSB
= AArch64PSBHint::lookupPSBByEncoding(psbhintop
);
1127 O
<< '#' << formatImm(psbhintop
);
1130 void AArch64InstPrinter::printBTIHintOp(const MCInst
*MI
, unsigned OpNum
,
1131 const MCSubtargetInfo
&STI
,
1133 unsigned btihintop
= (MI
->getOperand(OpNum
).getImm() ^ 32) >> 1;
1134 auto BTI
= AArch64BTIHint::lookupBTIByEncoding(btihintop
);
1138 O
<< '#' << formatImm(btihintop
);
1141 void AArch64InstPrinter::printFPImmOperand(const MCInst
*MI
, unsigned OpNum
,
1142 const MCSubtargetInfo
&STI
,
1144 const MCOperand
&MO
= MI
->getOperand(OpNum
);
1146 MO
.isFPImm() ? MO
.getFPImm() : AArch64_AM::getFPImmFloat(MO
.getImm());
1148 // 8 decimal places are enough to perfectly represent permitted floats.
1149 O
<< format("#%.8f", FPImm
);
1152 static unsigned getNextVectorRegister(unsigned Reg
, unsigned Stride
= 1) {
1156 llvm_unreachable("Vector register expected!");
1157 case AArch64::Q0
: Reg
= AArch64::Q1
; break;
1158 case AArch64::Q1
: Reg
= AArch64::Q2
; break;
1159 case AArch64::Q2
: Reg
= AArch64::Q3
; break;
1160 case AArch64::Q3
: Reg
= AArch64::Q4
; break;
1161 case AArch64::Q4
: Reg
= AArch64::Q5
; break;
1162 case AArch64::Q5
: Reg
= AArch64::Q6
; break;
1163 case AArch64::Q6
: Reg
= AArch64::Q7
; break;
1164 case AArch64::Q7
: Reg
= AArch64::Q8
; break;
1165 case AArch64::Q8
: Reg
= AArch64::Q9
; break;
1166 case AArch64::Q9
: Reg
= AArch64::Q10
; break;
1167 case AArch64::Q10
: Reg
= AArch64::Q11
; break;
1168 case AArch64::Q11
: Reg
= AArch64::Q12
; break;
1169 case AArch64::Q12
: Reg
= AArch64::Q13
; break;
1170 case AArch64::Q13
: Reg
= AArch64::Q14
; break;
1171 case AArch64::Q14
: Reg
= AArch64::Q15
; break;
1172 case AArch64::Q15
: Reg
= AArch64::Q16
; break;
1173 case AArch64::Q16
: Reg
= AArch64::Q17
; break;
1174 case AArch64::Q17
: Reg
= AArch64::Q18
; break;
1175 case AArch64::Q18
: Reg
= AArch64::Q19
; break;
1176 case AArch64::Q19
: Reg
= AArch64::Q20
; break;
1177 case AArch64::Q20
: Reg
= AArch64::Q21
; break;
1178 case AArch64::Q21
: Reg
= AArch64::Q22
; break;
1179 case AArch64::Q22
: Reg
= AArch64::Q23
; break;
1180 case AArch64::Q23
: Reg
= AArch64::Q24
; break;
1181 case AArch64::Q24
: Reg
= AArch64::Q25
; break;
1182 case AArch64::Q25
: Reg
= AArch64::Q26
; break;
1183 case AArch64::Q26
: Reg
= AArch64::Q27
; break;
1184 case AArch64::Q27
: Reg
= AArch64::Q28
; break;
1185 case AArch64::Q28
: Reg
= AArch64::Q29
; break;
1186 case AArch64::Q29
: Reg
= AArch64::Q30
; break;
1187 case AArch64::Q30
: Reg
= AArch64::Q31
; break;
1188 // Vector lists can wrap around.
1192 case AArch64::Z0
: Reg
= AArch64::Z1
; break;
1193 case AArch64::Z1
: Reg
= AArch64::Z2
; break;
1194 case AArch64::Z2
: Reg
= AArch64::Z3
; break;
1195 case AArch64::Z3
: Reg
= AArch64::Z4
; break;
1196 case AArch64::Z4
: Reg
= AArch64::Z5
; break;
1197 case AArch64::Z5
: Reg
= AArch64::Z6
; break;
1198 case AArch64::Z6
: Reg
= AArch64::Z7
; break;
1199 case AArch64::Z7
: Reg
= AArch64::Z8
; break;
1200 case AArch64::Z8
: Reg
= AArch64::Z9
; break;
1201 case AArch64::Z9
: Reg
= AArch64::Z10
; break;
1202 case AArch64::Z10
: Reg
= AArch64::Z11
; break;
1203 case AArch64::Z11
: Reg
= AArch64::Z12
; break;
1204 case AArch64::Z12
: Reg
= AArch64::Z13
; break;
1205 case AArch64::Z13
: Reg
= AArch64::Z14
; break;
1206 case AArch64::Z14
: Reg
= AArch64::Z15
; break;
1207 case AArch64::Z15
: Reg
= AArch64::Z16
; break;
1208 case AArch64::Z16
: Reg
= AArch64::Z17
; break;
1209 case AArch64::Z17
: Reg
= AArch64::Z18
; break;
1210 case AArch64::Z18
: Reg
= AArch64::Z19
; break;
1211 case AArch64::Z19
: Reg
= AArch64::Z20
; break;
1212 case AArch64::Z20
: Reg
= AArch64::Z21
; break;
1213 case AArch64::Z21
: Reg
= AArch64::Z22
; break;
1214 case AArch64::Z22
: Reg
= AArch64::Z23
; break;
1215 case AArch64::Z23
: Reg
= AArch64::Z24
; break;
1216 case AArch64::Z24
: Reg
= AArch64::Z25
; break;
1217 case AArch64::Z25
: Reg
= AArch64::Z26
; break;
1218 case AArch64::Z26
: Reg
= AArch64::Z27
; break;
1219 case AArch64::Z27
: Reg
= AArch64::Z28
; break;
1220 case AArch64::Z28
: Reg
= AArch64::Z29
; break;
1221 case AArch64::Z29
: Reg
= AArch64::Z30
; break;
1222 case AArch64::Z30
: Reg
= AArch64::Z31
; break;
1223 // Vector lists can wrap around.
1232 template<unsigned size
>
1233 void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst
*MI
,
1235 const MCSubtargetInfo
&STI
,
1237 static_assert(size
== 64 || size
== 32,
1238 "Template parameter must be either 32 or 64");
1239 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1241 unsigned Sube
= (size
== 32) ? AArch64::sube32
: AArch64::sube64
;
1242 unsigned Subo
= (size
== 32) ? AArch64::subo32
: AArch64::subo64
;
1244 unsigned Even
= MRI
.getSubReg(Reg
, Sube
);
1245 unsigned Odd
= MRI
.getSubReg(Reg
, Subo
);
1246 O
<< getRegisterName(Even
) << ", " << getRegisterName(Odd
);
1249 void AArch64InstPrinter::printVectorList(const MCInst
*MI
, unsigned OpNum
,
1250 const MCSubtargetInfo
&STI
,
1252 StringRef LayoutSuffix
) {
1253 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1257 // Work out how many registers there are in the list (if there is an actual
1259 unsigned NumRegs
= 1;
1260 if (MRI
.getRegClass(AArch64::DDRegClassID
).contains(Reg
) ||
1261 MRI
.getRegClass(AArch64::ZPR2RegClassID
).contains(Reg
) ||
1262 MRI
.getRegClass(AArch64::QQRegClassID
).contains(Reg
))
1264 else if (MRI
.getRegClass(AArch64::DDDRegClassID
).contains(Reg
) ||
1265 MRI
.getRegClass(AArch64::ZPR3RegClassID
).contains(Reg
) ||
1266 MRI
.getRegClass(AArch64::QQQRegClassID
).contains(Reg
))
1268 else if (MRI
.getRegClass(AArch64::DDDDRegClassID
).contains(Reg
) ||
1269 MRI
.getRegClass(AArch64::ZPR4RegClassID
).contains(Reg
) ||
1270 MRI
.getRegClass(AArch64::QQQQRegClassID
).contains(Reg
))
1273 // Now forget about the list and find out what the first register is.
1274 if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::dsub0
))
1276 else if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::qsub0
))
1278 else if (unsigned FirstReg
= MRI
.getSubReg(Reg
, AArch64::zsub0
))
1281 // If it's a D-reg, we need to promote it to the equivalent Q-reg before
1282 // printing (otherwise getRegisterName fails).
1283 if (MRI
.getRegClass(AArch64::FPR64RegClassID
).contains(Reg
)) {
1284 const MCRegisterClass
&FPR128RC
=
1285 MRI
.getRegClass(AArch64::FPR128RegClassID
);
1286 Reg
= MRI
.getMatchingSuperReg(Reg
, AArch64::dsub
, &FPR128RC
);
1289 for (unsigned i
= 0; i
< NumRegs
; ++i
, Reg
= getNextVectorRegister(Reg
)) {
1290 if (MRI
.getRegClass(AArch64::ZPRRegClassID
).contains(Reg
))
1291 O
<< getRegisterName(Reg
) << LayoutSuffix
;
1293 O
<< getRegisterName(Reg
, AArch64::vreg
) << LayoutSuffix
;
1295 if (i
+ 1 != NumRegs
)
1303 AArch64InstPrinter::printImplicitlyTypedVectorList(const MCInst
*MI
,
1305 const MCSubtargetInfo
&STI
,
1307 printVectorList(MI
, OpNum
, STI
, O
, "");
1310 template <unsigned NumLanes
, char LaneKind
>
1311 void AArch64InstPrinter::printTypedVectorList(const MCInst
*MI
, unsigned OpNum
,
1312 const MCSubtargetInfo
&STI
,
1314 std::string
Suffix(".");
1316 Suffix
+= itostr(NumLanes
) + LaneKind
;
1320 printVectorList(MI
, OpNum
, STI
, O
, Suffix
);
1323 void AArch64InstPrinter::printVectorIndex(const MCInst
*MI
, unsigned OpNum
,
1324 const MCSubtargetInfo
&STI
,
1326 O
<< "[" << MI
->getOperand(OpNum
).getImm() << "]";
1329 void AArch64InstPrinter::printAlignedLabel(const MCInst
*MI
, unsigned OpNum
,
1330 const MCSubtargetInfo
&STI
,
1332 const MCOperand
&Op
= MI
->getOperand(OpNum
);
1334 // If the label has already been resolved to an immediate offset (say, when
1335 // we're running the disassembler), just print the immediate.
1337 O
<< "#" << formatImm(Op
.getImm() * 4);
1341 // If the branch target is simply an address then print it in hex.
1342 const MCConstantExpr
*BranchTarget
=
1343 dyn_cast
<MCConstantExpr
>(MI
->getOperand(OpNum
).getExpr());
1345 if (BranchTarget
&& BranchTarget
->evaluateAsAbsolute(Address
)) {
1347 O
.write_hex(Address
);
1349 // Otherwise, just print the expression.
1350 MI
->getOperand(OpNum
).getExpr()->print(O
, &MAI
);
1354 void AArch64InstPrinter::printAdrpLabel(const MCInst
*MI
, unsigned OpNum
,
1355 const MCSubtargetInfo
&STI
,
1357 const MCOperand
&Op
= MI
->getOperand(OpNum
);
1359 // If the label has already been resolved to an immediate offset (say, when
1360 // we're running the disassembler), just print the immediate.
1362 O
<< "#" << formatImm(Op
.getImm() * (1 << 12));
1366 // Otherwise, just print the expression.
1367 MI
->getOperand(OpNum
).getExpr()->print(O
, &MAI
);
1370 void AArch64InstPrinter::printBarrierOption(const MCInst
*MI
, unsigned OpNo
,
1371 const MCSubtargetInfo
&STI
,
1373 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1374 unsigned Opcode
= MI
->getOpcode();
1377 if (Opcode
== AArch64::ISB
) {
1378 auto ISB
= AArch64ISB::lookupISBByEncoding(Val
);
1379 Name
= ISB
? ISB
->Name
: "";
1380 } else if (Opcode
== AArch64::TSB
) {
1381 auto TSB
= AArch64TSB::lookupTSBByEncoding(Val
);
1382 Name
= TSB
? TSB
->Name
: "";
1384 auto DB
= AArch64DB::lookupDBByEncoding(Val
);
1385 Name
= DB
? DB
->Name
: "";
1393 void AArch64InstPrinter::printMRSSystemRegister(const MCInst
*MI
, unsigned OpNo
,
1394 const MCSubtargetInfo
&STI
,
1396 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1398 // Horrible hack for the one register that has identical encodings but
1399 // different names in MSR and MRS. Because of this, one of MRS and MSR is
1400 // going to get the wrong entry
1401 if (Val
== AArch64SysReg::DBGDTRRX_EL0
) {
1402 O
<< "DBGDTRRX_EL0";
1406 const AArch64SysReg::SysReg
*Reg
= AArch64SysReg::lookupSysRegByEncoding(Val
);
1407 if (Reg
&& Reg
->Readable
&& Reg
->haveFeatures(STI
.getFeatureBits()))
1410 O
<< AArch64SysReg::genericRegisterString(Val
);
1413 void AArch64InstPrinter::printMSRSystemRegister(const MCInst
*MI
, unsigned OpNo
,
1414 const MCSubtargetInfo
&STI
,
1416 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1418 // Horrible hack for the one register that has identical encodings but
1419 // different names in MSR and MRS. Because of this, one of MRS and MSR is
1420 // going to get the wrong entry
1421 if (Val
== AArch64SysReg::DBGDTRTX_EL0
) {
1422 O
<< "DBGDTRTX_EL0";
1426 const AArch64SysReg::SysReg
*Reg
= AArch64SysReg::lookupSysRegByEncoding(Val
);
1427 if (Reg
&& Reg
->Writeable
&& Reg
->haveFeatures(STI
.getFeatureBits()))
1430 O
<< AArch64SysReg::genericRegisterString(Val
);
1433 void AArch64InstPrinter::printSystemPStateField(const MCInst
*MI
, unsigned OpNo
,
1434 const MCSubtargetInfo
&STI
,
1436 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1438 auto PState
= AArch64PState::lookupPStateByEncoding(Val
);
1439 if (PState
&& PState
->haveFeatures(STI
.getFeatureBits()))
1442 O
<< "#" << formatImm(Val
);
1445 void AArch64InstPrinter::printSIMDType10Operand(const MCInst
*MI
, unsigned OpNo
,
1446 const MCSubtargetInfo
&STI
,
1448 unsigned RawVal
= MI
->getOperand(OpNo
).getImm();
1449 uint64_t Val
= AArch64_AM::decodeAdvSIMDModImmType10(RawVal
);
1450 O
<< format("#%#016llx", Val
);
1453 template<int64_t Angle
, int64_t Remainder
>
1454 void AArch64InstPrinter::printComplexRotationOp(const MCInst
*MI
, unsigned OpNo
,
1455 const MCSubtargetInfo
&STI
,
1457 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1458 O
<< "#" << (Val
* Angle
) + Remainder
;
1461 void AArch64InstPrinter::printSVEPattern(const MCInst
*MI
, unsigned OpNum
,
1462 const MCSubtargetInfo
&STI
,
1464 unsigned Val
= MI
->getOperand(OpNum
).getImm();
1465 if (auto Pat
= AArch64SVEPredPattern::lookupSVEPREDPATByEncoding(Val
))
1468 O
<< '#' << formatImm(Val
);
1471 template <char suffix
>
1472 void AArch64InstPrinter::printSVERegOp(const MCInst
*MI
, unsigned OpNum
,
1473 const MCSubtargetInfo
&STI
,
1483 default: llvm_unreachable("Invalid kind specifier.");
1486 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1487 O
<< getRegisterName(Reg
);
1492 template <typename T
>
1493 void AArch64InstPrinter::printImmSVE(T Value
, raw_ostream
&O
) {
1494 typename
std::make_unsigned
<T
>::type HexValue
= Value
;
1496 if (getPrintImmHex())
1497 O
<< '#' << formatHex((uint64_t)HexValue
);
1499 O
<< '#' << formatDec(Value
);
1501 if (CommentStream
) {
1502 // Do the opposite to that used for instruction operands.
1503 if (getPrintImmHex())
1504 *CommentStream
<< '=' << formatDec(HexValue
) << '\n';
1506 *CommentStream
<< '=' << formatHex((uint64_t)Value
) << '\n';
1510 template <typename T
>
1511 void AArch64InstPrinter::printImm8OptLsl(const MCInst
*MI
, unsigned OpNum
,
1512 const MCSubtargetInfo
&STI
,
1514 unsigned UnscaledVal
= MI
->getOperand(OpNum
).getImm();
1515 unsigned Shift
= MI
->getOperand(OpNum
+ 1).getImm();
1516 assert(AArch64_AM::getShiftType(Shift
) == AArch64_AM::LSL
&&
1517 "Unexepected shift type!");
1519 // #0 lsl #8 is never pretty printed
1520 if ((UnscaledVal
== 0) && (AArch64_AM::getShiftValue(Shift
) != 0)) {
1521 O
<< '#' << formatImm(UnscaledVal
);
1522 printShifter(MI
, OpNum
+ 1, STI
, O
);
1527 if (std::is_signed
<T
>())
1528 Val
= (int8_t)UnscaledVal
* (1 << AArch64_AM::getShiftValue(Shift
));
1530 Val
= (uint8_t)UnscaledVal
* (1 << AArch64_AM::getShiftValue(Shift
));
1532 printImmSVE(Val
, O
);
1535 template <typename T
>
1536 void AArch64InstPrinter::printSVELogicalImm(const MCInst
*MI
, unsigned OpNum
,
1537 const MCSubtargetInfo
&STI
,
1539 typedef typename
std::make_signed
<T
>::type SignedT
;
1540 typedef typename
std::make_unsigned
<T
>::type UnsignedT
;
1542 uint64_t Val
= MI
->getOperand(OpNum
).getImm();
1543 UnsignedT PrintVal
= AArch64_AM::decodeLogicalImmediate(Val
, 64);
1545 // Prefer the default format for 16bit values, hex otherwise.
1546 if ((int16_t)PrintVal
== (SignedT
)PrintVal
)
1547 printImmSVE((T
)PrintVal
, O
);
1548 else if ((uint16_t)PrintVal
== PrintVal
)
1549 printImmSVE(PrintVal
, O
);
1551 O
<< '#' << formatHex((uint64_t)PrintVal
);
1554 template <int Width
>
1555 void AArch64InstPrinter::printZPRasFPR(const MCInst
*MI
, unsigned OpNum
,
1556 const MCSubtargetInfo
&STI
,
1560 case 8: Base
= AArch64::B0
; break;
1561 case 16: Base
= AArch64::H0
; break;
1562 case 32: Base
= AArch64::S0
; break;
1563 case 64: Base
= AArch64::D0
; break;
1564 case 128: Base
= AArch64::Q0
; break;
1566 llvm_unreachable("Unsupported width");
1568 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1569 O
<< getRegisterName(Reg
- AArch64::Z0
+ Base
);
1572 template <unsigned ImmIs0
, unsigned ImmIs1
>
1573 void AArch64InstPrinter::printExactFPImm(const MCInst
*MI
, unsigned OpNum
,
1574 const MCSubtargetInfo
&STI
,
1576 auto *Imm0Desc
= AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs0
);
1577 auto *Imm1Desc
= AArch64ExactFPImm::lookupExactFPImmByEnum(ImmIs1
);
1578 unsigned Val
= MI
->getOperand(OpNum
).getImm();
1579 O
<< "#" << (Val
? Imm1Desc
->Repr
: Imm0Desc
->Repr
);
1582 void AArch64InstPrinter::printGPR64as32(const MCInst
*MI
, unsigned OpNum
,
1583 const MCSubtargetInfo
&STI
,
1585 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1586 O
<< getRegisterName(getWRegFromXReg(Reg
));