This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PowerPC gas -many


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]