1351278Sdim//===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===// 2351278Sdim// 3351278Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4351278Sdim// See https://llvm.org/LICENSE.txt for license information. 5351278Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6351278Sdim// 7351278Sdim//===----------------------------------------------------------------------===// 8351278Sdim// 9351278Sdim// This class prints an Lanai MCInst to a .s file. 10351278Sdim// 11351278Sdim//===----------------------------------------------------------------------===// 12351278Sdim 13351278Sdim#include "LanaiInstPrinter.h" 14351278Sdim#include "LanaiMCExpr.h" 15351278Sdim#include "LanaiAluCode.h" 16351278Sdim#include "LanaiCondCode.h" 17351278Sdim#include "MCTargetDesc/LanaiMCTargetDesc.h" 18351278Sdim#include "llvm/MC/MCAsmInfo.h" 19351278Sdim#include "llvm/MC/MCExpr.h" 20351278Sdim#include "llvm/MC/MCInst.h" 21351278Sdim#include "llvm/MC/MCRegisterInfo.h" 22351278Sdim#include "llvm/MC/MCSymbol.h" 23351278Sdim#include "llvm/Support/ErrorHandling.h" 24351278Sdim#include "llvm/Support/FormattedStream.h" 25351278Sdim 26351278Sdimusing namespace llvm; 27351278Sdim 28351278Sdim#define DEBUG_TYPE "asm-printer" 29351278Sdim 30351278Sdim// Include the auto-generated portion of the assembly writer. 31351278Sdim#define PRINT_ALIAS_INSTR 32351278Sdim#include "LanaiGenAsmWriter.inc" 33351278Sdim 34351278Sdimvoid LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 35351278Sdim OS << StringRef(getRegisterName(RegNo)).lower(); 36351278Sdim} 37351278Sdim 38351278Sdimbool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 39351278Sdim StringRef Alias, unsigned OpNo0, 40351278Sdim unsigned OpNo1) { 41351278Sdim OS << "\t" << Alias << " "; 42351278Sdim printOperand(MI, OpNo0, OS); 43351278Sdim OS << ", "; 44351278Sdim printOperand(MI, OpNo1, OS); 45351278Sdim return true; 46351278Sdim} 47351278Sdim 48351278Sdimstatic bool usesGivenOffset(const MCInst *MI, int AddOffset) { 49351278Sdim unsigned AluCode = MI->getOperand(3).getImm(); 50351278Sdim return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD && 51351278Sdim (MI->getOperand(2).getImm() == AddOffset || 52351278Sdim MI->getOperand(2).getImm() == -AddOffset); 53351278Sdim} 54351278Sdim 55351278Sdimstatic bool isPreIncrementForm(const MCInst *MI, int AddOffset) { 56351278Sdim unsigned AluCode = MI->getOperand(3).getImm(); 57351278Sdim return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset); 58351278Sdim} 59351278Sdim 60351278Sdimstatic bool isPostIncrementForm(const MCInst *MI, int AddOffset) { 61351278Sdim unsigned AluCode = MI->getOperand(3).getImm(); 62351278Sdim return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset); 63351278Sdim} 64351278Sdim 65351278Sdimstatic StringRef decIncOperator(const MCInst *MI) { 66351278Sdim if (MI->getOperand(2).getImm() < 0) 67351278Sdim return "--"; 68351278Sdim return "++"; 69351278Sdim} 70351278Sdim 71351278Sdimbool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI, 72351278Sdim raw_ostream &OS, 73351278Sdim StringRef Opcode, 74351278Sdim int AddOffset) { 75351278Sdim if (isPreIncrementForm(MI, AddOffset)) { 76351278Sdim OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%" 77351278Sdim << getRegisterName(MI->getOperand(1).getReg()) << "], %" 78351278Sdim << getRegisterName(MI->getOperand(0).getReg()); 79351278Sdim return true; 80351278Sdim } 81351278Sdim if (isPostIncrementForm(MI, AddOffset)) { 82351278Sdim OS << "\t" << Opcode << "\t[%" 83351278Sdim << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI) 84351278Sdim << "], %" << getRegisterName(MI->getOperand(0).getReg()); 85351278Sdim return true; 86351278Sdim } 87351278Sdim return false; 88351278Sdim} 89351278Sdim 90351278Sdimbool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI, 91351278Sdim raw_ostream &OS, 92351278Sdim StringRef Opcode, 93351278Sdim int AddOffset) { 94351278Sdim if (isPreIncrementForm(MI, AddOffset)) { 95351278Sdim OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg()) 96351278Sdim << ", [" << decIncOperator(MI) << "%" 97351278Sdim << getRegisterName(MI->getOperand(1).getReg()) << "]"; 98351278Sdim return true; 99351278Sdim } 100351278Sdim if (isPostIncrementForm(MI, AddOffset)) { 101351278Sdim OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg()) 102351278Sdim << ", [%" << getRegisterName(MI->getOperand(1).getReg()) 103351278Sdim << decIncOperator(MI) << "]"; 104351278Sdim return true; 105351278Sdim } 106351278Sdim return false; 107351278Sdim} 108351278Sdim 109351278Sdimbool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) { 110351278Sdim switch (MI->getOpcode()) { 111351278Sdim case Lanai::LDW_RI: 112351278Sdim // ld 4[*%rN], %rX => ld [++imm], %rX 113351278Sdim // ld -4[*%rN], %rX => ld [--imm], %rX 114351278Sdim // ld 4[%rN*], %rX => ld [imm++], %rX 115351278Sdim // ld -4[%rN*], %rX => ld [imm--], %rX 116351278Sdim return printMemoryLoadIncrement(MI, OS, "ld", 4); 117351278Sdim case Lanai::LDHs_RI: 118351278Sdim return printMemoryLoadIncrement(MI, OS, "ld.h", 2); 119351278Sdim case Lanai::LDHz_RI: 120351278Sdim return printMemoryLoadIncrement(MI, OS, "uld.h", 2); 121351278Sdim case Lanai::LDBs_RI: 122351278Sdim return printMemoryLoadIncrement(MI, OS, "ld.b", 1); 123351278Sdim case Lanai::LDBz_RI: 124351278Sdim return printMemoryLoadIncrement(MI, OS, "uld.b", 1); 125351278Sdim case Lanai::SW_RI: 126351278Sdim // st %rX, 4[*%rN] => st %rX, [++imm] 127351278Sdim // st %rX, -4[*%rN] => st %rX, [--imm] 128351278Sdim // st %rX, 4[%rN*] => st %rX, [imm++] 129351278Sdim // st %rX, -4[%rN*] => st %rX, [imm--] 130351278Sdim return printMemoryStoreIncrement(MI, OS, "st", 4); 131351278Sdim case Lanai::STH_RI: 132351278Sdim return printMemoryStoreIncrement(MI, OS, "st.h", 2); 133351278Sdim case Lanai::STB_RI: 134351278Sdim return printMemoryStoreIncrement(MI, OS, "st.b", 1); 135351278Sdim default: 136351278Sdim return false; 137351278Sdim } 138351278Sdim} 139351278Sdim 140360784Sdimvoid LanaiInstPrinter::printInst(const MCInst *MI, uint64_t Address, 141351278Sdim StringRef Annotation, 142360784Sdim const MCSubtargetInfo & /*STI*/, 143360784Sdim raw_ostream &OS) { 144351278Sdim if (!printAlias(MI, OS) && !printAliasInstr(MI, OS)) 145360784Sdim printInstruction(MI, Address, OS); 146351278Sdim printAnnotation(OS, Annotation); 147351278Sdim} 148351278Sdim 149351278Sdimvoid LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 150351278Sdim raw_ostream &OS, const char *Modifier) { 151351278Sdim assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 152351278Sdim const MCOperand &Op = MI->getOperand(OpNo); 153351278Sdim if (Op.isReg()) 154351278Sdim OS << "%" << getRegisterName(Op.getReg()); 155351278Sdim else if (Op.isImm()) 156351278Sdim OS << formatHex(Op.getImm()); 157351278Sdim else { 158351278Sdim assert(Op.isExpr() && "Expected an expression"); 159351278Sdim Op.getExpr()->print(OS, &MAI); 160351278Sdim } 161351278Sdim} 162351278Sdim 163351278Sdimvoid LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo, 164351278Sdim raw_ostream &OS) { 165351278Sdim const MCOperand &Op = MI->getOperand(OpNo); 166351278Sdim if (Op.isImm()) { 167351278Sdim OS << '[' << formatHex(Op.getImm()) << ']'; 168351278Sdim } else { 169351278Sdim // Symbolic operand will be lowered to immediate value by linker 170351278Sdim assert(Op.isExpr() && "Expected an expression"); 171351278Sdim OS << '['; 172351278Sdim Op.getExpr()->print(OS, &MAI); 173351278Sdim OS << ']'; 174351278Sdim } 175351278Sdim} 176351278Sdim 177351278Sdimvoid LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo, 178351278Sdim raw_ostream &OS) { 179351278Sdim const MCOperand &Op = MI->getOperand(OpNo); 180351278Sdim if (Op.isImm()) { 181351278Sdim OS << formatHex(Op.getImm() << 16); 182351278Sdim } else { 183351278Sdim // Symbolic operand will be lowered to immediate value by linker 184351278Sdim assert(Op.isExpr() && "Expected an expression"); 185351278Sdim Op.getExpr()->print(OS, &MAI); 186351278Sdim } 187351278Sdim} 188351278Sdim 189351278Sdimvoid LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, 190351278Sdim raw_ostream &OS) { 191351278Sdim const MCOperand &Op = MI->getOperand(OpNo); 192351278Sdim if (Op.isImm()) { 193351278Sdim OS << formatHex((Op.getImm() << 16) | 0xffff); 194351278Sdim } else { 195351278Sdim // Symbolic operand will be lowered to immediate value by linker 196351278Sdim assert(Op.isExpr() && "Expected an expression"); 197351278Sdim Op.getExpr()->print(OS, &MAI); 198351278Sdim } 199351278Sdim} 200351278Sdim 201351278Sdimvoid LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo, 202351278Sdim raw_ostream &OS) { 203351278Sdim const MCOperand &Op = MI->getOperand(OpNo); 204351278Sdim if (Op.isImm()) { 205351278Sdim OS << formatHex(0xffff0000 | Op.getImm()); 206351278Sdim } else { 207351278Sdim // Symbolic operand will be lowered to immediate value by linker 208351278Sdim assert(Op.isExpr() && "Expected an expression"); 209351278Sdim Op.getExpr()->print(OS, &MAI); 210351278Sdim } 211351278Sdim} 212351278Sdim 213351278Sdimstatic void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode, 214351278Sdim const MCOperand &RegOp) { 215351278Sdim assert(RegOp.isReg() && "Register operand expected"); 216351278Sdim OS << "["; 217351278Sdim if (LPAC::isPreOp(AluCode)) 218351278Sdim OS << "*"; 219351278Sdim OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg()); 220351278Sdim if (LPAC::isPostOp(AluCode)) 221351278Sdim OS << "*"; 222351278Sdim OS << "]"; 223351278Sdim} 224351278Sdim 225351278Sdimtemplate <unsigned SizeInBits> 226351278Sdimstatic void printMemoryImmediateOffset(const MCAsmInfo &MAI, 227351278Sdim const MCOperand &OffsetOp, 228351278Sdim raw_ostream &OS) { 229351278Sdim assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected"); 230351278Sdim if (OffsetOp.isImm()) { 231351278Sdim assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated"); 232351278Sdim OS << OffsetOp.getImm(); 233351278Sdim } else 234351278Sdim OffsetOp.getExpr()->print(OS, &MAI); 235351278Sdim} 236351278Sdim 237351278Sdimvoid LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo, 238351278Sdim raw_ostream &OS, 239351278Sdim const char * /*Modifier*/) { 240351278Sdim const MCOperand &RegOp = MI->getOperand(OpNo); 241351278Sdim const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); 242351278Sdim const MCOperand &AluOp = MI->getOperand(OpNo + 2); 243351278Sdim const unsigned AluCode = AluOp.getImm(); 244351278Sdim 245351278Sdim // Offset 246351278Sdim printMemoryImmediateOffset<16>(MAI, OffsetOp, OS); 247351278Sdim 248351278Sdim // Register 249351278Sdim printMemoryBaseRegister(OS, AluCode, RegOp); 250351278Sdim} 251351278Sdim 252351278Sdimvoid LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo, 253351278Sdim raw_ostream &OS, 254351278Sdim const char * /*Modifier*/) { 255351278Sdim const MCOperand &RegOp = MI->getOperand(OpNo); 256351278Sdim const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); 257351278Sdim const MCOperand &AluOp = MI->getOperand(OpNo + 2); 258351278Sdim const unsigned AluCode = AluOp.getImm(); 259351278Sdim assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected."); 260351278Sdim 261351278Sdim // [ Base OP Offset ] 262351278Sdim OS << "["; 263351278Sdim if (LPAC::isPreOp(AluCode)) 264351278Sdim OS << "*"; 265351278Sdim OS << "%" << getRegisterName(RegOp.getReg()); 266351278Sdim if (LPAC::isPostOp(AluCode)) 267351278Sdim OS << "*"; 268351278Sdim OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " "; 269351278Sdim OS << "%" << getRegisterName(OffsetOp.getReg()); 270351278Sdim OS << "]"; 271351278Sdim} 272351278Sdim 273351278Sdimvoid LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo, 274351278Sdim raw_ostream &OS, 275351278Sdim const char * /*Modifier*/) { 276351278Sdim const MCOperand &RegOp = MI->getOperand(OpNo); 277351278Sdim const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); 278351278Sdim const MCOperand &AluOp = MI->getOperand(OpNo + 2); 279351278Sdim const unsigned AluCode = AluOp.getImm(); 280351278Sdim 281351278Sdim // Offset 282351278Sdim printMemoryImmediateOffset<10>(MAI, OffsetOp, OS); 283351278Sdim 284351278Sdim // Register 285351278Sdim printMemoryBaseRegister(OS, AluCode, RegOp); 286351278Sdim} 287351278Sdim 288351278Sdimvoid LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo, 289351278Sdim raw_ostream &OS) { 290351278Sdim LPCC::CondCode CC = 291351278Sdim static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm()); 292351278Sdim // Handle the undefined value here for printing so we don't abort(). 293351278Sdim if (CC >= LPCC::UNKNOWN) 294351278Sdim OS << "<und>"; 295351278Sdim else 296351278Sdim OS << lanaiCondCodeToString(CC); 297351278Sdim} 298351278Sdim 299351278Sdimvoid LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, 300351278Sdim raw_ostream &OS) { 301351278Sdim LPCC::CondCode CC = 302351278Sdim static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm()); 303351278Sdim // Handle the undefined value here for printing so we don't abort(). 304351278Sdim if (CC >= LPCC::UNKNOWN) 305351278Sdim OS << "<und>"; 306351278Sdim else if (CC != LPCC::ICC_T) 307351278Sdim OS << "." << lanaiCondCodeToString(CC); 308351278Sdim} 309