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
22using namespace llvm;
23
24#define DEBUG_TYPE "ve-asmprinter"
25
26// The generated AsmMatcher VEGenAsmWriter uses "VE" as the target
27// namespace.
28namespace llvm {
29namespace VE {
30using namespace VE;
31}
32} // namespace llvm
33
34#define GET_INSTRUCTION_NAME
35#define PRINT_ALIAS_INSTR
36#include "VEGenAsmWriter.inc"
37
38void 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
47void 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
55void 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
78void 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
122void 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
153void 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
184void 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
207void 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
217void 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
223void 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