xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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 
13fe6060f1SDimitry Andric #include "CSKYInstPrinter.h"
14*349cc55cSDimitry Andric #include "llvm/ADT/StringExtras.h"
15fe6060f1SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
16fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h"
17fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
19fe6060f1SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
20fe6060f1SDimitry Andric #include "llvm/MC/MCSymbol.h"
21fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h"
22fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
23fe6060f1SDimitry Andric #include "llvm/Support/FormattedStream.h"
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric using namespace llvm;
26fe6060f1SDimitry Andric 
27fe6060f1SDimitry Andric #define DEBUG_TYPE "csky-asm-printer"
28fe6060f1SDimitry Andric 
29fe6060f1SDimitry Andric // Include the auto-generated portion of the assembly writer.
30fe6060f1SDimitry Andric #define PRINT_ALIAS_INSTR
31fe6060f1SDimitry Andric #include "CSKYGenAsmWriter.inc"
32fe6060f1SDimitry Andric 
33fe6060f1SDimitry Andric static cl::opt<bool>
34fe6060f1SDimitry Andric     NoAliases("csky-no-aliases",
35fe6060f1SDimitry Andric               cl::desc("Disable the emission of assembler pseudo instructions"),
36fe6060f1SDimitry Andric               cl::init(false), cl::Hidden);
37fe6060f1SDimitry Andric 
38fe6060f1SDimitry Andric static cl::opt<bool>
39fe6060f1SDimitry Andric     ArchRegNames("csky-arch-reg-names",
40fe6060f1SDimitry Andric                  cl::desc("Print architectural register names rather than the "
41fe6060f1SDimitry Andric                           "ABI names (such as r14 instead of sp)"),
42fe6060f1SDimitry Andric                  cl::init(false), cl::Hidden);
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric // The command-line flags above are used by llvm-mc and llc. They can be used by
45fe6060f1SDimitry Andric // `llvm-objdump`, but we override their values here to handle options passed to
46fe6060f1SDimitry Andric // `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to
47fe6060f1SDimitry Andric // be an easier way to allow these options in all these tools, without doing it
48fe6060f1SDimitry Andric // this way.
49fe6060f1SDimitry Andric bool CSKYInstPrinter::applyTargetSpecificCLOption(StringRef Opt) {
50fe6060f1SDimitry Andric   if (Opt == "no-aliases") {
51fe6060f1SDimitry Andric     NoAliases = true;
52fe6060f1SDimitry Andric     return true;
53fe6060f1SDimitry Andric   }
54fe6060f1SDimitry Andric   if (Opt == "numeric") {
55fe6060f1SDimitry Andric     ArchRegNames = true;
56fe6060f1SDimitry Andric     return true;
57fe6060f1SDimitry Andric   }
58fe6060f1SDimitry Andric 
59fe6060f1SDimitry Andric   return false;
60fe6060f1SDimitry Andric }
61fe6060f1SDimitry Andric 
62fe6060f1SDimitry Andric void CSKYInstPrinter::printInst(const MCInst *MI, uint64_t Address,
63fe6060f1SDimitry Andric                                 StringRef Annot, const MCSubtargetInfo &STI,
64fe6060f1SDimitry Andric                                 raw_ostream &O) {
65fe6060f1SDimitry Andric   const MCInst *NewMI = MI;
66fe6060f1SDimitry Andric 
67fe6060f1SDimitry Andric   if (NoAliases || !printAliasInstr(NewMI, Address, STI, O))
68fe6060f1SDimitry Andric     printInstruction(NewMI, Address, STI, O);
69fe6060f1SDimitry Andric   printAnnotation(O, Annot);
70fe6060f1SDimitry Andric }
71fe6060f1SDimitry Andric 
72fe6060f1SDimitry Andric void CSKYInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
73fe6060f1SDimitry Andric   O << getRegisterName(RegNo);
74fe6060f1SDimitry Andric }
75fe6060f1SDimitry Andric 
76fe6060f1SDimitry Andric void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
77fe6060f1SDimitry Andric                                    const MCSubtargetInfo &STI, raw_ostream &O,
78fe6060f1SDimitry Andric                                    const char *Modifier) {
79fe6060f1SDimitry Andric   assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
80fe6060f1SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
81fe6060f1SDimitry Andric 
82fe6060f1SDimitry Andric   if (MO.isReg()) {
83fe6060f1SDimitry Andric     if (MO.getReg() == CSKY::C)
84fe6060f1SDimitry Andric       O << "";
85fe6060f1SDimitry Andric     else
86fe6060f1SDimitry Andric       printRegName(O, MO.getReg());
87fe6060f1SDimitry Andric     return;
88fe6060f1SDimitry Andric   }
89fe6060f1SDimitry Andric 
90fe6060f1SDimitry Andric   if (MO.isImm()) {
91fe6060f1SDimitry Andric     O << formatImm(MO.getImm());
92fe6060f1SDimitry Andric     return;
93fe6060f1SDimitry Andric   }
94fe6060f1SDimitry Andric 
95fe6060f1SDimitry Andric   assert(MO.isExpr() && "Unknown operand kind in printOperand");
96fe6060f1SDimitry Andric   MO.getExpr()->print(O, &MAI);
97fe6060f1SDimitry Andric }
98fe6060f1SDimitry Andric 
99*349cc55cSDimitry Andric void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo,
100*349cc55cSDimitry Andric                                       const MCSubtargetInfo &STI,
101*349cc55cSDimitry Andric                                       raw_ostream &O) {
102*349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
103*349cc55cSDimitry Andric 
104*349cc55cSDimitry Andric   O << "[";
105*349cc55cSDimitry Andric   if (MO.isImm())
106*349cc55cSDimitry Andric     O << MO.getImm();
107*349cc55cSDimitry Andric   else
108*349cc55cSDimitry Andric     MO.getExpr()->print(O, &MAI);
109*349cc55cSDimitry Andric   O << "]";
110*349cc55cSDimitry Andric }
111*349cc55cSDimitry Andric 
112*349cc55cSDimitry Andric void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address,
113*349cc55cSDimitry Andric                                      unsigned OpNo, const MCSubtargetInfo &STI,
114*349cc55cSDimitry Andric                                      raw_ostream &O) {
115*349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
116*349cc55cSDimitry Andric 
117*349cc55cSDimitry Andric   if (MO.isImm()) {
118*349cc55cSDimitry Andric     if (PrintBranchImmAsAddress) {
119*349cc55cSDimitry Andric       uint64_t Target = Address + MO.getImm();
120*349cc55cSDimitry Andric       Target &= 0xfffffffc;
121*349cc55cSDimitry Andric       O << formatHex(Target);
122*349cc55cSDimitry Andric     } else {
123*349cc55cSDimitry Andric       O << MO.getImm();
124*349cc55cSDimitry Andric     }
125*349cc55cSDimitry Andric     return;
126*349cc55cSDimitry Andric   }
127*349cc55cSDimitry Andric 
128*349cc55cSDimitry Andric   assert(MO.isExpr() && "Unknown operand kind in printConstpool");
129*349cc55cSDimitry Andric 
130*349cc55cSDimitry Andric   O << "[";
131*349cc55cSDimitry Andric   MO.getExpr()->print(O, &MAI);
132*349cc55cSDimitry Andric   O << "]";
133*349cc55cSDimitry Andric }
134*349cc55cSDimitry Andric 
135*349cc55cSDimitry Andric void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address,
136*349cc55cSDimitry Andric                                              unsigned OpNo,
137*349cc55cSDimitry Andric                                              const MCSubtargetInfo &STI,
138*349cc55cSDimitry Andric                                              raw_ostream &O) {
139*349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
140*349cc55cSDimitry Andric   if (!MO.isImm()) {
141*349cc55cSDimitry Andric     return printOperand(MI, OpNo, STI, O);
142*349cc55cSDimitry Andric   }
143*349cc55cSDimitry Andric 
144*349cc55cSDimitry Andric   if (PrintBranchImmAsAddress) {
145*349cc55cSDimitry Andric     uint64_t Target = Address + MO.getImm();
146*349cc55cSDimitry Andric     Target &= 0xffffffff;
147*349cc55cSDimitry Andric     O << formatHex(Target);
148*349cc55cSDimitry Andric   } else {
149*349cc55cSDimitry Andric     O << MO.getImm();
150*349cc55cSDimitry Andric   }
151*349cc55cSDimitry Andric }
152*349cc55cSDimitry Andric 
153*349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum,
154*349cc55cSDimitry Andric                                        const MCSubtargetInfo &STI,
155*349cc55cSDimitry Andric                                        raw_ostream &O) {
156*349cc55cSDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
157*349cc55cSDimitry Andric   O << "-";
158*349cc55cSDimitry Andric   printRegName(O, MI->getOperand(OpNum + 1).getReg());
159*349cc55cSDimitry Andric }
160*349cc55cSDimitry Andric 
161*349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
162*349cc55cSDimitry Andric                                         const MCSubtargetInfo &STI,
163*349cc55cSDimitry Andric                                         raw_ostream &O) {
164*349cc55cSDimitry Andric   auto V = MI->getOperand(OpNum).getImm();
165*349cc55cSDimitry Andric   ListSeparator LS;
166*349cc55cSDimitry Andric 
167*349cc55cSDimitry Andric   if (V & 0xf) {
168*349cc55cSDimitry Andric     O << LS;
169*349cc55cSDimitry Andric     printRegName(O, CSKY::R4);
170*349cc55cSDimitry Andric     auto Offset = (V & 0xf) - 1;
171*349cc55cSDimitry Andric     if (Offset) {
172*349cc55cSDimitry Andric       O << "-";
173*349cc55cSDimitry Andric       printRegName(O, CSKY::R4 + Offset);
174*349cc55cSDimitry Andric     }
175*349cc55cSDimitry Andric   }
176*349cc55cSDimitry Andric 
177*349cc55cSDimitry Andric   if ((V >> 4) & 0x1) {
178*349cc55cSDimitry Andric     O << LS;
179*349cc55cSDimitry Andric     printRegName(O, CSKY::R15);
180*349cc55cSDimitry Andric   }
181*349cc55cSDimitry Andric 
182*349cc55cSDimitry Andric   if ((V >> 5) & 0x7) {
183*349cc55cSDimitry Andric     O << LS;
184*349cc55cSDimitry Andric     printRegName(O, CSKY::R16);
185*349cc55cSDimitry Andric 
186*349cc55cSDimitry Andric     auto Offset = ((V >> 5) & 0x7) - 1;
187*349cc55cSDimitry Andric 
188*349cc55cSDimitry Andric     if (Offset) {
189*349cc55cSDimitry Andric       O << "-";
190*349cc55cSDimitry Andric       printRegName(O, CSKY::R16 + Offset);
191*349cc55cSDimitry Andric     }
192*349cc55cSDimitry Andric   }
193*349cc55cSDimitry Andric 
194*349cc55cSDimitry Andric   if ((V >> 8) & 0x1) {
195*349cc55cSDimitry Andric     O << LS;
196*349cc55cSDimitry Andric     printRegName(O, CSKY::R28);
197*349cc55cSDimitry Andric   }
198*349cc55cSDimitry Andric }
199*349cc55cSDimitry Andric 
200fe6060f1SDimitry Andric const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) {
201fe6060f1SDimitry Andric   return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName
202fe6060f1SDimitry Andric                                              : CSKY::ABIRegAltName);
203fe6060f1SDimitry Andric }
204