181ad6265SDimitry Andric //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file implements the LoongArchMCCodeEmitter class. 1081ad6265SDimitry Andric // 1181ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1281ad6265SDimitry Andric 13bdd1243dSDimitry Andric #include "LoongArchFixupKinds.h" 1481ad6265SDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h" 15bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchMCExpr.h" 1681ad6265SDimitry Andric #include "MCTargetDesc/LoongArchMCTargetDesc.h" 1781ad6265SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 1881ad6265SDimitry Andric #include "llvm/MC/MCContext.h" 1981ad6265SDimitry Andric #include "llvm/MC/MCInstBuilder.h" 2081ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 2181ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 22647cbc5dSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 23bdd1243dSDimitry Andric #include "llvm/Support/Casting.h" 2481ad6265SDimitry Andric #include "llvm/Support/EndianStream.h" 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric using namespace llvm; 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric #define DEBUG_TYPE "mccodeemitter" 2981ad6265SDimitry Andric 3081ad6265SDimitry Andric namespace { 3181ad6265SDimitry Andric class LoongArchMCCodeEmitter : public MCCodeEmitter { 3281ad6265SDimitry Andric LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; 3381ad6265SDimitry Andric void operator=(const LoongArchMCCodeEmitter &) = delete; 3481ad6265SDimitry Andric MCContext &Ctx; 3581ad6265SDimitry Andric MCInstrInfo const &MCII; 3681ad6265SDimitry Andric 3781ad6265SDimitry Andric public: 3881ad6265SDimitry Andric LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 3981ad6265SDimitry Andric : Ctx(ctx), MCII(MCII) {} 4081ad6265SDimitry Andric 4181ad6265SDimitry Andric ~LoongArchMCCodeEmitter() override {} 4281ad6265SDimitry Andric 4306c3fb27SDimitry Andric void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, 4481ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4581ad6265SDimitry Andric const MCSubtargetInfo &STI) const override; 4681ad6265SDimitry Andric 4706c3fb27SDimitry Andric template <unsigned Opc> 4806c3fb27SDimitry Andric void expandToVectorLDI(const MCInst &MI, SmallVectorImpl<char> &CB, 4906c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5006c3fb27SDimitry Andric const MCSubtargetInfo &STI) const; 5106c3fb27SDimitry Andric 520fca6ea1SDimitry Andric void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB, 530fca6ea1SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 540fca6ea1SDimitry Andric const MCSubtargetInfo &STI) const; 550fca6ea1SDimitry Andric 5681ad6265SDimitry Andric /// TableGen'erated function for getting the binary encoding for an 5781ad6265SDimitry Andric /// instruction. 5881ad6265SDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI, 5981ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6081ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric /// Return binary encoding of operand. If the machine operand requires 6381ad6265SDimitry Andric /// relocation, record the relocation and return zero. 6481ad6265SDimitry Andric unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 6581ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6681ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric /// Return binary encoding of an immediate operand specified by OpNo. 6981ad6265SDimitry Andric /// The value returned is the value of the immediate minus 1. 7081ad6265SDimitry Andric /// Note that this function is dedicated to specific immediate types, 7181ad6265SDimitry Andric /// e.g. uimm2_plus1. 7281ad6265SDimitry Andric unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 7381ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7481ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 7581ad6265SDimitry Andric 7681ad6265SDimitry Andric /// Return binary encoding of an immediate operand specified by OpNo. 7781ad6265SDimitry Andric /// The value returned is the value of the immediate shifted right 7806c3fb27SDimitry Andric // arithmetically by N. 7981ad6265SDimitry Andric /// Note that this function is dedicated to specific immediate types, 8081ad6265SDimitry Andric /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. 8106c3fb27SDimitry Andric template <unsigned N> 8206c3fb27SDimitry Andric unsigned getImmOpValueAsr(const MCInst &MI, unsigned OpNo, 8381ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8406c3fb27SDimitry Andric const MCSubtargetInfo &STI) const { 8506c3fb27SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 8606c3fb27SDimitry Andric if (MO.isImm()) { 8706c3fb27SDimitry Andric unsigned Res = MI.getOperand(OpNo).getImm(); 8806c3fb27SDimitry Andric assert((Res & ((1U << N) - 1U)) == 0 && "lowest N bits are non-zero"); 8906c3fb27SDimitry Andric return Res >> N; 9006c3fb27SDimitry Andric } 9106c3fb27SDimitry Andric return getExprOpValue(MI, MO, Fixups, STI); 9206c3fb27SDimitry Andric } 93bdd1243dSDimitry Andric 94bdd1243dSDimitry Andric unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO, 95bdd1243dSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 96bdd1243dSDimitry Andric const MCSubtargetInfo &STI) const; 9781ad6265SDimitry Andric }; 98972a253aSDimitry Andric } // end namespace 9981ad6265SDimitry Andric 10081ad6265SDimitry Andric unsigned 10181ad6265SDimitry Andric LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 10281ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10381ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 10481ad6265SDimitry Andric 10581ad6265SDimitry Andric if (MO.isReg()) 10681ad6265SDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 10781ad6265SDimitry Andric 10881ad6265SDimitry Andric if (MO.isImm()) 10981ad6265SDimitry Andric return static_cast<unsigned>(MO.getImm()); 11081ad6265SDimitry Andric 111bdd1243dSDimitry Andric // MO must be an Expr. 112bdd1243dSDimitry Andric assert(MO.isExpr()); 113bdd1243dSDimitry Andric return getExprOpValue(MI, MO, Fixups, STI); 11481ad6265SDimitry Andric } 11581ad6265SDimitry Andric 11681ad6265SDimitry Andric unsigned 11781ad6265SDimitry Andric LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 11881ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 11981ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 12081ad6265SDimitry Andric return MI.getOperand(OpNo).getImm() - 1; 12181ad6265SDimitry Andric } 12281ad6265SDimitry Andric 12381ad6265SDimitry Andric unsigned 124bdd1243dSDimitry Andric LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO, 125bdd1243dSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 126bdd1243dSDimitry Andric const MCSubtargetInfo &STI) const { 127bdd1243dSDimitry Andric assert(MO.isExpr() && "getExprOpValue expects only expressions"); 128647cbc5dSDimitry Andric bool RelaxCandidate = false; 129647cbc5dSDimitry Andric bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax); 130bdd1243dSDimitry Andric const MCExpr *Expr = MO.getExpr(); 131bdd1243dSDimitry Andric MCExpr::ExprKind Kind = Expr->getKind(); 132bdd1243dSDimitry Andric LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid; 133bdd1243dSDimitry Andric if (Kind == MCExpr::Target) { 134bdd1243dSDimitry Andric const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr); 135bdd1243dSDimitry Andric 136647cbc5dSDimitry Andric RelaxCandidate = LAExpr->getRelaxHint(); 137bdd1243dSDimitry Andric switch (LAExpr->getKind()) { 138bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_None: 139bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_Invalid: 140bdd1243dSDimitry Andric llvm_unreachable("Unhandled fixup kind!"); 1410fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R: 1420fca6ea1SDimitry Andric llvm_unreachable("VK_LoongArch_TLS_LE_ADD_R should not represent an " 1430fca6ea1SDimitry Andric "instruction operand"); 144bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_B16: 145bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_b16; 146bdd1243dSDimitry Andric break; 147bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_B21: 148bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_b21; 149bdd1243dSDimitry Andric break; 150bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_B26: 151bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_CALL: 152bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_CALL_PLT: 153bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_b26; 154bdd1243dSDimitry Andric break; 155bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_ABS_HI20: 156bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_abs_hi20; 157bdd1243dSDimitry Andric break; 158bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_ABS_LO12: 159bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_abs_lo12; 160bdd1243dSDimitry Andric break; 161bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_ABS64_LO20: 162bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_abs64_lo20; 163bdd1243dSDimitry Andric break; 164bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_ABS64_HI12: 165bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_abs64_hi12; 166bdd1243dSDimitry Andric break; 167bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_PCALA_HI20: 168bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_pcala_hi20; 169bdd1243dSDimitry Andric break; 170bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_PCALA_LO12: 171bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_pcala_lo12; 172bdd1243dSDimitry Andric break; 173bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_PCALA64_LO20: 174bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_pcala64_lo20; 175bdd1243dSDimitry Andric break; 176bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_PCALA64_HI12: 177bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_pcala64_hi12; 178bdd1243dSDimitry Andric break; 179bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20: 180bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_got_pc_hi20; 181bdd1243dSDimitry Andric break; 182bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12: 183bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_got_pc_lo12; 184bdd1243dSDimitry Andric break; 185bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20: 186bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_got64_pc_lo20; 187bdd1243dSDimitry Andric break; 188bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12: 189bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_got64_pc_hi12; 190bdd1243dSDimitry Andric break; 191bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_GOT_HI20: 192bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_got_hi20; 193bdd1243dSDimitry Andric break; 194bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_GOT_LO12: 195bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_got_lo12; 196bdd1243dSDimitry Andric break; 197bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_GOT64_LO20: 198bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_got64_lo20; 199bdd1243dSDimitry Andric break; 200bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_GOT64_HI12: 201bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_got64_hi12; 202bdd1243dSDimitry Andric break; 203bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20: 204bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_le_hi20; 205bdd1243dSDimitry Andric break; 206bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12: 207bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_le_lo12; 208bdd1243dSDimitry Andric break; 209bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20: 210bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_le64_lo20; 211bdd1243dSDimitry Andric break; 212bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12: 213bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_le64_hi12; 214bdd1243dSDimitry Andric break; 215bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20: 216bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_hi20; 217bdd1243dSDimitry Andric break; 218bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12: 219bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_lo12; 220bdd1243dSDimitry Andric break; 221bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20: 222bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_lo20; 223bdd1243dSDimitry Andric break; 224bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12: 225bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_hi12; 226bdd1243dSDimitry Andric break; 227bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20: 228bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ie_hi20; 229bdd1243dSDimitry Andric break; 230bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12: 231bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ie_lo12; 232bdd1243dSDimitry Andric break; 233bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20: 234bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ie64_lo20; 235bdd1243dSDimitry Andric break; 236bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12: 237bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ie64_hi12; 238bdd1243dSDimitry Andric break; 239bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20: 240bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ld_pc_hi20; 241bdd1243dSDimitry Andric break; 242bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20: 243bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ld_hi20; 244bdd1243dSDimitry Andric break; 245bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20: 246bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_gd_pc_hi20; 247bdd1243dSDimitry Andric break; 248bdd1243dSDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20: 249bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_gd_hi20; 250bdd1243dSDimitry Andric break; 2511db9f3b2SDimitry Andric case LoongArchMCExpr::VK_LoongArch_CALL36: 2521db9f3b2SDimitry Andric FixupKind = LoongArch::fixup_loongarch_call36; 2531db9f3b2SDimitry Andric break; 2540fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20: 2550fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_hi20; 2560fca6ea1SDimitry Andric break; 2570fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12: 2580fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_lo12; 2590fca6ea1SDimitry Andric break; 2600fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20: 2610fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_lo20; 2620fca6ea1SDimitry Andric break; 2630fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12: 2640fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_hi12; 2650fca6ea1SDimitry Andric break; 2660fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20: 2670fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc_hi20; 2680fca6ea1SDimitry Andric break; 2690fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12: 2700fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc_lo12; 2710fca6ea1SDimitry Andric break; 2720fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20: 2730fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc64_lo20; 2740fca6ea1SDimitry Andric break; 2750fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12: 2760fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc64_hi12; 2770fca6ea1SDimitry Andric break; 2780fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD: 2790fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc_ld; 2800fca6ea1SDimitry Andric break; 2810fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL: 2820fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc_call; 2830fca6ea1SDimitry Andric break; 2840fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R: 2850fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_le_hi20_r; 2860fca6ea1SDimitry Andric break; 2870fca6ea1SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R: 2880fca6ea1SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_le_lo12_r; 2890fca6ea1SDimitry Andric break; 290*52418fc2SDimitry Andric case LoongArchMCExpr::VK_LoongArch_PCREL20_S2: 291*52418fc2SDimitry Andric FixupKind = LoongArch::fixup_loongarch_pcrel20_s2; 292*52418fc2SDimitry Andric break; 293*52418fc2SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2: 294*52418fc2SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_ld_pcrel20_s2; 295*52418fc2SDimitry Andric break; 296*52418fc2SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2: 297*52418fc2SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_gd_pcrel20_s2; 298*52418fc2SDimitry Andric break; 299*52418fc2SDimitry Andric case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2: 300*52418fc2SDimitry Andric FixupKind = LoongArch::fixup_loongarch_tls_desc_pcrel20_s2; 301*52418fc2SDimitry Andric break; 302bdd1243dSDimitry Andric } 303bdd1243dSDimitry Andric } else if (Kind == MCExpr::SymbolRef && 304bdd1243dSDimitry Andric cast<MCSymbolRefExpr>(Expr)->getKind() == 305bdd1243dSDimitry Andric MCSymbolRefExpr::VK_None) { 306bdd1243dSDimitry Andric switch (MI.getOpcode()) { 307bdd1243dSDimitry Andric default: 308bdd1243dSDimitry Andric break; 309bdd1243dSDimitry Andric case LoongArch::BEQ: 310bdd1243dSDimitry Andric case LoongArch::BNE: 311bdd1243dSDimitry Andric case LoongArch::BLT: 312bdd1243dSDimitry Andric case LoongArch::BGE: 313bdd1243dSDimitry Andric case LoongArch::BLTU: 314bdd1243dSDimitry Andric case LoongArch::BGEU: 315bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_b16; 316bdd1243dSDimitry Andric break; 317bdd1243dSDimitry Andric case LoongArch::BEQZ: 318bdd1243dSDimitry Andric case LoongArch::BNEZ: 319bdd1243dSDimitry Andric case LoongArch::BCEQZ: 320bdd1243dSDimitry Andric case LoongArch::BCNEZ: 321bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_b21; 322bdd1243dSDimitry Andric break; 323bdd1243dSDimitry Andric case LoongArch::B: 3245f757f3fSDimitry Andric case LoongArch::BL: 325bdd1243dSDimitry Andric FixupKind = LoongArch::fixup_loongarch_b26; 326bdd1243dSDimitry Andric break; 327bdd1243dSDimitry Andric } 328bdd1243dSDimitry Andric } 329bdd1243dSDimitry Andric 330bdd1243dSDimitry Andric assert(FixupKind != LoongArch::fixup_loongarch_invalid && 331bdd1243dSDimitry Andric "Unhandled expression!"); 332bdd1243dSDimitry Andric 333bdd1243dSDimitry Andric Fixups.push_back( 334bdd1243dSDimitry Andric MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); 335647cbc5dSDimitry Andric 336647cbc5dSDimitry Andric // Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax 337647cbc5dSDimitry Andric // hint. 338647cbc5dSDimitry Andric if (EnableRelax && RelaxCandidate) { 339647cbc5dSDimitry Andric const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); 340647cbc5dSDimitry Andric Fixups.push_back(MCFixup::create( 341647cbc5dSDimitry Andric 0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc())); 342647cbc5dSDimitry Andric } 343647cbc5dSDimitry Andric 344bdd1243dSDimitry Andric return 0; 345bdd1243dSDimitry Andric } 346bdd1243dSDimitry Andric 34706c3fb27SDimitry Andric template <unsigned Opc> 34806c3fb27SDimitry Andric void LoongArchMCCodeEmitter::expandToVectorLDI( 34906c3fb27SDimitry Andric const MCInst &MI, SmallVectorImpl<char> &CB, 35006c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { 35106c3fb27SDimitry Andric int64_t Imm = MI.getOperand(1).getImm() & 0x3FF; 35206c3fb27SDimitry Andric switch (MI.getOpcode()) { 35306c3fb27SDimitry Andric case LoongArch::PseudoVREPLI_B: 35406c3fb27SDimitry Andric case LoongArch::PseudoXVREPLI_B: 35506c3fb27SDimitry Andric break; 35606c3fb27SDimitry Andric case LoongArch::PseudoVREPLI_H: 35706c3fb27SDimitry Andric case LoongArch::PseudoXVREPLI_H: 35806c3fb27SDimitry Andric Imm |= 0x400; 35906c3fb27SDimitry Andric break; 36006c3fb27SDimitry Andric case LoongArch::PseudoVREPLI_W: 36106c3fb27SDimitry Andric case LoongArch::PseudoXVREPLI_W: 36206c3fb27SDimitry Andric Imm |= 0x800; 36306c3fb27SDimitry Andric break; 36406c3fb27SDimitry Andric case LoongArch::PseudoVREPLI_D: 36506c3fb27SDimitry Andric case LoongArch::PseudoXVREPLI_D: 36606c3fb27SDimitry Andric Imm |= 0xC00; 36706c3fb27SDimitry Andric break; 36806c3fb27SDimitry Andric } 36906c3fb27SDimitry Andric MCInst TmpInst = MCInstBuilder(Opc).addOperand(MI.getOperand(0)).addImm(Imm); 37006c3fb27SDimitry Andric uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 3715f757f3fSDimitry Andric support::endian::write(CB, Binary, llvm::endianness::little); 37206c3fb27SDimitry Andric } 37306c3fb27SDimitry Andric 3740fca6ea1SDimitry Andric void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI, 3750fca6ea1SDimitry Andric SmallVectorImpl<char> &CB, 3760fca6ea1SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3770fca6ea1SDimitry Andric const MCSubtargetInfo &STI) const { 3780fca6ea1SDimitry Andric MCOperand Rd = MI.getOperand(0); 3790fca6ea1SDimitry Andric MCOperand Rj = MI.getOperand(1); 3800fca6ea1SDimitry Andric MCOperand Rk = MI.getOperand(2); 3810fca6ea1SDimitry Andric MCOperand Symbol = MI.getOperand(3); 3820fca6ea1SDimitry Andric assert(Symbol.isExpr() && 3830fca6ea1SDimitry Andric "Expected expression as third input to TP-relative add"); 3840fca6ea1SDimitry Andric 3850fca6ea1SDimitry Andric const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Symbol.getExpr()); 3860fca6ea1SDimitry Andric assert(Expr && 3870fca6ea1SDimitry Andric Expr->getKind() == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R && 3880fca6ea1SDimitry Andric "Expected %le_add_r relocation on TP-relative symbol"); 3890fca6ea1SDimitry Andric 3900fca6ea1SDimitry Andric // Emit the correct %le_add_r relocation for the symbol. 3910fca6ea1SDimitry Andric // TODO: Emit R_LARCH_RELAX for %le_add_r where the relax feature is enabled. 3920fca6ea1SDimitry Andric Fixups.push_back(MCFixup::create( 3930fca6ea1SDimitry Andric 0, Expr, MCFixupKind(LoongArch::fixup_loongarch_tls_le_add_r), 3940fca6ea1SDimitry Andric MI.getLoc())); 3950fca6ea1SDimitry Andric 3960fca6ea1SDimitry Andric // Emit a normal ADD instruction with the given operands. 3970fca6ea1SDimitry Andric unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D 3980fca6ea1SDimitry Andric ? LoongArch::ADD_D 3990fca6ea1SDimitry Andric : LoongArch::ADD_W; 4000fca6ea1SDimitry Andric MCInst TmpInst = 4010fca6ea1SDimitry Andric MCInstBuilder(ADD).addOperand(Rd).addOperand(Rj).addOperand(Rk); 4020fca6ea1SDimitry Andric uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 4030fca6ea1SDimitry Andric support::endian::write(CB, Binary, llvm::endianness::little); 4040fca6ea1SDimitry Andric } 4050fca6ea1SDimitry Andric 40681ad6265SDimitry Andric void LoongArchMCCodeEmitter::encodeInstruction( 40706c3fb27SDimitry Andric const MCInst &MI, SmallVectorImpl<char> &CB, 40806c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { 40981ad6265SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 41081ad6265SDimitry Andric // Get byte count of instruction. 41181ad6265SDimitry Andric unsigned Size = Desc.getSize(); 41281ad6265SDimitry Andric 41306c3fb27SDimitry Andric switch (MI.getOpcode()) { 41406c3fb27SDimitry Andric default: 41506c3fb27SDimitry Andric break; 41606c3fb27SDimitry Andric case LoongArch::PseudoVREPLI_B: 41706c3fb27SDimitry Andric case LoongArch::PseudoVREPLI_H: 41806c3fb27SDimitry Andric case LoongArch::PseudoVREPLI_W: 41906c3fb27SDimitry Andric case LoongArch::PseudoVREPLI_D: 42006c3fb27SDimitry Andric return expandToVectorLDI<LoongArch::VLDI>(MI, CB, Fixups, STI); 42106c3fb27SDimitry Andric case LoongArch::PseudoXVREPLI_B: 42206c3fb27SDimitry Andric case LoongArch::PseudoXVREPLI_H: 42306c3fb27SDimitry Andric case LoongArch::PseudoXVREPLI_W: 42406c3fb27SDimitry Andric case LoongArch::PseudoXVREPLI_D: 42506c3fb27SDimitry Andric return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI); 4260fca6ea1SDimitry Andric case LoongArch::PseudoAddTPRel_W: 4270fca6ea1SDimitry Andric case LoongArch::PseudoAddTPRel_D: 4280fca6ea1SDimitry Andric return expandAddTPRel(MI, CB, Fixups, STI); 42906c3fb27SDimitry Andric } 43006c3fb27SDimitry Andric 43181ad6265SDimitry Andric switch (Size) { 43281ad6265SDimitry Andric default: 43381ad6265SDimitry Andric llvm_unreachable("Unhandled encodeInstruction length!"); 43481ad6265SDimitry Andric case 4: { 43581ad6265SDimitry Andric uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 4365f757f3fSDimitry Andric support::endian::write(CB, Bits, llvm::endianness::little); 43781ad6265SDimitry Andric break; 43881ad6265SDimitry Andric } 43981ad6265SDimitry Andric } 44081ad6265SDimitry Andric } 44181ad6265SDimitry Andric 44281ad6265SDimitry Andric MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, 44381ad6265SDimitry Andric MCContext &Ctx) { 44481ad6265SDimitry Andric return new LoongArchMCCodeEmitter(Ctx, MCII); 44581ad6265SDimitry Andric } 44681ad6265SDimitry Andric 44781ad6265SDimitry Andric #include "LoongArchGenMCCodeEmitter.inc" 448