1 //===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===//
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
7 //===----------------------------------------------------------------------===//
9 // This class prints an AVR MCInst to a .s file.
11 //===----------------------------------------------------------------------===//
13 #include "AVRInstPrinter.h"
15 #include "MCTargetDesc/AVRMCTargetDesc.h"
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"
27 #define DEBUG_TYPE "asm-printer"
31 // Include the auto-generated portion of the assembly writer.
32 #define PRINT_ALIAS_INSTR
33 #include "AVRGenAsmWriter.inc"
35 void AVRInstPrinter::printInst(const MCInst
*MI
, uint64_t Address
,
36 StringRef Annot
, const MCSubtargetInfo
&STI
,
38 unsigned Opcode
= MI
->getOpcode();
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.
48 printOperand(MI
, 0, O
);
51 if (Opcode
== AVR::LDRdPtrPd
)
54 printOperand(MI
, 1, O
);
56 if (Opcode
== AVR::LDRdPtrPi
)
61 printOperand(MI
, 0, O
);
63 printOperand(MI
, 1, O
);
69 if (Opcode
== AVR::STPtrPdRr
)
72 printOperand(MI
, 1, O
);
74 if (Opcode
== AVR::STPtrPiRr
)
78 printOperand(MI
, 2, O
);
81 if (!printAliasInstr(MI
, Address
, O
))
82 printInstruction(MI
, Address
, O
);
84 printAnnotation(O
, Annot
);
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
;
98 return getRegisterName(RegNum
);
101 void AVRInstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
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
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
115 // To avoid asserting, print <unknown> instead until the necessary support
116 // has been implemented.
121 const MCOperand
&Op
= MI
->getOperand(OpNo
);
124 bool isPtrReg
= (MOI
.RegClass
== AVR::PTRREGSRegClassID
) ||
125 (MOI
.RegClass
== AVR::PTRDISPREGSRegClassID
) ||
126 (MOI
.RegClass
== AVR::ZREGRegClassID
);
129 O
<< getRegisterName(Op
.getReg(), AVR::ptr
);
131 O
<< getPrettyRegisterName(Op
.getReg(), MRI
);
133 } else if (Op
.isImm()) {
134 O
<< formatImm(Op
.getImm());
136 assert(Op
.isExpr() && "Unknown operand kind in printOperand");
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
,
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
149 // To avoid asserting, print <unknown> instead until the necessary support
150 // has been implemented.
155 const MCOperand
&Op
= MI
->getOperand(OpNo
);
158 int64_t Imm
= Op
.getImm();
161 // Print a position sign if needed.
162 // Negative values have their sign printed automatically.
168 assert(Op
.isExpr() && "Unknown pcrel immediate operand");
173 void AVRInstPrinter::printMemri(const MCInst
*MI
, unsigned OpNo
,
175 assert(MI
->getOperand(OpNo
).isReg() &&
176 "Expected a register for the first operand");
178 const MCOperand
&OffsetOp
= MI
->getOperand(OpNo
+ 1);
180 // Print the register.
181 printOperand(MI
, OpNo
, O
);
183 // Print the {+,-}offset.
184 if (OffsetOp
.isImm()) {
185 int64_t Offset
= OffsetOp
.getImm();
191 } else if (OffsetOp
.isExpr()) {
192 O
<< *OffsetOp
.getExpr();
194 llvm_unreachable("unknown type for offset");
198 } // end of namespace llvm