xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
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