xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1fe6060f1SDimitry Andric //===-- CSKYInstPrinter.cpp - Convert CSKY MCInst to asm syntax ---------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // This class prints an CSKY MCInst to a .s file.
10fe6060f1SDimitry Andric //
11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
12fe6060f1SDimitry Andric #include "CSKYInstPrinter.h"
13*81ad6265SDimitry Andric #include "MCTargetDesc/CSKYBaseInfo.h"
14*81ad6265SDimitry Andric #include "MCTargetDesc/CSKYMCExpr.h"
15*81ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h"
16349cc55cSDimitry Andric #include "llvm/ADT/StringExtras.h"
17fe6060f1SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h"
19fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h"
20*81ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
21fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
22*81ad6265SDimitry Andric #include "llvm/MC/MCSection.h"
23fe6060f1SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
24fe6060f1SDimitry Andric #include "llvm/MC/MCSymbol.h"
25fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h"
26*81ad6265SDimitry Andric #include "llvm/Support/Debug.h"
27fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
28fe6060f1SDimitry Andric #include "llvm/Support/FormattedStream.h"
29fe6060f1SDimitry Andric 
30fe6060f1SDimitry Andric using namespace llvm;
31fe6060f1SDimitry Andric 
32fe6060f1SDimitry Andric #define DEBUG_TYPE "csky-asm-printer"
33fe6060f1SDimitry Andric 
34fe6060f1SDimitry Andric // Include the auto-generated portion of the assembly writer.
35fe6060f1SDimitry Andric #define PRINT_ALIAS_INSTR
36fe6060f1SDimitry Andric #include "CSKYGenAsmWriter.inc"
37fe6060f1SDimitry Andric 
38fe6060f1SDimitry Andric static cl::opt<bool>
39fe6060f1SDimitry Andric     NoAliases("csky-no-aliases",
40fe6060f1SDimitry Andric               cl::desc("Disable the emission of assembler pseudo instructions"),
41fe6060f1SDimitry Andric               cl::init(false), cl::Hidden);
42fe6060f1SDimitry Andric 
43fe6060f1SDimitry Andric static cl::opt<bool>
44fe6060f1SDimitry Andric     ArchRegNames("csky-arch-reg-names",
45fe6060f1SDimitry Andric                  cl::desc("Print architectural register names rather than the "
46fe6060f1SDimitry Andric                           "ABI names (such as r14 instead of sp)"),
47fe6060f1SDimitry Andric                  cl::init(false), cl::Hidden);
48fe6060f1SDimitry Andric 
49fe6060f1SDimitry Andric // The command-line flags above are used by llvm-mc and llc. They can be used by
50fe6060f1SDimitry Andric // `llvm-objdump`, but we override their values here to handle options passed to
51fe6060f1SDimitry Andric // `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to
52fe6060f1SDimitry Andric // be an easier way to allow these options in all these tools, without doing it
53fe6060f1SDimitry Andric // this way.
54fe6060f1SDimitry Andric bool CSKYInstPrinter::applyTargetSpecificCLOption(StringRef Opt) {
55fe6060f1SDimitry Andric   if (Opt == "no-aliases") {
56fe6060f1SDimitry Andric     NoAliases = true;
57fe6060f1SDimitry Andric     return true;
58fe6060f1SDimitry Andric   }
59fe6060f1SDimitry Andric   if (Opt == "numeric") {
60fe6060f1SDimitry Andric     ArchRegNames = true;
61fe6060f1SDimitry Andric     return true;
62fe6060f1SDimitry Andric   }
63*81ad6265SDimitry Andric   if (Opt == "debug") {
64*81ad6265SDimitry Andric     DebugFlag = true;
65*81ad6265SDimitry Andric     return true;
66*81ad6265SDimitry Andric   }
67*81ad6265SDimitry Andric   if (Opt == "abi-names") {
68*81ad6265SDimitry Andric     ABIRegNames = true;
69*81ad6265SDimitry Andric     return true;
70*81ad6265SDimitry Andric   }
71fe6060f1SDimitry Andric 
72fe6060f1SDimitry Andric   return false;
73fe6060f1SDimitry Andric }
74fe6060f1SDimitry Andric 
75fe6060f1SDimitry Andric void CSKYInstPrinter::printInst(const MCInst *MI, uint64_t Address,
76fe6060f1SDimitry Andric                                 StringRef Annot, const MCSubtargetInfo &STI,
77fe6060f1SDimitry Andric                                 raw_ostream &O) {
78fe6060f1SDimitry Andric   const MCInst *NewMI = MI;
79fe6060f1SDimitry Andric 
80fe6060f1SDimitry Andric   if (NoAliases || !printAliasInstr(NewMI, Address, STI, O))
81fe6060f1SDimitry Andric     printInstruction(NewMI, Address, STI, O);
82fe6060f1SDimitry Andric   printAnnotation(O, Annot);
83fe6060f1SDimitry Andric }
84fe6060f1SDimitry Andric 
85fe6060f1SDimitry Andric void CSKYInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
86*81ad6265SDimitry Andric   if (PrintBranchImmAsAddress)
87*81ad6265SDimitry Andric     O << getRegisterName(RegNo, ABIRegNames ? CSKY::ABIRegAltName
88*81ad6265SDimitry Andric                                             : CSKY::NoRegAltName);
89*81ad6265SDimitry Andric   else
90fe6060f1SDimitry Andric     O << getRegisterName(RegNo);
91fe6060f1SDimitry Andric }
92fe6060f1SDimitry Andric 
9304eeddc0SDimitry Andric void CSKYInstPrinter::printFPRRegName(raw_ostream &O, unsigned RegNo) const {
9404eeddc0SDimitry Andric   if (PrintBranchImmAsAddress)
9504eeddc0SDimitry Andric     O << getRegisterName(RegNo, CSKY::NoRegAltName);
9604eeddc0SDimitry Andric   else
9704eeddc0SDimitry Andric     O << getRegisterName(RegNo);
9804eeddc0SDimitry Andric }
9904eeddc0SDimitry Andric 
100fe6060f1SDimitry Andric void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
101fe6060f1SDimitry Andric                                    const MCSubtargetInfo &STI, raw_ostream &O,
102fe6060f1SDimitry Andric                                    const char *Modifier) {
103fe6060f1SDimitry Andric   assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
104fe6060f1SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric   if (MO.isReg()) {
107*81ad6265SDimitry Andric     unsigned Reg = MO.getReg();
108*81ad6265SDimitry Andric     bool useABIName = false;
109*81ad6265SDimitry Andric     if (PrintBranchImmAsAddress)
110*81ad6265SDimitry Andric       useABIName = ABIRegNames;
111fe6060f1SDimitry Andric     else
112*81ad6265SDimitry Andric       useABIName = !ArchRegNames;
113*81ad6265SDimitry Andric 
114*81ad6265SDimitry Andric     if (Reg == CSKY::C)
115*81ad6265SDimitry Andric       O << "";
116*81ad6265SDimitry Andric     else if (STI.getFeatureBits()[CSKY::FeatureJAVA]) {
117*81ad6265SDimitry Andric       if (Reg == CSKY::R23)
118*81ad6265SDimitry Andric         O << (useABIName ? "fp" : "r23");
119*81ad6265SDimitry Andric       else if (Reg == CSKY::R24)
120*81ad6265SDimitry Andric         O << (useABIName ? "top" : "r24");
121*81ad6265SDimitry Andric       else if (Reg == CSKY::R25)
122*81ad6265SDimitry Andric         O << (useABIName ? "bsp" : "r25");
123*81ad6265SDimitry Andric       else
124*81ad6265SDimitry Andric         printRegName(O, Reg);
125*81ad6265SDimitry Andric     } else
126*81ad6265SDimitry Andric       printRegName(O, Reg);
127*81ad6265SDimitry Andric 
128fe6060f1SDimitry Andric     return;
129fe6060f1SDimitry Andric   }
130fe6060f1SDimitry Andric 
131fe6060f1SDimitry Andric   if (MO.isImm()) {
132*81ad6265SDimitry Andric     uint64_t TSFlags = MII.get(MI->getOpcode()).TSFlags;
133*81ad6265SDimitry Andric 
134*81ad6265SDimitry Andric     if (((TSFlags & CSKYII::AddrModeMask) != CSKYII::AddrModeNone) &&
135*81ad6265SDimitry Andric         PrintBranchImmAsAddress)
136*81ad6265SDimitry Andric       O << formatHex(MO.getImm());
137*81ad6265SDimitry Andric     else
138*81ad6265SDimitry Andric       O << MO.getImm();
139fe6060f1SDimitry Andric     return;
140fe6060f1SDimitry Andric   }
141fe6060f1SDimitry Andric 
142fe6060f1SDimitry Andric   assert(MO.isExpr() && "Unknown operand kind in printOperand");
143fe6060f1SDimitry Andric   MO.getExpr()->print(O, &MAI);
144fe6060f1SDimitry Andric }
145fe6060f1SDimitry Andric 
146349cc55cSDimitry Andric void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo,
147349cc55cSDimitry Andric                                       const MCSubtargetInfo &STI,
148349cc55cSDimitry Andric                                       raw_ostream &O) {
149349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
150349cc55cSDimitry Andric 
151349cc55cSDimitry Andric   O << "[";
152349cc55cSDimitry Andric   if (MO.isImm())
153349cc55cSDimitry Andric     O << MO.getImm();
154349cc55cSDimitry Andric   else
155349cc55cSDimitry Andric     MO.getExpr()->print(O, &MAI);
156349cc55cSDimitry Andric   O << "]";
157349cc55cSDimitry Andric }
158349cc55cSDimitry Andric 
159349cc55cSDimitry Andric void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address,
160349cc55cSDimitry Andric                                      unsigned OpNo, const MCSubtargetInfo &STI,
161349cc55cSDimitry Andric                                      raw_ostream &O) {
162349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
163349cc55cSDimitry Andric 
164349cc55cSDimitry Andric   if (MO.isImm()) {
165349cc55cSDimitry Andric     if (PrintBranchImmAsAddress) {
166349cc55cSDimitry Andric       uint64_t Target = Address + MO.getImm();
167349cc55cSDimitry Andric       Target &= 0xfffffffc;
168349cc55cSDimitry Andric       O << formatHex(Target);
169349cc55cSDimitry Andric     } else {
170349cc55cSDimitry Andric       O << MO.getImm();
171349cc55cSDimitry Andric     }
172349cc55cSDimitry Andric     return;
173349cc55cSDimitry Andric   }
174349cc55cSDimitry Andric 
175349cc55cSDimitry Andric   assert(MO.isExpr() && "Unknown operand kind in printConstpool");
176349cc55cSDimitry Andric 
177349cc55cSDimitry Andric   O << "[";
178349cc55cSDimitry Andric   MO.getExpr()->print(O, &MAI);
179349cc55cSDimitry Andric   O << "]";
180349cc55cSDimitry Andric }
181349cc55cSDimitry Andric 
182349cc55cSDimitry Andric void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address,
183349cc55cSDimitry Andric                                              unsigned OpNo,
184349cc55cSDimitry Andric                                              const MCSubtargetInfo &STI,
185349cc55cSDimitry Andric                                              raw_ostream &O) {
186349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
187349cc55cSDimitry Andric   if (!MO.isImm()) {
188349cc55cSDimitry Andric     return printOperand(MI, OpNo, STI, O);
189349cc55cSDimitry Andric   }
190349cc55cSDimitry Andric 
191349cc55cSDimitry Andric   if (PrintBranchImmAsAddress) {
192349cc55cSDimitry Andric     uint64_t Target = Address + MO.getImm();
193349cc55cSDimitry Andric     Target &= 0xffffffff;
194349cc55cSDimitry Andric     O << formatHex(Target);
195349cc55cSDimitry Andric   } else {
196349cc55cSDimitry Andric     O << MO.getImm();
197349cc55cSDimitry Andric   }
198349cc55cSDimitry Andric }
199349cc55cSDimitry Andric 
200*81ad6265SDimitry Andric void CSKYInstPrinter::printPSRFlag(const MCInst *MI, unsigned OpNo,
201*81ad6265SDimitry Andric                                    const MCSubtargetInfo &STI, raw_ostream &O) {
202*81ad6265SDimitry Andric   auto V = MI->getOperand(OpNo).getImm();
203*81ad6265SDimitry Andric 
204*81ad6265SDimitry Andric   ListSeparator LS;
205*81ad6265SDimitry Andric 
206*81ad6265SDimitry Andric   if ((V >> 3) & 0x1)
207*81ad6265SDimitry Andric     O << LS << "ee";
208*81ad6265SDimitry Andric   if ((V >> 2) & 0x1)
209*81ad6265SDimitry Andric     O << LS << "ie";
210*81ad6265SDimitry Andric   if ((V >> 1) & 0x1)
211*81ad6265SDimitry Andric     O << LS << "fe";
212*81ad6265SDimitry Andric   if ((V >> 0) & 0x1)
213*81ad6265SDimitry Andric     O << LS << "af";
214*81ad6265SDimitry Andric }
215*81ad6265SDimitry Andric 
216349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum,
217349cc55cSDimitry Andric                                        const MCSubtargetInfo &STI,
218349cc55cSDimitry Andric                                        raw_ostream &O) {
219349cc55cSDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
220349cc55cSDimitry Andric   O << "-";
221349cc55cSDimitry Andric   printRegName(O, MI->getOperand(OpNum + 1).getReg());
222349cc55cSDimitry Andric }
223349cc55cSDimitry Andric 
224349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
225349cc55cSDimitry Andric                                         const MCSubtargetInfo &STI,
226349cc55cSDimitry Andric                                         raw_ostream &O) {
227349cc55cSDimitry Andric   auto V = MI->getOperand(OpNum).getImm();
228349cc55cSDimitry Andric   ListSeparator LS;
229349cc55cSDimitry Andric 
230349cc55cSDimitry Andric   if (V & 0xf) {
231349cc55cSDimitry Andric     O << LS;
232349cc55cSDimitry Andric     printRegName(O, CSKY::R4);
233349cc55cSDimitry Andric     auto Offset = (V & 0xf) - 1;
234349cc55cSDimitry Andric     if (Offset) {
235349cc55cSDimitry Andric       O << "-";
236349cc55cSDimitry Andric       printRegName(O, CSKY::R4 + Offset);
237349cc55cSDimitry Andric     }
238349cc55cSDimitry Andric   }
239349cc55cSDimitry Andric 
240349cc55cSDimitry Andric   if ((V >> 4) & 0x1) {
241349cc55cSDimitry Andric     O << LS;
242349cc55cSDimitry Andric     printRegName(O, CSKY::R15);
243349cc55cSDimitry Andric   }
244349cc55cSDimitry Andric 
245349cc55cSDimitry Andric   if ((V >> 5) & 0x7) {
246349cc55cSDimitry Andric     O << LS;
247349cc55cSDimitry Andric     printRegName(O, CSKY::R16);
248349cc55cSDimitry Andric 
249349cc55cSDimitry Andric     auto Offset = ((V >> 5) & 0x7) - 1;
250349cc55cSDimitry Andric 
251349cc55cSDimitry Andric     if (Offset) {
252349cc55cSDimitry Andric       O << "-";
253349cc55cSDimitry Andric       printRegName(O, CSKY::R16 + Offset);
254349cc55cSDimitry Andric     }
255349cc55cSDimitry Andric   }
256349cc55cSDimitry Andric 
257349cc55cSDimitry Andric   if ((V >> 8) & 0x1) {
258349cc55cSDimitry Andric     O << LS;
259349cc55cSDimitry Andric     printRegName(O, CSKY::R28);
260349cc55cSDimitry Andric   }
261349cc55cSDimitry Andric }
262349cc55cSDimitry Andric 
263fe6060f1SDimitry Andric const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) {
264fe6060f1SDimitry Andric   return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName
265fe6060f1SDimitry Andric                                              : CSKY::ABIRegAltName);
266fe6060f1SDimitry Andric }
26704eeddc0SDimitry Andric 
26804eeddc0SDimitry Andric void CSKYInstPrinter::printFPR(const MCInst *MI, unsigned OpNo,
26904eeddc0SDimitry Andric                                const MCSubtargetInfo &STI, raw_ostream &O) {
27004eeddc0SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
27104eeddc0SDimitry Andric   assert(MO.isReg());
27204eeddc0SDimitry Andric 
27304eeddc0SDimitry Andric   printFPRRegName(O, MO.getReg());
27404eeddc0SDimitry Andric }
275