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