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