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