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


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]