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#define GET_INSTRUCTION_NAME
27#define PRINT_ALIAS_INSTR
28#include "VEGenAsmWriter.inc"
29
30void VEInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) 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(Reg))
35    AltIdx = VE::NoRegAltName;
36  OS << '%' << getRegisterName(Reg, AltIdx);
37}
38
39void 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
47void 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
67void 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
111void 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
142void 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
173void 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
196void 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
206void 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
212void 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