Path: blob/main/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
35267 views
//===- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly ---===//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 file contains a printer that converts from our internal representation9// of machine-dependent LLVM code to Hexagon assembly language. This printer is10// the output mechanism used by `llc'.11//12//===----------------------------------------------------------------------===//1314#include "HexagonAsmPrinter.h"15#include "Hexagon.h"16#include "HexagonInstrInfo.h"17#include "HexagonRegisterInfo.h"18#include "HexagonSubtarget.h"19#include "HexagonTargetStreamer.h"20#include "MCTargetDesc/HexagonInstPrinter.h"21#include "MCTargetDesc/HexagonMCExpr.h"22#include "MCTargetDesc/HexagonMCInstrInfo.h"23#include "MCTargetDesc/HexagonMCTargetDesc.h"24#include "TargetInfo/HexagonTargetInfo.h"25#include "llvm/ADT/StringExtras.h"26#include "llvm/ADT/StringRef.h"27#include "llvm/ADT/Twine.h"28#include "llvm/BinaryFormat/ELF.h"29#include "llvm/CodeGen/AsmPrinter.h"30#include "llvm/CodeGen/MachineBasicBlock.h"31#include "llvm/CodeGen/MachineFunction.h"32#include "llvm/CodeGen/MachineInstr.h"33#include "llvm/CodeGen/MachineOperand.h"34#include "llvm/CodeGen/TargetRegisterInfo.h"35#include "llvm/CodeGen/TargetSubtargetInfo.h"36#include "llvm/MC/MCContext.h"37#include "llvm/MC/MCDirectives.h"38#include "llvm/MC/MCExpr.h"39#include "llvm/MC/MCInst.h"40#include "llvm/MC/MCRegisterInfo.h"41#include "llvm/MC/MCSectionELF.h"42#include "llvm/MC/MCStreamer.h"43#include "llvm/MC/MCSymbol.h"44#include "llvm/MC/TargetRegistry.h"45#include "llvm/Support/Casting.h"46#include "llvm/Support/CommandLine.h"47#include "llvm/Support/ErrorHandling.h"48#include "llvm/Support/raw_ostream.h"49#include "llvm/Target/TargetMachine.h"50#include <algorithm>51#include <cassert>52#include <cstdint>53#include <string>5455using namespace llvm;5657namespace llvm {5859void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,60MCInst &MCB, HexagonAsmPrinter &AP);6162} // end namespace llvm6364#define DEBUG_TYPE "asm-printer"6566// Given a scalar register return its pair.67inline static unsigned getHexagonRegisterPair(unsigned Reg,68const MCRegisterInfo *RI) {69assert(Hexagon::IntRegsRegClass.contains(Reg));70unsigned Pair = *RI->superregs(Reg).begin();71assert(Hexagon::DoubleRegsRegClass.contains(Pair));72return Pair;73}7475void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,76raw_ostream &O) {77const MachineOperand &MO = MI->getOperand(OpNo);7879switch (MO.getType()) {80default:81llvm_unreachable ("<unknown operand type>");82case MachineOperand::MO_Register:83O << HexagonInstPrinter::getRegisterName(MO.getReg());84return;85case MachineOperand::MO_Immediate:86O << MO.getImm();87return;88case MachineOperand::MO_MachineBasicBlock:89MO.getMBB()->getSymbol()->print(O, MAI);90return;91case MachineOperand::MO_ConstantPoolIndex:92GetCPISymbol(MO.getIndex())->print(O, MAI);93return;94case MachineOperand::MO_GlobalAddress:95PrintSymbolOperand(MO, O);96return;97}98}99100// isBlockOnlyReachableByFallthrough - We need to override this since the101// default AsmPrinter does not print labels for any basic block that102// is only reachable by a fall through. That works for all cases except103// for the case in which the basic block is reachable by a fall through but104// through an indirect from a jump table. In this case, the jump table105// will contain a label not defined by AsmPrinter.106bool HexagonAsmPrinter::isBlockOnlyReachableByFallthrough(107const MachineBasicBlock *MBB) const {108if (MBB->hasAddressTaken())109return false;110return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB);111}112113/// PrintAsmOperand - Print out an operand for an inline asm expression.114bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,115const char *ExtraCode,116raw_ostream &OS) {117// Does this asm operand have a single letter operand modifier?118if (ExtraCode && ExtraCode[0]) {119if (ExtraCode[1] != 0)120return true; // Unknown modifier.121122switch (ExtraCode[0]) {123default:124// See if this is a generic print operand125return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);126case 'L':127case 'H': { // The highest-numbered register of a pair.128const MachineOperand &MO = MI->getOperand(OpNo);129const MachineFunction &MF = *MI->getParent()->getParent();130const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();131if (!MO.isReg())132return true;133Register RegNumber = MO.getReg();134// This should be an assert in the frontend.135if (Hexagon::DoubleRegsRegClass.contains(RegNumber))136RegNumber = TRI->getSubReg(RegNumber, ExtraCode[0] == 'L' ?137Hexagon::isub_lo :138Hexagon::isub_hi);139OS << HexagonInstPrinter::getRegisterName(RegNumber);140return false;141}142case 'I':143// Write 'i' if an integer constant, otherwise nothing. Used to print144// addi vs add, etc.145if (MI->getOperand(OpNo).isImm())146OS << "i";147return false;148}149}150151printOperand(MI, OpNo, OS);152return false;153}154155bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,156unsigned OpNo,157const char *ExtraCode,158raw_ostream &O) {159if (ExtraCode && ExtraCode[0])160return true; // Unknown modifier.161162const MachineOperand &Base = MI->getOperand(OpNo);163const MachineOperand &Offset = MI->getOperand(OpNo+1);164165if (Base.isReg())166printOperand(MI, OpNo, O);167else168llvm_unreachable("Unimplemented");169170if (Offset.isImm()) {171if (Offset.getImm())172O << "+#" << Offset.getImm();173} else {174llvm_unreachable("Unimplemented");175}176177return false;178}179180static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI,181MCStreamer &OutStreamer, const MCOperand &Imm,182int AlignSize, const MCSubtargetInfo& STI) {183MCSymbol *Sym;184int64_t Value;185if (Imm.getExpr()->evaluateAsAbsolute(Value)) {186StringRef sectionPrefix;187std::string ImmString;188StringRef Name;189if (AlignSize == 8) {190Name = ".CONST_0000000000000000";191sectionPrefix = ".gnu.linkonce.l8";192ImmString = utohexstr(Value);193} else {194Name = ".CONST_00000000";195sectionPrefix = ".gnu.linkonce.l4";196ImmString = utohexstr(static_cast<uint32_t>(Value));197}198199std::string symbolName = // Yes, leading zeros are kept.200Name.drop_back(ImmString.size()).str() + ImmString;201std::string sectionName = sectionPrefix.str() + symbolName;202203MCSectionELF *Section = OutStreamer.getContext().getELFSection(204sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);205OutStreamer.switchSection(Section);206207Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName));208if (Sym->isUndefined()) {209OutStreamer.emitLabel(Sym);210OutStreamer.emitSymbolAttribute(Sym, MCSA_Global);211OutStreamer.emitIntValue(Value, AlignSize);212OutStreamer.emitCodeAlignment(Align(AlignSize), &STI);213}214} else {215assert(Imm.isExpr() && "Expected expression and found none");216const MachineOperand &MO = MI.getOperand(1);217assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());218MCSymbol *MOSymbol = nullptr;219if (MO.isGlobal())220MOSymbol = AP.getSymbol(MO.getGlobal());221else if (MO.isCPI())222MOSymbol = AP.GetCPISymbol(MO.getIndex());223else if (MO.isJTI())224MOSymbol = AP.GetJTISymbol(MO.getIndex());225else226llvm_unreachable("Unknown operand type!");227228StringRef SymbolName = MOSymbol->getName();229std::string LitaName = ".CONST_" + SymbolName.str();230231MCSectionELF *Section = OutStreamer.getContext().getELFSection(232".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);233234OutStreamer.switchSection(Section);235Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName));236if (Sym->isUndefined()) {237OutStreamer.emitLabel(Sym);238OutStreamer.emitSymbolAttribute(Sym, MCSA_Local);239OutStreamer.emitValue(Imm.getExpr(), AlignSize);240OutStreamer.emitCodeAlignment(Align(AlignSize), &STI);241}242}243return Sym;244}245246static MCInst ScaleVectorOffset(MCInst &Inst, unsigned OpNo,247unsigned VectorSize, MCContext &Ctx) {248MCInst T;249T.setOpcode(Inst.getOpcode());250for (unsigned i = 0, n = Inst.getNumOperands(); i != n; ++i) {251if (i != OpNo) {252T.addOperand(Inst.getOperand(i));253continue;254}255MCOperand &ImmOp = Inst.getOperand(i);256const auto *HE = static_cast<const HexagonMCExpr*>(ImmOp.getExpr());257int32_t V = cast<MCConstantExpr>(HE->getExpr())->getValue();258auto *NewCE = MCConstantExpr::create(V / int32_t(VectorSize), Ctx);259auto *NewHE = HexagonMCExpr::create(NewCE, Ctx);260T.addOperand(MCOperand::createExpr(NewHE));261}262return T;263}264265void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst,266const MachineInstr &MI) {267MCInst &MappedInst = static_cast <MCInst &>(Inst);268const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo();269const MachineFunction &MF = *MI.getParent()->getParent();270auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();271unsigned VectorSize = HRI.getRegSizeInBits(Hexagon::HvxVRRegClass) / 8;272273switch (Inst.getOpcode()) {274default:275return;276277case Hexagon::A2_iconst: {278Inst.setOpcode(Hexagon::A2_addi);279MCOperand Reg = Inst.getOperand(0);280MCOperand S16 = Inst.getOperand(1);281HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr());282HexagonMCInstrInfo::setS27_2_reloc(*S16.getExpr());283Inst.clear();284Inst.addOperand(Reg);285Inst.addOperand(MCOperand::createReg(Hexagon::R0));286Inst.addOperand(S16);287break;288}289290case Hexagon::A2_tfrf: {291const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext);292Inst.setOpcode(Hexagon::A2_paddif);293Inst.addOperand(MCOperand::createExpr(Zero));294break;295}296297case Hexagon::A2_tfrt: {298const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext);299Inst.setOpcode(Hexagon::A2_paddit);300Inst.addOperand(MCOperand::createExpr(Zero));301break;302}303304case Hexagon::A2_tfrfnew: {305const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext);306Inst.setOpcode(Hexagon::A2_paddifnew);307Inst.addOperand(MCOperand::createExpr(Zero));308break;309}310311case Hexagon::A2_tfrtnew: {312const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext);313Inst.setOpcode(Hexagon::A2_padditnew);314Inst.addOperand(MCOperand::createExpr(Zero));315break;316}317318case Hexagon::A2_zxtb: {319const MCConstantExpr *C255 = MCConstantExpr::create(255, OutContext);320Inst.setOpcode(Hexagon::A2_andir);321Inst.addOperand(MCOperand::createExpr(C255));322break;323}324325// "$dst = CONST64(#$src1)",326case Hexagon::CONST64:327if (!OutStreamer->hasRawTextSupport()) {328const MCOperand &Imm = MappedInst.getOperand(1);329MCSectionSubPair Current = OutStreamer->getCurrentSection();330331MCSymbol *Sym =332smallData(*this, MI, *OutStreamer, Imm, 8, getSubtargetInfo());333334OutStreamer->switchSection(Current.first, Current.second);335MCInst TmpInst;336MCOperand &Reg = MappedInst.getOperand(0);337TmpInst.setOpcode(Hexagon::L2_loadrdgp);338TmpInst.addOperand(Reg);339TmpInst.addOperand(MCOperand::createExpr(340MCSymbolRefExpr::create(Sym, OutContext)));341MappedInst = TmpInst;342343}344break;345case Hexagon::CONST32:346if (!OutStreamer->hasRawTextSupport()) {347MCOperand &Imm = MappedInst.getOperand(1);348MCSectionSubPair Current = OutStreamer->getCurrentSection();349MCSymbol *Sym =350smallData(*this, MI, *OutStreamer, Imm, 4, getSubtargetInfo());351OutStreamer->switchSection(Current.first, Current.second);352MCInst TmpInst;353MCOperand &Reg = MappedInst.getOperand(0);354TmpInst.setOpcode(Hexagon::L2_loadrigp);355TmpInst.addOperand(Reg);356TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(357MCSymbolRefExpr::create(Sym, OutContext), OutContext)));358MappedInst = TmpInst;359}360break;361362// C2_pxfer_map maps to C2_or instruction. Though, it's possible to use363// C2_or during instruction selection itself but it results364// into suboptimal code.365case Hexagon::C2_pxfer_map: {366MCOperand &Ps = Inst.getOperand(1);367MappedInst.setOpcode(Hexagon::C2_or);368MappedInst.addOperand(Ps);369return;370}371372// Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo373// The insn is mapped from the 4 operand to the 3 operand raw form taking374// 3 register pairs.375case Hexagon::M2_vrcmpys_acc_s1: {376MCOperand &Rt = Inst.getOperand(3);377assert(Rt.isReg() && "Expected register and none was found");378unsigned Reg = RI->getEncodingValue(Rt.getReg());379if (Reg & 1)380MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);381else382MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);383Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));384return;385}386case Hexagon::M2_vrcmpys_s1: {387MCOperand &Rt = Inst.getOperand(2);388assert(Rt.isReg() && "Expected register and none was found");389unsigned Reg = RI->getEncodingValue(Rt.getReg());390if (Reg & 1)391MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h);392else393MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l);394Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));395return;396}397398case Hexagon::M2_vrcmpys_s1rp: {399MCOperand &Rt = Inst.getOperand(2);400assert(Rt.isReg() && "Expected register and none was found");401unsigned Reg = RI->getEncodingValue(Rt.getReg());402if (Reg & 1)403MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);404else405MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);406Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));407return;408}409410case Hexagon::A4_boundscheck: {411MCOperand &Rs = Inst.getOperand(1);412assert(Rs.isReg() && "Expected register and none was found");413unsigned Reg = RI->getEncodingValue(Rs.getReg());414if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2415MappedInst.setOpcode(Hexagon::A4_boundscheck_hi);416else // raw:lo417MappedInst.setOpcode(Hexagon::A4_boundscheck_lo);418Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI));419return;420}421422case Hexagon::PS_call_nr:423Inst.setOpcode(Hexagon::J2_call);424break;425426case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {427MCOperand &MO = MappedInst.getOperand(2);428int64_t Imm;429MCExpr const *Expr = MO.getExpr();430bool Success = Expr->evaluateAsAbsolute(Imm);431assert(Success && "Expected immediate and none was found");432(void)Success;433MCInst TmpInst;434if (Imm == 0) {435TmpInst.setOpcode(Hexagon::S2_vsathub);436TmpInst.addOperand(MappedInst.getOperand(0));437TmpInst.addOperand(MappedInst.getOperand(1));438MappedInst = TmpInst;439return;440}441TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat);442TmpInst.addOperand(MappedInst.getOperand(0));443TmpInst.addOperand(MappedInst.getOperand(1));444const MCExpr *One = MCConstantExpr::create(1, OutContext);445const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);446TmpInst.addOperand(447MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));448MappedInst = TmpInst;449return;450}451452case Hexagon::S5_vasrhrnd_goodsyntax:453case Hexagon::S2_asr_i_p_rnd_goodsyntax: {454MCOperand &MO2 = MappedInst.getOperand(2);455MCExpr const *Expr = MO2.getExpr();456int64_t Imm;457bool Success = Expr->evaluateAsAbsolute(Imm);458assert(Success && "Expected immediate and none was found");459(void)Success;460MCInst TmpInst;461if (Imm == 0) {462TmpInst.setOpcode(Hexagon::A2_combinew);463TmpInst.addOperand(MappedInst.getOperand(0));464MCOperand &MO1 = MappedInst.getOperand(1);465unsigned High = RI->getSubReg(MO1.getReg(), Hexagon::isub_hi);466unsigned Low = RI->getSubReg(MO1.getReg(), Hexagon::isub_lo);467// Add a new operand for the second register in the pair.468TmpInst.addOperand(MCOperand::createReg(High));469TmpInst.addOperand(MCOperand::createReg(Low));470MappedInst = TmpInst;471return;472}473474if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax)475TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd);476else477TmpInst.setOpcode(Hexagon::S5_vasrhrnd);478TmpInst.addOperand(MappedInst.getOperand(0));479TmpInst.addOperand(MappedInst.getOperand(1));480const MCExpr *One = MCConstantExpr::create(1, OutContext);481const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);482TmpInst.addOperand(483MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));484MappedInst = TmpInst;485return;486}487488// if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd489case Hexagon::S2_asr_i_r_rnd_goodsyntax: {490MCOperand &MO = Inst.getOperand(2);491MCExpr const *Expr = MO.getExpr();492int64_t Imm;493bool Success = Expr->evaluateAsAbsolute(Imm);494assert(Success && "Expected immediate and none was found");495(void)Success;496MCInst TmpInst;497if (Imm == 0) {498TmpInst.setOpcode(Hexagon::A2_tfr);499TmpInst.addOperand(MappedInst.getOperand(0));500TmpInst.addOperand(MappedInst.getOperand(1));501MappedInst = TmpInst;502return;503}504TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);505TmpInst.addOperand(MappedInst.getOperand(0));506TmpInst.addOperand(MappedInst.getOperand(1));507const MCExpr *One = MCConstantExpr::create(1, OutContext);508const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);509TmpInst.addOperand(510MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));511MappedInst = TmpInst;512return;513}514515// Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)"516case Hexagon::A2_tfrpi: {517MCInst TmpInst;518MCOperand &Rdd = MappedInst.getOperand(0);519MCOperand &MO = MappedInst.getOperand(1);520521TmpInst.setOpcode(Hexagon::A2_combineii);522TmpInst.addOperand(Rdd);523int64_t Imm;524bool Success = MO.getExpr()->evaluateAsAbsolute(Imm);525if (Success && Imm < 0) {526const MCExpr *MOne = MCConstantExpr::create(-1, OutContext);527const HexagonMCExpr *E = HexagonMCExpr::create(MOne, OutContext);528TmpInst.addOperand(MCOperand::createExpr(E));529} else {530const MCExpr *Zero = MCConstantExpr::create(0, OutContext);531const HexagonMCExpr *E = HexagonMCExpr::create(Zero, OutContext);532TmpInst.addOperand(MCOperand::createExpr(E));533}534TmpInst.addOperand(MO);535MappedInst = TmpInst;536return;537}538539// Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"540case Hexagon::A2_tfrp: {541MCOperand &MO = MappedInst.getOperand(1);542unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi);543unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo);544MO.setReg(High);545// Add a new operand for the second register in the pair.546MappedInst.addOperand(MCOperand::createReg(Low));547MappedInst.setOpcode(Hexagon::A2_combinew);548return;549}550551case Hexagon::A2_tfrpt:552case Hexagon::A2_tfrpf: {553MCOperand &MO = MappedInst.getOperand(2);554unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi);555unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo);556MO.setReg(High);557// Add a new operand for the second register in the pair.558MappedInst.addOperand(MCOperand::createReg(Low));559MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)560? Hexagon::C2_ccombinewt561: Hexagon::C2_ccombinewf);562return;563}564565case Hexagon::A2_tfrptnew:566case Hexagon::A2_tfrpfnew: {567MCOperand &MO = MappedInst.getOperand(2);568unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi);569unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo);570MO.setReg(High);571// Add a new operand for the second register in the pair.572MappedInst.addOperand(MCOperand::createReg(Low));573MappedInst.setOpcode(Inst.getOpcode() == Hexagon::A2_tfrptnew574? Hexagon::C2_ccombinewnewt575: Hexagon::C2_ccombinewnewf);576return;577}578579case Hexagon::M2_mpysmi: {580MCOperand &Imm = MappedInst.getOperand(2);581MCExpr const *Expr = Imm.getExpr();582int64_t Value;583bool Success = Expr->evaluateAsAbsolute(Value);584assert(Success);585(void)Success;586if (Value < 0 && Value > -256) {587MappedInst.setOpcode(Hexagon::M2_mpysin);588Imm.setExpr(HexagonMCExpr::create(589MCUnaryExpr::createMinus(Expr, OutContext), OutContext));590} else591MappedInst.setOpcode(Hexagon::M2_mpysip);592return;593}594595case Hexagon::A2_addsp: {596MCOperand &Rt = Inst.getOperand(1);597assert(Rt.isReg() && "Expected register and none was found");598unsigned Reg = RI->getEncodingValue(Rt.getReg());599if (Reg & 1)600MappedInst.setOpcode(Hexagon::A2_addsph);601else602MappedInst.setOpcode(Hexagon::A2_addspl);603Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));604return;605}606607case Hexagon::V6_vd0: {608MCInst TmpInst;609assert(Inst.getOperand(0).isReg() &&610"Expected register and none was found");611612TmpInst.setOpcode(Hexagon::V6_vxor);613TmpInst.addOperand(Inst.getOperand(0));614TmpInst.addOperand(Inst.getOperand(0));615TmpInst.addOperand(Inst.getOperand(0));616MappedInst = TmpInst;617return;618}619620case Hexagon::V6_vdd0: {621MCInst TmpInst;622assert (Inst.getOperand(0).isReg() &&623"Expected register and none was found");624625TmpInst.setOpcode(Hexagon::V6_vsubw_dv);626TmpInst.addOperand(Inst.getOperand(0));627TmpInst.addOperand(Inst.getOperand(0));628TmpInst.addOperand(Inst.getOperand(0));629MappedInst = TmpInst;630return;631}632633case Hexagon::V6_vL32Ub_pi:634case Hexagon::V6_vL32b_cur_pi:635case Hexagon::V6_vL32b_nt_cur_pi:636case Hexagon::V6_vL32b_pi:637case Hexagon::V6_vL32b_nt_pi:638case Hexagon::V6_vL32b_nt_tmp_pi:639case Hexagon::V6_vL32b_tmp_pi:640MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext);641return;642643case Hexagon::V6_vL32Ub_ai:644case Hexagon::V6_vL32b_ai:645case Hexagon::V6_vL32b_cur_ai:646case Hexagon::V6_vL32b_nt_ai:647case Hexagon::V6_vL32b_nt_cur_ai:648case Hexagon::V6_vL32b_nt_tmp_ai:649case Hexagon::V6_vL32b_tmp_ai:650MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext);651return;652653case Hexagon::V6_vS32Ub_pi:654case Hexagon::V6_vS32b_new_pi:655case Hexagon::V6_vS32b_nt_new_pi:656case Hexagon::V6_vS32b_nt_pi:657case Hexagon::V6_vS32b_pi:658MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext);659return;660661case Hexagon::V6_vS32Ub_ai:662case Hexagon::V6_vS32b_ai:663case Hexagon::V6_vS32b_new_ai:664case Hexagon::V6_vS32b_nt_ai:665case Hexagon::V6_vS32b_nt_new_ai:666MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext);667return;668669case Hexagon::V6_vL32b_cur_npred_pi:670case Hexagon::V6_vL32b_cur_pred_pi:671case Hexagon::V6_vL32b_npred_pi:672case Hexagon::V6_vL32b_nt_cur_npred_pi:673case Hexagon::V6_vL32b_nt_cur_pred_pi:674case Hexagon::V6_vL32b_nt_npred_pi:675case Hexagon::V6_vL32b_nt_pred_pi:676case Hexagon::V6_vL32b_nt_tmp_npred_pi:677case Hexagon::V6_vL32b_nt_tmp_pred_pi:678case Hexagon::V6_vL32b_pred_pi:679case Hexagon::V6_vL32b_tmp_npred_pi:680case Hexagon::V6_vL32b_tmp_pred_pi:681MappedInst = ScaleVectorOffset(Inst, 4, VectorSize, OutContext);682return;683684case Hexagon::V6_vL32b_cur_npred_ai:685case Hexagon::V6_vL32b_cur_pred_ai:686case Hexagon::V6_vL32b_npred_ai:687case Hexagon::V6_vL32b_nt_cur_npred_ai:688case Hexagon::V6_vL32b_nt_cur_pred_ai:689case Hexagon::V6_vL32b_nt_npred_ai:690case Hexagon::V6_vL32b_nt_pred_ai:691case Hexagon::V6_vL32b_nt_tmp_npred_ai:692case Hexagon::V6_vL32b_nt_tmp_pred_ai:693case Hexagon::V6_vL32b_pred_ai:694case Hexagon::V6_vL32b_tmp_npred_ai:695case Hexagon::V6_vL32b_tmp_pred_ai:696MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext);697return;698699case Hexagon::V6_vS32Ub_npred_pi:700case Hexagon::V6_vS32Ub_pred_pi:701case Hexagon::V6_vS32b_new_npred_pi:702case Hexagon::V6_vS32b_new_pred_pi:703case Hexagon::V6_vS32b_npred_pi:704case Hexagon::V6_vS32b_nqpred_pi:705case Hexagon::V6_vS32b_nt_new_npred_pi:706case Hexagon::V6_vS32b_nt_new_pred_pi:707case Hexagon::V6_vS32b_nt_npred_pi:708case Hexagon::V6_vS32b_nt_nqpred_pi:709case Hexagon::V6_vS32b_nt_pred_pi:710case Hexagon::V6_vS32b_nt_qpred_pi:711case Hexagon::V6_vS32b_pred_pi:712case Hexagon::V6_vS32b_qpred_pi:713MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext);714return;715716case Hexagon::V6_vS32Ub_npred_ai:717case Hexagon::V6_vS32Ub_pred_ai:718case Hexagon::V6_vS32b_new_npred_ai:719case Hexagon::V6_vS32b_new_pred_ai:720case Hexagon::V6_vS32b_npred_ai:721case Hexagon::V6_vS32b_nqpred_ai:722case Hexagon::V6_vS32b_nt_new_npred_ai:723case Hexagon::V6_vS32b_nt_new_pred_ai:724case Hexagon::V6_vS32b_nt_npred_ai:725case Hexagon::V6_vS32b_nt_nqpred_ai:726case Hexagon::V6_vS32b_nt_pred_ai:727case Hexagon::V6_vS32b_nt_qpred_ai:728case Hexagon::V6_vS32b_pred_ai:729case Hexagon::V6_vS32b_qpred_ai:730MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext);731return;732733// V65+734case Hexagon::V6_vS32b_srls_ai:735MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext);736return;737738case Hexagon::V6_vS32b_srls_pi:739MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext);740return;741}742}743744/// Print out a single Hexagon MI to the current output stream.745void HexagonAsmPrinter::emitInstruction(const MachineInstr *MI) {746Hexagon_MC::verifyInstructionPredicates(MI->getOpcode(),747getSubtargetInfo().getFeatureBits());748749MCInst MCB;750MCB.setOpcode(Hexagon::BUNDLE);751MCB.addOperand(MCOperand::createImm(0));752const MCInstrInfo &MCII = *Subtarget->getInstrInfo();753754if (MI->isBundle()) {755const MachineBasicBlock* MBB = MI->getParent();756MachineBasicBlock::const_instr_iterator MII = MI->getIterator();757758for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII)759if (!MII->isDebugInstr() && !MII->isImplicitDef())760HexagonLowerToMC(MCII, &*MII, MCB, *this);761} else {762HexagonLowerToMC(MCII, MI, MCB, *this);763}764765const MachineFunction &MF = *MI->getParent()->getParent();766const auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();767if (MI->isBundle() && HII.getBundleNoShuf(*MI))768HexagonMCInstrInfo::setMemReorderDisabled(MCB);769770MCContext &Ctx = OutStreamer->getContext();771bool Ok = HexagonMCInstrInfo::canonicalizePacket(MCII, *Subtarget, Ctx,772MCB, nullptr);773assert(Ok); (void)Ok;774if (HexagonMCInstrInfo::bundleSize(MCB) == 0)775return;776OutStreamer->emitInstruction(MCB, getSubtargetInfo());777}778779void HexagonAsmPrinter::emitStartOfAsmFile(Module &M) {780if (TM.getTargetTriple().isOSBinFormatELF())781emitAttributes();782}783784void HexagonAsmPrinter::emitEndOfAsmFile(Module &M) {785HexagonTargetStreamer &HTS =786static_cast<HexagonTargetStreamer &>(*OutStreamer->getTargetStreamer());787if (TM.getTargetTriple().isOSBinFormatELF())788HTS.finishAttributeSection();789}790791void HexagonAsmPrinter::emitAttributes() {792HexagonTargetStreamer &HTS =793static_cast<HexagonTargetStreamer &>(*OutStreamer->getTargetStreamer());794HTS.emitTargetAttributes(*TM.getMCSubtargetInfo());795}796797void HexagonAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) {798static const int8_t NoopsInSledCount = 4;799// We want to emit the following pattern:800//801// .L_xray_sled_N:802// <xray_sled_base>:803// { jump .Ltmp0 }804// { nop805// nop806// nop807// nop }808// .Ltmp0:809//810// We need the 4 nop words because at runtime, we'd be patching over the811// full 5 words with the following pattern:812//813// <xray_sled_n>:814// { immext(#...) // upper 26-bits of trampoline815// r6 = ##... // lower 6-bits of trampoline816// immext(#...) // upper 26-bits of func id817// r7 = ##... } // lower 6 bits of func id818// { callr r6 }819//820//821auto CurSled = OutContext.createTempSymbol("xray_sled_", true);822OutStreamer->emitLabel(CurSled);823824MCInst *SledJump = new (OutContext) MCInst();825SledJump->setOpcode(Hexagon::J2_jump);826auto PostSled = OutContext.createTempSymbol();827SledJump->addOperand(MCOperand::createExpr(HexagonMCExpr::create(828MCSymbolRefExpr::create(PostSled, OutContext), OutContext)));829830// Emit "jump PostSled" instruction, which jumps over the nop series.831MCInst SledJumpPacket;832SledJumpPacket.setOpcode(Hexagon::BUNDLE);833SledJumpPacket.addOperand(MCOperand::createImm(0));834SledJumpPacket.addOperand(MCOperand::createInst(SledJump));835836EmitToStreamer(*OutStreamer, SledJumpPacket);837838// FIXME: this will emit individual packets, we should839// special-case this and combine them into a single packet.840emitNops(NoopsInSledCount);841842OutStreamer->emitLabel(PostSled);843recordSled(CurSled, MI, Kind, 2);844}845846void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) {847EmitSled(MI, SledKind::FUNCTION_ENTER);848}849850void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) {851EmitSled(MI, SledKind::FUNCTION_EXIT);852}853854void HexagonAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) {855EmitSled(MI, SledKind::TAIL_CALL);856}857858extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmPrinter() {859RegisterAsmPrinter<HexagonAsmPrinter> X(getTheHexagonTarget());860}861862863