1 //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch 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 LoongArchMCCodeEmitter class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LoongArchFixupKinds.h" 14 #include "MCTargetDesc/LoongArchBaseInfo.h" 15 #include "MCTargetDesc/LoongArchMCExpr.h" 16 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 17 #include "llvm/MC/MCCodeEmitter.h" 18 #include "llvm/MC/MCContext.h" 19 #include "llvm/MC/MCInstBuilder.h" 20 #include "llvm/MC/MCInstrInfo.h" 21 #include "llvm/MC/MCRegisterInfo.h" 22 #include "llvm/MC/MCSubtargetInfo.h" 23 #include "llvm/Support/Casting.h" 24 #include "llvm/Support/EndianStream.h" 25 26 using namespace llvm; 27 28 #define DEBUG_TYPE "mccodeemitter" 29 30 namespace { 31 class LoongArchMCCodeEmitter : public MCCodeEmitter { 32 LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; 33 void operator=(const LoongArchMCCodeEmitter &) = delete; 34 MCContext &Ctx; 35 MCInstrInfo const &MCII; 36 37 public: 38 LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 39 : Ctx(ctx), MCII(MCII) {} 40 41 ~LoongArchMCCodeEmitter() override {} 42 43 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, 44 SmallVectorImpl<MCFixup> &Fixups, 45 const MCSubtargetInfo &STI) const override; 46 47 template <unsigned Opc> 48 void expandToVectorLDI(const MCInst &MI, SmallVectorImpl<char> &CB, 49 SmallVectorImpl<MCFixup> &Fixups, 50 const MCSubtargetInfo &STI) const; 51 52 /// TableGen'erated function for getting the binary encoding for an 53 /// instruction. 54 uint64_t getBinaryCodeForInstr(const MCInst &MI, 55 SmallVectorImpl<MCFixup> &Fixups, 56 const MCSubtargetInfo &STI) const; 57 58 /// Return binary encoding of operand. If the machine operand requires 59 /// relocation, record the relocation and return zero. 60 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 61 SmallVectorImpl<MCFixup> &Fixups, 62 const MCSubtargetInfo &STI) const; 63 64 /// Return binary encoding of an immediate operand specified by OpNo. 65 /// The value returned is the value of the immediate minus 1. 66 /// Note that this function is dedicated to specific immediate types, 67 /// e.g. uimm2_plus1. 68 unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 69 SmallVectorImpl<MCFixup> &Fixups, 70 const MCSubtargetInfo &STI) const; 71 72 /// Return binary encoding of an immediate operand specified by OpNo. 73 /// The value returned is the value of the immediate shifted right 74 // arithmetically by N. 75 /// Note that this function is dedicated to specific immediate types, 76 /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. 77 template <unsigned N> 78 unsigned getImmOpValueAsr(const MCInst &MI, unsigned OpNo, 79 SmallVectorImpl<MCFixup> &Fixups, 80 const MCSubtargetInfo &STI) const { 81 const MCOperand &MO = MI.getOperand(OpNo); 82 if (MO.isImm()) { 83 unsigned Res = MI.getOperand(OpNo).getImm(); 84 assert((Res & ((1U << N) - 1U)) == 0 && "lowest N bits are non-zero"); 85 return Res >> N; 86 } 87 return getExprOpValue(MI, MO, Fixups, STI); 88 } 89 90 unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO, 91 SmallVectorImpl<MCFixup> &Fixups, 92 const MCSubtargetInfo &STI) const; 93 }; 94 } // end namespace 95 96 unsigned 97 LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 98 SmallVectorImpl<MCFixup> &Fixups, 99 const MCSubtargetInfo &STI) const { 100 101 if (MO.isReg()) 102 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 103 104 if (MO.isImm()) 105 return static_cast<unsigned>(MO.getImm()); 106 107 // MO must be an Expr. 108 assert(MO.isExpr()); 109 return getExprOpValue(MI, MO, Fixups, STI); 110 } 111 112 unsigned 113 LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 114 SmallVectorImpl<MCFixup> &Fixups, 115 const MCSubtargetInfo &STI) const { 116 return MI.getOperand(OpNo).getImm() - 1; 117 } 118 119 unsigned 120 LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO, 121 SmallVectorImpl<MCFixup> &Fixups, 122 const MCSubtargetInfo &STI) const { 123 assert(MO.isExpr() && "getExprOpValue expects only expressions"); 124 bool RelaxCandidate = false; 125 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax); 126 const MCExpr *Expr = MO.getExpr(); 127 MCExpr::ExprKind Kind = Expr->getKind(); 128 LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid; 129 if (Kind == MCExpr::Target) { 130 const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr); 131 132 RelaxCandidate = LAExpr->getRelaxHint(); 133 switch (LAExpr->getKind()) { 134 case LoongArchMCExpr::VK_LoongArch_None: 135 case LoongArchMCExpr::VK_LoongArch_Invalid: 136 llvm_unreachable("Unhandled fixup kind!"); 137 case LoongArchMCExpr::VK_LoongArch_B16: 138 FixupKind = LoongArch::fixup_loongarch_b16; 139 break; 140 case LoongArchMCExpr::VK_LoongArch_B21: 141 FixupKind = LoongArch::fixup_loongarch_b21; 142 break; 143 case LoongArchMCExpr::VK_LoongArch_B26: 144 case LoongArchMCExpr::VK_LoongArch_CALL: 145 case LoongArchMCExpr::VK_LoongArch_CALL_PLT: 146 FixupKind = LoongArch::fixup_loongarch_b26; 147 break; 148 case LoongArchMCExpr::VK_LoongArch_ABS_HI20: 149 FixupKind = LoongArch::fixup_loongarch_abs_hi20; 150 break; 151 case LoongArchMCExpr::VK_LoongArch_ABS_LO12: 152 FixupKind = LoongArch::fixup_loongarch_abs_lo12; 153 break; 154 case LoongArchMCExpr::VK_LoongArch_ABS64_LO20: 155 FixupKind = LoongArch::fixup_loongarch_abs64_lo20; 156 break; 157 case LoongArchMCExpr::VK_LoongArch_ABS64_HI12: 158 FixupKind = LoongArch::fixup_loongarch_abs64_hi12; 159 break; 160 case LoongArchMCExpr::VK_LoongArch_PCALA_HI20: 161 FixupKind = LoongArch::fixup_loongarch_pcala_hi20; 162 break; 163 case LoongArchMCExpr::VK_LoongArch_PCALA_LO12: 164 FixupKind = LoongArch::fixup_loongarch_pcala_lo12; 165 break; 166 case LoongArchMCExpr::VK_LoongArch_PCALA64_LO20: 167 FixupKind = LoongArch::fixup_loongarch_pcala64_lo20; 168 break; 169 case LoongArchMCExpr::VK_LoongArch_PCALA64_HI12: 170 FixupKind = LoongArch::fixup_loongarch_pcala64_hi12; 171 break; 172 case LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20: 173 FixupKind = LoongArch::fixup_loongarch_got_pc_hi20; 174 break; 175 case LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12: 176 FixupKind = LoongArch::fixup_loongarch_got_pc_lo12; 177 break; 178 case LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20: 179 FixupKind = LoongArch::fixup_loongarch_got64_pc_lo20; 180 break; 181 case LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12: 182 FixupKind = LoongArch::fixup_loongarch_got64_pc_hi12; 183 break; 184 case LoongArchMCExpr::VK_LoongArch_GOT_HI20: 185 FixupKind = LoongArch::fixup_loongarch_got_hi20; 186 break; 187 case LoongArchMCExpr::VK_LoongArch_GOT_LO12: 188 FixupKind = LoongArch::fixup_loongarch_got_lo12; 189 break; 190 case LoongArchMCExpr::VK_LoongArch_GOT64_LO20: 191 FixupKind = LoongArch::fixup_loongarch_got64_lo20; 192 break; 193 case LoongArchMCExpr::VK_LoongArch_GOT64_HI12: 194 FixupKind = LoongArch::fixup_loongarch_got64_hi12; 195 break; 196 case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20: 197 FixupKind = LoongArch::fixup_loongarch_tls_le_hi20; 198 break; 199 case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12: 200 FixupKind = LoongArch::fixup_loongarch_tls_le_lo12; 201 break; 202 case LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20: 203 FixupKind = LoongArch::fixup_loongarch_tls_le64_lo20; 204 break; 205 case LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12: 206 FixupKind = LoongArch::fixup_loongarch_tls_le64_hi12; 207 break; 208 case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20: 209 FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_hi20; 210 break; 211 case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12: 212 FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_lo12; 213 break; 214 case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20: 215 FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_lo20; 216 break; 217 case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12: 218 FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_hi12; 219 break; 220 case LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20: 221 FixupKind = LoongArch::fixup_loongarch_tls_ie_hi20; 222 break; 223 case LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12: 224 FixupKind = LoongArch::fixup_loongarch_tls_ie_lo12; 225 break; 226 case LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20: 227 FixupKind = LoongArch::fixup_loongarch_tls_ie64_lo20; 228 break; 229 case LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12: 230 FixupKind = LoongArch::fixup_loongarch_tls_ie64_hi12; 231 break; 232 case LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20: 233 FixupKind = LoongArch::fixup_loongarch_tls_ld_pc_hi20; 234 break; 235 case LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20: 236 FixupKind = LoongArch::fixup_loongarch_tls_ld_hi20; 237 break; 238 case LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20: 239 FixupKind = LoongArch::fixup_loongarch_tls_gd_pc_hi20; 240 break; 241 case LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20: 242 FixupKind = LoongArch::fixup_loongarch_tls_gd_hi20; 243 break; 244 case LoongArchMCExpr::VK_LoongArch_CALL36: 245 FixupKind = LoongArch::fixup_loongarch_call36; 246 break; 247 } 248 } else if (Kind == MCExpr::SymbolRef && 249 cast<MCSymbolRefExpr>(Expr)->getKind() == 250 MCSymbolRefExpr::VK_None) { 251 switch (MI.getOpcode()) { 252 default: 253 break; 254 case LoongArch::BEQ: 255 case LoongArch::BNE: 256 case LoongArch::BLT: 257 case LoongArch::BGE: 258 case LoongArch::BLTU: 259 case LoongArch::BGEU: 260 FixupKind = LoongArch::fixup_loongarch_b16; 261 break; 262 case LoongArch::BEQZ: 263 case LoongArch::BNEZ: 264 case LoongArch::BCEQZ: 265 case LoongArch::BCNEZ: 266 FixupKind = LoongArch::fixup_loongarch_b21; 267 break; 268 case LoongArch::B: 269 case LoongArch::BL: 270 FixupKind = LoongArch::fixup_loongarch_b26; 271 break; 272 } 273 } 274 275 assert(FixupKind != LoongArch::fixup_loongarch_invalid && 276 "Unhandled expression!"); 277 278 Fixups.push_back( 279 MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); 280 281 // Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax 282 // hint. 283 if (EnableRelax && RelaxCandidate) { 284 const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); 285 Fixups.push_back(MCFixup::create( 286 0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc())); 287 } 288 289 return 0; 290 } 291 292 template <unsigned Opc> 293 void LoongArchMCCodeEmitter::expandToVectorLDI( 294 const MCInst &MI, SmallVectorImpl<char> &CB, 295 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { 296 int64_t Imm = MI.getOperand(1).getImm() & 0x3FF; 297 switch (MI.getOpcode()) { 298 case LoongArch::PseudoVREPLI_B: 299 case LoongArch::PseudoXVREPLI_B: 300 break; 301 case LoongArch::PseudoVREPLI_H: 302 case LoongArch::PseudoXVREPLI_H: 303 Imm |= 0x400; 304 break; 305 case LoongArch::PseudoVREPLI_W: 306 case LoongArch::PseudoXVREPLI_W: 307 Imm |= 0x800; 308 break; 309 case LoongArch::PseudoVREPLI_D: 310 case LoongArch::PseudoXVREPLI_D: 311 Imm |= 0xC00; 312 break; 313 } 314 MCInst TmpInst = MCInstBuilder(Opc).addOperand(MI.getOperand(0)).addImm(Imm); 315 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 316 support::endian::write(CB, Binary, llvm::endianness::little); 317 } 318 319 void LoongArchMCCodeEmitter::encodeInstruction( 320 const MCInst &MI, SmallVectorImpl<char> &CB, 321 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { 322 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 323 // Get byte count of instruction. 324 unsigned Size = Desc.getSize(); 325 326 switch (MI.getOpcode()) { 327 default: 328 break; 329 case LoongArch::PseudoVREPLI_B: 330 case LoongArch::PseudoVREPLI_H: 331 case LoongArch::PseudoVREPLI_W: 332 case LoongArch::PseudoVREPLI_D: 333 return expandToVectorLDI<LoongArch::VLDI>(MI, CB, Fixups, STI); 334 case LoongArch::PseudoXVREPLI_B: 335 case LoongArch::PseudoXVREPLI_H: 336 case LoongArch::PseudoXVREPLI_W: 337 case LoongArch::PseudoXVREPLI_D: 338 return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI); 339 } 340 341 switch (Size) { 342 default: 343 llvm_unreachable("Unhandled encodeInstruction length!"); 344 case 4: { 345 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 346 support::endian::write(CB, Bits, llvm::endianness::little); 347 break; 348 } 349 } 350 } 351 352 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, 353 MCContext &Ctx) { 354 return new LoongArchMCCodeEmitter(Ctx, MCII); 355 } 356 357 #include "LoongArchGenMCCodeEmitter.inc" 358