]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / 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 "SparcMCExpr.h"
16 #include "SparcMCTargetDesc.h"
17 #include "MCTargetDesc/SparcFixupKinds.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/MC/MCSymbol.h"
24 #include "llvm/ADT/Statistic.h"
25 #include "llvm/Support/raw_ostream.h"
26
27 using namespace llvm;
28
29 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
30
31 namespace {
32 class SparcMCCodeEmitter : public MCCodeEmitter {
33   SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
34   void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
35   MCContext &Ctx;
36
37 public:
38   SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
39
40   ~SparcMCCodeEmitter() {}
41
42   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
43                          SmallVectorImpl<MCFixup> &Fixups) const;
44
45   // getBinaryCodeForInstr - TableGen'erated function for getting the
46   // binary encoding for an instruction.
47   uint64_t getBinaryCodeForInstr(const MCInst &MI,
48                                  SmallVectorImpl<MCFixup> &Fixups) const;
49
50   /// getMachineOpValue - Return binary encoding of operand. If the machine
51   /// operand requires relocation, record the relocation and return zero.
52   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
53                              SmallVectorImpl<MCFixup> &Fixups) const;
54
55   unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
56                              SmallVectorImpl<MCFixup> &Fixups) const;
57   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
58                              SmallVectorImpl<MCFixup> &Fixups) const;
59
60 };
61 } // end anonymous namespace
62
63 MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
64                                               const MCRegisterInfo &MRI,
65                                               const MCSubtargetInfo &STI,
66                                               MCContext &Ctx) {
67   return new SparcMCCodeEmitter(Ctx);
68 }
69
70 void SparcMCCodeEmitter::
71 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
72                   SmallVectorImpl<MCFixup> &Fixups) const {
73   unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
74
75   // Output the constant in big endian byte order.
76   for (unsigned i = 0; i != 4; ++i) {
77     OS << (char)(Bits >> 24);
78     Bits <<= 8;
79   }
80   unsigned tlsOpNo = 0;
81   switch (MI.getOpcode()) {
82   default: break;
83   case SP::TLS_CALL:   tlsOpNo = 1; break;
84   case SP::TLS_ADDrr:
85   case SP::TLS_ADDXrr:
86   case SP::TLS_LDrr:
87   case SP::TLS_LDXrr:  tlsOpNo = 3; break;
88   }
89   if (tlsOpNo != 0) {
90     const MCOperand &MO = MI.getOperand(tlsOpNo);
91     uint64_t op = getMachineOpValue(MI, MO, Fixups);
92     assert(op == 0 && "Unexpected operand value!");
93     (void)op; // suppress warning.
94   }
95
96   ++MCNumEmitted;  // Keep track of the # of mi's emitted.
97 }
98
99
100 unsigned SparcMCCodeEmitter::
101 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
102                   SmallVectorImpl<MCFixup> &Fixups) const {
103
104   if (MO.isReg())
105     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
106
107   if (MO.isImm())
108     return MO.getImm();
109
110   assert(MO.isExpr());
111   const MCExpr *Expr = MO.getExpr();
112   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
113     MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
114     Fixups.push_back(MCFixup::Create(0, Expr, Kind));
115     return 0;
116   }
117
118   int64_t Res;
119   if (Expr->EvaluateAsAbsolute(Res))
120     return Res;
121
122   assert(0 && "Unhandled expression!");
123   return 0;
124 }
125
126 unsigned SparcMCCodeEmitter::
127 getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
128                      SmallVectorImpl<MCFixup> &Fixups) const {
129   const MCOperand &MO = MI.getOperand(OpNo);
130   if (MO.isReg() || MO.isImm())
131     return getMachineOpValue(MI, MO, Fixups);
132
133   if (MI.getOpcode() == SP::TLS_CALL) {
134     // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
135     // EncodeInstruction.
136 #ifndef NDEBUG
137     // Verify that the callee is actually __tls_get_addr.
138     const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
139     assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
140            "Unexpected expression in TLS_CALL");
141     const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
142     assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
143            "Unexpected function for TLS_CALL");
144 #endif
145     return 0;
146   }
147
148   MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
149
150   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
151     if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
152       fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
153   }
154
155   Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind));
156
157   return 0;
158 }
159
160 unsigned SparcMCCodeEmitter::
161 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
162                   SmallVectorImpl<MCFixup> &Fixups) const {
163   const MCOperand &MO = MI.getOperand(OpNo);
164   if (MO.isReg() || MO.isImm())
165     return getMachineOpValue(MI, MO, Fixups);
166
167   Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
168   if (MI.getOpcode() == SP::BPXCC)
169     fixup = Sparc::fixup_sparc_br19;
170
171   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
172                                    (MCFixupKind)fixup));
173   return 0;
174 }
175
176 #include "SparcGenMCCodeEmitter.inc"