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