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 
38 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   OS << '%' << getRegisterName(RegNo, AltIdx);
42 }
43 
44 void VEInstPrinter::printInst(const MCInst *MI, uint64_t Address,
45                               StringRef Annot, const MCSubtargetInfo &STI,
46                               raw_ostream &OS) {
47   if (!printAliasInstr(MI, Address, STI, OS))
48     printInstruction(MI, Address, STI, OS);
49   printAnnotation(OS, Annot);
50 }
51 
52 void VEInstPrinter::printOperand(const MCInst *MI, int OpNum,
53                                  const MCSubtargetInfo &STI, raw_ostream &O) {
54   const MCOperand &MO = MI->getOperand(OpNum);
55 
56   if (MO.isReg()) {
57     printRegName(O, MO.getReg());
58     return;
59   }
60 
61   if (MO.isImm()) {
62     switch (MI->getOpcode()) {
63     default:
64       // Expects signed 32bit literals
65       int32_t TruncatedImm = static_cast<int32_t>(MO.getImm());
66       O << TruncatedImm;
67       return;
68     }
69   }
70 
71   assert(MO.isExpr() && "Unknown operand kind in printOperand");
72   MO.getExpr()->print(O, &MAI);
73 }
74 
75 void VEInstPrinter::printMemASXOperand(const MCInst *MI, int OpNum,
76                                        const MCSubtargetInfo &STI,
77                                        raw_ostream &O, const char *Modifier) {
78   // If this is an ADD operand, emit it like normal operands.
79   if (Modifier && !strcmp(Modifier, "arith")) {
80     printOperand(MI, OpNum, STI, O);
81     O << ", ";
82     printOperand(MI, OpNum + 1, STI, O);
83     return;
84   }
85 
86   if (MI->getOperand(OpNum + 2).isImm() &&
87       MI->getOperand(OpNum + 2).getImm() == 0) {
88     // don't print "+0"
89   } else {
90     printOperand(MI, OpNum + 2, STI, O);
91   }
92   if (MI->getOperand(OpNum + 1).isImm() &&
93       MI->getOperand(OpNum + 1).getImm() == 0 &&
94       MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
95     if (MI->getOperand(OpNum + 2).isImm() &&
96         MI->getOperand(OpNum + 2).getImm() == 0) {
97       O << "0";
98     } else {
99       // don't print "+0,+0"
100     }
101   } else {
102     O << "(";
103     if (MI->getOperand(OpNum + 1).isImm() &&
104         MI->getOperand(OpNum + 1).getImm() == 0) {
105       // don't print "+0"
106     } else {
107       printOperand(MI, OpNum + 1, STI, O);
108     }
109     if (MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
110       // don't print "+0"
111     } else {
112       O << ", ";
113       printOperand(MI, OpNum, STI, O);
114     }
115     O << ")";
116   }
117 }
118 
119 void VEInstPrinter::printMemASOperandASX(const MCInst *MI, int OpNum,
120                                          const MCSubtargetInfo &STI,
121                                          raw_ostream &O, const char *Modifier) {
122   // If this is an ADD operand, emit it like normal operands.
123   if (Modifier && !strcmp(Modifier, "arith")) {
124     printOperand(MI, OpNum, STI, O);
125     O << ", ";
126     printOperand(MI, OpNum + 1, STI, O);
127     return;
128   }
129 
130   if (MI->getOperand(OpNum + 1).isImm() &&
131       MI->getOperand(OpNum + 1).getImm() == 0) {
132     // don't print "+0"
133   } else {
134     printOperand(MI, OpNum + 1, STI, O);
135   }
136   if (MI->getOperand(OpNum).isImm() && MI->getOperand(OpNum).getImm() == 0) {
137     if (MI->getOperand(OpNum + 1).isImm() &&
138         MI->getOperand(OpNum + 1).getImm() == 0) {
139       O << "0";
140     } else {
141       // don't print "(0)"
142     }
143   } else {
144     O << "(, ";
145     printOperand(MI, OpNum, STI, O);
146     O << ")";
147   }
148 }
149 
150 void VEInstPrinter::printMemASOperand(const MCInst *MI, int OpNum,
151                                       const MCSubtargetInfo &STI,
152                                       raw_ostream &O, const char *Modifier) {
153   // If this is an ADD operand, emit it like normal operands.
154   if (Modifier && !strcmp(Modifier, "arith")) {
155     printOperand(MI, OpNum, STI, O);
156     O << ", ";
157     printOperand(MI, OpNum + 1, STI, O);
158     return;
159   }
160 
161   const MCOperand &MO = MI->getOperand(OpNum + 1);
162   if (!MO.isImm() || MO.getImm() != 0) {
163     printOperand(MI, OpNum + 1, STI, O);
164   }
165   O << "(";
166   printOperand(MI, OpNum, STI, O);
167   O << ")";
168 }
169 
170 void VEInstPrinter::printMImmOperand(const MCInst *MI, int OpNum,
171                                      const MCSubtargetInfo &STI,
172                                      raw_ostream &O) {
173   int MImm = (int)MI->getOperand(OpNum).getImm() & 0x7f;
174   if (MImm > 63)
175     O << "(" << MImm - 64 << ")0";
176   else
177     O << "(" << MImm << ")1";
178 }
179 
180 void VEInstPrinter::printCCOperand(const MCInst *MI, int OpNum,
181                                    const MCSubtargetInfo &STI, raw_ostream &O) {
182   int CC = (int)MI->getOperand(OpNum).getImm();
183   O << VECondCodeToString((VECC::CondCode)CC);
184 }
185 
186 void VEInstPrinter::printRDOperand(const MCInst *MI, int OpNum,
187                                    const MCSubtargetInfo &STI, raw_ostream &O) {
188   int RD = (int)MI->getOperand(OpNum).getImm();
189   O << VERDToString((VERD::RoundingMode)RD);
190 }
191