]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AVR/InstPrinter/AVRInstPrinter.cpp
MFV r339640,339641,339644:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AVR / InstPrinter / AVRInstPrinter.cpp
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 void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
37                                StringRef Annot, const MCSubtargetInfo &STI) {
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, O))
82       printInstruction(MI, 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 MCOperand &Op = MI->getOperand(OpNo);
104   const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo];
105
106   if (Op.isReg()) {
107     bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
108                     (MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
109                     (MOI.RegClass == AVR::ZREGRegClassID);
110
111     if (isPtrReg) {
112       O << getRegisterName(Op.getReg(), AVR::ptr);
113     } else {
114       O << getPrettyRegisterName(Op.getReg(), MRI);
115     }
116   } else if (Op.isImm()) {
117     O << Op.getImm();
118   } else {
119     assert(Op.isExpr() && "Unknown operand kind in printOperand");
120     O << *Op.getExpr();
121   }
122 }
123
124 /// This is used to print an immediate value that ends up
125 /// being encoded as a pc-relative value.
126 void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
127                                    raw_ostream &O) {
128   const MCOperand &Op = MI->getOperand(OpNo);
129
130   if (Op.isImm()) {
131     int64_t Imm = Op.getImm();
132     O << '.';
133
134     // Print a position sign if needed.
135     // Negative values have their sign printed automatically.
136     if (Imm >= 0)
137       O << '+';
138
139     O << Imm;
140   } else {
141     assert(Op.isExpr() && "Unknown pcrel immediate operand");
142     O << *Op.getExpr();
143   }
144 }
145
146 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   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
151
152   // Print the register.
153   printOperand(MI, OpNo, O);
154
155   // Print the {+,-}offset.
156   if (OffsetOp.isImm()) {
157     int64_t Offset = OffsetOp.getImm();
158
159     if (Offset >= 0)
160       O << '+';
161
162     O << Offset;
163   } else if (OffsetOp.isExpr()) {
164     O << *OffsetOp.getExpr();
165   } else {
166     llvm_unreachable("unknown type for offset");
167   }
168 }
169
170 } // end of namespace llvm
171