xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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"
14349cc55cSDimitry 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 
76*04eeddc0SDimitry Andric void CSKYInstPrinter::printFPRRegName(raw_ostream &O, unsigned RegNo) const {
77*04eeddc0SDimitry Andric   if (PrintBranchImmAsAddress)
78*04eeddc0SDimitry Andric     O << getRegisterName(RegNo, CSKY::NoRegAltName);
79*04eeddc0SDimitry Andric   else
80*04eeddc0SDimitry Andric     O << getRegisterName(RegNo);
81*04eeddc0SDimitry Andric }
82*04eeddc0SDimitry Andric 
83fe6060f1SDimitry Andric void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
84fe6060f1SDimitry Andric                                    const MCSubtargetInfo &STI, raw_ostream &O,
85fe6060f1SDimitry Andric                                    const char *Modifier) {
86fe6060f1SDimitry Andric   assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
87fe6060f1SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
88fe6060f1SDimitry Andric 
89fe6060f1SDimitry Andric   if (MO.isReg()) {
90fe6060f1SDimitry Andric     if (MO.getReg() == CSKY::C)
91fe6060f1SDimitry Andric       O << "";
92fe6060f1SDimitry Andric     else
93fe6060f1SDimitry Andric       printRegName(O, MO.getReg());
94fe6060f1SDimitry Andric     return;
95fe6060f1SDimitry Andric   }
96fe6060f1SDimitry Andric 
97fe6060f1SDimitry Andric   if (MO.isImm()) {
98fe6060f1SDimitry Andric     O << formatImm(MO.getImm());
99fe6060f1SDimitry Andric     return;
100fe6060f1SDimitry Andric   }
101fe6060f1SDimitry Andric 
102fe6060f1SDimitry Andric   assert(MO.isExpr() && "Unknown operand kind in printOperand");
103fe6060f1SDimitry Andric   MO.getExpr()->print(O, &MAI);
104fe6060f1SDimitry Andric }
105fe6060f1SDimitry Andric 
106349cc55cSDimitry Andric void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo,
107349cc55cSDimitry Andric                                       const MCSubtargetInfo &STI,
108349cc55cSDimitry Andric                                       raw_ostream &O) {
109349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
110349cc55cSDimitry Andric 
111349cc55cSDimitry Andric   O << "[";
112349cc55cSDimitry Andric   if (MO.isImm())
113349cc55cSDimitry Andric     O << MO.getImm();
114349cc55cSDimitry Andric   else
115349cc55cSDimitry Andric     MO.getExpr()->print(O, &MAI);
116349cc55cSDimitry Andric   O << "]";
117349cc55cSDimitry Andric }
118349cc55cSDimitry Andric 
119349cc55cSDimitry Andric void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address,
120349cc55cSDimitry Andric                                      unsigned OpNo, const MCSubtargetInfo &STI,
121349cc55cSDimitry Andric                                      raw_ostream &O) {
122349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
123349cc55cSDimitry Andric 
124349cc55cSDimitry Andric   if (MO.isImm()) {
125349cc55cSDimitry Andric     if (PrintBranchImmAsAddress) {
126349cc55cSDimitry Andric       uint64_t Target = Address + MO.getImm();
127349cc55cSDimitry Andric       Target &= 0xfffffffc;
128349cc55cSDimitry Andric       O << formatHex(Target);
129349cc55cSDimitry Andric     } else {
130349cc55cSDimitry Andric       O << MO.getImm();
131349cc55cSDimitry Andric     }
132349cc55cSDimitry Andric     return;
133349cc55cSDimitry Andric   }
134349cc55cSDimitry Andric 
135349cc55cSDimitry Andric   assert(MO.isExpr() && "Unknown operand kind in printConstpool");
136349cc55cSDimitry Andric 
137349cc55cSDimitry Andric   O << "[";
138349cc55cSDimitry Andric   MO.getExpr()->print(O, &MAI);
139349cc55cSDimitry Andric   O << "]";
140349cc55cSDimitry Andric }
141349cc55cSDimitry Andric 
142349cc55cSDimitry Andric void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address,
143349cc55cSDimitry Andric                                              unsigned OpNo,
144349cc55cSDimitry Andric                                              const MCSubtargetInfo &STI,
145349cc55cSDimitry Andric                                              raw_ostream &O) {
146349cc55cSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
147349cc55cSDimitry Andric   if (!MO.isImm()) {
148349cc55cSDimitry Andric     return printOperand(MI, OpNo, STI, O);
149349cc55cSDimitry Andric   }
150349cc55cSDimitry Andric 
151349cc55cSDimitry Andric   if (PrintBranchImmAsAddress) {
152349cc55cSDimitry Andric     uint64_t Target = Address + MO.getImm();
153349cc55cSDimitry Andric     Target &= 0xffffffff;
154349cc55cSDimitry Andric     O << formatHex(Target);
155349cc55cSDimitry Andric   } else {
156349cc55cSDimitry Andric     O << MO.getImm();
157349cc55cSDimitry Andric   }
158349cc55cSDimitry Andric }
159349cc55cSDimitry Andric 
160349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum,
161349cc55cSDimitry Andric                                        const MCSubtargetInfo &STI,
162349cc55cSDimitry Andric                                        raw_ostream &O) {
163349cc55cSDimitry Andric   printRegName(O, MI->getOperand(OpNum).getReg());
164349cc55cSDimitry Andric   O << "-";
165349cc55cSDimitry Andric   printRegName(O, MI->getOperand(OpNum + 1).getReg());
166349cc55cSDimitry Andric }
167349cc55cSDimitry Andric 
168349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
169349cc55cSDimitry Andric                                         const MCSubtargetInfo &STI,
170349cc55cSDimitry Andric                                         raw_ostream &O) {
171349cc55cSDimitry Andric   auto V = MI->getOperand(OpNum).getImm();
172349cc55cSDimitry Andric   ListSeparator LS;
173349cc55cSDimitry Andric 
174349cc55cSDimitry Andric   if (V & 0xf) {
175349cc55cSDimitry Andric     O << LS;
176349cc55cSDimitry Andric     printRegName(O, CSKY::R4);
177349cc55cSDimitry Andric     auto Offset = (V & 0xf) - 1;
178349cc55cSDimitry Andric     if (Offset) {
179349cc55cSDimitry Andric       O << "-";
180349cc55cSDimitry Andric       printRegName(O, CSKY::R4 + Offset);
181349cc55cSDimitry Andric     }
182349cc55cSDimitry Andric   }
183349cc55cSDimitry Andric 
184349cc55cSDimitry Andric   if ((V >> 4) & 0x1) {
185349cc55cSDimitry Andric     O << LS;
186349cc55cSDimitry Andric     printRegName(O, CSKY::R15);
187349cc55cSDimitry Andric   }
188349cc55cSDimitry Andric 
189349cc55cSDimitry Andric   if ((V >> 5) & 0x7) {
190349cc55cSDimitry Andric     O << LS;
191349cc55cSDimitry Andric     printRegName(O, CSKY::R16);
192349cc55cSDimitry Andric 
193349cc55cSDimitry Andric     auto Offset = ((V >> 5) & 0x7) - 1;
194349cc55cSDimitry Andric 
195349cc55cSDimitry Andric     if (Offset) {
196349cc55cSDimitry Andric       O << "-";
197349cc55cSDimitry Andric       printRegName(O, CSKY::R16 + Offset);
198349cc55cSDimitry Andric     }
199349cc55cSDimitry Andric   }
200349cc55cSDimitry Andric 
201349cc55cSDimitry Andric   if ((V >> 8) & 0x1) {
202349cc55cSDimitry Andric     O << LS;
203349cc55cSDimitry Andric     printRegName(O, CSKY::R28);
204349cc55cSDimitry Andric   }
205349cc55cSDimitry Andric }
206349cc55cSDimitry Andric 
207fe6060f1SDimitry Andric const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) {
208fe6060f1SDimitry Andric   return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName
209fe6060f1SDimitry Andric                                              : CSKY::ABIRegAltName);
210fe6060f1SDimitry Andric }
211*04eeddc0SDimitry Andric 
212*04eeddc0SDimitry Andric void CSKYInstPrinter::printFPR(const MCInst *MI, unsigned OpNo,
213*04eeddc0SDimitry Andric                                const MCSubtargetInfo &STI, raw_ostream &O) {
214*04eeddc0SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNo);
215*04eeddc0SDimitry Andric   assert(MO.isReg());
216*04eeddc0SDimitry Andric 
217*04eeddc0SDimitry Andric   printFPRRegName(O, MO.getReg());
218*04eeddc0SDimitry Andric }
219