LLVM 20.0.0git
AVRInstPrinter.cpp
Go to the documentation of this file.
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
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"
23
24#include <cstring>
25
26#define DEBUG_TYPE "asm-printer"
27
28namespace llvm {
29
30// Include the auto-generated portion of the assembly writer.
31#define PRINT_ALIAS_INSTR
32#include "AVRGenAsmWriter.inc"
33
35 StringRef Annot, const MCSubtargetInfo &STI,
36 raw_ostream &O) {
37 unsigned Opcode = MI->getOpcode();
38
39 // First handle load and store instructions with postinc or predec
40 // of the form "ld reg, X+".
41 // TODO: We should be able to rewrite this using TableGen data.
42 switch (Opcode) {
43 case AVR::LDRdPtr:
44 case AVR::LDRdPtrPi:
45 case AVR::LDRdPtrPd:
46 O << "\tld\t";
47 printOperand(MI, 0, O);
48 O << ", ";
49
50 if (Opcode == AVR::LDRdPtrPd)
51 O << '-';
52
53 printOperand(MI, 1, O);
54
55 if (Opcode == AVR::LDRdPtrPi)
56 O << '+';
57 break;
58 case AVR::STPtrRr:
59 O << "\tst\t";
60 printOperand(MI, 0, O);
61 O << ", ";
62 printOperand(MI, 1, O);
63 break;
64 case AVR::STPtrPiRr:
65 case AVR::STPtrPdRr:
66 O << "\tst\t";
67
68 if (Opcode == AVR::STPtrPdRr)
69 O << '-';
70
71 printOperand(MI, 1, O);
72
73 if (Opcode == AVR::STPtrPiRr)
74 O << '+';
75
76 O << ", ";
77 printOperand(MI, 2, O);
78 break;
79 default:
80 if (!printAliasInstr(MI, Address, O))
81 printInstruction(MI, Address, O);
82
83 printAnnotation(O, Annot);
84 break;
85 }
86}
87
89 MCRegisterInfo const &MRI) {
90 // GCC prints register pairs by just printing the lower register
91 // If the register contains a subregister, print it instead
92 if (MRI.getNumSubRegIndices() > 0) {
93 MCRegister RegLo = MRI.getSubReg(Reg, AVR::sub_lo);
94 Reg = (RegLo != AVR::NoRegister) ? RegLo : Reg;
95 }
96
97 return getRegisterName(Reg);
98}
99
100void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
101 raw_ostream &O) {
102 const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).operands()[OpNo];
103 if (MOI.RegClass == AVR::ZREGRegClassID) {
104 // Special case for the Z register, which sometimes doesn't have an operand
105 // in the MCInst.
106 O << "Z";
107 return;
108 }
109
110 if (OpNo >= MI->size()) {
111 // Not all operands are correctly disassembled at the moment. This means
112 // that some machine instructions won't have all the necessary operands
113 // set.
114 // To avoid asserting, print <unknown> instead until the necessary support
115 // has been implemented.
116 O << "<unknown>";
117 return;
118 }
119
120 const MCOperand &Op = MI->getOperand(OpNo);
121
122 if (Op.isReg()) {
123 bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
124 (MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
125 (MOI.RegClass == AVR::ZREGRegClassID);
126
127 if (isPtrReg) {
128 O << getRegisterName(Op.getReg(), AVR::ptr);
129 } else {
130 O << getPrettyRegisterName(Op.getReg(), MRI);
131 }
132 } else if (Op.isImm()) {
133 O << formatImm(Op.getImm());
134 } else {
135 assert(Op.isExpr() && "Unknown operand kind in printOperand");
136 O << *Op.getExpr();
137 }
138}
139
140/// This is used to print an immediate value that ends up
141/// being encoded as a pc-relative value.
142void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
143 raw_ostream &O) {
144 if (OpNo >= MI->size()) {
145 // Not all operands are correctly disassembled at the moment. This means
146 // that some machine instructions won't have all the necessary operands
147 // set.
148 // To avoid asserting, print <unknown> instead until the necessary support
149 // has been implemented.
150 O << "<unknown>";
151 return;
152 }
153
154 const MCOperand &Op = MI->getOperand(OpNo);
155
156 if (Op.isImm()) {
157 int64_t Imm = Op.getImm();
158 O << '.';
159
160 // Print a position sign if needed.
161 // Negative values have their sign printed automatically.
162 if (Imm >= 0)
163 O << '+';
164
165 O << Imm;
166 } else {
167 assert(Op.isExpr() && "Unknown pcrel immediate operand");
168 O << *Op.getExpr();
169 }
170}
171
172void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,
173 raw_ostream &O) {
174 assert(MI->getOperand(OpNo).isReg() &&
175 "Expected a register for the first operand");
176
177 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
178
179 // Print the register.
180 printOperand(MI, OpNo, O);
181
182 // Print the {+,-}offset.
183 if (OffsetOp.isImm()) {
184 int64_t Offset = OffsetOp.getImm();
185
186 if (Offset >= 0)
187 O << '+';
188
189 O << Offset;
190 } else if (OffsetOp.isExpr()) {
191 O << *OffsetOp.getExpr();
192 } else {
193 llvm_unreachable("unknown type for offset");
194 }
195}
196
197} // end of namespace llvm
unsigned const MachineRegisterInfo * MRI
IRTranslator LLVM IR MI
unsigned Reg
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override
Print the specified MCInst to the specified raw_ostream.
static const char * getPrettyRegisterName(MCRegister Reg, MCRegisterInfo const &MRI)
const MCInstrInfo & MII
Definition: MCInstPrinter.h:53
const MCRegisterInfo & MRI
Definition: MCInstPrinter.h:54
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
format_object< int64_t > formatImm(int64_t Value) const
Utility function to print immediates in decimal or hex.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
unsigned getOpcode() const
Definition: MCInst.h:199
ArrayRef< MCOperandInfo > operands() const
Definition: MCInstrDesc.h:239
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:85
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition: MCInstrDesc.h:91
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
unsigned getNumSubRegIndices() const
Return the number of sub-register indices understood by the target.
MCRegister getSubReg(MCRegister Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Generic base class for all target subtargets.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
DWARFExpression::Operation Op