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, 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 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); 159 } 160 } 161 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 << ']'; 173 } 174 } 175 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); 185 } 186 } 187 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); 197 } 198 } 199 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); 209 } 210 } 211 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 << "]"; 222 } 223 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); 234 } 235 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(); 243 244 // Offset 245 printMemoryImmediateOffset<16>(MAI, OffsetOp, OS); 246 247 // Register 248 printMemoryBaseRegister(OS, AluCode, RegOp); 249 } 250 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."); 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 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(); 279 280 // Offset 281 printMemoryImmediateOffset<10>(MAI, OffsetOp, OS); 282 283 // Register 284 printMemoryBaseRegister(OS, AluCode, RegOp); 285 } 286 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); 296 } 297 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); 307 } 308