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