Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp
35294 views
1
//===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===//
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 AVR MCInst to a .s file.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "AVRInstPrinter.h"
14
15
#include "MCTargetDesc/AVRMCTargetDesc.h"
16
17
#include "llvm/MC/MCExpr.h"
18
#include "llvm/MC/MCInst.h"
19
#include "llvm/MC/MCInstrDesc.h"
20
#include "llvm/MC/MCInstrInfo.h"
21
#include "llvm/MC/MCRegisterInfo.h"
22
#include "llvm/Support/ErrorHandling.h"
23
#include "llvm/Support/FormattedStream.h"
24
25
#include <cstring>
26
27
#define DEBUG_TYPE "asm-printer"
28
29
namespace llvm {
30
31
// Include the auto-generated portion of the assembly writer.
32
#define PRINT_ALIAS_INSTR
33
#include "AVRGenAsmWriter.inc"
34
35
void AVRInstPrinter::printInst(const MCInst *MI, uint64_t Address,
36
StringRef Annot, const MCSubtargetInfo &STI,
37
raw_ostream &O) {
38
unsigned Opcode = MI->getOpcode();
39
40
// First handle load and store instructions with postinc or predec
41
// of the form "ld reg, X+".
42
// TODO: We should be able to rewrite this using TableGen data.
43
switch (Opcode) {
44
case AVR::LDRdPtr:
45
case AVR::LDRdPtrPi:
46
case AVR::LDRdPtrPd:
47
O << "\tld\t";
48
printOperand(MI, 0, O);
49
O << ", ";
50
51
if (Opcode == AVR::LDRdPtrPd)
52
O << '-';
53
54
printOperand(MI, 1, O);
55
56
if (Opcode == AVR::LDRdPtrPi)
57
O << '+';
58
break;
59
case AVR::STPtrRr:
60
O << "\tst\t";
61
printOperand(MI, 0, O);
62
O << ", ";
63
printOperand(MI, 1, O);
64
break;
65
case AVR::STPtrPiRr:
66
case AVR::STPtrPdRr:
67
O << "\tst\t";
68
69
if (Opcode == AVR::STPtrPdRr)
70
O << '-';
71
72
printOperand(MI, 1, O);
73
74
if (Opcode == AVR::STPtrPiRr)
75
O << '+';
76
77
O << ", ";
78
printOperand(MI, 2, O);
79
break;
80
default:
81
if (!printAliasInstr(MI, Address, O))
82
printInstruction(MI, Address, O);
83
84
printAnnotation(O, Annot);
85
break;
86
}
87
}
88
89
const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum,
90
MCRegisterInfo const &MRI) {
91
// GCC prints register pairs by just printing the lower register
92
// If the register contains a subregister, print it instead
93
if (MRI.getNumSubRegIndices() > 0) {
94
unsigned RegLoNum = MRI.getSubReg(RegNum, AVR::sub_lo);
95
RegNum = (RegLoNum != AVR::NoRegister) ? RegLoNum : RegNum;
96
}
97
98
return getRegisterName(RegNum);
99
}
100
101
void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
102
raw_ostream &O) {
103
const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).operands()[OpNo];
104
if (MOI.RegClass == AVR::ZREGRegClassID) {
105
// Special case for the Z register, which sometimes doesn't have an operand
106
// in the MCInst.
107
O << "Z";
108
return;
109
}
110
111
if (OpNo >= MI->size()) {
112
// Not all operands are correctly disassembled at the moment. This means
113
// that some machine instructions won't have all the necessary operands
114
// set.
115
// To avoid asserting, print <unknown> instead until the necessary support
116
// has been implemented.
117
O << "<unknown>";
118
return;
119
}
120
121
const MCOperand &Op = MI->getOperand(OpNo);
122
123
if (Op.isReg()) {
124
bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
125
(MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
126
(MOI.RegClass == AVR::ZREGRegClassID);
127
128
if (isPtrReg) {
129
O << getRegisterName(Op.getReg(), AVR::ptr);
130
} else {
131
O << getPrettyRegisterName(Op.getReg(), MRI);
132
}
133
} else if (Op.isImm()) {
134
O << formatImm(Op.getImm());
135
} else {
136
assert(Op.isExpr() && "Unknown operand kind in printOperand");
137
O << *Op.getExpr();
138
}
139
}
140
141
/// This is used to print an immediate value that ends up
142
/// being encoded as a pc-relative value.
143
void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
144
raw_ostream &O) {
145
if (OpNo >= MI->size()) {
146
// Not all operands are correctly disassembled at the moment. This means
147
// that some machine instructions won't have all the necessary operands
148
// set.
149
// To avoid asserting, print <unknown> instead until the necessary support
150
// has been implemented.
151
O << "<unknown>";
152
return;
153
}
154
155
const MCOperand &Op = MI->getOperand(OpNo);
156
157
if (Op.isImm()) {
158
int64_t Imm = Op.getImm();
159
O << '.';
160
161
// Print a position sign if needed.
162
// Negative values have their sign printed automatically.
163
if (Imm >= 0)
164
O << '+';
165
166
O << Imm;
167
} else {
168
assert(Op.isExpr() && "Unknown pcrel immediate operand");
169
O << *Op.getExpr();
170
}
171
}
172
173
void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,
174
raw_ostream &O) {
175
assert(MI->getOperand(OpNo).isReg() &&
176
"Expected a register for the first operand");
177
178
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
179
180
// Print the register.
181
printOperand(MI, OpNo, O);
182
183
// Print the {+,-}offset.
184
if (OffsetOp.isImm()) {
185
int64_t Offset = OffsetOp.getImm();
186
187
if (Offset >= 0)
188
O << '+';
189
190
O << Offset;
191
} else if (OffsetOp.isExpr()) {
192
O << *OffsetOp.getExpr();
193
} else {
194
llvm_unreachable("unknown type for offset");
195
}
196
}
197
198
} // end of namespace llvm
199
200