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/CSKYMCExpr.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, unsigned RegNo) const { 86 if (PrintBranchImmAsAddress) 87 O << getRegisterName(RegNo, ABIRegNames ? CSKY::ABIRegAltName 88 : CSKY::NoRegAltName); 89 else 90 O << getRegisterName(RegNo); 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 char *Modifier) { 103 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 104 const MCOperand &MO = MI->getOperand(OpNo); 105 106 if (MO.isReg()) { 107 unsigned Reg = MO.getReg(); 108 bool useABIName = false; 109 if (PrintBranchImmAsAddress) 110 useABIName = ABIRegNames; 111 else 112 useABIName = !ArchRegNames; 113 114 if (Reg == CSKY::C) 115 O << ""; 116 else if (STI.getFeatureBits()[CSKY::FeatureJAVA]) { 117 if (Reg == CSKY::R23) 118 O << (useABIName ? "fp" : "r23"); 119 else if (Reg == CSKY::R24) 120 O << (useABIName ? "top" : "r24"); 121 else if (Reg == CSKY::R25) 122 O << (useABIName ? "bsp" : "r25"); 123 else 124 printRegName(O, Reg); 125 } else 126 printRegName(O, Reg); 127 128 return; 129 } 130 131 if (MO.isImm()) { 132 uint64_t TSFlags = MII.get(MI->getOpcode()).TSFlags; 133 134 if (((TSFlags & CSKYII::AddrModeMask) != CSKYII::AddrModeNone) && 135 PrintBranchImmAsAddress) 136 O << formatHex(MO.getImm()); 137 else 138 O << MO.getImm(); 139 return; 140 } 141 142 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 143 MO.getExpr()->print(O, &MAI); 144 } 145 146 void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo, 147 const MCSubtargetInfo &STI, 148 raw_ostream &O) { 149 const MCOperand &MO = MI->getOperand(OpNo); 150 151 O << "["; 152 if (MO.isImm()) 153 O << MO.getImm(); 154 else 155 MO.getExpr()->print(O, &MAI); 156 O << "]"; 157 } 158 159 void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address, 160 unsigned OpNo, const MCSubtargetInfo &STI, 161 raw_ostream &O) { 162 const MCOperand &MO = MI->getOperand(OpNo); 163 164 if (MO.isImm()) { 165 if (PrintBranchImmAsAddress) { 166 uint64_t Target = Address + MO.getImm(); 167 Target &= 0xfffffffc; 168 O << formatHex(Target); 169 } else { 170 O << MO.getImm(); 171 } 172 return; 173 } 174 175 assert(MO.isExpr() && "Unknown operand kind in printConstpool"); 176 177 O << "["; 178 MO.getExpr()->print(O, &MAI); 179 O << "]"; 180 } 181 182 void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address, 183 unsigned OpNo, 184 const MCSubtargetInfo &STI, 185 raw_ostream &O) { 186 const MCOperand &MO = MI->getOperand(OpNo); 187 if (!MO.isImm()) { 188 return printOperand(MI, OpNo, STI, O); 189 } 190 191 if (PrintBranchImmAsAddress) { 192 uint64_t Target = Address + MO.getImm(); 193 Target &= 0xffffffff; 194 O << formatHex(Target); 195 } else { 196 O << MO.getImm(); 197 } 198 } 199 200 void CSKYInstPrinter::printPSRFlag(const MCInst *MI, unsigned OpNo, 201 const MCSubtargetInfo &STI, raw_ostream &O) { 202 auto V = MI->getOperand(OpNo).getImm(); 203 204 ListSeparator LS; 205 206 if ((V >> 3) & 0x1) 207 O << LS << "ee"; 208 if ((V >> 2) & 0x1) 209 O << LS << "ie"; 210 if ((V >> 1) & 0x1) 211 O << LS << "fe"; 212 if ((V >> 0) & 0x1) 213 O << LS << "af"; 214 } 215 216 void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum, 217 const MCSubtargetInfo &STI, 218 raw_ostream &O) { 219 printRegName(O, MI->getOperand(OpNum).getReg()); 220 O << "-"; 221 printRegName(O, MI->getOperand(OpNum + 1).getReg()); 222 } 223 224 void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 225 const MCSubtargetInfo &STI, 226 raw_ostream &O) { 227 auto V = MI->getOperand(OpNum).getImm(); 228 ListSeparator LS; 229 230 if (V & 0xf) { 231 O << LS; 232 printRegName(O, CSKY::R4); 233 auto Offset = (V & 0xf) - 1; 234 if (Offset) { 235 O << "-"; 236 printRegName(O, CSKY::R4 + Offset); 237 } 238 } 239 240 if ((V >> 4) & 0x1) { 241 O << LS; 242 printRegName(O, CSKY::R15); 243 } 244 245 if ((V >> 5) & 0x7) { 246 O << LS; 247 printRegName(O, CSKY::R16); 248 249 auto Offset = ((V >> 5) & 0x7) - 1; 250 251 if (Offset) { 252 O << "-"; 253 printRegName(O, CSKY::R16 + Offset); 254 } 255 } 256 257 if ((V >> 8) & 0x1) { 258 O << LS; 259 printRegName(O, CSKY::R28); 260 } 261 } 262 263 const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) { 264 return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName 265 : CSKY::ABIRegAltName); 266 } 267 268 void CSKYInstPrinter::printFPR(const MCInst *MI, unsigned OpNo, 269 const MCSubtargetInfo &STI, raw_ostream &O) { 270 const MCOperand &MO = MI->getOperand(OpNo); 271 assert(MO.isReg()); 272 273 printFPRRegName(O, MO.getReg()); 274 } 275