From ea192fa3956e5085bb3354af02cd0b3066c055ea Mon Sep 17 00:00:00 2001 From: Peter Bergner Date: Thu, 17 May 2007 00:52:14 +0000 Subject: [PATCH] * ppc-dis.c (operand_value_powerpc, skip_optional_operands): New. (print_insn_powerpc): Use the new operand_value_powerpc and skip_optional_operands functions to omit or print all optional operands as a group. * ppc-opc.c (BFF, W, XFL_L, XWRA_MASK): New. (XFL_MASK): Delete L and W bits from the mask. (mtfsfi, mtfsfi.): Replace use of BF with BFF. Relpace use of XRA_MASK with XWRA_MASK. Use W. (mtfsf, mtfsf.): Use XFL_L and W. --- opcodes/ChangeLog | 12 ++++++++ opcodes/ppc-dis.c | 83 ++++++++++++++++++++++++++++++++++++++++--------------- opcodes/ppc-opc.c | 26 ++++++++++++----- 3 files changed, 91 insertions(+), 30 deletions(-) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 3d999bb..5634096 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,15 @@ +2007-05-16 Peter Bergner + + * ppc-dis.c (operand_value_powerpc, skip_optional_operands): New. + (print_insn_powerpc): Use the new operand_value_powerpc and + skip_optional_operands functions to omit or print all optional + operands as a group. + * ppc-opc.c (BFF, W, XFL_L, XWRA_MASK): New. + (XFL_MASK): Delete L and W bits from the mask. + (mtfsfi, mtfsfi.): Replace use of BF with BFF. Relpace use of XRA_MASK + with XWRA_MASK. Use W. + (mtfsf, mtfsf.): Use XFL_L and W. + 2007-05-14 H.J. Lu PR binutils/4502 diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index 557e5a5..295b04d 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -127,6 +127,56 @@ print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info) return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER); } +/* Extract the operand value from the PowerPC or POWER instruction. */ + +static long +operand_value_powerpc (const struct powerpc_operand *operand, + unsigned long insn, int dialect) +{ + long value; + int invalid; + /* Extract the value from the instruction. */ + if (operand->extract) + value = (*operand->extract) (insn, dialect, &invalid); + else + { + value = (insn >> operand->shift) & operand->bitm; + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + { + /* BITM is always some number of zeros followed by some + number of ones, followed by some numer of zeros. */ + unsigned long top = operand->bitm; + /* top & -top gives the rightmost 1 bit, so this + fills in any trailing zeros. */ + top |= (top & -top) - 1; + top &= ~(top >> 1); + value = (value ^ top) - top; + } + } + + return value; +} + +/* Determine whether the optional operand(s) should be printed. */ + +static int +skip_optional_operands (const unsigned char *opindex, + unsigned long insn, int dialect) +{ + const struct powerpc_operand *operand; + + for (; *opindex != 0; 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)) + return 0; + } + + return 1; +} + /* Print a PowerPC or POWER instruction. */ static int @@ -172,6 +222,7 @@ print_insn_powerpc (bfd_vma memaddr, int invalid; int need_comma; int need_paren; + int skip_optional; table_op = PPC_OP (opcode->opcode); if (op < table_op) @@ -205,6 +256,7 @@ print_insn_powerpc (bfd_vma memaddr, /* Now extract and print the operands. */ need_comma = 0; need_paren = 0; + skip_optional = -1; for (opindex = opcode->operands; *opindex != 0; opindex++) { long value; @@ -217,32 +269,17 @@ print_insn_powerpc (bfd_vma memaddr, if ((operand->flags & PPC_OPERAND_FAKE) != 0) continue; - /* Extract the value from the instruction. */ - if (operand->extract) - value = (*operand->extract) (insn, dialect, &invalid); - else - { - value = (insn >> operand->shift) & operand->bitm; - if ((operand->flags & PPC_OPERAND_SIGNED) != 0) - { - /* BITM is always some number of zeros followed by some - number of ones, followed by some numer of zeros. */ - unsigned long top = operand->bitm; - /* top & -top gives the rightmost 1 bit, so this - fills in any trailing zeros. */ - top |= (top & -top) - 1; - top &= ~(top >> 1); - value = (value ^ top) - top; - } - } + /* If all of the optional operands have the value zero, + then don't print any of them. */ + if (skip_optional < 0 + && (operand->flags & PPC_OPERAND_OPTIONAL) != 0) + skip_optional = skip_optional_operands (opindex, insn, dialect); - /* If the operand is optional, and the value is zero, don't - print anything. */ - if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 - && (operand->flags & PPC_OPERAND_NEXT) == 0 - && value == 0) + if (skip_optional > 0) continue; + value = operand_value_powerpc (operand, insn, dialect); + if (need_comma) { (*info->fprintf_func) (info->stream, ","); diff --git a/opcodes/ppc-opc.c b/opcodes/ppc-opc.c index 5e2fb28..5995f81 100644 --- a/opcodes/ppc-opc.c +++ b/opcodes/ppc-opc.c @@ -154,9 +154,13 @@ const struct powerpc_operand powerpc_operands[] = #define CRFD BF { 0x7, 23, NULL, NULL, PPC_OPERAND_CR }, + /* The BF field in an X or XL form instruction. */ +#define BFF BF + 1 + { 0x7, 23, NULL, NULL, 0 }, + /* An optional BF field. This is used for comparison instructions, in which an omitted BF field is taken as zero. */ -#define OBF BF + 1 +#define OBF BFF + 1 { 0x7, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, /* The BFA field in an X or XL form instruction. */ @@ -515,8 +519,9 @@ const struct powerpc_operand powerpc_operands[] = #define WS EVUIMM_8 + 1 { 0x7, 11, NULL, NULL, 0 }, - /* The L field in an mtmsrd or A form instruction. */ + /* The L field in an mtmsrd or A form instruction or W in an X form. */ #define A_L WS + 1 +#define W A_L { 0x1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL }, #define RMC A_L + 1 @@ -541,6 +546,10 @@ const struct powerpc_operand powerpc_operands[] = /* The EH field in larx instruction. */ #define EH SH16 + 1 { 0x1, 0, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The L field in an mtfsf or XFL form instruction. */ +#define XFL_L EH + 1 + { 0x1, 25, NULL, NULL, PPC_OPERAND_OPTIONAL}, }; const unsigned int num_powerpc_operands = (sizeof (powerpc_operands) @@ -1400,6 +1409,9 @@ extract_tbr (unsigned long insn, /* An X_MASK with the RA field fixed. */ #define XRA_MASK (X_MASK | RA_MASK) +/* An XRA_MASK with the W field clear. */ +#define XWRA_MASK (XRA_MASK & ~((unsigned long) 1 << 16)) + /* An X_MASK with the RB field fixed. */ #define XRB_MASK (X_MASK | RB_MASK) @@ -1454,7 +1466,7 @@ extract_tbr (unsigned long insn, /* An XFL form instruction. */ #define XFL(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1) | (((unsigned long)(rc)) & 1)) -#define XFL_MASK (XFL (0x3f, 0x3ff, 1) | (((unsigned long)1) << 25) | (((unsigned long)1) << 16)) +#define XFL_MASK XFL (0x3f, 0x3ff, 1) /* An X form isel instruction. */ #define XISEL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1)) @@ -4586,8 +4598,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { { "dcmpoq", X(63,130), X_MASK, POWER6, { BF, FRA, FRB } }, -{ "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, -{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, +{ "mtfsfi", XRC(63,134,0), XWRA_MASK|(3<<21)|(1<<11), COM, { BFF, U, W } }, +{ "mtfsfi.", XRC(63,134,1), XWRA_MASK|(3<<21)|(1<<11), COM, { BFF, U, W } }, { "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } }, { "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } }, @@ -4636,8 +4648,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { { "dtstsfq", X(63,674), X_MASK, POWER6, { BF, FRA, FRB } }, -{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } }, -{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } }, +{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB, XFL_L, W } }, +{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB, XFL_L, W } }, { "drdpq", XRC(63,770,0), X_MASK, POWER6, { FRT, FRB } }, { "drdpq.", XRC(63,770,1), X_MASK, POWER6, { FRT, FRB } }, -- 2.7.4