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.
This commit is contained in:
parent
18a94d75a0
commit
11a0cf2ec0
11 changed files with 75 additions and 32 deletions
|
@ -1,3 +1,8 @@
|
|||
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
|
||||
|
|
|
@ -2752,12 +2752,18 @@ md_assemble (char *str)
|
|||
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
|
||||
&& skip_optional)
|
||||
{
|
||||
long val = ppc_optional_operand_value (operand);
|
||||
if (operand->insert)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
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
|
||||
|
|
|
@ -347,7 +347,7 @@ Disassembly of section \.text:
|
|||
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
|
||||
|
|
|
@ -322,7 +322,7 @@ start:
|
|||
mcrxr 0
|
||||
mcrxr 3
|
||||
mfcr 3
|
||||
mfcr 3,0
|
||||
mfcr 3,0x02
|
||||
mfcr 3,0x01
|
||||
mfcr 3,0x80
|
||||
mfdcr. 10,234
|
||||
|
|
|
@ -27,9 +27,9 @@ Disassembly of section \.text:
|
|||
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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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".
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue