Path: blob/main/contrib/llvm-project/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp
35294 views
//===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This class prints an AVR MCInst to a .s file.9//10//===----------------------------------------------------------------------===//1112#include "AVRInstPrinter.h"1314#include "MCTargetDesc/AVRMCTargetDesc.h"1516#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCInst.h"18#include "llvm/MC/MCInstrDesc.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/MC/MCRegisterInfo.h"21#include "llvm/Support/ErrorHandling.h"22#include "llvm/Support/FormattedStream.h"2324#include <cstring>2526#define DEBUG_TYPE "asm-printer"2728namespace llvm {2930// Include the auto-generated portion of the assembly writer.31#define PRINT_ALIAS_INSTR32#include "AVRGenAsmWriter.inc"3334void AVRInstPrinter::printInst(const MCInst *MI, uint64_t Address,35StringRef Annot, const MCSubtargetInfo &STI,36raw_ostream &O) {37unsigned Opcode = MI->getOpcode();3839// First handle load and store instructions with postinc or predec40// of the form "ld reg, X+".41// TODO: We should be able to rewrite this using TableGen data.42switch (Opcode) {43case AVR::LDRdPtr:44case AVR::LDRdPtrPi:45case AVR::LDRdPtrPd:46O << "\tld\t";47printOperand(MI, 0, O);48O << ", ";4950if (Opcode == AVR::LDRdPtrPd)51O << '-';5253printOperand(MI, 1, O);5455if (Opcode == AVR::LDRdPtrPi)56O << '+';57break;58case AVR::STPtrRr:59O << "\tst\t";60printOperand(MI, 0, O);61O << ", ";62printOperand(MI, 1, O);63break;64case AVR::STPtrPiRr:65case AVR::STPtrPdRr:66O << "\tst\t";6768if (Opcode == AVR::STPtrPdRr)69O << '-';7071printOperand(MI, 1, O);7273if (Opcode == AVR::STPtrPiRr)74O << '+';7576O << ", ";77printOperand(MI, 2, O);78break;79default:80if (!printAliasInstr(MI, Address, O))81printInstruction(MI, Address, O);8283printAnnotation(O, Annot);84break;85}86}8788const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum,89MCRegisterInfo const &MRI) {90// GCC prints register pairs by just printing the lower register91// If the register contains a subregister, print it instead92if (MRI.getNumSubRegIndices() > 0) {93unsigned RegLoNum = MRI.getSubReg(RegNum, AVR::sub_lo);94RegNum = (RegLoNum != AVR::NoRegister) ? RegLoNum : RegNum;95}9697return getRegisterName(RegNum);98}99100void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,101raw_ostream &O) {102const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).operands()[OpNo];103if (MOI.RegClass == AVR::ZREGRegClassID) {104// Special case for the Z register, which sometimes doesn't have an operand105// in the MCInst.106O << "Z";107return;108}109110if (OpNo >= MI->size()) {111// Not all operands are correctly disassembled at the moment. This means112// that some machine instructions won't have all the necessary operands113// set.114// To avoid asserting, print <unknown> instead until the necessary support115// has been implemented.116O << "<unknown>";117return;118}119120const MCOperand &Op = MI->getOperand(OpNo);121122if (Op.isReg()) {123bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||124(MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||125(MOI.RegClass == AVR::ZREGRegClassID);126127if (isPtrReg) {128O << getRegisterName(Op.getReg(), AVR::ptr);129} else {130O << getPrettyRegisterName(Op.getReg(), MRI);131}132} else if (Op.isImm()) {133O << formatImm(Op.getImm());134} else {135assert(Op.isExpr() && "Unknown operand kind in printOperand");136O << *Op.getExpr();137}138}139140/// This is used to print an immediate value that ends up141/// being encoded as a pc-relative value.142void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,143raw_ostream &O) {144if (OpNo >= MI->size()) {145// Not all operands are correctly disassembled at the moment. This means146// that some machine instructions won't have all the necessary operands147// set.148// To avoid asserting, print <unknown> instead until the necessary support149// has been implemented.150O << "<unknown>";151return;152}153154const MCOperand &Op = MI->getOperand(OpNo);155156if (Op.isImm()) {157int64_t Imm = Op.getImm();158O << '.';159160// Print a position sign if needed.161// Negative values have their sign printed automatically.162if (Imm >= 0)163O << '+';164165O << Imm;166} else {167assert(Op.isExpr() && "Unknown pcrel immediate operand");168O << *Op.getExpr();169}170}171172void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,173raw_ostream &O) {174assert(MI->getOperand(OpNo).isReg() &&175"Expected a register for the first operand");176177const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);178179// Print the register.180printOperand(MI, OpNo, O);181182// Print the {+,-}offset.183if (OffsetOp.isImm()) {184int64_t Offset = OffsetOp.getImm();185186if (Offset >= 0)187O << '+';188189O << Offset;190} else if (OffsetOp.isExpr()) {191O << *OffsetOp.getExpr();192} else {193llvm_unreachable("unknown type for offset");194}195}196197} // end of namespace llvm198199200