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