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 #define GET_INSTRUCTION_NAME
27 #define PRINT_ALIAS_INSTR
28 #include "VEGenAsmWriter.inc"
29 
30 void VEInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
31   // Generic registers have identical register name among register classes.
32   unsigned AltIdx = VE::AsmName;
33   // Misc registers have each own name, so no use alt-names.
34   if (MRI.getRegClass(VE::MISCRegClassID).contains(RegNo))
35     AltIdx = VE::NoRegAltName;
36   OS << '%' << getRegisterName(RegNo, AltIdx);
37 }
38 
39 void VEInstPrinter::printInst(const MCInst *MI, uint64_t Address,
40                               StringRef Annot, const MCSubtargetInfo &STI,
41                               raw_ostream &OS) {
42   if (!printAliasInstr(MI, Address, STI, OS))
43     printInstruction(MI, Address, STI, OS);
44   printAnnotation(OS, Annot);
45 }
46 
47 void VEInstPrinter::printOperand(const MCInst *MI, int OpNum,
48                                  const MCSubtargetInfo &STI, raw_ostream &O) {
49   const MCOperand &MO = MI->getOperand(OpNum);
50 
51   if (MO.isReg()) {
52     printRegName(O, MO.getReg());
53     return;
54   }
55 
56   if (MO.isImm()) {
57     // Expects signed 32bit literals.
58     int32_t TruncatedImm = static_cast<int32_t>(MO.getImm());
59     O << TruncatedImm;
60     return;
61   }
62 
63   assert(MO.isExpr() && "Unknown operand kind in printOperand");
64   MO.getExpr()->print(O, &MAI);
65 }
66 
67 void VEInstPrinter::printMemASXOperand(const MCInst *MI, int OpNum,
68                                        const MCSubtargetInfo &STI,
69                                        raw_ostream &O, const char *Modifier) {
70   // If this is an ADD operand, emit it like normal operands.
71   if (Modifier && !strcmp(Modifier, "arith")) {
72     printOperand(MI, OpNum, STI, O);
73     O << ", ";
74     printOperand(MI, OpNum + 1, STI, O);
75     return;
76   }
77 
78   if (MI->getOperand(OpNum + 2).isImm() &&
79       MI->getOperand(OpNum + 2).getImm() == 0) {
80     // don't print "+0"
81   } else {
82     printOperand(MI, OpNum + 2, STI, O);
83   }
84   if (MI->getOperand(OpNum + 1).isImm() &&
85       MI->getOperand(OpNum + 1).getImm() == 0 &&
86       MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
87     if (MI->getOperand(OpNum + 2).isImm() &&
88         MI->getOperand(OpNum + 2).getImm() == 0) {
89       O << "0";
90     } else {
91       // don't print "+0,+0"
92     }
93   } else {
94     O << "(";
95     if (MI->getOperand(OpNum + 1).isImm() &&
96         MI->getOperand(OpNum + 1).getImm() == 0) {
97       // don't print "+0"
98     } else {
99       printOperand(MI, OpNum + 1, STI, O);
100     }
101     if (MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
102       // don't print "+0"
103     } else {
104       O << ", ";
105       printOperand(MI, OpNum, STI, O);
106     }
107     O << ")";
108   }
109 }
110 
111 void VEInstPrinter::printMemASOperandASX(const MCInst *MI, int OpNum,
112                                          const MCSubtargetInfo &STI,
113                                          raw_ostream &O, const char *Modifier) {
114   // If this is an ADD operand, emit it like normal operands.
115   if (Modifier && !strcmp(Modifier, "arith")) {
116     printOperand(MI, OpNum, STI, O);
117     O << ", ";
118     printOperand(MI, OpNum + 1, STI, O);
119     return;
120   }
121 
122   if (MI->getOperand(OpNum + 1).isImm() &&
123       MI->getOperand(OpNum + 1).getImm() == 0) {
124     // don't print "+0"
125   } else {
126     printOperand(MI, OpNum + 1, STI, O);
127   }
128   if (MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
129     if (MI->getOperand(OpNum + 1).isImm() &&
130         MI->getOperand(OpNum + 1).getImm() == 0) {
131       O << "0";
132     } else {
133       // don't print "(0)"
134     }
135   } else {
136     O << "(, ";
137     printOperand(MI, OpNum, STI, O);
138     O << ")";
139   }
140 }
141 
142 void VEInstPrinter::printMemASOperandRRM(const MCInst *MI, int OpNum,
143                                          const MCSubtargetInfo &STI,
144                                          raw_ostream &O, const char *Modifier) {
145   // If this is an ADD operand, emit it like normal operands.
146   if (Modifier && !strcmp(Modifier, "arith")) {
147     printOperand(MI, OpNum, STI, O);
148     O << ", ";
149     printOperand(MI, OpNum + 1, STI, O);
150     return;
151   }
152 
153   if (MI->getOperand(OpNum + 1).isImm() &&
154       MI->getOperand(OpNum + 1).getImm() == 0) {
155     // don't print "+0"
156   } else {
157     printOperand(MI, OpNum + 1, STI, O);
158   }
159   if (MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
160     if (MI->getOperand(OpNum + 1).isImm() &&
161         MI->getOperand(OpNum + 1).getImm() == 0) {
162       O << "0";
163     } else {
164       // don't print "(0)"
165     }
166   } else {
167     O << "(";
168     printOperand(MI, OpNum, STI, O);
169     O << ")";
170   }
171 }
172 
173 void VEInstPrinter::printMemASOperandHM(const MCInst *MI, int OpNum,
174                                         const MCSubtargetInfo &STI,
175                                         raw_ostream &O, const char *Modifier) {
176   // If this is an ADD operand, emit it like normal operands.
177   if (Modifier && !strcmp(Modifier, "arith")) {
178     printOperand(MI, OpNum, STI, O);
179     O << ", ";
180     printOperand(MI, OpNum + 1, STI, O);
181     return;
182   }
183 
184   if (MI->getOperand(OpNum + 1).isImm() &&
185       MI->getOperand(OpNum + 1).getImm() == 0) {
186     // don't print "+0"
187   } else {
188     printOperand(MI, OpNum + 1, STI, O);
189   }
190   O << "(";
191   if (MI->getOperand(OpNum).isReg())
192     printOperand(MI, OpNum, STI, O);
193   O << ")";
194 }
195 
196 void VEInstPrinter::printMImmOperand(const MCInst *MI, int OpNum,
197                                      const MCSubtargetInfo &STI,
198                                      raw_ostream &O) {
199   int MImm = (int)MI->getOperand(OpNum).getImm() & 0x7f;
200   if (MImm > 63)
201     O << "(" << MImm - 64 << ")0";
202   else
203     O << "(" << MImm << ")1";
204 }
205 
206 void VEInstPrinter::printCCOperand(const MCInst *MI, int OpNum,
207                                    const MCSubtargetInfo &STI, raw_ostream &O) {
208   int CC = (int)MI->getOperand(OpNum).getImm();
209   O << VECondCodeToString((VECC::CondCode)CC);
210 }
211 
212 void VEInstPrinter::printRDOperand(const MCInst *MI, int OpNum,
213                                    const MCSubtargetInfo &STI, raw_ostream &O) {
214   int RD = (int)MI->getOperand(OpNum).getImm();
215   O << VERDToString((VERD::RoundingMode)RD);
216 }
217