|
|
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
|