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)
committerPeter Bergner <bergner@vnet.ibm.com>
Fri, 19 Jun 2015 22:17:07 +0000 (17:17 -0500)
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 0a1326e4241d3916c953c64166e9b14c1d5819f3..8d0f28fed96055c2dcddfd79eb3dd695467a3e78 100644 (file)
@@ -1,3 +1,8 @@
+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-06-18  Nick Clifton  <nickc@redhat.com>
 
        PR gas/18541
index 3f6de73d1b801d3d4cc4952e153b411f083057e6..18a11bedbbdbcc2f6fb1ecfcd8790c9af79b2961 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 64e8cd7b18d8a9c5fede0248075e3bd2163c6f6b..511dce3d34bdc57cf33ea8564c61afd2302dc158 100644 (file)
@@ -1,3 +1,9 @@
+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-18  Nick Clifton  <nickc@redhat.com>
 
        PR gas/18541
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 0caabd52afab4e1f78cabcb0fde4115f2f61c525..f1b3f1fa264139d0f0f27fb90823d9cb31c3c47b 100644 (file)
@@ -1,3 +1,8 @@
+2015-06-19  Peter Bergner <bergner@vnet.ibm.com>
+
+       * ppc.h (PPC_OPERAND_OPTIONAL_VALUE): New.
+       (ppc_optional_operand_value): New inline function.
+
 2015-06-04  Matthew Wahab  <matthew.wahab@arm.com>
 
        * aarch64.h (AARCH64_V8_1): New.
index 5dc132ea383050b669f037807e8f543394edbea9..52463653250d3fcfaf161051d8b3f2b7e7349bae 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 d76ad3bcd964de633beab140dcc8eb623677e9a4..f764473b1b71084d5981df621237564f8a639811 100644 (file)
@@ -1,3 +1,14 @@
+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-16  Matthew Wahab  <matthew.wahab@arm.com>
 
        * arch64-opc.c (aarch64_sys_regs): Add "id_mmfr4_el1".
index ccea46680e2d6edc1e7cc76b61acf401431eb510..581d342cefb4d7a7a660b1ef4dd4fa726e908d12 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 b3dc9450d9a7b9a89647b273eafd8ef348b6af94..9689a81a0594a7b47175dcc3818bf7117cb882a7 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;
 }