Recommit r373598 "[yaml2obj/obj2yaml] - Add support for SHT_LLVM_ADDRSIG sections."
[llvm-complete.git] / lib / Target / AVR / MCTargetDesc / AVRInstPrinter.cpp
blob88ce9a25680e2b0447c9b87b36a71a656d18c348
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.
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"
25 #include <cstring>
27 #define DEBUG_TYPE "asm-printer"
29 namespace llvm {
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, raw_ostream &O,
36 StringRef Annot, const MCSubtargetInfo &STI) {
37 unsigned Opcode = MI->getOpcode();
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 << ", ";
50 if (Opcode == AVR::LDRdPtrPd)
51 O << '-';
53 printOperand(MI, 1, O);
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";
68 if (Opcode == AVR::STPtrPdRr)
69 O << '-';
71 printOperand(MI, 1, O);
73 if (Opcode == AVR::STPtrPiRr)
74 O << '+';
76 O << ", ";
77 printOperand(MI, 2, O);
78 break;
79 default:
80 if (!printAliasInstr(MI, O))
81 printInstruction(MI, O);
83 printAnnotation(O, Annot);
84 break;
88 const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum,
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 unsigned RegLoNum = MRI.getSubReg(RegNum, AVR::sub_lo);
94 RegNum = (RegLoNum != AVR::NoRegister) ? RegLoNum : RegNum;
97 return getRegisterName(RegNum);
100 void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
101 raw_ostream &O) {
102 const MCOperand &Op = MI->getOperand(OpNo);
103 const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo];
105 if (Op.isReg()) {
106 bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
107 (MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
108 (MOI.RegClass == AVR::ZREGRegClassID);
110 if (isPtrReg) {
111 O << getRegisterName(Op.getReg(), AVR::ptr);
112 } else {
113 O << getPrettyRegisterName(Op.getReg(), MRI);
115 } else if (Op.isImm()) {
116 O << Op.getImm();
117 } else {
118 assert(Op.isExpr() && "Unknown operand kind in printOperand");
119 O << *Op.getExpr();
123 /// This is used to print an immediate value that ends up
124 /// being encoded as a pc-relative value.
125 void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
126 raw_ostream &O) {
127 const MCOperand &Op = MI->getOperand(OpNo);
129 if (Op.isImm()) {
130 int64_t Imm = Op.getImm();
131 O << '.';
133 // Print a position sign if needed.
134 // Negative values have their sign printed automatically.
135 if (Imm >= 0)
136 O << '+';
138 O << Imm;
139 } else {
140 assert(Op.isExpr() && "Unknown pcrel immediate operand");
141 O << *Op.getExpr();
145 void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,
146 raw_ostream &O) {
147 assert(MI->getOperand(OpNo).isReg() && "Expected a register for the first operand");
149 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
151 // Print the register.
152 printOperand(MI, OpNo, O);
154 // Print the {+,-}offset.
155 if (OffsetOp.isImm()) {
156 int64_t Offset = OffsetOp.getImm();
158 if (Offset >= 0)
159 O << '+';
161 O << Offset;
162 } else if (OffsetOp.isExpr()) {
163 O << *OffsetOp.getExpr();
164 } else {
165 llvm_unreachable("unknown type for offset");
169 } // end of namespace llvm