[Sparc] Add initial implementation of MC Code emitter for sparc.
[oota-llvm.git] / lib / Target / Sparc / MCTargetDesc / SparcMCCodeEmitter.cpp
1 //===-- SparcMCCodeEmitter.cpp - Convert Sparc 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 SparcMCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "mccodeemitter"
15 #include "SparcMCTargetDesc.h"
16 #include "MCTargetDesc/SparcFixupKinds.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/ADT/Statistic.h"
23 #include "llvm/Support/raw_ostream.h"
24
25 using namespace llvm;
26
27 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
28
29 namespace {
30 class SparcMCCodeEmitter : public MCCodeEmitter {
31   SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
32   void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
33   MCContext &Ctx;
34
35 public:
36   SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
37
38   ~SparcMCCodeEmitter() {}
39
40   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
41                          SmallVectorImpl<MCFixup> &Fixups) const;
42
43   // getBinaryCodeForInstr - TableGen'erated function for getting the
44   // binary encoding for an instruction.
45   uint64_t getBinaryCodeForInstr(const MCInst &MI,
46                                  SmallVectorImpl<MCFixup> &Fixups) const;
47
48   /// getMachineOpValue - Return binary encoding of operand. If the machine
49   /// operand requires relocation, record the relocation and return zero.
50   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
51                              SmallVectorImpl<MCFixup> &Fixups) const;
52
53   unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
54                              SmallVectorImpl<MCFixup> &Fixups) const;
55   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
56                              SmallVectorImpl<MCFixup> &Fixups) const;
57
58 };
59 } // end anonymous namespace
60
61 MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
62                                               const MCRegisterInfo &MRI,
63                                               const MCSubtargetInfo &STI,
64                                               MCContext &Ctx) {
65   return new SparcMCCodeEmitter(Ctx);
66 }
67
68 void SparcMCCodeEmitter::
69 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
70                   SmallVectorImpl<MCFixup> &Fixups) const {
71   unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
72
73   // Output the constant in big endian byte order.
74   for (unsigned i = 0; i != 4; ++i) {
75     OS << (char)(Bits >> 24);
76     Bits <<= 8;
77   }
78
79   ++MCNumEmitted;  // Keep track of the # of mi's emitted.
80 }
81
82
83 unsigned SparcMCCodeEmitter::
84 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
85                   SmallVectorImpl<MCFixup> &Fixups) const {
86
87   if (MO.isReg())
88     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
89
90   if (MO.isImm())
91     return MO.getImm();
92
93   assert(MO.isExpr());
94   const MCExpr *Expr = MO.getExpr();
95   int64_t Res;
96   if (Expr->EvaluateAsAbsolute(Res))
97     return Res;
98
99   assert(0 && "Unhandled expression!");
100   return 0;
101 }
102
103 unsigned SparcMCCodeEmitter::
104 getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
105                      SmallVectorImpl<MCFixup> &Fixups) const {
106   const MCOperand &MO = MI.getOperand(OpNo);
107   if (MO.isReg() || MO.isImm())
108     return getMachineOpValue(MI, MO, Fixups);
109
110   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
111                                    (MCFixupKind)Sparc::fixup_sparc_call30));
112   return 0;
113 }
114
115 unsigned SparcMCCodeEmitter::
116 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
117                   SmallVectorImpl<MCFixup> &Fixups) const {
118   const MCOperand &MO = MI.getOperand(OpNo);
119   if (MO.isReg() || MO.isImm())
120     return getMachineOpValue(MI, MO, Fixups);
121
122   Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
123   if (MI.getOpcode() == SP::BPXCC)
124     fixup = Sparc::fixup_sparc_br19;
125
126   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
127                                    (MCFixupKind)fixup));
128   return 0;
129 }
130
131 #include "SparcGenMCCodeEmitter.inc"