28#define DEBUG_TYPE "mccodeemitter"
32 LoongArchMCCodeEmitter(
const LoongArchMCCodeEmitter &) =
delete;
33 void operator=(
const LoongArchMCCodeEmitter &) =
delete;
39 : Ctx(ctx), MCII(MCII) {}
41 ~LoongArchMCCodeEmitter()
override =
default;
47 template <
unsigned Opc>
72 unsigned getImmOpValueSub1(
const MCInst &
MI,
unsigned OpNo,
82 unsigned getImmOpValueAsr(
const MCInst &
MI,
unsigned OpNo,
87 unsigned Res =
MI.getOperand(OpNo).getImm();
88 assert((Res & ((1U <<
N) - 1U)) == 0 &&
"lowest N bits are non-zero");
91 return getExprOpValue(
MI, MO, Fixups, STI);
121 return static_cast<unsigned>(MO.
getImm());
125 return getExprOpValue(
MI, MO, Fixups, STI);
129LoongArchMCCodeEmitter::getImmOpValueSub1(
const MCInst &
MI,
unsigned OpNo,
130 SmallVectorImpl<MCFixup> &Fixups,
131 const MCSubtargetInfo &STI)
const {
132 return MI.getOperand(OpNo).getImm() - 1;
136LoongArchMCCodeEmitter::getExprOpValue(
const MCInst &
MI,
const MCOperand &MO,
137 SmallVectorImpl<MCFixup> &Fixups,
138 const MCSubtargetInfo &STI)
const {
139 assert(MO.
isExpr() &&
"getExprOpValue expects only expressions");
140 bool RelaxCandidate =
false;
141 bool EnableRelax = STI.
hasFeature(LoongArch::FeatureRelax);
142 const MCExpr *Expr = MO.
getExpr();
152 case ELF::R_LARCH_TLS_LE_ADD_R:
154 "instruction operand");
155 case ELF::R_LARCH_B16:
158 case ELF::R_LARCH_B21:
161 case ELF::R_LARCH_B26:
164 case ELF::R_LARCH_MARK_LA:
171 case ELF::R_LARCH_ABS_HI20:
174 case ELF::R_LARCH_ABS_LO12:
177 case ELF::R_LARCH_ABS64_LO20:
180 case ELF::R_LARCH_ABS64_HI12:
183 case ELF::R_LARCH_CALL30:
184 case ELF::R_LARCH_CALL36:
185 case ELF::R_LARCH_TLS_LE_HI20_R:
186 case ELF::R_LARCH_TLS_LE_LO12_R:
187 RelaxCandidate =
true;
191 switch (
MI.getOpcode()) {
198 case LoongArch::BLTU:
199 case LoongArch::BGEU:
202 case LoongArch::BEQZ:
203 case LoongArch::BNEZ:
204 case LoongArch::BCEQZ:
205 case LoongArch::BCNEZ:
216 "Unhandled expression!");
222 if (EnableRelax && RelaxCandidate)
223 Fixups.back().setLinkerRelaxable();
228template <
unsigned Opc>
229void LoongArchMCCodeEmitter::expandToVectorLDI(
230 const MCInst &
MI, SmallVectorImpl<char> &CB,
231 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
232 int64_t
Imm =
MI.getOperand(1).getImm() & 0x3FF;
233 switch (
MI.getOpcode()) {
234 case LoongArch::PseudoVREPLI_B:
235 case LoongArch::PseudoXVREPLI_B:
237 case LoongArch::PseudoVREPLI_H:
238 case LoongArch::PseudoXVREPLI_H:
241 case LoongArch::PseudoVREPLI_W:
242 case LoongArch::PseudoXVREPLI_W:
245 case LoongArch::PseudoVREPLI_D:
246 case LoongArch::PseudoXVREPLI_D:
250 MCInst TmpInst = MCInstBuilder(
Opc).addOperand(
MI.getOperand(0)).addImm(Imm);
251 uint32_t
Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
255void LoongArchMCCodeEmitter::expandAddTPRel(
const MCInst &
MI,
256 SmallVectorImpl<char> &CB,
257 SmallVectorImpl<MCFixup> &Fixups,
258 const MCSubtargetInfo &STI)
const {
259 MCOperand Rd =
MI.getOperand(0);
260 MCOperand Rj =
MI.getOperand(1);
261 MCOperand Rk =
MI.getOperand(2);
262 MCOperand
Symbol =
MI.getOperand(3);
264 "Expected expression as third input to TP-relative add");
268 "Expected %le_add_r relocation on TP-relative symbol");
271 addFixup(Fixups, 0, Expr, ELF::R_LARCH_TLS_LE_ADD_R);
273 Fixups.back().setLinkerRelaxable();
276 unsigned ADD =
MI.getOpcode() == LoongArch::PseudoAddTPRel_D
280 MCInstBuilder(ADD).
addOperand(Rd).addOperand(Rj).addOperand(Rk);
281 uint32_t
Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
285void LoongArchMCCodeEmitter::encodeInstruction(
286 const MCInst &
MI, SmallVectorImpl<char> &CB,
287 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
288 const MCInstrDesc &
Desc = MCII.
get(
MI.getOpcode());
292 switch (
MI.getOpcode()) {
295 case LoongArch::PseudoVREPLI_B:
296 case LoongArch::PseudoVREPLI_H:
297 case LoongArch::PseudoVREPLI_W:
298 case LoongArch::PseudoVREPLI_D:
299 return expandToVectorLDI<LoongArch::VLDI>(
MI, CB, Fixups, STI);
300 case LoongArch::PseudoXVREPLI_B:
301 case LoongArch::PseudoXVREPLI_H:
302 case LoongArch::PseudoXVREPLI_W:
303 case LoongArch::PseudoXVREPLI_D:
304 return expandToVectorLDI<LoongArch::XVLDI>(
MI, CB, Fixups, STI);
305 case LoongArch::PseudoAddTPRel_W:
306 case LoongArch::PseudoAddTPRel_D:
307 return expandAddTPRel(
MI, CB, Fixups, STI);
314 uint32_t
Bits = getBinaryCodeForInstr(
MI, Fixups, STI);
323 return new LoongArchMCCodeEmitter(Ctx, MCII);
326#include "LoongArchGenMCCodeEmitter.inc"
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!")
bool getRelaxHint() const
MCCodeEmitter - Generic instruction encoding interface.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
const MCRegisterInfo * getRegisterInfo() const
Base class for the full range of assembler expressions which are needed for parsing.
@ SymbolRef
References to labels and assigned expressions.
@ Specifier
Expression with a relocation specifier.
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Instances of this class represent operands of the MCInst class.
MCRegister getReg() const
Returns the register number.
const MCExpr * getExpr() const
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Spec getSpecifier() const
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ ADD
Simple integer binary arithmetic operators.
@ fixup_loongarch_abs64_hi12
@ fixup_loongarch_abs_hi20
@ fixup_loongarch_abs_lo12
@ fixup_loongarch_invalid
@ fixup_loongarch_abs64_lo20
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
MCCodeEmitter * createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
static Lanai::Fixups FixupKind(const MCExpr *Expr)
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
@ FirstLiteralRelocationKind
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.