blob: 641aed429bbd91f776450362fc42b9be8f1863fb [file] [log] [blame]
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +00001//===-- 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
25using namespace llvm;
26
27STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
28
29namespace {
30class SparcMCCodeEmitter : public MCCodeEmitter {
31 SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
32 void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
33 MCContext &Ctx;
34
35public:
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
61MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
62 const MCRegisterInfo &MRI,
63 const MCSubtargetInfo &STI,
64 MCContext &Ctx) {
65 return new SparcMCCodeEmitter(Ctx);
66}
67
68void SparcMCCodeEmitter::
69EncodeInstruction(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
83unsigned SparcMCCodeEmitter::
84getMachineOpValue(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
103unsigned SparcMCCodeEmitter::
104getCallTargetOpValue(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
115unsigned SparcMCCodeEmitter::
116getBranchTargetOpValue(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"