1//===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This class prints an Lanai MCInst to a .s file. 11// 12//===----------------------------------------------------------------------===// 13 14#include "LanaiInstPrinter.h" 15#include "Lanai.h" 16#include "MCTargetDesc/LanaiMCExpr.h" 17#include "llvm/MC/MCAsmInfo.h" 18#include "llvm/MC/MCExpr.h" 19#include "llvm/MC/MCInst.h" 20#include "llvm/MC/MCSymbol.h" 21#include "llvm/Support/ErrorHandling.h" 22#include "llvm/Support/FormattedStream.h" 23 24using namespace llvm; 25 26#define DEBUG_TYPE "asm-printer" 27 28// Include the auto-generated portion of the assembly writer. 29#define PRINT_ALIAS_INSTR 30#include "LanaiGenAsmWriter.inc" 31 32void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 33 OS << StringRef(getRegisterName(RegNo)).lower(); 34} 35 36bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 37 StringRef Alias, unsigned OpNo0, 38 unsigned OpNo1) { 39 OS << "\t" << Alias << " "; 40 printOperand(MI, OpNo0, OS); 41 OS << ", "; 42 printOperand(MI, OpNo1, OS); 43 return true; 44} 45 46static bool usesGivenOffset(const MCInst *MI, int AddOffset) { 47 unsigned AluCode = MI->getOperand(3).getImm(); 48 return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD && 49 (MI->getOperand(2).getImm() == AddOffset || 50 MI->getOperand(2).getImm() == -AddOffset); 51} 52 53static bool isPreIncrementForm(const MCInst *MI, int AddOffset) { 54 unsigned AluCode = MI->getOperand(3).getImm(); 55 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset); 56} 57 58static bool isPostIncrementForm(const MCInst *MI, int AddOffset) { 59 unsigned AluCode = MI->getOperand(3).getImm(); 60 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset); 61} 62 63static StringRef decIncOperator(const MCInst *MI) { 64 if (MI->getOperand(2).getImm() < 0) 65 return "--"; 66 return "++"; 67} 68 69bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI, 70 raw_ostream &OS, 71 StringRef Opcode, 72 int AddOffset) { 73 if (isPreIncrementForm(MI, AddOffset)) { 74 OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%" 75 << getRegisterName(MI->getOperand(1).getReg()) << "], %" 76 << getRegisterName(MI->getOperand(0).getReg()); 77 return true; 78 } 79 if (isPostIncrementForm(MI, AddOffset)) { 80 OS << "\t" << Opcode << "\t[%" 81 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI) 82 << "], %" << getRegisterName(MI->getOperand(0).getReg()); 83 return true; 84 } 85 return false; 86} 87 88bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI, 89 raw_ostream &OS, 90 StringRef Opcode, 91 int AddOffset) { 92 if (isPreIncrementForm(MI, AddOffset)) { 93 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg()) 94 << ", [" << decIncOperator(MI) << "%" 95 << getRegisterName(MI->getOperand(1).getReg()) << "]"; 96 return true; 97 } 98 if (isPostIncrementForm(MI, AddOffset)) { 99 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg()) 100 << ", [%" << getRegisterName(MI->getOperand(1).getReg()) 101 << decIncOperator(MI) << "]"; 102 return true; 103 } 104 return false; 105} 106 107bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) { 108 switch (MI->getOpcode()) { 109 case Lanai::LDW_RI: 110 // ld 4[*%rN], %rX => ld [++imm], %rX 111 // ld -4[*%rN], %rX => ld [--imm], %rX 112 // ld 4[%rN*], %rX => ld [imm++], %rX 113 // ld -4[%rN*], %rX => ld [imm--], %rX 114 return printMemoryLoadIncrement(MI, OS, "ld", 4); 115 case Lanai::LDHs_RI: 116 return printMemoryLoadIncrement(MI, OS, "ld.h", 2); 117 case Lanai::LDHz_RI: 118 return printMemoryLoadIncrement(MI, OS, "uld.h", 2); 119 case Lanai::LDBs_RI: 120 return printMemoryLoadIncrement(MI, OS, "ld.b", 1); 121 case Lanai::LDBz_RI: 122 return printMemoryLoadIncrement(MI, OS, "uld.b", 1); 123 case Lanai::SW_RI: 124 // st %rX, 4[*%rN] => st %rX, [++imm] 125 // st %rX, -4[*%rN] => st %rX, [--imm] 126 // st %rX, 4[%rN*] => st %rX, [imm++] 127 // st %rX, -4[%rN*] => st %rX, [imm--] 128 return printMemoryStoreIncrement(MI, OS, "st", 4); 129 case Lanai::STH_RI: 130 return printMemoryStoreIncrement(MI, OS, "st.h", 2); 131 case Lanai::STB_RI: 132 return printMemoryStoreIncrement(MI, OS, "st.b", 1); 133 default: 134 return false; 135 } 136} 137 138void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 139 StringRef Annotation, 140 const MCSubtargetInfo &STI) { 141 if (!printAlias(MI, OS) && !printAliasInstr(MI, OS)) 142 printInstruction(MI, OS); 143 printAnnotation(OS, Annotation); 144} 145 146void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 147 raw_ostream &OS, const char *Modifier) { 148 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 149 const MCOperand &Op = MI->getOperand(OpNo); 150 if (Op.isReg()) 151 OS << "%" << getRegisterName(Op.getReg()); 152 else if (Op.isImm()) 153 OS << formatHex(Op.getImm()); 154 else { 155 assert(Op.isExpr() && "Expected an expression"); 156 Op.getExpr()->print(OS, &MAI); 157 } 158} 159 160void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo, 161 raw_ostream &OS) { 162 const MCOperand &Op = MI->getOperand(OpNo); 163 if (Op.isImm()) { 164 OS << '[' << formatHex(Op.getImm()) << ']'; 165 } else { 166 // Symbolic operand will be lowered to immediate value by linker 167 assert(Op.isExpr() && "Expected an expression"); 168 OS << '['; 169 Op.getExpr()->print(OS, &MAI); 170 OS << ']'; 171 } 172} 173 174void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo, 175 raw_ostream &OS) { 176 const MCOperand &Op = MI->getOperand(OpNo); 177 if (Op.isImm()) { 178 OS << formatHex(Op.getImm() << 16); 179 } else { 180 // Symbolic operand will be lowered to immediate value by linker 181 assert(Op.isExpr() && "Expected an expression"); 182 Op.getExpr()->print(OS, &MAI); 183 } 184} 185 186void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, 187 raw_ostream &OS) { 188 const MCOperand &Op = MI->getOperand(OpNo); 189 if (Op.isImm()) { 190 OS << formatHex((Op.getImm() << 16) | 0xffff); 191 } else { 192 // Symbolic operand will be lowered to immediate value by linker 193 assert(Op.isExpr() && "Expected an expression"); 194 Op.getExpr()->print(OS, &MAI); 195 } 196} 197 198void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo, 199 raw_ostream &OS) { 200 const MCOperand &Op = MI->getOperand(OpNo); 201 if (Op.isImm()) { 202 OS << formatHex(0xffff0000 | Op.getImm()); 203 } else { 204 // Symbolic operand will be lowered to immediate value by linker 205 assert(Op.isExpr() && "Expected an expression"); 206 Op.getExpr()->print(OS, &MAI); 207 } 208} 209 210static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode, 211 const MCOperand &RegOp) { 212 assert(RegOp.isReg() && "Register operand expected"); 213 OS << "["; 214 if (LPAC::isPreOp(AluCode)) 215 OS << "*"; 216 OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg()); 217 if (LPAC::isPostOp(AluCode)) 218 OS << "*"; 219 OS << "]"; 220} 221 222template <unsigned SizeInBits> 223static void printMemoryImmediateOffset(const MCAsmInfo &MAI, 224 const MCOperand &OffsetOp, 225 raw_ostream &OS) { 226 assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected"); 227 if (OffsetOp.isImm()) { 228 assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated"); 229 OS << OffsetOp.getImm(); 230 } else 231 OffsetOp.getExpr()->print(OS, &MAI); 232} 233 234void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo, 235 raw_ostream &OS, 236 const char *Modifier) { 237 const MCOperand &RegOp = MI->getOperand(OpNo); 238 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); 239 const MCOperand &AluOp = MI->getOperand(OpNo + 2); 240 const unsigned AluCode = AluOp.getImm(); 241 242 // Offset 243 printMemoryImmediateOffset<16>(MAI, OffsetOp, OS); 244 245 // Register 246 printMemoryBaseRegister(OS, AluCode, RegOp); 247} 248 249void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo, 250 raw_ostream &OS, 251 const char *Modifier) { 252 const MCOperand &RegOp = MI->getOperand(OpNo); 253 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); 254 const MCOperand &AluOp = MI->getOperand(OpNo + 2); 255 const unsigned AluCode = AluOp.getImm(); 256 assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected."); 257 258 // [ Base OP Offset ] 259 OS << "["; 260 if (LPAC::isPreOp(AluCode)) 261 OS << "*"; 262 OS << "%" << getRegisterName(RegOp.getReg()); 263 if (LPAC::isPostOp(AluCode)) 264 OS << "*"; 265 OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " "; 266 OS << "%" << getRegisterName(OffsetOp.getReg()); 267 OS << "]"; 268} 269 270void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo, 271 raw_ostream &OS, 272 const char *Modifier) { 273 const MCOperand &RegOp = MI->getOperand(OpNo); 274 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); 275 const MCOperand &AluOp = MI->getOperand(OpNo + 2); 276 const unsigned AluCode = AluOp.getImm(); 277 278 // Offset 279 printMemoryImmediateOffset<10>(MAI, OffsetOp, OS); 280 281 // Register 282 printMemoryBaseRegister(OS, AluCode, RegOp); 283} 284 285void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo, 286 raw_ostream &OS) { 287 LPCC::CondCode CC = 288 static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm()); 289 // Handle the undefined value here for printing so we don't abort(). 290 if (CC >= LPCC::UNKNOWN) 291 OS << "<und>"; 292 else 293 OS << lanaiCondCodeToString(CC); 294} 295 296void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, 297 raw_ostream &OS) { 298 LPCC::CondCode CC = 299 static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm()); 300 // Handle the undefined value here for printing so we don't abort(). 301 if (CC >= LPCC::UNKNOWN) 302 OS << "<und>"; 303 else if (CC != LPCC::ICC_T) 304 OS << "." << lanaiCondCodeToString(CC); 305} 306