blob: 2904929ce376b23908e627abb4538d198cc83432 [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
Venkatraman Govindarajub73aeca2014-01-06 01:22:54 +000014#include "SparcMCExpr.h"
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000015#include "MCTargetDesc/SparcFixupKinds.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "SparcMCTargetDesc.h"
17#include "llvm/ADT/Statistic.h"
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000018#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"
Venkatraman Govindarajufd075002014-02-07 05:54:20 +000023#include "llvm/MC/MCSymbol.h"
Douglas Katzman9160e782015-04-29 20:30:57 +000024#include "llvm/MC/MCAsmInfo.h"
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000025#include "llvm/Support/raw_ostream.h"
26
27using namespace llvm;
28
Chandler Carruth84e68b22014-04-22 02:41:26 +000029#define DEBUG_TYPE "mccodeemitter"
30
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000031STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
32
33namespace {
34class SparcMCCodeEmitter : public MCCodeEmitter {
Aaron Ballmanf9a18972015-02-15 22:54:22 +000035 SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
36 void operator=(const SparcMCCodeEmitter &) = delete;
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000037 MCContext &Ctx;
38
39public:
40 SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
41
Alexander Kornienkof817c1c2015-04-11 02:11:45 +000042 ~SparcMCCodeEmitter() override {}
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000043
Jim Grosbach91df21f2015-05-15 19:13:16 +000044 void encodeInstruction(const MCInst &MI, raw_ostream &OS,
David Woodhouse9784cef2014-01-28 23:13:07 +000045 SmallVectorImpl<MCFixup> &Fixups,
Craig Topperb0c941b2014-04-29 07:57:13 +000046 const MCSubtargetInfo &STI) const override;
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000047
48 // getBinaryCodeForInstr - TableGen'erated function for getting the
49 // binary encoding for an instruction.
50 uint64_t getBinaryCodeForInstr(const MCInst &MI,
David Woodhouse3fa98a62014-01-28 23:13:18 +000051 SmallVectorImpl<MCFixup> &Fixups,
52 const MCSubtargetInfo &STI) const;
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000053
54 /// getMachineOpValue - Return binary encoding of operand. If the machine
55 /// operand requires relocation, record the relocation and return zero.
56 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
David Woodhouse3fa98a62014-01-28 23:13:18 +000057 SmallVectorImpl<MCFixup> &Fixups,
58 const MCSubtargetInfo &STI) const;
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000059
60 unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +000061 SmallVectorImpl<MCFixup> &Fixups,
62 const MCSubtargetInfo &STI) const;
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000063 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +000064 SmallVectorImpl<MCFixup> &Fixups,
65 const MCSubtargetInfo &STI) const;
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +000066 unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
67 SmallVectorImpl<MCFixup> &Fixups,
68 const MCSubtargetInfo &STI) const;
Venkatraman Govindarajub745e672014-03-02 09:46:56 +000069 unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
70 SmallVectorImpl<MCFixup> &Fixups,
71 const MCSubtargetInfo &STI) const;
72
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000073};
74} // end anonymous namespace
75
76MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
77 const MCRegisterInfo &MRI,
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000078 MCContext &Ctx) {
79 return new SparcMCCodeEmitter(Ctx);
80}
81
Jim Grosbach91df21f2015-05-15 19:13:16 +000082void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
Douglas Katzman9160e782015-04-29 20:30:57 +000083 SmallVectorImpl<MCFixup> &Fixups,
84 const MCSubtargetInfo &STI) const {
David Woodhouse3fa98a62014-01-28 23:13:18 +000085 unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000086
Douglas Katzman9160e782015-04-29 20:30:57 +000087 if (Ctx.getAsmInfo()->isLittleEndian()) {
88 // Output the bits in little-endian byte order.
89 for (unsigned i = 0; i != 4; ++i) {
90 OS << (char)Bits;
91 Bits >>= 8;
92 }
93 } else {
94 // Output the bits in big-endian byte order.
95 for (unsigned i = 0; i != 4; ++i) {
96 OS << (char)(Bits >> 24);
97 Bits <<= 8;
98 }
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000099 }
Venkatraman Govindarajufd075002014-02-07 05:54:20 +0000100 unsigned tlsOpNo = 0;
101 switch (MI.getOpcode()) {
102 default: break;
103 case SP::TLS_CALL: tlsOpNo = 1; break;
104 case SP::TLS_ADDrr:
105 case SP::TLS_ADDXrr:
106 case SP::TLS_LDrr:
107 case SP::TLS_LDXrr: tlsOpNo = 3; break;
108 }
109 if (tlsOpNo != 0) {
110 const MCOperand &MO = MI.getOperand(tlsOpNo);
111 uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
112 assert(op == 0 && "Unexpected operand value!");
113 (void)op; // suppress warning.
114 }
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000115
116 ++MCNumEmitted; // Keep track of the # of mi's emitted.
117}
118
119
120unsigned SparcMCCodeEmitter::
121getMachineOpValue(const MCInst &MI, const MCOperand &MO,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000122 SmallVectorImpl<MCFixup> &Fixups,
123 const MCSubtargetInfo &STI) const {
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000124
125 if (MO.isReg())
126 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
127
128 if (MO.isImm())
129 return MO.getImm();
130
131 assert(MO.isExpr());
132 const MCExpr *Expr = MO.getExpr();
Venkatraman Govindarajub73aeca2014-01-06 01:22:54 +0000133 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
Venkatraman Govindaraju104643d2014-02-07 04:24:35 +0000134 MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
Jim Grosbach63661f82015-05-15 19:13:05 +0000135 Fixups.push_back(MCFixup::create(0, Expr, Kind));
Venkatraman Govindarajub73aeca2014-01-06 01:22:54 +0000136 return 0;
137 }
138
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000139 int64_t Res;
Jim Grosbach13760bd2015-05-30 01:25:56 +0000140 if (Expr->evaluateAsAbsolute(Res))
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000141 return Res;
142
Craig Topper35b2f752014-06-19 06:10:58 +0000143 llvm_unreachable("Unhandled expression!");
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000144 return 0;
145}
146
147unsigned SparcMCCodeEmitter::
148getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000149 SmallVectorImpl<MCFixup> &Fixups,
150 const MCSubtargetInfo &STI) const {
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000151 const MCOperand &MO = MI.getOperand(OpNo);
152 if (MO.isReg() || MO.isImm())
David Woodhouse3fa98a62014-01-28 23:13:18 +0000153 return getMachineOpValue(MI, MO, Fixups, STI);
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000154
Venkatraman Govindarajufd075002014-02-07 05:54:20 +0000155 if (MI.getOpcode() == SP::TLS_CALL) {
156 // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
Jim Grosbach91df21f2015-05-15 19:13:16 +0000157 // encodeInstruction.
Venkatraman Govindarajufd075002014-02-07 05:54:20 +0000158#ifndef NDEBUG
159 // Verify that the callee is actually __tls_get_addr.
160 const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
161 assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
162 "Unexpected expression in TLS_CALL");
163 const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
164 assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
165 "Unexpected function for TLS_CALL");
166#endif
167 return 0;
168 }
169
Venkatraman Govindaraju104643d2014-02-07 04:24:35 +0000170 MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
171
172 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
173 if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
174 fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
175 }
176
Jim Grosbach63661f82015-05-15 19:13:05 +0000177 Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind));
Venkatraman Govindaraju104643d2014-02-07 04:24:35 +0000178
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000179 return 0;
180}
181
182unsigned SparcMCCodeEmitter::
183getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000184 SmallVectorImpl<MCFixup> &Fixups,
185 const MCSubtargetInfo &STI) const {
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000186 const MCOperand &MO = MI.getOperand(OpNo);
187 if (MO.isReg() || MO.isImm())
David Woodhouse3fa98a62014-01-28 23:13:18 +0000188 return getMachineOpValue(MI, MO, Fixups, STI);
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000189
Jim Grosbach63661f82015-05-15 19:13:05 +0000190 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +0000191 (MCFixupKind)Sparc::fixup_sparc_br22));
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000192 return 0;
193}
194
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +0000195unsigned SparcMCCodeEmitter::
196getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
197 SmallVectorImpl<MCFixup> &Fixups,
198 const MCSubtargetInfo &STI) const {
199 const MCOperand &MO = MI.getOperand(OpNo);
200 if (MO.isReg() || MO.isImm())
201 return getMachineOpValue(MI, MO, Fixups, STI);
202
Jim Grosbach63661f82015-05-15 19:13:05 +0000203 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +0000204 (MCFixupKind)Sparc::fixup_sparc_br19));
205 return 0;
206}
Venkatraman Govindarajub745e672014-03-02 09:46:56 +0000207unsigned SparcMCCodeEmitter::
208getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
209 SmallVectorImpl<MCFixup> &Fixups,
210 const MCSubtargetInfo &STI) const {
211 const MCOperand &MO = MI.getOperand(OpNo);
212 if (MO.isReg() || MO.isImm())
213 return getMachineOpValue(MI, MO, Fixups, STI);
214
Jim Grosbach63661f82015-05-15 19:13:05 +0000215 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
Venkatraman Govindarajub745e672014-03-02 09:46:56 +0000216 (MCFixupKind)Sparc::fixup_sparc_br16_2));
Jim Grosbach63661f82015-05-15 19:13:05 +0000217 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
Venkatraman Govindarajub745e672014-03-02 09:46:56 +0000218 (MCFixupKind)Sparc::fixup_sparc_br16_14));
219
220 return 0;
221}
222
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +0000223
224
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000225#include "SparcGenMCCodeEmitter.inc"