/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
Line | Count | Source (jump to first uncovered line) |
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. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
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/MC/MCCodeEmitter.h" |
20 | | #include "llvm/MC/MCContext.h" |
21 | | #include "llvm/MC/MCFixup.h" |
22 | | #include "llvm/MC/MCInst.h" |
23 | | #include "llvm/MC/MCInstrInfo.h" |
24 | | #include "llvm/MC/MCRegisterInfo.h" |
25 | | #include "llvm/MC/MCSubtargetInfo.h" |
26 | | #include "llvm/Support/Casting.h" |
27 | | #include "llvm/Support/Endian.h" |
28 | | #include "llvm/Support/EndianStream.h" |
29 | | #include "llvm/Support/ErrorHandling.h" |
30 | | #include "llvm/Support/raw_ostream.h" |
31 | | #include <cassert> |
32 | | #include <cstdint> |
33 | | |
34 | | using namespace llvm; |
35 | | |
36 | | #define DEBUG_TYPE "mccodeemitter" |
37 | | |
38 | | STATISTIC(MCNumEmitted, "Number of MC instructions emitted."); |
39 | | STATISTIC(MCNumFixups, "Number of MC fixups created."); |
40 | | |
41 | | namespace { |
42 | | |
43 | | class AArch64MCCodeEmitter : public MCCodeEmitter { |
44 | | MCContext &Ctx; |
45 | | const MCInstrInfo &MCII; |
46 | | |
47 | | public: |
48 | | AArch64MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) |
49 | 10.4k | : Ctx(ctx), MCII(mcii) {} |
50 | | AArch64MCCodeEmitter(const AArch64MCCodeEmitter &) = delete; |
51 | | void operator=(const AArch64MCCodeEmitter &) = delete; |
52 | 10.4k | ~AArch64MCCodeEmitter() override = default; |
53 | | |
54 | | // getBinaryCodeForInstr - TableGen'erated function for getting the |
55 | | // binary encoding for an instruction. |
56 | | uint64_t getBinaryCodeForInstr(const MCInst &MI, |
57 | | SmallVectorImpl<MCFixup> &Fixups, |
58 | | const MCSubtargetInfo &STI) const; |
59 | | |
60 | | /// getMachineOpValue - Return binary encoding of operand. If the machine |
61 | | /// operand requires relocation, record the relocation and return zero. |
62 | | unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, |
63 | | SmallVectorImpl<MCFixup> &Fixups, |
64 | | const MCSubtargetInfo &STI) const; |
65 | | |
66 | | /// getLdStUImm12OpValue - Return encoding info for 12-bit unsigned immediate |
67 | | /// attached to a load, store or prfm instruction. If operand requires a |
68 | | /// relocation, record it and return zero in that part of the encoding. |
69 | | template <uint32_t FixupKind> |
70 | | uint32_t getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx, |
71 | | SmallVectorImpl<MCFixup> &Fixups, |
72 | | const MCSubtargetInfo &STI) const; |
73 | | |
74 | | /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label |
75 | | /// target. |
76 | | uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, |
77 | | SmallVectorImpl<MCFixup> &Fixups, |
78 | | const MCSubtargetInfo &STI) const; |
79 | | |
80 | | /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and |
81 | | /// the 2-bit shift field. |
82 | | uint32_t getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, |
83 | | SmallVectorImpl<MCFixup> &Fixups, |
84 | | const MCSubtargetInfo &STI) const; |
85 | | |
86 | | /// getCondBranchTargetOpValue - Return the encoded value for a conditional |
87 | | /// branch target. |
88 | | uint32_t getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, |
89 | | SmallVectorImpl<MCFixup> &Fixups, |
90 | | const MCSubtargetInfo &STI) const; |
91 | | |
92 | | /// getLoadLiteralOpValue - Return the encoded value for a load-literal |
93 | | /// pc-relative address. |
94 | | uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, |
95 | | SmallVectorImpl<MCFixup> &Fixups, |
96 | | const MCSubtargetInfo &STI) const; |
97 | | |
98 | | /// getMemExtendOpValue - Return the encoded value for a reg-extend load/store |
99 | | /// instruction: bit 0 is whether a shift is present, bit 1 is whether the |
100 | | /// operation is a sign extend (as opposed to a zero extend). |
101 | | uint32_t getMemExtendOpValue(const MCInst &MI, unsigned OpIdx, |
102 | | SmallVectorImpl<MCFixup> &Fixups, |
103 | | const MCSubtargetInfo &STI) const; |
104 | | |
105 | | /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and- |
106 | | /// branch target. |
107 | | uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, |
108 | | SmallVectorImpl<MCFixup> &Fixups, |
109 | | const MCSubtargetInfo &STI) const; |
110 | | |
111 | | /// getBranchTargetOpValue - Return the encoded value for an unconditional |
112 | | /// branch target. |
113 | | uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, |
114 | | SmallVectorImpl<MCFixup> &Fixups, |
115 | | const MCSubtargetInfo &STI) const; |
116 | | |
117 | | /// getMoveWideImmOpValue - Return the encoded value for the immediate operand |
118 | | /// of a MOVZ or MOVK instruction. |
119 | | uint32_t getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, |
120 | | SmallVectorImpl<MCFixup> &Fixups, |
121 | | const MCSubtargetInfo &STI) const; |
122 | | |
123 | | /// getVecShifterOpValue - Return the encoded value for the vector shifter. |
124 | | uint32_t getVecShifterOpValue(const MCInst &MI, unsigned OpIdx, |
125 | | SmallVectorImpl<MCFixup> &Fixups, |
126 | | const MCSubtargetInfo &STI) const; |
127 | | |
128 | | /// getMoveVecShifterOpValue - Return the encoded value for the vector move |
129 | | /// shifter (MSL). |
130 | | uint32_t getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx, |
131 | | SmallVectorImpl<MCFixup> &Fixups, |
132 | | const MCSubtargetInfo &STI) const; |
133 | | |
134 | | /// getFixedPointScaleOpValue - Return the encoded value for the |
135 | | // FP-to-fixed-point scale factor. |
136 | | uint32_t getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx, |
137 | | SmallVectorImpl<MCFixup> &Fixups, |
138 | | const MCSubtargetInfo &STI) const; |
139 | | |
140 | | uint32_t getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx, |
141 | | SmallVectorImpl<MCFixup> &Fixups, |
142 | | const MCSubtargetInfo &STI) const; |
143 | | uint32_t getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx, |
144 | | SmallVectorImpl<MCFixup> &Fixups, |
145 | | const MCSubtargetInfo &STI) const; |
146 | | uint32_t getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx, |
147 | | SmallVectorImpl<MCFixup> &Fixups, |
148 | | const MCSubtargetInfo &STI) const; |
149 | | uint32_t getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx, |
150 | | SmallVectorImpl<MCFixup> &Fixups, |
151 | | const MCSubtargetInfo &STI) const; |
152 | | uint32_t getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx, |
153 | | SmallVectorImpl<MCFixup> &Fixups, |
154 | | const MCSubtargetInfo &STI) const; |
155 | | uint32_t getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx, |
156 | | SmallVectorImpl<MCFixup> &Fixups, |
157 | | const MCSubtargetInfo &STI) const; |
158 | | uint32_t getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx, |
159 | | SmallVectorImpl<MCFixup> &Fixups, |
160 | | const MCSubtargetInfo &STI) const; |
161 | | uint32_t getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx, |
162 | | SmallVectorImpl<MCFixup> &Fixups, |
163 | | const MCSubtargetInfo &STI) const; |
164 | | |
165 | | uint32_t getImm8OptLsl(const MCInst &MI, unsigned OpIdx, |
166 | | SmallVectorImpl<MCFixup> &Fixups, |
167 | | const MCSubtargetInfo &STI) const; |
168 | | uint32_t getSVEIncDecImm(const MCInst &MI, unsigned OpIdx, |
169 | | SmallVectorImpl<MCFixup> &Fixups, |
170 | | const MCSubtargetInfo &STI) const; |
171 | | |
172 | | unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue, |
173 | | const MCSubtargetInfo &STI) const; |
174 | | |
175 | | void encodeInstruction(const MCInst &MI, raw_ostream &OS, |
176 | | SmallVectorImpl<MCFixup> &Fixups, |
177 | | const MCSubtargetInfo &STI) const override; |
178 | | |
179 | | unsigned fixMulHigh(const MCInst &MI, unsigned EncodedValue, |
180 | | const MCSubtargetInfo &STI) const; |
181 | | |
182 | | template<int hasRs, int hasRt2> unsigned |
183 | | fixLoadStoreExclusive(const MCInst &MI, unsigned EncodedValue, |
184 | | const MCSubtargetInfo &STI) const; |
185 | | |
186 | | unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue, |
187 | | const MCSubtargetInfo &STI) const; |
188 | | |
189 | | private: |
190 | | FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; |
191 | | void |
192 | | verifyInstructionPredicates(const MCInst &MI, |
193 | | const FeatureBitset &AvailableFeatures) const; |
194 | | }; |
195 | | |
196 | | } // end anonymous namespace |
197 | | |
198 | | /// getMachineOpValue - Return binary encoding of operand. If the machine |
199 | | /// operand requires relocation, record the relocation and return zero. |
200 | | unsigned |
201 | | AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, |
202 | | SmallVectorImpl<MCFixup> &Fixups, |
203 | 34.8M | const MCSubtargetInfo &STI) const { |
204 | 34.8M | if (MO.isReg()) |
205 | 27.2M | return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); |
206 | 7.60M | |
207 | 7.60M | assert(MO.isImm() && "did not expect relocated expression"); |
208 | 7.60M | return static_cast<unsigned>(MO.getImm()); |
209 | 7.60M | } |
210 | | |
211 | | template<unsigned FixupKind> uint32_t |
212 | | AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx, |
213 | | SmallVectorImpl<MCFixup> &Fixups, |
214 | 2.13M | const MCSubtargetInfo &STI) const { |
215 | 2.13M | const MCOperand &MO = MI.getOperand(OpIdx); |
216 | 2.13M | uint32_t ImmVal = 0; |
217 | 2.13M | |
218 | 2.13M | if (MO.isImm()) |
219 | 1.92M | ImmVal = static_cast<uint32_t>(MO.getImm()); |
220 | 209k | else { |
221 | 209k | assert(MO.isExpr() && "unable to encode load/store imm operand"); |
222 | 209k | MCFixupKind Kind = MCFixupKind(FixupKind); |
223 | 209k | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); |
224 | 209k | ++MCNumFixups; |
225 | 209k | } |
226 | 2.13M | |
227 | 2.13M | return ImmVal; |
228 | 2.13M | } AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<135u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const Line | Count | Source | 214 | 123k | const MCSubtargetInfo &STI) const { | 215 | 123k | const MCOperand &MO = MI.getOperand(OpIdx); | 216 | 123k | uint32_t ImmVal = 0; | 217 | 123k | | 218 | 123k | if (MO.isImm()) | 219 | 103k | ImmVal = static_cast<uint32_t>(MO.getImm()); | 220 | 19.4k | else { | 221 | 19.4k | assert(MO.isExpr() && "unable to encode load/store imm operand"); | 222 | 19.4k | MCFixupKind Kind = MCFixupKind(FixupKind); | 223 | 19.4k | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); | 224 | 19.4k | ++MCNumFixups; | 225 | 19.4k | } | 226 | 123k | | 227 | 123k | return ImmVal; | 228 | 123k | } |
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<131u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const Line | Count | Source | 214 | 341k | const MCSubtargetInfo &STI) const { | 215 | 341k | const MCOperand &MO = MI.getOperand(OpIdx); | 216 | 341k | uint32_t ImmVal = 0; | 217 | 341k | | 218 | 341k | if (MO.isImm()) | 219 | 333k | ImmVal = static_cast<uint32_t>(MO.getImm()); | 220 | 8.68k | else { | 221 | 8.68k | assert(MO.isExpr() && "unable to encode load/store imm operand"); | 222 | 8.68k | MCFixupKind Kind = MCFixupKind(FixupKind); | 223 | 8.68k | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); | 224 | 8.68k | ++MCNumFixups; | 225 | 8.68k | } | 226 | 341k | | 227 | 341k | return ImmVal; | 228 | 341k | } |
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<132u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const Line | Count | Source | 214 | 95.0k | const MCSubtargetInfo &STI) const { | 215 | 95.0k | const MCOperand &MO = MI.getOperand(OpIdx); | 216 | 95.0k | uint32_t ImmVal = 0; | 217 | 95.0k | | 218 | 95.0k | if (MO.isImm()) | 219 | 94.9k | ImmVal = static_cast<uint32_t>(MO.getImm()); | 220 | 100 | else { | 221 | 100 | assert(MO.isExpr() && "unable to encode load/store imm operand"); | 222 | 100 | MCFixupKind Kind = MCFixupKind(FixupKind); | 223 | 100 | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); | 224 | 100 | ++MCNumFixups; | 225 | 100 | } | 226 | 95.0k | | 227 | 95.0k | return ImmVal; | 228 | 95.0k | } |
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<133u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const Line | Count | Source | 214 | 490k | const MCSubtargetInfo &STI) const { | 215 | 490k | const MCOperand &MO = MI.getOperand(OpIdx); | 216 | 490k | uint32_t ImmVal = 0; | 217 | 490k | | 218 | 490k | if (MO.isImm()) | 219 | 484k | ImmVal = static_cast<uint32_t>(MO.getImm()); | 220 | 6.30k | else { | 221 | 6.30k | assert(MO.isExpr() && "unable to encode load/store imm operand"); | 222 | 6.30k | MCFixupKind Kind = MCFixupKind(FixupKind); | 223 | 6.30k | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); | 224 | 6.30k | ++MCNumFixups; | 225 | 6.30k | } | 226 | 490k | | 227 | 490k | return ImmVal; | 228 | 490k | } |
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<134u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const Line | Count | Source | 214 | 1.08M | const MCSubtargetInfo &STI) const { | 215 | 1.08M | const MCOperand &MO = MI.getOperand(OpIdx); | 216 | 1.08M | uint32_t ImmVal = 0; | 217 | 1.08M | | 218 | 1.08M | if (MO.isImm()) | 219 | 906k | ImmVal = static_cast<uint32_t>(MO.getImm()); | 220 | 174k | else { | 221 | 174k | assert(MO.isExpr() && "unable to encode load/store imm operand"); | 222 | 174k | MCFixupKind Kind = MCFixupKind(FixupKind); | 223 | 174k | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); | 224 | 174k | ++MCNumFixups; | 225 | 174k | } | 226 | 1.08M | | 227 | 1.08M | return ImmVal; | 228 | 1.08M | } |
|
229 | | |
230 | | /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label |
231 | | /// target. |
232 | | uint32_t |
233 | | AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, |
234 | | SmallVectorImpl<MCFixup> &Fixups, |
235 | 638k | const MCSubtargetInfo &STI) const { |
236 | 638k | const MCOperand &MO = MI.getOperand(OpIdx); |
237 | 638k | |
238 | 638k | // If the destination is an immediate, we have nothing to do. |
239 | 638k | if (MO.isImm()) |
240 | 15 | return MO.getImm(); |
241 | 638k | assert(MO.isExpr() && "Unexpected target type!"); |
242 | 638k | const MCExpr *Expr = MO.getExpr(); |
243 | 638k | |
244 | 638k | MCFixupKind Kind = MI.getOpcode() == AArch64::ADR |
245 | 638k | ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21)2.37k |
246 | 638k | : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21)636k ; |
247 | 638k | Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); |
248 | 638k | |
249 | 638k | MCNumFixups += 1; |
250 | 638k | |
251 | 638k | // All of the information is in the fixup. |
252 | 638k | return 0; |
253 | 638k | } |
254 | | |
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 |
257 | | /// return value. |
258 | | uint32_t |
259 | | AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, |
260 | | SmallVectorImpl<MCFixup> &Fixups, |
261 | 1.39M | const MCSubtargetInfo &STI) const { |
262 | 1.39M | // Suboperands are [imm, shifter]. |
263 | 1.39M | const MCOperand &MO = MI.getOperand(OpIdx); |
264 | 1.39M | const MCOperand &MO1 = MI.getOperand(OpIdx + 1); |
265 | 1.39M | assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL && |
266 | 1.39M | "unexpected shift type for add/sub immediate"); |
267 | 1.39M | unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm()); |
268 | 1.39M | assert((ShiftVal == 0 || ShiftVal == 12) && |
269 | 1.39M | "unexpected shift value for add/sub immediate"); |
270 | 1.39M | if (MO.isImm()) |
271 | 946k | return MO.getImm() | (ShiftVal == 0 ? 0923k : (1 << ShiftVal)23.0k ); |
272 | 445k | assert(MO.isExpr() && "Unable to encode MCOperand!"); |
273 | 445k | const MCExpr *Expr = MO.getExpr(); |
274 | 445k | |
275 | 445k | // Encode the 12 bits of the fixup. |
276 | 445k | MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_add_imm12); |
277 | 445k | Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); |
278 | 445k | |
279 | 445k | ++MCNumFixups; |
280 | 445k | |
281 | 445k | // Set the shift bit of the add instruction for relocation types |
282 | 445k | // R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLD_ADD_DTPREL_HI12. |
283 | 445k | if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { |
284 | 186 | AArch64MCExpr::VariantKind RefKind = A64E->getKind(); |
285 | 186 | if (RefKind == AArch64MCExpr::VK_TPREL_HI12 || |
286 | 186 | RefKind == AArch64MCExpr::VK_DTPREL_HI12164 || |
287 | 186 | RefKind == AArch64MCExpr::VK_SECREL_HI12154 ) |
288 | 33 | ShiftVal = 12; |
289 | 186 | } |
290 | 445k | return ShiftVal == 0 ? 0445k : (1 << ShiftVal)41 ; |
291 | 445k | } |
292 | | |
293 | | /// getCondBranchTargetOpValue - Return the encoded value for a conditional |
294 | | /// branch target. |
295 | | uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue( |
296 | | const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, |
297 | 1.03M | const MCSubtargetInfo &STI) const { |
298 | 1.03M | const MCOperand &MO = MI.getOperand(OpIdx); |
299 | 1.03M | |
300 | 1.03M | // If the destination is an immediate, we have nothing to do. |
301 | 1.03M | if (MO.isImm()) |
302 | 13 | return MO.getImm(); |
303 | 1.03M | assert(MO.isExpr() && "Unexpected target type!"); |
304 | 1.03M | |
305 | 1.03M | MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19); |
306 | 1.03M | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); |
307 | 1.03M | |
308 | 1.03M | ++MCNumFixups; |
309 | 1.03M | |
310 | 1.03M | // All of the information is in the fixup. |
311 | 1.03M | return 0; |
312 | 1.03M | } |
313 | | |
314 | | /// getLoadLiteralOpValue - Return the encoded value for a load-literal |
315 | | /// pc-relative address. |
316 | | uint32_t |
317 | | AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, |
318 | | SmallVectorImpl<MCFixup> &Fixups, |
319 | 49 | const MCSubtargetInfo &STI) const { |
320 | 49 | const MCOperand &MO = MI.getOperand(OpIdx); |
321 | 49 | |
322 | 49 | // If the destination is an immediate, we have nothing to do. |
323 | 49 | if (MO.isImm()) |
324 | 2 | return MO.getImm(); |
325 | 47 | assert(MO.isExpr() && "Unexpected target type!"); |
326 | 47 | |
327 | 47 | MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19); |
328 | 47 | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); |
329 | 47 | |
330 | 47 | ++MCNumFixups; |
331 | 47 | |
332 | 47 | // All of the information is in the fixup. |
333 | 47 | return 0; |
334 | 47 | } |
335 | | |
336 | | uint32_t |
337 | | AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx, |
338 | | SmallVectorImpl<MCFixup> &Fixups, |
339 | 91.8k | const MCSubtargetInfo &STI) const { |
340 | 91.8k | unsigned SignExtend = MI.getOperand(OpIdx).getImm(); |
341 | 91.8k | unsigned DoShift = MI.getOperand(OpIdx + 1).getImm(); |
342 | 91.8k | return (SignExtend << 1) | DoShift; |
343 | 91.8k | } |
344 | | |
345 | | uint32_t |
346 | | AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, |
347 | | SmallVectorImpl<MCFixup> &Fixups, |
348 | 1.48M | const MCSubtargetInfo &STI) const { |
349 | 1.48M | const MCOperand &MO = MI.getOperand(OpIdx); |
350 | 1.48M | |
351 | 1.48M | if (MO.isImm()) |
352 | 1.48M | return MO.getImm(); |
353 | 297 | assert(MO.isExpr() && "Unexpected movz/movk immediate"); |
354 | 297 | |
355 | 297 | Fixups.push_back(MCFixup::create( |
356 | 297 | 0, MO.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw), MI.getLoc())); |
357 | 297 | |
358 | 297 | ++MCNumFixups; |
359 | 297 | |
360 | 297 | return 0; |
361 | 297 | } |
362 | | |
363 | | /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and- |
364 | | /// branch target. |
365 | | uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue( |
366 | | const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, |
367 | 86.8k | const MCSubtargetInfo &STI) const { |
368 | 86.8k | const MCOperand &MO = MI.getOperand(OpIdx); |
369 | 86.8k | |
370 | 86.8k | // If the destination is an immediate, we have nothing to do. |
371 | 86.8k | if (MO.isImm()) |
372 | 3 | return MO.getImm(); |
373 | 86.8k | assert(MO.isExpr() && "Unexpected ADR target type!"); |
374 | 86.8k | |
375 | 86.8k | MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14); |
376 | 86.8k | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); |
377 | 86.8k | |
378 | 86.8k | ++MCNumFixups; |
379 | 86.8k | |
380 | 86.8k | // All of the information is in the fixup. |
381 | 86.8k | return 0; |
382 | 86.8k | } |
383 | | |
384 | | /// getBranchTargetOpValue - Return the encoded value for an unconditional |
385 | | /// branch target. |
386 | | uint32_t |
387 | | AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, |
388 | | SmallVectorImpl<MCFixup> &Fixups, |
389 | 1.45M | const MCSubtargetInfo &STI) const { |
390 | 1.45M | const MCOperand &MO = MI.getOperand(OpIdx); |
391 | 1.45M | |
392 | 1.45M | // If the destination is an immediate, we have nothing to do. |
393 | 1.45M | if (MO.isImm()) |
394 | 7 | return MO.getImm(); |
395 | 1.45M | assert(MO.isExpr() && "Unexpected ADR target type!"); |
396 | 1.45M | |
397 | 1.45M | MCFixupKind Kind = MI.getOpcode() == AArch64::BL |
398 | 1.45M | ? MCFixupKind(AArch64::fixup_aarch64_pcrel_call26)1.11M |
399 | 1.45M | : MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26)340k ; |
400 | 1.45M | Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); |
401 | 1.45M | |
402 | 1.45M | ++MCNumFixups; |
403 | 1.45M | |
404 | 1.45M | // All of the information is in the fixup. |
405 | 1.45M | return 0; |
406 | 1.45M | } |
407 | | |
408 | | /// getVecShifterOpValue - Return the encoded value for the vector shifter: |
409 | | /// |
410 | | /// 00 -> 0 |
411 | | /// 01 -> 8 |
412 | | /// 10 -> 16 |
413 | | /// 11 -> 24 |
414 | | uint32_t |
415 | | AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx, |
416 | | SmallVectorImpl<MCFixup> &Fixups, |
417 | 17.7k | const MCSubtargetInfo &STI) const { |
418 | 17.7k | const MCOperand &MO = MI.getOperand(OpIdx); |
419 | 17.7k | assert(MO.isImm() && "Expected an immediate value for the shift amount!"); |
420 | 17.7k | |
421 | 17.7k | switch (MO.getImm()) { |
422 | 17.7k | default: |
423 | 0 | break; |
424 | 17.7k | case 0: |
425 | 17.4k | return 0; |
426 | 17.7k | case 8: |
427 | 199 | return 1; |
428 | 17.7k | case 16: |
429 | 54 | return 2; |
430 | 17.7k | case 24: |
431 | 75 | return 3; |
432 | 0 | } |
433 | 0 | |
434 | 0 | llvm_unreachable("Invalid value for vector shift amount!"); |
435 | 0 | } |
436 | | |
437 | | /// getFixedPointScaleOpValue - Return the encoded value for the |
438 | | // FP-to-fixed-point scale factor. |
439 | | uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue( |
440 | | const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, |
441 | 104 | const MCSubtargetInfo &STI) const { |
442 | 104 | const MCOperand &MO = MI.getOperand(OpIdx); |
443 | 104 | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
444 | 104 | return 64 - MO.getImm(); |
445 | 104 | } |
446 | | |
447 | | uint32_t |
448 | | AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx, |
449 | | SmallVectorImpl<MCFixup> &Fixups, |
450 | 1.34k | const MCSubtargetInfo &STI) const { |
451 | 1.34k | const MCOperand &MO = MI.getOperand(OpIdx); |
452 | 1.34k | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
453 | 1.34k | return 64 - MO.getImm(); |
454 | 1.34k | } |
455 | | |
456 | | uint32_t |
457 | | AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx, |
458 | | SmallVectorImpl<MCFixup> &Fixups, |
459 | 6.32k | const MCSubtargetInfo &STI) const { |
460 | 6.32k | const MCOperand &MO = MI.getOperand(OpIdx); |
461 | 6.32k | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
462 | 6.32k | return 32 - MO.getImm(); |
463 | 6.32k | } |
464 | | |
465 | | uint32_t |
466 | | AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx, |
467 | | SmallVectorImpl<MCFixup> &Fixups, |
468 | 537 | const MCSubtargetInfo &STI) const { |
469 | 537 | const MCOperand &MO = MI.getOperand(OpIdx); |
470 | 537 | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
471 | 537 | return 16 - MO.getImm(); |
472 | 537 | } |
473 | | |
474 | | uint32_t |
475 | | AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx, |
476 | | SmallVectorImpl<MCFixup> &Fixups, |
477 | 360 | const MCSubtargetInfo &STI) const { |
478 | 360 | const MCOperand &MO = MI.getOperand(OpIdx); |
479 | 360 | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
480 | 360 | return 8 - MO.getImm(); |
481 | 360 | } |
482 | | |
483 | | uint32_t |
484 | | AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx, |
485 | | SmallVectorImpl<MCFixup> &Fixups, |
486 | 216 | const MCSubtargetInfo &STI) const { |
487 | 216 | const MCOperand &MO = MI.getOperand(OpIdx); |
488 | 216 | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
489 | 216 | return MO.getImm() - 64; |
490 | 216 | } |
491 | | |
492 | | uint32_t |
493 | | AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx, |
494 | | SmallVectorImpl<MCFixup> &Fixups, |
495 | 30.5k | const MCSubtargetInfo &STI) const { |
496 | 30.5k | const MCOperand &MO = MI.getOperand(OpIdx); |
497 | 30.5k | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
498 | 30.5k | return MO.getImm() - 32; |
499 | 30.5k | } |
500 | | |
501 | | uint32_t |
502 | | AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx, |
503 | | SmallVectorImpl<MCFixup> &Fixups, |
504 | 1.33k | const MCSubtargetInfo &STI) const { |
505 | 1.33k | const MCOperand &MO = MI.getOperand(OpIdx); |
506 | 1.33k | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
507 | 1.33k | return MO.getImm() - 16; |
508 | 1.33k | } |
509 | | |
510 | | uint32_t |
511 | | AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx, |
512 | | SmallVectorImpl<MCFixup> &Fixups, |
513 | 437 | const MCSubtargetInfo &STI) const { |
514 | 437 | const MCOperand &MO = MI.getOperand(OpIdx); |
515 | 437 | assert(MO.isImm() && "Expected an immediate value for the scale amount!"); |
516 | 437 | return MO.getImm() - 8; |
517 | 437 | } |
518 | | |
519 | | uint32_t |
520 | | AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx, |
521 | | SmallVectorImpl<MCFixup> &Fixups, |
522 | 636 | const MCSubtargetInfo &STI) const { |
523 | 636 | // Test shift |
524 | 636 | auto ShiftOpnd = MI.getOperand(OpIdx + 1).getImm(); |
525 | 636 | assert(AArch64_AM::getShiftType(ShiftOpnd) == AArch64_AM::LSL && |
526 | 636 | "Unexpected shift type for imm8_opt_lsl immediate."); |
527 | 636 | |
528 | 636 | unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftOpnd); |
529 | 636 | assert((ShiftVal == 0 || ShiftVal == 8) && |
530 | 636 | "Unexpected shift value for imm8_opt_lsl immediate."); |
531 | 636 | |
532 | 636 | // Test immediate |
533 | 636 | auto Immediate = MI.getOperand(OpIdx).getImm(); |
534 | 636 | return (Immediate & 0xff) | (ShiftVal == 0 ? 0246 : (1 << ShiftVal)390 ); |
535 | 636 | } |
536 | | |
537 | | uint32_t |
538 | | AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst &MI, unsigned OpIdx, |
539 | | SmallVectorImpl<MCFixup> &Fixups, |
540 | 2.85k | const MCSubtargetInfo &STI) const { |
541 | 2.85k | const MCOperand &MO = MI.getOperand(OpIdx); |
542 | 2.85k | assert(MO.isImm() && "Expected an immediate value!"); |
543 | 2.85k | // Normalize 1-16 range to 0-15. |
544 | 2.85k | return MO.getImm() - 1; |
545 | 2.85k | } |
546 | | |
547 | | /// getMoveVecShifterOpValue - Return the encoded value for the vector move |
548 | | /// shifter (MSL). |
549 | | uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue( |
550 | | const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, |
551 | 69 | const MCSubtargetInfo &STI) const { |
552 | 69 | const MCOperand &MO = MI.getOperand(OpIdx); |
553 | 69 | assert(MO.isImm() && |
554 | 69 | "Expected an immediate value for the move shift amount!"); |
555 | 69 | unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm()); |
556 | 69 | assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!"); |
557 | 69 | return ShiftVal == 8 ? 057 : 112 ; |
558 | 69 | } |
559 | | |
560 | | unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue, |
561 | 1.23M | const MCSubtargetInfo &STI) const { |
562 | 1.23M | // If one of the signed fixup kinds is applied to a MOVZ instruction, the |
563 | 1.23M | // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's |
564 | 1.23M | // job to ensure that any bits possibly affected by this are 0. This means we |
565 | 1.23M | // must zero out bit 30 (essentially emitting a MOVN). |
566 | 1.23M | MCOperand UImm16MO = MI.getOperand(1); |
567 | 1.23M | |
568 | 1.23M | // Nothing to do if there's no fixup. |
569 | 1.23M | if (UImm16MO.isImm()) |
570 | 1.23M | return EncodedValue; |
571 | 133 | |
572 | 133 | const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr()); |
573 | 133 | switch (A64E->getKind()) { |
574 | 133 | case AArch64MCExpr::VK_DTPREL_G2: |
575 | 53 | case AArch64MCExpr::VK_DTPREL_G1: |
576 | 53 | case AArch64MCExpr::VK_DTPREL_G0: |
577 | 53 | case AArch64MCExpr::VK_GOTTPREL_G1: |
578 | 53 | case AArch64MCExpr::VK_TPREL_G2: |
579 | 53 | case AArch64MCExpr::VK_TPREL_G1: |
580 | 53 | case AArch64MCExpr::VK_TPREL_G0: |
581 | 53 | return EncodedValue & ~(1u << 30); |
582 | 80 | default: |
583 | 80 | // Nothing to do for an unsigned fixup. |
584 | 80 | return EncodedValue; |
585 | 0 | } |
586 | 0 | |
587 | 0 | |
588 | 0 | return EncodedValue & ~(1u << 30); |
589 | 0 | } |
590 | | |
591 | | void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, |
592 | | SmallVectorImpl<MCFixup> &Fixups, |
593 | 14.5M | const MCSubtargetInfo &STI) const { |
594 | 14.5M | verifyInstructionPredicates(MI, |
595 | 14.5M | computeAvailableFeatures(STI.getFeatureBits())); |
596 | 14.5M | |
597 | 14.5M | if (MI.getOpcode() == AArch64::TLSDESCCALL) { |
598 | 21 | // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the |
599 | 21 | // following (BLR) instruction. It doesn't emit any code itself so it |
600 | 21 | // doesn't go through the normal TableGenerated channels. |
601 | 21 | MCFixupKind Fixup = MCFixupKind(AArch64::fixup_aarch64_tlsdesc_call); |
602 | 21 | Fixups.push_back(MCFixup::create(0, MI.getOperand(0).getExpr(), Fixup)); |
603 | 21 | return; |
604 | 14.5M | } else if (MI.getOpcode() == AArch64::CompilerBarrier) { |
605 | 9 | // This just prevents the compiler from reordering accesses, no actual code. |
606 | 9 | return; |
607 | 9 | } |
608 | 14.5M | |
609 | 14.5M | uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); |
610 | 14.5M | support::endian::write<uint32_t>(OS, Binary, support::little); |
611 | 14.5M | ++MCNumEmitted; // Keep track of the # of mi's emitted. |
612 | 14.5M | } |
613 | | |
614 | | unsigned |
615 | | AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI, |
616 | | unsigned EncodedValue, |
617 | 529 | const MCSubtargetInfo &STI) const { |
618 | 529 | // The Ra field of SMULH and UMULH is unused: it should be assembled as 31 |
619 | 529 | // (i.e. all bits 1) but is ignored by the processor. |
620 | 529 | EncodedValue |= 0x1f << 10; |
621 | 529 | return EncodedValue; |
622 | 529 | } |
623 | | |
624 | | template<int hasRs, int hasRt2> unsigned |
625 | | AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI, |
626 | | unsigned EncodedValue, |
627 | 54.7k | const MCSubtargetInfo &STI) const { |
628 | 54.7k | if (!hasRs) EncodedValue |= 0x001F000031.0k ; |
629 | 54.7k | if (!hasRt2) EncodedValue |= 0x00007C0054.6k ; |
630 | 54.7k | |
631 | 54.7k | return EncodedValue; |
632 | 54.7k | } AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::fixLoadStoreExclusive<0, 0>(llvm::MCInst const&, unsigned int, llvm::MCSubtargetInfo const&) const Line | Count | Source | 627 | 31.0k | const MCSubtargetInfo &STI) const { | 628 | 31.0k | if (!hasRs) EncodedValue |= 0x001F0000; | 629 | 31.0k | if (!hasRt2) EncodedValue |= 0x00007C00; | 630 | 31.0k | | 631 | 31.0k | return EncodedValue; | 632 | 31.0k | } |
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::fixLoadStoreExclusive<0, 1>(llvm::MCInst const&, unsigned int, llvm::MCSubtargetInfo const&) const Line | Count | Source | 627 | 8 | const MCSubtargetInfo &STI) const { | 628 | 8 | if (!hasRs) EncodedValue |= 0x001F0000; | 629 | 8 | if (!hasRt2) EncodedValue |= 0x00007C000 ; | 630 | 8 | | 631 | 8 | return EncodedValue; | 632 | 8 | } |
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::fixLoadStoreExclusive<1, 0>(llvm::MCInst const&, unsigned int, llvm::MCSubtargetInfo const&) const Line | Count | Source | 627 | 23.6k | const MCSubtargetInfo &STI) const { | 628 | 23.6k | if (!hasRs) EncodedValue |= 0x001F00000 ; | 629 | 23.6k | if (!hasRt2) EncodedValue |= 0x00007C00; | 630 | 23.6k | | 631 | 23.6k | return EncodedValue; | 632 | 23.6k | } |
|
633 | | |
634 | | unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison( |
635 | 2.15k | const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { |
636 | 2.15k | // The Rm field of FCMP and friends is unused - it should be assembled |
637 | 2.15k | // as 0, but is ignored by the processor. |
638 | 2.15k | EncodedValue &= ~(0x1f << 16); |
639 | 2.15k | return EncodedValue; |
640 | 2.15k | } |
641 | | |
642 | | #define ENABLE_INSTR_PREDICATE_VERIFIER |
643 | | #include "AArch64GenMCCodeEmitter.inc" |
644 | | |
645 | | MCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII, |
646 | | const MCRegisterInfo &MRI, |
647 | 10.4k | MCContext &Ctx) { |
648 | 10.4k | return new AArch64MCCodeEmitter(MCII, Ctx); |
649 | 10.4k | } |