OSDN Git Service

[mips] Generate big GOT code.
[android-x86/external-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   case MCSymbolRefExpr::VK_Mips_HIGHER:    OS << "%higher("; break;
130   case MCSymbolRefExpr::VK_Mips_HIGHEST:   OS << "%highest("; break;
131   case MCSymbolRefExpr::VK_Mips_GOT_HI16:  OS << "%got_hi("; break;
132   case MCSymbolRefExpr::VK_Mips_GOT_LO16:  OS << "%got_lo("; break;
133   case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break;
134   case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break;
135   }
136
137   OS << SRE->getSymbol();
138
139   if (Offset) {
140     if (Offset > 0)
141       OS << '+';
142     OS << Offset;
143   }
144
145   if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) ||
146       (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO))
147     OS << ")))";
148   else if (Kind != MCSymbolRefExpr::VK_None)
149     OS << ')';
150 }
151
152 void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
153                                    raw_ostream &O) {
154   const MCOperand &Op = MI->getOperand(OpNo);
155   if (Op.isReg()) {
156     printRegName(O, Op.getReg());
157     return;
158   }
159
160   if (Op.isImm()) {
161     O << Op.getImm();
162     return;
163   }
164
165   assert(Op.isExpr() && "unknown operand kind in printOperand");
166   printExpr(Op.getExpr(), O);
167 }
168
169 void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum,
170                                        raw_ostream &O) {
171   const MCOperand &MO = MI->getOperand(opNum);
172   if (MO.isImm())
173     O << (unsigned short int)MO.getImm();
174   else
175     printOperand(MI, opNum, O);
176 }
177
178 void MipsInstPrinter::
179 printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {
180   // Load/Store memory operands -- imm($reg)
181   // If PIC target the target is loaded as the
182   // pattern lw $25,%call16($28)
183   printOperand(MI, opNum+1, O);
184   O << "(";
185   printOperand(MI, opNum, O);
186   O << ")";
187 }
188
189 void MipsInstPrinter::
190 printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) {
191   // when using stack locations for not load/store instructions
192   // print the same way as all normal 3 operand instructions.
193   printOperand(MI, opNum, O);
194   O << ", ";
195   printOperand(MI, opNum+1, O);
196   return;
197 }
198
199 void MipsInstPrinter::
200 printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) {
201   const MCOperand& MO = MI->getOperand(opNum);
202   O << MipsFCCToString((Mips::CondCode)MO.getImm());
203 }