1*9880d681SAndroid Build Coastguard Worker //===-- SparcInstPrinter.cpp - Convert Sparc MCInst to assembly syntax -----==//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This class prints an Sparc MCInst to a .s file.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "SparcInstPrinter.h"
15*9880d681SAndroid Build Coastguard Worker #include "Sparc.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
22*9880d681SAndroid Build Coastguard Worker using namespace llvm;
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "asm-printer"
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker // The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target
27*9880d681SAndroid Build Coastguard Worker // namespace. But SPARC backend uses "SP" as its namespace.
28*9880d681SAndroid Build Coastguard Worker namespace llvm {
29*9880d681SAndroid Build Coastguard Worker namespace Sparc {
30*9880d681SAndroid Build Coastguard Worker using namespace SP;
31*9880d681SAndroid Build Coastguard Worker }
32*9880d681SAndroid Build Coastguard Worker }
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker #define GET_INSTRUCTION_NAME
35*9880d681SAndroid Build Coastguard Worker #define PRINT_ALIAS_INSTR
36*9880d681SAndroid Build Coastguard Worker #include "SparcGenAsmWriter.inc"
37*9880d681SAndroid Build Coastguard Worker
isV9(const MCSubtargetInfo & STI) const38*9880d681SAndroid Build Coastguard Worker bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const {
39*9880d681SAndroid Build Coastguard Worker return (STI.getFeatureBits()[Sparc::FeatureV9]) != 0;
40*9880d681SAndroid Build Coastguard Worker }
41*9880d681SAndroid Build Coastguard Worker
printRegName(raw_ostream & OS,unsigned RegNo) const42*9880d681SAndroid Build Coastguard Worker void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
43*9880d681SAndroid Build Coastguard Worker {
44*9880d681SAndroid Build Coastguard Worker OS << '%' << StringRef(getRegisterName(RegNo)).lower();
45*9880d681SAndroid Build Coastguard Worker }
46*9880d681SAndroid Build Coastguard Worker
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot,const MCSubtargetInfo & STI)47*9880d681SAndroid Build Coastguard Worker void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
48*9880d681SAndroid Build Coastguard Worker StringRef Annot, const MCSubtargetInfo &STI) {
49*9880d681SAndroid Build Coastguard Worker if (!printAliasInstr(MI, STI, O) && !printSparcAliasInstr(MI, STI, O))
50*9880d681SAndroid Build Coastguard Worker printInstruction(MI, STI, O);
51*9880d681SAndroid Build Coastguard Worker printAnnotation(O, Annot);
52*9880d681SAndroid Build Coastguard Worker }
53*9880d681SAndroid Build Coastguard Worker
printSparcAliasInstr(const MCInst * MI,const MCSubtargetInfo & STI,raw_ostream & O)54*9880d681SAndroid Build Coastguard Worker bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI,
55*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI,
56*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
57*9880d681SAndroid Build Coastguard Worker switch (MI->getOpcode()) {
58*9880d681SAndroid Build Coastguard Worker default: return false;
59*9880d681SAndroid Build Coastguard Worker case SP::JMPLrr:
60*9880d681SAndroid Build Coastguard Worker case SP::JMPLri: {
61*9880d681SAndroid Build Coastguard Worker if (MI->getNumOperands() != 3)
62*9880d681SAndroid Build Coastguard Worker return false;
63*9880d681SAndroid Build Coastguard Worker if (!MI->getOperand(0).isReg())
64*9880d681SAndroid Build Coastguard Worker return false;
65*9880d681SAndroid Build Coastguard Worker switch (MI->getOperand(0).getReg()) {
66*9880d681SAndroid Build Coastguard Worker default: return false;
67*9880d681SAndroid Build Coastguard Worker case SP::G0: // jmp $addr | ret | retl
68*9880d681SAndroid Build Coastguard Worker if (MI->getOperand(2).isImm() &&
69*9880d681SAndroid Build Coastguard Worker MI->getOperand(2).getImm() == 8) {
70*9880d681SAndroid Build Coastguard Worker switch(MI->getOperand(1).getReg()) {
71*9880d681SAndroid Build Coastguard Worker default: break;
72*9880d681SAndroid Build Coastguard Worker case SP::I7: O << "\tret"; return true;
73*9880d681SAndroid Build Coastguard Worker case SP::O7: O << "\tretl"; return true;
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker }
76*9880d681SAndroid Build Coastguard Worker O << "\tjmp "; printMemOperand(MI, 1, STI, O);
77*9880d681SAndroid Build Coastguard Worker return true;
78*9880d681SAndroid Build Coastguard Worker case SP::O7: // call $addr
79*9880d681SAndroid Build Coastguard Worker O << "\tcall "; printMemOperand(MI, 1, STI, O);
80*9880d681SAndroid Build Coastguard Worker return true;
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker }
83*9880d681SAndroid Build Coastguard Worker case SP::V9FCMPS: case SP::V9FCMPD: case SP::V9FCMPQ:
84*9880d681SAndroid Build Coastguard Worker case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: {
85*9880d681SAndroid Build Coastguard Worker if (isV9(STI)
86*9880d681SAndroid Build Coastguard Worker || (MI->getNumOperands() != 3)
87*9880d681SAndroid Build Coastguard Worker || (!MI->getOperand(0).isReg())
88*9880d681SAndroid Build Coastguard Worker || (MI->getOperand(0).getReg() != SP::FCC0))
89*9880d681SAndroid Build Coastguard Worker return false;
90*9880d681SAndroid Build Coastguard Worker // if V8, skip printing %fcc0.
91*9880d681SAndroid Build Coastguard Worker switch(MI->getOpcode()) {
92*9880d681SAndroid Build Coastguard Worker default:
93*9880d681SAndroid Build Coastguard Worker case SP::V9FCMPS: O << "\tfcmps "; break;
94*9880d681SAndroid Build Coastguard Worker case SP::V9FCMPD: O << "\tfcmpd "; break;
95*9880d681SAndroid Build Coastguard Worker case SP::V9FCMPQ: O << "\tfcmpq "; break;
96*9880d681SAndroid Build Coastguard Worker case SP::V9FCMPES: O << "\tfcmpes "; break;
97*9880d681SAndroid Build Coastguard Worker case SP::V9FCMPED: O << "\tfcmped "; break;
98*9880d681SAndroid Build Coastguard Worker case SP::V9FCMPEQ: O << "\tfcmpeq "; break;
99*9880d681SAndroid Build Coastguard Worker }
100*9880d681SAndroid Build Coastguard Worker printOperand(MI, 1, STI, O);
101*9880d681SAndroid Build Coastguard Worker O << ", ";
102*9880d681SAndroid Build Coastguard Worker printOperand(MI, 2, STI, O);
103*9880d681SAndroid Build Coastguard Worker return true;
104*9880d681SAndroid Build Coastguard Worker }
105*9880d681SAndroid Build Coastguard Worker }
106*9880d681SAndroid Build Coastguard Worker }
107*9880d681SAndroid Build Coastguard Worker
printOperand(const MCInst * MI,int opNum,const MCSubtargetInfo & STI,raw_ostream & O)108*9880d681SAndroid Build Coastguard Worker void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,
109*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI,
110*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
111*9880d681SAndroid Build Coastguard Worker const MCOperand &MO = MI->getOperand (opNum);
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker if (MO.isReg()) {
114*9880d681SAndroid Build Coastguard Worker printRegName(O, MO.getReg());
115*9880d681SAndroid Build Coastguard Worker return ;
116*9880d681SAndroid Build Coastguard Worker }
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker if (MO.isImm()) {
119*9880d681SAndroid Build Coastguard Worker switch (MI->getOpcode()) {
120*9880d681SAndroid Build Coastguard Worker default:
121*9880d681SAndroid Build Coastguard Worker O << (int)MO.getImm();
122*9880d681SAndroid Build Coastguard Worker return;
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker case SP::TICCri: // Fall through
125*9880d681SAndroid Build Coastguard Worker case SP::TICCrr: // Fall through
126*9880d681SAndroid Build Coastguard Worker case SP::TRAPri: // Fall through
127*9880d681SAndroid Build Coastguard Worker case SP::TRAPrr: // Fall through
128*9880d681SAndroid Build Coastguard Worker case SP::TXCCri: // Fall through
129*9880d681SAndroid Build Coastguard Worker case SP::TXCCrr: // Fall through
130*9880d681SAndroid Build Coastguard Worker // Only seven-bit values up to 127.
131*9880d681SAndroid Build Coastguard Worker O << ((int) MO.getImm() & 0x7f);
132*9880d681SAndroid Build Coastguard Worker return;
133*9880d681SAndroid Build Coastguard Worker }
134*9880d681SAndroid Build Coastguard Worker }
135*9880d681SAndroid Build Coastguard Worker
136*9880d681SAndroid Build Coastguard Worker assert(MO.isExpr() && "Unknown operand kind in printOperand");
137*9880d681SAndroid Build Coastguard Worker MO.getExpr()->print(O, &MAI);
138*9880d681SAndroid Build Coastguard Worker }
139*9880d681SAndroid Build Coastguard Worker
printMemOperand(const MCInst * MI,int opNum,const MCSubtargetInfo & STI,raw_ostream & O,const char * Modifier)140*9880d681SAndroid Build Coastguard Worker void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum,
141*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI,
142*9880d681SAndroid Build Coastguard Worker raw_ostream &O, const char *Modifier) {
143*9880d681SAndroid Build Coastguard Worker printOperand(MI, opNum, STI, O);
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Worker // If this is an ADD operand, emit it like normal operands.
146*9880d681SAndroid Build Coastguard Worker if (Modifier && !strcmp(Modifier, "arith")) {
147*9880d681SAndroid Build Coastguard Worker O << ", ";
148*9880d681SAndroid Build Coastguard Worker printOperand(MI, opNum+1, STI, O);
149*9880d681SAndroid Build Coastguard Worker return;
150*9880d681SAndroid Build Coastguard Worker }
151*9880d681SAndroid Build Coastguard Worker const MCOperand &MO = MI->getOperand(opNum+1);
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.getReg() == SP::G0)
154*9880d681SAndroid Build Coastguard Worker return; // don't print "+%g0"
155*9880d681SAndroid Build Coastguard Worker if (MO.isImm() && MO.getImm() == 0)
156*9880d681SAndroid Build Coastguard Worker return; // don't print "+0"
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker O << "+";
159*9880d681SAndroid Build Coastguard Worker
160*9880d681SAndroid Build Coastguard Worker printOperand(MI, opNum+1, STI, O);
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker
printCCOperand(const MCInst * MI,int opNum,const MCSubtargetInfo & STI,raw_ostream & O)163*9880d681SAndroid Build Coastguard Worker void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,
164*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI,
165*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
166*9880d681SAndroid Build Coastguard Worker int CC = (int)MI->getOperand(opNum).getImm();
167*9880d681SAndroid Build Coastguard Worker switch (MI->getOpcode()) {
168*9880d681SAndroid Build Coastguard Worker default: break;
169*9880d681SAndroid Build Coastguard Worker case SP::FBCOND:
170*9880d681SAndroid Build Coastguard Worker case SP::FBCONDA:
171*9880d681SAndroid Build Coastguard Worker case SP::BPFCC:
172*9880d681SAndroid Build Coastguard Worker case SP::BPFCCA:
173*9880d681SAndroid Build Coastguard Worker case SP::BPFCCNT:
174*9880d681SAndroid Build Coastguard Worker case SP::BPFCCANT:
175*9880d681SAndroid Build Coastguard Worker case SP::MOVFCCrr: case SP::V9MOVFCCrr:
176*9880d681SAndroid Build Coastguard Worker case SP::MOVFCCri: case SP::V9MOVFCCri:
177*9880d681SAndroid Build Coastguard Worker case SP::FMOVS_FCC: case SP::V9FMOVS_FCC:
178*9880d681SAndroid Build Coastguard Worker case SP::FMOVD_FCC: case SP::V9FMOVD_FCC:
179*9880d681SAndroid Build Coastguard Worker case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC:
180*9880d681SAndroid Build Coastguard Worker // Make sure CC is a fp conditional flag.
181*9880d681SAndroid Build Coastguard Worker CC = (CC < 16) ? (CC + 16) : CC;
182*9880d681SAndroid Build Coastguard Worker break;
183*9880d681SAndroid Build Coastguard Worker case SP::CBCOND:
184*9880d681SAndroid Build Coastguard Worker case SP::CBCONDA:
185*9880d681SAndroid Build Coastguard Worker // Make sure CC is a cp conditional flag.
186*9880d681SAndroid Build Coastguard Worker CC = (CC < 32) ? (CC + 32) : CC;
187*9880d681SAndroid Build Coastguard Worker break;
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker O << SPARCCondCodeToString((SPCC::CondCodes)CC);
190*9880d681SAndroid Build Coastguard Worker }
191*9880d681SAndroid Build Coastguard Worker
printGetPCX(const MCInst * MI,unsigned opNum,const MCSubtargetInfo & STI,raw_ostream & O)192*9880d681SAndroid Build Coastguard Worker bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum,
193*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI,
194*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
195*9880d681SAndroid Build Coastguard Worker llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX.");
196*9880d681SAndroid Build Coastguard Worker return true;
197*9880d681SAndroid Build Coastguard Worker }
198