1fe6060f1SDimitry Andric //===-- CSKYInstPrinter.cpp - Convert CSKY MCInst to asm syntax ---------===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // This class prints an CSKY MCInst to a .s file. 10fe6060f1SDimitry Andric // 11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 12fe6060f1SDimitry Andric #include "CSKYInstPrinter.h" 1381ad6265SDimitry Andric #include "MCTargetDesc/CSKYBaseInfo.h" 1481ad6265SDimitry Andric #include "MCTargetDesc/CSKYMCExpr.h" 1581ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 16349cc55cSDimitry Andric #include "llvm/ADT/StringExtras.h" 17fe6060f1SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 18fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h" 19fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h" 2081ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 21fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 2281ad6265SDimitry Andric #include "llvm/MC/MCSection.h" 23fe6060f1SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 24fe6060f1SDimitry Andric #include "llvm/MC/MCSymbol.h" 25fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h" 2681ad6265SDimitry Andric #include "llvm/Support/Debug.h" 27fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 28fe6060f1SDimitry Andric #include "llvm/Support/FormattedStream.h" 29fe6060f1SDimitry Andric 30fe6060f1SDimitry Andric using namespace llvm; 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric #define DEBUG_TYPE "csky-asm-printer" 33fe6060f1SDimitry Andric 34fe6060f1SDimitry Andric // Include the auto-generated portion of the assembly writer. 35fe6060f1SDimitry Andric #define PRINT_ALIAS_INSTR 36fe6060f1SDimitry Andric #include "CSKYGenAsmWriter.inc" 37fe6060f1SDimitry Andric 38fe6060f1SDimitry Andric static cl::opt<bool> 39fe6060f1SDimitry Andric NoAliases("csky-no-aliases", 40fe6060f1SDimitry Andric cl::desc("Disable the emission of assembler pseudo instructions"), 41fe6060f1SDimitry Andric cl::init(false), cl::Hidden); 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric static cl::opt<bool> 44fe6060f1SDimitry Andric ArchRegNames("csky-arch-reg-names", 45fe6060f1SDimitry Andric cl::desc("Print architectural register names rather than the " 46fe6060f1SDimitry Andric "ABI names (such as r14 instead of sp)"), 47fe6060f1SDimitry Andric cl::init(false), cl::Hidden); 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric // The command-line flags above are used by llvm-mc and llc. They can be used by 50fe6060f1SDimitry Andric // `llvm-objdump`, but we override their values here to handle options passed to 51fe6060f1SDimitry Andric // `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to 52fe6060f1SDimitry Andric // be an easier way to allow these options in all these tools, without doing it 53fe6060f1SDimitry Andric // this way. 54fe6060f1SDimitry Andric bool CSKYInstPrinter::applyTargetSpecificCLOption(StringRef Opt) { 55fe6060f1SDimitry Andric if (Opt == "no-aliases") { 56fe6060f1SDimitry Andric NoAliases = true; 57fe6060f1SDimitry Andric return true; 58fe6060f1SDimitry Andric } 59fe6060f1SDimitry Andric if (Opt == "numeric") { 60fe6060f1SDimitry Andric ArchRegNames = true; 61fe6060f1SDimitry Andric return true; 62fe6060f1SDimitry Andric } 6381ad6265SDimitry Andric if (Opt == "debug") { 6481ad6265SDimitry Andric DebugFlag = true; 6581ad6265SDimitry Andric return true; 6681ad6265SDimitry Andric } 6781ad6265SDimitry Andric if (Opt == "abi-names") { 6881ad6265SDimitry Andric ABIRegNames = true; 6981ad6265SDimitry Andric return true; 7081ad6265SDimitry Andric } 71fe6060f1SDimitry Andric 72fe6060f1SDimitry Andric return false; 73fe6060f1SDimitry Andric } 74fe6060f1SDimitry Andric 75fe6060f1SDimitry Andric void CSKYInstPrinter::printInst(const MCInst *MI, uint64_t Address, 76fe6060f1SDimitry Andric StringRef Annot, const MCSubtargetInfo &STI, 77fe6060f1SDimitry Andric raw_ostream &O) { 78fe6060f1SDimitry Andric const MCInst *NewMI = MI; 79fe6060f1SDimitry Andric 80fe6060f1SDimitry Andric if (NoAliases || !printAliasInstr(NewMI, Address, STI, O)) 81fe6060f1SDimitry Andric printInstruction(NewMI, Address, STI, O); 82fe6060f1SDimitry Andric printAnnotation(O, Annot); 83fe6060f1SDimitry Andric } 84fe6060f1SDimitry Andric 85*bdd1243dSDimitry Andric void CSKYInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const { 8681ad6265SDimitry Andric if (PrintBranchImmAsAddress) 87*bdd1243dSDimitry Andric O << getRegisterName(Reg, ABIRegNames ? CSKY::ABIRegAltName 8881ad6265SDimitry Andric : CSKY::NoRegAltName); 8981ad6265SDimitry Andric else 90*bdd1243dSDimitry Andric O << getRegisterName(Reg); 91fe6060f1SDimitry Andric } 92fe6060f1SDimitry Andric 9304eeddc0SDimitry Andric void CSKYInstPrinter::printFPRRegName(raw_ostream &O, unsigned RegNo) const { 9404eeddc0SDimitry Andric if (PrintBranchImmAsAddress) 9504eeddc0SDimitry Andric O << getRegisterName(RegNo, CSKY::NoRegAltName); 9604eeddc0SDimitry Andric else 9704eeddc0SDimitry Andric O << getRegisterName(RegNo); 9804eeddc0SDimitry Andric } 9904eeddc0SDimitry Andric 100fe6060f1SDimitry Andric void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 101fe6060f1SDimitry Andric const MCSubtargetInfo &STI, raw_ostream &O, 102fe6060f1SDimitry Andric const char *Modifier) { 103fe6060f1SDimitry Andric assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 104fe6060f1SDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 105fe6060f1SDimitry Andric 106fe6060f1SDimitry Andric if (MO.isReg()) { 10781ad6265SDimitry Andric unsigned Reg = MO.getReg(); 10881ad6265SDimitry Andric bool useABIName = false; 10981ad6265SDimitry Andric if (PrintBranchImmAsAddress) 11081ad6265SDimitry Andric useABIName = ABIRegNames; 111fe6060f1SDimitry Andric else 11281ad6265SDimitry Andric useABIName = !ArchRegNames; 11381ad6265SDimitry Andric 11481ad6265SDimitry Andric if (Reg == CSKY::C) 11581ad6265SDimitry Andric O << ""; 11681ad6265SDimitry Andric else if (STI.getFeatureBits()[CSKY::FeatureJAVA]) { 11781ad6265SDimitry Andric if (Reg == CSKY::R23) 11881ad6265SDimitry Andric O << (useABIName ? "fp" : "r23"); 11981ad6265SDimitry Andric else if (Reg == CSKY::R24) 12081ad6265SDimitry Andric O << (useABIName ? "top" : "r24"); 12181ad6265SDimitry Andric else if (Reg == CSKY::R25) 12281ad6265SDimitry Andric O << (useABIName ? "bsp" : "r25"); 12381ad6265SDimitry Andric else 12481ad6265SDimitry Andric printRegName(O, Reg); 12581ad6265SDimitry Andric } else 12681ad6265SDimitry Andric printRegName(O, Reg); 12781ad6265SDimitry Andric 128fe6060f1SDimitry Andric return; 129fe6060f1SDimitry Andric } 130fe6060f1SDimitry Andric 131fe6060f1SDimitry Andric if (MO.isImm()) { 13281ad6265SDimitry Andric uint64_t TSFlags = MII.get(MI->getOpcode()).TSFlags; 13381ad6265SDimitry Andric 13481ad6265SDimitry Andric if (((TSFlags & CSKYII::AddrModeMask) != CSKYII::AddrModeNone) && 13581ad6265SDimitry Andric PrintBranchImmAsAddress) 13681ad6265SDimitry Andric O << formatHex(MO.getImm()); 13781ad6265SDimitry Andric else 13881ad6265SDimitry Andric O << MO.getImm(); 139fe6060f1SDimitry Andric return; 140fe6060f1SDimitry Andric } 141fe6060f1SDimitry Andric 142fe6060f1SDimitry Andric assert(MO.isExpr() && "Unknown operand kind in printOperand"); 143fe6060f1SDimitry Andric MO.getExpr()->print(O, &MAI); 144fe6060f1SDimitry Andric } 145fe6060f1SDimitry Andric 146349cc55cSDimitry Andric void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo, 147349cc55cSDimitry Andric const MCSubtargetInfo &STI, 148349cc55cSDimitry Andric raw_ostream &O) { 149349cc55cSDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 150349cc55cSDimitry Andric 151349cc55cSDimitry Andric O << "["; 152349cc55cSDimitry Andric if (MO.isImm()) 153349cc55cSDimitry Andric O << MO.getImm(); 154349cc55cSDimitry Andric else 155349cc55cSDimitry Andric MO.getExpr()->print(O, &MAI); 156349cc55cSDimitry Andric O << "]"; 157349cc55cSDimitry Andric } 158349cc55cSDimitry Andric 159349cc55cSDimitry Andric void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address, 160349cc55cSDimitry Andric unsigned OpNo, const MCSubtargetInfo &STI, 161349cc55cSDimitry Andric raw_ostream &O) { 162349cc55cSDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 163349cc55cSDimitry Andric 164349cc55cSDimitry Andric if (MO.isImm()) { 165349cc55cSDimitry Andric if (PrintBranchImmAsAddress) { 166349cc55cSDimitry Andric uint64_t Target = Address + MO.getImm(); 167349cc55cSDimitry Andric Target &= 0xfffffffc; 168349cc55cSDimitry Andric O << formatHex(Target); 169349cc55cSDimitry Andric } else { 170349cc55cSDimitry Andric O << MO.getImm(); 171349cc55cSDimitry Andric } 172349cc55cSDimitry Andric return; 173349cc55cSDimitry Andric } 174349cc55cSDimitry Andric 175349cc55cSDimitry Andric assert(MO.isExpr() && "Unknown operand kind in printConstpool"); 176349cc55cSDimitry Andric 177349cc55cSDimitry Andric O << "["; 178349cc55cSDimitry Andric MO.getExpr()->print(O, &MAI); 179349cc55cSDimitry Andric O << "]"; 180349cc55cSDimitry Andric } 181349cc55cSDimitry Andric 182349cc55cSDimitry Andric void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address, 183349cc55cSDimitry Andric unsigned OpNo, 184349cc55cSDimitry Andric const MCSubtargetInfo &STI, 185349cc55cSDimitry Andric raw_ostream &O) { 186349cc55cSDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 187349cc55cSDimitry Andric if (!MO.isImm()) { 188349cc55cSDimitry Andric return printOperand(MI, OpNo, STI, O); 189349cc55cSDimitry Andric } 190349cc55cSDimitry Andric 191349cc55cSDimitry Andric if (PrintBranchImmAsAddress) { 192349cc55cSDimitry Andric uint64_t Target = Address + MO.getImm(); 193349cc55cSDimitry Andric Target &= 0xffffffff; 194349cc55cSDimitry Andric O << formatHex(Target); 195349cc55cSDimitry Andric } else { 196349cc55cSDimitry Andric O << MO.getImm(); 197349cc55cSDimitry Andric } 198349cc55cSDimitry Andric } 199349cc55cSDimitry Andric 20081ad6265SDimitry Andric void CSKYInstPrinter::printPSRFlag(const MCInst *MI, unsigned OpNo, 20181ad6265SDimitry Andric const MCSubtargetInfo &STI, raw_ostream &O) { 20281ad6265SDimitry Andric auto V = MI->getOperand(OpNo).getImm(); 20381ad6265SDimitry Andric 20481ad6265SDimitry Andric ListSeparator LS; 20581ad6265SDimitry Andric 20681ad6265SDimitry Andric if ((V >> 3) & 0x1) 20781ad6265SDimitry Andric O << LS << "ee"; 20881ad6265SDimitry Andric if ((V >> 2) & 0x1) 20981ad6265SDimitry Andric O << LS << "ie"; 21081ad6265SDimitry Andric if ((V >> 1) & 0x1) 21181ad6265SDimitry Andric O << LS << "fe"; 21281ad6265SDimitry Andric if ((V >> 0) & 0x1) 21381ad6265SDimitry Andric O << LS << "af"; 21481ad6265SDimitry Andric } 21581ad6265SDimitry Andric 216349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum, 217349cc55cSDimitry Andric const MCSubtargetInfo &STI, 218349cc55cSDimitry Andric raw_ostream &O) { 219349cc55cSDimitry Andric printRegName(O, MI->getOperand(OpNum).getReg()); 220349cc55cSDimitry Andric O << "-"; 221349cc55cSDimitry Andric printRegName(O, MI->getOperand(OpNum + 1).getReg()); 222349cc55cSDimitry Andric } 223349cc55cSDimitry Andric 224349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 225349cc55cSDimitry Andric const MCSubtargetInfo &STI, 226349cc55cSDimitry Andric raw_ostream &O) { 227349cc55cSDimitry Andric auto V = MI->getOperand(OpNum).getImm(); 228349cc55cSDimitry Andric ListSeparator LS; 229349cc55cSDimitry Andric 230349cc55cSDimitry Andric if (V & 0xf) { 231349cc55cSDimitry Andric O << LS; 232349cc55cSDimitry Andric printRegName(O, CSKY::R4); 233349cc55cSDimitry Andric auto Offset = (V & 0xf) - 1; 234349cc55cSDimitry Andric if (Offset) { 235349cc55cSDimitry Andric O << "-"; 236349cc55cSDimitry Andric printRegName(O, CSKY::R4 + Offset); 237349cc55cSDimitry Andric } 238349cc55cSDimitry Andric } 239349cc55cSDimitry Andric 240349cc55cSDimitry Andric if ((V >> 4) & 0x1) { 241349cc55cSDimitry Andric O << LS; 242349cc55cSDimitry Andric printRegName(O, CSKY::R15); 243349cc55cSDimitry Andric } 244349cc55cSDimitry Andric 245349cc55cSDimitry Andric if ((V >> 5) & 0x7) { 246349cc55cSDimitry Andric O << LS; 247349cc55cSDimitry Andric printRegName(O, CSKY::R16); 248349cc55cSDimitry Andric 249349cc55cSDimitry Andric auto Offset = ((V >> 5) & 0x7) - 1; 250349cc55cSDimitry Andric 251349cc55cSDimitry Andric if (Offset) { 252349cc55cSDimitry Andric O << "-"; 253349cc55cSDimitry Andric printRegName(O, CSKY::R16 + Offset); 254349cc55cSDimitry Andric } 255349cc55cSDimitry Andric } 256349cc55cSDimitry Andric 257349cc55cSDimitry Andric if ((V >> 8) & 0x1) { 258349cc55cSDimitry Andric O << LS; 259349cc55cSDimitry Andric printRegName(O, CSKY::R28); 260349cc55cSDimitry Andric } 261349cc55cSDimitry Andric } 262349cc55cSDimitry Andric 263*bdd1243dSDimitry Andric const char *CSKYInstPrinter::getRegisterName(MCRegister Reg) { 264*bdd1243dSDimitry Andric return getRegisterName(Reg, ArchRegNames ? CSKY::NoRegAltName 265fe6060f1SDimitry Andric : CSKY::ABIRegAltName); 266fe6060f1SDimitry Andric } 26704eeddc0SDimitry Andric 26804eeddc0SDimitry Andric void CSKYInstPrinter::printFPR(const MCInst *MI, unsigned OpNo, 26904eeddc0SDimitry Andric const MCSubtargetInfo &STI, raw_ostream &O) { 27004eeddc0SDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 27104eeddc0SDimitry Andric assert(MO.isReg()); 27204eeddc0SDimitry Andric 27304eeddc0SDimitry Andric printFPRRegName(O, MO.getReg()); 27404eeddc0SDimitry Andric } 275