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