1 //===-- VEInstPrinter.cpp - Convert VE MCInst to assembly syntax -----------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class prints an VE MCInst to a .s file.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "VEInstPrinter.h"
14 #include "VE.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCInst.h"
17 #include "llvm/MC/MCRegisterInfo.h"
18 #include "llvm/MC/MCSubtargetInfo.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/Support/raw_ostream.h"
21 
22 using namespace llvm;
23 
24 #define DEBUG_TYPE "ve-asmprinter"
25 
26 // The generated AsmMatcher VEGenAsmWriter uses "VE" as the target
27 // namespace.
28 namespace llvm {
29 namespace VE {
30 using namespace VE;
31 }
32 } // namespace llvm
33 
34 #define GET_INSTRUCTION_NAME
35 #define PRINT_ALIAS_INSTR
36 #include "VEGenAsmWriter.inc"
37 
printRegName(raw_ostream & OS,unsigned RegNo) const38 void VEInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
39   // Generic registers have identical register name among register classes.
40   unsigned AltIdx = VE::AsmName;
41   // Misc registers have each own name, so no use alt-names.
42   if (MRI.getRegClass(VE::MISCRegClassID).contains(RegNo))
43     AltIdx = VE::NoRegAltName;
44   OS << '%' << getRegisterName(RegNo, AltIdx);
45 }
46 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & OS)47 void VEInstPrinter::printInst(const MCInst *MI, uint64_t Address,
48                               StringRef Annot, const MCSubtargetInfo &STI,
49                               raw_ostream &OS) {
50   if (!printAliasInstr(MI, Address, STI, OS))
51     printInstruction(MI, Address, STI, OS);
52   printAnnotation(OS, Annot);
53 }
54 
printOperand(const MCInst * MI,int OpNum,const MCSubtargetInfo & STI,raw_ostream & O)55 void VEInstPrinter::printOperand(const MCInst *MI, int OpNum,
56                                  const MCSubtargetInfo &STI, raw_ostream &O) {
57   const MCOperand &MO = MI->getOperand(OpNum);
58 
59   if (MO.isReg()) {
60     printRegName(O, MO.getReg());
61     return;
62   }
63 
64   if (MO.isImm()) {
65     switch (MI->getOpcode()) {
66     default:
67       // Expects signed 32bit literals
68       int32_t TruncatedImm = static_cast<int32_t>(MO.getImm());
69       O << TruncatedImm;
70       return;
71     }
72   }
73 
74   assert(MO.isExpr() && "Unknown operand kind in printOperand");
75   MO.getExpr()->print(O, &MAI);
76 }
77 
printMemASXOperand(const MCInst * MI,int OpNum,const MCSubtargetInfo & STI,raw_ostream & O,const char * Modifier)78 void VEInstPrinter::printMemASXOperand(const MCInst *MI, int OpNum,
79                                        const MCSubtargetInfo &STI,
80                                        raw_ostream &O, const char *Modifier) {
81   // If this is an ADD operand, emit it like normal operands.
82   if (Modifier && !strcmp(Modifier, "arith")) {
83     printOperand(MI, OpNum, STI, O);
84     O << ", ";
85     printOperand(MI, OpNum + 1, STI, O);
86     return;
87   }
88 
89   if (MI->getOperand(OpNum + 2).isImm() &&
90       MI->getOperand(OpNum + 2).getImm() == 0) {
91     // don't print "+0"
92   } else {
93     printOperand(MI, OpNum + 2, STI, O);
94   }
95   if (MI->getOperand(OpNum + 1).isImm() &&
96       MI->getOperand(OpNum + 1).getImm() == 0 &&
97       MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
98     if (MI->getOperand(OpNum + 2).isImm() &&
99         MI->getOperand(OpNum + 2).getImm() == 0) {
100       O << "0";
101     } else {
102       // don't print "+0,+0"
103     }
104   } else {
105     O << "(";
106     if (MI->getOperand(OpNum + 1).isImm() &&
107         MI->getOperand(OpNum + 1).getImm() == 0) {
108       // don't print "+0"
109     } else {
110       printOperand(MI, OpNum + 1, STI, O);
111     }
112     if (MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
113       // don't print "+0"
114     } else {
115       O << ", ";
116       printOperand(MI, OpNum, STI, O);
117     }
118     O << ")";
119   }
120 }
121 
printMemASOperandASX(const MCInst * MI,int OpNum,const MCSubtargetInfo & STI,raw_ostream & O,const char * Modifier)122 void VEInstPrinter::printMemASOperandASX(const MCInst *MI, int OpNum,
123                                          const MCSubtargetInfo &STI,
124                                          raw_ostream &O, const char *Modifier) {
125   // If this is an ADD operand, emit it like normal operands.
126   if (Modifier && !strcmp(Modifier, "arith")) {
127     printOperand(MI, OpNum, STI, O);
128     O << ", ";
129     printOperand(MI, OpNum + 1, STI, O);
130     return;
131   }
132 
133   if (MI->getOperand(OpNum + 1).isImm() &&
134       MI->getOperand(OpNum + 1).getImm() == 0) {
135     // don't print "+0"
136   } else {
137     printOperand(MI, OpNum + 1, STI, O);
138   }
139   if (MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
140     if (MI->getOperand(OpNum + 1).isImm() &&
141         MI->getOperand(OpNum + 1).getImm() == 0) {
142       O << "0";
143     } else {
144       // don't print "(0)"
145     }
146   } else {
147     O << "(, ";
148     printOperand(MI, OpNum, STI, O);
149     O << ")";
150   }
151 }
152 
printMemASOperandRRM(const MCInst * MI,int OpNum,const MCSubtargetInfo & STI,raw_ostream & O,const char * Modifier)153 void VEInstPrinter::printMemASOperandRRM(const MCInst *MI, int OpNum,
154                                          const MCSubtargetInfo &STI,
155                                          raw_ostream &O, const char *Modifier) {
156   // If this is an ADD operand, emit it like normal operands.
157   if (Modifier && !strcmp(Modifier, "arith")) {
158     printOperand(MI, OpNum, STI, O);
159     O << ", ";
160     printOperand(MI, OpNum + 1, STI, O);
161     return;
162   }
163 
164   if (MI->getOperand(OpNum + 1).isImm() &&
165       MI->getOperand(OpNum + 1).getImm() == 0) {
166     // don't print "+0"
167   } else {
168     printOperand(MI, OpNum + 1, STI, O);
169   }
170   if (MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
171     if (MI->getOperand(OpNum + 1).isImm() &&
172         MI->getOperand(OpNum + 1).getImm() == 0) {
173       O << "0";
174     } else {
175       // don't print "(0)"
176     }
177   } else {
178     O << "(";
179     printOperand(MI, OpNum, STI, O);
180     O << ")";
181   }
182 }
183 
printMemASOperandHM(const MCInst * MI,int OpNum,const MCSubtargetInfo & STI,raw_ostream & O,const char * Modifier)184 void VEInstPrinter::printMemASOperandHM(const MCInst *MI, int OpNum,
185                                         const MCSubtargetInfo &STI,
186                                         raw_ostream &O, const char *Modifier) {
187   // If this is an ADD operand, emit it like normal operands.
188   if (Modifier && !strcmp(Modifier, "arith")) {
189     printOperand(MI, OpNum, STI, O);
190     O << ", ";
191     printOperand(MI, OpNum + 1, STI, O);
192     return;
193   }
194 
195   if (MI->getOperand(OpNum + 1).isImm() &&
196       MI->getOperand(OpNum + 1).getImm() == 0) {
197     // don't print "+0"
198   } else {
199     printOperand(MI, OpNum + 1, STI, O);
200   }
201   O << "(";
202   if (MI->getOperand(OpNum).isReg())
203     printOperand(MI, OpNum, STI, O);
204   O << ")";
205 }
206 
printMImmOperand(const MCInst * MI,int OpNum,const MCSubtargetInfo & STI,raw_ostream & O)207 void VEInstPrinter::printMImmOperand(const MCInst *MI, int OpNum,
208                                      const MCSubtargetInfo &STI,
209                                      raw_ostream &O) {
210   int MImm = (int)MI->getOperand(OpNum).getImm() & 0x7f;
211   if (MImm > 63)
212     O << "(" << MImm - 64 << ")0";
213   else
214     O << "(" << MImm << ")1";
215 }
216 
printCCOperand(const MCInst * MI,int OpNum,const MCSubtargetInfo & STI,raw_ostream & O)217 void VEInstPrinter::printCCOperand(const MCInst *MI, int OpNum,
218                                    const MCSubtargetInfo &STI, raw_ostream &O) {
219   int CC = (int)MI->getOperand(OpNum).getImm();
220   O << VECondCodeToString((VECC::CondCode)CC);
221 }
222 
printRDOperand(const MCInst * MI,int OpNum,const MCSubtargetInfo & STI,raw_ostream & O)223 void VEInstPrinter::printRDOperand(const MCInst *MI, int OpNum,
224                                    const MCSubtargetInfo &STI, raw_ostream &O) {
225   int RD = (int)MI->getOperand(OpNum).getImm();
226   O << VERDToString((VERD::RoundingMode)RD);
227 }
228