Blame SOURCES/gdb-rhbz1320945-power9-19of38.patch

01917d
commit 7b9341139a693eac8d316275004b2d752b1f0cb8
01917d
Author: Peter Bergner <bergner@vnet.ibm.com>
01917d
Date:   Mon Jun 22 14:55:24 2015 -0500
01917d
01917d
    PPC sync instruction accepts invalid and incompatible operands
01917d
    
01917d
    ISA 2.07 added a new category called Elemental Memory Barriers that modifies
01917d
    the sync instruction to accept an additional operand ESYNC.  Edmar added
01917d
    support for this insruction varient here:
01917d
    
01917d
        https://sourceware.org/ml/binutils/2012-02/msg00221.html
01917d
    
01917d
    Looking at this closer, I see that the insert_ls() function is misnamed
01917d
    (since it's attached to the ESYNC operand, not the LS operand) but more
01917d
    importantly, it is silently modifying the LS operand value behind the
01917d
    users back when the LS operand is either invalid or is incompatible with
01917d
    the new ESYNC operand.  The ISA 2.07 doc has an Assembler Note that clearly
01917d
    states that assemblers that support the ESYNC operand should report all
01917d
    invalid uses of LS and ESYNC.  This patch changes the assembler to
01917d
    error out on invalid and incompatible operand usage.
01917d
    
01917d
    opcodes/
01917d
            * ppc-opc.c (insert_ls): Test for invalid LS operands.
01917d
            (insert_esync): New function.
01917d
            (LS, WC): Use insert_ls.
01917d
            (ESYNC): Use insert_esync.
01917d
    
01917d
    gas/testsuite/
01917d
            * gas/ppc/e6500.s <sync>: Fix invalid test.
01917d
            * gas/ppc/e6500.d: Likewise.
01917d
01917d
### a/opcodes/ChangeLog
01917d
### b/opcodes/ChangeLog
01917d
## -1,3 +1,10 @@
01917d
+2015-06-22  Peter Bergner  <bergner@vnet.ibm.com>
01917d
+
01917d
+	* ppc-opc.c (insert_ls): Test for invalid LS operands.
01917d
+	(insert_esync): New function.
01917d
+	(LS, WC): Use insert_ls.
01917d
+	(ESYNC): Use insert_esync.
01917d
+
01917d
 2015-06-22  Nick Clifton  <nickc@redhat.com>
01917d
 
01917d
 	* dis-buf.c (buffer_read_memory): Fail is stop_vma is set and the
01917d
--- a/opcodes/ppc-opc.c
01917d
+++ b/opcodes/ppc-opc.c
01917d
@@ -53,6 +53,7 @@ static unsigned long insert_bo (unsigned long, long, ppc_cpu_t, const char **);
01917d
 static long extract_bo (unsigned long, ppc_cpu_t, int *);
01917d
 static unsigned long insert_boe (unsigned long, long, ppc_cpu_t, const char **);
01917d
 static long extract_boe (unsigned long, ppc_cpu_t, int *);
01917d
+static unsigned long insert_esync (unsigned long, long, ppc_cpu_t, const char **);
01917d
 static unsigned long insert_fxm (unsigned long, long, ppc_cpu_t, const char **);
01917d
 static long extract_fxm (unsigned long, ppc_cpu_t, int *);
01917d
 static unsigned long insert_li20 (unsigned long, long, ppc_cpu_t, const char **);
01917d
@@ -417,7 +418,7 @@ const struct powerpc_operand powerpc_operands[] =
01917d
   /* The LS or WC field in an X (sync or wait) form instruction.  */
01917d
 #define LS LIA + 1
01917d
 #define WC LS
01917d
-  { 0x3, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
01917d
+  { 0x3, 21, insert_ls, NULL, PPC_OPERAND_OPTIONAL },
01917d
 
01917d
   /* The ME field in an M form instruction.  */
01917d
 #define ME LS + 1
01917d
@@ -635,7 +636,7 @@ const struct powerpc_operand powerpc_operands[] =
01917d
 
01917d
   /* The ESYNC field in an X (sync) form instruction.  */
01917d
 #define ESYNC STRM + 1
01917d
-  { 0xf, 16, insert_ls, NULL, PPC_OPERAND_OPTIONAL },
01917d
+  { 0xf, 16, insert_esync, NULL, PPC_OPERAND_OPTIONAL },
01917d
 
01917d
   /* The SV field in a POWER SC form instruction.  */
01917d
 #define SV ESYNC + 1
01917d
@@ -1365,17 +1366,40 @@ extract_li20 (unsigned long insn,
01917d
          | (insn & 0x7ff);
01917d
 }
01917d
 
01917d
-/* The LS field in a sync instruction that accepts 2 operands
01917d
-   Values 2 and 3 are reserved,
01917d
-     must be treated as 0 for future compatibility
01917d
-   Values 0 and 1 can be accepted, if field ESYNC is zero
01917d
-   Otherwise L = complement of ESYNC-bit2 (1<<18) */
01917d
+/* The 2-bit L field in a SYNC or WC field in a WAIT instruction.
01917d
+   For SYNC, some L values are reserved:
01917d
+     * Value 3 is reserved on newer server cpus.
01917d
+     * Values 2 and 3 are reserved on all other cpus.  */
01917d
 
01917d
 static unsigned long
01917d
 insert_ls (unsigned long insn,
01917d
 	   long value,
01917d
-	   ppc_cpu_t dialect ATTRIBUTE_UNUSED,
01917d
-	   const char **errmsg ATTRIBUTE_UNUSED)
01917d
+	   ppc_cpu_t dialect,
01917d
+	   const char **errmsg)
01917d
+{
01917d
+  /* For SYNC, some L values are illegal.  */
01917d
+  if (((insn >> 1) & 0x3ff) == 598)
01917d
+    {
01917d
+      long max_lvalue = (dialect & PPC_OPCODE_POWER4) ? 2 : 1;
01917d
+      if (value > max_lvalue)
01917d
+	{
01917d
+	  *errmsg = _("illegal L operand value");
01917d
+	  return insn;
01917d
+	}
01917d
+    }
01917d
+
01917d
+  return insn | ((value & 0x3) << 21);
01917d
+}
01917d
+
01917d
+/* The 4-bit E field in a sync instruction that accepts 2 operands.
01917d
+   If ESYNC is non-zero, then the L field must be either 0 or 1 and
01917d
+   the complement of ESYNC-bit2.  */
01917d
+
01917d
+static unsigned long
01917d
+insert_esync (unsigned long insn,
01917d
+	      long value,
01917d
+	      ppc_cpu_t dialect ATTRIBUTE_UNUSED,
01917d
+	      const char **errmsg)
01917d
 {
01917d
   unsigned long ls;
01917d
 
01917d
@@ -1383,12 +1407,15 @@ insert_ls (unsigned long insn,
01917d
   if (value == 0)
01917d
     {
01917d
       if (ls > 1)
01917d
-	return insn & ~(0x3 << 21);
01917d
+	*errmsg = _("illegal L operand value");
01917d
       return insn;
01917d
     }
01917d
-  if ((value & 0x2) != 0)
01917d
-    return (insn & ~(0x3 << 21)) | ((value & 0xf) << 16);
01917d
-  return (insn & ~(0x3 << 21)) | (0x1 << 21) | ((value & 0xf) << 16);
01917d
+
01917d
+  if ((ls & ~0x1)
01917d
+      || (((value >> 1) & 0x1) ^ ls) == 0)
01917d
+        *errmsg = _("incompatible L operand value");
01917d
+
01917d
+  return insn | ((value & 0xf) << 16);
01917d
 }
01917d
 
01917d
 /* The MB and ME fields in an M form instruction expressed as a single
01917d
@@ -2024,6 +2051,7 @@ extract_dm (unsigned long insn,
01917d
     *invalid = 1;
01917d
   return (value) ? 1 : 0;
01917d
 }
01917d
+
01917d
 /* The VLESIMM field in an I16A form instruction.  This is split.  */
01917d
 
01917d
 static unsigned long