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