]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Allow for optional operands with non-zero default values.
authorPeter Bergner <bergner@vnet.ibm.com>
Fri, 19 Jun 2015 22:17:07 +0000 (17:17 -0500)
committerAlan Modra <amodra@gmail.com>
Fri, 10 Jul 2015 10:28:19 +0000 (19:58 +0930)
ISA 2.07 (ie, POWER8) added the rfebb instruction which takes one operand
with the value of either a 0 or 1.  It also defines an extended mnemonic
with no operands (ie, "rfebb") that is supposed to be equivalent to "rfebb 1".
I implemented rfebb's lone operand with PPC_OPERAND_OPTIONAL, but the
problem is, optional operands that are ommitted always default to the
value 0, which is wrong in this case.  I have added support for allowing
non-zero default values by adding an additional flag PPC_OPERAND_OPTIONAL_VALUE
that specifies that the default operand value to be used is stored in the
SHIFT field of the operand field immediately following this one.

This fixes the rfebb issue.  I also fixed the mftb and mfcr instructions
so they use the same mechanism.  This allows us to flag invalid uses of
mfcr where we explicitly pass in a zero FXM value, like the use in a2.[sd].

include/opcode/

* ppc.h (PPC_OPERAND_OPTIONAL_VALUE): New.
(ppc_optional_operand_value): New inline function.

opcodes/
* ppc-dis.h (skip_optional_operands): Use ppc_optional_operand_value.
* ppc-opc.c (FXM4): Add non-zero optional value.
(TBR): Likewise.
(SXL): Likewise.
(insert_fxm): Handle new default operand value.
(extract_fxm): Likewise.
(insert_tbr): Likewise.
(extract_tbr): Likewise.

gas/
* config/tc-ppc.c (md_assemble): Use ppc_optional_operand_value.
Allow for optional operands without insert functions.

gas/testsuite/
* gas/ppc/power8.d: Fixup rfebb test results.
* gas/ppc/a2.s: Fix invalid mfcr test.
* gas/ppc/a2.d: Likewise.

gas/ChangeLog
gas/config/tc-ppc.c
gas/testsuite/ChangeLog
gas/testsuite/gas/ppc/a2.d
gas/testsuite/gas/ppc/a2.s
gas/testsuite/gas/ppc/power8.d
include/opcode/ChangeLog
include/opcode/ppc.h
opcodes/ChangeLog
opcodes/ppc-dis.c
opcodes/ppc-opc.c

index 68f5b7bf894e4ca9b67cb284b88bc735b4b10a0c..6ca50670458c892a80cf7483b54aa07506ef0a10 100644 (file)
@@ -1,6 +1,10 @@
 2015-07-10  Alan Modra  <amodra@gmail.com>
 
        Apply from master
+       2015-06-19  Peter Bergner  <bergner@vnet.ibm.com>
+       * config/tc-ppc.c (md_assemble): Use ppc_optional_operand_value.
+       Allow for optional operands without insert functions.
+
        2015-03-11  Alan Modra  <amodra@gmail.com>
        * config/tc-ppc.c (md_assemble): Don't abort on 8 byte insn fixups.
        (md_apply_fix): Report an error on data-only fixups used with insns.
index 13d8dba31915b7348e21fd6153af40158ef78163..00e20f9c83f68ecc7671c1767ce7cb1a1c96933c 100644 (file)
@@ -2752,12 +2752,18 @@ md_assemble (char *str)
       if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
          && skip_optional)
        {
+         long val = ppc_optional_operand_value (operand);
          if (operand->insert)
            {
-             insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
+             insn = (*operand->insert) (insn, val, ppc_cpu, &errmsg);
              if (errmsg != (const char *) NULL)
                as_bad ("%s", errmsg);
            }
+         else if (operand->shift >= 0)
+           insn |= ((long) val & operand->bitm) << operand->shift;
+         else
+           insn |= ((long) val & operand->bitm) >> -operand->shift;
+
          if ((operand->flags & PPC_OPERAND_NEXT) != 0)
            next_opindex = *opindex_ptr + 1;
          continue;
index 3ebb81b4cb34f8451f937528248e3b9b40e0bb84..4af0bb01e2365a2f2c226b45e1e1d007fba6a6c9 100644 (file)
@@ -1,6 +1,11 @@
 2015-07-10  Alan Modra  <amodra@gmail.com>
 
        Apply from master
+       2015-06-19  Peter Bergner  <bergner@vnet.ibm.com>
+       * gas/ppc/power8.d: Fixup rfebb test results.
+       * gas/ppc/a2.s: Fix invalid mfcr test.
+       * gas/ppc/a2.d: Likewise.
+
        2015-06-04  Peter Bergner  <bergner@vnet.ibm.com>
        * gas/ppc/a2.d: Fixup test case due to new extended mnemonic.
        * gas/ppc/power4.s <hwsync, lwsync, ptesync, sync>: Add tests.
index aa05cbca5f2476716dc852d4661f00b6ad58dfc9..bb60275afe4874b4daa46873528b9b84af989d3a 100644 (file)
@@ -347,7 +347,7 @@ Disassembly of section \.text:
  4fc:  (7c 00 04 00|00 04 00 7c)       mcrxr   cr0
  500:  (7d 80 04 00|00 04 80 7d)       mcrxr   cr3
  504:  (7c 60 00 26|26 00 60 7c)       mfcr    r3
- 508:  (7c 60 00 26|26 00 60 7c)       mfcr    r3
+ 508:  (7c 70 20 26|26 20 70 7c)       mfocrf  r3,2
  50c:  (7c 70 10 26|26 10 70 7c)       mfocrf  r3,1
  510:  (7c 78 00 26|26 00 78 7c)       mfocrf  r3,128
  514:  (7d 4a 3a 87|87 3a 4a 7d)       mfdcr\.  r10,234
index 7d0ddc77561b8046c75e34d3805a0e62e7957270..ecb8668a51a5026247917b6e7f12633f64023462 100644 (file)
@@ -322,7 +322,7 @@ start:
        mcrxr   0
        mcrxr   3
        mfcr    3
-       mfcr    3,0
+       mfcr    3,0x02
        mfcr    3,0x01
        mfcr    3,0x80
        mfdcr.  10,234
index e66951e2100ee49a0ea5e975bff04c58a4c5667e..61e1cabb7f00aa4504e67ca1f989f958c71b151a 100644 (file)
@@ -27,9 +27,9 @@ Disassembly of section \.text:
   44:  (60 42 00 00|00 00 42 60)       ori     r2,r2,0
   48:  (60 00 00 00|00 00 00 60)       nop
   4c:  (60 42 00 00|00 00 42 60)       ori     r2,r2,0
-  50:  (4c 00 01 24|24 01 00 4c)       rfebb   
-  54:  (4c 00 01 24|24 01 00 4c)       rfebb   
-  58:  (4c 00 09 24|24 09 00 4c)       rfebb   1
+  50:  (4c 00 01 24|24 01 00 4c)       rfebb   0
+  54:  (4c 00 09 24|24 09 00 4c)       rfebb   
+  58:  (4c 00 09 24|24 09 00 4c)       rfebb   
   5c:  (4d 95 04 60|60 04 95 4d)       bctar-  12,4\*cr5\+gt
   60:  (4c 87 04 61|61 04 87 4c)       bctarl- 4,4\*cr1\+so
   64:  (4d ac 04 60|60 04 ac 4d)       bctar\+  12,4\*cr3\+lt
index d378910e4778dae7fc4ebb810a2bf90d041a9efc..e3132d8dd5265dc7231e3041bea0992ead98f177 100644 (file)
@@ -1,3 +1,10 @@
+2015-07-10  Alan Modra  <amodra@gmail.com>
+
+       Apply from master
+       2015-06-19  Peter Bergner <bergner@vnet.ibm.com>
+       * ppc.h (PPC_OPERAND_OPTIONAL_VALUE): New.
+       (ppc_optional_operand_value): New inline function.
+
 2014-10-09  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * sparc.h (sparc_opcode): new field `hwcaps2'.
index c797fa55051477cd16afc35d2b2b9904688e9bf3..5add00fe7fafb8a89389b0b29aa8ac2c14cccfe8 100644 (file)
@@ -380,6 +380,11 @@ extern const unsigned int num_powerpc_operands;
 
 /* This is a CR FIELD that does not use symbolic names.  */
 #define PPC_OPERAND_CR_REG (0x200000)
+
+/* This flag is only used with PPC_OPERAND_OPTIONAL.  If this operand
+   is omitted, then the value it should use for the operand is stored
+   in the SHIFT field of the immediatly following operand field.  */
+#define PPC_OPERAND_OPTIONAL_VALUE (0x400000)
 \f
 /* The POWER and PowerPC assemblers use a few macros.  We keep them
    with the operands table for simplicity.  The macro table is an
@@ -409,4 +414,12 @@ extern const int powerpc_num_macros;
 
 extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, ppc_cpu_t *, const char *);
 
+static inline long
+ppc_optional_operand_value (const struct powerpc_operand *operand)
+{
+  if ((operand->flags & PPC_OPERAND_OPTIONAL_VALUE) != 0)
+    return (operand+1)->shift;
+  return 0;
+}
+
 #endif /* PPC_H */
index da1fdac2b8e044e0965ed4ff007b08d4a8f92337..64b28e23b94d76d1abf0e71db02abb51cc230d45 100644 (file)
@@ -1,6 +1,16 @@
 2015-07-10  Alan Modra  <amodra@gmail.com>
 
        Apply from master
+       2015-06-19  Peter Bergner  <bergner@vnet.ibm.com>
+        * ppc-dis.h (skip_optional_operands): Use ppc_optional_operand_value.
+       * ppc-opc.c (FXM4): Add non-zero optional value.
+       (TBR): Likewise.
+       (SXL): Likewise.
+       (insert_fxm): Handle new default operand value.
+       (extract_fxm): Likewise.
+       (insert_tbr): Likewise.
+       (extract_tbr): Likewise.
+
        2015-06-12  Peter Bergner  <bergner@vnet.ibm.com>
        * ppc-opc.c: Add comment accidentally removed by old commit.
        (MTMSRD_L): Delete.
index 85bbebaa8993dfc17b9f02f69679dc439848df35..2e1075c942d50eb7efa8f9e7565eb10009e15423 100644 (file)
@@ -452,7 +452,8 @@ skip_optional_operands (const unsigned char *opindex,
       operand = &powerpc_operands[*opindex];
       if ((operand->flags & PPC_OPERAND_NEXT) != 0
          || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
-             && operand_value_powerpc (operand, insn, dialect) != 0))
+             && operand_value_powerpc (operand, insn, dialect) !=
+                ppc_optional_operand_value (operand)))
        return 0;
     }
 
index f68d9de767b624757ec2b579ec7ac8c542af6022..40c73ad654d8f6067f2afe5861356d34d7b09c7c 100644 (file)
@@ -382,10 +382,12 @@ const struct powerpc_operand powerpc_operands[] =
 
   /* Power4 version for mfcr.  */
 #define FXM4 FXM + 1
-  { 0xff, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL },
+  { 0xff, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL_VALUE},
+  /* If the FXM4 operand is ommitted, use the sentinel value -1.  */
+  { -1, -1, NULL, NULL, 0},
 
   /* The IMM20 field in an LI instruction.  */
-#define IMM20 FXM4 + 1
+#define IMM20 FXM4 + 2
   { 0xfffff, PPC_OPSHIFT_INV, insert_li20, extract_li20, PPC_OPERAND_SIGNED},
 
   /* The L field in a D or X form instruction.  */
@@ -642,10 +644,12 @@ const struct powerpc_operand powerpc_operands[] =
   /* The TBR field in an XFX form instruction.  This is like the SPR
      field, but it is optional.  */
 #define TBR SV + 1
-  { 0x3ff, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL },
+  { 0x3ff, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL_VALUE},
+  /* If the TBR operand is ommitted, use the value 268.  */
+  { -1, 268, NULL, NULL, 0},
 
   /* The TO field in a D or X form instruction.  */
-#define TO TBR + 1
+#define TO TBR + 2
 #define DUI TO
 #define TO_MASK (0x1f << 21)
   { 0x1f, 21, NULL, NULL, 0 },
@@ -766,10 +770,12 @@ const struct powerpc_operand powerpc_operands[] =
 
   /* The S field in a XL form instruction.  */
 #define SXL S + 1
-  { 0x1, 11, NULL, NULL, PPC_OPERAND_OPTIONAL },
+  { 0x1, 11, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL_VALUE},
+  /* If the SXL operand is ommitted, use the value 1.  */
+  { -1, 1, NULL, NULL, 0},
 
   /* SH field starting at bit position 16.  */
-#define SH16 SXL + 1
+#define SH16 SXL + 2
   /* The DCM and DGM fields in a Z form instruction.  */
 #define DCM SH16
 #define DGM DCM
@@ -1284,19 +1290,13 @@ insert_fxm (unsigned long insn,
        }
     }
 
-  /* If the optional field on mfcr is missing that means we want to use
-     the old form of the instruction that moves the whole cr.  In that
-     case we'll have VALUE zero.  There doesn't seem to be a way to
-     distinguish this from the case where someone writes mfcr %r3,0.  */
-  else if (value == 0)
-    ;
-
   /* If only one bit of the FXM field is set, we can use the new form
      of the instruction, which is faster.  Unlike the Power4 branch hint
      encoding, this is not backward compatible.  Do not generate the
      new form unless -mpower4 has been given, or -many and the two
      operand form of mfcr was used.  */
-  else if ((value & -value) == value
+  else if (value > 0
+          && (value & -value) == value
           && ((dialect & PPC_OPCODE_POWER4) != 0
               || ((dialect & PPC_OPCODE_ANY) != 0
                   && (insn & (0x3ff << 1)) == 19 << 1)))
@@ -1305,7 +1305,10 @@ insert_fxm (unsigned long insn,
   /* Any other value on mfcr is an error.  */
   else if ((insn & (0x3ff << 1)) == 19 << 1)
     {
-      *errmsg = _("ignoring invalid mfcr mask");
+      /* A value of -1 means we used the one operand form of
+        mfcr which is valid.  */
+      if (value != -1)
+        *errmsg = _("ignoring invalid mfcr mask");
       value = 0;
     }
 
@@ -1332,6 +1335,8 @@ extract_fxm (unsigned long insn,
     {
       if (mask != 0)
        *invalid = 1;
+      else
+       mask = -1;
     }
 
   return mask;
@@ -1868,12 +1873,7 @@ extract_sprg (unsigned long insn,
 }
 
 /* The TBR field in an XFX instruction.  This is just like SPR, but it
-   is optional.  When TBR is omitted, it must be inserted as 268 (the
-   magic number of the TB register).  These functions treat 0
-   (indicating an omitted optional operand) as 268.  This means that
-   ``mftb 4,0'' is not handled correctly.  This does not matter very
-   much, since the architecture manual does not define mftb as
-   accepting any values other than 268 or 269.  */
+   is optional.  */
 
 static unsigned long
 insert_tbr (unsigned long insn,
@@ -1881,8 +1881,6 @@ insert_tbr (unsigned long insn,
            ppc_cpu_t dialect ATTRIBUTE_UNUSED,
            const char **errmsg)
 {
-  if (value == 0)
-    value = 268;
   if (value != 268 && value != 269)
     *errmsg = _("invalid tbr number");
   return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
@@ -1898,8 +1896,6 @@ extract_tbr (unsigned long insn,
   ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
   if (ret != 268 && ret != 269)
     *invalid = 1;
-  if (ret == 268)
-    ret = 0;
   return ret;
 }