blob: 9171d4dc9c00e507227e8897007ee161ed9bc84a [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.
Benjamin Kramer50e2a292015-06-04 15:03:02 +000089 support::endian::Writer<support::little>(OS).write<uint32_t>(Bits);
Douglas Katzman9160e782015-04-29 20:30:57 +000090 } else {
91 // Output the bits in big-endian byte order.
Benjamin Kramer50e2a292015-06-04 15:03:02 +000092 support::endian::Writer<support::big>(OS).write<uint32_t>(Bits);
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +000093 }
Venkatraman Govindarajufd075002014-02-07 05:54:20 +000094 unsigned tlsOpNo = 0;
95 switch (MI.getOpcode()) {
96 default: break;
97 case SP::TLS_CALL: tlsOpNo = 1; break;
98 case SP::TLS_ADDrr:
99 case SP::TLS_ADDXrr:
100 case SP::TLS_LDrr:
101 case SP::TLS_LDXrr: tlsOpNo = 3; break;
102 }
103 if (tlsOpNo != 0) {
104 const MCOperand &MO = MI.getOperand(tlsOpNo);
105 uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
106 assert(op == 0 && "Unexpected operand value!");
107 (void)op; // suppress warning.
108 }
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000109
110 ++MCNumEmitted; // Keep track of the # of mi's emitted.
111}
112
113
114unsigned SparcMCCodeEmitter::
115getMachineOpValue(const MCInst &MI, const MCOperand &MO,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000116 SmallVectorImpl<MCFixup> &Fixups,
117 const MCSubtargetInfo &STI) const {
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000118
119 if (MO.isReg())
120 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
121
122 if (MO.isImm())
123 return MO.getImm();
124
125 assert(MO.isExpr());
126 const MCExpr *Expr = MO.getExpr();
Venkatraman Govindarajub73aeca2014-01-06 01:22:54 +0000127 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
Venkatraman Govindaraju104643d2014-02-07 04:24:35 +0000128 MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
Jim Grosbach63661f82015-05-15 19:13:05 +0000129 Fixups.push_back(MCFixup::create(0, Expr, Kind));
Venkatraman Govindarajub73aeca2014-01-06 01:22:54 +0000130 return 0;
131 }
132
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000133 int64_t Res;
Jim Grosbach13760bd2015-05-30 01:25:56 +0000134 if (Expr->evaluateAsAbsolute(Res))
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000135 return Res;
136
Craig Topper35b2f752014-06-19 06:10:58 +0000137 llvm_unreachable("Unhandled expression!");
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000138 return 0;
139}
140
141unsigned SparcMCCodeEmitter::
142getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000143 SmallVectorImpl<MCFixup> &Fixups,
144 const MCSubtargetInfo &STI) const {
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000145 const MCOperand &MO = MI.getOperand(OpNo);
146 if (MO.isReg() || MO.isImm())
David Woodhouse3fa98a62014-01-28 23:13:18 +0000147 return getMachineOpValue(MI, MO, Fixups, STI);
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000148
Venkatraman Govindarajufd075002014-02-07 05:54:20 +0000149 if (MI.getOpcode() == SP::TLS_CALL) {
150 // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
Jim Grosbach91df21f2015-05-15 19:13:16 +0000151 // encodeInstruction.
Venkatraman Govindarajufd075002014-02-07 05:54:20 +0000152#ifndef NDEBUG
153 // Verify that the callee is actually __tls_get_addr.
154 const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
155 assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
156 "Unexpected expression in TLS_CALL");
157 const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
158 assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
159 "Unexpected function for TLS_CALL");
160#endif
161 return 0;
162 }
163
Venkatraman Govindaraju104643d2014-02-07 04:24:35 +0000164 MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
165
166 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
167 if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
168 fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
169 }
170
Jim Grosbach63661f82015-05-15 19:13:05 +0000171 Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind));
Venkatraman Govindaraju104643d2014-02-07 04:24:35 +0000172
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000173 return 0;
174}
175
176unsigned SparcMCCodeEmitter::
177getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000178 SmallVectorImpl<MCFixup> &Fixups,
179 const MCSubtargetInfo &STI) const {
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000180 const MCOperand &MO = MI.getOperand(OpNo);
181 if (MO.isReg() || MO.isImm())
David Woodhouse3fa98a62014-01-28 23:13:18 +0000182 return getMachineOpValue(MI, MO, Fixups, STI);
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000183
Jim Grosbach63661f82015-05-15 19:13:05 +0000184 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +0000185 (MCFixupKind)Sparc::fixup_sparc_br22));
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000186 return 0;
187}
188
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +0000189unsigned SparcMCCodeEmitter::
190getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
191 SmallVectorImpl<MCFixup> &Fixups,
192 const MCSubtargetInfo &STI) const {
193 const MCOperand &MO = MI.getOperand(OpNo);
194 if (MO.isReg() || MO.isImm())
195 return getMachineOpValue(MI, MO, Fixups, STI);
196
Jim Grosbach63661f82015-05-15 19:13:05 +0000197 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +0000198 (MCFixupKind)Sparc::fixup_sparc_br19));
199 return 0;
200}
Venkatraman Govindarajub745e672014-03-02 09:46:56 +0000201unsigned SparcMCCodeEmitter::
202getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
203 SmallVectorImpl<MCFixup> &Fixups,
204 const MCSubtargetInfo &STI) const {
205 const MCOperand &MO = MI.getOperand(OpNo);
206 if (MO.isReg() || MO.isImm())
207 return getMachineOpValue(MI, MO, Fixups, STI);
208
Jim Grosbach63661f82015-05-15 19:13:05 +0000209 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
Venkatraman Govindarajub745e672014-03-02 09:46:56 +0000210 (MCFixupKind)Sparc::fixup_sparc_br16_2));
Jim Grosbach63661f82015-05-15 19:13:05 +0000211 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
Venkatraman Govindarajub745e672014-03-02 09:46:56 +0000212 (MCFixupKind)Sparc::fixup_sparc_br16_14));
213
214 return 0;
215}
216
Venkatraman Govindarajuc86e0f32014-03-01 22:03:07 +0000217
218
Venkatraman Govindaraju5f1cce52014-01-05 02:13:48 +0000219#include "SparcGenMCCodeEmitter.inc"