227fd387f2c8db63e5ef95d8edc36ce9fd53d401
[oota-llvm.git] / lib / Target / Mips / InstPrinter / MipsInstPrinter.cpp
1 //===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===//
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 class prints an Mips MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "asm-printer"
15 #include "MipsInstPrinter.h"
16 #include "MipsInstrInfo.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCSymbol.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/raw_ostream.h"
24 using namespace llvm;
25
26 #include "MipsGenAsmWriter.inc"
27
28 const char* Mips::MipsFCCToString(Mips::CondCode CC) {
29   switch (CC) {
30   case FCOND_F:
31   case FCOND_T:   return "f";
32   case FCOND_UN:
33   case FCOND_OR:  return "un";
34   case FCOND_OEQ:
35   case FCOND_UNE: return "eq";
36   case FCOND_UEQ:
37   case FCOND_ONE: return "ueq";
38   case FCOND_OLT:
39   case FCOND_UGE: return "olt";
40   case FCOND_ULT:
41   case FCOND_OGE: return "ult";
42   case FCOND_OLE:
43   case FCOND_UGT: return "ole";
44   case FCOND_ULE:
45   case FCOND_OGT: return "ule";
46   case FCOND_SF:
47   case FCOND_ST:  return "sf";
48   case FCOND_NGLE:
49   case FCOND_GLE: return "ngle";
50   case FCOND_SEQ:
51   case FCOND_SNE: return "seq";
52   case FCOND_NGL:
53   case FCOND_GL:  return "ngl";
54   case FCOND_LT:
55   case FCOND_NLT: return "lt";
56   case FCOND_NGE:
57   case FCOND_GE:  return "nge";
58   case FCOND_LE:
59   case FCOND_NLE: return "le";
60   case FCOND_NGT:
61   case FCOND_GT:  return "ngt";
62   }
63   llvm_unreachable("Impossible condition code!");
64 }
65
66 void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
67   OS << '$' << StringRef(getRegisterName(RegNo)).lower();
68 }
69
70 void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
71                                 StringRef Annot) {
72   switch (MI->getOpcode()) {
73   default:
74     break;
75   case Mips::RDHWR:
76   case Mips::RDHWR64:
77     O << "\t.set\tpush\n";
78     O << "\t.set\tmips32r2\n";
79   }
80
81   printInstruction(MI, O);
82   printAnnotation(O, Annot);
83
84   switch (MI->getOpcode()) {
85   default:
86     break;
87   case Mips::RDHWR:
88   case Mips::RDHWR64:
89     O << "\n\t.set\tpop";
90   }
91 }
92
93 static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
94   int Offset = 0;
95   const MCSymbolRefExpr *SRE;
96
97   if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
98     SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
99     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
100     assert(SRE && CE && "Binary expression must be sym+const.");
101     Offset = CE->getValue();
102   }
103   else if (!(SRE = dyn_cast<MCSymbolRefExpr>(Expr)))
104     assert(false && "Unexpected MCExpr type.");
105
106   MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
107
108   switch (Kind) {
109   default:                                 llvm_unreachable("Invalid kind!");
110   case MCSymbolRefExpr::VK_None:           break;
111   case MCSymbolRefExpr::VK_Mips_GPREL:     OS << "%gp_rel("; break;
112   case MCSymbolRefExpr::VK_Mips_GOT_CALL:  OS << "%call16("; break;
113   case MCSymbolRefExpr::VK_Mips_GOT16:     OS << "%got(";    break;
114   case MCSymbolRefExpr::VK_Mips_GOT:       OS << "%got(";    break;
115   case MCSymbolRefExpr::VK_Mips_ABS_HI:    OS << "%hi(";     break;
116   case MCSymbolRefExpr::VK_Mips_ABS_LO:    OS << "%lo(";     break;
117   case MCSymbolRefExpr::VK_Mips_TLSGD:     OS << "%tlsgd(";  break;
118   case MCSymbolRefExpr::VK_Mips_TLSLDM:    OS << "%tlsldm(";  break;
119   case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi(";  break;
120   case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo(";  break;
121   case MCSymbolRefExpr::VK_Mips_GOTTPREL:  OS << "%gottprel("; break;
122   case MCSymbolRefExpr::VK_Mips_TPREL_HI:  OS << "%tprel_hi("; break;
123   case MCSymbolRefExpr::VK_Mips_TPREL_LO:  OS << "%tprel_lo("; break;
124   case MCSymbolRefExpr::VK_Mips_GPOFF_HI:  OS << "%hi(%neg(%gp_rel("; break;
125   case MCSymbolRefExpr::VK_Mips_GPOFF_LO:  OS << "%lo(%neg(%gp_rel("; break;
126   case MCSymbolRefExpr::VK_Mips_GOT_DISP:  OS << "%got_disp("; break;
127   case MCSymbolRefExpr::VK_Mips_GOT_PAGE:  OS << "%got_page("; break;
128   case MCSymbolRefExpr::VK_Mips_GOT_OFST:  OS << "%got_ofst("; break;
129   }
130
131   OS << SRE->getSymbol();
132
133   if (Offset) {
134     if (Offset > 0)
135       OS << '+';
136     OS << Offset;
137   }
138
139   if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) ||
140       (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO))
141     OS << ")))";
142   else if (Kind != MCSymbolRefExpr::VK_None)
143     OS << ')';
144 }
145
146 void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
147                                    raw_ostream &O) {
148   const MCOperand &Op = MI->getOperand(OpNo);
149   if (Op.isReg()) {
150     printRegName(O, Op.getReg());
151     return;
152   }
153
154   if (Op.isImm()) {
155     O << Op.getImm();
156     return;
157   }
158
159   assert(Op.isExpr() && "unknown operand kind in printOperand");
160   printExpr(Op.getExpr(), O);
161 }
162
163 void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum,
164                                        raw_ostream &O) {
165   const MCOperand &MO = MI->getOperand(opNum);
166   if (MO.isImm())
167     O << (unsigned short int)MO.getImm();
168   else
169     printOperand(MI, opNum, O);
170 }
171
172 void MipsInstPrinter::
173 printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {
174   // Load/Store memory operands -- imm($reg)
175   // If PIC target the target is loaded as the
176   // pattern lw $25,%call16($28)
177   printOperand(MI, opNum+1, O);
178   O << "(";
179   printOperand(MI, opNum, O);
180   O << ")";
181 }
182
183 void MipsInstPrinter::
184 printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) {
185   // when using stack locations for not load/store instructions
186   // print the same way as all normal 3 operand instructions.
187   printOperand(MI, opNum, O);
188   O << ", ";
189   printOperand(MI, opNum+1, O);
190   return;
191 }
192
193 void MipsInstPrinter::
194 printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) {
195   const MCOperand& MO = MI->getOperand(opNum);
196   O << MipsFCCToString((Mips::CondCode)MO.getImm());
197 }