LanaiInstPrinter.cpp revision 360784
1262569Simp//===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
2262569Simp//
3262569Simp// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4262569Simp// See https://llvm.org/LICENSE.txt for license information.
5262569Simp// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6262569Simp//
7262569Simp//===----------------------------------------------------------------------===//
8262569Simp//
9262569Simp// This class prints an Lanai MCInst to a .s file.
10262569Simp//
11270864Simp//===----------------------------------------------------------------------===//
12262569Simp
13262569Simp#include "LanaiInstPrinter.h"
14262569Simp#include "LanaiMCExpr.h"
15262569Simp#include "LanaiAluCode.h"
16284090Sian#include "LanaiCondCode.h"
17284090Sian#include "MCTargetDesc/LanaiMCTargetDesc.h"
18284090Sian#include "llvm/MC/MCAsmInfo.h"
19284090Sian#include "llvm/MC/MCExpr.h"
20262569Simp#include "llvm/MC/MCInst.h"
21262569Simp#include "llvm/MC/MCRegisterInfo.h"
22262569Simp#include "llvm/MC/MCSymbol.h"
23262569Simp#include "llvm/Support/ErrorHandling.h"
24262569Simp#include "llvm/Support/FormattedStream.h"
25262569Simp
26262569Simpusing namespace llvm;
27262569Simp
28262569Simp#define DEBUG_TYPE "asm-printer"
29270864Simp
30270864Simp// Include the auto-generated portion of the assembly writer.
31284090Sian#define PRINT_ALIAS_INSTR
32270864Simp#include "LanaiGenAsmWriter.inc"
33270864Simp
34270864Simpvoid LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
35270864Simp  OS << StringRef(getRegisterName(RegNo)).lower();
36270864Simp}
37270864Simp
38270864Simpbool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
39270864Simp                                 StringRef Alias, unsigned OpNo0,
40270864Simp                                 unsigned OpNo1) {
41270864Simp  OS << "\t" << Alias << " ";
42270864Simp  printOperand(MI, OpNo0, OS);
43270864Simp  OS << ", ";
44270864Simp  printOperand(MI, OpNo1, OS);
45270864Simp  return true;
46270864Simp}
47270864Simp
48270864Simpstatic bool usesGivenOffset(const MCInst *MI, int AddOffset) {
49270864Simp  unsigned AluCode = MI->getOperand(3).getImm();
50270864Simp  return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
51270864Simp         (MI->getOperand(2).getImm() == AddOffset ||
52262569Simp          MI->getOperand(2).getImm() == -AddOffset);
53262569Simp}
54262569Simp
55262569Simpstatic bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
56262569Simp  unsigned AluCode = MI->getOperand(3).getImm();
57262569Simp  return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
58262569Simp}
59262569Simp
60262569Simpstatic bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
61262569Simp  unsigned AluCode = MI->getOperand(3).getImm();
62262569Simp  return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
63262569Simp}
64262569Simp
65262569Simpstatic StringRef decIncOperator(const MCInst *MI) {
66270864Simp  if (MI->getOperand(2).getImm() < 0)
67262569Simp    return "--";
68262569Simp  return "++";
69262569Simp}
70262569Simp
71262569Simpbool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
72262569Simp                                                raw_ostream &OS,
73262569Simp                                                StringRef Opcode,
74262569Simp                                                int AddOffset) {
75262569Simp  if (isPreIncrementForm(MI, AddOffset)) {
76270864Simp    OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
77262569Simp       << getRegisterName(MI->getOperand(1).getReg()) << "], %"
78262569Simp       << getRegisterName(MI->getOperand(0).getReg());
79262569Simp    return true;
80262569Simp  }
81270864Simp  if (isPostIncrementForm(MI, AddOffset)) {
82262569Simp    OS << "\t" << Opcode << "\t[%"
83262569Simp       << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
84262569Simp       << "], %" << getRegisterName(MI->getOperand(0).getReg());
85262569Simp    return true;
86270864Simp  }
87262569Simp  return false;
88262569Simp}
89262569Simp
90262569Simpbool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
91262569Simp                                                 raw_ostream &OS,
92262569Simp                                                 StringRef Opcode,
93262569Simp                                                 int AddOffset) {
94270864Simp  if (isPreIncrementForm(MI, AddOffset)) {
95262569Simp    OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
96270864Simp       << ", [" << decIncOperator(MI) << "%"
97270864Simp       << getRegisterName(MI->getOperand(1).getReg()) << "]";
98262569Simp    return true;
99262569Simp  }
100262569Simp  if (isPostIncrementForm(MI, AddOffset)) {
101262569Simp    OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
102270864Simp       << ", [%" << getRegisterName(MI->getOperand(1).getReg())
103270864Simp       << decIncOperator(MI) << "]";
104270864Simp    return true;
105270864Simp  }
106270864Simp  return false;
107262569Simp}
108262569Simp
109270864Simpbool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
110270864Simp  switch (MI->getOpcode()) {
111270864Simp  case Lanai::LDW_RI:
112270864Simp    // ld 4[*%rN], %rX => ld [++imm], %rX
113262569Simp    // ld -4[*%rN], %rX => ld [--imm], %rX
114270864Simp    // ld 4[%rN*], %rX => ld [imm++], %rX
115270864Simp    // ld -4[%rN*], %rX => ld [imm--], %rX
116270864Simp    return printMemoryLoadIncrement(MI, OS, "ld", 4);
117262569Simp  case Lanai::LDHs_RI:
118262569Simp    return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
119262569Simp  case Lanai::LDHz_RI:
120262569Simp    return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
121284090Sian  case Lanai::LDBs_RI:
122284090Sian    return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
123284090Sian  case Lanai::LDBz_RI:
124284090Sian    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;
137  }
138}
139
140void LanaiInstPrinter::printInst(const MCInst *MI, uint64_t Address,
141                                 StringRef Annotation,
142                                 const MCSubtargetInfo & /*STI*/,
143                                 raw_ostream &OS) {
144  if (!printAlias(MI, OS) && !printAliasInstr(MI, OS))
145    printInstruction(MI, Address, OS);
146  printAnnotation(OS, Annotation);
147}
148
149void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
150                                    raw_ostream &OS, const char *Modifier) {
151  assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
152  const MCOperand &Op = MI->getOperand(OpNo);
153  if (Op.isReg())
154    OS << "%" << getRegisterName(Op.getReg());
155  else if (Op.isImm())
156    OS << formatHex(Op.getImm());
157  else {
158    assert(Op.isExpr() && "Expected an expression");
159    Op.getExpr()->print(OS, &MAI);
160  }
161}
162
163void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
164                                          raw_ostream &OS) {
165  const MCOperand &Op = MI->getOperand(OpNo);
166  if (Op.isImm()) {
167    OS << '[' << formatHex(Op.getImm()) << ']';
168  } else {
169    // Symbolic operand will be lowered to immediate value by linker
170    assert(Op.isExpr() && "Expected an expression");
171    OS << '[';
172    Op.getExpr()->print(OS, &MAI);
173    OS << ']';
174  }
175}
176
177void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
178                                           raw_ostream &OS) {
179  const MCOperand &Op = MI->getOperand(OpNo);
180  if (Op.isImm()) {
181    OS << formatHex(Op.getImm() << 16);
182  } else {
183    // Symbolic operand will be lowered to immediate value by linker
184    assert(Op.isExpr() && "Expected an expression");
185    Op.getExpr()->print(OS, &MAI);
186  }
187}
188
189void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
190                                              raw_ostream &OS) {
191  const MCOperand &Op = MI->getOperand(OpNo);
192  if (Op.isImm()) {
193    OS << formatHex((Op.getImm() << 16) | 0xffff);
194  } else {
195    // Symbolic operand will be lowered to immediate value by linker
196    assert(Op.isExpr() && "Expected an expression");
197    Op.getExpr()->print(OS, &MAI);
198  }
199}
200
201void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
202                                              raw_ostream &OS) {
203  const MCOperand &Op = MI->getOperand(OpNo);
204  if (Op.isImm()) {
205    OS << formatHex(0xffff0000 | Op.getImm());
206  } else {
207    // Symbolic operand will be lowered to immediate value by linker
208    assert(Op.isExpr() && "Expected an expression");
209    Op.getExpr()->print(OS, &MAI);
210  }
211}
212
213static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
214                                    const MCOperand &RegOp) {
215  assert(RegOp.isReg() && "Register operand expected");
216  OS << "[";
217  if (LPAC::isPreOp(AluCode))
218    OS << "*";
219  OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
220  if (LPAC::isPostOp(AluCode))
221    OS << "*";
222  OS << "]";
223}
224
225template <unsigned SizeInBits>
226static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
227                                       const MCOperand &OffsetOp,
228                                       raw_ostream &OS) {
229  assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
230  if (OffsetOp.isImm()) {
231    assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
232    OS << OffsetOp.getImm();
233  } else
234    OffsetOp.getExpr()->print(OS, &MAI);
235}
236
237void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
238                                         raw_ostream &OS,
239                                         const char * /*Modifier*/) {
240  const MCOperand &RegOp = MI->getOperand(OpNo);
241  const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
242  const MCOperand &AluOp = MI->getOperand(OpNo + 2);
243  const unsigned AluCode = AluOp.getImm();
244
245  // Offset
246  printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
247
248  // Register
249  printMemoryBaseRegister(OS, AluCode, RegOp);
250}
251
252void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
253                                         raw_ostream &OS,
254                                         const char * /*Modifier*/) {
255  const MCOperand &RegOp = MI->getOperand(OpNo);
256  const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
257  const MCOperand &AluOp = MI->getOperand(OpNo + 2);
258  const unsigned AluCode = AluOp.getImm();
259  assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
260
261  // [ Base OP Offset ]
262  OS << "[";
263  if (LPAC::isPreOp(AluCode))
264    OS << "*";
265  OS << "%" << getRegisterName(RegOp.getReg());
266  if (LPAC::isPostOp(AluCode))
267    OS << "*";
268  OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
269  OS << "%" << getRegisterName(OffsetOp.getReg());
270  OS << "]";
271}
272
273void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
274                                           raw_ostream &OS,
275                                           const char * /*Modifier*/) {
276  const MCOperand &RegOp = MI->getOperand(OpNo);
277  const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
278  const MCOperand &AluOp = MI->getOperand(OpNo + 2);
279  const unsigned AluCode = AluOp.getImm();
280
281  // Offset
282  printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
283
284  // Register
285  printMemoryBaseRegister(OS, AluCode, RegOp);
286}
287
288void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
289                                      raw_ostream &OS) {
290  LPCC::CondCode CC =
291      static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
292  // Handle the undefined value here for printing so we don't abort().
293  if (CC >= LPCC::UNKNOWN)
294    OS << "<und>";
295  else
296    OS << lanaiCondCodeToString(CC);
297}
298
299void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
300                                             raw_ostream &OS) {
301  LPCC::CondCode CC =
302      static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
303  // Handle the undefined value here for printing so we don't abort().
304  if (CC >= LPCC::UNKNOWN)
305    OS << "<und>";
306  else if (CC != LPCC::ICC_T)
307    OS << "." << lanaiCondCodeToString(CC);
308}
309