From a5721ba270ddf860e0e5a45bba456214e8eac2be Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 29 Sep 2016 15:12:47 +0930 Subject: [PATCH] Disallow 3-operand cmp[l][i] for ppc64 cmp[l][o] get an optional L field only when generating 32-bit code. dcbf, tlbie and tlbiel keep their optional L field, ditto for R field of tbegin. cmprb, tsr., wlcr[all] and mtsle all change to a compulsory L field. L field of dcbf and wclr is 2 bits. PR 20641 include/ * opcode/ppc.h (PPC_OPERAND_OPTIONAL32): Define. opcodes/ * ppc-opc.c (L): Make compulsory. (LOPT): New, optional form of L. (HTM_R): Define as LOPT. (L0, L1): Delete. (L32OPT): New, optional for 32-bit L. (L2OPT): New, 2-bit L for dcbf. (SVC_LEC): Update. (L2): Define. (insert_l0, extract_l0, insert_l1, extract_l2): Delete. (powerpc_opcodes ): Use L32OPT. : Use L2OPT. : Use LOPT. : Use L2. gas/ * config/tc-ppc.c (md_assemble): Handle PPC_OPERAND_OPTIONAL32. * testsuite/gas/ppc/power8.s: Provide tbegin. operand. * testsuite/gas/ppc/power9.d: Update cmprb disassembly. --- gas/ChangeLog | 6 +++ gas/config/tc-ppc.c | 4 +- gas/testsuite/gas/ppc/power8.s | 2 +- gas/testsuite/gas/ppc/power9.d | 4 +- include/ChangeLog | 4 ++ include/opcode/ppc.h | 4 ++ opcodes/ChangeLog | 16 ++++++ opcodes/ppc-opc.c | 96 ++++++++-------------------------- 8 files changed, 59 insertions(+), 77 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index d499099a7ab..e4db0f0d595 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2016-09-29 Alan Modra + + * config/tc-ppc.c (md_assemble): Handle PPC_OPERAND_OPTIONAL32. + * testsuite/gas/ppc/power8.s: Provide tbegin. operand. + * testsuite/gas/ppc/power9.d: Update cmprb disassembly. + 2016-09-26 Trevor Saunders * config/tc-xtensa.c (xg_reverse_shift_count): Pass cnt_arg instead of diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index d2b53169804..5c7b09f02bc 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -2695,7 +2695,8 @@ md_assemble (char *str) const struct powerpc_operand *operand; operand = &powerpc_operands[*opindex_ptr]; - if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) + if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 + && !((operand->flags & PPC_OPERAND_OPTIONAL32) != 0 && ppc_obj64)) { unsigned int opcount; unsigned int num_operands_expected; @@ -2765,6 +2766,7 @@ md_assemble (char *str) /* If this is an optional operand, and we are skipping it, just insert a zero. */ if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 + && !((operand->flags & PPC_OPERAND_OPTIONAL32) != 0 && ppc_obj64) && skip_optional) { long val = ppc_optional_operand_value (operand); diff --git a/gas/testsuite/gas/ppc/power8.s b/gas/testsuite/gas/ppc/power8.s index 728caae3161..857bda2a910 100644 --- a/gas/testsuite/gas/ppc/power8.s +++ b/gas/testsuite/gas/ppc/power8.s @@ -5,7 +5,7 @@ power8: tabortdc. 20,11,10 tabortwci. 17,10,-13 tabortdci. 29,3,-5 - tbegin. + tbegin. 0 tcheck 7 tend. 0 tend. diff --git a/gas/testsuite/gas/ppc/power9.d b/gas/testsuite/gas/ppc/power9.d index 31e45304a14..6f2f53a7253 100644 --- a/gas/testsuite/gas/ppc/power9.d +++ b/gas/testsuite/gas/ppc/power9.d @@ -274,8 +274,8 @@ Disassembly of section \.text: .*: (f3 89 ef 6f|6f ef 89 f3) xvxsigsp vs60,vs61 .*: (7c 06 39 c0|c0 39 06 7c) cmpeqb cr0,r6,r7 .*: (7f 86 39 c0|c0 39 86 7f) cmpeqb cr7,r6,r7 -.*: (7c 08 49 80|80 49 08 7c) cmprb cr0,r8,r9 -.*: (7f 88 49 80|80 49 88 7f) cmprb cr7,r8,r9 +.*: (7c 08 49 80|80 49 08 7c) cmprb cr0,0,r8,r9 +.*: (7f 88 49 80|80 49 88 7f) cmprb cr7,0,r8,r9 .*: (7c 28 49 80|80 49 28 7c) cmprb cr0,1,r8,r9 .*: (7f a8 49 80|80 49 a8 7f) cmprb cr7,1,r8,r9 .*: (7d e0 01 00|00 01 e0 7d) setb r15,cr0 diff --git a/include/ChangeLog b/include/ChangeLog index 01d1c1416c2..652bb212f23 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2016-09-29 Alan Modra + + * opcode/ppc.h (PPC_OPERAND_OPTIONAL32): Define. + 2016-09-26 Claudiu Zissulescu * opcode/arc.h (insn_class_t): Add two new classes. diff --git a/include/opcode/ppc.h b/include/opcode/ppc.h index d9f973ddea8..66d2ceb31db 100644 --- a/include/opcode/ppc.h +++ b/include/opcode/ppc.h @@ -407,6 +407,10 @@ extern const unsigned int num_powerpc_operands; 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) + +/* This flag is only used with PPC_OPERAND_OPTIONAL. The operand is + only optional when generating 32-bit code. */ +#define PPC_OPERAND_OPTIONAL32 (0x800000) /* The POWER and PowerPC assemblers use a few macros. We keep them with the operands table for simplicity. The macro table is an diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 1613154249b..98866efe17b 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,19 @@ +2016-09-29 Alan Modra + + * ppc-opc.c (L): Make compulsory. + (LOPT): New, optional form of L. + (HTM_R): Define as LOPT. + (L0, L1): Delete. + (L32OPT): New, optional for 32-bit L. + (L2OPT): New, 2-bit L for dcbf. + (SVC_LEC): Update. + (L2): Define. + (insert_l0, extract_l0, insert_l1, extract_l2): Delete. + (powerpc_opcodes ): Use L32OPT. + : Use L2OPT. + : Use LOPT. + : Use L2. + 2016-09-26 Vlad Zakharov * Makefile.in: Regenerate. diff --git a/opcodes/ppc-opc.c b/opcodes/ppc-opc.c index 1c6e9704d90..8c590332fd0 100644 --- a/opcodes/ppc-opc.c +++ b/opcodes/ppc-opc.c @@ -62,10 +62,6 @@ static unsigned long insert_dxdn (unsigned long, long, ppc_cpu_t, const char **) static long extract_dxdn (unsigned long, ppc_cpu_t, int *); 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_l0 (unsigned long, long, ppc_cpu_t, const char **); -static long extract_l0 (unsigned long, ppc_cpu_t, int *); -static unsigned long insert_l1 (unsigned long, long, ppc_cpu_t, const char **); -static long extract_l1 (unsigned long, ppc_cpu_t, int *); static unsigned long insert_li20 (unsigned long, long, ppc_cpu_t, const char **); static long extract_li20 (unsigned long, ppc_cpu_t, int *); static unsigned long insert_ls (unsigned long, long, ppc_cpu_t, const char **); @@ -429,20 +425,24 @@ const struct powerpc_operand powerpc_operands[] = /* The L field in a D or X form instruction. */ #define L IMM20 + 1 + { 0x1, 21, NULL, NULL, 0 }, + + /* The optional L field in tlbie and tlbiel instructions. */ +#define LOPT L + 1 /* The R field in a HTM X form instruction. */ -#define HTM_R L +#define HTM_R LOPT { 0x1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, - /* The L field in an X form instruction which must be zero. */ -#define L0 L + 1 - { 0x1, 21, insert_l0, extract_l0, PPC_OPERAND_OPTIONAL }, + /* The optional (for 32-bit) L field in cmp[l][i] instructions. */ +#define L32OPT LOPT + 1 + { 0x1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL32 }, - /* The L field in an X form instruction which must be one. */ -#define L1 L0 + 1 - { 0x1, 21, insert_l1, extract_l1, 0 }, + /* The L field in dcbf instruction. */ +#define L2OPT L32OPT + 1 + { 0x3, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, /* The LEV field in a POWER SVC form instruction. */ -#define SVC_LEV L1 + 1 +#define SVC_LEV L2OPT + 1 { 0x7f, 5, NULL, NULL, 0 }, /* The LEV field in an SC form instruction. */ @@ -688,6 +688,8 @@ const struct powerpc_operand powerpc_operands[] = #define STRM SR + 1 /* The T field in a tlbilx form instruction. */ #define T STRM + /* The L field in wclr instructions. */ +#define L2 STRM { 0x3, 21, NULL, NULL, 0 }, /* The ESYNC field in an X (sync) form instruction. */ @@ -1483,58 +1485,6 @@ extract_fxm (unsigned long insn, return mask; } -/* The L field in an X form instruction which must have the value zero. */ - -static unsigned long -insert_l0 (unsigned long insn, - long value, - ppc_cpu_t dialect ATTRIBUTE_UNUSED, - const char **errmsg) -{ - if (value != 0) - *errmsg = _("invalid operand constant"); - return insn & ~(0x1 << 21); -} - -static long -extract_l0 (unsigned long insn, - ppc_cpu_t dialect ATTRIBUTE_UNUSED, - int *invalid) -{ - long value; - - value = (insn >> 21) & 0x1; - if (value != 0) - *invalid = 1; - return value; -} - -/* The L field in an X form instruction which must have the value one. */ - -static unsigned long -insert_l1 (unsigned long insn, - long value, - ppc_cpu_t dialect ATTRIBUTE_UNUSED, - const char **errmsg) -{ - if (value != 1) - *errmsg = _("invalid operand constant"); - return insn | (0x1 << 21); -} - -static long -extract_l1 (unsigned long insn, - ppc_cpu_t dialect ATTRIBUTE_UNUSED, - int *invalid) -{ - long value; - - value = (insn >> 21) & 0x1; - if (value != 1) - *invalid = 1; - return value; -} - static unsigned long insert_li20 (unsigned long insn, long value, @@ -3890,12 +3840,12 @@ const struct powerpc_opcode powerpc_opcodes[] = { {"cmplwi", OPL(10,0), OPL_MASK, PPCCOM, PPCVLE, {OBF, RA, UISIGNOPT}}, {"cmpldi", OPL(10,1), OPL_MASK, PPC64, PPCVLE, {OBF, RA, UISIGNOPT}}, -{"cmpli", OP(10), OP_MASK, PPC, PPCVLE, {BF, L, RA, UISIGNOPT}}, +{"cmpli", OP(10), OP_MASK, PPC, PPCVLE, {BF, L32OPT, RA, UISIGNOPT}}, {"cmpli", OP(10), OP_MASK, PWRCOM, PPC|PPCVLE, {BF, RA, UISIGNOPT}}, {"cmpwi", OPL(11,0), OPL_MASK, PPCCOM, PPCVLE, {OBF, RA, SI}}, {"cmpdi", OPL(11,1), OPL_MASK, PPC64, PPCVLE, {OBF, RA, SI}}, -{"cmpi", OP(11), OP_MASK, PPC, PPCVLE, {BF, L, RA, SI}}, +{"cmpi", OP(11), OP_MASK, PPC, PPCVLE, {BF, L32OPT, RA, SI}}, {"cmpi", OP(11), OP_MASK, PWRCOM, PPC|PPCVLE, {BF, RA, SI}}, {"addic", OP(12), OP_MASK, PPCCOM, PPCVLE, {RT, RA, SI}}, @@ -4713,7 +4663,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { {"cmpw", XOPL(31,0,0), XCMPL_MASK, PPCCOM, 0, {OBF, RA, RB}}, {"cmpd", XOPL(31,0,1), XCMPL_MASK, PPC64, 0, {OBF, RA, RB}}, -{"cmp", X(31,0), XCMP_MASK, PPC, 0, {BF, L, RA, RB}}, +{"cmp", X(31,0), XCMP_MASK, PPC, 0, {BF, L32OPT, RA, RB}}, {"cmp", X(31,0), XCMPL_MASK, PWRCOM, PPC, {BF, RA, RB}}, {"twlgt", XTO(31,4,TOLGT), XTO_MASK, PPCCOM, 0, {RA, RB}}, @@ -4821,7 +4771,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { {"cmplw", XOPL(31,32,0), XCMPL_MASK, PPCCOM, 0, {OBF, RA, RB}}, {"cmpld", XOPL(31,32,1), XCMPL_MASK, PPC64, 0, {OBF, RA, RB}}, -{"cmpl", X(31,32), XCMP_MASK, PPC, 0, {BF, L, RA, RB}}, +{"cmpl", X(31,32), XCMP_MASK, PPC, 0, {BF, L32OPT, RA, RB}}, {"cmpl", X(31,32), XCMPL_MASK, PWRCOM, PPC, {BF, RA, RB}}, {"lvsr", X(31,38), X_MASK, PPCVEC, 0, {VD, RA0, RB}}, @@ -4907,7 +4857,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { {"ldarx", X(31,84), XEH_MASK, PPC64, 0, {RT, RA0, RB, EH}}, {"dcbfl", XOPL(31,86,1), XRT_MASK, POWER5, PPC476, {RA0, RB}}, -{"dcbf", X(31,86), XLRT_MASK, PPC, 0, {RA0, RB, L}}, +{"dcbf", X(31,86), XLRT_MASK, PPC, 0, {RA0, RB, L2OPT}}, {"lbzx", X(31,87), X_MASK, COM, 0, {RT, RA0, RB}}, @@ -5149,7 +5099,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { {"ehpriv", X(31,270), 0xffffffff, E500MC|PPCA2, 0, {0}}, {"tlbiel", X(31,274), X_MASK|1<<20,POWER9, PPC476, {RB, RSO, RIC, PRS, X_R}}, -{"tlbiel", X(31,274), XRTLRA_MASK, POWER4, POWER9|PPC476, {RB, L}}, +{"tlbiel", X(31,274), XRTLRA_MASK, POWER4, POWER9|PPC476, {RB, LOPT}}, {"mfapidi", X(31,275), X_MASK, BOOKE, E500|TITAN, {RT, RA}}, @@ -5183,7 +5133,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { {"tlbie", X(31,306), X_MASK|1<<20,POWER9, TITAN, {RB, RS, RIC, PRS, X_R}}, {"tlbie", X(31,306), XRA_MASK, POWER7, POWER9|TITAN, {RB, RS}}, -{"tlbie", X(31,306), XRTLRA_MASK, PPC, E500|POWER7|TITAN, {RB, L}}, +{"tlbie", X(31,306), XRTLRA_MASK, PPC, E500|POWER7|TITAN, {RB, LOPT}}, {"tlbi", X(31,306), XRT_MASK, POWER, 0, {RA0, RB}}, {"mfvsrld", X(31,307), XX1RB_MASK, PPCVSX3, 0, {RA, XS6}}, @@ -6234,8 +6184,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { {"stvfrxl", X(31,933), X_MASK, PPCVEC2, 0, {VS, RA0, RB}}, {"wclrone", XOPL2(31,934,2),XRT_MASK, PPCA2, 0, {RA0, RB}}, -{"wclrall", X(31,934), XRARB_MASK, PPCA2, 0, {L}}, -{"wclr", X(31,934), X_MASK, PPCA2, 0, {L, RA0, RB}}, +{"wclrall", X(31,934), XRARB_MASK, PPCA2, 0, {L2}}, +{"wclr", X(31,934), X_MASK, PPCA2, 0, {L2, RA0, RB}}, {"stvrxl", X(31,935), X_MASK, CELL, 0, {VS, RA0, RB}}, -- 2.30.2