Line data Source code
1 : //=- AArch64/AArch64MCCodeEmitter.cpp - Convert AArch64 code to machine code-=//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file implements the AArch64MCCodeEmitter class.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "MCTargetDesc/AArch64AddressingModes.h"
15 : #include "MCTargetDesc/AArch64FixupKinds.h"
16 : #include "MCTargetDesc/AArch64MCExpr.h"
17 : #include "Utils/AArch64BaseInfo.h"
18 : #include "llvm/ADT/SmallVector.h"
19 : #include "llvm/ADT/Statistic.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>
34 :
35 : using namespace llvm;
36 :
37 : #define DEBUG_TYPE "mccodeemitter"
38 :
39 : STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
40 : STATISTIC(MCNumFixups, "Number of MC fixups created.");
41 :
42 : namespace {
43 :
44 : class AArch64MCCodeEmitter : public MCCodeEmitter {
45 : MCContext &Ctx;
46 : const MCInstrInfo &MCII;
47 :
48 : public:
49 : AArch64MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
50 2057 : : Ctx(ctx), MCII(mcii) {}
51 : AArch64MCCodeEmitter(const AArch64MCCodeEmitter &) = delete;
52 : void operator=(const AArch64MCCodeEmitter &) = delete;
53 2056 : ~AArch64MCCodeEmitter() override = default;
54 :
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;
60 :
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;
66 :
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;
74 :
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;
80 :
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;
86 :
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;
92 :
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;
98 :
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;
105 :
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;
111 :
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;
117 :
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;
123 :
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;
128 :
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;
134 :
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;
140 :
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;
165 :
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;
172 :
173 : unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue,
174 : const MCSubtargetInfo &STI) const;
175 :
176 : void encodeInstruction(const MCInst &MI, raw_ostream &OS,
177 : SmallVectorImpl<MCFixup> &Fixups,
178 : const MCSubtargetInfo &STI) const override;
179 :
180 : unsigned fixMulHigh(const MCInst &MI, unsigned EncodedValue,
181 : const MCSubtargetInfo &STI) const;
182 :
183 : template<int hasRs, int hasRt2> unsigned
184 : fixLoadStoreExclusive(const MCInst &MI, unsigned EncodedValue,
185 : const MCSubtargetInfo &STI) const;
186 :
187 : unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue,
188 : const MCSubtargetInfo &STI) const;
189 :
190 : private:
191 : uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
192 : void verifyInstructionPredicates(const MCInst &MI,
193 : uint64_t 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 0 : AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
202 : SmallVectorImpl<MCFixup> &Fixups,
203 : const MCSubtargetInfo &STI) const {
204 0 : if (MO.isReg())
205 0 : return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
206 :
207 : assert(MO.isImm() && "did not expect relocated expression");
208 0 : return static_cast<unsigned>(MO.getImm());
209 : }
210 :
211 : template<unsigned FixupKind> uint32_t
212 0 : AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,
213 : SmallVectorImpl<MCFixup> &Fixups,
214 : const MCSubtargetInfo &STI) const {
215 : const MCOperand &MO = MI.getOperand(OpIdx);
216 : uint32_t ImmVal = 0;
217 :
218 0 : if (MO.isImm())
219 0 : ImmVal = static_cast<uint32_t>(MO.getImm());
220 : else {
221 : assert(MO.isExpr() && "unable to encode load/store imm operand");
222 : MCFixupKind Kind = MCFixupKind(FixupKind);
223 0 : Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
224 : ++MCNumFixups;
225 : }
226 :
227 0 : return ImmVal;
228 : }
229 0 :
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 0 : const MCSubtargetInfo &STI) const {
236 0 : const MCOperand &MO = MI.getOperand(OpIdx);
237 :
238 : // If the destination is an immediate, we have nothing to do.
239 : if (MO.isImm())
240 0 : return MO.getImm();
241 : assert(MO.isExpr() && "Unexpected target type!");
242 : const MCExpr *Expr = MO.getExpr();
243 :
244 0 : MCFixupKind Kind = MI.getOpcode() == AArch64::ADR
245 : ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21)
246 0 : : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21);
247 : Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
248 :
249 : MCNumFixups += 1;
250 :
251 : // All of the information is in the fixup.
252 0 : return 0;
253 0 : }
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 0 : /// return value.
258 : uint32_t
259 : AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
260 : SmallVectorImpl<MCFixup> &Fixups,
261 0 : const MCSubtargetInfo &STI) const {
262 : // Suboperands are [imm, shifter].
263 0 : const MCOperand &MO = MI.getOperand(OpIdx);
264 : const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
265 : assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL &&
266 : "unexpected shift type for add/sub immediate");
267 : unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm());
268 : assert((ShiftVal == 0 || ShiftVal == 12) &&
269 0 : "unexpected shift value for add/sub immediate");
270 0 : if (MO.isImm())
271 : return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << ShiftVal));
272 : assert(MO.isExpr() && "Unable to encode MCOperand!");
273 : const MCExpr *Expr = MO.getExpr();
274 0 :
275 : // Encode the 12 bits of the fixup.
276 : MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_add_imm12);
277 : Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
278 0 :
279 : ++MCNumFixups;
280 0 :
281 : // Set the shift bit of the add instruction for relocation types
282 : // R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLD_ADD_DTPREL_HI12.
283 : if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
284 : AArch64MCExpr::VariantKind RefKind = A64E->getKind();
285 : if (RefKind == AArch64MCExpr::VK_TPREL_HI12 ||
286 0 : RefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
287 0 : RefKind == AArch64MCExpr::VK_SECREL_HI12)
288 : ShiftVal = 12;
289 : }
290 : return ShiftVal == 0 ? 0 : (1 << ShiftVal);
291 0 : }
292 :
293 : /// getCondBranchTargetOpValue - Return the encoded value for a conditional
294 : /// branch target.
295 0 : uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(
296 : const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
297 0 : const MCSubtargetInfo &STI) const {
298 : const MCOperand &MO = MI.getOperand(OpIdx);
299 :
300 : // If the destination is an immediate, we have nothing to do.
301 : if (MO.isImm())
302 : return MO.getImm();
303 0 : assert(MO.isExpr() && "Unexpected target type!");
304 0 :
305 : MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19);
306 : Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
307 :
308 0 : ++MCNumFixups;
309 :
310 : // All of the information is in the fixup.
311 : return 0;
312 0 : }
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 0 : SmallVectorImpl<MCFixup> &Fixups,
319 : const MCSubtargetInfo &STI) const {
320 : const MCOperand &MO = MI.getOperand(OpIdx);
321 :
322 : // If the destination is an immediate, we have nothing to do.
323 : if (MO.isImm())
324 0 : return MO.getImm();
325 0 : assert(MO.isExpr() && "Unexpected target type!");
326 :
327 0 : MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19);
328 : Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
329 0 :
330 0 : ++MCNumFixups;
331 :
332 0 : // All of the information is in the fixup.
333 : return 0;
334 : }
335 :
336 : uint32_t
337 0 : AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,
338 : SmallVectorImpl<MCFixup> &Fixups,
339 : const MCSubtargetInfo &STI) const {
340 : unsigned SignExtend = MI.getOperand(OpIdx).getImm();
341 : unsigned DoShift = MI.getOperand(OpIdx + 1).getImm();
342 : return (SignExtend << 1) | DoShift;
343 : }
344 0 :
345 : uint32_t
346 : AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
347 : SmallVectorImpl<MCFixup> &Fixups,
348 : const MCSubtargetInfo &STI) const {
349 0 : const MCOperand &MO = MI.getOperand(OpIdx);
350 :
351 : if (MO.isImm())
352 0 : return MO.getImm();
353 : assert(MO.isExpr() && "Unexpected movz/movk immediate");
354 :
355 0 : Fixups.push_back(MCFixup::create(
356 0 : 0, MO.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw), MI.getLoc()));
357 :
358 0 : ++MCNumFixups;
359 :
360 : return 0;
361 : }
362 0 :
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 : const MCSubtargetInfo &STI) const {
368 0 : const MCOperand &MO = MI.getOperand(OpIdx);
369 0 :
370 0 : // If the destination is an immediate, we have nothing to do.
371 0 : if (MO.isImm())
372 : return MO.getImm();
373 : assert(MO.isExpr() && "Unexpected ADR target type!");
374 :
375 0 : MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14);
376 : Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
377 :
378 : ++MCNumFixups;
379 :
380 0 : // All of the information is in the fixup.
381 : return 0;
382 : }
383 :
384 : /// getBranchTargetOpValue - Return the encoded value for an unconditional
385 : /// branch target.
386 0 : uint32_t
387 0 : AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
388 : SmallVectorImpl<MCFixup> &Fixups,
389 : const MCSubtargetInfo &STI) const {
390 : const MCOperand &MO = MI.getOperand(OpIdx);
391 0 :
392 : // If the destination is an immediate, we have nothing to do.
393 : if (MO.isImm())
394 : return MO.getImm();
395 : assert(MO.isExpr() && "Unexpected ADR target type!");
396 0 :
397 : MCFixupKind Kind = MI.getOpcode() == AArch64::BL
398 : ? MCFixupKind(AArch64::fixup_aarch64_pcrel_call26)
399 : : MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26);
400 : Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
401 :
402 0 : ++MCNumFixups;
403 :
404 : // All of the information is in the fixup.
405 : return 0;
406 : }
407 :
408 0 : /// getVecShifterOpValue - Return the encoded value for the vector shifter:
409 0 : ///
410 : /// 00 -> 0
411 : /// 01 -> 8
412 : /// 10 -> 16
413 0 : /// 11 -> 24
414 : uint32_t
415 : AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
416 : SmallVectorImpl<MCFixup> &Fixups,
417 : const MCSubtargetInfo &STI) const {
418 0 : const MCOperand &MO = MI.getOperand(OpIdx);
419 : assert(MO.isImm() && "Expected an immediate value for the shift amount!");
420 :
421 : switch (MO.getImm()) {
422 0 : default:
423 : break;
424 : case 0:
425 0 : return 0;
426 0 : case 8:
427 0 : return 1;
428 : case 16:
429 : return 2;
430 : case 24:
431 0 : return 3;
432 : }
433 :
434 : llvm_unreachable("Invalid value for vector shift amount!");
435 : }
436 0 :
437 0 : /// getFixedPointScaleOpValue - Return the encoded value for the
438 : // FP-to-fixed-point scale factor.
439 : uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue(
440 0 : const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
441 0 : const MCSubtargetInfo &STI) const {
442 : const MCOperand &MO = MI.getOperand(OpIdx);
443 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
444 : return 64 - MO.getImm();
445 0 : }
446 :
447 : uint32_t
448 : AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
449 : SmallVectorImpl<MCFixup> &Fixups,
450 0 : const MCSubtargetInfo &STI) const {
451 : const MCOperand &MO = MI.getOperand(OpIdx);
452 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
453 : return 64 - MO.getImm();
454 : }
455 :
456 0 : uint32_t
457 0 : AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
458 : SmallVectorImpl<MCFixup> &Fixups,
459 : const MCSubtargetInfo &STI) const {
460 : const MCOperand &MO = MI.getOperand(OpIdx);
461 0 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
462 : return 32 - MO.getImm();
463 : }
464 :
465 : uint32_t
466 0 : AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
467 : SmallVectorImpl<MCFixup> &Fixups,
468 : const MCSubtargetInfo &STI) const {
469 : const MCOperand &MO = MI.getOperand(OpIdx);
470 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
471 : return 16 - MO.getImm();
472 0 : }
473 :
474 : uint32_t
475 : AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
476 : SmallVectorImpl<MCFixup> &Fixups,
477 : const MCSubtargetInfo &STI) const {
478 0 : const MCOperand &MO = MI.getOperand(OpIdx);
479 0 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
480 : return 8 - MO.getImm();
481 : }
482 0 :
483 0 : uint32_t
484 : AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
485 0 : SmallVectorImpl<MCFixup> &Fixups,
486 : const MCSubtargetInfo &STI) const {
487 : const MCOperand &MO = MI.getOperand(OpIdx);
488 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
489 : return MO.getImm() - 64;
490 0 : }
491 :
492 : uint32_t
493 : AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
494 : SmallVectorImpl<MCFixup> &Fixups,
495 : const MCSubtargetInfo &STI) const {
496 : const MCOperand &MO = MI.getOperand(OpIdx);
497 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
498 : return MO.getImm() - 32;
499 : }
500 0 :
501 : uint32_t
502 : AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
503 : SmallVectorImpl<MCFixup> &Fixups,
504 : const MCSubtargetInfo &STI) const {
505 : const MCOperand &MO = MI.getOperand(OpIdx);
506 0 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
507 : return MO.getImm() - 16;
508 : }
509 :
510 : uint32_t
511 0 : AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
512 0 : SmallVectorImpl<MCFixup> &Fixups,
513 0 : const MCSubtargetInfo &STI) const {
514 0 : const MCOperand &MO = MI.getOperand(OpIdx);
515 0 : assert(MO.isImm() && "Expected an immediate value for the scale amount!");
516 0 : return MO.getImm() - 8;
517 : }
518 :
519 0 : uint32_t
520 : AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
521 : SmallVectorImpl<MCFixup> &Fixups,
522 : const MCSubtargetInfo &STI) const {
523 : // Test shift
524 0 : auto ShiftOpnd = MI.getOperand(OpIdx + 1).getImm();
525 : assert(AArch64_AM::getShiftType(ShiftOpnd) == AArch64_AM::LSL &&
526 : "Unexpected shift type for imm8_opt_lsl immediate.");
527 :
528 : unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftOpnd);
529 0 : assert((ShiftVal == 0 || ShiftVal == 8) &&
530 : "Unexpected shift value for imm8_opt_lsl immediate.");
531 :
532 : // Test immediate
533 0 : auto Immediate = MI.getOperand(OpIdx).getImm();
534 : return (Immediate & 0xff) | (ShiftVal == 0 ? 0 : (1 << ShiftVal));
535 : }
536 :
537 : uint32_t
538 0 : AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,
539 : SmallVectorImpl<MCFixup> &Fixups,
540 : const MCSubtargetInfo &STI) const {
541 : const MCOperand &MO = MI.getOperand(OpIdx);
542 0 : assert(MO.isImm() && "Expected an immediate value!");
543 : // Normalize 1-16 range to 0-15.
544 : return MO.getImm() - 1;
545 : }
546 :
547 0 : /// 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 0 : const MCSubtargetInfo &STI) const {
552 : const MCOperand &MO = MI.getOperand(OpIdx);
553 : assert(MO.isImm() &&
554 : "Expected an immediate value for the move shift amount!");
555 : unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm());
556 0 : assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!");
557 : return ShiftVal == 8 ? 0 : 1;
558 : }
559 :
560 0 : unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
561 : const MCSubtargetInfo &STI) const {
562 : // If one of the signed fixup kinds is applied to a MOVZ instruction, the
563 : // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's
564 : // job to ensure that any bits possibly affected by this are 0. This means we
565 0 : // must zero out bit 30 (essentially emitting a MOVN).
566 : MCOperand UImm16MO = MI.getOperand(1);
567 :
568 : // Nothing to do if there's no fixup.
569 0 : if (UImm16MO.isImm())
570 : return EncodedValue;
571 :
572 : const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr());
573 : switch (A64E->getKind()) {
574 0 : case AArch64MCExpr::VK_DTPREL_G2:
575 : case AArch64MCExpr::VK_DTPREL_G1:
576 : case AArch64MCExpr::VK_DTPREL_G0:
577 : case AArch64MCExpr::VK_GOTTPREL_G1:
578 0 : case AArch64MCExpr::VK_TPREL_G2:
579 : case AArch64MCExpr::VK_TPREL_G1:
580 : case AArch64MCExpr::VK_TPREL_G0:
581 : return EncodedValue & ~(1u << 30);
582 : default:
583 0 : // Nothing to do for an unsigned fixup.
584 : return EncodedValue;
585 : }
586 :
587 0 :
588 : return EncodedValue & ~(1u << 30);
589 : }
590 :
591 : void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
592 0 : SmallVectorImpl<MCFixup> &Fixups,
593 : const MCSubtargetInfo &STI) const {
594 : verifyInstructionPredicates(MI,
595 : computeAvailableFeatures(STI.getFeatureBits()));
596 0 :
597 : if (MI.getOpcode() == AArch64::TLSDESCCALL) {
598 : // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the
599 : // following (BLR) instruction. It doesn't emit any code itself so it
600 : // doesn't go through the normal TableGenerated channels.
601 0 : MCFixupKind Fixup = MCFixupKind(AArch64::fixup_aarch64_tlsdesc_call);
602 : Fixups.push_back(MCFixup::create(0, MI.getOperand(0).getExpr(), Fixup));
603 : return;
604 : } else if (MI.getOpcode() == AArch64::CompilerBarrier) {
605 0 : // This just prevents the compiler from reordering accesses, no actual code.
606 : return;
607 : }
608 :
609 0 : uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
610 : support::endian::write<uint32_t>(OS, Binary, support::little);
611 : ++MCNumEmitted; // Keep track of the # of mi's emitted.
612 : }
613 0 :
614 : unsigned
615 : AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI,
616 : unsigned EncodedValue,
617 : const MCSubtargetInfo &STI) const {
618 0 : // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
619 0 : // (i.e. all bits 1) but is ignored by the processor.
620 : EncodedValue |= 0x1f << 10;
621 : return EncodedValue;
622 : }
623 0 :
624 : template<int hasRs, int hasRt2> unsigned
625 : AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI,
626 : unsigned EncodedValue,
627 : const MCSubtargetInfo &STI) const {
628 : if (!hasRs) EncodedValue |= 0x001F0000;
629 0 : if (!hasRt2) EncodedValue |= 0x00007C00;
630 :
631 : return EncodedValue;
632 : }
633 :
634 0 : unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison(
635 : const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const {
636 : // The Rm field of FCMP and friends is unused - it should be assembled
637 : // as 0, but is ignored by the processor.
638 : EncodedValue &= ~(0x1f << 16);
639 : return EncodedValue;
640 0 : }
641 :
642 0 : #define ENABLE_INSTR_PREDICATE_VERIFIER
643 : #include "AArch64GenMCCodeEmitter.inc"
644 :
645 0 : MCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII,
646 : const MCRegisterInfo &MRI,
647 : MCContext &Ctx) {
648 : return new AArch64MCCodeEmitter(MCII, Ctx);
649 : }
|