~pali/+junk/llvm-toolchain-3.7

« back to all changes in this revision

Viewing changes to lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2015-07-15 17:51:08 UTC
  • Revision ID: package-import@ubuntu.com-20150715175108-l8mynwovkx4zx697
Tags: upstream-3.7~+rc2
ImportĀ upstreamĀ versionĀ 3.7~+rc2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include "MipsInstPrinter.h"
 
15
#include "MCTargetDesc/MipsMCExpr.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 DEBUG_TYPE "asm-printer"
 
27
 
 
28
#define PRINT_ALIAS_INSTR
 
29
#include "MipsGenAsmWriter.inc"
 
30
 
 
31
template<unsigned R>
 
32
static bool isReg(const MCInst &MI, unsigned OpNo) {
 
33
  assert(MI.getOperand(OpNo).isReg() && "Register operand expected.");
 
34
  return MI.getOperand(OpNo).getReg() == R;
 
35
}
 
36
 
 
37
const char* Mips::MipsFCCToString(Mips::CondCode CC) {
 
38
  switch (CC) {
 
39
  case FCOND_F:
 
40
  case FCOND_T:   return "f";
 
41
  case FCOND_UN:
 
42
  case FCOND_OR:  return "un";
 
43
  case FCOND_OEQ:
 
44
  case FCOND_UNE: return "eq";
 
45
  case FCOND_UEQ:
 
46
  case FCOND_ONE: return "ueq";
 
47
  case FCOND_OLT:
 
48
  case FCOND_UGE: return "olt";
 
49
  case FCOND_ULT:
 
50
  case FCOND_OGE: return "ult";
 
51
  case FCOND_OLE:
 
52
  case FCOND_UGT: return "ole";
 
53
  case FCOND_ULE:
 
54
  case FCOND_OGT: return "ule";
 
55
  case FCOND_SF:
 
56
  case FCOND_ST:  return "sf";
 
57
  case FCOND_NGLE:
 
58
  case FCOND_GLE: return "ngle";
 
59
  case FCOND_SEQ:
 
60
  case FCOND_SNE: return "seq";
 
61
  case FCOND_NGL:
 
62
  case FCOND_GL:  return "ngl";
 
63
  case FCOND_LT:
 
64
  case FCOND_NLT: return "lt";
 
65
  case FCOND_NGE:
 
66
  case FCOND_GE:  return "nge";
 
67
  case FCOND_LE:
 
68
  case FCOND_NLE: return "le";
 
69
  case FCOND_NGT:
 
70
  case FCOND_GT:  return "ngt";
 
71
  }
 
72
  llvm_unreachable("Impossible condition code!");
 
73
}
 
74
 
 
75
void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
 
76
  OS << '$' << StringRef(getRegisterName(RegNo)).lower();
 
77
}
 
78
 
 
79
void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
 
80
                                StringRef Annot, const MCSubtargetInfo &STI) {
 
81
  switch (MI->getOpcode()) {
 
82
  default:
 
83
    break;
 
84
  case Mips::RDHWR:
 
85
  case Mips::RDHWR64:
 
86
    O << "\t.set\tpush\n";
 
87
    O << "\t.set\tmips32r2\n";
 
88
    break;
 
89
  case Mips::Save16:
 
90
    O << "\tsave\t";
 
91
    printSaveRestore(MI, O);
 
92
    O << " # 16 bit inst\n";
 
93
    return;
 
94
  case Mips::SaveX16:
 
95
    O << "\tsave\t";
 
96
    printSaveRestore(MI, O);
 
97
    O << "\n";
 
98
    return;
 
99
  case Mips::Restore16:
 
100
    O << "\trestore\t";
 
101
    printSaveRestore(MI, O);
 
102
    O << " # 16 bit inst\n";
 
103
    return;
 
104
  case Mips::RestoreX16:
 
105
    O << "\trestore\t";
 
106
    printSaveRestore(MI, O);
 
107
    O << "\n";
 
108
    return;
 
109
  }
 
110
 
 
111
  // Try to print any aliases first.
 
112
  if (!printAliasInstr(MI, O) && !printAlias(*MI, O))
 
113
    printInstruction(MI, O);
 
114
  printAnnotation(O, Annot);
 
115
 
 
116
  switch (MI->getOpcode()) {
 
117
  default:
 
118
    break;
 
119
  case Mips::RDHWR:
 
120
  case Mips::RDHWR64:
 
121
    O << "\n\t.set\tpop";
 
122
  }
 
123
}
 
124
 
 
125
static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,
 
126
                      raw_ostream &OS) {
 
127
  int Offset = 0;
 
128
  const MCSymbolRefExpr *SRE;
 
129
 
 
130
  if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
 
131
    SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
 
132
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
 
133
    assert(SRE && CE && "Binary expression must be sym+const.");
 
134
    Offset = CE->getValue();
 
135
  } else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) {
 
136
    ME->print(OS, MAI);
 
137
    return;
 
138
  } else
 
139
    SRE = cast<MCSymbolRefExpr>(Expr);
 
140
 
 
141
  MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
 
142
 
 
143
  switch (Kind) {
 
144
  default:                                 llvm_unreachable("Invalid kind!");
 
145
  case MCSymbolRefExpr::VK_None:           break;
 
146
  case MCSymbolRefExpr::VK_Mips_GPREL:     OS << "%gp_rel("; break;
 
147
  case MCSymbolRefExpr::VK_Mips_GOT_CALL:  OS << "%call16("; break;
 
148
  case MCSymbolRefExpr::VK_Mips_GOT16:     OS << "%got(";    break;
 
149
  case MCSymbolRefExpr::VK_Mips_GOT:       OS << "%got(";    break;
 
150
  case MCSymbolRefExpr::VK_Mips_ABS_HI:    OS << "%hi(";     break;
 
151
  case MCSymbolRefExpr::VK_Mips_ABS_LO:    OS << "%lo(";     break;
 
152
  case MCSymbolRefExpr::VK_Mips_TLSGD:     OS << "%tlsgd(";  break;
 
153
  case MCSymbolRefExpr::VK_Mips_TLSLDM:    OS << "%tlsldm(";  break;
 
154
  case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi(";  break;
 
155
  case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo(";  break;
 
156
  case MCSymbolRefExpr::VK_Mips_GOTTPREL:  OS << "%gottprel("; break;
 
157
  case MCSymbolRefExpr::VK_Mips_TPREL_HI:  OS << "%tprel_hi("; break;
 
158
  case MCSymbolRefExpr::VK_Mips_TPREL_LO:  OS << "%tprel_lo("; break;
 
159
  case MCSymbolRefExpr::VK_Mips_GPOFF_HI:  OS << "%hi(%neg(%gp_rel("; break;
 
160
  case MCSymbolRefExpr::VK_Mips_GPOFF_LO:  OS << "%lo(%neg(%gp_rel("; break;
 
161
  case MCSymbolRefExpr::VK_Mips_GOT_DISP:  OS << "%got_disp("; break;
 
162
  case MCSymbolRefExpr::VK_Mips_GOT_PAGE:  OS << "%got_page("; break;
 
163
  case MCSymbolRefExpr::VK_Mips_GOT_OFST:  OS << "%got_ofst("; break;
 
164
  case MCSymbolRefExpr::VK_Mips_HIGHER:    OS << "%higher("; break;
 
165
  case MCSymbolRefExpr::VK_Mips_HIGHEST:   OS << "%highest("; break;
 
166
  case MCSymbolRefExpr::VK_Mips_GOT_HI16:  OS << "%got_hi("; break;
 
167
  case MCSymbolRefExpr::VK_Mips_GOT_LO16:  OS << "%got_lo("; break;
 
168
  case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break;
 
169
  case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break;
 
170
  case MCSymbolRefExpr::VK_Mips_PCREL_HI16: OS << "%pcrel_hi("; break;
 
171
  case MCSymbolRefExpr::VK_Mips_PCREL_LO16: OS << "%pcrel_lo("; break;
 
172
  }
 
173
 
 
174
  SRE->getSymbol().print(OS, MAI);
 
175
 
 
176
  if (Offset) {
 
177
    if (Offset > 0)
 
178
      OS << '+';
 
179
    OS << Offset;
 
180
  }
 
181
 
 
182
  if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) ||
 
183
      (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO))
 
184
    OS << ")))";
 
185
  else if (Kind != MCSymbolRefExpr::VK_None)
 
186
    OS << ')';
 
187
}
 
188
 
 
189
void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
 
190
                                   raw_ostream &O) {
 
191
  const MCOperand &Op = MI->getOperand(OpNo);
 
192
  if (Op.isReg()) {
 
193
    printRegName(O, Op.getReg());
 
194
    return;
 
195
  }
 
196
 
 
197
  if (Op.isImm()) {
 
198
    O << Op.getImm();
 
199
    return;
 
200
  }
 
201
 
 
202
  assert(Op.isExpr() && "unknown operand kind in printOperand");
 
203
  printExpr(Op.getExpr(), &MAI, O);
 
204
}
 
205
 
 
206
void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum,
 
207
                                       raw_ostream &O) {
 
208
  const MCOperand &MO = MI->getOperand(opNum);
 
209
  if (MO.isImm())
 
210
    O << (unsigned short int)MO.getImm();
 
211
  else
 
212
    printOperand(MI, opNum, O);
 
213
}
 
214
 
 
215
void MipsInstPrinter::printUnsignedImm8(const MCInst *MI, int opNum,
 
216
                                        raw_ostream &O) {
 
217
  const MCOperand &MO = MI->getOperand(opNum);
 
218
  if (MO.isImm())
 
219
    O << (unsigned short int)(unsigned char)MO.getImm();
 
220
  else
 
221
    printOperand(MI, opNum, O);
 
222
}
 
223
 
 
224
void MipsInstPrinter::
 
225
printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {
 
226
  // Load/Store memory operands -- imm($reg)
 
227
  // If PIC target the target is loaded as the
 
228
  // pattern lw $25,%call16($28)
 
229
 
 
230
  // opNum can be invalid if instruction had reglist as operand.
 
231
  // MemOperand is always last operand of instruction (base + offset).
 
232
  switch (MI->getOpcode()) {
 
233
  default:
 
234
    break;
 
235
  case Mips::SWM32_MM:
 
236
  case Mips::LWM32_MM:
 
237
  case Mips::SWM16_MM:
 
238
  case Mips::LWM16_MM:
 
239
    opNum = MI->getNumOperands() - 2;
 
240
    break;
 
241
  }
 
242
 
 
243
  printOperand(MI, opNum+1, O);
 
244
  O << "(";
 
245
  printOperand(MI, opNum, O);
 
246
  O << ")";
 
247
}
 
248
 
 
249
void MipsInstPrinter::
 
250
printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) {
 
251
  // when using stack locations for not load/store instructions
 
252
  // print the same way as all normal 3 operand instructions.
 
253
  printOperand(MI, opNum, O);
 
254
  O << ", ";
 
255
  printOperand(MI, opNum+1, O);
 
256
  return;
 
257
}
 
258
 
 
259
void MipsInstPrinter::
 
260
printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) {
 
261
  const MCOperand& MO = MI->getOperand(opNum);
 
262
  O << MipsFCCToString((Mips::CondCode)MO.getImm());
 
263
}
 
264
 
 
265
void MipsInstPrinter::
 
266
printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O) {
 
267
  printRegName(O, MI->getOperand(opNum).getReg());
 
268
}
 
269
 
 
270
void MipsInstPrinter::
 
271
printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) {
 
272
  llvm_unreachable("TODO");
 
273
}
 
274
 
 
275
bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,
 
276
                                 unsigned OpNo, raw_ostream &OS) {
 
277
  OS << "\t" << Str << "\t";
 
278
  printOperand(&MI, OpNo, OS);
 
279
  return true;
 
280
}
 
281
 
 
282
bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,
 
283
                                 unsigned OpNo0, unsigned OpNo1,
 
284
                                 raw_ostream &OS) {
 
285
  printAlias(Str, MI, OpNo0, OS);
 
286
  OS << ", ";
 
287
  printOperand(&MI, OpNo1, OS);
 
288
  return true;
 
289
}
 
290
 
 
291
bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) {
 
292
  switch (MI.getOpcode()) {
 
293
  case Mips::BEQ:
 
294
  case Mips::BEQ_MM:
 
295
    // beq $zero, $zero, $L2 => b $L2
 
296
    // beq $r0, $zero, $L2 => beqz $r0, $L2
 
297
    return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) &&
 
298
            printAlias("b", MI, 2, OS)) ||
 
299
           (isReg<Mips::ZERO>(MI, 1) && printAlias("beqz", MI, 0, 2, OS));
 
300
  case Mips::BEQ64:
 
301
    // beq $r0, $zero, $L2 => beqz $r0, $L2
 
302
    return isReg<Mips::ZERO_64>(MI, 1) && printAlias("beqz", MI, 0, 2, OS);
 
303
  case Mips::BNE:
 
304
    // bne $r0, $zero, $L2 => bnez $r0, $L2
 
305
    return isReg<Mips::ZERO>(MI, 1) && printAlias("bnez", MI, 0, 2, OS);
 
306
  case Mips::BNE64:
 
307
    // bne $r0, $zero, $L2 => bnez $r0, $L2
 
308
    return isReg<Mips::ZERO_64>(MI, 1) && printAlias("bnez", MI, 0, 2, OS);
 
309
  case Mips::BGEZAL:
 
310
    // bgezal $zero, $L1 => bal $L1
 
311
    return isReg<Mips::ZERO>(MI, 0) && printAlias("bal", MI, 1, OS);
 
312
  case Mips::BC1T:
 
313
    // bc1t $fcc0, $L1 => bc1t $L1
 
314
    return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1t", MI, 1, OS);
 
315
  case Mips::BC1F:
 
316
    // bc1f $fcc0, $L1 => bc1f $L1
 
317
    return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1f", MI, 1, OS);
 
318
  case Mips::JALR:
 
319
    // jalr $ra, $r1 => jalr $r1
 
320
    return isReg<Mips::RA>(MI, 0) && printAlias("jalr", MI, 1, OS);
 
321
  case Mips::JALR64:
 
322
    // jalr $ra, $r1 => jalr $r1
 
323
    return isReg<Mips::RA_64>(MI, 0) && printAlias("jalr", MI, 1, OS);
 
324
  case Mips::NOR:
 
325
  case Mips::NOR_MM:
 
326
    // nor $r0, $r1, $zero => not $r0, $r1
 
327
    return isReg<Mips::ZERO>(MI, 2) && printAlias("not", MI, 0, 1, OS);
 
328
  case Mips::NOR64:
 
329
    // nor $r0, $r1, $zero => not $r0, $r1
 
330
    return isReg<Mips::ZERO_64>(MI, 2) && printAlias("not", MI, 0, 1, OS);
 
331
  case Mips::OR:
 
332
    // or $r0, $r1, $zero => move $r0, $r1
 
333
    return isReg<Mips::ZERO>(MI, 2) && printAlias("move", MI, 0, 1, OS);
 
334
  default: return false;
 
335
  }
 
336
}
 
337
 
 
338
void MipsInstPrinter::printSaveRestore(const MCInst *MI, raw_ostream &O) {
 
339
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
 
340
    if (i != 0) O << ", ";
 
341
    if (MI->getOperand(i).isReg())
 
342
      printRegName(O, MI->getOperand(i).getReg());
 
343
    else
 
344
      printUnsignedImm(MI, i, O);
 
345
  }
 
346
}
 
347
 
 
348
void MipsInstPrinter::
 
349
printRegisterList(const MCInst *MI, int opNum, raw_ostream &O) {
 
350
  // - 2 because register List is always first operand of instruction and it is
 
351
  // always followed by memory operand (base + offset).
 
352
  for (int i = opNum, e = MI->getNumOperands() - 2; i != e; ++i) {
 
353
    if (i != opNum)
 
354
      O << ", ";
 
355
    printRegName(O, MI->getOperand(i).getReg());
 
356
  }
 
357
}