1 //===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class prints an AVR MCInst to a .s file.
12 //===----------------------------------------------------------------------===//
14 #include "AVRInstPrinter.h"
16 #include "MCTargetDesc/AVRMCTargetDesc.h"
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"
28 #define DEBUG_TYPE "asm-printer"
32 // Include the auto-generated portion of the assembly writer.
33 #define PRINT_ALIAS_INSTR
34 #include "AVRGenAsmWriter.inc"
36 void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
37 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, O))
82 printInstruction(MI, 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 MCOperand &Op = MI->getOperand(OpNo);
104 const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo];
107 bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
108 (MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
109 (MOI.RegClass == AVR::ZREGRegClassID);
112 O << getRegisterName(Op.getReg(), AVR::ptr);
114 O << getPrettyRegisterName(Op.getReg(), MRI);
116 } else if (Op.isImm()) {
119 assert(Op.isExpr() && "Unknown operand kind in printOperand");
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,
128 const MCOperand &Op = MI->getOperand(OpNo);
131 int64_t Imm = Op.getImm();
134 // Print a position sign if needed.
135 // Negative values have their sign printed automatically.
141 assert(Op.isExpr() && "Unknown pcrel immediate operand");
146 void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,
148 assert(MI->getOperand(OpNo).isReg() && "Expected a register for the first operand");
150 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
152 // Print the register.
153 printOperand(MI, OpNo, O);
155 // Print the {+,-}offset.
156 if (OffsetOp.isImm()) {
157 int64_t Offset = OffsetOp.getImm();
163 } else if (OffsetOp.isExpr()) {
164 O << *OffsetOp.getExpr();
166 llvm_unreachable("unknown type for offset");
170 } // end of namespace llvm