1 //===- ARCInstPrinter.cpp - ARC MCInst to assembly syntax -------*- C++ -*-===// 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 ARC MCInst to a .s file. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "ARCInstPrinter.h" 14 #include "MCTargetDesc/ARCInfo.h" 15 #include "llvm/ADT/StringExtras.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCInst.h" 18 #include "llvm/MC/MCInstrInfo.h" 19 #include "llvm/MC/MCSymbol.h" 20 #include "llvm/Support/Casting.h" 21 #include "llvm/Support/Debug.h" 22 #include "llvm/Support/raw_ostream.h" 23 24 using namespace llvm; 25 26 #define DEBUG_TYPE "asm-printer" 27 28 #include "ARCGenAsmWriter.inc" 29 30 template <class T> 31 static const char *BadConditionCode(T cc) { 32 LLVM_DEBUG(dbgs() << "Unknown condition code passed: " << cc << "\n"); 33 return "{unknown-cc}"; 34 } 35 36 static const char *ARCBRCondCodeToString(ARCCC::BRCondCode BRCC) { 37 switch (BRCC) { 38 case ARCCC::BREQ: 39 return "eq"; 40 case ARCCC::BRNE: 41 return "ne"; 42 case ARCCC::BRLT: 43 return "lt"; 44 case ARCCC::BRGE: 45 return "ge"; 46 case ARCCC::BRLO: 47 return "lo"; 48 case ARCCC::BRHS: 49 return "hs"; 50 } 51 return BadConditionCode(BRCC); 52 } 53 54 static const char *ARCCondCodeToString(ARCCC::CondCode CC) { 55 switch (CC) { 56 case ARCCC::EQ: 57 return "eq"; 58 case ARCCC::NE: 59 return "ne"; 60 case ARCCC::P: 61 return "p"; 62 case ARCCC::N: 63 return "n"; 64 case ARCCC::HS: 65 return "hs"; 66 case ARCCC::LO: 67 return "lo"; 68 case ARCCC::GT: 69 return "gt"; 70 case ARCCC::GE: 71 return "ge"; 72 case ARCCC::VS: 73 return "vs"; 74 case ARCCC::VC: 75 return "vc"; 76 case ARCCC::LT: 77 return "lt"; 78 case ARCCC::LE: 79 return "le"; 80 case ARCCC::HI: 81 return "hi"; 82 case ARCCC::LS: 83 return "ls"; 84 case ARCCC::PNZ: 85 return "pnz"; 86 case ARCCC::AL: 87 return "al"; 88 case ARCCC::NZ: 89 return "nz"; 90 case ARCCC::Z: 91 return "z"; 92 } 93 return BadConditionCode(CC); 94 } 95 96 void ARCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 97 OS << StringRef(getRegisterName(RegNo)).lower(); 98 } 99 100 void ARCInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 101 StringRef Annot, const MCSubtargetInfo &STI) { 102 printInstruction(MI, O); 103 printAnnotation(O, Annot); 104 } 105 106 static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI, 107 raw_ostream &OS) { 108 int Offset = 0; 109 const MCSymbolRefExpr *SRE; 110 111 if (const auto *CE = dyn_cast<MCConstantExpr>(Expr)) { 112 OS << "0x"; 113 OS.write_hex(CE->getValue()); 114 return; 115 } 116 117 if (const auto *BE = dyn_cast<MCBinaryExpr>(Expr)) { 118 SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS()); 119 const auto *CE = dyn_cast<MCConstantExpr>(BE->getRHS()); 120 assert(SRE && CE && "Binary expression must be sym+const."); 121 Offset = CE->getValue(); 122 } else { 123 SRE = dyn_cast<MCSymbolRefExpr>(Expr); 124 assert(SRE && "Unexpected MCExpr type."); 125 } 126 assert(SRE->getKind() == MCSymbolRefExpr::VK_None); 127 128 // Symbols are prefixed with '@' 129 OS << '@'; 130 SRE->getSymbol().print(OS, MAI); 131 132 if (Offset) { 133 if (Offset > 0) 134 OS << '+'; 135 OS << Offset; 136 } 137 } 138 139 void ARCInstPrinter::printOperand(const MCInst *MI, unsigned OpNum, 140 raw_ostream &O) { 141 const MCOperand &Op = MI->getOperand(OpNum); 142 if (Op.isReg()) { 143 printRegName(O, Op.getReg()); 144 return; 145 } 146 147 if (Op.isImm()) { 148 O << Op.getImm(); 149 return; 150 } 151 152 assert(Op.isExpr() && "unknown operand kind in printOperand"); 153 printExpr(Op.getExpr(), &MAI, O); 154 } 155 156 void ARCInstPrinter::printMemOperandRI(const MCInst *MI, unsigned OpNum, 157 raw_ostream &O) { 158 const MCOperand &base = MI->getOperand(OpNum); 159 const MCOperand &offset = MI->getOperand(OpNum + 1); 160 assert(base.isReg() && "Base should be register."); 161 assert(offset.isImm() && "Offset should be immediate."); 162 printRegName(O, base.getReg()); 163 O << "," << offset.getImm(); 164 } 165 166 void ARCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, 167 raw_ostream &O) { 168 169 const MCOperand &Op = MI->getOperand(OpNum); 170 assert(Op.isImm() && "Predicate operand is immediate."); 171 O << ARCCondCodeToString((ARCCC::CondCode)Op.getImm()); 172 } 173 174 void ARCInstPrinter::printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum, 175 raw_ostream &O) { 176 const MCOperand &Op = MI->getOperand(OpNum); 177 assert(Op.isImm() && "Predicate operand is immediate."); 178 O << ARCBRCondCodeToString((ARCCC::BRCondCode)Op.getImm()); 179 } 180