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
ARCBRCondCodeToString(ARCCC::BRCondCode BRCC)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
ARCCondCodeToString(ARCCC::CondCode CC)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
printRegName(raw_ostream & OS,unsigned RegNo) const92 void ARCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
93 OS << StringRef(getRegisterName(RegNo)).lower();
94 }
95
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot,const MCSubtargetInfo & STI)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
printExpr(const MCExpr * Expr,const MCAsmInfo * MAI,raw_ostream & OS)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
printOperand(const MCInst * MI,unsigned OpNum,raw_ostream & O)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
printMemOperandRI(const MCInst * MI,unsigned OpNum,raw_ostream & O)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
printPredicateOperand(const MCInst * MI,unsigned OpNum,raw_ostream & O)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
printBRCCPredicateOperand(const MCInst * MI,unsigned OpNum,raw_ostream & O)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