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