LanaiInstPrinter.cpp revision 360660
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, 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); 146} 147 148void 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); 159 } 160} 161 162void 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 << ']'; 173 } 174} 175 176void 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); 185 } 186} 187 188void 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); 197 } 198} 199 200void 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); 209 } 210} 211 212static 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 << "]"; 222} 223 224template <unsigned SizeInBits> 225static 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); 234} 235 236void 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(); 243 244 // Offset 245 printMemoryImmediateOffset<16>(MAI, OffsetOp, OS); 246 247 // Register 248 printMemoryBaseRegister(OS, AluCode, RegOp); 249} 250 251void 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."); 259 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 << "]"; 270} 271 272void 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(); 279 280 // Offset 281 printMemoryImmediateOffset<10>(MAI, OffsetOp, OS); 282 283 // Register 284 printMemoryBaseRegister(OS, AluCode, RegOp); 285} 286 287void 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); 296} 297 298void 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); 307} 308