SparcMCCodeEmitter.cpp revision 263763
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
27using namespace llvm;
28
29STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
30
31namespace {
32class SparcMCCodeEmitter : public MCCodeEmitter {
33  SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
34  void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
35  MCContext &Ctx;
36
37public:
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
63MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
64                                              const MCRegisterInfo &MRI,
65                                              const MCSubtargetInfo &STI,
66                                              MCContext &Ctx) {
67  return new SparcMCCodeEmitter(Ctx);
68}
69
70void SparcMCCodeEmitter::
71EncodeInstruction(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
100unsigned SparcMCCodeEmitter::
101getMachineOpValue(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
126unsigned SparcMCCodeEmitter::
127getCallTargetOpValue(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
160unsigned SparcMCCodeEmitter::
161getBranchTargetOpValue(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"
177