Allow both signed and unsigned fields in PowerPC cmpli insn
authorAlan Modra <amodra@gmail.com>
Sat, 7 Jun 2014 02:39:04 +0000 (12:09 +0930)
committerAlan Modra <amodra@gmail.com>
Sat, 7 Jun 2014 05:25:11 +0000 (14:55 +0930)
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.

bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf64-ppc.c
gas/ChangeLog
gas/config/tc-ppc.c
gold/ChangeLog
gold/powerpc.cc
opcodes/ChangeLog
opcodes/ppc-opc.c

index 1ff9fca4876f5177891baa341f7f04e2bb404968..c14719f01e396a1b5fc06d194bd7326adb505c92 100644 (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.
index 1bea6f820698ea641bf11b463cb65102c2437944..344845d76c4161d4cef2e03c5b0f844cfc8640bd 100644 (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)
index e7e2e397666d097d87325297a4955525f5d2594a..b8d74658b8a0fc273c202da6670125546f2df2f1 100644 (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)
            {
index f68f30c8ee2ae020af25b27c82c9051795832712..fd331d7986338fb895032c9eebfaaa23da9e9e13 100644 (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:.
index 2c8ce6af4bac96d5713cb4412215967dc98fd6c2..ff4ea646de09e01563c8a3e693e3b3a1637b391b 100644 (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)
+    {
+      /* 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)
     {
-      if ((operand->flags & PPC_OPERAND_SIGNOPT) == 0)
-       max = (max >> 1) & -right;
+      max = (max >> 1) & -right;
       min = ~max & -right;
     }
 
index 2fb28c56194e3d47b7c3c725da2cfb1d9933fe9f..385fef12cb0cf502dbb07e0fbcced824b3084890 100644 (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_.
index bd3994a9d186cb808fb25d550b4bb48c2d7068cb..96432ed2ffe97d1b59294fcfc30e07cbdf7d3455 100644 (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;
     }
 
index 499ec643ddbb83f27155cc15458e3bca6b51d703..6e3d6c97cbcf2ea0ab6d7ca8d97da1e75dc7008b 100644 (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
index 1d27961d4880fc267c2b9d65e320e8633d5246cc..a5cfe1aab25d92cc46c72885285e7c2bc0bf71da 100644 (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}},