1 //=- AArch64/AArch64MCCodeEmitter.cpp - Convert AArch64 code to machine code-=//
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 file implements the AArch64MCCodeEmitter class.
11 //===----------------------------------------------------------------------===//
13 #include "MCTargetDesc/AArch64AddressingModes.h"
14 #include "MCTargetDesc/AArch64FixupKinds.h"
15 #include "MCTargetDesc/AArch64MCExpr.h"
16 #include "Utils/AArch64BaseInfo.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/Statistic.h"
19 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/MC/MCCodeEmitter.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCFixup.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCRegisterInfo.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/Endian.h"
29 #include "llvm/Support/EndianStream.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
37 #define DEBUG_TYPE "mccodeemitter"
39 STATISTIC(MCNumEmitted
, "Number of MC instructions emitted.");
40 STATISTIC(MCNumFixups
, "Number of MC fixups created.");
44 class AArch64MCCodeEmitter
: public MCCodeEmitter
{
46 const MCInstrInfo
&MCII
;
49 AArch64MCCodeEmitter(const MCInstrInfo
&mcii
, MCContext
&ctx
)
50 : Ctx(ctx
), MCII(mcii
) {}
51 AArch64MCCodeEmitter(const AArch64MCCodeEmitter
&) = delete;
52 void operator=(const AArch64MCCodeEmitter
&) = delete;
53 ~AArch64MCCodeEmitter() override
= default;
55 // getBinaryCodeForInstr - TableGen'erated function for getting the
56 // binary encoding for an instruction.
57 uint64_t getBinaryCodeForInstr(const MCInst
&MI
,
58 SmallVectorImpl
<MCFixup
> &Fixups
,
59 const MCSubtargetInfo
&STI
) const;
61 /// getMachineOpValue - Return binary encoding of operand. If the machine
62 /// operand requires relocation, record the relocation and return zero.
63 unsigned getMachineOpValue(const MCInst
&MI
, const MCOperand
&MO
,
64 SmallVectorImpl
<MCFixup
> &Fixups
,
65 const MCSubtargetInfo
&STI
) const;
67 /// getLdStUImm12OpValue - Return encoding info for 12-bit unsigned immediate
68 /// attached to a load, store or prfm instruction. If operand requires a
69 /// relocation, record it and return zero in that part of the encoding.
70 template <uint32_t FixupKind
>
71 uint32_t getLdStUImm12OpValue(const MCInst
&MI
, unsigned OpIdx
,
72 SmallVectorImpl
<MCFixup
> &Fixups
,
73 const MCSubtargetInfo
&STI
) const;
75 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
77 uint32_t getAdrLabelOpValue(const MCInst
&MI
, unsigned OpIdx
,
78 SmallVectorImpl
<MCFixup
> &Fixups
,
79 const MCSubtargetInfo
&STI
) const;
81 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
82 /// the 2-bit shift field.
83 uint32_t getAddSubImmOpValue(const MCInst
&MI
, unsigned OpIdx
,
84 SmallVectorImpl
<MCFixup
> &Fixups
,
85 const MCSubtargetInfo
&STI
) const;
87 /// getCondBranchTargetOpValue - Return the encoded value for a conditional
89 uint32_t getCondBranchTargetOpValue(const MCInst
&MI
, unsigned OpIdx
,
90 SmallVectorImpl
<MCFixup
> &Fixups
,
91 const MCSubtargetInfo
&STI
) const;
93 /// getLoadLiteralOpValue - Return the encoded value for a load-literal
94 /// pc-relative address.
95 uint32_t getLoadLiteralOpValue(const MCInst
&MI
, unsigned OpIdx
,
96 SmallVectorImpl
<MCFixup
> &Fixups
,
97 const MCSubtargetInfo
&STI
) const;
99 /// getMemExtendOpValue - Return the encoded value for a reg-extend load/store
100 /// instruction: bit 0 is whether a shift is present, bit 1 is whether the
101 /// operation is a sign extend (as opposed to a zero extend).
102 uint32_t getMemExtendOpValue(const MCInst
&MI
, unsigned OpIdx
,
103 SmallVectorImpl
<MCFixup
> &Fixups
,
104 const MCSubtargetInfo
&STI
) const;
106 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
108 uint32_t getTestBranchTargetOpValue(const MCInst
&MI
, unsigned OpIdx
,
109 SmallVectorImpl
<MCFixup
> &Fixups
,
110 const MCSubtargetInfo
&STI
) const;
112 /// getBranchTargetOpValue - Return the encoded value for an unconditional
114 uint32_t getBranchTargetOpValue(const MCInst
&MI
, unsigned OpIdx
,
115 SmallVectorImpl
<MCFixup
> &Fixups
,
116 const MCSubtargetInfo
&STI
) const;
118 /// getMoveWideImmOpValue - Return the encoded value for the immediate operand
119 /// of a MOVZ or MOVK instruction.
120 uint32_t getMoveWideImmOpValue(const MCInst
&MI
, unsigned OpIdx
,
121 SmallVectorImpl
<MCFixup
> &Fixups
,
122 const MCSubtargetInfo
&STI
) const;
124 /// getVecShifterOpValue - Return the encoded value for the vector shifter.
125 uint32_t getVecShifterOpValue(const MCInst
&MI
, unsigned OpIdx
,
126 SmallVectorImpl
<MCFixup
> &Fixups
,
127 const MCSubtargetInfo
&STI
) const;
129 /// getMoveVecShifterOpValue - Return the encoded value for the vector move
131 uint32_t getMoveVecShifterOpValue(const MCInst
&MI
, unsigned OpIdx
,
132 SmallVectorImpl
<MCFixup
> &Fixups
,
133 const MCSubtargetInfo
&STI
) const;
135 /// getFixedPointScaleOpValue - Return the encoded value for the
136 // FP-to-fixed-point scale factor.
137 uint32_t getFixedPointScaleOpValue(const MCInst
&MI
, unsigned OpIdx
,
138 SmallVectorImpl
<MCFixup
> &Fixups
,
139 const MCSubtargetInfo
&STI
) const;
141 uint32_t getVecShiftR64OpValue(const MCInst
&MI
, unsigned OpIdx
,
142 SmallVectorImpl
<MCFixup
> &Fixups
,
143 const MCSubtargetInfo
&STI
) const;
144 uint32_t getVecShiftR32OpValue(const MCInst
&MI
, unsigned OpIdx
,
145 SmallVectorImpl
<MCFixup
> &Fixups
,
146 const MCSubtargetInfo
&STI
) const;
147 uint32_t getVecShiftR16OpValue(const MCInst
&MI
, unsigned OpIdx
,
148 SmallVectorImpl
<MCFixup
> &Fixups
,
149 const MCSubtargetInfo
&STI
) const;
150 uint32_t getVecShiftR8OpValue(const MCInst
&MI
, unsigned OpIdx
,
151 SmallVectorImpl
<MCFixup
> &Fixups
,
152 const MCSubtargetInfo
&STI
) const;
153 uint32_t getVecShiftL64OpValue(const MCInst
&MI
, unsigned OpIdx
,
154 SmallVectorImpl
<MCFixup
> &Fixups
,
155 const MCSubtargetInfo
&STI
) const;
156 uint32_t getVecShiftL32OpValue(const MCInst
&MI
, unsigned OpIdx
,
157 SmallVectorImpl
<MCFixup
> &Fixups
,
158 const MCSubtargetInfo
&STI
) const;
159 uint32_t getVecShiftL16OpValue(const MCInst
&MI
, unsigned OpIdx
,
160 SmallVectorImpl
<MCFixup
> &Fixups
,
161 const MCSubtargetInfo
&STI
) const;
162 uint32_t getVecShiftL8OpValue(const MCInst
&MI
, unsigned OpIdx
,
163 SmallVectorImpl
<MCFixup
> &Fixups
,
164 const MCSubtargetInfo
&STI
) const;
166 uint32_t getImm8OptLsl(const MCInst
&MI
, unsigned OpIdx
,
167 SmallVectorImpl
<MCFixup
> &Fixups
,
168 const MCSubtargetInfo
&STI
) const;
169 uint32_t getSVEIncDecImm(const MCInst
&MI
, unsigned OpIdx
,
170 SmallVectorImpl
<MCFixup
> &Fixups
,
171 const MCSubtargetInfo
&STI
) const;
173 unsigned fixMOVZ(const MCInst
&MI
, unsigned EncodedValue
,
174 const MCSubtargetInfo
&STI
) const;
176 void encodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
177 SmallVectorImpl
<MCFixup
> &Fixups
,
178 const MCSubtargetInfo
&STI
) const override
;
180 unsigned fixMulHigh(const MCInst
&MI
, unsigned EncodedValue
,
181 const MCSubtargetInfo
&STI
) const;
183 template<int hasRs
, int hasRt2
> unsigned
184 fixLoadStoreExclusive(const MCInst
&MI
, unsigned EncodedValue
,
185 const MCSubtargetInfo
&STI
) const;
187 unsigned fixOneOperandFPComparison(const MCInst
&MI
, unsigned EncodedValue
,
188 const MCSubtargetInfo
&STI
) const;
190 uint32_t EncodeMatrixTileListRegisterClass(const MCInst
&MI
, unsigned OpIdx
,
191 SmallVectorImpl
<MCFixup
> &Fixups
,
192 const MCSubtargetInfo
&STI
) const;
193 uint32_t encodeMatrixIndexGPR32(const MCInst
&MI
, unsigned OpIdx
,
194 SmallVectorImpl
<MCFixup
> &Fixups
,
195 const MCSubtargetInfo
&STI
) const;
198 FeatureBitset
computeAvailableFeatures(const FeatureBitset
&FB
) const;
200 verifyInstructionPredicates(const MCInst
&MI
,
201 const FeatureBitset
&AvailableFeatures
) const;
204 } // end anonymous namespace
206 /// getMachineOpValue - Return binary encoding of operand. If the machine
207 /// operand requires relocation, record the relocation and return zero.
209 AArch64MCCodeEmitter::getMachineOpValue(const MCInst
&MI
, const MCOperand
&MO
,
210 SmallVectorImpl
<MCFixup
> &Fixups
,
211 const MCSubtargetInfo
&STI
) const {
213 return Ctx
.getRegisterInfo()->getEncodingValue(MO
.getReg());
215 assert(MO
.isImm() && "did not expect relocated expression");
216 return static_cast<unsigned>(MO
.getImm());
219 template<unsigned FixupKind
> uint32_t
220 AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst
&MI
, unsigned OpIdx
,
221 SmallVectorImpl
<MCFixup
> &Fixups
,
222 const MCSubtargetInfo
&STI
) const {
223 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
227 ImmVal
= static_cast<uint32_t>(MO
.getImm());
229 assert(MO
.isExpr() && "unable to encode load/store imm operand");
230 MCFixupKind Kind
= MCFixupKind(FixupKind
);
231 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(), Kind
, MI
.getLoc()));
238 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
241 AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst
&MI
, unsigned OpIdx
,
242 SmallVectorImpl
<MCFixup
> &Fixups
,
243 const MCSubtargetInfo
&STI
) const {
244 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
246 // If the destination is an immediate, we have nothing to do.
249 assert(MO
.isExpr() && "Unexpected target type!");
250 const MCExpr
*Expr
= MO
.getExpr();
252 MCFixupKind Kind
= MI
.getOpcode() == AArch64::ADR
253 ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21
)
254 : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21
);
255 Fixups
.push_back(MCFixup::create(0, Expr
, Kind
, MI
.getLoc()));
259 // All of the information is in the fixup.
263 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
264 /// the 2-bit shift field. The shift field is stored in bits 13-14 of the
267 AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst
&MI
, unsigned OpIdx
,
268 SmallVectorImpl
<MCFixup
> &Fixups
,
269 const MCSubtargetInfo
&STI
) const {
270 // Suboperands are [imm, shifter].
271 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
272 const MCOperand
&MO1
= MI
.getOperand(OpIdx
+ 1);
273 assert(AArch64_AM::getShiftType(MO1
.getImm()) == AArch64_AM::LSL
&&
274 "unexpected shift type for add/sub immediate");
275 unsigned ShiftVal
= AArch64_AM::getShiftValue(MO1
.getImm());
276 assert((ShiftVal
== 0 || ShiftVal
== 12) &&
277 "unexpected shift value for add/sub immediate");
279 return MO
.getImm() | (ShiftVal
== 0 ? 0 : (1 << ShiftVal
));
280 assert(MO
.isExpr() && "Unable to encode MCOperand!");
281 const MCExpr
*Expr
= MO
.getExpr();
283 // Encode the 12 bits of the fixup.
284 MCFixupKind Kind
= MCFixupKind(AArch64::fixup_aarch64_add_imm12
);
285 Fixups
.push_back(MCFixup::create(0, Expr
, Kind
, MI
.getLoc()));
289 // Set the shift bit of the add instruction for relocation types
290 // R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLD_ADD_DTPREL_HI12.
291 if (const AArch64MCExpr
*A64E
= dyn_cast
<AArch64MCExpr
>(Expr
)) {
292 AArch64MCExpr::VariantKind RefKind
= A64E
->getKind();
293 if (RefKind
== AArch64MCExpr::VK_TPREL_HI12
||
294 RefKind
== AArch64MCExpr::VK_DTPREL_HI12
||
295 RefKind
== AArch64MCExpr::VK_SECREL_HI12
)
298 return ShiftVal
== 0 ? 0 : (1 << ShiftVal
);
301 /// getCondBranchTargetOpValue - Return the encoded value for a conditional
303 uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(
304 const MCInst
&MI
, unsigned OpIdx
, SmallVectorImpl
<MCFixup
> &Fixups
,
305 const MCSubtargetInfo
&STI
) const {
306 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
308 // If the destination is an immediate, we have nothing to do.
311 assert(MO
.isExpr() && "Unexpected target type!");
313 MCFixupKind Kind
= MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19
);
314 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(), Kind
, MI
.getLoc()));
318 // All of the information is in the fixup.
322 /// getLoadLiteralOpValue - Return the encoded value for a load-literal
323 /// pc-relative address.
325 AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst
&MI
, unsigned OpIdx
,
326 SmallVectorImpl
<MCFixup
> &Fixups
,
327 const MCSubtargetInfo
&STI
) const {
328 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
330 // If the destination is an immediate, we have nothing to do.
333 assert(MO
.isExpr() && "Unexpected target type!");
335 MCFixupKind Kind
= MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19
);
336 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(), Kind
, MI
.getLoc()));
340 // All of the information is in the fixup.
345 AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst
&MI
, unsigned OpIdx
,
346 SmallVectorImpl
<MCFixup
> &Fixups
,
347 const MCSubtargetInfo
&STI
) const {
348 unsigned SignExtend
= MI
.getOperand(OpIdx
).getImm();
349 unsigned DoShift
= MI
.getOperand(OpIdx
+ 1).getImm();
350 return (SignExtend
<< 1) | DoShift
;
354 AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst
&MI
, unsigned OpIdx
,
355 SmallVectorImpl
<MCFixup
> &Fixups
,
356 const MCSubtargetInfo
&STI
) const {
357 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
361 assert(MO
.isExpr() && "Unexpected movz/movk immediate");
363 Fixups
.push_back(MCFixup::create(
364 0, MO
.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw
), MI
.getLoc()));
371 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
373 uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue(
374 const MCInst
&MI
, unsigned OpIdx
, SmallVectorImpl
<MCFixup
> &Fixups
,
375 const MCSubtargetInfo
&STI
) const {
376 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
378 // If the destination is an immediate, we have nothing to do.
381 assert(MO
.isExpr() && "Unexpected ADR target type!");
383 MCFixupKind Kind
= MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14
);
384 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(), Kind
, MI
.getLoc()));
388 // All of the information is in the fixup.
392 /// getBranchTargetOpValue - Return the encoded value for an unconditional
395 AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst
&MI
, unsigned OpIdx
,
396 SmallVectorImpl
<MCFixup
> &Fixups
,
397 const MCSubtargetInfo
&STI
) const {
398 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
400 // If the destination is an immediate, we have nothing to do.
403 assert(MO
.isExpr() && "Unexpected ADR target type!");
405 MCFixupKind Kind
= MI
.getOpcode() == AArch64::BL
406 ? MCFixupKind(AArch64::fixup_aarch64_pcrel_call26
)
407 : MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26
);
408 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(), Kind
, MI
.getLoc()));
412 // All of the information is in the fixup.
416 /// getVecShifterOpValue - Return the encoded value for the vector shifter:
423 AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst
&MI
, unsigned OpIdx
,
424 SmallVectorImpl
<MCFixup
> &Fixups
,
425 const MCSubtargetInfo
&STI
) const {
426 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
427 assert(MO
.isImm() && "Expected an immediate value for the shift amount!");
429 switch (MO
.getImm()) {
442 llvm_unreachable("Invalid value for vector shift amount!");
445 /// getFixedPointScaleOpValue - Return the encoded value for the
446 // FP-to-fixed-point scale factor.
447 uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue(
448 const MCInst
&MI
, unsigned OpIdx
, SmallVectorImpl
<MCFixup
> &Fixups
,
449 const MCSubtargetInfo
&STI
) const {
450 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
451 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
452 return 64 - MO
.getImm();
456 AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst
&MI
, unsigned OpIdx
,
457 SmallVectorImpl
<MCFixup
> &Fixups
,
458 const MCSubtargetInfo
&STI
) const {
459 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
460 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
461 return 64 - MO
.getImm();
465 AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst
&MI
, unsigned OpIdx
,
466 SmallVectorImpl
<MCFixup
> &Fixups
,
467 const MCSubtargetInfo
&STI
) const {
468 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
469 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
470 return 32 - MO
.getImm();
474 AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst
&MI
, unsigned OpIdx
,
475 SmallVectorImpl
<MCFixup
> &Fixups
,
476 const MCSubtargetInfo
&STI
) const {
477 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
478 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
479 return 16 - MO
.getImm();
483 AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst
&MI
, unsigned OpIdx
,
484 SmallVectorImpl
<MCFixup
> &Fixups
,
485 const MCSubtargetInfo
&STI
) const {
486 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
487 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
488 return 8 - MO
.getImm();
492 AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst
&MI
, unsigned OpIdx
,
493 SmallVectorImpl
<MCFixup
> &Fixups
,
494 const MCSubtargetInfo
&STI
) const {
495 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
496 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
497 return MO
.getImm() - 64;
501 AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst
&MI
, unsigned OpIdx
,
502 SmallVectorImpl
<MCFixup
> &Fixups
,
503 const MCSubtargetInfo
&STI
) const {
504 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
505 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
506 return MO
.getImm() - 32;
510 AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst
&MI
, unsigned OpIdx
,
511 SmallVectorImpl
<MCFixup
> &Fixups
,
512 const MCSubtargetInfo
&STI
) const {
513 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
514 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
515 return MO
.getImm() - 16;
519 AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst
&MI
, unsigned OpIdx
,
520 SmallVectorImpl
<MCFixup
> &Fixups
,
521 const MCSubtargetInfo
&STI
) const {
522 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
523 assert(MO
.isImm() && "Expected an immediate value for the scale amount!");
524 return MO
.getImm() - 8;
527 uint32_t AArch64MCCodeEmitter::EncodeMatrixTileListRegisterClass(
528 const MCInst
&MI
, unsigned OpIdx
, SmallVectorImpl
<MCFixup
> &Fixups
,
529 const MCSubtargetInfo
&STI
) const {
530 unsigned RegMask
= MI
.getOperand(OpIdx
).getImm();
531 assert(RegMask
<= 0xFF && "Invalid register mask!");
536 AArch64MCCodeEmitter::encodeMatrixIndexGPR32(const MCInst
&MI
, unsigned OpIdx
,
537 SmallVectorImpl
<MCFixup
> &Fixups
,
538 const MCSubtargetInfo
&STI
) const {
539 auto RegOpnd
= MI
.getOperand(OpIdx
).getReg();
540 assert(RegOpnd
>= AArch64::W12
&& RegOpnd
<= AArch64::W15
&&
541 "Expected register in the range w12-w15!");
542 return RegOpnd
- AArch64::W12
;
546 AArch64MCCodeEmitter::getImm8OptLsl(const MCInst
&MI
, unsigned OpIdx
,
547 SmallVectorImpl
<MCFixup
> &Fixups
,
548 const MCSubtargetInfo
&STI
) const {
550 auto ShiftOpnd
= MI
.getOperand(OpIdx
+ 1).getImm();
551 assert(AArch64_AM::getShiftType(ShiftOpnd
) == AArch64_AM::LSL
&&
552 "Unexpected shift type for imm8_opt_lsl immediate.");
554 unsigned ShiftVal
= AArch64_AM::getShiftValue(ShiftOpnd
);
555 assert((ShiftVal
== 0 || ShiftVal
== 8) &&
556 "Unexpected shift value for imm8_opt_lsl immediate.");
559 auto Immediate
= MI
.getOperand(OpIdx
).getImm();
560 return (Immediate
& 0xff) | (ShiftVal
== 0 ? 0 : (1 << ShiftVal
));
564 AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst
&MI
, unsigned OpIdx
,
565 SmallVectorImpl
<MCFixup
> &Fixups
,
566 const MCSubtargetInfo
&STI
) const {
567 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
568 assert(MO
.isImm() && "Expected an immediate value!");
569 // Normalize 1-16 range to 0-15.
570 return MO
.getImm() - 1;
573 /// getMoveVecShifterOpValue - Return the encoded value for the vector move
575 uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue(
576 const MCInst
&MI
, unsigned OpIdx
, SmallVectorImpl
<MCFixup
> &Fixups
,
577 const MCSubtargetInfo
&STI
) const {
578 const MCOperand
&MO
= MI
.getOperand(OpIdx
);
580 "Expected an immediate value for the move shift amount!");
581 unsigned ShiftVal
= AArch64_AM::getShiftValue(MO
.getImm());
582 assert((ShiftVal
== 8 || ShiftVal
== 16) && "Invalid shift amount!");
583 return ShiftVal
== 8 ? 0 : 1;
586 unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst
&MI
, unsigned EncodedValue
,
587 const MCSubtargetInfo
&STI
) const {
588 // If one of the signed fixup kinds is applied to a MOVZ instruction, the
589 // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's
590 // job to ensure that any bits possibly affected by this are 0. This means we
591 // must zero out bit 30 (essentially emitting a MOVN).
592 MCOperand UImm16MO
= MI
.getOperand(1);
594 // Nothing to do if there's no fixup.
595 if (UImm16MO
.isImm())
598 const MCExpr
*E
= UImm16MO
.getExpr();
599 if (const AArch64MCExpr
*A64E
= dyn_cast
<AArch64MCExpr
>(E
)) {
600 switch (A64E
->getKind()) {
601 case AArch64MCExpr::VK_DTPREL_G2
:
602 case AArch64MCExpr::VK_DTPREL_G1
:
603 case AArch64MCExpr::VK_DTPREL_G0
:
604 case AArch64MCExpr::VK_GOTTPREL_G1
:
605 case AArch64MCExpr::VK_TPREL_G2
:
606 case AArch64MCExpr::VK_TPREL_G1
:
607 case AArch64MCExpr::VK_TPREL_G0
:
608 return EncodedValue
& ~(1u << 30);
610 // Nothing to do for an unsigned fixup.
618 void AArch64MCCodeEmitter::encodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
619 SmallVectorImpl
<MCFixup
> &Fixups
,
620 const MCSubtargetInfo
&STI
) const {
621 verifyInstructionPredicates(MI
,
622 computeAvailableFeatures(STI
.getFeatureBits()));
624 if (MI
.getOpcode() == AArch64::TLSDESCCALL
) {
625 // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the
626 // following (BLR) instruction. It doesn't emit any code itself so it
627 // doesn't go through the normal TableGenerated channels.
628 auto Reloc
= STI
.getTargetTriple().getEnvironment() == Triple::GNUILP32
629 ? ELF::R_AARCH64_P32_TLSDESC_CALL
630 : ELF::R_AARCH64_TLSDESC_CALL
;
632 MCFixup::create(0, MI
.getOperand(0).getExpr(),
633 MCFixupKind(FirstLiteralRelocationKind
+ Reloc
)));
637 if (MI
.getOpcode() == AArch64::CompilerBarrier
||
638 MI
.getOpcode() == AArch64::SPACE
) {
639 // CompilerBarrier just prevents the compiler from reordering accesses, and
640 // SPACE just increases basic block size, in both cases no actual code.
644 uint64_t Binary
= getBinaryCodeForInstr(MI
, Fixups
, STI
);
645 support::endian::write
<uint32_t>(OS
, Binary
, support::little
);
646 ++MCNumEmitted
; // Keep track of the # of mi's emitted.
650 AArch64MCCodeEmitter::fixMulHigh(const MCInst
&MI
,
651 unsigned EncodedValue
,
652 const MCSubtargetInfo
&STI
) const {
653 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
654 // (i.e. all bits 1) but is ignored by the processor.
655 EncodedValue
|= 0x1f << 10;
659 template<int hasRs
, int hasRt2
> unsigned
660 AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst
&MI
,
661 unsigned EncodedValue
,
662 const MCSubtargetInfo
&STI
) const {
663 if (!hasRs
) EncodedValue
|= 0x001F0000;
664 if (!hasRt2
) EncodedValue
|= 0x00007C00;
669 unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison(
670 const MCInst
&MI
, unsigned EncodedValue
, const MCSubtargetInfo
&STI
) const {
671 // The Rm field of FCMP and friends is unused - it should be assembled
672 // as 0, but is ignored by the processor.
673 EncodedValue
&= ~(0x1f << 16);
677 #define ENABLE_INSTR_PREDICATE_VERIFIER
678 #include "AArch64GenMCCodeEmitter.inc"
680 MCCodeEmitter
*llvm::createAArch64MCCodeEmitter(const MCInstrInfo
&MCII
,
682 return new AArch64MCCodeEmitter(MCII
, Ctx
);