diff options
Diffstat (limited to 'llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp')
| -rw-r--r-- | llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp new file mode 100644 index 000000000000..9c6a4f39b9ea --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp @@ -0,0 +1,127 @@ +//=- 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<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const override; + + /// TableGen'erated function for getting the binary encoding for an + /// instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl<MCFixup> &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<MCFixup> &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<MCFixup> &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<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; +}; +} // end anonymous namespace + +unsigned +LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + if (MO.isReg()) + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + + if (MO.isImm()) + return static_cast<unsigned>(MO.getImm()); + + llvm_unreachable("Unhandled expression!"); +} + +unsigned +LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + return MI.getOperand(OpNo).getImm() - 1; +} + +unsigned +LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &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<MCFixup> &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" |
