Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
35294 views
1
//===-- SparcInstPrinter.cpp - Convert Sparc MCInst to assembly syntax -----==//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This class prints an Sparc MCInst to a .s file.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "SparcInstPrinter.h"
14
#include "Sparc.h"
15
#include "llvm/MC/MCExpr.h"
16
#include "llvm/MC/MCInst.h"
17
#include "llvm/MC/MCRegisterInfo.h"
18
#include "llvm/MC/MCSubtargetInfo.h"
19
#include "llvm/MC/MCSymbol.h"
20
#include "llvm/Support/raw_ostream.h"
21
using namespace llvm;
22
23
#define DEBUG_TYPE "asm-printer"
24
25
// The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target
26
// namespace. But SPARC backend uses "SP" as its namespace.
27
namespace llvm {
28
namespace Sparc {
29
using namespace SP;
30
}
31
}
32
33
#define GET_INSTRUCTION_NAME
34
#define PRINT_ALIAS_INSTR
35
#include "SparcGenAsmWriter.inc"
36
37
bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const {
38
return (STI.hasFeature(Sparc::FeatureV9)) != 0;
39
}
40
41
void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
42
OS << '%' << getRegisterName(Reg);
43
}
44
45
void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg,
46
unsigned AltIdx) const {
47
OS << '%' << getRegisterName(Reg, AltIdx);
48
}
49
50
void SparcInstPrinter::printInst(const MCInst *MI, uint64_t Address,
51
StringRef Annot, const MCSubtargetInfo &STI,
52
raw_ostream &O) {
53
if (!printAliasInstr(MI, Address, STI, O) &&
54
!printSparcAliasInstr(MI, STI, O))
55
printInstruction(MI, Address, STI, O);
56
printAnnotation(O, Annot);
57
}
58
59
bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI,
60
const MCSubtargetInfo &STI,
61
raw_ostream &O) {
62
switch (MI->getOpcode()) {
63
default: return false;
64
case SP::JMPLrr:
65
case SP::JMPLri: {
66
if (MI->getNumOperands() != 3)
67
return false;
68
if (!MI->getOperand(0).isReg())
69
return false;
70
switch (MI->getOperand(0).getReg()) {
71
default: return false;
72
case SP::G0: // jmp $addr | ret | retl
73
if (MI->getOperand(2).isImm() &&
74
MI->getOperand(2).getImm() == 8) {
75
switch(MI->getOperand(1).getReg()) {
76
default: break;
77
case SP::I7: O << "\tret"; return true;
78
case SP::O7: O << "\tretl"; return true;
79
}
80
}
81
O << "\tjmp "; printMemOperand(MI, 1, STI, O);
82
return true;
83
case SP::O7: // call $addr
84
O << "\tcall "; printMemOperand(MI, 1, STI, O);
85
return true;
86
}
87
}
88
case SP::V9FCMPS: case SP::V9FCMPD: case SP::V9FCMPQ:
89
case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: {
90
if (isV9(STI)
91
|| (MI->getNumOperands() != 3)
92
|| (!MI->getOperand(0).isReg())
93
|| (MI->getOperand(0).getReg() != SP::FCC0))
94
return false;
95
// if V8, skip printing %fcc0.
96
switch(MI->getOpcode()) {
97
default:
98
case SP::V9FCMPS: O << "\tfcmps "; break;
99
case SP::V9FCMPD: O << "\tfcmpd "; break;
100
case SP::V9FCMPQ: O << "\tfcmpq "; break;
101
case SP::V9FCMPES: O << "\tfcmpes "; break;
102
case SP::V9FCMPED: O << "\tfcmped "; break;
103
case SP::V9FCMPEQ: O << "\tfcmpeq "; break;
104
}
105
printOperand(MI, 1, STI, O);
106
O << ", ";
107
printOperand(MI, 2, STI, O);
108
return true;
109
}
110
}
111
}
112
113
void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,
114
const MCSubtargetInfo &STI,
115
raw_ostream &O) {
116
const MCOperand &MO = MI->getOperand (opNum);
117
118
if (MO.isReg()) {
119
unsigned Reg = MO.getReg();
120
if (isV9(STI))
121
printRegName(O, Reg, SP::RegNamesStateReg);
122
else
123
printRegName(O, Reg);
124
return ;
125
}
126
127
if (MO.isImm()) {
128
switch (MI->getOpcode()) {
129
default:
130
O << (int)MO.getImm();
131
return;
132
133
case SP::TICCri: // Fall through
134
case SP::TICCrr: // Fall through
135
case SP::TRAPri: // Fall through
136
case SP::TRAPrr: // Fall through
137
case SP::TXCCri: // Fall through
138
case SP::TXCCrr: // Fall through
139
// Only seven-bit values up to 127.
140
O << ((int) MO.getImm() & 0x7f);
141
return;
142
}
143
}
144
145
assert(MO.isExpr() && "Unknown operand kind in printOperand");
146
MO.getExpr()->print(O, &MAI);
147
}
148
149
void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum,
150
const MCSubtargetInfo &STI,
151
raw_ostream &O) {
152
const MCOperand &Op1 = MI->getOperand(opNum);
153
const MCOperand &Op2 = MI->getOperand(opNum + 1);
154
155
bool PrintedFirstOperand = false;
156
if (Op1.isReg() && Op1.getReg() != SP::G0) {
157
printOperand(MI, opNum, STI, O);
158
PrintedFirstOperand = true;
159
}
160
161
// Skip the second operand iff it adds nothing (literal 0 or %g0) and we've
162
// already printed the first one
163
const bool SkipSecondOperand =
164
PrintedFirstOperand && ((Op2.isReg() && Op2.getReg() == SP::G0) ||
165
(Op2.isImm() && Op2.getImm() == 0));
166
167
if (!SkipSecondOperand) {
168
if (PrintedFirstOperand)
169
O << '+';
170
printOperand(MI, opNum + 1, STI, O);
171
}
172
}
173
174
void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,
175
const MCSubtargetInfo &STI,
176
raw_ostream &O) {
177
int CC = (int)MI->getOperand(opNum).getImm();
178
switch (MI->getOpcode()) {
179
default: break;
180
case SP::FBCOND:
181
case SP::FBCONDA:
182
case SP::FBCOND_V9:
183
case SP::FBCONDA_V9:
184
case SP::BPFCC:
185
case SP::BPFCCA:
186
case SP::BPFCCNT:
187
case SP::BPFCCANT:
188
case SP::MOVFCCrr: case SP::V9MOVFCCrr:
189
case SP::MOVFCCri: case SP::V9MOVFCCri:
190
case SP::FMOVS_FCC: case SP::V9FMOVS_FCC:
191
case SP::FMOVD_FCC: case SP::V9FMOVD_FCC:
192
case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC:
193
// Make sure CC is a fp conditional flag.
194
CC = (CC < SPCC::FCC_BEGIN) ? (CC + SPCC::FCC_BEGIN) : CC;
195
break;
196
case SP::CBCOND:
197
case SP::CBCONDA:
198
// Make sure CC is a cp conditional flag.
199
CC = (CC < SPCC::CPCC_BEGIN) ? (CC + SPCC::CPCC_BEGIN) : CC;
200
break;
201
case SP::BPR:
202
case SP::BPRA:
203
case SP::BPRNT:
204
case SP::BPRANT:
205
case SP::MOVRri:
206
case SP::MOVRrr:
207
case SP::FMOVRS:
208
case SP::FMOVRD:
209
case SP::FMOVRQ:
210
// Make sure CC is a register conditional flag.
211
CC = (CC < SPCC::REG_BEGIN) ? (CC + SPCC::REG_BEGIN) : CC;
212
break;
213
}
214
O << SPARCCondCodeToString((SPCC::CondCodes)CC);
215
}
216
217
bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum,
218
const MCSubtargetInfo &STI,
219
raw_ostream &O) {
220
llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX.");
221
return true;
222
}
223
224
void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum,
225
const MCSubtargetInfo &STI,
226
raw_ostream &O) {
227
static const char *const TagNames[] = {
228
"#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore",
229
"#Lookaside", "#MemIssue", "#Sync"};
230
231
unsigned Imm = MI->getOperand(opNum).getImm();
232
233
if (Imm > 127) {
234
O << Imm;
235
return;
236
}
237
238
bool First = true;
239
for (unsigned i = 0; i < std::size(TagNames); i++) {
240
if (Imm & (1 << i)) {
241
O << (First ? "" : " | ") << TagNames[i];
242
First = false;
243
}
244
}
245
}
246
247
void SparcInstPrinter::printASITag(const MCInst *MI, int opNum,
248
const MCSubtargetInfo &STI, raw_ostream &O) {
249
unsigned Imm = MI->getOperand(opNum).getImm();
250
auto ASITag = SparcASITag::lookupASITagByEncoding(Imm);
251
if (isV9(STI) && ASITag)
252
O << '#' << ASITag->Name;
253
else
254
O << Imm;
255
}
256
257
void SparcInstPrinter::printPrefetchTag(const MCInst *MI, int opNum,
258
const MCSubtargetInfo &STI,
259
raw_ostream &O) {
260
unsigned Imm = MI->getOperand(opNum).getImm();
261
auto PrefetchTag = SparcPrefetchTag::lookupPrefetchTagByEncoding(Imm);
262
if (PrefetchTag)
263
O << '#' << PrefetchTag->Name;
264
else
265
O << Imm;
266
}
267
268