aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorPeter Bergner <bergner@vnet.ibm.com>2015-11-11 19:52:52 -0600
committerPeter Bergner <bergner@vnet.ibm.com>2015-11-11 19:52:52 -0600
commita680de9a980e9d268846e8605af14ba1e7f3a39b (patch)
treee341fa2892cd8bac6b4cebf16b3082070e81144c /gold
parent3604307d2f39ddd0b7f640148338b7ecc0ea4b45 (diff)
downloadfsf-binutils-gdb-a680de9a980e9d268846e8605af14ba1e7f3a39b.zip
fsf-binutils-gdb-a680de9a980e9d268846e8605af14ba1e7f3a39b.tar.gz
fsf-binutils-gdb-a680de9a980e9d268846e8605af14ba1e7f3a39b.tar.bz2
Add assembler, disassembler and linker support for power9.
include/opcode/ * ppc.h (PPC_OPCODE_POWER9): New define. (PPC_OPCODE_VSX3): Likewise. opcodes/ * ppc-dis.c (ppc_opts): Add "power9" and "pwr9" entries. Add PPC_OPCODE_VSX3 to the vsx entry. (powerpc_init_dialect): Set default dialect to power9. * ppc-opc.c (insert_dcmxs, extract_dcmxs, insert_dxd, extract_dxd, insert_dxdn, extract_dxdn, insert_l0, extract_l0, insert_l1, extract_l1 insert_xtq6, extract_xtq6): New static functions. (insert_esync): Test for illegal L operand value. (DCMX, DCMXS, DXD, NDXD, L0, L1, RC, FC, UIM6, X_R, RIC, PRS, XSQ6, XTQ6, LRAND, IMM8, DQX, DQX_MASK, DX, DX_MASK, VXVAPS_MASK, VXVA,XVA, XX2VA, XVARC, XBF_MASK, XX2UIM4_MASK, XX2BFD_MASK, XX2DCMXS_MASK, XVA_MASK, XRLA_MASK, XBFRARB_MASK, XLRAND_MASK, POWER9, PPCVEC3, PPCVSX3): New defines. (powerpc_opcodes) <ps_cmpu0, ps_cmpo0, ps_cmpu1, ps_cmpo1, fcmpu, fcmpo, ftdiv, ftsqrt>: Use XBF_MASK. <mcrxr>: Use XBFRARB_MASK. <addpcis, bcdcfn., bcdcfsq., bcdcfz., bcdcpsgn., bcdctn., bcdctsq., bcdctz., bcds., bcdsetsgn., bcdsr., bcdtrunc., bcdus., bcdutrunc., cmpeqb, cmprb, cnttzd, cnttzd., cnttzw, cnttzw., copy, copy_first, cp_abort, darn, dtstsfi, dtstsfiq, extswsli, extswsli., ldat, ldmx, lwat, lxsd, lxsibzx, lxsihzx, lxssp, lxv, lxvb16x, lxvh8x, lxvl, lxvll, lxvwsx, lxvx, maddhd, maddhdu, maddld, mcrxrx, mfvsrld, modsd, modsw, modud, moduw, msgsync, mtvsrdd, mtvsrws, paste, paste., paste_last, rmieg, setb, slbieg, slbsync, stdat, stop, stwat, stxsd, stxsibx, stxsihx, stxssp, stxv, stxvb16x, stxvh8x, stxvl, stxvll, stxvx, subpcis, urfid, vbpermd, vclzlsbb, vcmpneb, vcmpneb., vcmpneh, vcmpneh., vcmpnew, vcmpnew., vcmpnezb, vcmpnezb., vcmpnezh, vcmpnezh., vcmpnezw, vcmpnezw., vctzb, vctzd, vctzh, vctzlsbb, vctzw, vextractd, vextractub, vextractuh, vextractuw, vextsb2d, vextsb2w, vextsh2d, vextsh2w, vextsw2d, vextublx, vextubrx, vextuhlx, vextuhrx, vextuwlx, vextuwrx, vinsertb, vinsertd, vinserth, vinsertw, vmul10cuq, vmul10ecuq, vmul10euq, vmul10uq, vnegd, vnegw, vpermr, vprtybd, vprtybq, vprtybw, vrldmi, vrldnm, vrlwmi, vrlwnm, vslv, vsrv, wait, xsabsqp, xsaddqp, xsaddqpo, xscmpeqdp, xscmpexpdp, xscmpexpqp, xscmpgedp, xscmpgtdp, xscmpnedp, xscmpoqp, xscmpuqp, xscpsgnqp, xscvdphp, xscvdpqp, xscvhpdp, xscvqpdp, xscvqpdpo, xscvqpsdz, xscvqpswz, xscvqpudz, xscvqpuwz, xscvsdqp, xscvudqp, xsdivqp, xsdivqpo, xsiexpdp, xsiexpqp, xsmaddqp, xsmaddqpo, xsmaxcdp, xsmaxjdp, xsmincdp, xsminjdp, xsmsubqp, xsmsubqpo, xsmulqp, xsmulqpo, xsnabsqp, xsnegqp, xsnmaddqp, xsnmaddqpo, xsnmsubqp, xsnmsubqpo, xsrqpi, xsrqpix, xsrqpxp, xssqrtqp, xssqrtqpo, xssubqp, xssubqpo, xststdcdp, xststdcqp, xststdcsp, xsxexpdp, xsxexpqp, xsxsigdp, xsxsigqp, xvcmpnedp, xvcmpnedp., xvcmpnesp, xvcmpnesp., xvcvhpsp, xvcvsphp, xviexpdp, xviexpsp, xvtstdcdp, xvtstdcsp, xvxexpdp, xvxexpsp, xvxsigdp, xvxsigsp, xxbrd, xxbrh, xxbrq, xxbrw, xxextractuw, xxinsertw, xxperm, xxpermr, xxspltib>: New instructions. <doze, nap, sleep, rvwinkle, waitasec, lxvx, stxvx>: Disable on POWER9. <tlbiel, tlbie, sync, slbmfev, slbmfee>: Add additional operands. include/elf/ * ppc.h (R_PPC_REL16DX_HA): New reloction. * ppc64.h (R_PPC64_REL16DX_HA): Likewise. bfd/ * elf32-ppc.c (ppc_elf_howto_raw): Add R_PPC_REL16DX_HA. (ppc_elf_reloc_type_lookup): Handle R_PPC_REL16DX_HA. (ppc_elf_addr16_ha_reloc): Likewise. (ppc_elf_check_relocs): Likewise. (ppc_elf_relocate_section): Likewise. (is_insn_dq_form): Handle lxv and stxv instructions. * elf64-ppc.c (ppc64_elf_howto_raw): Add R_PPC64_REL16DX_HA. (ppc64_elf_reloc_type_lookup): Handle R_PPC64_REL16DX_HA. (ppc64_elf_ha_reloc): Likewise. (ppc64_elf_check_relocs): Likewise. (ppc64_elf_relocate_section): Likewise. * bfd-in2.h: Regenerate. * libbfd.h: Likewise. * reloc.c (BFD_RELOC_PPC_REL16DX_HA): New. elfcpp/ * powerpc.h (R_POWERPC_REL16DX_HA): Define. gas/ * doc/as.texinfo (Target PowerPC): Document -mpower9 and -mpwr9. * doc/c-ppc.texi (PowerPC-Opts): Likewise. * config/tc-ppc.c (md_show_usage): Likewise. (md_assemble): Handle BFD_RELOC_PPC_REL16DX_HA. (md_apply_fix): Likewise. (ppc_handle_align): Handle power9's group ending nop. gas/testsuite/ * gas/ppc/altivec3.s: New test. * gas/ppc/altivec3.d: Likewise. * gas/ppc/vsx3.s: Likewise. * gas/ppc/vsx3.d: Likewise. * gas/ppc/power9.s: Likewise. * gas/ppc/power9.d: Likewise. * gas/ppc/ppc.exp: Run them. * gas/ppc/power8.s <lxvx, lxvd2x, stxvx, stxvd2x>: Add new tests. * gas/ppc/power8.d: Likewise. * gas/ppc/vsx.s: <lxvx, stxvx>: Rename invalid mnemonics ... <lxvd2x, stxvd2x>: ...to this. * gas/ppc/vsx.d: Likewise. gold/ * gold/powerpc.cc (Powerpc_relocate_functions::addr16_dq): New function. (Powerpc_relocate_functions::addr16dx_ha): Likewise. (Target_powerpc::Scan::local): Handle R_POWERPC_REL16DX_HA. (Target_powerpc::Scan::global): Likewise. (Target_powerpc::Relocate::relocate): Likewise. ld/testsuite/ * ld-powerpc/addpcis.d: New test. * ld-powerpc/addpcis.s: New test. * ld-powerpc/powerpc.exp: Run it.
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog9
-rw-r--r--gold/powerpc.cc69
2 files changed, 73 insertions, 5 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index a08b425..2b96de5 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,12 @@
+2015-11-11 Alan Modra <amodra@gmail.com>
+ Peter Bergner <bergner@vnet.ibm.com>
+
+ * gold/powerpc.cc (Powerpc_relocate_functions::addr16_dq): New function.
+ (Powerpc_relocate_functions::addr16dx_ha): Likewise.
+ (Target_powerpc::Scan::local): Handle R_POWERPC_REL16DX_HA.
+ (Target_powerpc::Scan::global): Likewise.
+ (Target_powerpc::Relocate::relocate): Likewise.
+
2015-11-09 Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
* layout.h (Layout::is_debug_info_section): Recognize .pdr debug
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index e991371..3a013ef 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -1520,6 +1520,7 @@ public:
private:
typedef Powerpc_relocate_functions<size, big_endian> This;
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+ typedef typename elfcpp::Elf_types<size>::Elf_Swxword SignedAddress;
template<int valsize>
static inline bool
@@ -1680,6 +1681,16 @@ public:
return stat;
}
+ // R_POWERPC_ADDR16_DQ: (Symbol + Addend) & 0xfff0
+ static inline Status
+ addr16_dq(unsigned char* view, Address value, Overflow_check overflow)
+ {
+ Status stat = This::template rela<16,16>(view, 0, 0xfff0, value, overflow);
+ if ((value & 15) != 0)
+ stat = STATUS_OVERFLOW;
+ return stat;
+ }
+
// R_POWERPC_ADDR16_HI: ((Symbol + Addend) >> 16) & 0xffff
static inline void
addr16_hi(unsigned char* view, Address value)
@@ -1719,6 +1730,20 @@ public:
stat = STATUS_OVERFLOW;
return stat;
}
+
+ // R_POWERPC_REL16DX_HA
+ static inline Status
+ addr16dx_ha(unsigned char *view, Address value, Overflow_check overflow)
+ {
+ typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
+ Valtype* wv = reinterpret_cast<Valtype*>(view);
+ Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
+ value += 0x8000;
+ value = static_cast<SignedAddress>(value) >> 16;
+ val |= (value & 0xffc1) | ((value & 0x3e) << 15);
+ elfcpp::Swap<32, big_endian>::writeval(wv, val);
+ return overflowed<16>(value, overflow);
+ }
};
// Set ABI version for input and output.
@@ -5689,6 +5714,7 @@ Target_powerpc<size, big_endian>::Scan::local(
case elfcpp::R_POWERPC_REL16_LO:
case elfcpp::R_POWERPC_REL16_HI:
case elfcpp::R_POWERPC_REL16_HA:
+ case elfcpp::R_POWERPC_REL16DX_HA:
case elfcpp::R_POWERPC_SECTOFF:
case elfcpp::R_POWERPC_SECTOFF_LO:
case elfcpp::R_POWERPC_SECTOFF_HI:
@@ -6138,6 +6164,7 @@ Target_powerpc<size, big_endian>::Scan::global(
case elfcpp::R_POWERPC_REL16_LO:
case elfcpp::R_POWERPC_REL16_HI:
case elfcpp::R_POWERPC_REL16_HA:
+ case elfcpp::R_POWERPC_REL16DX_HA:
case elfcpp::R_POWERPC_SECTOFF:
case elfcpp::R_POWERPC_SECTOFF_LO:
case elfcpp::R_POWERPC_SECTOFF_HI:
@@ -7441,6 +7468,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_POWERPC_REL16_LO:
case elfcpp::R_POWERPC_REL16_HI:
case elfcpp::R_POWERPC_REL16_HA:
+ case elfcpp::R_POWERPC_REL16DX_HA:
case elfcpp::R_POWERPC_REL14:
case elfcpp::R_POWERPC_REL14_BRTAKEN:
case elfcpp::R_POWERPC_REL14_BRNTAKEN:
@@ -7639,6 +7667,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
break;
case elfcpp::R_POWERPC_REL32:
+ case elfcpp::R_POWERPC_REL16DX_HA:
if (size == 64)
overflow = Reloc::CHECK_SIGNED;
break;
@@ -7719,11 +7748,13 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
break;
}
+ Insn* iview = reinterpret_cast<Insn*>(view - 2 * big_endian);
+ Insn insn = 0;
+
if (overflow == Reloc::CHECK_LOW_INSN
|| overflow == Reloc::CHECK_HIGH_INSN)
{
- Insn* iview = reinterpret_cast<Insn*>(view - 2 * big_endian);
- Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
+ insn = elfcpp::Swap<32, big_endian>::readval(iview);
if ((insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
overflow = Reloc::CHECK_BITFIELD;
@@ -7739,6 +7770,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
overflow = Reloc::CHECK_SIGNED;
}
+ bool maybe_dq_reloc = false;
typename Powerpc_relocate_functions<size, big_endian>::Status status
= Powerpc_relocate_functions<size, big_endian>::STATUS_OK;
switch (r_type)
@@ -7791,7 +7823,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
if (size == 64)
{
// On ppc64 these are all ds form
- status = Reloc::addr16_ds(view, value, overflow);
+ maybe_dq_reloc = true;
break;
}
case elfcpp::R_POWERPC_ADDR16:
@@ -7812,7 +7844,10 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_POWERPC_DTPREL16_LO:
case elfcpp::R_POWERPC_GOT_TLSGD16_LO:
case elfcpp::R_POWERPC_GOT_TLSLD16_LO:
- status = Reloc::addr16(view, value, overflow);
+ if (size == 64)
+ status = Reloc::addr16(view, value, overflow);
+ else
+ maybe_dq_reloc = true;
break;
case elfcpp::R_POWERPC_UADDR16:
@@ -7859,6 +7894,10 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
Reloc::addr16_ha(view, value);
break;
+ case elfcpp::R_POWERPC_REL16DX_HA:
+ status = Reloc::addr16dx_ha(view, value, overflow);
+ break;
+
case elfcpp::R_PPC64_DTPREL16_HIGHER:
if (size == 32)
// R_PPC_EMB_NADDR16_LO
@@ -7913,7 +7952,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_PPC64_GOT16_LO_DS:
case elfcpp::R_PPC64_SECTOFF_DS:
case elfcpp::R_PPC64_SECTOFF_LO_DS:
- status = Reloc::addr16_ds(view, value, overflow);
+ maybe_dq_reloc = true;
break;
case elfcpp::R_POWERPC_ADDR14:
@@ -7978,6 +8017,26 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
r_type);
break;
}
+
+ if (maybe_dq_reloc)
+ {
+ if (insn == 0)
+ insn = elfcpp::Swap<32, big_endian>::readval(iview);
+
+ if ((insn & (0x3f << 26)) == 56u << 26 /* lq */
+ || ((insn & (0x3f << 26)) == (61u << 26) /* lxv, stxv */
+ && (insn & 3) == 1))
+ status = Reloc::addr16_dq(view, value, overflow);
+ else if (size == 64
+ || (insn & (0x3f << 26)) == 58u << 26 /* ld,ldu,lwa */
+ || (insn & (0x3f << 26)) == 62u << 26 /* std,stdu,stq */
+ || (insn & (0x3f << 26)) == 57u << 26 /* lfdp */
+ || (insn & (0x3f << 26)) == 61u << 26 /* stfdp */)
+ status = Reloc::addr16_ds(view, value, overflow);
+ else
+ status = Reloc::addr16(view, value, overflow);
+ }
+
if (status != Powerpc_relocate_functions<size, big_endian>::STATUS_OK
&& (has_stub_value
|| !(gsym != NULL