LLVM  9.0.0svn
MipsInstPrinter.cpp
Go to the documentation of this file.
1 //===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class prints an Mips MCInst to a .s file.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "MipsInstPrinter.h"
15 #include "MipsInstrInfo.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCInstrInfo.h"
20 #include "llvm/MC/MCSymbol.h"
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "asm-printer"
26 
27 #define PRINT_ALIAS_INSTR
28 #include "MipsGenAsmWriter.inc"
29 
30 template<unsigned R>
31 static bool isReg(const MCInst &MI, unsigned OpNo) {
32  assert(MI.getOperand(OpNo).isReg() && "Register operand expected.");
33  return MI.getOperand(OpNo).getReg() == R;
34 }
35 
37  switch (CC) {
38  case FCOND_F:
39  case FCOND_T: return "f";
40  case FCOND_UN:
41  case FCOND_OR: return "un";
42  case FCOND_OEQ:
43  case FCOND_UNE: return "eq";
44  case FCOND_UEQ:
45  case FCOND_ONE: return "ueq";
46  case FCOND_OLT:
47  case FCOND_UGE: return "olt";
48  case FCOND_ULT:
49  case FCOND_OGE: return "ult";
50  case FCOND_OLE:
51  case FCOND_UGT: return "ole";
52  case FCOND_ULE:
53  case FCOND_OGT: return "ule";
54  case FCOND_SF:
55  case FCOND_ST: return "sf";
56  case FCOND_NGLE:
57  case FCOND_GLE: return "ngle";
58  case FCOND_SEQ:
59  case FCOND_SNE: return "seq";
60  case FCOND_NGL:
61  case FCOND_GL: return "ngl";
62  case FCOND_LT:
63  case FCOND_NLT: return "lt";
64  case FCOND_NGE:
65  case FCOND_GE: return "nge";
66  case FCOND_LE:
67  case FCOND_NLE: return "le";
68  case FCOND_NGT:
69  case FCOND_GT: return "ngt";
70  }
71  llvm_unreachable("Impossible condition code!");
72 }
73 
74 void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
75  OS << '$' << StringRef(getRegisterName(RegNo)).lower();
76 }
77 
79  StringRef Annot, const MCSubtargetInfo &STI) {
80  switch (MI->getOpcode()) {
81  default:
82  break;
83  case Mips::RDHWR:
84  case Mips::RDHWR64:
85  O << "\t.set\tpush\n";
86  O << "\t.set\tmips32r2\n";
87  break;
88  case Mips::Save16:
89  O << "\tsave\t";
90  printSaveRestore(MI, O);
91  O << " # 16 bit inst\n";
92  return;
93  case Mips::SaveX16:
94  O << "\tsave\t";
95  printSaveRestore(MI, O);
96  O << "\n";
97  return;
98  case Mips::Restore16:
99  O << "\trestore\t";
100  printSaveRestore(MI, O);
101  O << " # 16 bit inst\n";
102  return;
103  case Mips::RestoreX16:
104  O << "\trestore\t";
105  printSaveRestore(MI, O);
106  O << "\n";
107  return;
108  }
109 
110  // Try to print any aliases first.
111  if (!printAliasInstr(MI, O) && !printAlias(*MI, O))
112  printInstruction(MI, O);
113  printAnnotation(O, Annot);
114 
115  switch (MI->getOpcode()) {
116  default:
117  break;
118  case Mips::RDHWR:
119  case Mips::RDHWR64:
120  O << "\n\t.set\tpop";
121  }
122 }
123 
124 void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
125  raw_ostream &O) {
126  const MCOperand &Op = MI->getOperand(OpNo);
127  if (Op.isReg()) {
128  printRegName(O, Op.getReg());
129  return;
130  }
131 
132  if (Op.isImm()) {
133  O << formatImm(Op.getImm());
134  return;
135  }
136 
137  assert(Op.isExpr() && "unknown operand kind in printOperand");
138  Op.getExpr()->print(O, &MAI, true);
139 }
140 
141 template <unsigned Bits, unsigned Offset>
142 void MipsInstPrinter::printUImm(const MCInst *MI, int opNum, raw_ostream &O) {
143  const MCOperand &MO = MI->getOperand(opNum);
144  if (MO.isImm()) {
145  uint64_t Imm = MO.getImm();
146  Imm -= Offset;
147  Imm &= (1 << Bits) - 1;
148  Imm += Offset;
149  O << formatImm(Imm);
150  return;
151  }
152 
153  printOperand(MI, opNum, O);
154 }
155 
156 void MipsInstPrinter::
157 printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {
158  // Load/Store memory operands -- imm($reg)
159  // If PIC target the target is loaded as the
160  // pattern lw $25,%call16($28)
161 
162  // opNum can be invalid if instruction had reglist as operand.
163  // MemOperand is always last operand of instruction (base + offset).
164  switch (MI->getOpcode()) {
165  default:
166  break;
167  case Mips::SWM32_MM:
168  case Mips::LWM32_MM:
169  case Mips::SWM16_MM:
170  case Mips::SWM16_MMR6:
171  case Mips::LWM16_MM:
172  case Mips::LWM16_MMR6:
173  opNum = MI->getNumOperands() - 2;
174  break;
175  }
176 
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 }
191 
192 void MipsInstPrinter::
193 printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) {
194  const MCOperand& MO = MI->getOperand(opNum);
196 }
197 
198 void MipsInstPrinter::
199 printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) {
200  llvm_unreachable("TODO");
201 }
202 
203 bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,
204  unsigned OpNo, raw_ostream &OS) {
205  OS << "\t" << Str << "\t";
206  printOperand(&MI, OpNo, OS);
207  return true;
208 }
209 
210 bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,
211  unsigned OpNo0, unsigned OpNo1,
212  raw_ostream &OS) {
213  printAlias(Str, MI, OpNo0, OS);
214  OS << ", ";
215  printOperand(&MI, OpNo1, OS);
216  return true;
217 }
218 
219 bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) {
220  switch (MI.getOpcode()) {
221  case Mips::BEQ:
222  case Mips::BEQ_MM:
223  // beq $zero, $zero, $L2 => b $L2
224  // beq $r0, $zero, $L2 => beqz $r0, $L2
225  return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) &&
226  printAlias("b", MI, 2, OS)) ||
227  (isReg<Mips::ZERO>(MI, 1) && printAlias("beqz", MI, 0, 2, OS));
228  case Mips::BEQ64:
229  // beq $r0, $zero, $L2 => beqz $r0, $L2
230  return isReg<Mips::ZERO_64>(MI, 1) && printAlias("beqz", MI, 0, 2, OS);
231  case Mips::BNE:
232  case Mips::BNE_MM:
233  // bne $r0, $zero, $L2 => bnez $r0, $L2
234  return isReg<Mips::ZERO>(MI, 1) && printAlias("bnez", MI, 0, 2, OS);
235  case Mips::BNE64:
236  // bne $r0, $zero, $L2 => bnez $r0, $L2
237  return isReg<Mips::ZERO_64>(MI, 1) && printAlias("bnez", MI, 0, 2, OS);
238  case Mips::BGEZAL:
239  // bgezal $zero, $L1 => bal $L1
240  return isReg<Mips::ZERO>(MI, 0) && printAlias("bal", MI, 1, OS);
241  case Mips::BC1T:
242  // bc1t $fcc0, $L1 => bc1t $L1
243  return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1t", MI, 1, OS);
244  case Mips::BC1F:
245  // bc1f $fcc0, $L1 => bc1f $L1
246  return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1f", MI, 1, OS);
247  case Mips::JALR:
248  // jalr $ra, $r1 => jalr $r1
249  return isReg<Mips::RA>(MI, 0) && printAlias("jalr", MI, 1, OS);
250  case Mips::JALR64:
251  // jalr $ra, $r1 => jalr $r1
252  return isReg<Mips::RA_64>(MI, 0) && printAlias("jalr", MI, 1, OS);
253  case Mips::NOR:
254  case Mips::NOR_MM:
255  case Mips::NOR_MMR6:
256  // nor $r0, $r1, $zero => not $r0, $r1
257  return isReg<Mips::ZERO>(MI, 2) && printAlias("not", MI, 0, 1, OS);
258  case Mips::NOR64:
259  // nor $r0, $r1, $zero => not $r0, $r1
260  return isReg<Mips::ZERO_64>(MI, 2) && printAlias("not", MI, 0, 1, OS);
261  case Mips::OR:
262  // or $r0, $r1, $zero => move $r0, $r1
263  return isReg<Mips::ZERO>(MI, 2) && printAlias("move", MI, 0, 1, OS);
264  default: return false;
265  }
266 }
267 
268 void MipsInstPrinter::printSaveRestore(const MCInst *MI, raw_ostream &O) {
269  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
270  if (i != 0) O << ", ";
271  if (MI->getOperand(i).isReg())
272  printRegName(O, MI->getOperand(i).getReg());
273  else
274  printUImm<16>(MI, i, O);
275  }
276 }
277 
278 void MipsInstPrinter::
279 printRegisterList(const MCInst *MI, int opNum, raw_ostream &O) {
280  // - 2 because register List is always first operand of instruction and it is
281  // always followed by memory operand (base + offset).
282  for (int i = opNum, e = MI->getNumOperands() - 2; i != e; ++i) {
283  if (i != opNum)
284  O << ", ";
285  printRegName(O, MI->getOperand(i).getReg());
286  }
287 }
static bool isReg(const MCInst &MI, unsigned OpNo)
bool isImm() const
Definition: MCInst.h:58
bool printAliasInstr(const MCInst *MI, raw_ostream &OS)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool isReg() const
Definition: MCInst.h:57
void printRegName(raw_ostream &OS, unsigned RegNo) const override
Print the assembler register name.
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:64
format_object< int64_t > formatImm(int64_t Value) const
Utility function to print immediates in decimal or hex.
Definition: MCInstPrinter.h:99
const MCExpr * getExpr() const
Definition: MCInst.h:95
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
int64_t getImm() const
Definition: MCInst.h:75
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:41
static ManagedStatic< OptionRegistry > OR
Definition: Options.cpp:30
bool isExpr() const
Definition: MCInst.h:60
unsigned getNumOperands() const
Definition: MCInst.h:181
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) override
Print the specified MCInst to the specified raw_ostream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:179
const char * MipsFCCToString(Mips::CondCode CC)
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:45
Generic base class for all target subtargets.
LLVM_NODISCARD std::string lower() const
Definition: StringRef.cpp:107
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char * getRegisterName(unsigned RegNo)
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
void printInstruction(const MCInst *MI, raw_ostream &O)
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
unsigned getOpcode() const
Definition: MCInst.h:171
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34