PowerPC gas -many
Kumar Gala
kumar.gala@motorola.com
Tue Sep 2 13:39:00 GMT 2003
I'm also concerned about the use of -many. For example, between Book-E
and classic PPC mftb changes encoding. I'm not sure what expectation
users have today with -many, but it may be more confusion when
conflicts arise that the 'default' behavior is not what they expect
based on their focus. Also, disassembly is a nightmare with -many.
I'm pretty sure between AltiVec / SPE / macc* there are over lapping
opcodes and which one should get precedences?
- kumar
On Tuesday, September 2, 2003, at 02:56 AM, Alan Modra wrote:
> On Tue, Sep 02, 2003 at 08:12:05AM +0100, Nick Clifton wrote:
>> Wouldn't it be simpler to drop the "-many" switch since as you point
>> out the correct choice of instruction coding cannot always be
>> guaranteed. Instead you could have a pseudo op (eg ".machine") which
>> could be used to select the desired architecture at the desired point
>> in the source. ie:
>
> That's actually more work, because the opcode table is currently set
> at md_begin time. Here's what I'm playing with at the moment.
>
> opcodes/ChangeLog
> * ppc-opc.c (insert_fxm): Expand comment.
> (PPC, PPCCOM, PPC32, PPC64, PPCVEC): Remove PPC_OPCODE_ANY.
> (POWER, POWER2, PPCPWR2, POWER32, COM, COM32, M601, PWRCOM): Likewise.
> (POWER4): Remove PPCCOM.
> * ppc-dis.c (powerpc_dialect): Make static. Accept -Many in addition
> to existing options.
> (print_insn_big_powerpc, print_insn_little_powerpc): Formatting.
> (print_insn_powerpc): Remove unnecessary efs/altivec check. Try
> harder
> to disassemble if given -Many.
>
> gas/ChangeLog
> * config/tc-ppc.c (md_parse_option): Add PPC_OPCODE_ANY to existing
> ppc_cpu selection rather than replacing.
> (ppc_set_cpu): Ignore and preserve PPC_OPCODE_ANY in ppc_cpu.
> (md_begin): When PPC_OPCODE_ANY, insert all opcodes in ppc_hash.
>
> Index: opcodes/ppc-dis.c
> ===================================================================
> RCS file: /cvs/src/src/opcodes/ppc-dis.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 ppc-dis.c
> --- opcodes/ppc-dis.c 2 Sep 2003 04:15:29 -0000 1.14
> +++ opcodes/ppc-dis.c 2 Sep 2003 07:51:55 -0000
> @@ -36,7 +36,7 @@ static int print_insn_powerpc (bfd_vma,
> BookE. For convenience, also disassemble instructions supported
> by the AltiVec vector unit. */
>
> -int
> +static int
> powerpc_dialect (struct disassemble_info *info)
> {
> int dialect = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC;
> @@ -45,40 +45,39 @@ powerpc_dialect (struct disassemble_info
> dialect |= PPC_OPCODE_64;
>
> if (info->disassembler_options
> - && (strcmp (info->disassembler_options, "booke") == 0
> - || strcmp (info->disassembler_options, "booke32") == 0
> - || strcmp (info->disassembler_options, "booke64") == 0))
> + && strstr (info->disassembler_options, "booke") != NULL)
> dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
> - else
> - if ((info->mach == bfd_mach_ppc_e500)
> - || (info->disassembler_options
> - && ( strcmp (info->disassembler_options, "e500") == 0
> - || strcmp (info->disassembler_options, "e500x2") == 0)))
> - {
> - dialect |= PPC_OPCODE_BOOKE
> - | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
> - | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
> - | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
> - | PPC_OPCODE_RFMCI;
> - /* efs* and AltiVec conflict. */
> - dialect &= ~PPC_OPCODE_ALTIVEC;
> - }
> - else
> - if (info->disassembler_options
> - && (strcmp (info->disassembler_options, "efs") == 0))
> - {
> - dialect |= PPC_OPCODE_EFS;
> - /* efs* and AltiVec conflict. */
> - dialect &= ~PPC_OPCODE_ALTIVEC;
> - }
> + else if ((info->mach == bfd_mach_ppc_e500)
> + || (info->disassembler_options
> + && strstr (info->disassembler_options, "e500") != NULL))
> + {
> + dialect |= PPC_OPCODE_BOOKE
> + | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
> + | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
> + | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
> + | PPC_OPCODE_RFMCI;
> + /* efs* and AltiVec conflict. */
> + dialect &= ~PPC_OPCODE_ALTIVEC;
> + }
> + else if (info->disassembler_options
> + && strstr (info->disassembler_options, "efs") != NULL)
> + {
> + dialect |= PPC_OPCODE_EFS;
> + /* efs* and AltiVec conflict. */
> + dialect &= ~PPC_OPCODE_ALTIVEC;
> + }
> else
> dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
> | PPC_OPCODE_COMMON);
>
> if (info->disassembler_options
> - && strcmp (info->disassembler_options, "power4") == 0)
> + && strstr (info->disassembler_options, "power4") != NULL)
> dialect |= PPC_OPCODE_POWER4;
>
> + if (info->disassembler_options
> + && strstr (info->disassembler_options, "any") != NULL)
> + dialect |= PPC_OPCODE_ANY;
> +
> if (info->disassembler_options)
> {
> if (strstr (info->disassembler_options, "32") != NULL)
> @@ -95,7 +94,7 @@ powerpc_dialect (struct disassemble_info
> int
> print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info
> *info)
> {
> - return print_insn_powerpc (memaddr, info, 1, powerpc_dialect(info));
> + return print_insn_powerpc (memaddr, info, 1, powerpc_dialect
> (info));
> }
>
> /* Print a little endian PowerPC instruction. */
> @@ -103,7 +102,7 @@ print_insn_big_powerpc (bfd_vma memaddr,
> int
> print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info
> *info)
> {
> - return print_insn_powerpc (memaddr, info, 0, powerpc_dialect(info));
> + return print_insn_powerpc (memaddr, info, 0, powerpc_dialect
> (info));
> }
>
> /* Print a POWER (RS/6000) instruction. */
> @@ -147,6 +146,7 @@ print_insn_powerpc (bfd_vma memaddr,
> /* Find the first match in the opcode table. We could speed this up
> a bit by doing a binary search on the major opcode. */
> opcode_end = powerpc_opcodes + powerpc_num_opcodes;
> + again:
> for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
> {
> unsigned long table_op;
> @@ -166,9 +166,6 @@ print_insn_powerpc (bfd_vma memaddr,
> || (opcode->flags & dialect) == 0)
> continue;
>
> - if ((dialect & PPC_OPCODE_EFS) && (opcode->flags &
> PPC_OPCODE_ALTIVEC))
> - continue;
> -
> /* Make two passes over the operands. First see if any of them
> have extraction functions, and, if they do, make sure the
> instruction is valid. */
> @@ -275,6 +272,12 @@ print_insn_powerpc (bfd_vma memaddr,
>
> /* We have found and printed an instruction; return. */
> return 4;
> + }
> +
> + if ((dialect & PPC_OPCODE_ANY) != 0)
> + {
> + dialect = ~PPC_OPCODE_ANY;
> + goto again;
> }
>
> /* We could not find a match. */
> Index: opcodes/ppc-opc.c
> ===================================================================
> RCS file: /cvs/src/src/opcodes/ppc-opc.c,v
> retrieving revision 1.56
> diff -u -p -r1.56 ppc-opc.c
> --- opcodes/ppc-opc.c 2 Sep 2003 04:15:29 -0000 1.56
> +++ opcodes/ppc-opc.c 2 Sep 2003 07:51:57 -0000
> @@ -1001,7 +1001,8 @@ insert_fxm (unsigned long insn,
> ;
>
> /* If only one bit of the FXM field is set, we can use the new form
> - of the instruction, which is faster. */
> + of the instruction, which is faster. Unlike the Power4 branch
> hint
> + encoding, this is not backward compatible. */
> else if ((dialect & PPC_OPCODE_POWER4) != 0 && (value & -value) ==
> value)
> insn |= 1 << 20;
>
> @@ -1762,27 +1763,27 @@ extract_tbr (unsigned long insn,
> /* Smaller names for the flags so each entry in the opcodes table will
> fit on a single line. */
> #undef PPC
> -#define PPC PPC_OPCODE_PPC | PPC_OPCODE_ANY
> -#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_ANY
> +#define PPC PPC_OPCODE_PPC
> +#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON
> #define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM
> -#define POWER4 PPC_OPCODE_POWER4 | PPCCOM
> -#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC | PPC_OPCODE_ANY
> -#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC | PPC_OPCODE_ANY
> +#define POWER4 PPC_OPCODE_POWER4
> +#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC
> +#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC
> #define PPCONLY PPC_OPCODE_PPC
> #define PPC403 PPC_OPCODE_403
> #define PPC405 PPC403
> #define PPC440 PPC_OPCODE_440
> #define PPC750 PPC
> #define PPC860 PPC
> -#define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_ANY | PPC_OPCODE_PPC
> -#define POWER PPC_OPCODE_POWER | PPC_OPCODE_ANY
> -#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_ANY
> -#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2
> | PPC_OPCODE_ANY
> -#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_ANY | PPC_OPCODE_32
> -#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON
> | PPC_OPCODE_ANY
> -#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON
> | PPC_OPCODE_ANY | PPC_OPCODE_32
> -#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_ANY
> -#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON
> | PPC_OPCODE_ANY
> +#define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_PPC
> +#define POWER PPC_OPCODE_POWER
> +#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2
> +#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2
> +#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_32
> +#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON
> +#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON
> | PPC_OPCODE_32
> +#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601
> +#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON
> #define MFDEC1 PPC_OPCODE_POWER
> #define MFDEC2 PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_BOOKE
> #define BOOKE PPC_OPCODE_BOOKE
> Index: gas/config/tc-ppc.c
> ===================================================================
> RCS file: /cvs/src/src/gas/config/tc-ppc.c,v
> retrieving revision 1.81
> diff -u -p -r1.81 tc-ppc.c
> --- gas/config/tc-ppc.c 19 Aug 2003 15:48:53 -0000 1.81
> +++ gas/config/tc-ppc.c 2 Sep 2003 07:52:00 -0000
> @@ -974,7 +974,7 @@ md_parse_option (c, arg)
> ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
> /* -many means to assemble for any architecture (PWR/PWRX/PPC).
> */
> else if (strcmp (arg, "any") == 0)
> - ppc_cpu = PPC_OPCODE_ANY | PPC_OPCODE_32;
> + ppc_cpu |= PPC_OPCODE_ANY;
>
> else if (strcmp (arg, "regnames") == 0)
> reg_names_p = TRUE;
> @@ -1118,23 +1118,23 @@ ppc_set_cpu ()
> const char *default_os = TARGET_OS;
> const char *default_cpu = TARGET_CPU;
>
> - if (ppc_cpu == 0)
> + if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0)
> {
> if (ppc_obj64)
> - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
> + ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
> else if (strncmp (default_os, "aix", 3) == 0
> && default_os[3] >= '4' && default_os[3] <= '9')
> - ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
> + ppc_cpu |= PPC_OPCODE_COMMON | PPC_OPCODE_32;
> else if (strncmp (default_os, "aix3", 4) == 0)
> - ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
> + ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
> else if (strcmp (default_cpu, "rs6000") == 0)
> - ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
> + ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
> else if (strncmp (default_cpu, "powerpc", 7) == 0)
> {
> if (default_cpu[7] == '6' && default_cpu[8] == '4')
> - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
> + ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
> else
> - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
> + ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
> }
> else
> as_fatal (_("Unknown default cpu = %s, os = %s"),
> @@ -1264,6 +1264,10 @@ md_begin ()
> }
> }
> }
> +
> + if ((ppc_cpu & PPC_OPCODE_ANY) != 0)
> + for (op = powerpc_opcodes; op < op_end; op++)
> + hash_insert (ppc_hash, op->name, (PTR) op);
>
> /* Insert the macros into a hash table. */
> ppc_macro_hash = hash_new ();
>
>
> --
> Alan Modra
> IBM OzLabs - Linux Technology Centre
More information about the Binutils
mailing list