LLVM 22.0.0git
CSKYInstPrinter.cpp
Go to the documentation of this file.
1//===-- CSKYInstPrinter.cpp - Convert CSKY MCInst to asm 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 CSKY MCInst to a .s file.
10//
11//===----------------------------------------------------------------------===//
12#include "CSKYInstPrinter.h"
15#include "llvm/ADT/STLExtras.h"
17#include "llvm/MC/MCAsmInfo.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstrInfo.h"
22#include "llvm/MC/MCSection.h"
24#include "llvm/MC/MCSymbol.h"
26#include "llvm/Support/Debug.h"
29
30using namespace llvm;
31
32#define DEBUG_TYPE "csky-asm-printer"
33
34// Include the auto-generated portion of the assembly writer.
35#define PRINT_ALIAS_INSTR
36#include "CSKYGenAsmWriter.inc"
37
38static cl::opt<bool>
39 NoAliases("csky-no-aliases",
40 cl::desc("Disable the emission of assembler pseudo instructions"),
41 cl::init(false), cl::Hidden);
42
43static cl::opt<bool>
44 ArchRegNames("csky-arch-reg-names",
45 cl::desc("Print architectural register names rather than the "
46 "ABI names (such as r14 instead of sp)"),
47 cl::init(false), cl::Hidden);
48
49// The command-line flags above are used by llvm-mc and llc. They can be used by
50// `llvm-objdump`, but we override their values here to handle options passed to
51// `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to
52// be an easier way to allow these options in all these tools, without doing it
53// this way.
55 if (Opt == "no-aliases") {
56 NoAliases = true;
57 return true;
58 }
59 if (Opt == "numeric") {
60 ArchRegNames = true;
61 return true;
62 }
63 if (Opt == "debug") {
64 DebugFlag = true;
65 return true;
66 }
67 if (Opt == "abi-names") {
68 ABIRegNames = true;
69 return true;
70 }
71
72 return false;
73}
74
76 StringRef Annot, const MCSubtargetInfo &STI,
77 raw_ostream &O) {
78 const MCInst *NewMI = MI;
79
80 if (NoAliases || !printAliasInstr(NewMI, Address, STI, O))
81 printInstruction(NewMI, Address, STI, O);
82 printAnnotation(O, Annot);
83}
84
87 O << getRegisterName(Reg, ABIRegNames ? CSKY::ABIRegAltName
88 : CSKY::NoRegAltName);
89 else
90 O << getRegisterName(Reg);
91}
92
93void CSKYInstPrinter::printFPRRegName(raw_ostream &O, unsigned RegNo) const {
95 O << getRegisterName(RegNo, CSKY::NoRegAltName);
96 else
97 O << getRegisterName(RegNo);
98}
99
100void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
101 const MCSubtargetInfo &STI, raw_ostream &O) {
102 const MCOperand &MO = MI->getOperand(OpNo);
103
104 if (MO.isReg()) {
105 unsigned Reg = MO.getReg();
106 bool useABIName = false;
108 useABIName = ABIRegNames;
109 else
110 useABIName = !ArchRegNames;
111
112 if (Reg == CSKY::C)
113 O << "";
114 else if (STI.hasFeature(CSKY::FeatureJAVA)) {
115 if (Reg == CSKY::R23)
116 O << (useABIName ? "fp" : "r23");
117 else if (Reg == CSKY::R24)
118 O << (useABIName ? "top" : "r24");
119 else if (Reg == CSKY::R25)
120 O << (useABIName ? "bsp" : "r25");
121 else
122 printRegName(O, Reg);
123 } else
124 printRegName(O, Reg);
125
126 return;
127 }
128
129 if (MO.isImm()) {
130 uint64_t TSFlags = MII.get(MI->getOpcode()).TSFlags;
131
132 if (((TSFlags & CSKYII::AddrModeMask) != CSKYII::AddrModeNone) &&
134 O << formatHex(MO.getImm());
135 else
136 O << MO.getImm();
137 return;
138 }
139
140 assert(MO.isExpr() && "Unknown operand kind in printOperand");
141 MAI.printExpr(O, *MO.getExpr());
142}
143
144void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo,
145 const MCSubtargetInfo &STI,
146 raw_ostream &O) {
147 const MCOperand &MO = MI->getOperand(OpNo);
148
149 O << "[";
150 if (MO.isImm())
151 O << MO.getImm();
152 else
153 MAI.printExpr(O, *MO.getExpr());
154 O << "]";
155}
156
158 unsigned OpNo, const MCSubtargetInfo &STI,
159 raw_ostream &O) {
160 const MCOperand &MO = MI->getOperand(OpNo);
161
162 if (MO.isImm()) {
164 uint64_t Target = Address + MO.getImm();
165 Target &= 0xfffffffc;
166 O << formatHex(Target);
167 } else {
168 O << MO.getImm();
169 }
170 return;
171 }
172
173 assert(MO.isExpr() && "Unknown operand kind in printConstpool");
174
175 O << "[";
176 MAI.printExpr(O, *MO.getExpr());
177 O << "]";
178}
179
181 unsigned OpNo,
182 const MCSubtargetInfo &STI,
183 raw_ostream &O) {
184 const MCOperand &MO = MI->getOperand(OpNo);
185 if (!MO.isImm()) {
186 return printOperand(MI, OpNo, STI, O);
187 }
188
190 uint64_t Target = Address + MO.getImm();
191 Target &= 0xffffffff;
192 O << formatHex(Target);
193 } else {
194 O << MO.getImm();
195 }
196}
197
198void CSKYInstPrinter::printPSRFlag(const MCInst *MI, unsigned OpNo,
199 const MCSubtargetInfo &STI, raw_ostream &O) {
200 auto V = MI->getOperand(OpNo).getImm();
201
202 ListSeparator LS;
203
204 if ((V >> 3) & 0x1)
205 O << LS << "ee";
206 if ((V >> 2) & 0x1)
207 O << LS << "ie";
208 if ((V >> 1) & 0x1)
209 O << LS << "fe";
210 if ((V >> 0) & 0x1)
211 O << LS << "af";
212}
213
214void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum,
215 const MCSubtargetInfo &STI,
216 raw_ostream &O) {
217 printRegName(O, MI->getOperand(OpNum).getReg());
218 O << "-";
219 printRegName(O, MI->getOperand(OpNum + 1).getReg());
220}
221
222void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
223 const MCSubtargetInfo &STI,
224 raw_ostream &O) {
225 auto V = MI->getOperand(OpNum).getImm();
226 ListSeparator LS;
227
228 if (V & 0xf) {
229 O << LS;
230 printRegName(O, CSKY::R4);
231 auto Offset = (V & 0xf) - 1;
232 if (Offset) {
233 O << "-";
234 printRegName(O, CSKY::R4 + Offset);
235 }
236 }
237
238 if ((V >> 4) & 0x1) {
239 O << LS;
240 printRegName(O, CSKY::R15);
241 }
242
243 if ((V >> 5) & 0x7) {
244 O << LS;
245 printRegName(O, CSKY::R16);
246
247 auto Offset = ((V >> 5) & 0x7) - 1;
248
249 if (Offset) {
250 O << "-";
251 printRegName(O, CSKY::R16 + Offset);
252 }
253 }
254
255 if ((V >> 8) & 0x1) {
256 O << LS;
257 printRegName(O, CSKY::R28);
258 }
259}
260
262 return getRegisterName(Reg, ArchRegNames ? CSKY::NoRegAltName
263 : CSKY::ABIRegAltName);
264}
265
266void CSKYInstPrinter::printFPR(const MCInst *MI, unsigned OpNo,
267 const MCSubtargetInfo &STI, raw_ostream &O) {
268 const MCOperand &MO = MI->getOperand(OpNo);
269 assert(MO.isReg());
270
271 printFPRRegName(O, MO.getReg());
272}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > NoAliases("csky-no-aliases", cl::desc("Disable the emission of assembler pseudo instructions"), cl::init(false), cl::Hidden)
static cl::opt< bool > ArchRegNames("csky-arch-reg-names", cl::desc("Print architectural register names rather than the " "ABI names (such as r14 instead of sp)"), cl::init(false), cl::Hidden)
IRTranslator LLVM IR MI
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override
Print the specified MCInst to the specified raw_ostream.
void printRegisterSeq(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printFPRRegName(raw_ostream &O, unsigned RegNo) const
static const char * getRegisterName(MCRegister Reg)
void printDataSymbol(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
bool applyTargetSpecificCLOption(StringRef Opt) override
Customize the printer according to a command line option.
void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printPSRFlag(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printCSKYSymbolOperand(const MCInst *MI, uint64_t Address, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printFPR(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printConstpool(const MCInst *MI, uint64_t Address, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
bool printAliasInstr(const MCInst *MI, uint64_t Address, const MCSubtargetInfo &STI, raw_ostream &O)
void printRegisterList(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printInstruction(const MCInst *MI, uint64_t Address, const MCSubtargetInfo &STI, raw_ostream &O)
void printRegName(raw_ostream &O, MCRegister Reg) override
Print the assembler register name.
A helper class to return the specified delimiter string after the first invocation of operator String...
format_object< int64_t > formatHex(int64_t Value) const
const MCInstrInfo & MII
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
bool PrintBranchImmAsAddress
If true, a branch immediate (e.g.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:33
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
LLVM_ABI bool DebugFlag
This boolean is set to true if the '-debug' command line option is specified.
Definition Debug.cpp:68