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