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" 14349cc55cSDimitry 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 76*04eeddc0SDimitry Andric void CSKYInstPrinter::printFPRRegName(raw_ostream &O, unsigned RegNo) const { 77*04eeddc0SDimitry Andric if (PrintBranchImmAsAddress) 78*04eeddc0SDimitry Andric O << getRegisterName(RegNo, CSKY::NoRegAltName); 79*04eeddc0SDimitry Andric else 80*04eeddc0SDimitry Andric O << getRegisterName(RegNo); 81*04eeddc0SDimitry Andric } 82*04eeddc0SDimitry Andric 83fe6060f1SDimitry Andric void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 84fe6060f1SDimitry Andric const MCSubtargetInfo &STI, raw_ostream &O, 85fe6060f1SDimitry Andric const char *Modifier) { 86fe6060f1SDimitry Andric assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); 87fe6060f1SDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 88fe6060f1SDimitry Andric 89fe6060f1SDimitry Andric if (MO.isReg()) { 90fe6060f1SDimitry Andric if (MO.getReg() == CSKY::C) 91fe6060f1SDimitry Andric O << ""; 92fe6060f1SDimitry Andric else 93fe6060f1SDimitry Andric printRegName(O, MO.getReg()); 94fe6060f1SDimitry Andric return; 95fe6060f1SDimitry Andric } 96fe6060f1SDimitry Andric 97fe6060f1SDimitry Andric if (MO.isImm()) { 98fe6060f1SDimitry Andric O << formatImm(MO.getImm()); 99fe6060f1SDimitry Andric return; 100fe6060f1SDimitry Andric } 101fe6060f1SDimitry Andric 102fe6060f1SDimitry Andric assert(MO.isExpr() && "Unknown operand kind in printOperand"); 103fe6060f1SDimitry Andric MO.getExpr()->print(O, &MAI); 104fe6060f1SDimitry Andric } 105fe6060f1SDimitry Andric 106349cc55cSDimitry Andric void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo, 107349cc55cSDimitry Andric const MCSubtargetInfo &STI, 108349cc55cSDimitry Andric raw_ostream &O) { 109349cc55cSDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 110349cc55cSDimitry Andric 111349cc55cSDimitry Andric O << "["; 112349cc55cSDimitry Andric if (MO.isImm()) 113349cc55cSDimitry Andric O << MO.getImm(); 114349cc55cSDimitry Andric else 115349cc55cSDimitry Andric MO.getExpr()->print(O, &MAI); 116349cc55cSDimitry Andric O << "]"; 117349cc55cSDimitry Andric } 118349cc55cSDimitry Andric 119349cc55cSDimitry Andric void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address, 120349cc55cSDimitry Andric unsigned OpNo, const MCSubtargetInfo &STI, 121349cc55cSDimitry Andric raw_ostream &O) { 122349cc55cSDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 123349cc55cSDimitry Andric 124349cc55cSDimitry Andric if (MO.isImm()) { 125349cc55cSDimitry Andric if (PrintBranchImmAsAddress) { 126349cc55cSDimitry Andric uint64_t Target = Address + MO.getImm(); 127349cc55cSDimitry Andric Target &= 0xfffffffc; 128349cc55cSDimitry Andric O << formatHex(Target); 129349cc55cSDimitry Andric } else { 130349cc55cSDimitry Andric O << MO.getImm(); 131349cc55cSDimitry Andric } 132349cc55cSDimitry Andric return; 133349cc55cSDimitry Andric } 134349cc55cSDimitry Andric 135349cc55cSDimitry Andric assert(MO.isExpr() && "Unknown operand kind in printConstpool"); 136349cc55cSDimitry Andric 137349cc55cSDimitry Andric O << "["; 138349cc55cSDimitry Andric MO.getExpr()->print(O, &MAI); 139349cc55cSDimitry Andric O << "]"; 140349cc55cSDimitry Andric } 141349cc55cSDimitry Andric 142349cc55cSDimitry Andric void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address, 143349cc55cSDimitry Andric unsigned OpNo, 144349cc55cSDimitry Andric const MCSubtargetInfo &STI, 145349cc55cSDimitry Andric raw_ostream &O) { 146349cc55cSDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 147349cc55cSDimitry Andric if (!MO.isImm()) { 148349cc55cSDimitry Andric return printOperand(MI, OpNo, STI, O); 149349cc55cSDimitry Andric } 150349cc55cSDimitry Andric 151349cc55cSDimitry Andric if (PrintBranchImmAsAddress) { 152349cc55cSDimitry Andric uint64_t Target = Address + MO.getImm(); 153349cc55cSDimitry Andric Target &= 0xffffffff; 154349cc55cSDimitry Andric O << formatHex(Target); 155349cc55cSDimitry Andric } else { 156349cc55cSDimitry Andric O << MO.getImm(); 157349cc55cSDimitry Andric } 158349cc55cSDimitry Andric } 159349cc55cSDimitry Andric 160349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum, 161349cc55cSDimitry Andric const MCSubtargetInfo &STI, 162349cc55cSDimitry Andric raw_ostream &O) { 163349cc55cSDimitry Andric printRegName(O, MI->getOperand(OpNum).getReg()); 164349cc55cSDimitry Andric O << "-"; 165349cc55cSDimitry Andric printRegName(O, MI->getOperand(OpNum + 1).getReg()); 166349cc55cSDimitry Andric } 167349cc55cSDimitry Andric 168349cc55cSDimitry Andric void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, 169349cc55cSDimitry Andric const MCSubtargetInfo &STI, 170349cc55cSDimitry Andric raw_ostream &O) { 171349cc55cSDimitry Andric auto V = MI->getOperand(OpNum).getImm(); 172349cc55cSDimitry Andric ListSeparator LS; 173349cc55cSDimitry Andric 174349cc55cSDimitry Andric if (V & 0xf) { 175349cc55cSDimitry Andric O << LS; 176349cc55cSDimitry Andric printRegName(O, CSKY::R4); 177349cc55cSDimitry Andric auto Offset = (V & 0xf) - 1; 178349cc55cSDimitry Andric if (Offset) { 179349cc55cSDimitry Andric O << "-"; 180349cc55cSDimitry Andric printRegName(O, CSKY::R4 + Offset); 181349cc55cSDimitry Andric } 182349cc55cSDimitry Andric } 183349cc55cSDimitry Andric 184349cc55cSDimitry Andric if ((V >> 4) & 0x1) { 185349cc55cSDimitry Andric O << LS; 186349cc55cSDimitry Andric printRegName(O, CSKY::R15); 187349cc55cSDimitry Andric } 188349cc55cSDimitry Andric 189349cc55cSDimitry Andric if ((V >> 5) & 0x7) { 190349cc55cSDimitry Andric O << LS; 191349cc55cSDimitry Andric printRegName(O, CSKY::R16); 192349cc55cSDimitry Andric 193349cc55cSDimitry Andric auto Offset = ((V >> 5) & 0x7) - 1; 194349cc55cSDimitry Andric 195349cc55cSDimitry Andric if (Offset) { 196349cc55cSDimitry Andric O << "-"; 197349cc55cSDimitry Andric printRegName(O, CSKY::R16 + Offset); 198349cc55cSDimitry Andric } 199349cc55cSDimitry Andric } 200349cc55cSDimitry Andric 201349cc55cSDimitry Andric if ((V >> 8) & 0x1) { 202349cc55cSDimitry Andric O << LS; 203349cc55cSDimitry Andric printRegName(O, CSKY::R28); 204349cc55cSDimitry Andric } 205349cc55cSDimitry Andric } 206349cc55cSDimitry Andric 207fe6060f1SDimitry Andric const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) { 208fe6060f1SDimitry Andric return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName 209fe6060f1SDimitry Andric : CSKY::ABIRegAltName); 210fe6060f1SDimitry Andric } 211*04eeddc0SDimitry Andric 212*04eeddc0SDimitry Andric void CSKYInstPrinter::printFPR(const MCInst *MI, unsigned OpNo, 213*04eeddc0SDimitry Andric const MCSubtargetInfo &STI, raw_ostream &O) { 214*04eeddc0SDimitry Andric const MCOperand &MO = MI->getOperand(OpNo); 215*04eeddc0SDimitry Andric assert(MO.isReg()); 216*04eeddc0SDimitry Andric 217*04eeddc0SDimitry Andric printFPRRegName(O, MO.getReg()); 218*04eeddc0SDimitry Andric } 219