mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 13:27:26 +08:00
R_PPC64_PCREL_OPT
The loads and stores handled in the second instruction of a sequence marked by R_PPC64_PCREL_OPT may be a prefix instruction. For example: pld ra,symbol@got@pcrel 0: pld rt,off(ra) .reloc 0b-8,R_PPC64_PCREL_OPT,(.-8)-(0b-8) can be optimised to pld rt,symbol+off@pcrel pnop * elf64-ppc.c (xlate_pcrel_opt): Handle prefix loads and stores in second instruction. (ppc64_elf_relocate_section): Likewise.
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
2019-09-05 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* elf64-ppc.c (xlate_pcrel_opt): Handle prefix loads and stores
|
||||||
|
in second instruction.
|
||||||
|
(ppc64_elf_relocate_section): Likewise.
|
||||||
|
|
||||||
2019-09-05 Alan Modra <amodra@gmail.com>
|
2019-09-05 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR 24955
|
PR 24955
|
||||||
|
@ -8282,12 +8282,31 @@ ok_lo_toc_insn (unsigned int insn, enum elf_ppc64_reloc_type r_type)
|
|||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
|
xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
|
||||||
{
|
{
|
||||||
uint32_t insn2 = *pinsn2 >> 32;
|
uint64_t insn1 = *pinsn1;
|
||||||
uint64_t i1new;
|
uint64_t insn2 = *pinsn2;
|
||||||
bfd_signed_vma off;
|
bfd_signed_vma off;
|
||||||
|
|
||||||
|
if ((insn2 & (63ULL << 58)) == 1ULL << 58)
|
||||||
|
{
|
||||||
|
/* Check that regs match. */
|
||||||
|
if (((insn2 >> 16) & 31) != ((insn1 >> 21) & 31))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* P8LS or PMLS form, non-pcrel. */
|
||||||
|
if ((insn2 & (-1ULL << 50) & ~(1ULL << 56)) != (1ULL << 58))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*pinsn1 = (insn2 & ~(31 << 16) & ~0x3ffff0000ffffULL) | (1ULL << 52);
|
||||||
|
*pinsn2 = PNOP;
|
||||||
|
off = ((insn2 >> 16) & 0x3ffff0000ULL) | (insn2 & 0xffff);
|
||||||
|
*poff = (off ^ 0x200000000ULL) - 0x200000000ULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
insn2 >>= 32;
|
||||||
|
|
||||||
/* Check that regs match. */
|
/* Check that regs match. */
|
||||||
if (((insn2 >> 16) & 31) != ((*pinsn1 >> 21) & 31))
|
if (((insn2 >> 16) & 31) != ((insn1 >> 21) & 31))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
switch ((insn2 >> 26) & 63)
|
switch ((insn2 >> 26) & 63)
|
||||||
@ -8308,7 +8327,7 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
|
|||||||
case 54: /* stfd */
|
case 54: /* stfd */
|
||||||
/* These are the PMLS cases, where we just need to tack a prefix
|
/* These are the PMLS cases, where we just need to tack a prefix
|
||||||
on the insn. */
|
on the insn. */
|
||||||
i1new = ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
|
insn1 = ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
|
||||||
| (insn2 & ((63ULL << 26) | (31ULL << 21))));
|
| (insn2 & ((63ULL << 26) | (31ULL << 21))));
|
||||||
off = insn2 & 0xffff;
|
off = insn2 & 0xffff;
|
||||||
break;
|
break;
|
||||||
@ -8316,7 +8335,7 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
|
|||||||
case 58: /* lwa, ld */
|
case 58: /* lwa, ld */
|
||||||
if ((insn2 & 1) != 0)
|
if ((insn2 & 1) != 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
i1new = ((1ULL << 58) | (1ULL << 52)
|
insn1 = ((1ULL << 58) | (1ULL << 52)
|
||||||
| (insn2 & 2 ? 41ULL << 26 : 57ULL << 26)
|
| (insn2 & 2 ? 41ULL << 26 : 57ULL << 26)
|
||||||
| (insn2 & (31ULL << 21)));
|
| (insn2 & (31ULL << 21)));
|
||||||
off = insn2 & 0xfffc;
|
off = insn2 & 0xfffc;
|
||||||
@ -8325,7 +8344,7 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
|
|||||||
case 57: /* lxsd, lxssp */
|
case 57: /* lxsd, lxssp */
|
||||||
if ((insn2 & 3) < 2)
|
if ((insn2 & 3) < 2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
i1new = ((1ULL << 58) | (1ULL << 52)
|
insn1 = ((1ULL << 58) | (1ULL << 52)
|
||||||
| ((40ULL | (insn2 & 3)) << 26)
|
| ((40ULL | (insn2 & 3)) << 26)
|
||||||
| (insn2 & (31ULL << 21)));
|
| (insn2 & (31ULL << 21)));
|
||||||
off = insn2 & 0xfffc;
|
off = insn2 & 0xfffc;
|
||||||
@ -8336,14 +8355,14 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
else if ((insn2 & 3) >= 2)
|
else if ((insn2 & 3) >= 2)
|
||||||
{
|
{
|
||||||
i1new = ((1ULL << 58) | (1ULL << 52)
|
insn1 = ((1ULL << 58) | (1ULL << 52)
|
||||||
| ((44ULL | (insn2 & 3)) << 26)
|
| ((44ULL | (insn2 & 3)) << 26)
|
||||||
| (insn2 & (31ULL << 21)));
|
| (insn2 & (31ULL << 21)));
|
||||||
off = insn2 & 0xfffc;
|
off = insn2 & 0xfffc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i1new = ((1ULL << 58) | (1ULL << 52)
|
insn1 = ((1ULL << 58) | (1ULL << 52)
|
||||||
| ((50ULL | (insn2 & 4) | ((insn2 & 8) >> 3)) << 26)
|
| ((50ULL | (insn2 & 4) | ((insn2 & 8) >> 3)) << 26)
|
||||||
| (insn2 & (31ULL << 21)));
|
| (insn2 & (31ULL << 21)));
|
||||||
off = insn2 & 0xfff0;
|
off = insn2 & 0xfff0;
|
||||||
@ -8351,7 +8370,7 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 56: /* lq */
|
case 56: /* lq */
|
||||||
i1new = ((1ULL << 58) | (1ULL << 52)
|
insn1 = ((1ULL << 58) | (1ULL << 52)
|
||||||
| (insn2 & ((63ULL << 26) | (31ULL << 21))));
|
| (insn2 & ((63ULL << 26) | (31ULL << 21))));
|
||||||
off = insn2 & 0xffff;
|
off = insn2 & 0xffff;
|
||||||
break;
|
break;
|
||||||
@ -8359,14 +8378,14 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
|
|||||||
case 62: /* std, stq */
|
case 62: /* std, stq */
|
||||||
if ((insn2 & 1) != 0)
|
if ((insn2 & 1) != 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
i1new = ((1ULL << 58) | (1ULL << 52)
|
insn1 = ((1ULL << 58) | (1ULL << 52)
|
||||||
| ((insn2 & 2) == 0 ? 61ULL << 26 : 60ULL << 26)
|
| ((insn2 & 2) == 0 ? 61ULL << 26 : 60ULL << 26)
|
||||||
| (insn2 & (31ULL << 21)));
|
| (insn2 & (31ULL << 21)));
|
||||||
off = insn2 & 0xfffc;
|
off = insn2 & 0xfffc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pinsn1 = i1new;
|
*pinsn1 = insn1;
|
||||||
*pinsn2 = (uint64_t) NOP << 32;
|
*pinsn2 = (uint64_t) NOP << 32;
|
||||||
*poff = (off ^ 0x8000) - 0x8000;
|
*poff = (off ^ 0x8000) - 0x8000;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -15413,7 +15432,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
pinsn2 = bfd_get_32 (input_bfd, contents + off2);
|
pinsn2 = bfd_get_32 (input_bfd, contents + off2);
|
||||||
pinsn2 <<= 32;
|
pinsn2 <<= 32;
|
||||||
if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
|
if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
|
||||||
break;
|
{
|
||||||
|
if (off2 + 8 > input_section->size)
|
||||||
|
break;
|
||||||
|
pinsn2 |= bfd_get_32 (input_bfd,
|
||||||
|
contents + off2 + 4);
|
||||||
|
}
|
||||||
if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off))
|
if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off))
|
||||||
{
|
{
|
||||||
addend += addend_off;
|
addend += addend_off;
|
||||||
@ -15424,6 +15448,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
contents + offset + 4);
|
contents + offset + 4);
|
||||||
bfd_put_32 (input_bfd, pinsn2 >> 32,
|
bfd_put_32 (input_bfd, pinsn2 >> 32,
|
||||||
contents + off2);
|
contents + off2);
|
||||||
|
if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
|
||||||
|
bfd_put_32 (input_bfd, pinsn2,
|
||||||
|
contents + off2 + 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2019-09-05 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* testsuite/ld-powerpc/pcrelopt.s,
|
||||||
|
* testsuite/ld-powerpc/pcrelopt.d: Test offset and prefix in
|
||||||
|
second instruction.
|
||||||
|
|
||||||
2019-08-29 Alan Modra <amodra@gmail.com>
|
2019-08-29 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR ld/24406
|
PR ld/24406
|
||||||
|
@ -80,10 +80,17 @@ Disassembly of section \.text:
|
|||||||
.*: (04 10 00 01|01 00 10 04) pstxv vs0,66028
|
.*: (04 10 00 01|01 00 10 04) pstxv vs0,66028
|
||||||
.*: (d8 00 01 ec|ec 01 00 d8)
|
.*: (d8 00 01 ec|ec 01 00 d8)
|
||||||
.*: (60 00 00 00|00 00 00 60) nop
|
.*: (60 00 00 00|00 00 00 60) nop
|
||||||
.*: (04 10 00 01|01 00 10 04) pld r9,66008
|
.*: (06 10 00 01|01 00 10 06) plbz r3,70676
|
||||||
.*: (e5 20 01 d8|d8 01 20 e5)
|
.*: (88 60 14 14|14 14 60 88)
|
||||||
.*: (e8 09 00 00|00 00 09 e8) ld r0,0\(r9\)
|
|
||||||
.*: (60 00 00 00|00 00 00 60) nop
|
.*: (60 00 00 00|00 00 00 60) nop
|
||||||
.*: (06 10 00 01|01 00 10 06) pla r7,66000
|
.*: (60 00 00 00|00 00 00 60) nop
|
||||||
.*: (38 e0 01 d0|d0 01 e0 38)
|
.*: (04 10 12 35|35 12 10 04) plq r4,305485896
|
||||||
|
.*: (e0 80 58 48|48 58 80 e0)
|
||||||
|
.*: (07 00 00 00|00 00 00 07) pnop
|
||||||
|
.*: (00 00 00 00|00 00 00 00)
|
||||||
|
.*: (04 10 00 01|01 00 10 04) pld r9,65976
|
||||||
|
.*: (e5 20 01 b8|b8 01 20 e5)
|
||||||
|
.*: (e8 09 00 00|00 00 09 e8) ld r0,0\(r9\)
|
||||||
|
.*: (06 10 00 01|01 00 10 06) pla r7,65972
|
||||||
|
.*: (38 e0 01 b4|b4 01 e0 38)
|
||||||
.*: (88 c7 00 00|00 00 c7 88) lbz r6,0\(r7\)
|
.*: (88 c7 00 00|00 00 c7 88) lbz r6,0\(r7\)
|
||||||
|
@ -103,6 +103,18 @@ _start:
|
|||||||
.reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8)
|
.reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8)
|
||||||
0: stxv 0,0(9)
|
0: stxv 0,0(9)
|
||||||
|
|
||||||
|
#offsets are allowed too
|
||||||
|
pld 9,sym@got@pcrel
|
||||||
|
0:
|
||||||
|
lbz 3,0x1234(9)
|
||||||
|
.reloc 0b-8,R_PPC64_PCREL_OPT,(.-4)-(0b-8)
|
||||||
|
|
||||||
|
#and prefix insns as the second insn
|
||||||
|
pld 9,sym@got@pcrel
|
||||||
|
0:
|
||||||
|
plq 4,0x12345678(9)
|
||||||
|
.reloc 0b-8,R_PPC64_PCREL_OPT,(.-8)-(0b-8)
|
||||||
|
|
||||||
# This should not optimize
|
# This should not optimize
|
||||||
.extern i
|
.extern i
|
||||||
.type i,@object
|
.type i,@object
|
||||||
|
Reference in New Issue
Block a user