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