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 26 using 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 34 void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 35 OS << StringRef(getRegisterName(RegNo)).lower(); 36 } 37 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; 46 } 47 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); 53 } 54 55 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) { 56 unsigned AluCode = MI->getOperand(3).getImm(); 57 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset); 58 } 59 60 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) { 61 unsigned AluCode = MI->getOperand(3).getImm(); 62 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset); 63 } 64 65 static StringRef decIncOperator(const MCInst *MI) { 66 if (MI->getOperand(2).getImm() < 0) 67 return "--"; 68 return "++"; 69 } 70 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; 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 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; 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 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; 137 } 138 } 139 140 void 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, Address, OS)) 145 printInstruction(MI, Address, OS); 146 printAnnotation(OS, Annotation); 147 } 148 149 void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 150 raw_ostream &OS, const char *Modifier) { 151 assert((Modifier == nullptr || 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 163 void 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 177 void 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 189 void 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 201 void 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 213 static 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 225 template <unsigned SizeInBits> 226 static 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 237 void 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 252 void 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 273 void 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 288 void 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 299 void 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