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