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.
+2015-06-19 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/tc-ppc.c (md_assemble): Use ppc_optional_operand_value.
+ Allow for optional operands without insert functions.
+
2015-06-18 Nick Clifton <nickc@redhat.com>
PR gas/18541
2015-06-18 Nick Clifton <nickc@redhat.com>
PR gas/18541
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
&& skip_optional)
{
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
&& skip_optional)
{
+ long val = ppc_optional_operand_value (operand);
- insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
+ insn = (*operand->insert) (insn, val, ppc_cpu, &errmsg);
if (errmsg != (const char *) NULL)
as_bad ("%s", errmsg);
}
if (errmsg != (const char *) NULL)
as_bad ("%s", errmsg);
}
+ else if (operand->shift >= 0)
+ insn |= ((long) val & operand->bitm) << operand->shift;
+ else
+ insn |= ((long) val & operand->bitm) >> -operand->shift;
+
if ((operand->flags & PPC_OPERAND_NEXT) != 0)
next_opindex = *opindex_ptr + 1;
continue;
if ((operand->flags & PPC_OPERAND_NEXT) != 0)
next_opindex = *opindex_ptr + 1;
continue;
+2015-06-19 Peter Bergner <bergner@vnet.ibm.com>
+
+ * gas/ppc/power8.d: Fixup rfebb test results.
+ * gas/ppc/a2.s: Fix invalid mfcr test.
+ * gas/ppc/a2.d: Likewise.
+
2015-06-18 Nick Clifton <nickc@redhat.com>
PR gas/18541
2015-06-18 Nick Clifton <nickc@redhat.com>
PR gas/18541
4fc: (7c 00 04 00|00 04 00 7c) mcrxr cr0
500: (7d 80 04 00|00 04 80 7d) mcrxr cr3
504: (7c 60 00 26|26 00 60 7c) mfcr r3
4fc: (7c 00 04 00|00 04 00 7c) mcrxr cr0
500: (7d 80 04 00|00 04 80 7d) mcrxr cr3
504: (7c 60 00 26|26 00 60 7c) mfcr r3
- 508: (7c 60 00 26|26 00 60 7c) mfcr r3
+ 508: (7c 70 20 26|26 20 70 7c) mfocrf r3,2
50c: (7c 70 10 26|26 10 70 7c) mfocrf r3,1
510: (7c 78 00 26|26 00 78 7c) mfocrf r3,128
514: (7d 4a 3a 87|87 3a 4a 7d) mfdcr\. r10,234
50c: (7c 70 10 26|26 10 70 7c) mfocrf r3,1
510: (7c 78 00 26|26 00 78 7c) mfocrf r3,128
514: (7d 4a 3a 87|87 3a 4a 7d) mfdcr\. r10,234
mfcr 3,0x01
mfcr 3,0x80
mfdcr. 10,234
mfcr 3,0x01
mfcr 3,0x80
mfdcr. 10,234
44: (60 42 00 00|00 00 42 60) ori r2,r2,0
48: (60 00 00 00|00 00 00 60) nop
4c: (60 42 00 00|00 00 42 60) ori r2,r2,0
44: (60 42 00 00|00 00 42 60) ori r2,r2,0
48: (60 00 00 00|00 00 00 60) nop
4c: (60 42 00 00|00 00 42 60) ori r2,r2,0
- 50: (4c 00 01 24|24 01 00 4c) rfebb
- 54: (4c 00 01 24|24 01 00 4c) rfebb
- 58: (4c 00 09 24|24 09 00 4c) rfebb 1
+ 50: (4c 00 01 24|24 01 00 4c) rfebb 0
+ 54: (4c 00 09 24|24 09 00 4c) rfebb
+ 58: (4c 00 09 24|24 09 00 4c) rfebb
5c: (4d 95 04 60|60 04 95 4d) bctar- 12,4\*cr5\+gt
60: (4c 87 04 61|61 04 87 4c) bctarl- 4,4\*cr1\+so
64: (4d ac 04 60|60 04 ac 4d) bctar\+ 12,4\*cr3\+lt
5c: (4d 95 04 60|60 04 95 4d) bctar- 12,4\*cr5\+gt
60: (4c 87 04 61|61 04 87 4c) bctarl- 4,4\*cr1\+so
64: (4d ac 04 60|60 04 ac 4d) bctar\+ 12,4\*cr3\+lt
+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.
2015-06-04 Matthew Wahab <matthew.wahab@arm.com>
* aarch64.h (AARCH64_V8_1): New.
/* This is a CR FIELD that does not use symbolic names. */
#define PPC_OPERAND_CR_REG (0x200000)
/* 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)
\f
/* The POWER and PowerPC assemblers use a few macros. We keep them
with the operands table for simplicity. The macro table is an
\f
/* The POWER and PowerPC assemblers use a few macros. We keep them
with the operands table for simplicity. The macro table is an
extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, ppc_cpu_t *, const char *);
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;
+}
+
+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".
2015-06-16 Matthew Wahab <matthew.wahab@arm.com>
* arch64-opc.c (aarch64_sys_regs): Add "id_mmfr4_el1".
operand = &powerpc_operands[*opindex];
if ((operand->flags & PPC_OPERAND_NEXT) != 0
|| ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
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)))
/* Power4 version for mfcr. */
#define FXM4 FXM + 1
/* 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. */
/* The IMM20 field in an LI instruction. */
{ 0xfffff, PPC_OPSHIFT_INV, insert_li20, extract_li20, PPC_OPERAND_SIGNED},
/* The L field in a D or X form instruction. */
{ 0xfffff, PPC_OPSHIFT_INV, insert_li20, extract_li20, PPC_OPERAND_SIGNED},
/* The L field in a D or X form instruction. */
/* The TBR field in an XFX form instruction. This is like the SPR
field, but it is optional. */
#define TBR SV + 1
/* 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. */
/* The TO field in a D or X form instruction. */
#define DUI TO
#define TO_MASK (0x1f << 21)
{ 0x1f, 21, NULL, NULL, 0 },
#define DUI TO
#define TO_MASK (0x1f << 21)
{ 0x1f, 21, NULL, NULL, 0 },
/* The S field in a XL form instruction. */
#define SXL S + 1
/* 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. */
/* SH field starting at bit position 16. */
/* The DCM and DGM fields in a Z form instruction. */
#define DCM SH16
#define DGM DCM
/* The DCM and DGM fields in a Z form instruction. */
#define DCM SH16
#define DGM DCM
- /* 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. */
/* 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)))
&& ((dialect & PPC_OPCODE_POWER4) != 0
|| ((dialect & PPC_OPCODE_ANY) != 0
&& (insn & (0x3ff << 1)) == 19 << 1)))
/* Any other value on mfcr is an error. */
else if ((insn & (0x3ff << 1)) == 19 << 1)
{
/* 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");
{
if (mask != 0)
*invalid = 1;
{
if (mask != 0)
*invalid = 1;
}
/* The TBR field in an XFX instruction. This is just like SPR, but it
}
/* 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. */
static unsigned long
insert_tbr (unsigned long insn,
static unsigned long
insert_tbr (unsigned long insn,
ppc_cpu_t dialect ATTRIBUTE_UNUSED,
const char **errmsg)
{
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);
if (value != 268 && value != 269)
*errmsg = _("invalid tbr number");
return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
if (ret != 268 && ret != 269)
*invalid = 1;
ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
if (ret != 268 && ret != 269)
*invalid = 1;
- if (ret == 268)
- ret = 0;