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