Line data Source code
1 : //===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This class prints an AVR MCInst to a .s file.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "AVRInstPrinter.h"
15 :
16 : #include "MCTargetDesc/AVRMCTargetDesc.h"
17 :
18 : #include "llvm/MC/MCExpr.h"
19 : #include "llvm/MC/MCInst.h"
20 : #include "llvm/MC/MCInstrDesc.h"
21 : #include "llvm/MC/MCInstrInfo.h"
22 : #include "llvm/MC/MCRegisterInfo.h"
23 : #include "llvm/Support/ErrorHandling.h"
24 : #include "llvm/Support/FormattedStream.h"
25 :
26 : #include <cstring>
27 :
28 : #define DEBUG_TYPE "asm-printer"
29 :
30 : namespace llvm {
31 :
32 : // Include the auto-generated portion of the assembly writer.
33 : #define PRINT_ALIAS_INSTR
34 : #include "AVRGenAsmWriter.inc"
35 :
36 9898 : void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
37 : StringRef Annot, const MCSubtargetInfo &STI) {
38 9898 : 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 9898 : switch (Opcode) {
44 78 : case AVR::LDRdPtr:
45 : case AVR::LDRdPtrPi:
46 : case AVR::LDRdPtrPd:
47 78 : O << "\tld\t";
48 78 : printOperand(MI, 0, O);
49 78 : O << ", ";
50 :
51 78 : if (Opcode == AVR::LDRdPtrPd)
52 : O << '-';
53 :
54 78 : printOperand(MI, 1, O);
55 :
56 78 : if (Opcode == AVR::LDRdPtrPi)
57 : O << '+';
58 : break;
59 41 : case AVR::STPtrRr:
60 41 : O << "\tst\t";
61 41 : printOperand(MI, 0, O);
62 41 : O << ", ";
63 41 : printOperand(MI, 1, O);
64 41 : break;
65 23 : case AVR::STPtrPiRr:
66 : case AVR::STPtrPdRr:
67 23 : O << "\tst\t";
68 :
69 23 : if (Opcode == AVR::STPtrPdRr)
70 : O << '-';
71 :
72 23 : printOperand(MI, 1, O);
73 :
74 23 : if (Opcode == AVR::STPtrPiRr)
75 : O << '+';
76 :
77 23 : O << ", ";
78 23 : printOperand(MI, 2, O);
79 23 : break;
80 9756 : default:
81 9756 : if (!printAliasInstr(MI, O))
82 9094 : printInstruction(MI, O);
83 :
84 9756 : printAnnotation(O, Annot);
85 9756 : break;
86 : }
87 9898 : }
88 :
89 5936 : 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 5936 : if (MRI.getNumSubRegIndices() > 0) {
94 5936 : unsigned RegLoNum = MRI.getSubReg(RegNum, AVR::sub_lo);
95 5936 : RegNum = (RegLoNum != AVR::NoRegister) ? RegLoNum : RegNum;
96 : }
97 :
98 5936 : return getRegisterName(RegNum);
99 : }
100 :
101 8479 : void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
102 : raw_ostream &O) {
103 : const MCOperand &Op = MI->getOperand(OpNo);
104 8479 : const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo];
105 :
106 8479 : if (Op.isReg()) {
107 13014 : bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
108 6507 : (MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
109 : (MOI.RegClass == AVR::ZREGRegClassID);
110 :
111 6507 : if (isPtrReg) {
112 573 : O << getRegisterName(Op.getReg(), AVR::ptr);
113 : } else {
114 5934 : O << getPrettyRegisterName(Op.getReg(), MRI);
115 : }
116 1972 : } else if (Op.isImm()) {
117 1634 : O << Op.getImm();
118 : } else {
119 : assert(Op.isExpr() && "Unknown operand kind in printOperand");
120 338 : O << *Op.getExpr();
121 : }
122 8479 : }
123 :
124 : /// This is used to print an immediate value that ends up
125 : /// being encoded as a pc-relative value.
126 252 : void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
127 : raw_ostream &O) {
128 : const MCOperand &Op = MI->getOperand(OpNo);
129 :
130 252 : if (Op.isImm()) {
131 0 : int64_t Imm = Op.getImm();
132 : O << '.';
133 :
134 : // Print a position sign if needed.
135 : // Negative values have their sign printed automatically.
136 0 : if (Imm >= 0)
137 : O << '+';
138 :
139 0 : O << Imm;
140 : } else {
141 : assert(Op.isExpr() && "Unknown pcrel immediate operand");
142 252 : O << *Op.getExpr();
143 : }
144 252 : }
145 :
146 401 : void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,
147 : raw_ostream &O) {
148 : assert(MI->getOperand(OpNo).isReg() && "Expected a register for the first operand");
149 :
150 401 : const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
151 :
152 : // Print the register.
153 401 : printOperand(MI, OpNo, O);
154 :
155 : // Print the {+,-}offset.
156 401 : if (OffsetOp.isImm()) {
157 399 : int64_t Offset = OffsetOp.getImm();
158 :
159 399 : if (Offset >= 0)
160 : O << '+';
161 :
162 399 : O << Offset;
163 2 : } else if (OffsetOp.isExpr()) {
164 2 : O << *OffsetOp.getExpr();
165 : } else {
166 0 : llvm_unreachable("unknown type for offset");
167 : }
168 401 : }
169 :
170 : } // end of namespace llvm
171 :
|