[PATCH] (Attempt to) Fix link compatibility check (was: Re: recent mips-elf linker "architecture ... incompatible" regressions)

Thiemo Seufer ica2_ts@csv.ica.uni-stuttgart.de
Fri Mar 15 06:50:00 GMT 2002


Alan Modra wrote:
> On Thu, Mar 14, 2002 at 01:50:46PM +0100, Thiemo Seufer wrote:
> > 
> > How will this work? It seems to do as it did before, but I don't
> > understand why it worked ever. The bfd_mach_mips* defines are not
> > always upward compatible to all of the lower numbers. E.g.
> > 
> > #define bfd_mach_mips6000 6000
> > 
> > and
> > 
> > #define bfd_mach_mipsisa64 64
> > 
> > are obvious exceptions.
> 
> I don't pretend to understand mips.  Please rewrite the function
> properly.  ;)

The patch below fixes at least some obvious cases. I'm not sure about
the r4xxx compatibility, especially WRT r4010 which is defined as
64bit below but the disassembler calls it a MIPS II ISA. I also don't
know how mips16 should be handled, there are 32bit and 64bit CPU's
which implement the MIPS 16 extension.


Thiemo


	/bfd/ChangeLog
	* cpu-mips.c (compat_tree): How MIPS CPU's are upward
	comapatible.
	(mips_compatible): Check for CPU compatibility instead of
	comparing arbitrary numbers.


diff -BurpN source-orig/bfd/cpu-mips.c source/bfd/cpu-mips.c
--- source-orig/bfd/cpu-mips.c	Fri Mar 15 09:41:59 2002
+++ source/bfd/cpu-mips.c	Fri Mar 15 15:25:37 2002
@@ -23,24 +23,120 @@ Foundation, Inc., 59 Temple Place - Suit
 #include "sysdep.h"
 #include "libbfd.h"
 
+static const bfd_arch_info_type *mips_compatible
+  PARAMS((const bfd_arch_info_type *, const bfd_arch_info_type *));
+
+/* MIPS CPU's aren't upward compatible in one straightforward line.
+   We can't even test for common ISA's because of additional CPU
+   specific insns.  The compatibility tree is given below.  */
+
+static const struct compat_tree
+{
+  unsigned int cpu;
+  unsigned int compatible;
+} compat_tree[] = {
+  {bfd_mach_mips3000, 0},
+     {bfd_mach_mips3900, bfd_mach_mips3000},
+     {bfd_mach_mips6000, bfd_mach_mips3000},
+  /* First 64bit CPU, some CP0 instructions are different.  */
+  {bfd_mach_mips4000, 0},
+     {bfd_mach_mips4010, bfd_mach_mips4000},
+     {bfd_mach_mips4100, bfd_mach_mips4000},
+     {bfd_mach_mips4111, bfd_mach_mips4000},
+     {bfd_mach_mips4300, bfd_mach_mips4000},
+     {bfd_mach_mips4400, bfd_mach_mips4000},
+     {bfd_mach_mips4600, bfd_mach_mips4000},
+     {bfd_mach_mips4650, bfd_mach_mips4000},
+     {bfd_mach_mips5000, bfd_mach_mips4000},
+     {bfd_mach_mips8000, bfd_mach_mips4000},
+	{bfd_mach_mips10000, bfd_mach_mips8000},
+	   {bfd_mach_mips12000, bfd_mach_mips10000},
+	   /* Generic MIPS V ISA.  */
+	      {bfd_mach_mips5, bfd_mach_mips12000},
+		 /* Generic MIPS 64 ISA.  */
+		 {bfd_mach_mipsisa64, bfd_mach_mips5},
+		    /* Sibyte sb1.  */
+		    {bfd_mach_mips_sb1, bfd_mach_mipsisa64},
+  /* Generic MIPS 32 ISA.  */
+  {bfd_mach_mipsisa32, 0},
+  /* Generic CPU with MIPS 16 extension.  */
+  {bfd_mach_mips16, bfd_mach_mips3000},
+  /* Table termination.  */
+  {0, 0}
+};
+
 /* The default routine tests bits_per_word, which is wrong on mips as
    mips word size doesn't correlate with reloc size.  */
 
-const bfd_arch_info_type *
+static const bfd_arch_info_type *
 mips_compatible (a, b)
      const bfd_arch_info_type *a;
      const bfd_arch_info_type *b;
 {
+  int i;
+  int j;
+
   if (a->arch != b->arch)
     return NULL;
 
-  if (a->mach > b->mach)
+  /* Check if a and b have the same mach.  */
+  if (a->mach == b->mach)
     return a;
 
-  if (b->mach > a->mach)
-    return b;
+  /* Check if a is upward compatible to b.  */
+  for (i = 0; compat_tree[i].cpu; i++)
+    {
+      if (a->mach == compat_tree[i].cpu)
+	{
+	  while (compat_tree[i].compatible
+		 && (compat_tree[i].compatible != b->mach))
+	  {
+	    for (j = 0; compat_tree[j].cpu; j++)
+	      {
+		if (compat_tree[i].compatible == compat_tree[j].cpu)
+		  i = j;
+	      }
+	  }
+	  if (compat_tree[i].compatible == b->mach)
+	    return a;
+	  break;
+	}
+      if (! compat_tree[i].cpu)
+	{
+	  (*_bfd_error_handler)
+	    (_("Internal error: %s architecture unknown"), a->printable_name);
+	  abort();
+	}
+    }
+
+  /* Check if b is upward compatible to a.  */
+  for (i = 0; compat_tree[i].cpu; i++)
+    {
+      if (b->mach == compat_tree[i].cpu)
+	{
+	  while (compat_tree[i].compatible
+		 && (compat_tree[i].compatible != a->mach))
+	  {
+	    for (j = 0; compat_tree[j].cpu; j++)
+	      {
+		if (compat_tree[i].compatible == compat_tree[j].cpu)
+		  i = j;
+	      }
+	  }
+	  if (compat_tree[i].compatible == b->mach)
+	    return b;
+	  break;
+	}
+      if (! compat_tree[i].cpu)
+	{
+	  (*_bfd_error_handler)
+	    (_("Internal error: %s architecture unknown"), b->printable_name);
+	  abort();
+	}
+    }
 
-  return a;
+  /* a and b are incompatible.  */
+  return NULL;
 }
 
 #define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT)		\



More information about the Binutils mailing list