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 13 #include "CSKYInstPrinter.h" 14 #include "llvm/ADT/StringExtras.h" 15 #include "llvm/MC/MCAsmInfo.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCInst.h" 18 #include "llvm/MC/MCRegisterInfo.h" 19 #include "llvm/MC/MCSubtargetInfo.h" 20 #include "llvm/MC/MCSymbol.h" 21 #include "llvm/Support/CommandLine.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include "llvm/Support/FormattedStream.h" 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "csky-asm-printer" 28 29 // Include the auto-generated portion of the assembly writer. 30 #define PRINT_ALIAS_INSTR 31 #include "CSKYGenAsmWriter.inc" 32 33 static cl::opt<bool> 34 NoAliases("csky-no-aliases", 35 cl::desc("Disable the emission of assembler pseudo instructions"), 36 cl::init(false), cl::Hidden); 37 38 static cl::opt<bool> 39 ArchRegNames("csky-arch-reg-names", 40 cl::desc("Print architectural register names rather than the " 41 "ABI names (such as r14 instead of sp)"), 42 cl::init(false), cl::Hidden); 43 44 // The command-line flags above are used by llvm-mc and llc. They can be used by 45 // `llvm-objdump`, but we override their values here to handle options passed to 46 // `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to 47 // be an easier way to allow these options in all these tools, without doing it 48 // this way. 49 bool CSKYInstPrinter::applyTargetSpecificCLOption(StringRef Opt) { 50 if (Opt == "no-aliases") { 51 NoAliases = true; 52 return true; 53 } 54 if (Opt == "numeric") { 55 ArchRegNames = true; 56 return true; 57 } 58 59 return false; 60 } 61 62 void CSKYInstPrinter::printInst(const MCInst *MI, uint64_t Address, 63 StringRef Annot, const MCSubtargetInfo &STI, 64 raw_ostream &O) { 65 const MCInst *NewMI = MI; 66 67 if (NoAliases || !printAliasInstr(NewMI, Address, STI, O)) 68 printInstruction(NewMI, Address, STI, O); 69 printAnnotation(O, Annot); 70 } 71 72 void CSKYInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { 73 O << getRegisterName(RegNo); 74 } 75 76 void CSKYInstPrinter::printFPRRegName(raw_ostream &O, unsigned RegNo) const { 77 if (PrintBranchImmAsAddress) 78 O << getRegisterName(RegNo, CSKY::NoRegAltName); 79 else 80 O << getRegisterName(RegNo); 81 } 82 83 void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 84 const MCSubtargetInfo &STI, raw_ostream &O, 85 const char *Modifier) { 86 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 87 const MCOperand &MO = MI->getOperand(OpNo); 88 89 if (MO.isReg()) { 90 if (MO.getReg() == CSKY::C) 91 O << ""; 92 else 93 printRegName(O, MO.getReg()); 94 return; 95 } 96 97 if (MO.isImm()) { 98 O << formatImm(MO.getImm()); 99 return; 100 } 101 102 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 103 MO.getExpr()->print(O, &MAI); 104 } 105 106 void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo, 107 const MCSubtargetInfo &STI, 108 raw_ostream &O) { 109 const MCOperand &MO = MI->getOperand(OpNo); 110 111 O << "["; 112 if (MO.isImm()) 113 O << MO.getImm(); 114 else 115 MO.getExpr()->print(O, &MAI); 116 O << "]"; 117 } 118 119 void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address, 120 unsigned OpNo, const MCSubtargetInfo &STI, 121 raw_ostream &O) { 122 const MCOperand &MO = MI->getOperand(OpNo); 123 124 if (MO.isImm()) { 125 if (PrintBranchImmAsAddress) { 126 uint64_t Target = Address + MO.getImm(); 127 Target &= 0xfffffffc; 128 O << formatHex(Target); 129 } else { 130 O << MO.getImm(); 131 } 132 return; 133 } 134 135 assert(MO.isExpr() && "Unknown operand kind in printConstpool"); 136 137 O << "["; 138 MO.getExpr()->print(O, &MAI); 139 O << "]"; 140 } 141 142 void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address, 143 unsigned OpNo, 144 const MCSubtargetInfo &STI, 145 raw_ostream &O) { 146 const MCOperand &MO = MI->getOperand(OpNo); 147 if (!MO.isImm()) { 148 return printOperand(MI, OpNo, STI, O); 149 } 150 151 if (PrintBranchImmAsAddress) { 152 uint64_t Target = Address + MO.getImm(); 153 Target &= 0xffffffff; 154 O << formatHex(Target); 155 } else { 156 O << MO.getImm(); 157 } 158 } 159 160 void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum, 161 const MCSubtargetInfo &STI, 162 raw_ostream &O) { 163 printRegName(O, MI->getOperand(OpNum).getReg()); 164 O << "-"; 165 printRegName(O, MI->getOperand(OpNum + 1).getReg()); 166 } 167 168 void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 169 const MCSubtargetInfo &STI, 170 raw_ostream &O) { 171 auto V = MI->getOperand(OpNum).getImm(); 172 ListSeparator LS; 173 174 if (V & 0xf) { 175 O << LS; 176 printRegName(O, CSKY::R4); 177 auto Offset = (V & 0xf) - 1; 178 if (Offset) { 179 O << "-"; 180 printRegName(O, CSKY::R4 + Offset); 181 } 182 } 183 184 if ((V >> 4) & 0x1) { 185 O << LS; 186 printRegName(O, CSKY::R15); 187 } 188 189 if ((V >> 5) & 0x7) { 190 O << LS; 191 printRegName(O, CSKY::R16); 192 193 auto Offset = ((V >> 5) & 0x7) - 1; 194 195 if (Offset) { 196 O << "-"; 197 printRegName(O, CSKY::R16 + Offset); 198 } 199 } 200 201 if ((V >> 8) & 0x1) { 202 O << LS; 203 printRegName(O, CSKY::R28); 204 } 205 } 206 207 const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) { 208 return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName 209 : CSKY::ABIRegAltName); 210 } 211 212 void CSKYInstPrinter::printFPR(const MCInst *MI, unsigned OpNo, 213 const MCSubtargetInfo &STI, raw_ostream &O) { 214 const MCOperand &MO = MI->getOperand(OpNo); 215 assert(MO.isReg()); 216 217 printFPRRegName(O, MO.getReg()); 218 } 219