LLVM  9.0.0svn
AVRInstPrinter.cpp
Go to the documentation of this file.
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.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "AVRInstPrinter.h"
14 
16 
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"
24 
25 #include <cstring>
26 
27 #define DEBUG_TYPE "asm-printer"
28 
29 namespace llvm {
30 
31 // Include the auto-generated portion of the assembly writer.
32 #define PRINT_ALIAS_INSTR
33 #include "AVRGenAsmWriter.inc"
34 
36  StringRef Annot, const MCSubtargetInfo &STI) {
37  unsigned Opcode = MI->getOpcode();
38 
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 << ", ";
49 
50  if (Opcode == AVR::LDRdPtrPd)
51  O << '-';
52 
53  printOperand(MI, 1, O);
54 
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";
67 
68  if (Opcode == AVR::STPtrPdRr)
69  O << '-';
70 
71  printOperand(MI, 1, O);
72 
73  if (Opcode == AVR::STPtrPiRr)
74  O << '+';
75 
76  O << ", ";
77  printOperand(MI, 2, O);
78  break;
79  default:
80  if (!printAliasInstr(MI, O))
81  printInstruction(MI, O);
82 
83  printAnnotation(O, Annot);
84  break;
85  }
86 }
87 
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;
95  }
96 
97  return getRegisterName(RegNum);
98 }
99 
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];
104 
105  if (Op.isReg()) {
106  bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
107  (MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
108  (MOI.RegClass == AVR::ZREGRegClassID);
109 
110  if (isPtrReg) {
111  O << getRegisterName(Op.getReg(), AVR::ptr);
112  } else {
113  O << getPrettyRegisterName(Op.getReg(), MRI);
114  }
115  } else if (Op.isImm()) {
116  O << Op.getImm();
117  } else {
118  assert(Op.isExpr() && "Unknown operand kind in printOperand");
119  O << *Op.getExpr();
120  }
121 }
122 
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);
128 
129  if (Op.isImm()) {
130  int64_t Imm = Op.getImm();
131  O << '.';
132 
133  // Print a position sign if needed.
134  // Negative values have their sign printed automatically.
135  if (Imm >= 0)
136  O << '+';
137 
138  O << Imm;
139  } else {
140  assert(Op.isExpr() && "Unknown pcrel immediate operand");
141  O << *Op.getExpr();
142  }
143 }
144 
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");
148 
149  const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
150 
151  // Print the register.
152  printOperand(MI, OpNo, O);
153 
154  // Print the {+,-}offset.
155  if (OffsetOp.isImm()) {
156  int64_t Offset = OffsetOp.getImm();
157 
158  if (Offset >= 0)
159  O << '+';
160 
161  O << Offset;
162  } else if (OffsetOp.isExpr()) {
163  O << *OffsetOp.getExpr();
164  } else {
165  llvm_unreachable("unknown type for offset");
166  }
167 }
168 
169 } // end of namespace llvm
170 
bool isImm() const
Definition: MCInst.h:58
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool isReg() const
Definition: MCInst.h:57
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:64
const MCExpr * getExpr() const
Definition: MCInst.h:95
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
int64_t getImm() const
Definition: MCInst.h:75
unsigned getSubReg(unsigned Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo...
bool isExpr() const
Definition: MCInst.h:60
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:179
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) override
Print the specified MCInst to the specified raw_ostream.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition: MCInstrDesc.h:72
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:44
Generic base class for all target subtargets.
const MCInstrInfo & MII
Definition: MCInstPrinter.h:46
unsigned getNumSubRegIndices() const
Return the number of sub-register indices understood by the target.
static const char * getPrettyRegisterName(unsigned RegNo, MCRegisterInfo const &MRI)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:66
unsigned getOpcode() const
Definition: MCInst.h:171
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
const MCRegisterInfo & MRI
Definition: MCInstPrinter.h:47