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