brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · 5adffee Raw
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