[InstCombine] Signed saturation patterns
[llvm-complete.git] / lib / Target / Lanai / MCTargetDesc / LanaiInstPrinter.cpp
blob0d42612824b4838d97ceb6f3edaefc15d21bcc0f
1 //===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm 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 Lanai MCInst to a .s file.
11 //===----------------------------------------------------------------------===//
13 #include "LanaiInstPrinter.h"
14 #include "LanaiMCExpr.h"
15 #include "LanaiAluCode.h"
16 #include "LanaiCondCode.h"
17 #include "MCTargetDesc/LanaiMCTargetDesc.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/FormattedStream.h"
26 using namespace llvm;
28 #define DEBUG_TYPE "asm-printer"
30 // Include the auto-generated portion of the assembly writer.
31 #define PRINT_ALIAS_INSTR
32 #include "LanaiGenAsmWriter.inc"
34 void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
35 OS << StringRef(getRegisterName(RegNo)).lower();
38 bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
39 StringRef Alias, unsigned OpNo0,
40 unsigned OpNo1) {
41 OS << "\t" << Alias << " ";
42 printOperand(MI, OpNo0, OS);
43 OS << ", ";
44 printOperand(MI, OpNo1, OS);
45 return true;
48 static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
49 unsigned AluCode = MI->getOperand(3).getImm();
50 return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
51 (MI->getOperand(2).getImm() == AddOffset ||
52 MI->getOperand(2).getImm() == -AddOffset);
55 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
56 unsigned AluCode = MI->getOperand(3).getImm();
57 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
60 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
61 unsigned AluCode = MI->getOperand(3).getImm();
62 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
65 static StringRef decIncOperator(const MCInst *MI) {
66 if (MI->getOperand(2).getImm() < 0)
67 return "--";
68 return "++";
71 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
72 raw_ostream &OS,
73 StringRef Opcode,
74 int AddOffset) {
75 if (isPreIncrementForm(MI, AddOffset)) {
76 OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
77 << getRegisterName(MI->getOperand(1).getReg()) << "], %"
78 << getRegisterName(MI->getOperand(0).getReg());
79 return true;
81 if (isPostIncrementForm(MI, AddOffset)) {
82 OS << "\t" << Opcode << "\t[%"
83 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
84 << "], %" << getRegisterName(MI->getOperand(0).getReg());
85 return true;
87 return false;
90 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
91 raw_ostream &OS,
92 StringRef Opcode,
93 int AddOffset) {
94 if (isPreIncrementForm(MI, AddOffset)) {
95 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
96 << ", [" << decIncOperator(MI) << "%"
97 << getRegisterName(MI->getOperand(1).getReg()) << "]";
98 return true;
100 if (isPostIncrementForm(MI, AddOffset)) {
101 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
102 << ", [%" << getRegisterName(MI->getOperand(1).getReg())
103 << decIncOperator(MI) << "]";
104 return true;
106 return false;
109 bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
110 switch (MI->getOpcode()) {
111 case Lanai::LDW_RI:
112 // ld 4[*%rN], %rX => ld [++imm], %rX
113 // ld -4[*%rN], %rX => ld [--imm], %rX
114 // ld 4[%rN*], %rX => ld [imm++], %rX
115 // ld -4[%rN*], %rX => ld [imm--], %rX
116 return printMemoryLoadIncrement(MI, OS, "ld", 4);
117 case Lanai::LDHs_RI:
118 return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
119 case Lanai::LDHz_RI:
120 return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
121 case Lanai::LDBs_RI:
122 return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
123 case Lanai::LDBz_RI:
124 return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
125 case Lanai::SW_RI:
126 // st %rX, 4[*%rN] => st %rX, [++imm]
127 // st %rX, -4[*%rN] => st %rX, [--imm]
128 // st %rX, 4[%rN*] => st %rX, [imm++]
129 // st %rX, -4[%rN*] => st %rX, [imm--]
130 return printMemoryStoreIncrement(MI, OS, "st", 4);
131 case Lanai::STH_RI:
132 return printMemoryStoreIncrement(MI, OS, "st.h", 2);
133 case Lanai::STB_RI:
134 return printMemoryStoreIncrement(MI, OS, "st.b", 1);
135 default:
136 return false;
140 void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
141 StringRef Annotation,
142 const MCSubtargetInfo & /*STI*/) {
143 if (!printAlias(MI, OS) && !printAliasInstr(MI, OS))
144 printInstruction(MI, OS);
145 printAnnotation(OS, Annotation);
148 void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
149 raw_ostream &OS, const char *Modifier) {
150 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
151 const MCOperand &Op = MI->getOperand(OpNo);
152 if (Op.isReg())
153 OS << "%" << getRegisterName(Op.getReg());
154 else if (Op.isImm())
155 OS << formatHex(Op.getImm());
156 else {
157 assert(Op.isExpr() && "Expected an expression");
158 Op.getExpr()->print(OS, &MAI);
162 void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
163 raw_ostream &OS) {
164 const MCOperand &Op = MI->getOperand(OpNo);
165 if (Op.isImm()) {
166 OS << '[' << formatHex(Op.getImm()) << ']';
167 } else {
168 // Symbolic operand will be lowered to immediate value by linker
169 assert(Op.isExpr() && "Expected an expression");
170 OS << '[';
171 Op.getExpr()->print(OS, &MAI);
172 OS << ']';
176 void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
177 raw_ostream &OS) {
178 const MCOperand &Op = MI->getOperand(OpNo);
179 if (Op.isImm()) {
180 OS << formatHex(Op.getImm() << 16);
181 } else {
182 // Symbolic operand will be lowered to immediate value by linker
183 assert(Op.isExpr() && "Expected an expression");
184 Op.getExpr()->print(OS, &MAI);
188 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
189 raw_ostream &OS) {
190 const MCOperand &Op = MI->getOperand(OpNo);
191 if (Op.isImm()) {
192 OS << formatHex((Op.getImm() << 16) | 0xffff);
193 } else {
194 // Symbolic operand will be lowered to immediate value by linker
195 assert(Op.isExpr() && "Expected an expression");
196 Op.getExpr()->print(OS, &MAI);
200 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
201 raw_ostream &OS) {
202 const MCOperand &Op = MI->getOperand(OpNo);
203 if (Op.isImm()) {
204 OS << formatHex(0xffff0000 | Op.getImm());
205 } else {
206 // Symbolic operand will be lowered to immediate value by linker
207 assert(Op.isExpr() && "Expected an expression");
208 Op.getExpr()->print(OS, &MAI);
212 static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
213 const MCOperand &RegOp) {
214 assert(RegOp.isReg() && "Register operand expected");
215 OS << "[";
216 if (LPAC::isPreOp(AluCode))
217 OS << "*";
218 OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
219 if (LPAC::isPostOp(AluCode))
220 OS << "*";
221 OS << "]";
224 template <unsigned SizeInBits>
225 static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
226 const MCOperand &OffsetOp,
227 raw_ostream &OS) {
228 assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
229 if (OffsetOp.isImm()) {
230 assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
231 OS << OffsetOp.getImm();
232 } else
233 OffsetOp.getExpr()->print(OS, &MAI);
236 void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
237 raw_ostream &OS,
238 const char * /*Modifier*/) {
239 const MCOperand &RegOp = MI->getOperand(OpNo);
240 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
241 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
242 const unsigned AluCode = AluOp.getImm();
244 // Offset
245 printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
247 // Register
248 printMemoryBaseRegister(OS, AluCode, RegOp);
251 void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
252 raw_ostream &OS,
253 const char * /*Modifier*/) {
254 const MCOperand &RegOp = MI->getOperand(OpNo);
255 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
256 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
257 const unsigned AluCode = AluOp.getImm();
258 assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
260 // [ Base OP Offset ]
261 OS << "[";
262 if (LPAC::isPreOp(AluCode))
263 OS << "*";
264 OS << "%" << getRegisterName(RegOp.getReg());
265 if (LPAC::isPostOp(AluCode))
266 OS << "*";
267 OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
268 OS << "%" << getRegisterName(OffsetOp.getReg());
269 OS << "]";
272 void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
273 raw_ostream &OS,
274 const char * /*Modifier*/) {
275 const MCOperand &RegOp = MI->getOperand(OpNo);
276 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
277 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
278 const unsigned AluCode = AluOp.getImm();
280 // Offset
281 printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
283 // Register
284 printMemoryBaseRegister(OS, AluCode, RegOp);
287 void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
288 raw_ostream &OS) {
289 LPCC::CondCode CC =
290 static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
291 // Handle the undefined value here for printing so we don't abort().
292 if (CC >= LPCC::UNKNOWN)
293 OS << "<und>";
294 else
295 OS << lanaiCondCodeToString(CC);
298 void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
299 raw_ostream &OS) {
300 LPCC::CondCode CC =
301 static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
302 // Handle the undefined value here for printing so we don't abort().
303 if (CC >= LPCC::UNKNOWN)
304 OS << "<und>";
305 else if (CC != LPCC::ICC_T)
306 OS << "." << lanaiCondCodeToString(CC);