109467b48Spatrick //===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This class prints an Lanai MCInst to a .s file.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick
1309467b48Spatrick #include "LanaiInstPrinter.h"
1409467b48Spatrick #include "LanaiMCExpr.h"
1509467b48Spatrick #include "LanaiAluCode.h"
1609467b48Spatrick #include "LanaiCondCode.h"
1709467b48Spatrick #include "MCTargetDesc/LanaiMCTargetDesc.h"
1809467b48Spatrick #include "llvm/MC/MCAsmInfo.h"
1909467b48Spatrick #include "llvm/MC/MCExpr.h"
2009467b48Spatrick #include "llvm/MC/MCInst.h"
2109467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
2209467b48Spatrick #include "llvm/MC/MCSymbol.h"
2309467b48Spatrick #include "llvm/Support/ErrorHandling.h"
2409467b48Spatrick #include "llvm/Support/FormattedStream.h"
2509467b48Spatrick
2609467b48Spatrick using namespace llvm;
2709467b48Spatrick
2809467b48Spatrick #define DEBUG_TYPE "asm-printer"
2909467b48Spatrick
3009467b48Spatrick // Include the auto-generated portion of the assembly writer.
3109467b48Spatrick #define PRINT_ALIAS_INSTR
3209467b48Spatrick #include "LanaiGenAsmWriter.inc"
3309467b48Spatrick
printRegName(raw_ostream & OS,MCRegister Reg) const34*d415bd75Srobert void LanaiInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
35*d415bd75Srobert OS << StringRef(getRegisterName(Reg)).lower();
3609467b48Spatrick }
3709467b48Spatrick
printInst(const MCInst * MI,raw_ostream & OS,StringRef Alias,unsigned OpNo0,unsigned OpNo1)3809467b48Spatrick bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
3909467b48Spatrick StringRef Alias, unsigned OpNo0,
4009467b48Spatrick unsigned OpNo1) {
4109467b48Spatrick OS << "\t" << Alias << " ";
4209467b48Spatrick printOperand(MI, OpNo0, OS);
4309467b48Spatrick OS << ", ";
4409467b48Spatrick printOperand(MI, OpNo1, OS);
4509467b48Spatrick return true;
4609467b48Spatrick }
4709467b48Spatrick
usesGivenOffset(const MCInst * MI,int AddOffset)4809467b48Spatrick static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
4909467b48Spatrick unsigned AluCode = MI->getOperand(3).getImm();
5009467b48Spatrick return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
5109467b48Spatrick (MI->getOperand(2).getImm() == AddOffset ||
5209467b48Spatrick MI->getOperand(2).getImm() == -AddOffset);
5309467b48Spatrick }
5409467b48Spatrick
isPreIncrementForm(const MCInst * MI,int AddOffset)5509467b48Spatrick static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
5609467b48Spatrick unsigned AluCode = MI->getOperand(3).getImm();
5709467b48Spatrick return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
5809467b48Spatrick }
5909467b48Spatrick
isPostIncrementForm(const MCInst * MI,int AddOffset)6009467b48Spatrick static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
6109467b48Spatrick unsigned AluCode = MI->getOperand(3).getImm();
6209467b48Spatrick return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
6309467b48Spatrick }
6409467b48Spatrick
decIncOperator(const MCInst * MI)6509467b48Spatrick static StringRef decIncOperator(const MCInst *MI) {
6609467b48Spatrick if (MI->getOperand(2).getImm() < 0)
6709467b48Spatrick return "--";
6809467b48Spatrick return "++";
6909467b48Spatrick }
7009467b48Spatrick
printMemoryLoadIncrement(const MCInst * MI,raw_ostream & OS,StringRef Opcode,int AddOffset)7109467b48Spatrick bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
7209467b48Spatrick raw_ostream &OS,
7309467b48Spatrick StringRef Opcode,
7409467b48Spatrick int AddOffset) {
7509467b48Spatrick if (isPreIncrementForm(MI, AddOffset)) {
7609467b48Spatrick OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
7709467b48Spatrick << getRegisterName(MI->getOperand(1).getReg()) << "], %"
7809467b48Spatrick << getRegisterName(MI->getOperand(0).getReg());
7909467b48Spatrick return true;
8009467b48Spatrick }
8109467b48Spatrick if (isPostIncrementForm(MI, AddOffset)) {
8209467b48Spatrick OS << "\t" << Opcode << "\t[%"
8309467b48Spatrick << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
8409467b48Spatrick << "], %" << getRegisterName(MI->getOperand(0).getReg());
8509467b48Spatrick return true;
8609467b48Spatrick }
8709467b48Spatrick return false;
8809467b48Spatrick }
8909467b48Spatrick
printMemoryStoreIncrement(const MCInst * MI,raw_ostream & OS,StringRef Opcode,int AddOffset)9009467b48Spatrick bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
9109467b48Spatrick raw_ostream &OS,
9209467b48Spatrick StringRef Opcode,
9309467b48Spatrick int AddOffset) {
9409467b48Spatrick if (isPreIncrementForm(MI, AddOffset)) {
9509467b48Spatrick OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
9609467b48Spatrick << ", [" << decIncOperator(MI) << "%"
9709467b48Spatrick << getRegisterName(MI->getOperand(1).getReg()) << "]";
9809467b48Spatrick return true;
9909467b48Spatrick }
10009467b48Spatrick if (isPostIncrementForm(MI, AddOffset)) {
10109467b48Spatrick OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
10209467b48Spatrick << ", [%" << getRegisterName(MI->getOperand(1).getReg())
10309467b48Spatrick << decIncOperator(MI) << "]";
10409467b48Spatrick return true;
10509467b48Spatrick }
10609467b48Spatrick return false;
10709467b48Spatrick }
10809467b48Spatrick
printAlias(const MCInst * MI,raw_ostream & OS)10909467b48Spatrick bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
11009467b48Spatrick switch (MI->getOpcode()) {
11109467b48Spatrick case Lanai::LDW_RI:
11209467b48Spatrick // ld 4[*%rN], %rX => ld [++imm], %rX
11309467b48Spatrick // ld -4[*%rN], %rX => ld [--imm], %rX
11409467b48Spatrick // ld 4[%rN*], %rX => ld [imm++], %rX
11509467b48Spatrick // ld -4[%rN*], %rX => ld [imm--], %rX
11609467b48Spatrick return printMemoryLoadIncrement(MI, OS, "ld", 4);
11709467b48Spatrick case Lanai::LDHs_RI:
11809467b48Spatrick return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
11909467b48Spatrick case Lanai::LDHz_RI:
12009467b48Spatrick return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
12109467b48Spatrick case Lanai::LDBs_RI:
12209467b48Spatrick return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
12309467b48Spatrick case Lanai::LDBz_RI:
12409467b48Spatrick return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
12509467b48Spatrick case Lanai::SW_RI:
12609467b48Spatrick // st %rX, 4[*%rN] => st %rX, [++imm]
12709467b48Spatrick // st %rX, -4[*%rN] => st %rX, [--imm]
12809467b48Spatrick // st %rX, 4[%rN*] => st %rX, [imm++]
12909467b48Spatrick // st %rX, -4[%rN*] => st %rX, [imm--]
13009467b48Spatrick return printMemoryStoreIncrement(MI, OS, "st", 4);
13109467b48Spatrick case Lanai::STH_RI:
13209467b48Spatrick return printMemoryStoreIncrement(MI, OS, "st.h", 2);
13309467b48Spatrick case Lanai::STB_RI:
13409467b48Spatrick return printMemoryStoreIncrement(MI, OS, "st.b", 1);
13509467b48Spatrick default:
13609467b48Spatrick return false;
13709467b48Spatrick }
13809467b48Spatrick }
13909467b48Spatrick
printInst(const MCInst * MI,uint64_t Address,StringRef Annotation,const MCSubtargetInfo &,raw_ostream & OS)14009467b48Spatrick void LanaiInstPrinter::printInst(const MCInst *MI, uint64_t Address,
14109467b48Spatrick StringRef Annotation,
14209467b48Spatrick const MCSubtargetInfo & /*STI*/,
14309467b48Spatrick raw_ostream &OS) {
144097a140dSpatrick if (!printAlias(MI, OS) && !printAliasInstr(MI, Address, OS))
14509467b48Spatrick printInstruction(MI, Address, OS);
14609467b48Spatrick printAnnotation(OS, Annotation);
14709467b48Spatrick }
14809467b48Spatrick
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS,const char * Modifier)14909467b48Spatrick void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
15009467b48Spatrick raw_ostream &OS, const char *Modifier) {
151*d415bd75Srobert assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported");
15209467b48Spatrick const MCOperand &Op = MI->getOperand(OpNo);
15309467b48Spatrick if (Op.isReg())
15409467b48Spatrick OS << "%" << getRegisterName(Op.getReg());
15509467b48Spatrick else if (Op.isImm())
15609467b48Spatrick OS << formatHex(Op.getImm());
15709467b48Spatrick else {
15809467b48Spatrick assert(Op.isExpr() && "Expected an expression");
15909467b48Spatrick Op.getExpr()->print(OS, &MAI);
16009467b48Spatrick }
16109467b48Spatrick }
16209467b48Spatrick
printMemImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)16309467b48Spatrick void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
16409467b48Spatrick raw_ostream &OS) {
16509467b48Spatrick const MCOperand &Op = MI->getOperand(OpNo);
16609467b48Spatrick if (Op.isImm()) {
16709467b48Spatrick OS << '[' << formatHex(Op.getImm()) << ']';
16809467b48Spatrick } else {
16909467b48Spatrick // Symbolic operand will be lowered to immediate value by linker
17009467b48Spatrick assert(Op.isExpr() && "Expected an expression");
17109467b48Spatrick OS << '[';
17209467b48Spatrick Op.getExpr()->print(OS, &MAI);
17309467b48Spatrick OS << ']';
17409467b48Spatrick }
17509467b48Spatrick }
17609467b48Spatrick
printHi16ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)17709467b48Spatrick void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
17809467b48Spatrick raw_ostream &OS) {
17909467b48Spatrick const MCOperand &Op = MI->getOperand(OpNo);
18009467b48Spatrick if (Op.isImm()) {
18109467b48Spatrick OS << formatHex(Op.getImm() << 16);
18209467b48Spatrick } else {
18309467b48Spatrick // Symbolic operand will be lowered to immediate value by linker
18409467b48Spatrick assert(Op.isExpr() && "Expected an expression");
18509467b48Spatrick Op.getExpr()->print(OS, &MAI);
18609467b48Spatrick }
18709467b48Spatrick }
18809467b48Spatrick
printHi16AndImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)18909467b48Spatrick void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
19009467b48Spatrick raw_ostream &OS) {
19109467b48Spatrick const MCOperand &Op = MI->getOperand(OpNo);
19209467b48Spatrick if (Op.isImm()) {
19309467b48Spatrick OS << formatHex((Op.getImm() << 16) | 0xffff);
19409467b48Spatrick } else {
19509467b48Spatrick // Symbolic operand will be lowered to immediate value by linker
19609467b48Spatrick assert(Op.isExpr() && "Expected an expression");
19709467b48Spatrick Op.getExpr()->print(OS, &MAI);
19809467b48Spatrick }
19909467b48Spatrick }
20009467b48Spatrick
printLo16AndImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)20109467b48Spatrick void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
20209467b48Spatrick raw_ostream &OS) {
20309467b48Spatrick const MCOperand &Op = MI->getOperand(OpNo);
20409467b48Spatrick if (Op.isImm()) {
20509467b48Spatrick OS << formatHex(0xffff0000 | Op.getImm());
20609467b48Spatrick } else {
20709467b48Spatrick // Symbolic operand will be lowered to immediate value by linker
20809467b48Spatrick assert(Op.isExpr() && "Expected an expression");
20909467b48Spatrick Op.getExpr()->print(OS, &MAI);
21009467b48Spatrick }
21109467b48Spatrick }
21209467b48Spatrick
printMemoryBaseRegister(raw_ostream & OS,const unsigned AluCode,const MCOperand & RegOp)21309467b48Spatrick static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
21409467b48Spatrick const MCOperand &RegOp) {
21509467b48Spatrick assert(RegOp.isReg() && "Register operand expected");
21609467b48Spatrick OS << "[";
21709467b48Spatrick if (LPAC::isPreOp(AluCode))
21809467b48Spatrick OS << "*";
21909467b48Spatrick OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
22009467b48Spatrick if (LPAC::isPostOp(AluCode))
22109467b48Spatrick OS << "*";
22209467b48Spatrick OS << "]";
22309467b48Spatrick }
22409467b48Spatrick
22509467b48Spatrick template <unsigned SizeInBits>
printMemoryImmediateOffset(const MCAsmInfo & MAI,const MCOperand & OffsetOp,raw_ostream & OS)22609467b48Spatrick static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
22709467b48Spatrick const MCOperand &OffsetOp,
22809467b48Spatrick raw_ostream &OS) {
22909467b48Spatrick assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
23009467b48Spatrick if (OffsetOp.isImm()) {
23109467b48Spatrick assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
23209467b48Spatrick OS << OffsetOp.getImm();
23309467b48Spatrick } else
23409467b48Spatrick OffsetOp.getExpr()->print(OS, &MAI);
23509467b48Spatrick }
23609467b48Spatrick
printMemRiOperand(const MCInst * MI,int OpNo,raw_ostream & OS,const char *)23709467b48Spatrick void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
23809467b48Spatrick raw_ostream &OS,
23909467b48Spatrick const char * /*Modifier*/) {
24009467b48Spatrick const MCOperand &RegOp = MI->getOperand(OpNo);
24109467b48Spatrick const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
24209467b48Spatrick const MCOperand &AluOp = MI->getOperand(OpNo + 2);
24309467b48Spatrick const unsigned AluCode = AluOp.getImm();
24409467b48Spatrick
24509467b48Spatrick // Offset
24609467b48Spatrick printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
24709467b48Spatrick
24809467b48Spatrick // Register
24909467b48Spatrick printMemoryBaseRegister(OS, AluCode, RegOp);
25009467b48Spatrick }
25109467b48Spatrick
printMemRrOperand(const MCInst * MI,int OpNo,raw_ostream & OS,const char *)25209467b48Spatrick void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
25309467b48Spatrick raw_ostream &OS,
25409467b48Spatrick const char * /*Modifier*/) {
25509467b48Spatrick const MCOperand &RegOp = MI->getOperand(OpNo);
25609467b48Spatrick const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
25709467b48Spatrick const MCOperand &AluOp = MI->getOperand(OpNo + 2);
25809467b48Spatrick const unsigned AluCode = AluOp.getImm();
25909467b48Spatrick assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
26009467b48Spatrick
26109467b48Spatrick // [ Base OP Offset ]
26209467b48Spatrick OS << "[";
26309467b48Spatrick if (LPAC::isPreOp(AluCode))
26409467b48Spatrick OS << "*";
26509467b48Spatrick OS << "%" << getRegisterName(RegOp.getReg());
26609467b48Spatrick if (LPAC::isPostOp(AluCode))
26709467b48Spatrick OS << "*";
26809467b48Spatrick OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
26909467b48Spatrick OS << "%" << getRegisterName(OffsetOp.getReg());
27009467b48Spatrick OS << "]";
27109467b48Spatrick }
27209467b48Spatrick
printMemSplsOperand(const MCInst * MI,int OpNo,raw_ostream & OS,const char *)27309467b48Spatrick void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
27409467b48Spatrick raw_ostream &OS,
27509467b48Spatrick const char * /*Modifier*/) {
27609467b48Spatrick const MCOperand &RegOp = MI->getOperand(OpNo);
27709467b48Spatrick const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
27809467b48Spatrick const MCOperand &AluOp = MI->getOperand(OpNo + 2);
27909467b48Spatrick const unsigned AluCode = AluOp.getImm();
28009467b48Spatrick
28109467b48Spatrick // Offset
28209467b48Spatrick printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
28309467b48Spatrick
28409467b48Spatrick // Register
28509467b48Spatrick printMemoryBaseRegister(OS, AluCode, RegOp);
28609467b48Spatrick }
28709467b48Spatrick
printCCOperand(const MCInst * MI,int OpNo,raw_ostream & OS)28809467b48Spatrick void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
28909467b48Spatrick raw_ostream &OS) {
29009467b48Spatrick LPCC::CondCode CC =
29109467b48Spatrick static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
29209467b48Spatrick // Handle the undefined value here for printing so we don't abort().
29309467b48Spatrick if (CC >= LPCC::UNKNOWN)
29409467b48Spatrick OS << "<und>";
29509467b48Spatrick else
29609467b48Spatrick OS << lanaiCondCodeToString(CC);
29709467b48Spatrick }
29809467b48Spatrick
printPredicateOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)29909467b48Spatrick void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
30009467b48Spatrick raw_ostream &OS) {
30109467b48Spatrick LPCC::CondCode CC =
30209467b48Spatrick static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
30309467b48Spatrick // Handle the undefined value here for printing so we don't abort().
30409467b48Spatrick if (CC >= LPCC::UNKNOWN)
30509467b48Spatrick OS << "<und>";
30609467b48Spatrick else if (CC != LPCC::ICC_T)
30709467b48Spatrick OS << "." << lanaiCondCodeToString(CC);
30809467b48Spatrick }
309