1 //===-- RISCVMCCodeEmitter.cpp - Convert RISCV code to machine code -------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the RISCVMCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MCTargetDesc/RISCVMCTargetDesc.h"
15 #include "llvm/ADT/Statistic.h"
16 #include "llvm/MC/MCAsmInfo.h"
17 #include "llvm/MC/MCCodeEmitter.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/Support/EndianStream.h"
24 #include "llvm/Support/raw_ostream.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "mccodeemitter"
29 
30 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
31 
32 namespace {
33 class RISCVMCCodeEmitter : public MCCodeEmitter {
34   RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete;
35   void operator=(const RISCVMCCodeEmitter &) = delete;
36   MCContext &Ctx;
37 
38 public:
39   RISCVMCCodeEmitter(MCContext &ctx) : Ctx(ctx) {}
40 
41   ~RISCVMCCodeEmitter() override {}
42 
43   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
44                          SmallVectorImpl<MCFixup> &Fixups,
45                          const MCSubtargetInfo &STI) const override;
46 
47   /// TableGen'erated function for getting the binary encoding for an
48   /// instruction.
49   uint64_t getBinaryCodeForInstr(const MCInst &MI,
50                                  SmallVectorImpl<MCFixup> &Fixups,
51                                  const MCSubtargetInfo &STI) const;
52 
53   /// Return binary encoding of operand. If the machine operand requires
54   /// relocation, record the relocation and return zero.
55   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
56                              SmallVectorImpl<MCFixup> &Fixups,
57                              const MCSubtargetInfo &STI) const;
58 
59   unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
60                              SmallVectorImpl<MCFixup> &Fixups,
61                              const MCSubtargetInfo &STI) const;
62   unsigned getImmOpValue(const MCInst &MI, unsigned OpNo,
63                          SmallVectorImpl<MCFixup> &Fixups,
64                          const MCSubtargetInfo &STI) const;
65 };
66 } // end anonymous namespace
67 
68 MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII,
69                                               const MCRegisterInfo &MRI,
70                                               MCContext &Ctx) {
71   return new RISCVMCCodeEmitter(Ctx);
72 }
73 
74 void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
75                                            SmallVectorImpl<MCFixup> &Fixups,
76                                            const MCSubtargetInfo &STI) const {
77   // For now, we only support RISC-V instructions with 32-bit length
78   uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
79   support::endian::Writer<support::little>(OS).write(Bits);
80   ++MCNumEmitted; // Keep track of the # of mi's emitted.
81 }
82 
83 unsigned
84 RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
85                                       SmallVectorImpl<MCFixup> &Fixups,
86                                       const MCSubtargetInfo &STI) const {
87 
88   if (MO.isReg())
89     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
90 
91   if (MO.isImm())
92     return static_cast<unsigned>(MO.getImm());
93 
94   llvm_unreachable("Unhandled expression!");
95   return 0;
96 }
97 
98 unsigned
99 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
100                                       SmallVectorImpl<MCFixup> &Fixups,
101                                       const MCSubtargetInfo &STI) const {
102   const MCOperand &MO = MI.getOperand(OpNo);
103 
104   if (MO.isImm()) {
105     unsigned Res = MO.getImm();
106     assert((Res & 1) == 0 && "LSB is non-zero");
107     return Res >> 1;
108   }
109 
110   llvm_unreachable("Unhandled expression!");
111 
112   return 0;
113 }
114 
115 unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
116                                            SmallVectorImpl<MCFixup> &Fixups,
117                                            const MCSubtargetInfo &STI) const {
118 
119   const MCOperand &MO = MI.getOperand(OpNo);
120 
121   // If the destination is an immediate, there is nothing to do
122   if (MO.isImm())
123     return MO.getImm();
124 
125   llvm_unreachable("Unhandled expression!");
126 
127   return 0;
128 }
129 
130 #include "RISCVGenMCCodeEmitter.inc"
131