xref: /freebsd/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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"
1381ad6265SDimitry Andric #include "MCTargetDesc/CSKYBaseInfo.h"
1481ad6265SDimitry Andric #include "MCTargetDesc/CSKYMCExpr.h"
1581ad6265SDimitry 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"
2081ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
21fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
2281ad6265SDimitry 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"
2681ad6265SDimitry 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.
applyTargetSpecificCLOption(StringRef Opt)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   }
6381ad6265SDimitry Andric   if (Opt == "debug") {
6481ad6265SDimitry Andric     DebugFlag = true;
6581ad6265SDimitry Andric     return true;
6681ad6265SDimitry Andric   }
6781ad6265SDimitry Andric   if (Opt == "abi-names") {
6881ad6265SDimitry Andric     ABIRegNames = true;
6981ad6265SDimitry Andric     return true;
7081ad6265SDimitry Andric   }
71fe6060f1SDimitry Andric 
72fe6060f1SDimitry Andric   return false;
73fe6060f1SDimitry Andric }
74fe6060f1SDimitry Andric 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)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 
printRegName(raw_ostream & O,MCRegister Reg) const85bdd1243dSDimitry Andric void CSKYInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
8681ad6265SDimitry Andric   if (PrintBranchImmAsAddress)
87bdd1243dSDimitry Andric     O << getRegisterName(Reg, ABIRegNames ? CSKY::ABIRegAltName
8881ad6265SDimitry Andric                                           : CSKY::NoRegAltName);
8981ad6265SDimitry Andric   else
90bdd1243dSDimitry Andric     O << getRegisterName(Reg);
91fe6060f1SDimitry Andric }
92fe6060f1SDimitry Andric 
printFPRRegName(raw_ostream & O,unsigned RegNo) const9304eeddc0SDimitry 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 
printOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O,const char * Modifier)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()) {
10781ad6265SDimitry Andric     unsigned Reg = MO.getReg();
10881ad6265SDimitry Andric     bool useABIName = false;
10981ad6265SDimitry Andric     if (PrintBranchImmAsAddress)
11081ad6265SDimitry Andric       useABIName = ABIRegNames;
111fe6060f1SDimitry Andric     else
11281ad6265SDimitry Andric       useABIName = !ArchRegNames;
11381ad6265SDimitry Andric 
11481ad6265SDimitry Andric     if (Reg == CSKY::C)
11581ad6265SDimitry Andric       O << "";
116*06c3fb27SDimitry Andric     else if (STI.hasFeature(CSKY::FeatureJAVA)) {
11781ad6265SDimitry Andric       if (Reg == CSKY::R23)
11881ad6265SDimitry Andric         O << (useABIName ? "fp" : "r23");
11981ad6265SDimitry Andric       else if (Reg == CSKY::R24)
12081ad6265SDimitry Andric         O << (useABIName ? "top" : "r24");
12181ad6265SDimitry Andric       else if (Reg == CSKY::R25)
12281ad6265SDimitry Andric         O << (useABIName ? "bsp" : "r25");
12381ad6265SDimitry Andric       else
12481ad6265SDimitry Andric         printRegName(O, Reg);
12581ad6265SDimitry Andric     } else
12681ad6265SDimitry Andric       printRegName(O, Reg);
12781ad6265SDimitry Andric 
128fe6060f1SDimitry Andric     return;
129fe6060f1SDimitry Andric   }
130fe6060f1SDimitry Andric 
131fe6060f1SDimitry Andric   if (MO.isImm()) {
13281ad6265SDimitry Andric     uint64_t TSFlags = MII.get(MI->getOpcode()).TSFlags;
13381ad6265SDimitry Andric 
13481ad6265SDimitry Andric     if (((TSFlags & CSKYII::AddrModeMask) != CSKYII::AddrModeNone) &&
13581ad6265SDimitry Andric         PrintBranchImmAsAddress)
13681ad6265SDimitry Andric       O << formatHex(MO.getImm());
13781ad6265SDimitry Andric     else
13881ad6265SDimitry 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 
printDataSymbol(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)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 
printConstpool(const MCInst * MI,uint64_t Address,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)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 
printCSKYSymbolOperand(const MCInst * MI,uint64_t Address,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)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 
printPSRFlag(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)20081ad6265SDimitry Andric void CSKYInstPrinter::printPSRFlag(const MCInst *MI, unsigned OpNo,
20181ad6265SDimitry Andric                                    const MCSubtargetInfo &STI, raw_ostream &O) {
20281ad6265SDimitry Andric   auto V = MI->getOperand(OpNo).getImm();
20381ad6265SDimitry Andric 
20481ad6265SDimitry Andric   ListSeparator LS;
20581ad6265SDimitry Andric 
20681ad6265SDimitry Andric   if ((V >> 3) & 0x1)
20781ad6265SDimitry Andric     O << LS << "ee";
20881ad6265SDimitry Andric   if ((V >> 2) & 0x1)
20981ad6265SDimitry Andric     O << LS << "ie";
21081ad6265SDimitry Andric   if ((V >> 1) & 0x1)
21181ad6265SDimitry Andric     O << LS << "fe";
21281ad6265SDimitry Andric   if ((V >> 0) & 0x1)
21381ad6265SDimitry Andric     O << LS << "af";
21481ad6265SDimitry Andric }
21581ad6265SDimitry Andric 
printRegisterSeq(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)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 
printRegisterList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)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 
getRegisterName(MCRegister Reg)263bdd1243dSDimitry Andric const char *CSKYInstPrinter::getRegisterName(MCRegister Reg) {
264bdd1243dSDimitry Andric   return getRegisterName(Reg, ArchRegNames ? CSKY::NoRegAltName
265fe6060f1SDimitry Andric                                            : CSKY::ABIRegAltName);
266fe6060f1SDimitry Andric }
26704eeddc0SDimitry Andric 
printFPR(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)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