//=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the LoongArchMCCodeEmitter class. // //===----------------------------------------------------------------------===// #include "MCTargetDesc/LoongArchBaseInfo.h" #include "MCTargetDesc/LoongArchMCTargetDesc.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/EndianStream.h" using namespace llvm; #define DEBUG_TYPE "mccodeemitter" namespace { class LoongArchMCCodeEmitter : public MCCodeEmitter { LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; void operator=(const LoongArchMCCodeEmitter &) = delete; MCContext &Ctx; MCInstrInfo const &MCII; public: LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) : Ctx(ctx), MCII(MCII) {} ~LoongArchMCCodeEmitter() override {} void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override; /// TableGen'erated function for getting the binary encoding for an /// instruction. uint64_t getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; /// Return binary encoding of operand. If the machine operand requires /// relocation, record the relocation and return zero. unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; /// Return binary encoding of an immediate operand specified by OpNo. /// The value returned is the value of the immediate minus 1. /// Note that this function is dedicated to specific immediate types, /// e.g. uimm2_plus1. unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; /// Return binary encoding of an immediate operand specified by OpNo. /// The value returned is the value of the immediate shifted right // arithmetically by 2. /// Note that this function is dedicated to specific immediate types, /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; }; } // end namespace unsigned LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); if (MO.isImm()) return static_cast(MO.getImm()); llvm_unreachable("Unhandled expression!"); } unsigned LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { return MI.getOperand(OpNo).getImm() - 1; } unsigned LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { unsigned Res = MI.getOperand(OpNo).getImm(); assert((Res & 3) == 0 && "lowest 2 bits are non-zero"); return Res >> 2; } void LoongArchMCCodeEmitter::encodeInstruction( const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); // Get byte count of instruction. unsigned Size = Desc.getSize(); switch (Size) { default: llvm_unreachable("Unhandled encodeInstruction length!"); case 4: { uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); support::endian::write(OS, Bits, support::little); break; } } } MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx) { return new LoongArchMCCodeEmitter(Ctx, MCII); } #include "LoongArchGenMCCodeEmitter.inc"