182 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This class prints an AVR MCInst to a .s file.10//11//===----------------------------------------------------------------------===//12 13#include "AVRInstPrinter.h"14 15#include "MCTargetDesc/AVRMCTargetDesc.h"16 17#include "llvm/MC/MCAsmInfo.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 25#include <cstring>26 27#define DEBUG_TYPE "asm-printer"28 29namespace llvm {30 31// Include the auto-generated portion of the assembly writer.32#define PRINT_ALIAS_INSTR33#include "AVRGenAsmWriter.inc"34 35void AVRInstPrinter::printInst(const MCInst *MI, uint64_t Address,36 StringRef Annot, const MCSubtargetInfo &STI,37 raw_ostream &O) {38 unsigned Opcode = MI->getOpcode();39 40 // First handle load and store instructions with postinc or predec41 // 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, Address, O))82 printInstruction(MI, Address, O);83 84 printAnnotation(O, Annot);85 break;86 }87}88 89const char *AVRInstPrinter::getPrettyRegisterName(MCRegister Reg,90 MCRegisterInfo const &MRI) {91 // GCC prints register pairs by just printing the lower register92 // If the register contains a subregister, print it instead93 if (MRI.getNumSubRegIndices() > 0) {94 MCRegister RegLo = MRI.getSubReg(Reg, AVR::sub_lo);95 Reg = (RegLo != AVR::NoRegister) ? RegLo : Reg;96 }97 98 return getRegisterName(Reg);99}100 101void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,102 raw_ostream &O) {103 const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).operands()[OpNo];104 const MCOperand &Op = MI->getOperand(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 << formatImm(Op.getImm());118 } else {119 assert(Op.isExpr() && "Unknown operand kind in printOperand");120 MAI.printExpr(O, *Op.getExpr());121 }122}123 124/// This is used to print an immediate value that ends up125/// being encoded as a pc-relative value.126void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,127 raw_ostream &O) {128 if (OpNo >= MI->size()) {129 // Not all operands are correctly disassembled at the moment. This means130 // that some machine instructions won't have all the necessary operands131 // set.132 // To avoid asserting, print <unknown> instead until the necessary support133 // has been implemented.134 O << "<unknown>";135 return;136 }137 138 const MCOperand &Op = MI->getOperand(OpNo);139 140 if (Op.isImm()) {141 int64_t Imm = Op.getImm();142 O << '.';143 144 // Print a position sign if needed.145 // Negative values have their sign printed automatically.146 if (Imm >= 0)147 O << '+';148 149 O << Imm;150 } else {151 assert(Op.isExpr() && "Unknown pcrel immediate operand");152 MAI.printExpr(O, *Op.getExpr());153 }154}155 156void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,157 raw_ostream &O) {158 assert(MI->getOperand(OpNo).isReg() &&159 "Expected a register for the first operand");160 161 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);162 163 // Print the register.164 printOperand(MI, OpNo, O);165 166 // Print the {+,-}offset.167 if (OffsetOp.isImm()) {168 int64_t Offset = OffsetOp.getImm();169 170 if (Offset >= 0)171 O << '+';172 173 O << Offset;174 } else if (OffsetOp.isExpr()) {175 MAI.printExpr(O, *OffsetOp.getExpr());176 } else {177 llvm_unreachable("unknown type for offset");178 }179}180 181} // end of namespace llvm182