static bfd_boolean
xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
{
- uint32_t insn2 = *pinsn2 >> 32;
- uint64_t i1new;
+ uint64_t insn1 = *pinsn1;
+ uint64_t insn2 = *pinsn2;
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. */
- if (((insn2 >> 16) & 31) != ((*pinsn1 >> 21) & 31))
+ if (((insn2 >> 16) & 31) != ((insn1 >> 21) & 31))
return FALSE;
switch ((insn2 >> 26) & 63)
case 54: /* stfd */
/* These are the PMLS cases, where we just need to tack a prefix
on the insn. */
- i1new = ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
+ insn1 = ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
| (insn2 & ((63ULL << 26) | (31ULL << 21))));
off = insn2 & 0xffff;
break;
case 58: /* lwa, ld */
if ((insn2 & 1) != 0)
return FALSE;
- i1new = ((1ULL << 58) | (1ULL << 52)
+ insn1 = ((1ULL << 58) | (1ULL << 52)
| (insn2 & 2 ? 41ULL << 26 : 57ULL << 26)
| (insn2 & (31ULL << 21)));
off = insn2 & 0xfffc;
case 57: /* lxsd, lxssp */
if ((insn2 & 3) < 2)
return FALSE;
- i1new = ((1ULL << 58) | (1ULL << 52)
+ insn1 = ((1ULL << 58) | (1ULL << 52)
| ((40ULL | (insn2 & 3)) << 26)
| (insn2 & (31ULL << 21)));
off = insn2 & 0xfffc;
return FALSE;
else if ((insn2 & 3) >= 2)
{
- i1new = ((1ULL << 58) | (1ULL << 52)
+ insn1 = ((1ULL << 58) | (1ULL << 52)
| ((44ULL | (insn2 & 3)) << 26)
| (insn2 & (31ULL << 21)));
off = insn2 & 0xfffc;
}
else
{
- i1new = ((1ULL << 58) | (1ULL << 52)
+ insn1 = ((1ULL << 58) | (1ULL << 52)
| ((50ULL | (insn2 & 4) | ((insn2 & 8) >> 3)) << 26)
| (insn2 & (31ULL << 21)));
off = insn2 & 0xfff0;
break;
case 56: /* lq */
- i1new = ((1ULL << 58) | (1ULL << 52)
+ insn1 = ((1ULL << 58) | (1ULL << 52)
| (insn2 & ((63ULL << 26) | (31ULL << 21))));
off = insn2 & 0xffff;
break;
case 62: /* std, stq */
if ((insn2 & 1) != 0)
return FALSE;
- i1new = ((1ULL << 58) | (1ULL << 52)
+ insn1 = ((1ULL << 58) | (1ULL << 52)
| ((insn2 & 2) == 0 ? 61ULL << 26 : 60ULL << 26)
| (insn2 & (31ULL << 21)));
off = insn2 & 0xfffc;
break;
}
- *pinsn1 = i1new;
+ *pinsn1 = insn1;
*pinsn2 = (uint64_t) NOP << 32;
*poff = (off ^ 0x8000) - 0x8000;
return TRUE;
pinsn2 = bfd_get_32 (input_bfd, contents + off2);
pinsn2 <<= 32;
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))
{
addend += addend_off;
contents + offset + 4);
bfd_put_32 (input_bfd, pinsn2 >> 32,
contents + off2);
+ if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
+ bfd_put_32 (input_bfd, pinsn2,
+ contents + off2 + 4);
}
}
}
.*: (04 10 00 01|01 00 10 04) pstxv vs0,66028
.*: (d8 00 01 ec|ec 01 00 d8)
.*: (60 00 00 00|00 00 00 60) nop
-.*: (04 10 00 01|01 00 10 04) pld r9,66008
-.*: (e5 20 01 d8|d8 01 20 e5)
-.*: (e8 09 00 00|00 00 09 e8) ld r0,0\(r9\)
+.*: (06 10 00 01|01 00 10 06) plbz r3,70676
+.*: (88 60 14 14|14 14 60 88)
+.*: (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
-.*: (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\)