|
|
|
|
commit 11a0cf2ec0ed6e70ff25e9a50c2223dcd98c1c10
|
|
|
|
|
Author: Peter Bergner <bergner@vnet.ibm.com>
|
|
|
|
|
Date: Fri Jun 19 17:17:07 2015 -0500
|
|
|
|
|
|
|
|
|
|
Allow for optional operands with non-zero default values.
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
### a/include/opcode/ChangeLog
|
|
|
|
|
### b/include/opcode/ChangeLog
|
|
|
|
|
## -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.
|
|
|
|
|
--- a/include/opcode/ppc.h
|
|
|
|
|
+++ b/include/opcode/ppc.h
|
|
|
|
|
@@ -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)
|
|
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
### a/opcodes/ChangeLog
|
|
|
|
|
### b/opcodes/ChangeLog
|
|
|
|
|
## -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".
|
|
|
|
|
--- a/opcodes/ppc-dis.c
|
|
|
|
|
+++ b/opcodes/ppc-dis.c
|
|
|
|
|
@@ -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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--- a/opcodes/ppc-opc.c
|
|
|
|
|
+++ b/opcodes/ppc-opc.c
|
|
|
|
|
@@ -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;
|
|
|
|
|
}
|
|
|
|
|
|