15ffd83dbSDimitry Andric //===-- VEAsmBackend.cpp - VE Assembler Backend ---------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "MCTargetDesc/VEFixupKinds.h" 105ffd83dbSDimitry Andric #include "MCTargetDesc/VEMCTargetDesc.h" 115ffd83dbSDimitry Andric #include "llvm/MC/MCAsmBackend.h" 125ffd83dbSDimitry Andric #include "llvm/MC/MCELFObjectWriter.h" 135ffd83dbSDimitry Andric #include "llvm/MC/MCExpr.h" 145ffd83dbSDimitry Andric #include "llvm/MC/MCFixupKindInfo.h" 155ffd83dbSDimitry Andric #include "llvm/MC/MCObjectWriter.h" 165ffd83dbSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 175ffd83dbSDimitry Andric #include "llvm/MC/MCValue.h" 18349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 195ffd83dbSDimitry Andric #include "llvm/Support/EndianStream.h" 205ffd83dbSDimitry Andric 215ffd83dbSDimitry Andric using namespace llvm; 225ffd83dbSDimitry Andric 235ffd83dbSDimitry Andric static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) { 245ffd83dbSDimitry Andric switch (Kind) { 255ffd83dbSDimitry Andric default: 265ffd83dbSDimitry Andric llvm_unreachable("Unknown fixup kind!"); 275ffd83dbSDimitry Andric case FK_Data_1: 285ffd83dbSDimitry Andric case FK_Data_2: 295ffd83dbSDimitry Andric case FK_Data_4: 305ffd83dbSDimitry Andric case FK_Data_8: 315ffd83dbSDimitry Andric case FK_PCRel_1: 325ffd83dbSDimitry Andric case FK_PCRel_2: 335ffd83dbSDimitry Andric case FK_PCRel_4: 345ffd83dbSDimitry Andric case FK_PCRel_8: 355ffd83dbSDimitry Andric return Value; 365ffd83dbSDimitry Andric case VE::fixup_ve_hi32: 375ffd83dbSDimitry Andric case VE::fixup_ve_pc_hi32: 385ffd83dbSDimitry Andric case VE::fixup_ve_got_hi32: 395ffd83dbSDimitry Andric case VE::fixup_ve_gotoff_hi32: 405ffd83dbSDimitry Andric case VE::fixup_ve_plt_hi32: 415ffd83dbSDimitry Andric case VE::fixup_ve_tls_gd_hi32: 425ffd83dbSDimitry Andric case VE::fixup_ve_tpoff_hi32: 435ffd83dbSDimitry Andric return (Value >> 32) & 0xffffffff; 445ffd83dbSDimitry Andric case VE::fixup_ve_reflong: 450eae32dcSDimitry Andric case VE::fixup_ve_srel32: 465ffd83dbSDimitry Andric case VE::fixup_ve_lo32: 475ffd83dbSDimitry Andric case VE::fixup_ve_pc_lo32: 485ffd83dbSDimitry Andric case VE::fixup_ve_got_lo32: 495ffd83dbSDimitry Andric case VE::fixup_ve_gotoff_lo32: 505ffd83dbSDimitry Andric case VE::fixup_ve_plt_lo32: 515ffd83dbSDimitry Andric case VE::fixup_ve_tls_gd_lo32: 525ffd83dbSDimitry Andric case VE::fixup_ve_tpoff_lo32: 535ffd83dbSDimitry Andric return Value & 0xffffffff; 545ffd83dbSDimitry Andric } 555ffd83dbSDimitry Andric } 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric /// getFixupKindNumBytes - The number of bytes the fixup may change. 585ffd83dbSDimitry Andric static unsigned getFixupKindNumBytes(unsigned Kind) { 595ffd83dbSDimitry Andric switch (Kind) { 605ffd83dbSDimitry Andric default: 615ffd83dbSDimitry Andric llvm_unreachable("Unknown fixup kind!"); 625ffd83dbSDimitry Andric case FK_Data_1: 635ffd83dbSDimitry Andric case FK_PCRel_1: 645ffd83dbSDimitry Andric return 1; 655ffd83dbSDimitry Andric case FK_Data_2: 665ffd83dbSDimitry Andric case FK_PCRel_2: 675ffd83dbSDimitry Andric return 2; 685ffd83dbSDimitry Andric return 4; 695ffd83dbSDimitry Andric case FK_Data_4: 705ffd83dbSDimitry Andric case FK_PCRel_4: 715ffd83dbSDimitry Andric case VE::fixup_ve_reflong: 720eae32dcSDimitry Andric case VE::fixup_ve_srel32: 735ffd83dbSDimitry Andric case VE::fixup_ve_hi32: 745ffd83dbSDimitry Andric case VE::fixup_ve_lo32: 755ffd83dbSDimitry Andric case VE::fixup_ve_pc_hi32: 765ffd83dbSDimitry Andric case VE::fixup_ve_pc_lo32: 775ffd83dbSDimitry Andric case VE::fixup_ve_got_hi32: 785ffd83dbSDimitry Andric case VE::fixup_ve_got_lo32: 795ffd83dbSDimitry Andric case VE::fixup_ve_gotoff_hi32: 805ffd83dbSDimitry Andric case VE::fixup_ve_gotoff_lo32: 815ffd83dbSDimitry Andric case VE::fixup_ve_plt_hi32: 825ffd83dbSDimitry Andric case VE::fixup_ve_plt_lo32: 835ffd83dbSDimitry Andric case VE::fixup_ve_tls_gd_hi32: 845ffd83dbSDimitry Andric case VE::fixup_ve_tls_gd_lo32: 855ffd83dbSDimitry Andric case VE::fixup_ve_tpoff_hi32: 865ffd83dbSDimitry Andric case VE::fixup_ve_tpoff_lo32: 875ffd83dbSDimitry Andric return 4; 885ffd83dbSDimitry Andric case FK_Data_8: 895ffd83dbSDimitry Andric case FK_PCRel_8: 905ffd83dbSDimitry Andric return 8; 915ffd83dbSDimitry Andric } 925ffd83dbSDimitry Andric } 935ffd83dbSDimitry Andric 945ffd83dbSDimitry Andric namespace { 955ffd83dbSDimitry Andric class VEAsmBackend : public MCAsmBackend { 965ffd83dbSDimitry Andric protected: 975ffd83dbSDimitry Andric const Target &TheTarget; 985ffd83dbSDimitry Andric 995ffd83dbSDimitry Andric public: 100*5f757f3fSDimitry Andric VEAsmBackend(const Target &T) 101*5f757f3fSDimitry Andric : MCAsmBackend(llvm::endianness::little), TheTarget(T) {} 1025ffd83dbSDimitry Andric 1035ffd83dbSDimitry Andric unsigned getNumFixupKinds() const override { return VE::NumTargetFixupKinds; } 1045ffd83dbSDimitry Andric 1055ffd83dbSDimitry Andric const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { 1065ffd83dbSDimitry Andric const static MCFixupKindInfo Infos[VE::NumTargetFixupKinds] = { 1075ffd83dbSDimitry Andric // name, offset, bits, flags 1085ffd83dbSDimitry Andric {"fixup_ve_reflong", 0, 32, 0}, 1090eae32dcSDimitry Andric {"fixup_ve_srel32", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, 1105ffd83dbSDimitry Andric {"fixup_ve_hi32", 0, 32, 0}, 1115ffd83dbSDimitry Andric {"fixup_ve_lo32", 0, 32, 0}, 1125ffd83dbSDimitry Andric {"fixup_ve_pc_hi32", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, 1135ffd83dbSDimitry Andric {"fixup_ve_pc_lo32", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, 1145ffd83dbSDimitry Andric {"fixup_ve_got_hi32", 0, 32, 0}, 1155ffd83dbSDimitry Andric {"fixup_ve_got_lo32", 0, 32, 0}, 1165ffd83dbSDimitry Andric {"fixup_ve_gotoff_hi32", 0, 32, 0}, 1175ffd83dbSDimitry Andric {"fixup_ve_gotoff_lo32", 0, 32, 0}, 1185ffd83dbSDimitry Andric {"fixup_ve_plt_hi32", 0, 32, 0}, 1195ffd83dbSDimitry Andric {"fixup_ve_plt_lo32", 0, 32, 0}, 1205ffd83dbSDimitry Andric {"fixup_ve_tls_gd_hi32", 0, 32, 0}, 1215ffd83dbSDimitry Andric {"fixup_ve_tls_gd_lo32", 0, 32, 0}, 1225ffd83dbSDimitry Andric {"fixup_ve_tpoff_hi32", 0, 32, 0}, 1235ffd83dbSDimitry Andric {"fixup_ve_tpoff_lo32", 0, 32, 0}, 1245ffd83dbSDimitry Andric }; 1255ffd83dbSDimitry Andric 1265ffd83dbSDimitry Andric if (Kind < FirstTargetFixupKind) 1275ffd83dbSDimitry Andric return MCAsmBackend::getFixupKindInfo(Kind); 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 1305ffd83dbSDimitry Andric "Invalid kind!"); 1315ffd83dbSDimitry Andric return Infos[Kind - FirstTargetFixupKind]; 1325ffd83dbSDimitry Andric } 1335ffd83dbSDimitry Andric 1345ffd83dbSDimitry Andric bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, 135*5f757f3fSDimitry Andric const MCValue &Target, 136*5f757f3fSDimitry Andric const MCSubtargetInfo *STI) override { 1375ffd83dbSDimitry Andric switch ((VE::Fixups)Fixup.getKind()) { 1385ffd83dbSDimitry Andric default: 1395ffd83dbSDimitry Andric return false; 1405ffd83dbSDimitry Andric case VE::fixup_ve_tls_gd_hi32: 1415ffd83dbSDimitry Andric case VE::fixup_ve_tls_gd_lo32: 1425ffd83dbSDimitry Andric case VE::fixup_ve_tpoff_hi32: 1435ffd83dbSDimitry Andric case VE::fixup_ve_tpoff_lo32: 1445ffd83dbSDimitry Andric return true; 1455ffd83dbSDimitry Andric } 1465ffd83dbSDimitry Andric } 1475ffd83dbSDimitry Andric 1485ffd83dbSDimitry Andric bool mayNeedRelaxation(const MCInst &Inst, 1495ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const override { 1505ffd83dbSDimitry Andric // Not implemented yet. For example, if we have a branch with 1515ffd83dbSDimitry Andric // lager than SIMM32 immediate value, we want to relaxation such 1525ffd83dbSDimitry Andric // branch instructions. 1535ffd83dbSDimitry Andric return false; 1545ffd83dbSDimitry Andric } 1555ffd83dbSDimitry Andric 1565ffd83dbSDimitry Andric void relaxInstruction(MCInst &Inst, 1575ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const override { 1585ffd83dbSDimitry Andric // Aurora VE doesn't support relaxInstruction yet. 1595ffd83dbSDimitry Andric llvm_unreachable("relaxInstruction() should not be called"); 1605ffd83dbSDimitry Andric } 1615ffd83dbSDimitry Andric 162349cc55cSDimitry Andric bool writeNopData(raw_ostream &OS, uint64_t Count, 163349cc55cSDimitry Andric const MCSubtargetInfo *STI) const override { 1645ffd83dbSDimitry Andric if ((Count % 8) != 0) 1655ffd83dbSDimitry Andric return false; 1665ffd83dbSDimitry Andric 1675ffd83dbSDimitry Andric for (uint64_t i = 0; i < Count; i += 8) 1685ffd83dbSDimitry Andric support::endian::write<uint64_t>(OS, 0x7900000000000000ULL, 169*5f757f3fSDimitry Andric llvm::endianness::little); 1705ffd83dbSDimitry Andric 1715ffd83dbSDimitry Andric return true; 1725ffd83dbSDimitry Andric } 1735ffd83dbSDimitry Andric }; 1745ffd83dbSDimitry Andric 1755ffd83dbSDimitry Andric class ELFVEAsmBackend : public VEAsmBackend { 1765ffd83dbSDimitry Andric Triple::OSType OSType; 1775ffd83dbSDimitry Andric 1785ffd83dbSDimitry Andric public: 1795ffd83dbSDimitry Andric ELFVEAsmBackend(const Target &T, Triple::OSType OSType) 1805ffd83dbSDimitry Andric : VEAsmBackend(T), OSType(OSType) {} 1815ffd83dbSDimitry Andric 1825ffd83dbSDimitry Andric void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 1835ffd83dbSDimitry Andric const MCValue &Target, MutableArrayRef<char> Data, 1845ffd83dbSDimitry Andric uint64_t Value, bool IsResolved, 1855ffd83dbSDimitry Andric const MCSubtargetInfo *STI) const override { 1865ffd83dbSDimitry Andric Value = adjustFixupValue(Fixup.getKind(), Value); 1875ffd83dbSDimitry Andric if (!Value) 1885ffd83dbSDimitry Andric return; // Doesn't change encoding. 1895ffd83dbSDimitry Andric 1905ffd83dbSDimitry Andric MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); 1915ffd83dbSDimitry Andric 1925ffd83dbSDimitry Andric // Shift the value into position. 1935ffd83dbSDimitry Andric Value <<= Info.TargetOffset; 1945ffd83dbSDimitry Andric 1955ffd83dbSDimitry Andric unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); 1965ffd83dbSDimitry Andric unsigned Offset = Fixup.getOffset(); 1975ffd83dbSDimitry Andric assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); 1985ffd83dbSDimitry Andric // For each byte of the fragment that the fixup touches, mask in the bits 1995ffd83dbSDimitry Andric // from the fixup value. The Value has been "split up" into the 2005ffd83dbSDimitry Andric // appropriate bitfields above. 2015ffd83dbSDimitry Andric for (unsigned i = 0; i != NumBytes; ++i) { 202*5f757f3fSDimitry Andric unsigned Idx = 203*5f757f3fSDimitry Andric Endian == llvm::endianness::little ? i : (NumBytes - 1) - i; 2045ffd83dbSDimitry Andric Data[Offset + Idx] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff); 2055ffd83dbSDimitry Andric } 2065ffd83dbSDimitry Andric } 2075ffd83dbSDimitry Andric 2085ffd83dbSDimitry Andric std::unique_ptr<MCObjectTargetWriter> 2095ffd83dbSDimitry Andric createObjectTargetWriter() const override { 2105ffd83dbSDimitry Andric uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); 2115ffd83dbSDimitry Andric return createVEELFObjectWriter(OSABI); 2125ffd83dbSDimitry Andric } 2135ffd83dbSDimitry Andric }; 2145ffd83dbSDimitry Andric } // end anonymous namespace 2155ffd83dbSDimitry Andric 2165ffd83dbSDimitry Andric MCAsmBackend *llvm::createVEAsmBackend(const Target &T, 2175ffd83dbSDimitry Andric const MCSubtargetInfo &STI, 2185ffd83dbSDimitry Andric const MCRegisterInfo &MRI, 2195ffd83dbSDimitry Andric const MCTargetOptions &Options) { 2205ffd83dbSDimitry Andric return new ELFVEAsmBackend(T, STI.getTargetTriple().getOS()); 2215ffd83dbSDimitry Andric } 222