Allow both signed and unsigned fields in PowerPC cmpli insn

There are legitimate reasons to allow a signed value in a cmpli insn
field, for example to test for a "stw r1,lock@sdarel(r13)" instruction
in user code, a kernel might use
	subis r3,r3,STW_R1_0R13@ha	# subtract off high part
	cmplwi r3,lock@sdarel		# is low part accessing lock?
Since the lock@sdarel may take a range of -32768 to 32767,
the allowed range of cmpli immediate must be at least [-32768,65535].

bfd/
	* elf32-ppc.c (ppc_elf_relocate_section): Treat field of cmpli
	insn as a bitfield; Use complain_overflow_bitfield.
	* elf64-ppc.c (ppc64_elf_relocate_section): Likewise.
opcodes/
	* ppc-opc.c (UISIGNOPT): Define and use with cmpli.
gas/
	* config/tc-ppc.c (ppc_insert_operand): Handle PPC_OPERAND_SIGNOPT
	on unsigned fields.  Comment on PPC_OPERAND_SIGNOPT signed fields
	in 64-bit mode.
gold/
	* powerpc.cc (relocate): Treat field of cmpli insn as a bitfield.
This commit is contained in:
Alan Modra 2014-06-07 12:09:04 +09:30
parent d634c69f87
commit a47622ac1b
9 changed files with 67 additions and 28 deletions

View file

@ -1,3 +1,9 @@
2014-06-07 Alan Modra <amodra@gmail.com>
* elf32-ppc.c (ppc_elf_relocate_section): Treat field of cmpli
insn as a bitfield; Use complain_overflow_bitfield.
* elf64-ppc.c (ppc64_elf_relocate_section): Likewise.
2014-06-05 Joel Brobecker <brobecker@adacore.com>
* development.sh: New file.

View file

@ -9147,10 +9147,11 @@ ppc_elf_relocate_section (bfd *output_bfd,
unsigned int insn;
insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
if ((insn & (0x3f << 26)) == 28u << 26 /* andi */
|| (insn & (0x3f << 26)) == 24u << 26 /* ori */
|| (insn & (0x3f << 26)) == 26u << 26 /* xori */
|| (insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
if ((insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
complain = complain_overflow_bitfield;
else if ((insn & (0x3f << 26)) == 28u << 26 /* andi */
|| (insn & (0x3f << 26)) == 24u << 26 /* ori */
|| (insn & (0x3f << 26)) == 26u << 26 /* xori */)
complain = complain_overflow_unsigned;
}
if (howto->complain_on_overflow != complain)

View file

@ -14648,14 +14648,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
enum complain_overflow complain = complain_overflow_signed;
insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
if (howto->rightshift == 0
? ((insn & (0x3f << 26)) == 28u << 26 /* andi */
|| (insn & (0x3f << 26)) == 24u << 26 /* ori */
|| (insn & (0x3f << 26)) == 26u << 26 /* xori */
|| (insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
: ((insn & (0x3f << 26)) == 29u << 26 /* andis */
|| (insn & (0x3f << 26)) == 25u << 26 /* oris */
|| (insn & (0x3f << 26)) == 27u << 26 /* xoris */))
if ((insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
complain = complain_overflow_bitfield;
else if (howto->rightshift == 0
? ((insn & (0x3f << 26)) == 28u << 26 /* andi */
|| (insn & (0x3f << 26)) == 24u << 26 /* ori */
|| (insn & (0x3f << 26)) == 26u << 26 /* xori */)
: ((insn & (0x3f << 26)) == 29u << 26 /* andis */
|| (insn & (0x3f << 26)) == 25u << 26 /* oris */
|| (insn & (0x3f << 26)) == 27u << 26 /* xoris */))
complain = complain_overflow_unsigned;
if (howto->complain_on_overflow != complain)
{

View file

@ -1,3 +1,9 @@
2014-06-07 Alan Modra <amodra@gmail.com>
* config/tc-ppc.c (ppc_insert_operand): Handle PPC_OPERAND_SIGNOPT
on unsigned fields. Comment on PPC_OPERAND_SIGNOPT signed fields
in 64-bit mode.
2014-06-02 Martin Storsjo <martin@martin.st>
* doc/c-aarch64.texi: Fix the documentation on :pg_hi21:.

View file

@ -1781,10 +1781,23 @@ ppc_insert_operand (unsigned long insn,
right = max & -max;
min = 0;
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0)
{
if ((operand->flags & PPC_OPERAND_SIGNOPT) == 0)
max = (max >> 1) & -right;
/* Extend the allowed range for addis to [-65536, 65535].
Similarly for some VLE high part insns. For 64-bit it
would be good to disable this for signed fields since the
value is sign extended into the high 32 bits of the register.
If the value is, say, an address, then we might care about
the high bits. However, gcc as of 2014-06 uses unsigned
values when loading the high part of 64-bit constants using
lis.
Use the same extended range for cmpli, to allow at least
[-32768, 65535]. */
min = ~max & -right;
}
else if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
{
max = (max >> 1) & -right;
min = ~max & -right;
}

View file

@ -1,3 +1,7 @@
2014-06-07 Alan Modra <amodra@gmail.com>
* powerpc.cc (relocate): Treat field of cmpli insn as a bitfield.
2014-06-06 Cary Coutant <ccoutant@google.com>
* dwarf_reader.h (Dwarf_pubnames_table): Remove output_section_offset_.

View file

@ -7409,14 +7409,15 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
overflow = Reloc::CHECK_SIGNED;
if (overflow == Reloc::CHECK_LOW_INSN
? ((insn & (0x3f << 26)) == 28u << 26 /* andi */
|| (insn & (0x3f << 26)) == 24u << 26 /* ori */
|| (insn & (0x3f << 26)) == 26u << 26 /* xori */
|| (insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
: ((insn & (0x3f << 26)) == 29u << 26 /* andis */
|| (insn & (0x3f << 26)) == 25u << 26 /* oris */
|| (insn & (0x3f << 26)) == 27u << 26 /* xoris */))
if ((insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
overflow = Reloc::CHECK_BITFIELD;
else if (overflow == Reloc::CHECK_LOW_INSN
? ((insn & (0x3f << 26)) == 28u << 26 /* andi */
|| (insn & (0x3f << 26)) == 24u << 26 /* ori */
|| (insn & (0x3f << 26)) == 26u << 26 /* xori */)
: ((insn & (0x3f << 26)) == 29u << 26 /* andis */
|| (insn & (0x3f << 26)) == 25u << 26 /* oris */
|| (insn & (0x3f << 26)) == 27u << 26 /* xoris */))
overflow = Reloc::CHECK_UNSIGNED;
}

View file

@ -1,3 +1,7 @@
2014-06-07 Alan Modra <amodra@gmail.com>
* ppc-opc.c (UISIGNOPT): Define and use with cmpli.
2014-06-05 Joel Brobecker <brobecker@adacore.com>
* Makefile.am (CONFIG_STATUS_DEPENDENCIES): Add dependency on

View file

@ -654,8 +654,11 @@ const struct powerpc_operand powerpc_operands[] =
#define UI TO + 1
{ 0xffff, 0, NULL, NULL, 0 },
#define UISIGNOPT UI + 1
{ 0xffff, 0, NULL, NULL, PPC_OPERAND_SIGNOPT },
/* The IMM field in an SE_IM5 instruction. */
#define UI5 UI + 1
#define UI5 UISIGNOPT + 1
{ 0x1f, 4, NULL, NULL, 0 },
/* The OIMM field in an SE_OIM5 instruction. */
@ -3500,10 +3503,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{"dozi", OP(9), OP_MASK, M601, PPCNONE, {RT, RA, SI}},
{"cmplwi", OPL(10,0), OPL_MASK, PPCCOM, PPCNONE, {OBF, RA, UI}},
{"cmpldi", OPL(10,1), OPL_MASK, PPC64, PPCNONE, {OBF, RA, UI}},
{"cmpli", OP(10), OP_MASK, PPC, PPCNONE, {BF, L, RA, UI}},
{"cmpli", OP(10), OP_MASK, PWRCOM, PPC, {BF, RA, UI}},
{"cmplwi", OPL(10,0), OPL_MASK, PPCCOM, PPCNONE, {OBF, RA, UISIGNOPT}},
{"cmpldi", OPL(10,1), OPL_MASK, PPC64, PPCNONE, {OBF, RA, UISIGNOPT}},
{"cmpli", OP(10), OP_MASK, PPC, PPCNONE, {BF, L, RA, UISIGNOPT}},
{"cmpli", OP(10), OP_MASK, PWRCOM, PPC, {BF, RA, UISIGNOPT}},
{"cmpwi", OPL(11,0), OPL_MASK, PPCCOM, PPCNONE, {OBF, RA, SI}},
{"cmpdi", OPL(11,1), OPL_MASK, PPC64, PPCNONE, {OBF, RA, SI}},