From 9cf7e5687f823a1009d25cb25ff653ee8372e517 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 16 Aug 2018 16:14:12 +0930 Subject: Use operand->extract to provide defaults for optional PowerPC operands Most optional operands to powerpc instructions use a default value of zero, but there are a few exceptions. Those have been handled by PPC_OPERAND_OPTIONAL_VALUE and an entry in the powerpc_operands table for the default value, smuggled in the shift field. This patch changes that to using the operand extract function to provide non-zero defaults. I've also moved the code determining whether optional operands are provided or omitted, to the point the first optional operand is seen, and allowed for the possibility of optional base register operands in a future patch. The patch does change the error you get on invalid assembly like ld 3,4 You'll now see "missing operand" rather than "syntax error; end of line, expected `('". gas/ * config/tc-ppc.c (md_assemble): Delay counting of optional operands until one is encountered. Allow for the possibility of optional base regs, ie. PPC_OPERAND_PARENS. Call ppc_optional_operand_value with extra args. include/ * opcode/ppc.h (struct powerpc_operand): Correct "insert" comment. Mention use of "extract" function to provide default value. (PPC_OPERAND_OPTIONAL_VALUE): Delete. (ppc_optional_operand_value): Rewrite to use extract function. opcodes/ * ppc-dis.c (operand_value_powerpc): Init "invalid". (skip_optional_operands): Count optional operands, and update ppc_optional_operand_value call. * ppc-opc.c (extract_dxdn): Remove ATTRIBUTE_UNUSED from used arg. (extract_vlensi): Likewise. (extract_fxm): Return default value for missing optional operand. (extract_ls, extract_raq, extract_tbr): Likewise. (insert_sxl, extract_sxl): New functions. (insert_esync, extract_esync): Remove Power9 handling and simplify. (powerpc_operands ): Delete PPC_OPERAND_OPTIONAL_VALUE flag and extra entry. (powerpc_operands ): Likewise, and use insert_sxl and extract_sxl. --- opcodes/ppc-dis.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'opcodes/ppc-dis.c') diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index 035767c..adbd124 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -451,7 +451,7 @@ operand_value_powerpc (const struct powerpc_operand *operand, uint64_t insn, ppc_cpu_t dialect) { int64_t value; - int invalid; + int invalid = 0; /* Extract the value from the instruction. */ if (operand->extract) value = (*operand->extract) (insn, dialect, &invalid); @@ -484,15 +484,22 @@ skip_optional_operands (const unsigned char *opindex, uint64_t insn, ppc_cpu_t dialect) { const struct powerpc_operand *operand; + int num_optional; - for (; *opindex != 0; opindex++) + for (num_optional = 0; *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) != - ppc_optional_operand_value (operand))) + if ((operand->flags & PPC_OPERAND_NEXT) != 0) return 0; + if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) + { + /* Negative count is used as a flag to extract function. */ + --num_optional; + if (operand_value_powerpc (operand, insn, dialect) + != ppc_optional_operand_value (operand, insn, dialect, + num_optional)) + return 0; + } } return 1; -- cgit v1.1