summaryrefslogtreecommitdiff
path: root/gold/powerpc.cc
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-06-07 12:09:04 +0930
committerAlan Modra <amodra@gmail.com>2014-06-07 14:55:11 +0930
commita47622ac1badbd906c7533ef6011b6bb021271ee (patch)
tree3e6ad4e4cb4ed80e652cf756cbbacf4a7a6ae3d1 /gold/powerpc.cc
parentd634c69f87e9b88a5ff5cd8af7a1f60e738ea0bd (diff)
downloadbinutils-gdb-a47622ac1badbd906c7533ef6011b6bb021271ee.tar.gz
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.
Diffstat (limited to 'gold/powerpc.cc')
-rw-r--r--gold/powerpc.cc17
1 files changed, 9 insertions, 8 deletions
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index bd3994a9d18..96432ed2ffe 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -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;
}