1 //===-- ARM64/ARM64MCCodeEmitter.cpp - Convert ARM64 code to machine code -===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the ARM64MCCodeEmitter class.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "mccodeemitter"
15 #include "MCTargetDesc/ARM64AddressingModes.h"
16 #include "MCTargetDesc/ARM64BaseInfo.h"
17 #include "MCTargetDesc/ARM64FixupKinds.h"
18 #include "MCTargetDesc/ARM64MCExpr.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCRegisterInfo.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/ADT/Statistic.h"
26 #include "llvm/Support/raw_ostream.h"
29 STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
30 STATISTIC(MCNumFixups, "Number of MC fixups created.");
34 class ARM64MCCodeEmitter : public MCCodeEmitter {
37 ARM64MCCodeEmitter(const ARM64MCCodeEmitter &); // DO NOT IMPLEMENT
38 void operator=(const ARM64MCCodeEmitter &); // DO NOT IMPLEMENT
40 ARM64MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
44 ~ARM64MCCodeEmitter() {}
46 // getBinaryCodeForInstr - TableGen'erated function for getting the
47 // binary encoding for an instruction.
48 uint64_t getBinaryCodeForInstr(const MCInst &MI,
49 SmallVectorImpl<MCFixup> &Fixups,
50 const MCSubtargetInfo &STI) const;
52 /// getMachineOpValue - Return binary encoding of operand. If the machine
53 /// operand requires relocation, record the relocation and return zero.
54 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
55 SmallVectorImpl<MCFixup> &Fixups,
56 const MCSubtargetInfo &STI) const;
58 /// getAMIndexed8OpValue - Return encoding info for base register
59 /// and 12-bit unsigned immediate attached to a load, store or prfm
60 /// instruction. If operand requires a relocation, record it and
61 /// return zero in that part of the encoding.
62 template <uint32_t FixupKind>
63 uint32_t getAMIndexed8OpValue(const MCInst &MI, unsigned OpIdx,
64 SmallVectorImpl<MCFixup> &Fixups,
65 const MCSubtargetInfo &STI) const;
67 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
69 uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
70 SmallVectorImpl<MCFixup> &Fixups,
71 const MCSubtargetInfo &STI) const;
73 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
74 /// the 2-bit shift field.
75 uint32_t getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
76 SmallVectorImpl<MCFixup> &Fixups,
77 const MCSubtargetInfo &STI) const;
79 /// getCondBranchTargetOpValue - Return the encoded value for a conditional
81 uint32_t getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
82 SmallVectorImpl<MCFixup> &Fixups,
83 const MCSubtargetInfo &STI) const;
85 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
87 uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
88 SmallVectorImpl<MCFixup> &Fixups,
89 const MCSubtargetInfo &STI) const;
91 /// getBranchTargetOpValue - Return the encoded value for an unconditional
93 uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
94 SmallVectorImpl<MCFixup> &Fixups,
95 const MCSubtargetInfo &STI) const;
97 /// getMoveWideImmOpValue - Return the encoded value for the immediate operand
98 /// of a MOVZ or MOVK instruction.
99 uint32_t getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
100 SmallVectorImpl<MCFixup> &Fixups,
101 const MCSubtargetInfo &STI) const;
103 /// getVecShifterOpValue - Return the encoded value for the vector shifter.
104 uint32_t getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
105 SmallVectorImpl<MCFixup> &Fixups,
106 const MCSubtargetInfo &STI) const;
108 /// getMoveVecShifterOpValue - Return the encoded value for the vector move
110 uint32_t getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
111 SmallVectorImpl<MCFixup> &Fixups,
112 const MCSubtargetInfo &STI) const;
114 /// getFixedPointScaleOpValue - Return the encoded value for the
115 // FP-to-fixed-point scale factor.
116 uint32_t getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx,
117 SmallVectorImpl<MCFixup> &Fixups,
118 const MCSubtargetInfo &STI) const;
120 uint32_t getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
121 SmallVectorImpl<MCFixup> &Fixups,
122 const MCSubtargetInfo &STI) const;
123 uint32_t getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
124 SmallVectorImpl<MCFixup> &Fixups,
125 const MCSubtargetInfo &STI) const;
126 uint32_t getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
127 SmallVectorImpl<MCFixup> &Fixups,
128 const MCSubtargetInfo &STI) const;
129 uint32_t getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
130 SmallVectorImpl<MCFixup> &Fixups,
131 const MCSubtargetInfo &STI) const;
132 uint32_t getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
133 SmallVectorImpl<MCFixup> &Fixups,
134 const MCSubtargetInfo &STI) const;
135 uint32_t getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
136 SmallVectorImpl<MCFixup> &Fixups,
137 const MCSubtargetInfo &STI) const;
138 uint32_t getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
139 SmallVectorImpl<MCFixup> &Fixups,
140 const MCSubtargetInfo &STI) const;
141 uint32_t getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
142 SmallVectorImpl<MCFixup> &Fixups,
143 const MCSubtargetInfo &STI) const;
145 /// getSIMDShift64OpValue - Return the encoded value for the
146 // shift-by-immediate AdvSIMD instructions.
147 uint32_t getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx,
148 SmallVectorImpl<MCFixup> &Fixups,
149 const MCSubtargetInfo &STI) const;
151 uint32_t getSIMDShift64_32OpValue(const MCInst &MI, unsigned OpIdx,
152 SmallVectorImpl<MCFixup> &Fixups,
153 const MCSubtargetInfo &STI) const;
155 uint32_t getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx,
156 SmallVectorImpl<MCFixup> &Fixups,
157 const MCSubtargetInfo &STI) const;
159 uint32_t getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx,
160 SmallVectorImpl<MCFixup> &Fixups,
161 const MCSubtargetInfo &STI) const;
163 unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue,
164 const MCSubtargetInfo &STI) const;
166 void EmitByte(unsigned char C, raw_ostream &OS) const { OS << (char)C; }
168 void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
169 // Output the constant in little endian byte order.
170 for (unsigned i = 0; i != Size; ++i) {
171 EmitByte(Val & 255, OS);
176 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
177 SmallVectorImpl<MCFixup> &Fixups,
178 const MCSubtargetInfo &STI) const;
181 } // end anonymous namespace
183 MCCodeEmitter *llvm::createARM64MCCodeEmitter(const MCInstrInfo &MCII,
184 const MCRegisterInfo &MRI,
185 const MCSubtargetInfo &STI,
187 return new ARM64MCCodeEmitter(MCII, STI, Ctx);
190 /// getMachineOpValue - Return binary encoding of operand. If the machine
191 /// operand requires relocation, record the relocation and return zero.
193 ARM64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
194 SmallVectorImpl<MCFixup> &Fixups,
195 const MCSubtargetInfo &STI) const {
197 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
199 assert(MO.isImm() && "did not expect relocated expression");
200 return static_cast<unsigned>(MO.getImm());
203 assert(0 && "Unable to encode MCOperand!");
207 template <uint32_t FixupKind>
209 ARM64MCCodeEmitter::getAMIndexed8OpValue(const MCInst &MI, unsigned OpIdx,
210 SmallVectorImpl<MCFixup> &Fixups,
211 const MCSubtargetInfo &STI) const {
212 unsigned BaseReg = MI.getOperand(OpIdx).getReg();
213 BaseReg = Ctx.getRegisterInfo()->getEncodingValue(BaseReg);
215 const MCOperand &MO = MI.getOperand(OpIdx + 1);
219 ImmVal = static_cast<uint32_t>(MO.getImm());
221 assert(MO.isExpr() && "unable to encode load/store imm operand");
222 MCFixupKind Kind = MCFixupKind(FixupKind);
223 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
227 return BaseReg | (ImmVal << 5);
230 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
233 ARM64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
234 SmallVectorImpl<MCFixup> &Fixups,
235 const MCSubtargetInfo &STI) const {
236 const MCOperand &MO = MI.getOperand(OpIdx);
238 // If the destination is an immediate, we have nothing to do.
241 assert(MO.isExpr() && "Unexpected ADR target type!");
242 const MCExpr *Expr = MO.getExpr();
244 MCFixupKind Kind = MI.getOpcode() == ARM64::ADR
245 ? MCFixupKind(ARM64::fixup_arm64_pcrel_adr_imm21)
246 : MCFixupKind(ARM64::fixup_arm64_pcrel_adrp_imm21);
247 Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
251 // All of the information is in the fixup.
255 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
256 /// the 2-bit shift field. The shift field is stored in bits 13-14 of the
259 ARM64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
260 SmallVectorImpl<MCFixup> &Fixups,
261 const MCSubtargetInfo &STI) const {
262 // Suboperands are [imm, shifter].
263 const MCOperand &MO = MI.getOperand(OpIdx);
264 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
265 assert(ARM64_AM::getShiftType(MO1.getImm()) == ARM64_AM::LSL &&
266 "unexpected shift type for add/sub immediate");
267 unsigned ShiftVal = ARM64_AM::getShiftValue(MO1.getImm());
268 assert((ShiftVal == 0 || ShiftVal == 12) &&
269 "unexpected shift value for add/sub immediate");
271 return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << 12));
272 assert(MO.isExpr() && "Unable to encode MCOperand!");
273 const MCExpr *Expr = MO.getExpr();
274 assert(ShiftVal == 0 && "shift not allowed on add/sub immediate with fixup");
276 // Encode the 12 bits of the fixup.
277 MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_add_imm12);
278 Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
285 /// getCondBranchTargetOpValue - Return the encoded value for a conditional
287 uint32_t ARM64MCCodeEmitter::getCondBranchTargetOpValue(
288 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
289 const MCSubtargetInfo &STI) const {
290 const MCOperand &MO = MI.getOperand(OpIdx);
292 // If the destination is an immediate, we have nothing to do.
295 assert(MO.isExpr() && "Unexpected target type!");
297 MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_pcrel_imm19);
298 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
302 // All of the information is in the fixup.
307 ARM64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
308 SmallVectorImpl<MCFixup> &Fixups,
309 const MCSubtargetInfo &STI) const {
310 const MCOperand &MO = MI.getOperand(OpIdx);
314 assert(MO.isExpr() && "Unexpected movz/movk immediate");
316 Fixups.push_back(MCFixup::Create(
317 0, MO.getExpr(), MCFixupKind(ARM64::fixup_arm64_movw), MI.getLoc()));
324 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
326 uint32_t ARM64MCCodeEmitter::getTestBranchTargetOpValue(
327 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
328 const MCSubtargetInfo &STI) const {
329 const MCOperand &MO = MI.getOperand(OpIdx);
331 // If the destination is an immediate, we have nothing to do.
334 assert(MO.isExpr() && "Unexpected ADR target type!");
336 MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_pcrel_branch14);
337 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
341 // All of the information is in the fixup.
345 /// getBranchTargetOpValue - Return the encoded value for an unconditional
348 ARM64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
349 SmallVectorImpl<MCFixup> &Fixups,
350 const MCSubtargetInfo &STI) const {
351 const MCOperand &MO = MI.getOperand(OpIdx);
353 // If the destination is an immediate, we have nothing to do.
356 assert(MO.isExpr() && "Unexpected ADR target type!");
358 MCFixupKind Kind = MI.getOpcode() == ARM64::BL
359 ? MCFixupKind(ARM64::fixup_arm64_pcrel_call26)
360 : MCFixupKind(ARM64::fixup_arm64_pcrel_branch26);
361 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
365 // All of the information is in the fixup.
369 /// getVecShifterOpValue - Return the encoded value for the vector shifter:
376 ARM64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
377 SmallVectorImpl<MCFixup> &Fixups,
378 const MCSubtargetInfo &STI) const {
379 const MCOperand &MO = MI.getOperand(OpIdx);
380 assert(MO.isImm() && "Expected an immediate value for the shift amount!");
382 switch (MO.getImm()) {
395 assert(false && "Invalid value for vector shift amount!");
400 ARM64MCCodeEmitter::getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx,
401 SmallVectorImpl<MCFixup> &Fixups,
402 const MCSubtargetInfo &STI) const {
403 const MCOperand &MO = MI.getOperand(OpIdx);
404 assert(MO.isImm() && "Expected an immediate value for the shift amount!");
405 return 64 - (MO.getImm());
409 ARM64MCCodeEmitter::getSIMDShift64_32OpValue(const MCInst &MI, unsigned OpIdx,
410 SmallVectorImpl<MCFixup> &Fixups,
411 const MCSubtargetInfo &STI) const {
412 const MCOperand &MO = MI.getOperand(OpIdx);
413 assert(MO.isImm() && "Expected an immediate value for the shift amount!");
414 return 64 - (MO.getImm() | 32);
418 ARM64MCCodeEmitter::getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx,
419 SmallVectorImpl<MCFixup> &Fixups,
420 const MCSubtargetInfo &STI) const {
421 const MCOperand &MO = MI.getOperand(OpIdx);
422 assert(MO.isImm() && "Expected an immediate value for the shift amount!");
423 return 32 - (MO.getImm() | 16);
427 ARM64MCCodeEmitter::getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx,
428 SmallVectorImpl<MCFixup> &Fixups,
429 const MCSubtargetInfo &STI) const {
430 const MCOperand &MO = MI.getOperand(OpIdx);
431 assert(MO.isImm() && "Expected an immediate value for the shift amount!");
432 return 16 - (MO.getImm() | 8);
435 /// getFixedPointScaleOpValue - Return the encoded value for the
436 // FP-to-fixed-point scale factor.
437 uint32_t ARM64MCCodeEmitter::getFixedPointScaleOpValue(
438 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
439 const MCSubtargetInfo &STI) const {
440 const MCOperand &MO = MI.getOperand(OpIdx);
441 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
442 return 64 - MO.getImm();
446 ARM64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
447 SmallVectorImpl<MCFixup> &Fixups,
448 const MCSubtargetInfo &STI) const {
449 const MCOperand &MO = MI.getOperand(OpIdx);
450 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
451 return 64 - MO.getImm();
455 ARM64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
456 SmallVectorImpl<MCFixup> &Fixups,
457 const MCSubtargetInfo &STI) const {
458 const MCOperand &MO = MI.getOperand(OpIdx);
459 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
460 return 32 - MO.getImm();
464 ARM64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
465 SmallVectorImpl<MCFixup> &Fixups,
466 const MCSubtargetInfo &STI) const {
467 const MCOperand &MO = MI.getOperand(OpIdx);
468 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
469 return 16 - MO.getImm();
473 ARM64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
474 SmallVectorImpl<MCFixup> &Fixups,
475 const MCSubtargetInfo &STI) const {
476 const MCOperand &MO = MI.getOperand(OpIdx);
477 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
478 return 8 - MO.getImm();
482 ARM64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
483 SmallVectorImpl<MCFixup> &Fixups,
484 const MCSubtargetInfo &STI) const {
485 const MCOperand &MO = MI.getOperand(OpIdx);
486 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
487 return MO.getImm() - 64;
491 ARM64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
492 SmallVectorImpl<MCFixup> &Fixups,
493 const MCSubtargetInfo &STI) const {
494 const MCOperand &MO = MI.getOperand(OpIdx);
495 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
496 return MO.getImm() - 32;
500 ARM64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
501 SmallVectorImpl<MCFixup> &Fixups,
502 const MCSubtargetInfo &STI) const {
503 const MCOperand &MO = MI.getOperand(OpIdx);
504 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
505 return MO.getImm() - 16;
509 ARM64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
510 SmallVectorImpl<MCFixup> &Fixups,
511 const MCSubtargetInfo &STI) const {
512 const MCOperand &MO = MI.getOperand(OpIdx);
513 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
514 return MO.getImm() - 8;
517 /// getMoveVecShifterOpValue - Return the encoded value for the vector move
520 ARM64MCCodeEmitter::getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
521 SmallVectorImpl<MCFixup> &Fixups,
522 const MCSubtargetInfo &STI) const {
523 const MCOperand &MO = MI.getOperand(OpIdx);
525 "Expected an immediate value for the move shift amount!");
526 unsigned ShiftVal = ARM64_AM::getShiftValue(MO.getImm());
527 assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!");
528 return ShiftVal == 8 ? 0 : 1;
531 unsigned ARM64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
532 const MCSubtargetInfo &STI) const {
533 // If one of the signed fixup kinds is applied to a MOVZ instruction, the
534 // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's
535 // job to ensure that any bits possibly affected by this are 0. This means we
536 // must zero out bit 30 (essentially emitting a MOVN).
537 MCOperand UImm16MO = MI.getOperand(1);
539 // Nothing to do if there's no fixup.
540 if (UImm16MO.isImm())
543 return EncodedValue & ~(1u << 30);
546 void ARM64MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
547 SmallVectorImpl<MCFixup> &Fixups,
548 const MCSubtargetInfo &STI) const {
549 if (MI.getOpcode() == ARM64::TLSDESCCALL) {
550 // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the
551 // following (BLR) instruction. It doesn't emit any code itself so it
552 // doesn't go through the normal TableGenerated channels.
553 MCFixupKind Fixup = MCFixupKind(ARM64::fixup_arm64_tlsdesc_call);
554 Fixups.push_back(MCFixup::Create(0, MI.getOperand(0).getExpr(), Fixup));
558 uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
559 EmitConstant(Binary, 4, OS);
560 ++MCNumEmitted; // Keep track of the # of mi's emitted.
563 #include "ARM64GenMCCodeEmitter.inc"