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" 13*81ad6265SDimitry Andric #include "MCTargetDesc/CSKYBaseInfo.h" 14*81ad6265SDimitry Andric #include "MCTargetDesc/CSKYMCExpr.h" 15*81ad6265SDimitry 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" 20*81ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 21fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 22*81ad6265SDimitry 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" 26*81ad6265SDimitry 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 } 63*81ad6265SDimitry Andric if (Opt == "debug") { 64*81ad6265SDimitry Andric DebugFlag = true; 65*81ad6265SDimitry Andric return true; 66*81ad6265SDimitry Andric } 67*81ad6265SDimitry Andric if (Opt == "abi-names") { 68*81ad6265SDimitry Andric ABIRegNames = true; 69*81ad6265SDimitry Andric return true; 70*81ad6265SDimitry 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 85fe6060f1SDimitry Andric void CSKYInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { 86*81ad6265SDimitry Andric if (PrintBranchImmAsAddress) 87*81ad6265SDimitry Andric O << getRegisterName(RegNo, ABIRegNames ? CSKY::ABIRegAltName 88*81ad6265SDimitry Andric : CSKY::NoRegAltName); 89*81ad6265SDimitry Andric else 90fe6060f1SDimitry Andric O << getRegisterName(RegNo); 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()) { 107*81ad6265SDimitry Andric unsigned Reg = MO.getReg(); 108*81ad6265SDimitry Andric bool useABIName = false; 109*81ad6265SDimitry Andric if (PrintBranchImmAsAddress) 110*81ad6265SDimitry Andric useABIName = ABIRegNames; 111fe6060f1SDimitry Andric else 112*81ad6265SDimitry Andric useABIName = !ArchRegNames; 113*81ad6265SDimitry Andric 114*81ad6265SDimitry Andric if (Reg == CSKY::C) 115*81ad6265SDimitry Andric O << ""; 116*81ad6265SDimitry Andric else if (STI.getFeatureBits()[CSKY::FeatureJAVA]) { 117*81ad6265SDimitry Andric if (Reg == CSKY::R23) 118*81ad6265SDimitry Andric O << (useABIName ? "fp" : "r23"); 119*81ad6265SDimitry Andric else if (Reg == CSKY::R24) 120*81ad6265SDimitry Andric O << (useABIName ? "top" : "r24"); 121*81ad6265SDimitry Andric else if (Reg == CSKY::R25) 122*81ad6265SDimitry Andric O << (useABIName ? "bsp" : "r25"); 123*81ad6265SDimitry Andric else 124*81ad6265SDimitry Andric printRegName(O, Reg); 125*81ad6265SDimitry Andric } else 126*81ad6265SDimitry Andric printRegName(O, Reg); 127*81ad6265SDimitry Andric 128fe6060f1SDimitry Andric return; 129fe6060f1SDimitry Andric } 130fe6060f1SDimitry Andric 131fe6060f1SDimitry Andric if (MO.isImm()) { 132*81ad6265SDimitry Andric uint64_t TSFlags = MII.get(MI->getOpcode()).TSFlags; 133*81ad6265SDimitry Andric 134*81ad6265SDimitry Andric if (((TSFlags & CSKYII::AddrModeMask) != CSKYII::AddrModeNone) && 135*81ad6265SDimitry Andric PrintBranchImmAsAddress) 136*81ad6265SDimitry Andric O << formatHex(MO.getImm()); 137*81ad6265SDimitry Andric else 138*81ad6265SDimitry 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 200*81ad6265SDimitry Andric void CSKYInstPrinter::printPSRFlag(const MCInst *MI, unsigned OpNo, 201*81ad6265SDimitry Andric const MCSubtargetInfo &STI, raw_ostream &O) { 202*81ad6265SDimitry Andric auto V = MI->getOperand(OpNo).getImm(); 203*81ad6265SDimitry Andric 204*81ad6265SDimitry Andric ListSeparator LS; 205*81ad6265SDimitry Andric 206*81ad6265SDimitry Andric if ((V >> 3) & 0x1) 207*81ad6265SDimitry Andric O << LS << "ee"; 208*81ad6265SDimitry Andric if ((V >> 2) & 0x1) 209*81ad6265SDimitry Andric O << LS << "ie"; 210*81ad6265SDimitry Andric if ((V >> 1) & 0x1) 211*81ad6265SDimitry Andric O << LS << "fe"; 212*81ad6265SDimitry Andric if ((V >> 0) & 0x1) 213*81ad6265SDimitry Andric O << LS << "af"; 214*81ad6265SDimitry Andric } 215*81ad6265SDimitry 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 263fe6060f1SDimitry Andric const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) { 264fe6060f1SDimitry Andric return getRegisterName(RegNo, 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