[AMDGPU] New gfx940 mfma instructions
[llvm-project.git] / llvm / lib / Target / AArch64 / MCTargetDesc / AArch64MCCodeEmitter.cpp
blob2901e5c0fe4da4087592aa9b095525fe7fc77f52
1 //=- AArch64/AArch64MCCodeEmitter.cpp - Convert AArch64 code to machine code-=//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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"
32 #include <cassert>
33 #include <cstdint>
35 using namespace llvm;
37 #define DEBUG_TYPE "mccodeemitter"
39 STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
40 STATISTIC(MCNumFixups, "Number of MC fixups created.");
42 namespace {
44 class AArch64MCCodeEmitter : public MCCodeEmitter {
45 MCContext &Ctx;
46 const MCInstrInfo &MCII;
48 public:
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
76 /// target.
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
88 /// branch target.
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-
107 /// branch target.
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
113 /// branch target.
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
130 /// shifter (MSL).
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;
197 private:
198 FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
199 void
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.
208 unsigned
209 AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
210 SmallVectorImpl<MCFixup> &Fixups,
211 const MCSubtargetInfo &STI) const {
212 if (MO.isReg())
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);
224 uint32_t ImmVal = 0;
226 if (MO.isImm())
227 ImmVal = static_cast<uint32_t>(MO.getImm());
228 else {
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()));
232 ++MCNumFixups;
235 return ImmVal;
238 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
239 /// target.
240 uint32_t
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.
247 if (MO.isImm())
248 return MO.getImm();
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()));
257 MCNumFixups += 1;
259 // All of the information is in the fixup.
260 return 0;
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
265 /// return value.
266 uint32_t
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");
278 if (MO.isImm())
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()));
287 ++MCNumFixups;
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)
296 ShiftVal = 12;
298 return ShiftVal == 0 ? 0 : (1 << ShiftVal);
301 /// getCondBranchTargetOpValue - Return the encoded value for a conditional
302 /// branch target.
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.
309 if (MO.isImm())
310 return MO.getImm();
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()));
316 ++MCNumFixups;
318 // All of the information is in the fixup.
319 return 0;
322 /// getLoadLiteralOpValue - Return the encoded value for a load-literal
323 /// pc-relative address.
324 uint32_t
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.
331 if (MO.isImm())
332 return MO.getImm();
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()));
338 ++MCNumFixups;
340 // All of the information is in the fixup.
341 return 0;
344 uint32_t
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;
353 uint32_t
354 AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
355 SmallVectorImpl<MCFixup> &Fixups,
356 const MCSubtargetInfo &STI) const {
357 const MCOperand &MO = MI.getOperand(OpIdx);
359 if (MO.isImm())
360 return MO.getImm();
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()));
366 ++MCNumFixups;
368 return 0;
371 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
372 /// branch target.
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.
379 if (MO.isImm())
380 return MO.getImm();
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()));
386 ++MCNumFixups;
388 // All of the information is in the fixup.
389 return 0;
392 /// getBranchTargetOpValue - Return the encoded value for an unconditional
393 /// branch target.
394 uint32_t
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.
401 if (MO.isImm())
402 return MO.getImm();
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()));
410 ++MCNumFixups;
412 // All of the information is in the fixup.
413 return 0;
416 /// getVecShifterOpValue - Return the encoded value for the vector shifter:
418 /// 00 -> 0
419 /// 01 -> 8
420 /// 10 -> 16
421 /// 11 -> 24
422 uint32_t
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()) {
430 default:
431 break;
432 case 0:
433 return 0;
434 case 8:
435 return 1;
436 case 16:
437 return 2;
438 case 24:
439 return 3;
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();
455 uint32_t
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();
464 uint32_t
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();
473 uint32_t
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();
482 uint32_t
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();
491 uint32_t
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;
500 uint32_t
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;
509 uint32_t
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;
518 uint32_t
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!");
532 return RegMask;
535 uint32_t
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;
545 uint32_t
546 AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
547 SmallVectorImpl<MCFixup> &Fixups,
548 const MCSubtargetInfo &STI) const {
549 // Test shift
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.");
558 // Test immediate
559 auto Immediate = MI.getOperand(OpIdx).getImm();
560 return (Immediate & 0xff) | (ShiftVal == 0 ? 0 : (1 << ShiftVal));
563 uint32_t
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
574 /// shifter (MSL).
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);
579 assert(MO.isImm() &&
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())
596 return EncodedValue;
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);
609 default:
610 // Nothing to do for an unsigned fixup.
611 return EncodedValue;
615 return EncodedValue;
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;
631 Fixups.push_back(
632 MCFixup::create(0, MI.getOperand(0).getExpr(),
633 MCFixupKind(FirstLiteralRelocationKind + Reloc)));
634 return;
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.
641 return;
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.
649 unsigned
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;
656 return EncodedValue;
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;
666 return EncodedValue;
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);
674 return EncodedValue;
677 #define ENABLE_INSTR_PREDICATE_VERIFIER
678 #include "AArch64GenMCCodeEmitter.inc"
680 MCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII,
681 MCContext &Ctx) {
682 return new AArch64MCCodeEmitter(MCII, Ctx);