LanaiInstPrinter.cpp revision 360784
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. 10// 11//===----------------------------------------------------------------------===// 12 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" 25 26using namespace llvm; 27 28#define DEBUG_TYPE "asm-printer" 29 30// Include the auto-generated portion of the assembly writer. 31#define PRINT_ALIAS_INSTR 32#include "LanaiGenAsmWriter.inc" 33 34void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 35 OS << StringRef(getRegisterName(RegNo)).lower(); 36} 37 38bool 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; 46} 47 48static 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); 53} 54 55static bool isPreIncrementForm(const MCInst *MI, int AddOffset) { 56 unsigned AluCode = MI->getOperand(3).getImm(); 57 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset); 58} 59 60static bool isPostIncrementForm(const MCInst *MI, int AddOffset) { 61 unsigned AluCode = MI->getOperand(3).getImm(); 62 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset); 63} 64 65static StringRef decIncOperator(const MCInst *MI) { 66 if (MI->getOperand(2).getImm() < 0) 67 return "--"; 68 return "++"; 69} 70 71bool 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; 80 } 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; 86 } 87 return false; 88} 89 90bool 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; 99 } 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; 105 } 106 return false; 107} 108 109bool 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; 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