1cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines//===- MipsAbiFlags.cpp ---------------------------------------------------===// 2cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// 3cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// The MCLinker Project 4cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// 5cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// This file is distributed under the University of Illinois Open Source 6cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// License. See LICENSE.TXT for details. 7cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// 8cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines//===----------------------------------------------------------------------===// 9cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "MipsAbiFlags.h" 10cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 11cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/Fragment/RegionFragment.h" 12cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/LDSection.h" 13cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/SectionData.h" 14cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/MC/Input.h" 15cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/Support/MsgHandling.h" 16cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 17cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <llvm/Support/Casting.h> 18cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <llvm/Support/MipsABIFlags.h> 19cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 20cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesnamespace mcld { 21cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 22cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// SHT_MIPS_ABIFLAGS has the same format for both 32/64-bit targets. 23cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// We do not support linking of big-endian code now so 32-bit LE 24cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// combination is Okay. 25cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinestypedef llvm::object::ELFType<llvm::support::little, false> ELF32LE; 26cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinestypedef llvm::object::Elf_Mips_ABIFlags<ELF32LE> ElfMipsAbiFlags; 27cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 28cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesuint64_t MipsAbiFlags::size() { 29cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return sizeof(ElfMipsAbiFlags); 30cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 31cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 32cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesuint64_t MipsAbiFlags::emit(const MipsAbiFlags& pInfo, MemoryRegion& pRegion) { 33cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines auto* buf = reinterpret_cast<ElfMipsAbiFlags*>(pRegion.begin()); 34cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->version = 0; 35cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->isa_level = pInfo.m_IsaLevel; 36cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->isa_rev = pInfo.m_IsaRev; 37cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->gpr_size = pInfo.m_GprSize; 38cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->cpr1_size = pInfo.m_Cpr1Size; 39cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->cpr2_size = pInfo.m_Cpr2Size; 40cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->fp_abi = pInfo.m_FpAbi; 41cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->isa_ext = pInfo.m_IsaExt; 42cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->ases = pInfo.m_Ases; 43cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->flags1 = pInfo.m_Flags1; 44cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines buf->flags2 = 0; 45cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return size(); 46cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 47cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 48cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesbool MipsAbiFlags::fillBySection(const Input& pInput, const LDSection& pSection, 49cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines MipsAbiFlags& mipsAbi) { 50cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines assert(pSection.type() == llvm::ELF::SHT_MIPS_ABIFLAGS && 51cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines "Unexpected section type"); 52cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 53cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (pSection.size() != size()) { 54cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines error(diag::error_Mips_abiflags_invalid_size) << pInput.name(); 55cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 56cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 57cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 58cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const SectionData* secData = pSection.getSectionData(); 59cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (secData->size() != 2 || !llvm::isa<RegionFragment>(secData->front())) { 60cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines error(diag::error_Mips_abiflags_invalid_size) << pInput.name(); 61cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 62cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 63cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 64cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const auto& frag = llvm::cast<RegionFragment>(secData->front()); 65cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines auto* data = 66cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines reinterpret_cast<const ElfMipsAbiFlags*>(frag.getRegion().data()); 67cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (data->version != 0) { 68cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines error(diag::error_Mips_abiflags_invalid_version) << int(data->version) 69cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines << pInput.name(); 70cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 71cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 72cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 73cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_IsaLevel = data->isa_level; 74cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_IsaRev = data->isa_rev; 75cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_GprSize = data->gpr_size; 76cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Cpr1Size = data->cpr1_size; 77cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Cpr2Size = data->cpr2_size; 78cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_FpAbi = data->fp_abi; 79cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_IsaExt = data->isa_ext; 80cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Ases = data->ases; 81cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Flags1 = data->flags1; 82cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 83cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 84cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 85cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic unsigned getIsaLevel(uint64_t flags) { 86cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines switch (flags & llvm::ELF::EF_MIPS_ARCH) { 87cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_1: 88cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 1; 89cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_2: 90cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 2; 91cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_3: 92cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 3; 93cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_4: 94cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 4; 95cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_5: 96cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 5; 97cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_32: 98cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_32R2: 99cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_32R6: 100cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 32; 101cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_64: 102cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_64R2: 103cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_64R6: 104cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 64; 105cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines default: 106cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines // We check ELF flags and show error in case 107cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines // of unknown value in other place. 108cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines llvm_unreachable("Unknown MIPS architecture flag"); 109cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 110cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 111cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 112cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic unsigned getIsaRev(uint64_t flags) { 113cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines switch (flags & llvm::ELF::EF_MIPS_ARCH) { 114cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_1: 115cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_2: 116cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_3: 117cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_4: 118cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_5: 119cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 0; 120cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_32: 121cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_64: 122cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 1; 123cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_32R2: 124cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_64R2: 125cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 2; 126cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_32R6: 127cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_ARCH_64R6: 128cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return 6; 129cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines default: 130cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines // We check ELF flags and show error in case 131cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines // of unknown value in other place. 132cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines llvm_unreachable("Unknown MIPS architecture flag"); 133cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 134cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 135cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 136cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic unsigned getIsaExt(uint64_t flags) { 137cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines switch (flags & llvm::ELF::EF_MIPS_MACH) { 138cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case 0: 139cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return llvm::Mips::AFL_EXT_NONE; 140cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_3900: return llvm::Mips::AFL_EXT_3900; 141cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_4010: return llvm::Mips::AFL_EXT_4010; 142cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_4100: return llvm::Mips::AFL_EXT_4010; 143cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_4111: return llvm::Mips::AFL_EXT_4111; 144cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_4120: return llvm::Mips::AFL_EXT_4120; 145cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_4650: return llvm::Mips::AFL_EXT_4650; 146cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_5400: return llvm::Mips::AFL_EXT_5400; 147cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_5500: return llvm::Mips::AFL_EXT_5500; 148cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_5900: return llvm::Mips::AFL_EXT_5900; 149cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_SB1: return llvm::Mips::AFL_EXT_SB1; 150cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_LS2E: return llvm::Mips::AFL_EXT_LOONGSON_2E; 151cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_LS2F: return llvm::Mips::AFL_EXT_LOONGSON_2F; 152cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_LS3A: return llvm::Mips::AFL_EXT_LOONGSON_3A; 153cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_OCTEON3: return llvm::Mips::AFL_EXT_OCTEON3; 154cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_OCTEON2: return llvm::Mips::AFL_EXT_OCTEON2; 155cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_OCTEON: return llvm::Mips::AFL_EXT_OCTEON; 156cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::ELF::EF_MIPS_MACH_XLR: return llvm::Mips::AFL_EXT_XLR; 157cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines default: 158cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines // We check ELF flags and show error in case 159cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines // of unknown value in other place. 160cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines llvm_unreachable("Unknown MIPS extension flag"); 161cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 162cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 163cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 164cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic bool is32BitElfFlags(uint64_t flags) { 165cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (flags & llvm::ELF::EF_MIPS_32BITMODE) 166cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 167cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 168cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines uint64_t arch = flags & llvm::ELF::EF_MIPS_ARCH; 169cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (arch == llvm::ELF::EF_MIPS_ARCH_1 || 170cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines arch == llvm::ELF::EF_MIPS_ARCH_2 || 171cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines arch == llvm::ELF::EF_MIPS_ARCH_32 || 172cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines arch == llvm::ELF::EF_MIPS_ARCH_32R2 || 173cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines arch == llvm::ELF::EF_MIPS_ARCH_32R6) 174cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 175cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 176cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines uint64_t abi = flags & llvm::ELF::EF_MIPS_ABI; 177cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (abi == llvm::ELF::EF_MIPS_ABI_O32 || abi == llvm::ELF::EF_MIPS_ABI_EABI32) 178cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 179cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 180cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 181cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 182cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 183cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesbool MipsAbiFlags::fillByElfFlags(const Input& pInput, uint64_t elfFlags, 184cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines MipsAbiFlags& mipsAbi) { 185cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_IsaLevel = getIsaLevel(elfFlags); 186cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_IsaRev = getIsaRev(elfFlags); 187cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_IsaExt = getIsaExt(elfFlags); 188cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 189cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_GprSize = is32BitElfFlags(elfFlags) ? 190cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines llvm::Mips::AFL_REG_32 : llvm::Mips::AFL_REG_64; 191cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 192cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Cpr1Size = llvm::Mips::AFL_REG_NONE; 193cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Cpr2Size = llvm::Mips::AFL_REG_NONE; 194cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_FpAbi = llvm::Mips::Val_GNU_MIPS_ABI_FP_ANY; 195cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 196cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Ases = 0; 197cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (elfFlags & llvm::ELF::EF_MIPS_MICROMIPS) 198cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Ases |= llvm::Mips::AFL_ASE_MICROMIPS; 199cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (elfFlags & llvm::ELF::EF_MIPS_ARCH_ASE_M16) 200cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Ases |= llvm::Mips::AFL_ASE_MIPS16; 201cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (elfFlags & llvm::ELF::EF_MIPS_ARCH_ASE_MDMX) 202cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Ases |= llvm::Mips::AFL_ASE_MDMX; 203cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 204cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines mipsAbi.m_Flags1 = 0; 205cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 206cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 207cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 208cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesbool MipsAbiFlags::isCompatible(const Input& pInput, const MipsAbiFlags& elf, 209cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const MipsAbiFlags& abi) { 210cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines unsigned isaRev = abi.m_IsaRev; 211cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (isaRev == 3 || isaRev == 5) 212cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines isaRev = 2; 213cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (abi.m_IsaLevel != elf.m_IsaLevel || isaRev != elf.m_IsaRev) { 214cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines warning(diag::warn_Mips_isa_incompatible) << pInput.name(); 215cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 216cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 217cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (abi.m_IsaExt != elf.m_IsaExt) { 218cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines warning(diag::warn_Mips_isa_ext_incompatible) << pInput.name(); 219cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 220cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 221cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if ((abi.m_Ases & elf.m_Ases) != elf.m_Ases) { 222cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines warning(diag::warn_Mips_ases_incompatible) << pInput.name(); 223cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 224cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 225cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 226cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 227cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 228cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic bool isFpGreater(uint64_t fpA, uint64_t fpB) { 229cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (fpB == llvm::Mips::Val_GNU_MIPS_ABI_FP_ANY) 230cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 231cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (fpB == llvm::Mips::Val_GNU_MIPS_ABI_FP_64A && 232cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines fpA == llvm::Mips::Val_GNU_MIPS_ABI_FP_64) 233cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 234cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (fpB != llvm::Mips::Val_GNU_MIPS_ABI_FP_XX) 235cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 236cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return fpA == llvm::Mips::Val_GNU_MIPS_ABI_FP_DOUBLE || 237cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines fpA == llvm::Mips::Val_GNU_MIPS_ABI_FP_64 || 238cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines fpA == llvm::Mips::Val_GNU_MIPS_ABI_FP_64A; 239cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 240cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 241cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic llvm::StringRef getFpAbiName(uint64_t abi) { 242cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines switch (abi) { 243cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::Mips::Val_GNU_MIPS_ABI_FP_ANY: 244cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "<any>"; 245cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::Mips::Val_GNU_MIPS_ABI_FP_DOUBLE: 246cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "-mdouble-float"; 247cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::Mips::Val_GNU_MIPS_ABI_FP_SINGLE: 248cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "-msingle-float"; 249cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::Mips::Val_GNU_MIPS_ABI_FP_SOFT: 250cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "-msoft-float"; 251cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::Mips::Val_GNU_MIPS_ABI_FP_OLD_64: 252cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "-mips32r2 -mfp64 (old)"; 253cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::Mips::Val_GNU_MIPS_ABI_FP_XX: 254cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "-mfpxx"; 255cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::Mips::Val_GNU_MIPS_ABI_FP_64: 256cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "-mgp32 -mfp64"; 257cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines case llvm::Mips::Val_GNU_MIPS_ABI_FP_64A: 258cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "-mgp32 -mfp64 -mno-odd-spreg"; 259cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines default: 260cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return "<unknown>"; 261cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 262cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 263cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 264cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesbool MipsAbiFlags::merge(const Input& pInput, MipsAbiFlags& oldFlags, 265cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const MipsAbiFlags& newFlags) { 266cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (oldFlags.m_IsaLevel == 0) { 267cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags = newFlags; 268cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 269cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 270cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 271cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (newFlags.m_IsaLevel > oldFlags.m_IsaLevel) 272cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags.m_IsaLevel = newFlags.m_IsaLevel; 273cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 274cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags.m_IsaRev = std::max(oldFlags.m_IsaRev, newFlags.m_IsaRev); 275cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags.m_GprSize = std::max(oldFlags.m_GprSize, newFlags.m_GprSize); 276cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags.m_Cpr1Size = std::max(oldFlags.m_Cpr1Size, newFlags.m_Cpr1Size); 277cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags.m_Cpr2Size = std::max(oldFlags.m_Cpr2Size, newFlags.m_Cpr2Size); 278cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags.m_Ases |= newFlags.m_Ases; 279cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags.m_Flags1 |= newFlags.m_Flags1; 280cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 281cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (oldFlags.m_FpAbi == newFlags.m_FpAbi) 282cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 283cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 284cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (isFpGreater(newFlags.m_FpAbi, oldFlags.m_FpAbi)) { 285cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines oldFlags.m_FpAbi = newFlags.m_FpAbi; 286cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 287cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 288cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 289cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (isFpGreater(oldFlags.m_FpAbi, newFlags.m_FpAbi)) 290cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 291cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 292cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines llvm::StringRef oldAbiName = getFpAbiName(oldFlags.m_FpAbi); 293cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines llvm::StringRef newAbiName = getFpAbiName(newFlags.m_FpAbi); 294cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines warning(diag::warn_Mips_fp_abi_incompatible) << oldAbiName << newAbiName 295cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines << pInput.name(); 296cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 297cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 298cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} // namespace mcld 299