1*81ad6265SDimitry Andric //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric // 9*81ad6265SDimitry Andric // This file implements the LoongArchMCCodeEmitter class. 10*81ad6265SDimitry Andric // 11*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 12*81ad6265SDimitry Andric 13*81ad6265SDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h" 14*81ad6265SDimitry Andric #include "MCTargetDesc/LoongArchMCTargetDesc.h" 15*81ad6265SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 16*81ad6265SDimitry Andric #include "llvm/MC/MCContext.h" 17*81ad6265SDimitry Andric #include "llvm/MC/MCInstBuilder.h" 18*81ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 19*81ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 20*81ad6265SDimitry Andric #include "llvm/Support/EndianStream.h" 21*81ad6265SDimitry Andric 22*81ad6265SDimitry Andric using namespace llvm; 23*81ad6265SDimitry Andric 24*81ad6265SDimitry Andric #define DEBUG_TYPE "mccodeemitter" 25*81ad6265SDimitry Andric 26*81ad6265SDimitry Andric namespace { 27*81ad6265SDimitry Andric class LoongArchMCCodeEmitter : public MCCodeEmitter { 28*81ad6265SDimitry Andric LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; 29*81ad6265SDimitry Andric void operator=(const LoongArchMCCodeEmitter &) = delete; 30*81ad6265SDimitry Andric MCContext &Ctx; 31*81ad6265SDimitry Andric MCInstrInfo const &MCII; 32*81ad6265SDimitry Andric 33*81ad6265SDimitry Andric public: 34*81ad6265SDimitry Andric LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 35*81ad6265SDimitry Andric : Ctx(ctx), MCII(MCII) {} 36*81ad6265SDimitry Andric 37*81ad6265SDimitry Andric ~LoongArchMCCodeEmitter() override {} 38*81ad6265SDimitry Andric 39*81ad6265SDimitry Andric void encodeInstruction(const MCInst &MI, raw_ostream &OS, 40*81ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 41*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const override; 42*81ad6265SDimitry Andric 43*81ad6265SDimitry Andric /// TableGen'erated function for getting the binary encoding for an 44*81ad6265SDimitry Andric /// instruction. 45*81ad6265SDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI, 46*81ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 47*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 48*81ad6265SDimitry Andric 49*81ad6265SDimitry Andric /// Return binary encoding of operand. If the machine operand requires 50*81ad6265SDimitry Andric /// relocation, record the relocation and return zero. 51*81ad6265SDimitry Andric unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 52*81ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 53*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 54*81ad6265SDimitry Andric 55*81ad6265SDimitry Andric /// Return binary encoding of an immediate operand specified by OpNo. 56*81ad6265SDimitry Andric /// The value returned is the value of the immediate minus 1. 57*81ad6265SDimitry Andric /// Note that this function is dedicated to specific immediate types, 58*81ad6265SDimitry Andric /// e.g. uimm2_plus1. 59*81ad6265SDimitry Andric unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 60*81ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 61*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 62*81ad6265SDimitry Andric 63*81ad6265SDimitry Andric /// Return binary encoding of an immediate operand specified by OpNo. 64*81ad6265SDimitry Andric /// The value returned is the value of the immediate shifted right 65*81ad6265SDimitry Andric // arithmetically by 2. 66*81ad6265SDimitry Andric /// Note that this function is dedicated to specific immediate types, 67*81ad6265SDimitry Andric /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. 68*81ad6265SDimitry Andric unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, 69*81ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 70*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 71*81ad6265SDimitry Andric }; 72*81ad6265SDimitry Andric } // end anonymous namespace 73*81ad6265SDimitry Andric 74*81ad6265SDimitry Andric unsigned 75*81ad6265SDimitry Andric LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 76*81ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 77*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 78*81ad6265SDimitry Andric 79*81ad6265SDimitry Andric if (MO.isReg()) 80*81ad6265SDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 81*81ad6265SDimitry Andric 82*81ad6265SDimitry Andric if (MO.isImm()) 83*81ad6265SDimitry Andric return static_cast<unsigned>(MO.getImm()); 84*81ad6265SDimitry Andric 85*81ad6265SDimitry Andric llvm_unreachable("Unhandled expression!"); 86*81ad6265SDimitry Andric } 87*81ad6265SDimitry Andric 88*81ad6265SDimitry Andric unsigned 89*81ad6265SDimitry Andric LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 90*81ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 91*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 92*81ad6265SDimitry Andric return MI.getOperand(OpNo).getImm() - 1; 93*81ad6265SDimitry Andric } 94*81ad6265SDimitry Andric 95*81ad6265SDimitry Andric unsigned 96*81ad6265SDimitry Andric LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, 97*81ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 98*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 99*81ad6265SDimitry Andric unsigned Res = MI.getOperand(OpNo).getImm(); 100*81ad6265SDimitry Andric assert((Res & 3) == 0 && "lowest 2 bits are non-zero"); 101*81ad6265SDimitry Andric return Res >> 2; 102*81ad6265SDimitry Andric } 103*81ad6265SDimitry Andric 104*81ad6265SDimitry Andric void LoongArchMCCodeEmitter::encodeInstruction( 105*81ad6265SDimitry Andric const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, 106*81ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 107*81ad6265SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 108*81ad6265SDimitry Andric // Get byte count of instruction. 109*81ad6265SDimitry Andric unsigned Size = Desc.getSize(); 110*81ad6265SDimitry Andric 111*81ad6265SDimitry Andric switch (Size) { 112*81ad6265SDimitry Andric default: 113*81ad6265SDimitry Andric llvm_unreachable("Unhandled encodeInstruction length!"); 114*81ad6265SDimitry Andric case 4: { 115*81ad6265SDimitry Andric uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 116*81ad6265SDimitry Andric support::endian::write(OS, Bits, support::little); 117*81ad6265SDimitry Andric break; 118*81ad6265SDimitry Andric } 119*81ad6265SDimitry Andric } 120*81ad6265SDimitry Andric } 121*81ad6265SDimitry Andric 122*81ad6265SDimitry Andric MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, 123*81ad6265SDimitry Andric MCContext &Ctx) { 124*81ad6265SDimitry Andric return new LoongArchMCCodeEmitter(Ctx, MCII); 125*81ad6265SDimitry Andric } 126*81ad6265SDimitry Andric 127*81ad6265SDimitry Andric #include "LoongArchGenMCCodeEmitter.inc" 128