2c2fa1
commit 11a0cf2ec0ed6e70ff25e9a50c2223dcd98c1c10
2c2fa1
Author: Peter Bergner <bergner@vnet.ibm.com>
2c2fa1
Date:   Fri Jun 19 17:17:07 2015 -0500
2c2fa1
2c2fa1
    Allow for optional operands with non-zero default values.
2c2fa1
    
2c2fa1
    ISA 2.07 (ie, POWER8) added the rfebb instruction which takes one operand
2c2fa1
    with the value of either a 0 or 1.  It also defines an extended mnemonic
2c2fa1
    with no operands (ie, "rfebb") that is supposed to be equivalent to "rfebb 1".
2c2fa1
    I implemented rfebb's lone operand with PPC_OPERAND_OPTIONAL, but the
2c2fa1
    problem is, optional operands that are ommitted always default to the
2c2fa1
    value 0, which is wrong in this case.  I have added support for allowing
2c2fa1
    non-zero default values by adding an additional flag PPC_OPERAND_OPTIONAL_VALUE
2c2fa1
    that specifies that the default operand value to be used is stored in the
2c2fa1
    SHIFT field of the operand field immediately following this one.
2c2fa1
    
2c2fa1
    This fixes the rfebb issue.  I also fixed the mftb and mfcr instructions
2c2fa1
    so they use the same mechanism.  This allows us to flag invalid uses of
2c2fa1
    mfcr where we explicitly pass in a zero FXM value, like the use in a2.[sd].
2c2fa1
    
2c2fa1
    include/opcode/
2c2fa1
    
2c2fa1
            * ppc.h (PPC_OPERAND_OPTIONAL_VALUE): New.
2c2fa1
            (ppc_optional_operand_value): New inline function.
2c2fa1
    
2c2fa1
    opcodes/
2c2fa1
            * ppc-dis.h (skip_optional_operands): Use ppc_optional_operand_value.
2c2fa1
            * ppc-opc.c (FXM4): Add non-zero optional value.
2c2fa1
            (TBR): Likewise.
2c2fa1
            (SXL): Likewise.
2c2fa1
            (insert_fxm): Handle new default operand value.
2c2fa1
            (extract_fxm): Likewise.
2c2fa1
            (insert_tbr): Likewise.
2c2fa1
            (extract_tbr): Likewise.
2c2fa1
    
2c2fa1
    gas/
2c2fa1
            * config/tc-ppc.c (md_assemble): Use ppc_optional_operand_value.
2c2fa1
            Allow for optional operands without insert functions.
2c2fa1
    
2c2fa1
    gas/testsuite/
2c2fa1
            * gas/ppc/power8.d: Fixup rfebb test results.
2c2fa1
            * gas/ppc/a2.s: Fix invalid mfcr test.
2c2fa1
            * gas/ppc/a2.d: Likewise.
2c2fa1
2c2fa1
### a/include/opcode/ChangeLog
2c2fa1
### b/include/opcode/ChangeLog
2c2fa1
## -1,3 +1,8 @@
2c2fa1
+2015-06-19  Peter Bergner <bergner@vnet.ibm.com>
2c2fa1
+
2c2fa1
+	* ppc.h (PPC_OPERAND_OPTIONAL_VALUE): New.
2c2fa1
+	(ppc_optional_operand_value): New inline function.
2c2fa1
+
2c2fa1
 2015-06-04  Matthew Wahab  <matthew.wahab@arm.com>
2c2fa1
 
2c2fa1
 	* aarch64.h (AARCH64_V8_1): New.
2c2fa1
--- a/include/opcode/ppc.h
2c2fa1
+++ b/include/opcode/ppc.h
2c2fa1
@@ -380,6 +380,11 @@ extern const unsigned int num_powerpc_operands;
2c2fa1
 
2c2fa1
 /* This is a CR FIELD that does not use symbolic names.  */
2c2fa1
 #define PPC_OPERAND_CR_REG (0x200000)
2c2fa1
+
2c2fa1
+/* This flag is only used with PPC_OPERAND_OPTIONAL.  If this operand
2c2fa1
+   is omitted, then the value it should use for the operand is stored
2c2fa1
+   in the SHIFT field of the immediatly following operand field.  */
2c2fa1
+#define PPC_OPERAND_OPTIONAL_VALUE (0x400000)
2c2fa1
 
2c2fa1
 /* The POWER and PowerPC assemblers use a few macros.  We keep them
2c2fa1
    with the operands table for simplicity.  The macro table is an
2c2fa1
@@ -409,4 +414,12 @@ extern const int powerpc_num_macros;
2c2fa1
 
2c2fa1
 extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, ppc_cpu_t *, const char *);
2c2fa1
 
2c2fa1
+static inline long
2c2fa1
+ppc_optional_operand_value (const struct powerpc_operand *operand)
2c2fa1
+{
2c2fa1
+  if ((operand->flags & PPC_OPERAND_OPTIONAL_VALUE) != 0)
2c2fa1
+    return (operand+1)->shift;
2c2fa1
+  return 0;
2c2fa1
+}
2c2fa1
+
2c2fa1
 #endif /* PPC_H */
2c2fa1
### a/opcodes/ChangeLog
2c2fa1
### b/opcodes/ChangeLog
2c2fa1
## -1,3 +1,14 @@
2c2fa1
+2015-06-19  Peter Bergner  <bergner@vnet.ibm.com>
2c2fa1
+
2c2fa1
+        * ppc-dis.h (skip_optional_operands): Use ppc_optional_operand_value.
2c2fa1
+	* ppc-opc.c (FXM4): Add non-zero optional value.
2c2fa1
+	(TBR): Likewise.
2c2fa1
+	(SXL): Likewise.
2c2fa1
+	(insert_fxm): Handle new default operand value.
2c2fa1
+	(extract_fxm): Likewise.
2c2fa1
+	(insert_tbr): Likewise.
2c2fa1
+	(extract_tbr): Likewise.
2c2fa1
+
2c2fa1
 2015-06-16  Matthew Wahab  <matthew.wahab@arm.com>
2c2fa1
 
2c2fa1
 	* arch64-opc.c (aarch64_sys_regs): Add "id_mmfr4_el1".
2c2fa1
--- a/opcodes/ppc-dis.c
2c2fa1
+++ b/opcodes/ppc-dis.c
2c2fa1
@@ -452,7 +452,8 @@ skip_optional_operands (const unsigned char *opindex,
2c2fa1
       operand = &powerpc_operands[*opindex];
2c2fa1
       if ((operand->flags & PPC_OPERAND_NEXT) != 0
2c2fa1
 	  || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
2c2fa1
-	      && operand_value_powerpc (operand, insn, dialect) != 0))
2c2fa1
+	      && operand_value_powerpc (operand, insn, dialect) !=
2c2fa1
+		 ppc_optional_operand_value (operand)))
2c2fa1
 	return 0;
2c2fa1
     }
2c2fa1
 
2c2fa1
--- a/opcodes/ppc-opc.c
2c2fa1
+++ b/opcodes/ppc-opc.c
2c2fa1
@@ -382,10 +382,12 @@ const struct powerpc_operand powerpc_operands[] =
2c2fa1
 
2c2fa1
   /* Power4 version for mfcr.  */
2c2fa1
 #define FXM4 FXM + 1
2c2fa1
-  { 0xff, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL },
2c2fa1
+  { 0xff, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL_VALUE},
2c2fa1
+  /* If the FXM4 operand is ommitted, use the sentinel value -1.  */
2c2fa1
+  { -1, -1, NULL, NULL, 0},
2c2fa1
 
2c2fa1
   /* The IMM20 field in an LI instruction.  */
2c2fa1
-#define IMM20 FXM4 + 1
2c2fa1
+#define IMM20 FXM4 + 2
2c2fa1
   { 0xfffff, PPC_OPSHIFT_INV, insert_li20, extract_li20, PPC_OPERAND_SIGNED},
2c2fa1
 
2c2fa1
   /* The L field in a D or X form instruction.  */
2c2fa1
@@ -642,10 +644,12 @@ const struct powerpc_operand powerpc_operands[] =
2c2fa1
   /* The TBR field in an XFX form instruction.  This is like the SPR
2c2fa1
      field, but it is optional.  */
2c2fa1
 #define TBR SV + 1
2c2fa1
-  { 0x3ff, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL },
2c2fa1
+  { 0x3ff, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL_VALUE},
2c2fa1
+  /* If the TBR operand is ommitted, use the value 268.  */
2c2fa1
+  { -1, 268, NULL, NULL, 0},
2c2fa1
 
2c2fa1
   /* The TO field in a D or X form instruction.  */
2c2fa1
-#define TO TBR + 1
2c2fa1
+#define TO TBR + 2
2c2fa1
 #define DUI TO
2c2fa1
 #define TO_MASK (0x1f << 21)
2c2fa1
   { 0x1f, 21, NULL, NULL, 0 },
2c2fa1
@@ -766,10 +770,12 @@ const struct powerpc_operand powerpc_operands[] =
2c2fa1
 
2c2fa1
   /* The S field in a XL form instruction.  */
2c2fa1
 #define SXL S + 1
2c2fa1
-  { 0x1, 11, NULL, NULL, PPC_OPERAND_OPTIONAL },
2c2fa1
+  { 0x1, 11, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL_VALUE},
2c2fa1
+  /* If the SXL operand is ommitted, use the value 1.  */
2c2fa1
+  { -1, 1, NULL, NULL, 0},
2c2fa1
 
2c2fa1
   /* SH field starting at bit position 16.  */
2c2fa1
-#define SH16 SXL + 1
2c2fa1
+#define SH16 SXL + 2
2c2fa1
   /* The DCM and DGM fields in a Z form instruction.  */
2c2fa1
 #define DCM SH16
2c2fa1
 #define DGM DCM
2c2fa1
@@ -1284,19 +1290,13 @@ insert_fxm (unsigned long insn,
2c2fa1
 	}
2c2fa1
     }
2c2fa1
 
2c2fa1
-  /* If the optional field on mfcr is missing that means we want to use
2c2fa1
-     the old form of the instruction that moves the whole cr.  In that
2c2fa1
-     case we'll have VALUE zero.  There doesn't seem to be a way to
2c2fa1
-     distinguish this from the case where someone writes mfcr %r3,0.  */
2c2fa1
-  else if (value == 0)
2c2fa1
-    ;
2c2fa1
-
2c2fa1
   /* If only one bit of the FXM field is set, we can use the new form
2c2fa1
      of the instruction, which is faster.  Unlike the Power4 branch hint
2c2fa1
      encoding, this is not backward compatible.  Do not generate the
2c2fa1
      new form unless -mpower4 has been given, or -many and the two
2c2fa1
      operand form of mfcr was used.  */
2c2fa1
-  else if ((value & -value) == value
2c2fa1
+  else if (value > 0
2c2fa1
+	   && (value & -value) == value
2c2fa1
 	   && ((dialect & PPC_OPCODE_POWER4) != 0
2c2fa1
 	       || ((dialect & PPC_OPCODE_ANY) != 0
2c2fa1
 		   && (insn & (0x3ff << 1)) == 19 << 1)))
2c2fa1
@@ -1305,7 +1305,10 @@ insert_fxm (unsigned long insn,
2c2fa1
   /* Any other value on mfcr is an error.  */
2c2fa1
   else if ((insn & (0x3ff << 1)) == 19 << 1)
2c2fa1
     {
2c2fa1
-      *errmsg = _("ignoring invalid mfcr mask");
2c2fa1
+      /* A value of -1 means we used the one operand form of
2c2fa1
+	 mfcr which is valid.  */
2c2fa1
+      if (value != -1)
2c2fa1
+        *errmsg = _("ignoring invalid mfcr mask");
2c2fa1
       value = 0;
2c2fa1
     }
2c2fa1
 
2c2fa1
@@ -1332,6 +1335,8 @@ extract_fxm (unsigned long insn,
2c2fa1
     {
2c2fa1
       if (mask != 0)
2c2fa1
 	*invalid = 1;
2c2fa1
+      else
2c2fa1
+	mask = -1;
2c2fa1
     }
2c2fa1
 
2c2fa1
   return mask;
2c2fa1
@@ -1868,12 +1873,7 @@ extract_sprg (unsigned long insn,
2c2fa1
 }
2c2fa1
 
2c2fa1
 /* The TBR field in an XFX instruction.  This is just like SPR, but it
2c2fa1
-   is optional.  When TBR is omitted, it must be inserted as 268 (the
2c2fa1
-   magic number of the TB register).  These functions treat 0
2c2fa1
-   (indicating an omitted optional operand) as 268.  This means that
2c2fa1
-   ``mftb 4,0'' is not handled correctly.  This does not matter very
2c2fa1
-   much, since the architecture manual does not define mftb as
2c2fa1
-   accepting any values other than 268 or 269.  */
2c2fa1
+   is optional.  */
2c2fa1
 
2c2fa1
 static unsigned long
2c2fa1
 insert_tbr (unsigned long insn,
2c2fa1
@@ -1881,8 +1881,6 @@ insert_tbr (unsigned long insn,
2c2fa1
 	    ppc_cpu_t dialect ATTRIBUTE_UNUSED,
2c2fa1
 	    const char **errmsg)
2c2fa1
 {
2c2fa1
-  if (value == 0)
2c2fa1
-    value = 268;
2c2fa1
   if (value != 268 && value != 269)
2c2fa1
     *errmsg = _("invalid tbr number");
2c2fa1
   return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
2c2fa1
@@ -1898,8 +1896,6 @@ extract_tbr (unsigned long insn,
2c2fa1
   ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
2c2fa1
   if (ret != 268 && ret != 269)
2c2fa1
     *invalid = 1;
2c2fa1
-  if (ret == 268)
2c2fa1
-    ret = 0;
2c2fa1
   return ret;
2c2fa1
 }
2c2fa1