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