1 //===-- CSKYInstPrinter.cpp - Convert CSKY 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This class prints an CSKY MCInst to a .s file. 10 // 11 //===----------------------------------------------------------------------===// 12 #include "CSKYInstPrinter.h" 13 #include "MCTargetDesc/CSKYBaseInfo.h" 14 #include "MCTargetDesc/CSKYMCAsmInfo.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/MC/MCAsmInfo.h" 18 #include "llvm/MC/MCExpr.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCInstrInfo.h" 21 #include "llvm/MC/MCRegisterInfo.h" 22 #include "llvm/MC/MCSection.h" 23 #include "llvm/MC/MCSubtargetInfo.h" 24 #include "llvm/MC/MCSymbol.h" 25 #include "llvm/Support/CommandLine.h" 26 #include "llvm/Support/Debug.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/FormattedStream.h" 29 30 using namespace llvm; 31 32 #define DEBUG_TYPE "csky-asm-printer" 33 34 // Include the auto-generated portion of the assembly writer. 35 #define PRINT_ALIAS_INSTR 36 #include "CSKYGenAsmWriter.inc" 37 38 static cl::opt<bool> 39 NoAliases("csky-no-aliases", 40 cl::desc("Disable the emission of assembler pseudo instructions"), 41 cl::init(false), cl::Hidden); 42 43 static cl::opt<bool> 44 ArchRegNames("csky-arch-reg-names", 45 cl::desc("Print architectural register names rather than the " 46 "ABI names (such as r14 instead of sp)"), 47 cl::init(false), cl::Hidden); 48 49 // The command-line flags above are used by llvm-mc and llc. They can be used by 50 // `llvm-objdump`, but we override their values here to handle options passed to 51 // `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to 52 // be an easier way to allow these options in all these tools, without doing it 53 // this way. 54 bool CSKYInstPrinter::applyTargetSpecificCLOption(StringRef Opt) { 55 if (Opt == "no-aliases") { 56 NoAliases = true; 57 return true; 58 } 59 if (Opt == "numeric") { 60 ArchRegNames = true; 61 return true; 62 } 63 if (Opt == "debug") { 64 DebugFlag = true; 65 return true; 66 } 67 if (Opt == "abi-names") { 68 ABIRegNames = true; 69 return true; 70 } 71 72 return false; 73 } 74 75 void CSKYInstPrinter::printInst(const MCInst *MI, uint64_t Address, 76 StringRef Annot, const MCSubtargetInfo &STI, 77 raw_ostream &O) { 78 const MCInst *NewMI = MI; 79 80 if (NoAliases || !printAliasInstr(NewMI, Address, STI, O)) 81 printInstruction(NewMI, Address, STI, O); 82 printAnnotation(O, Annot); 83 } 84 85 void CSKYInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) { 86 if (PrintBranchImmAsAddress) 87 O << getRegisterName(Reg, ABIRegNames ? CSKY::ABIRegAltName 88 : CSKY::NoRegAltName); 89 else 90 O << getRegisterName(Reg); 91 } 92 93 void CSKYInstPrinter::printFPRRegName(raw_ostream &O, unsigned RegNo) const { 94 if (PrintBranchImmAsAddress) 95 O << getRegisterName(RegNo, CSKY::NoRegAltName); 96 else 97 O << getRegisterName(RegNo); 98 } 99 100 void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 101 const MCSubtargetInfo &STI, raw_ostream &O) { 102 const MCOperand &MO = MI->getOperand(OpNo); 103 104 if (MO.isReg()) { 105 unsigned Reg = MO.getReg(); 106 bool useABIName = false; 107 if (PrintBranchImmAsAddress) 108 useABIName = ABIRegNames; 109 else 110 useABIName = !ArchRegNames; 111 112 if (Reg == CSKY::C) 113 O << ""; 114 else if (STI.hasFeature(CSKY::FeatureJAVA)) { 115 if (Reg == CSKY::R23) 116 O << (useABIName ? "fp" : "r23"); 117 else if (Reg == CSKY::R24) 118 O << (useABIName ? "top" : "r24"); 119 else if (Reg == CSKY::R25) 120 O << (useABIName ? "bsp" : "r25"); 121 else 122 printRegName(O, Reg); 123 } else 124 printRegName(O, Reg); 125 126 return; 127 } 128 129 if (MO.isImm()) { 130 uint64_t TSFlags = MII.get(MI->getOpcode()).TSFlags; 131 132 if (((TSFlags & CSKYII::AddrModeMask) != CSKYII::AddrModeNone) && 133 PrintBranchImmAsAddress) 134 O << formatHex(MO.getImm()); 135 else 136 O << MO.getImm(); 137 return; 138 } 139 140 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 141 MAI.printExpr(O, *MO.getExpr()); 142 } 143 144 void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo, 145 const MCSubtargetInfo &STI, 146 raw_ostream &O) { 147 const MCOperand &MO = MI->getOperand(OpNo); 148 149 O << "["; 150 if (MO.isImm()) 151 O << MO.getImm(); 152 else 153 MAI.printExpr(O, *MO.getExpr()); 154 O << "]"; 155 } 156 157 void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address, 158 unsigned OpNo, const MCSubtargetInfo &STI, 159 raw_ostream &O) { 160 const MCOperand &MO = MI->getOperand(OpNo); 161 162 if (MO.isImm()) { 163 if (PrintBranchImmAsAddress) { 164 uint64_t Target = Address + MO.getImm(); 165 Target &= 0xfffffffc; 166 O << formatHex(Target); 167 } else { 168 O << MO.getImm(); 169 } 170 return; 171 } 172 173 assert(MO.isExpr() && "Unknown operand kind in printConstpool"); 174 175 O << "["; 176 MAI.printExpr(O, *MO.getExpr()); 177 O << "]"; 178 } 179 180 void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address, 181 unsigned OpNo, 182 const MCSubtargetInfo &STI, 183 raw_ostream &O) { 184 const MCOperand &MO = MI->getOperand(OpNo); 185 if (!MO.isImm()) { 186 return printOperand(MI, OpNo, STI, O); 187 } 188 189 if (PrintBranchImmAsAddress) { 190 uint64_t Target = Address + MO.getImm(); 191 Target &= 0xffffffff; 192 O << formatHex(Target); 193 } else { 194 O << MO.getImm(); 195 } 196 } 197 198 void CSKYInstPrinter::printPSRFlag(const MCInst *MI, unsigned OpNo, 199 const MCSubtargetInfo &STI, raw_ostream &O) { 200 auto V = MI->getOperand(OpNo).getImm(); 201 202 ListSeparator LS; 203 204 if ((V >> 3) & 0x1) 205 O << LS << "ee"; 206 if ((V >> 2) & 0x1) 207 O << LS << "ie"; 208 if ((V >> 1) & 0x1) 209 O << LS << "fe"; 210 if ((V >> 0) & 0x1) 211 O << LS << "af"; 212 } 213 214 void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum, 215 const MCSubtargetInfo &STI, 216 raw_ostream &O) { 217 printRegName(O, MI->getOperand(OpNum).getReg()); 218 O << "-"; 219 printRegName(O, MI->getOperand(OpNum + 1).getReg()); 220 } 221 222 void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 223 const MCSubtargetInfo &STI, 224 raw_ostream &O) { 225 auto V = MI->getOperand(OpNum).getImm(); 226 ListSeparator LS; 227 228 if (V & 0xf) { 229 O << LS; 230 printRegName(O, CSKY::R4); 231 auto Offset = (V & 0xf) - 1; 232 if (Offset) { 233 O << "-"; 234 printRegName(O, CSKY::R4 + Offset); 235 } 236 } 237 238 if ((V >> 4) & 0x1) { 239 O << LS; 240 printRegName(O, CSKY::R15); 241 } 242 243 if ((V >> 5) & 0x7) { 244 O << LS; 245 printRegName(O, CSKY::R16); 246 247 auto Offset = ((V >> 5) & 0x7) - 1; 248 249 if (Offset) { 250 O << "-"; 251 printRegName(O, CSKY::R16 + Offset); 252 } 253 } 254 255 if ((V >> 8) & 0x1) { 256 O << LS; 257 printRegName(O, CSKY::R28); 258 } 259 } 260 261 const char *CSKYInstPrinter::getRegisterName(MCRegister Reg) { 262 return getRegisterName(Reg, ArchRegNames ? CSKY::NoRegAltName 263 : CSKY::ABIRegAltName); 264 } 265 266 void CSKYInstPrinter::printFPR(const MCInst *MI, unsigned OpNo, 267 const MCSubtargetInfo &STI, raw_ostream &O) { 268 const MCOperand &MO = MI->getOperand(OpNo); 269 assert(MO.isReg()); 270 271 printFPRRegName(O, MO.getReg()); 272 } 273