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