Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp
35294 views
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, MCRegister Reg) const {
97
OS << StringRef(getRegisterName(Reg)).lower();
98
}
99
100
void ARCInstPrinter::printInst(const MCInst *MI, uint64_t Address,
101
StringRef Annot, const MCSubtargetInfo &STI,
102
raw_ostream &O) {
103
printInstruction(MI, Address, 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
182
void ARCInstPrinter::printCCOperand(const MCInst *MI, int OpNum,
183
raw_ostream &O) {
184
O << ARCCondCodeToString((ARCCC::CondCode)MI->getOperand(OpNum).getImm());
185
}
186
187
void ARCInstPrinter::printU6ShiftedBy(unsigned ShiftBy, const MCInst *MI,
188
int OpNum, raw_ostream &O) {
189
const MCOperand &MO = MI->getOperand(OpNum);
190
if (MO.isImm()) {
191
unsigned Value = MO.getImm();
192
unsigned Value2 = Value >> ShiftBy;
193
if (Value2 > 0x3F || (Value2 << ShiftBy != Value)) {
194
errs() << "!!! Instruction has out-of-range U6 immediate operand:\n"
195
<< " Opcode is " << MI->getOpcode() << "; operand value is "
196
<< Value;
197
if (ShiftBy)
198
errs() << " scaled by " << (1 << ShiftBy) << "\n";
199
assert(false && "instruction has wrong format");
200
}
201
}
202
printOperand(MI, OpNum, O);
203
}
204
205
void ARCInstPrinter::printU6(const MCInst *MI, int OpNum, raw_ostream &O) {
206
printU6ShiftedBy(0, MI, OpNum, O);
207
}
208
209