1 //===-- SparcInstPrinter.cpp - Convert Sparc MCInst to assembly syntax -----==//
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
7 //===----------------------------------------------------------------------===//
9 // This class prints an Sparc MCInst to a .s file.
11 //===----------------------------------------------------------------------===//
13 #include "SparcInstPrinter.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"
23 #define DEBUG_TYPE "asm-printer"
25 // The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target
26 // namespace. But SPARC backend uses "SP" as its namespace.
33 #define GET_INSTRUCTION_NAME
34 #define PRINT_ALIAS_INSTR
35 #include "SparcGenAsmWriter.inc"
37 bool SparcInstPrinter::isV9(const MCSubtargetInfo
&STI
) const {
38 return (STI
.getFeatureBits()[Sparc::FeatureV9
]) != 0;
41 void SparcInstPrinter::printRegName(raw_ostream
&OS
, unsigned RegNo
) const
43 OS
<< '%' << StringRef(getRegisterName(RegNo
)).lower();
46 void SparcInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&O
,
47 StringRef Annot
, const MCSubtargetInfo
&STI
) {
48 if (!printAliasInstr(MI
, STI
, O
) && !printSparcAliasInstr(MI
, STI
, O
))
49 printInstruction(MI
, STI
, O
);
50 printAnnotation(O
, Annot
);
53 bool SparcInstPrinter::printSparcAliasInstr(const MCInst
*MI
,
54 const MCSubtargetInfo
&STI
,
56 switch (MI
->getOpcode()) {
57 default: return false;
60 if (MI
->getNumOperands() != 3)
62 if (!MI
->getOperand(0).isReg())
64 switch (MI
->getOperand(0).getReg()) {
65 default: return false;
66 case SP::G0
: // jmp $addr | ret | retl
67 if (MI
->getOperand(2).isImm() &&
68 MI
->getOperand(2).getImm() == 8) {
69 switch(MI
->getOperand(1).getReg()) {
71 case SP::I7
: O
<< "\tret"; return true;
72 case SP::O7
: O
<< "\tretl"; return true;
75 O
<< "\tjmp "; printMemOperand(MI
, 1, STI
, O
);
77 case SP::O7
: // call $addr
78 O
<< "\tcall "; printMemOperand(MI
, 1, STI
, O
);
82 case SP::V9FCMPS
: case SP::V9FCMPD
: case SP::V9FCMPQ
:
83 case SP::V9FCMPES
: case SP::V9FCMPED
: case SP::V9FCMPEQ
: {
85 || (MI
->getNumOperands() != 3)
86 || (!MI
->getOperand(0).isReg())
87 || (MI
->getOperand(0).getReg() != SP::FCC0
))
89 // if V8, skip printing %fcc0.
90 switch(MI
->getOpcode()) {
92 case SP::V9FCMPS
: O
<< "\tfcmps "; break;
93 case SP::V9FCMPD
: O
<< "\tfcmpd "; break;
94 case SP::V9FCMPQ
: O
<< "\tfcmpq "; break;
95 case SP::V9FCMPES
: O
<< "\tfcmpes "; break;
96 case SP::V9FCMPED
: O
<< "\tfcmped "; break;
97 case SP::V9FCMPEQ
: O
<< "\tfcmpeq "; break;
99 printOperand(MI
, 1, STI
, O
);
101 printOperand(MI
, 2, STI
, O
);
107 void SparcInstPrinter::printOperand(const MCInst
*MI
, int opNum
,
108 const MCSubtargetInfo
&STI
,
110 const MCOperand
&MO
= MI
->getOperand (opNum
);
113 printRegName(O
, MO
.getReg());
118 switch (MI
->getOpcode()) {
120 O
<< (int)MO
.getImm();
123 case SP::TICCri
: // Fall through
124 case SP::TICCrr
: // Fall through
125 case SP::TRAPri
: // Fall through
126 case SP::TRAPrr
: // Fall through
127 case SP::TXCCri
: // Fall through
128 case SP::TXCCrr
: // Fall through
129 // Only seven-bit values up to 127.
130 O
<< ((int) MO
.getImm() & 0x7f);
135 assert(MO
.isExpr() && "Unknown operand kind in printOperand");
136 MO
.getExpr()->print(O
, &MAI
);
139 void SparcInstPrinter::printMemOperand(const MCInst
*MI
, int opNum
,
140 const MCSubtargetInfo
&STI
,
141 raw_ostream
&O
, const char *Modifier
) {
142 printOperand(MI
, opNum
, STI
, O
);
144 // If this is an ADD operand, emit it like normal operands.
145 if (Modifier
&& !strcmp(Modifier
, "arith")) {
147 printOperand(MI
, opNum
+1, STI
, O
);
150 const MCOperand
&MO
= MI
->getOperand(opNum
+1);
152 if (MO
.isReg() && MO
.getReg() == SP::G0
)
153 return; // don't print "+%g0"
154 if (MO
.isImm() && MO
.getImm() == 0)
155 return; // don't print "+0"
159 printOperand(MI
, opNum
+1, STI
, O
);
162 void SparcInstPrinter::printCCOperand(const MCInst
*MI
, int opNum
,
163 const MCSubtargetInfo
&STI
,
165 int CC
= (int)MI
->getOperand(opNum
).getImm();
166 switch (MI
->getOpcode()) {
174 case SP::MOVFCCrr
: case SP::V9MOVFCCrr
:
175 case SP::MOVFCCri
: case SP::V9MOVFCCri
:
176 case SP::FMOVS_FCC
: case SP::V9FMOVS_FCC
:
177 case SP::FMOVD_FCC
: case SP::V9FMOVD_FCC
:
178 case SP::FMOVQ_FCC
: case SP::V9FMOVQ_FCC
:
179 // Make sure CC is a fp conditional flag.
180 CC
= (CC
< 16) ? (CC
+ 16) : CC
;
184 // Make sure CC is a cp conditional flag.
185 CC
= (CC
< 32) ? (CC
+ 32) : CC
;
188 O
<< SPARCCondCodeToString((SPCC::CondCodes
)CC
);
191 bool SparcInstPrinter::printGetPCX(const MCInst
*MI
, unsigned opNum
,
192 const MCSubtargetInfo
&STI
,
194 llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX.");
198 void SparcInstPrinter::printMembarTag(const MCInst
*MI
, int opNum
,
199 const MCSubtargetInfo
&STI
,
201 static const char *const TagNames
[] = {
202 "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore",
203 "#Lookaside", "#MemIssue", "#Sync"};
205 unsigned Imm
= MI
->getOperand(opNum
).getImm();
213 for (unsigned i
= 0; i
< sizeof(TagNames
) / sizeof(char *); i
++) {
214 if (Imm
& (1 << i
)) {
215 O
<< (First
? "" : " | ") << TagNames
[i
];