brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.6 KiB · f22852d Raw
866 lines · cpp
1//===- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly ---===//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 file contains a printer that converts from our internal representation10// of machine-dependent LLVM code to Hexagon assembly language. This printer is11// the output mechanism used by `llc'.12//13//===----------------------------------------------------------------------===//14 15#include "HexagonAsmPrinter.h"16#include "HexagonInstrInfo.h"17#include "HexagonRegisterInfo.h"18#include "HexagonSubtarget.h"19#include "MCTargetDesc/HexagonInstPrinter.h"20#include "MCTargetDesc/HexagonMCExpr.h"21#include "MCTargetDesc/HexagonMCInstrInfo.h"22#include "MCTargetDesc/HexagonMCTargetDesc.h"23#include "MCTargetDesc/HexagonTargetStreamer.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/Compiler.h"47#include "llvm/Support/ErrorHandling.h"48#include "llvm/Support/raw_ostream.h"49#include "llvm/Target/TargetMachine.h"50#include <cassert>51#include <cstdint>52#include <string>53 54using namespace llvm;55 56namespace llvm {57 58void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,59                      MCInst &MCB, HexagonAsmPrinter &AP);60 61} // end namespace llvm62 63#define DEBUG_TYPE "asm-printer"64 65// Given a scalar register return its pair.66inline static unsigned getHexagonRegisterPair(unsigned Reg,67      const MCRegisterInfo *RI) {68  assert(Hexagon::IntRegsRegClass.contains(Reg));69  unsigned Pair = *RI->superregs(Reg).begin();70  assert(Hexagon::DoubleRegsRegClass.contains(Pair));71  return Pair;72}73 74void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,75                                     raw_ostream &O) {76  const MachineOperand &MO = MI->getOperand(OpNo);77 78  switch (MO.getType()) {79  default:80    llvm_unreachable ("<unknown operand type>");81  case MachineOperand::MO_Register:82    O << HexagonInstPrinter::getRegisterName(MO.getReg());83    return;84  case MachineOperand::MO_Immediate:85    O << MO.getImm();86    return;87  case MachineOperand::MO_MachineBasicBlock:88    MO.getMBB()->getSymbol()->print(O, MAI);89    return;90  case MachineOperand::MO_ConstantPoolIndex:91    GetCPISymbol(MO.getIndex())->print(O, MAI);92    return;93  case MachineOperand::MO_GlobalAddress:94    PrintSymbolOperand(MO, O);95    return;96  }97}98 99// isBlockOnlyReachableByFallthrough - We need to override this since the100// default AsmPrinter does not print labels for any basic block that101// is only reachable by a fall through. That works for all cases except102// for the case in which the basic block is reachable by a fall through but103// through an indirect from a jump table. In this case, the jump table104// will contain a label not defined by AsmPrinter.105bool HexagonAsmPrinter::isBlockOnlyReachableByFallthrough(106      const MachineBasicBlock *MBB) const {107  if (MBB->hasAddressTaken())108    return false;109  return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB);110}111 112/// PrintAsmOperand - Print out an operand for an inline asm expression.113bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,114                                        const char *ExtraCode,115                                        raw_ostream &OS) {116  // Does this asm operand have a single letter operand modifier?117  if (ExtraCode && ExtraCode[0]) {118    if (ExtraCode[1] != 0)119      return true; // Unknown modifier.120 121    switch (ExtraCode[0]) {122    default:123      // See if this is a generic print operand124      return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);125    case 'L':126    case 'H': { // The highest-numbered register of a pair.127      const MachineOperand &MO = MI->getOperand(OpNo);128      const MachineFunction &MF = *MI->getParent()->getParent();129      const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();130      if (!MO.isReg())131        return true;132      Register RegNumber = MO.getReg();133      // This should be an assert in the frontend.134      if (Hexagon::DoubleRegsRegClass.contains(RegNumber))135        RegNumber = TRI->getSubReg(RegNumber, ExtraCode[0] == 'L' ?136                                              Hexagon::isub_lo :137                                              Hexagon::isub_hi);138      OS << HexagonInstPrinter::getRegisterName(RegNumber);139      return false;140    }141    case 'I':142      // Write 'i' if an integer constant, otherwise nothing.  Used to print143      // addi vs add, etc.144      if (MI->getOperand(OpNo).isImm())145        OS << "i";146      return false;147    }148  }149 150  printOperand(MI, OpNo, OS);151  return false;152}153 154bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,155                                              unsigned OpNo,156                                              const char *ExtraCode,157                                              raw_ostream &O) {158  if (ExtraCode && ExtraCode[0])159    return true; // Unknown modifier.160 161  const MachineOperand &Base  = MI->getOperand(OpNo);162  const MachineOperand &Offset = MI->getOperand(OpNo+1);163 164  if (Base.isReg())165    printOperand(MI, OpNo, O);166  else167    llvm_unreachable("Unimplemented");168 169  if (Offset.isImm()) {170    if (Offset.getImm())171      O << "+#" << Offset.getImm();172  } else {173    llvm_unreachable("Unimplemented");174  }175 176  return false;177}178 179static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI,180                           MCStreamer &OutStreamer, const MCOperand &Imm,181                           int AlignSize, const MCSubtargetInfo& STI) {182  MCSymbol *Sym;183  int64_t Value;184  if (Imm.getExpr()->evaluateAsAbsolute(Value)) {185    StringRef sectionPrefix;186    std::string ImmString;187    StringRef Name;188    if (AlignSize == 8) {189       Name = ".CONST_0000000000000000";190       sectionPrefix = ".gnu.linkonce.l8";191       ImmString = utohexstr(Value);192    } else {193       Name = ".CONST_00000000";194       sectionPrefix = ".gnu.linkonce.l4";195       ImmString = utohexstr(static_cast<uint32_t>(Value));196    }197 198    std::string symbolName =   // Yes, leading zeros are kept.199      Name.drop_back(ImmString.size()).str() + ImmString;200    std::string sectionName = sectionPrefix.str() + symbolName;201 202    MCSectionELF *Section = OutStreamer.getContext().getELFSection(203        sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);204    OutStreamer.switchSection(Section);205 206    Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName));207    if (Sym->isUndefined()) {208      OutStreamer.emitLabel(Sym);209      OutStreamer.emitSymbolAttribute(Sym, MCSA_Global);210      OutStreamer.emitIntValue(Value, AlignSize);211      OutStreamer.emitCodeAlignment(Align(AlignSize), &STI);212    }213  } else {214    assert(Imm.isExpr() && "Expected expression and found none");215    const MachineOperand &MO = MI.getOperand(1);216    assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());217    MCSymbol *MOSymbol = nullptr;218    if (MO.isGlobal())219      MOSymbol = AP.getSymbol(MO.getGlobal());220    else if (MO.isCPI())221      MOSymbol = AP.GetCPISymbol(MO.getIndex());222    else if (MO.isJTI())223      MOSymbol = AP.GetJTISymbol(MO.getIndex());224    else225      llvm_unreachable("Unknown operand type!");226 227    StringRef SymbolName = MOSymbol->getName();228    std::string LitaName = ".CONST_" + SymbolName.str();229 230    MCSectionELF *Section = OutStreamer.getContext().getELFSection(231        ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);232 233    OutStreamer.switchSection(Section);234    Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName));235    if (Sym->isUndefined()) {236      OutStreamer.emitLabel(Sym);237      OutStreamer.emitSymbolAttribute(Sym, MCSA_Local);238      OutStreamer.emitValue(Imm.getExpr(), AlignSize);239      OutStreamer.emitCodeAlignment(Align(AlignSize), &STI);240    }241  }242  return Sym;243}244 245static MCInst ScaleVectorOffset(MCInst &Inst, unsigned OpNo,246                                unsigned VectorSize, MCContext &Ctx) {247  MCInst T;248  T.setOpcode(Inst.getOpcode());249  for (unsigned i = 0, n = Inst.getNumOperands(); i != n; ++i) {250    if (i != OpNo) {251      T.addOperand(Inst.getOperand(i));252      continue;253    }254    MCOperand &ImmOp = Inst.getOperand(i);255    const auto *HE = static_cast<const HexagonMCExpr*>(ImmOp.getExpr());256    int32_t V = cast<MCConstantExpr>(HE->getExpr())->getValue();257    auto *NewCE = MCConstantExpr::create(V / int32_t(VectorSize), Ctx);258    auto *NewHE = HexagonMCExpr::create(NewCE, Ctx);259    T.addOperand(MCOperand::createExpr(NewHE));260  }261  return T;262}263 264void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst,265                                                  const MachineInstr &MI) {266  MCInst &MappedInst = static_cast <MCInst &>(Inst);267  const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo();268  const MachineFunction &MF = *MI.getParent()->getParent();269  auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();270  unsigned VectorSize = HRI.getRegSizeInBits(Hexagon::HvxVRRegClass) / 8;271 272  switch (Inst.getOpcode()) {273  default:274    return;275 276  case Hexagon::A2_iconst: {277    Inst.setOpcode(Hexagon::A2_addi);278    MCOperand Reg = Inst.getOperand(0);279    MCOperand S16 = Inst.getOperand(1);280    HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr());281    HexagonMCInstrInfo::setS27_2_reloc(*S16.getExpr());282    Inst.clear();283    Inst.addOperand(Reg);284    Inst.addOperand(MCOperand::createReg(Hexagon::R0));285    Inst.addOperand(S16);286    break;287  }288 289  case Hexagon::A2_tfrf: {290    const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext);291    Inst.setOpcode(Hexagon::A2_paddif);292    Inst.addOperand(MCOperand::createExpr(Zero));293    break;294  }295 296  case Hexagon::A2_tfrt: {297    const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext);298    Inst.setOpcode(Hexagon::A2_paddit);299    Inst.addOperand(MCOperand::createExpr(Zero));300    break;301  }302 303  case Hexagon::A2_tfrfnew: {304    const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext);305    Inst.setOpcode(Hexagon::A2_paddifnew);306    Inst.addOperand(MCOperand::createExpr(Zero));307    break;308  }309 310  case Hexagon::A2_tfrtnew: {311    const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext);312    Inst.setOpcode(Hexagon::A2_padditnew);313    Inst.addOperand(MCOperand::createExpr(Zero));314    break;315  }316 317  case Hexagon::A2_zxtb: {318    const MCConstantExpr *C255 = MCConstantExpr::create(255, OutContext);319    Inst.setOpcode(Hexagon::A2_andir);320    Inst.addOperand(MCOperand::createExpr(C255));321    break;322  }323 324  // "$dst = CONST64(#$src1)",325  case Hexagon::CONST64:326    if (!OutStreamer->hasRawTextSupport()) {327      const MCOperand &Imm = MappedInst.getOperand(1);328      MCSectionSubPair Current = OutStreamer->getCurrentSection();329 330      MCSymbol *Sym =331          smallData(*this, MI, *OutStreamer, Imm, 8, getSubtargetInfo());332 333      OutStreamer->switchSection(Current.first, Current.second);334      MCInst TmpInst;335      MCOperand &Reg = MappedInst.getOperand(0);336      TmpInst.setOpcode(Hexagon::L2_loadrdgp);337      TmpInst.addOperand(Reg);338      TmpInst.addOperand(MCOperand::createExpr(339                         MCSymbolRefExpr::create(Sym, OutContext)));340      MappedInst = TmpInst;341 342    }343    break;344  case Hexagon::CONST32:345    if (!OutStreamer->hasRawTextSupport()) {346      MCOperand &Imm = MappedInst.getOperand(1);347      MCSectionSubPair Current = OutStreamer->getCurrentSection();348      MCSymbol *Sym =349          smallData(*this, MI, *OutStreamer, Imm, 4, getSubtargetInfo());350      OutStreamer->switchSection(Current.first, Current.second);351      MCInst TmpInst;352      MCOperand &Reg = MappedInst.getOperand(0);353      TmpInst.setOpcode(Hexagon::L2_loadrigp);354      TmpInst.addOperand(Reg);355      TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(356          MCSymbolRefExpr::create(Sym, OutContext), OutContext)));357      MappedInst = TmpInst;358    }359    break;360 361  // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use362  // C2_or during instruction selection itself but it results363  // into suboptimal code.364  case Hexagon::C2_pxfer_map: {365    MCOperand &Ps = Inst.getOperand(1);366    MappedInst.setOpcode(Hexagon::C2_or);367    MappedInst.addOperand(Ps);368    return;369  }370 371  // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo372  // The insn is mapped from the 4 operand to the 3 operand raw form taking373  // 3 register pairs.374  case Hexagon::M2_vrcmpys_acc_s1: {375    MCOperand &Rt = Inst.getOperand(3);376    assert(Rt.isReg() && "Expected register and none was found");377    unsigned Reg = RI->getEncodingValue(Rt.getReg());378    if (Reg & 1)379      MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);380    else381      MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);382    Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));383    return;384  }385  case Hexagon::M2_vrcmpys_s1: {386    MCOperand &Rt = Inst.getOperand(2);387    assert(Rt.isReg() && "Expected register and none was found");388    unsigned Reg = RI->getEncodingValue(Rt.getReg());389    if (Reg & 1)390      MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h);391    else392      MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l);393    Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));394    return;395  }396 397  case Hexagon::M2_vrcmpys_s1rp: {398    MCOperand &Rt = Inst.getOperand(2);399    assert(Rt.isReg() && "Expected register and none was found");400    unsigned Reg = RI->getEncodingValue(Rt.getReg());401    if (Reg & 1)402      MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);403    else404      MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);405    Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));406    return;407  }408 409  case Hexagon::A4_boundscheck: {410    MCOperand &Rs = Inst.getOperand(1);411    assert(Rs.isReg() && "Expected register and none was found");412    unsigned Reg = RI->getEncodingValue(Rs.getReg());413    if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2414      MappedInst.setOpcode(Hexagon::A4_boundscheck_hi);415    else         // raw:lo416      MappedInst.setOpcode(Hexagon::A4_boundscheck_lo);417    Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI));418    return;419  }420 421  case Hexagon::PS_call_nr:422    Inst.setOpcode(Hexagon::J2_call);423    break;424 425  case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {426    MCOperand &MO = MappedInst.getOperand(2);427    int64_t Imm;428    MCExpr const *Expr = MO.getExpr();429    bool Success = Expr->evaluateAsAbsolute(Imm);430    assert(Success && "Expected immediate and none was found");431    (void)Success;432    MCInst TmpInst;433    if (Imm == 0) {434      TmpInst.setOpcode(Hexagon::S2_vsathub);435      TmpInst.addOperand(MappedInst.getOperand(0));436      TmpInst.addOperand(MappedInst.getOperand(1));437      MappedInst = TmpInst;438      return;439    }440    TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat);441    TmpInst.addOperand(MappedInst.getOperand(0));442    TmpInst.addOperand(MappedInst.getOperand(1));443    const MCExpr *One = MCConstantExpr::create(1, OutContext);444    const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);445    TmpInst.addOperand(446        MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));447    MappedInst = TmpInst;448    return;449  }450 451  case Hexagon::S5_vasrhrnd_goodsyntax:452  case Hexagon::S2_asr_i_p_rnd_goodsyntax: {453    MCOperand &MO2 = MappedInst.getOperand(2);454    MCExpr const *Expr = MO2.getExpr();455    int64_t Imm;456    bool Success = Expr->evaluateAsAbsolute(Imm);457    assert(Success && "Expected immediate and none was found");458    (void)Success;459    MCInst TmpInst;460    if (Imm == 0) {461      TmpInst.setOpcode(Hexagon::A2_combinew);462      TmpInst.addOperand(MappedInst.getOperand(0));463      MCOperand &MO1 = MappedInst.getOperand(1);464      MCRegister High = RI->getSubReg(MO1.getReg(), Hexagon::isub_hi);465      MCRegister Low = RI->getSubReg(MO1.getReg(), Hexagon::isub_lo);466      // Add a new operand for the second register in the pair.467      TmpInst.addOperand(MCOperand::createReg(High));468      TmpInst.addOperand(MCOperand::createReg(Low));469      MappedInst = TmpInst;470      return;471    }472 473    if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax)474      TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd);475    else476      TmpInst.setOpcode(Hexagon::S5_vasrhrnd);477    TmpInst.addOperand(MappedInst.getOperand(0));478    TmpInst.addOperand(MappedInst.getOperand(1));479    const MCExpr *One = MCConstantExpr::create(1, OutContext);480    const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);481    TmpInst.addOperand(482        MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));483    MappedInst = TmpInst;484    return;485  }486 487  // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd488  case Hexagon::S2_asr_i_r_rnd_goodsyntax: {489    MCOperand &MO = Inst.getOperand(2);490    MCExpr const *Expr = MO.getExpr();491    int64_t Imm;492    bool Success = Expr->evaluateAsAbsolute(Imm);493    assert(Success && "Expected immediate and none was found");494    (void)Success;495    MCInst TmpInst;496    if (Imm == 0) {497      TmpInst.setOpcode(Hexagon::A2_tfr);498      TmpInst.addOperand(MappedInst.getOperand(0));499      TmpInst.addOperand(MappedInst.getOperand(1));500      MappedInst = TmpInst;501      return;502    }503    TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);504    TmpInst.addOperand(MappedInst.getOperand(0));505    TmpInst.addOperand(MappedInst.getOperand(1));506    const MCExpr *One = MCConstantExpr::create(1, OutContext);507    const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);508    TmpInst.addOperand(509        MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));510    MappedInst = TmpInst;511    return;512  }513 514  // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)"515  case Hexagon::A2_tfrpi: {516    MCInst TmpInst;517    MCOperand &Rdd = MappedInst.getOperand(0);518    MCOperand &MO = MappedInst.getOperand(1);519 520    TmpInst.setOpcode(Hexagon::A2_combineii);521    TmpInst.addOperand(Rdd);522    int64_t Imm;523    bool Success = MO.getExpr()->evaluateAsAbsolute(Imm);524    if (Success && Imm < 0) {525      const MCExpr *MOne = MCConstantExpr::create(-1, OutContext);526      const HexagonMCExpr *E = HexagonMCExpr::create(MOne, OutContext);527      TmpInst.addOperand(MCOperand::createExpr(E));528    } else {529      const MCExpr *Zero = MCConstantExpr::create(0, OutContext);530      const HexagonMCExpr *E = HexagonMCExpr::create(Zero, OutContext);531      TmpInst.addOperand(MCOperand::createExpr(E));532    }533    TmpInst.addOperand(MO);534    MappedInst = TmpInst;535    return;536  }537 538  // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"539  case Hexagon::A2_tfrp: {540    MCOperand &MO = MappedInst.getOperand(1);541    MCRegister High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi);542    MCRegister Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo);543    MO.setReg(High);544    // Add a new operand for the second register in the pair.545    MappedInst.addOperand(MCOperand::createReg(Low));546    MappedInst.setOpcode(Hexagon::A2_combinew);547    return;548  }549 550  case Hexagon::A2_tfrpt:551  case Hexagon::A2_tfrpf: {552    MCOperand &MO = MappedInst.getOperand(2);553    MCRegister High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi);554    MCRegister Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo);555    MO.setReg(High);556    // Add a new operand for the second register in the pair.557    MappedInst.addOperand(MCOperand::createReg(Low));558    MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)559                          ? Hexagon::C2_ccombinewt560                          : Hexagon::C2_ccombinewf);561    return;562  }563 564  case Hexagon::A2_tfrptnew:565  case Hexagon::A2_tfrpfnew: {566    MCOperand &MO = MappedInst.getOperand(2);567    MCRegister High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi);568    MCRegister Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo);569    MO.setReg(High);570    // Add a new operand for the second register in the pair.571    MappedInst.addOperand(MCOperand::createReg(Low));572    MappedInst.setOpcode(Inst.getOpcode() == Hexagon::A2_tfrptnew573                            ? Hexagon::C2_ccombinewnewt574                            : Hexagon::C2_ccombinewnewf);575    return;576  }577 578  case Hexagon::M2_mpysmi: {579    MCOperand &Imm = MappedInst.getOperand(2);580    MCExpr const *Expr = Imm.getExpr();581    int64_t Value;582    bool Success = Expr->evaluateAsAbsolute(Value);583    assert(Success);584    (void)Success;585    if (Value < 0 && Value > -256) {586      MappedInst.setOpcode(Hexagon::M2_mpysin);587      Imm.setExpr(HexagonMCExpr::create(588          MCUnaryExpr::createMinus(Expr, OutContext), OutContext));589    } else590      MappedInst.setOpcode(Hexagon::M2_mpysip);591    return;592  }593 594  case Hexagon::A2_addsp: {595    MCOperand &Rt = Inst.getOperand(1);596    assert(Rt.isReg() && "Expected register and none was found");597    unsigned Reg = RI->getEncodingValue(Rt.getReg());598    if (Reg & 1)599      MappedInst.setOpcode(Hexagon::A2_addsph);600    else601      MappedInst.setOpcode(Hexagon::A2_addspl);602    Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));603    return;604  }605 606  case Hexagon::V6_vd0: {607    MCInst TmpInst;608    assert(Inst.getOperand(0).isReg() &&609           "Expected register and none was found");610 611    TmpInst.setOpcode(Hexagon::V6_vxor);612    TmpInst.addOperand(Inst.getOperand(0));613    TmpInst.addOperand(Inst.getOperand(0));614    TmpInst.addOperand(Inst.getOperand(0));615    MappedInst = TmpInst;616    return;617  }618 619  case Hexagon::V6_vdd0: {620    MCInst TmpInst;621    assert (Inst.getOperand(0).isReg() &&622            "Expected register and none was found");623 624    TmpInst.setOpcode(Hexagon::V6_vsubw_dv);625    TmpInst.addOperand(Inst.getOperand(0));626    TmpInst.addOperand(Inst.getOperand(0));627    TmpInst.addOperand(Inst.getOperand(0));628    MappedInst = TmpInst;629    return;630  }631 632  case Hexagon::V6_vL32Ub_pi:633  case Hexagon::V6_vL32b_cur_pi:634  case Hexagon::V6_vL32b_nt_cur_pi:635  case Hexagon::V6_vL32b_pi:636  case Hexagon::V6_vL32b_nt_pi:637  case Hexagon::V6_vL32b_nt_tmp_pi:638  case Hexagon::V6_vL32b_tmp_pi:639    MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext);640    return;641 642  case Hexagon::V6_vL32Ub_ai:643  case Hexagon::V6_vL32b_ai:644  case Hexagon::V6_vL32b_cur_ai:645  case Hexagon::V6_vL32b_nt_ai:646  case Hexagon::V6_vL32b_nt_cur_ai:647  case Hexagon::V6_vL32b_nt_tmp_ai:648  case Hexagon::V6_vL32b_tmp_ai:649    MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext);650    return;651 652  case Hexagon::V6_vS32Ub_pi:653  case Hexagon::V6_vS32b_new_pi:654  case Hexagon::V6_vS32b_nt_new_pi:655  case Hexagon::V6_vS32b_nt_pi:656  case Hexagon::V6_vS32b_pi:657    MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext);658    return;659 660  case Hexagon::V6_vS32Ub_ai:661  case Hexagon::V6_vS32b_ai:662  case Hexagon::V6_vS32b_new_ai:663  case Hexagon::V6_vS32b_nt_ai:664  case Hexagon::V6_vS32b_nt_new_ai:665    MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext);666    return;667 668  case Hexagon::V6_vL32b_cur_npred_pi:669  case Hexagon::V6_vL32b_cur_pred_pi:670  case Hexagon::V6_vL32b_npred_pi:671  case Hexagon::V6_vL32b_nt_cur_npred_pi:672  case Hexagon::V6_vL32b_nt_cur_pred_pi:673  case Hexagon::V6_vL32b_nt_npred_pi:674  case Hexagon::V6_vL32b_nt_pred_pi:675  case Hexagon::V6_vL32b_nt_tmp_npred_pi:676  case Hexagon::V6_vL32b_nt_tmp_pred_pi:677  case Hexagon::V6_vL32b_pred_pi:678  case Hexagon::V6_vL32b_tmp_npred_pi:679  case Hexagon::V6_vL32b_tmp_pred_pi:680    MappedInst = ScaleVectorOffset(Inst, 4, VectorSize, OutContext);681    return;682 683  case Hexagon::V6_vL32b_cur_npred_ai:684  case Hexagon::V6_vL32b_cur_pred_ai:685  case Hexagon::V6_vL32b_npred_ai:686  case Hexagon::V6_vL32b_nt_cur_npred_ai:687  case Hexagon::V6_vL32b_nt_cur_pred_ai:688  case Hexagon::V6_vL32b_nt_npred_ai:689  case Hexagon::V6_vL32b_nt_pred_ai:690  case Hexagon::V6_vL32b_nt_tmp_npred_ai:691  case Hexagon::V6_vL32b_nt_tmp_pred_ai:692  case Hexagon::V6_vL32b_pred_ai:693  case Hexagon::V6_vL32b_tmp_npred_ai:694  case Hexagon::V6_vL32b_tmp_pred_ai:695    MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext);696    return;697 698  case Hexagon::V6_vS32Ub_npred_pi:699  case Hexagon::V6_vS32Ub_pred_pi:700  case Hexagon::V6_vS32b_new_npred_pi:701  case Hexagon::V6_vS32b_new_pred_pi:702  case Hexagon::V6_vS32b_npred_pi:703  case Hexagon::V6_vS32b_nqpred_pi:704  case Hexagon::V6_vS32b_nt_new_npred_pi:705  case Hexagon::V6_vS32b_nt_new_pred_pi:706  case Hexagon::V6_vS32b_nt_npred_pi:707  case Hexagon::V6_vS32b_nt_nqpred_pi:708  case Hexagon::V6_vS32b_nt_pred_pi:709  case Hexagon::V6_vS32b_nt_qpred_pi:710  case Hexagon::V6_vS32b_pred_pi:711  case Hexagon::V6_vS32b_qpred_pi:712    MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext);713    return;714 715  case Hexagon::V6_vS32Ub_npred_ai:716  case Hexagon::V6_vS32Ub_pred_ai:717  case Hexagon::V6_vS32b_new_npred_ai:718  case Hexagon::V6_vS32b_new_pred_ai:719  case Hexagon::V6_vS32b_npred_ai:720  case Hexagon::V6_vS32b_nqpred_ai:721  case Hexagon::V6_vS32b_nt_new_npred_ai:722  case Hexagon::V6_vS32b_nt_new_pred_ai:723  case Hexagon::V6_vS32b_nt_npred_ai:724  case Hexagon::V6_vS32b_nt_nqpred_ai:725  case Hexagon::V6_vS32b_nt_pred_ai:726  case Hexagon::V6_vS32b_nt_qpred_ai:727  case Hexagon::V6_vS32b_pred_ai:728  case Hexagon::V6_vS32b_qpred_ai:729    MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext);730    return;731 732  // V65+733  case Hexagon::V6_vS32b_srls_ai:734    MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext);735    return;736 737  case Hexagon::V6_vS32b_srls_pi:738    MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext);739    return;740  }741}742 743/// Print out a single Hexagon MI to the current output stream.744void HexagonAsmPrinter::emitInstruction(const MachineInstr *MI) {745  Hexagon_MC::verifyInstructionPredicates(MI->getOpcode(),746                                          getSubtargetInfo().getFeatureBits());747 748  MCInst MCB;749  MCB.setOpcode(Hexagon::BUNDLE);750  MCB.addOperand(MCOperand::createImm(0));751  const MCInstrInfo &MCII = *Subtarget->getInstrInfo();752 753  if (MI->isBundle()) {754    const MachineBasicBlock* MBB = MI->getParent();755    MachineBasicBlock::const_instr_iterator MII = MI->getIterator();756 757    for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII)758      if (!MII->isDebugInstr() && !MII->isImplicitDef())759        HexagonLowerToMC(MCII, &*MII, MCB, *this);760  } else {761    HexagonLowerToMC(MCII, MI, MCB, *this);762  }763 764  const MachineFunction &MF = *MI->getParent()->getParent();765  const auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();766  if (MI->isBundle() && HII.getBundleNoShuf(*MI))767    HexagonMCInstrInfo::setMemReorderDisabled(MCB);768 769  MCContext &Ctx = OutStreamer->getContext();770  bool Ok = HexagonMCInstrInfo::canonicalizePacket(MCII, *Subtarget, Ctx,771                                                   MCB, nullptr);772  assert(Ok); (void)Ok;773  if (HexagonMCInstrInfo::bundleSize(MCB) == 0)774    return;775  OutStreamer->emitInstruction(MCB, getSubtargetInfo());776}777 778void HexagonAsmPrinter::emitStartOfAsmFile(Module &M) {779  if (TM.getTargetTriple().isOSBinFormatELF())780    emitAttributes();781}782 783void HexagonAsmPrinter::emitEndOfAsmFile(Module &M) {784  HexagonTargetStreamer &HTS =785      static_cast<HexagonTargetStreamer &>(*OutStreamer->getTargetStreamer());786  if (TM.getTargetTriple().isOSBinFormatELF())787    HTS.finishAttributeSection();788}789 790void HexagonAsmPrinter::emitAttributes() {791  HexagonTargetStreamer &HTS =792      static_cast<HexagonTargetStreamer &>(*OutStreamer->getTargetStreamer());793  HTS.emitTargetAttributes(*TM.getMCSubtargetInfo());794}795 796void HexagonAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) {797  static const int8_t NoopsInSledCount = 4;798  // We want to emit the following pattern:799  //800  // .L_xray_sled_N:801  // <xray_sled_base>:802  // { 	jump .Ltmp0 }803  // {  nop804  //    nop805  //    nop806  //    nop }807  // .Ltmp0:808  //809  // We need the 4 nop words because at runtime, we'd be patching over the810  // full 5 words with the following pattern:811  //812  // <xray_sled_n>:813  // { 	immext(#...) // upper 26-bits of trampoline814  //    r6 = ##...   // lower  6-bits of trampoline815  //    immext(#...) // upper 26-bits of func id816  //    r7 = ##... }  // lower 6 bits of func id817  // { 	callr r6 }818  //819  //820  auto CurSled = OutContext.createTempSymbol("xray_sled_", true);821  OutStreamer->emitLabel(CurSled);822 823  MCInst *SledJump = new (OutContext) MCInst();824  SledJump->setOpcode(Hexagon::J2_jump);825  auto PostSled = OutContext.createTempSymbol();826  SledJump->addOperand(MCOperand::createExpr(HexagonMCExpr::create(827      MCSymbolRefExpr::create(PostSled, OutContext), OutContext)));828 829  // Emit "jump PostSled" instruction, which jumps over the nop series.830  MCInst SledJumpPacket;831  SledJumpPacket.setOpcode(Hexagon::BUNDLE);832  SledJumpPacket.addOperand(MCOperand::createImm(0));833  SledJumpPacket.addOperand(MCOperand::createInst(SledJump));834 835  EmitToStreamer(*OutStreamer, SledJumpPacket);836 837  // FIXME: this will emit individual packets, we should838  // special-case this and combine them into a single packet.839  emitNops(NoopsInSledCount);840 841  OutStreamer->emitLabel(PostSled);842  recordSled(CurSled, MI, Kind, 2);843}844 845void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) {846  EmitSled(MI, SledKind::FUNCTION_ENTER);847}848 849void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) {850  EmitSled(MI, SledKind::FUNCTION_EXIT);851}852 853void HexagonAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) {854  EmitSled(MI, SledKind::TAIL_CALL);855}856 857char HexagonAsmPrinter::ID = 0;858 859INITIALIZE_PASS(HexagonAsmPrinter, "hexagon-asm-printer",860                "Hexagon Assembly Printer", false, false)861 862extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void863LLVMInitializeHexagonAsmPrinter() {864  RegisterAsmPrinter<HexagonAsmPrinter> X(getTheHexagonTarget());865}866