summaryrefslogtreecommitdiff
path: root/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp')
-rw-r--r--lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp115
1 files changed, 110 insertions, 5 deletions
diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 9309d493cef4..641997e67e06 100644
--- a/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -11,6 +11,9 @@
//
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/RISCVBaseInfo.h"
+#include "MCTargetDesc/RISCVFixupKinds.h"
+#include "MCTargetDesc/RISCVMCExpr.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -18,8 +21,10 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/raw_ostream.h"
@@ -28,15 +33,18 @@ using namespace llvm;
#define DEBUG_TYPE "mccodeemitter"
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
+STATISTIC(MCNumFixups, "Number of MC fixups created");
namespace {
class RISCVMCCodeEmitter : public MCCodeEmitter {
RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete;
void operator=(const RISCVMCCodeEmitter &) = delete;
MCContext &Ctx;
+ MCInstrInfo const &MCII;
public:
- RISCVMCCodeEmitter(MCContext &ctx) : Ctx(ctx) {}
+ RISCVMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
+ : Ctx(ctx), MCII(MCII) {}
~RISCVMCCodeEmitter() override {}
@@ -55,21 +63,45 @@ public:
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+
+ unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ unsigned getImmOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
};
} // end anonymous namespace
MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
MCContext &Ctx) {
- return new RISCVMCCodeEmitter(Ctx);
+ return new RISCVMCCodeEmitter(Ctx, MCII);
}
void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
- // For now, we only support RISC-V instructions with 32-bit length
- uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
- support::endian::Writer<support::little>(OS).write(Bits);
+ 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 2: {
+ uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
+ support::endian::Writer<support::little>(OS).write<uint16_t>(Bits);
+ break;
+ }
+ case 4: {
+ uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
+ support::endian::Writer<support::little>(OS).write(Bits);
+ break;
+ }
+ }
+
++MCNumEmitted; // Keep track of the # of mi's emitted.
}
@@ -88,4 +120,77 @@ RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
return 0;
}
+unsigned
+RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ if (MO.isImm()) {
+ unsigned Res = MO.getImm();
+ assert((Res & 1) == 0 && "LSB is non-zero");
+ return Res >> 1;
+ }
+
+ return getImmOpValue(MI, OpNo, Fixups, STI);
+}
+
+unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ MCInstrDesc const &Desc = MCII.get(MI.getOpcode());
+ unsigned MIFrm = Desc.TSFlags & RISCVII::InstFormatMask;
+
+ // If the destination is an immediate, there is nothing to do
+ if (MO.isImm())
+ return MO.getImm();
+
+ assert(MO.isExpr() &&
+ "getImmOpValue expects only expressions or immediates");
+ const MCExpr *Expr = MO.getExpr();
+ MCExpr::ExprKind Kind = Expr->getKind();
+ RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid;
+ if (Kind == MCExpr::Target) {
+ const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr);
+
+ switch (RVExpr->getKind()) {
+ case RISCVMCExpr::VK_RISCV_None:
+ case RISCVMCExpr::VK_RISCV_Invalid:
+ llvm_unreachable("Unhandled fixup kind!");
+ case RISCVMCExpr::VK_RISCV_LO:
+ FixupKind = MIFrm == RISCVII::InstFormatI ? RISCV::fixup_riscv_lo12_i
+ : RISCV::fixup_riscv_lo12_s;
+ break;
+ case RISCVMCExpr::VK_RISCV_HI:
+ FixupKind = RISCV::fixup_riscv_hi20;
+ break;
+ case RISCVMCExpr::VK_RISCV_PCREL_HI:
+ FixupKind = RISCV::fixup_riscv_pcrel_hi20;
+ break;
+ }
+ } else if (Kind == MCExpr::SymbolRef &&
+ cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) {
+ if (Desc.getOpcode() == RISCV::JAL) {
+ FixupKind = RISCV::fixup_riscv_jal;
+ } else if (MIFrm == RISCVII::InstFormatB) {
+ FixupKind = RISCV::fixup_riscv_branch;
+ } else if (MIFrm == RISCVII::InstFormatCJ) {
+ FixupKind = RISCV::fixup_riscv_rvc_jump;
+ } else if (MIFrm == RISCVII::InstFormatCB) {
+ FixupKind = RISCV::fixup_riscv_rvc_branch;
+ }
+ }
+
+ assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!");
+
+ Fixups.push_back(
+ MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));
+ ++MCNumFixups;
+
+ return 0;
+}
+
#include "RISCVGenMCCodeEmitter.inc"