[PATCH v2] MIPS: the default output fellows triple and with-arch

YunQiang Su yunqiang.su@cipunited.com
Mon Apr 3 11:06:35 GMT 2023


PR 25494.

1. as fellows the isa level in triple of target
   and the --with-arch buildtime option:
   > as -march=from-abi xx.s
   > as xx.s
2. ld fellows the isa level in triple of target
   > ld -r -b binary xx.dat -o xx.o
---
 bfd/Makefile.in                               |  1 +
 bfd/config.bfd                                | 48 ++++++++++++-
 bfd/configure                                 |  5 ++
 bfd/configure.ac                              |  4 ++
 bfd/elfxx-mips.c                              | 61 +++++++++++++++-
 .../binutils-all/mips/mips-note-2-n32.d       |  1 +
 gas/config/tc-mips.c                          | 70 +++++++++++++++++--
 gas/configure                                 | 20 +++++-
 gas/configure.ac                              | 18 ++++-
 gold/configure.tgt                            | 14 ++++
 ld/configure.tgt                              | 12 +++-
 11 files changed, 241 insertions(+), 13 deletions(-)

diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index 82aa96f30e5..7b7b262d64e 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -332,6 +332,7 @@ CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DEBUGDIR = @DEBUGDIR@
+DEFAULT_ARCH = @DEFAULT_ARCH@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DSYMUTIL = @DSYMUTIL@
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 7af481048db..f5f3b08e50b 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -227,6 +227,40 @@ z8k*)		 targ_archs=bfd_z8k_arch ;;
 *)		 targ_archs=bfd_${targ_cpu}_arch ;;
 esac
 
+case "${targ}" in
+  mipsisa64r6*)
+    DEFAULT_ARCH=mips64r6
+    ;;
+  mipsisa64r5*)
+    DEFAULT_ARCH=mips64r5
+    ;;
+  mipsisa64r3*)
+    DEFAULT_ARCH=mips64r3
+    ;;
+  mipsisa64r2*)
+    DEFAULT_ARCH=mips64r2
+    ;;
+  mipsisa64*)
+    DEFAULT_ARCH=mips64
+    ;;
+  mipsisa32r6*)
+    DEFAULT_ARCH=mips32r6
+    ;;
+  mipsisa32r5*)
+    DEFAULT_ARCH=mips32r5
+    ;;
+  mipsisa32r3*)
+    DEFAULT_ARCH=mips32r3
+    ;;
+  mipsisa32r2*)
+    DEFAULT_ARCH=mips32r2
+    ;;
+  mipsisa32*)
+    DEFAULT_ARCH=mips32
+    ;;
+  *)
+    ;;
+esac
 
 # WHEN ADDING ENTRIES TO THIS MATRIX:
 #  Make sure that the left side always has two dashes.  Otherwise you
@@ -941,11 +975,21 @@ case "${targ}" in
     targ_defvec=mips_elf32_be_vec
     targ_selvecs="mips_elf32_le_vec mips_elf64_be_vec mips_elf64_le_vec mips_ecoff_be_vec mips_ecoff_le_vec"
     ;;
-  mips64*el-*-linux*)
+  mips*64*el-*-linux*-gnuabi64)
+    targ_defvec=mips_elf64_trad_le_vec
+    targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_be_vec"
+    want64=true
+    ;;
+  mips*64*-*-linux*-gnuabi64)
+    targ_defvec=mips_elf64_trad_be_vec
+    targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_le_vec"
+    want64=true
+    ;;
+  mips*64*el-*-linux*)
     targ_defvec=mips_elf32_ntrad_le_vec
     targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_trad_le_vec mips_elf32_trad_be_vec mips_elf64_trad_le_vec mips_elf64_trad_be_vec"
     ;;
-  mips64*-*-linux*)
+  mips*64*-*-linux*)
     targ_defvec=mips_elf32_ntrad_be_vec
     targ_selvecs="mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_be_vec mips_elf64_trad_le_vec"
     ;;
diff --git a/bfd/configure b/bfd/configure
index 41d280ef461..3fc9aa6fdc2 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -695,6 +695,7 @@ WARN_CFLAGS
 REPORT_BUGS_TEXI
 REPORT_BUGS_TO
 PKGVERSION
+DEFAULT_ARCH
 DEBUGDIR
 ENABLE_BFD_64_BIT_FALSE
 ENABLE_BFD_64_BIT_TRUE
@@ -13775,6 +13776,10 @@ do
     fi
 done
 
+if test -n "$DEFAULT_ARCH"; then
+  TDEFINES="$TDEFINES -DDEFAULT_ARCH=\\\"${DEFAULT_ARCH}\\\""
+fi
+
 
 # This processing still needs to be done if we're to decide properly whether
 # 64-bit support needs to be compiled in.  Currently, it will be included if
diff --git a/bfd/configure.ac b/bfd/configure.ac
index f044616f4d9..b432d7cf10f 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -341,6 +341,10 @@ do
 	TDEFINES="$TDEFINES $targ_cflags"
     fi
 done
+
+if test -n "$DEFAULT_ARCH"; then
+  TDEFINES="$TDEFINES -DDEFAULT_ARCH=\\\"${DEFAULT_ARCH}\\\""
+fi
 AC_SUBST(TDEFINES)
 
 # This processing still needs to be done if we're to decide properly whether
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index d34a755807b..61f00981bfc 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -47,6 +47,15 @@
 
 #include "hashtab.h"
 
+/* A table describing all ISA and its 32bit and 64bit version for best matching */
+struct mips_eflags_32_64
+{
+  const char *name;
+  flagword e_mips_arch;
+  flagword e_mips_arch32;
+  flagword e_mips_arch64;
+};
+
 /* Types of TLS GOT entry.  */
 enum mips_got_tls_type {
   GOT_TLS_NONE,
@@ -1306,6 +1315,28 @@ bfd_get_micromips_32 (const bfd *abfd, const bfd_byte *ptr)
 #define TP_OFFSET 0x7000
 #define DTP_OFFSET 0x8000
 
+/* A table describing all ISA and its 32bit and 64bit version for best matching */
+__attribute__ ((unused))
+static const struct mips_eflags_32_64 mips_eflags_32_64_table[] =
+{
+  { "mips1", E_MIPS_ARCH_1, E_MIPS_ARCH_1, E_MIPS_ARCH_3},
+  { "mips2", E_MIPS_ARCH_2, E_MIPS_ARCH_2, E_MIPS_ARCH_3},
+  { "mips3", E_MIPS_ARCH_3, E_MIPS_ARCH_2, E_MIPS_ARCH_3},
+  { "mips4", E_MIPS_ARCH_3, E_MIPS_ARCH_2, E_MIPS_ARCH_4},
+  { "mips5", E_MIPS_ARCH_5, E_MIPS_ARCH_2, E_MIPS_ARCH_5},
+  { "mips32", E_MIPS_ARCH_32, E_MIPS_ARCH_32, E_MIPS_ARCH_64},
+  { "mips32r2", E_MIPS_ARCH_32R2, E_MIPS_ARCH_32R2, E_MIPS_ARCH_64R2},
+  { "mips32r3", E_MIPS_ARCH_32R2, E_MIPS_ARCH_32R2, E_MIPS_ARCH_64R2},
+  { "mips32r5", E_MIPS_ARCH_32R2, E_MIPS_ARCH_32R2, E_MIPS_ARCH_64R2},
+  { "mips32r6", E_MIPS_ARCH_32R6, E_MIPS_ARCH_32R6, E_MIPS_ARCH_64R6},
+  { "mips64", E_MIPS_ARCH_64, E_MIPS_ARCH_32, E_MIPS_ARCH_64},
+  { "mips64r2", E_MIPS_ARCH_64R2, E_MIPS_ARCH_32R2, E_MIPS_ARCH_64R2},
+  { "mips64r3", E_MIPS_ARCH_64R2, E_MIPS_ARCH_32R2, E_MIPS_ARCH_64R2},
+  { "mips64r5", E_MIPS_ARCH_64R2, E_MIPS_ARCH_32R2, E_MIPS_ARCH_64R2},
+  { "mips64r6", E_MIPS_ARCH_64R6, E_MIPS_ARCH_32R6, E_MIPS_ARCH_64R6},
+  { NULL, 0, 0, 0 }
+};
+
 static bfd_vma
 dtprel_base (struct bfd_link_info *info)
 {
@@ -12316,6 +12347,30 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
 }
 
 
+/* Get the E_MIPA_ARCH_?? value for the DEFAULT_ARCH
+   The value of bits can be 32/64 or 0 (guess from DEFAULT_ARCH)
+   */
+static flagword mips_get_default_arch_eflags(int bits)
+{
+#ifdef DEFAULT_ARCH
+  int i;
+
+  for (i = 0; mips_eflags_32_64_table[i].name; i++)
+    if (strcasecmp (mips_eflags_32_64_table[i].name, DEFAULT_ARCH) != 0)
+      continue;
+    else if (bits == 32)
+      return mips_eflags_32_64_table[i].e_mips_arch32;
+    else if (bits == 64)
+      return mips_eflags_32_64_table[i].e_mips_arch64;
+    else if (bits == 0)
+      return mips_eflags_32_64_table[i].e_mips_arch;
+#endif
+
+  if (bits == 64)
+    return E_MIPS_ARCH_3;
+  return E_MIPS_ARCH_1;
+}
+
 /* Set ABFD's EF_MIPS_ARCH and EF_MIPS_MACH flags.  */
 
 static void
@@ -12327,9 +12382,11 @@ mips_set_isa_flags (bfd *abfd)
     {
     default:
       if (ABI_N32_P (abfd) || ABI_64_P (abfd))
-        val = E_MIPS_ARCH_3;
+	 val = mips_get_default_arch_eflags(64);
+      else if (ABI_O32_P (abfd))
+	 val = mips_get_default_arch_eflags(32);
       else
-        val = E_MIPS_ARCH_1;
+	 val = mips_get_default_arch_eflags(0);
       break;
 
     case bfd_mach_mips3000:
diff --git a/binutils/testsuite/binutils-all/mips/mips-note-2-n32.d b/binutils/testsuite/binutils-all/mips/mips-note-2-n32.d
index c2a581858ed..5e24e7a115e 100644
--- a/binutils/testsuite/binutils-all/mips/mips-note-2-n32.d
+++ b/binutils/testsuite/binutils-all/mips/mips-note-2-n32.d
@@ -1,4 +1,5 @@
 #PROG: objcopy
+#as: -n32
 #readelf: --notes --wide
 #objcopy: --merge-notes
 #name: MIPS merge notes section (n32)
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index e911aaa904a..c906471eb92 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -1422,6 +1422,15 @@ static int relaxed_micromips_16bit_branch_length (fragS *, asection *, int);
 static int relaxed_micromips_32bit_branch_length (fragS *, asection *, int);
 static void file_mips_check_options (void);
 
+/* A table describing all ISA and its 32bit and 64bit version for best matching */
+
+struct mips_isa_32_64
+{
+  int isa;
+  int isa_32;
+  int isa_64;
+};
+
 /* Table and functions used to map between CPU/ISA names, and
    ISA levels, and CPU numbers.  */
 
@@ -1439,6 +1448,7 @@ struct mips_cpu_info
 static const struct mips_cpu_info *mips_parse_cpu (const char *, const char *);
 static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
 static const struct mips_cpu_info *mips_cpu_info_from_arch (int);
+static int mips_cpu_isa_32_64(int isa, int bits);
 
 /* Command-line options.  */
 const char *md_shortopts = "O::g::G:";
@@ -19979,6 +19989,28 @@ s_mips_mask (int reg_type)
     }
 }
 
+
+/* A table describing all ISA and its 32bit and 64bit version for best matching */
+static const struct mips_isa_32_64 mips_isa_32_64_table[] =
+{
+  { ISA_MIPS1, ISA_MIPS1, ISA_MIPS3 },
+  { ISA_MIPS2, ISA_MIPS2, ISA_MIPS3 },
+  { ISA_MIPS3, ISA_MIPS2, ISA_MIPS3 },
+  { ISA_MIPS4, ISA_MIPS2, ISA_MIPS4 },
+  { ISA_MIPS5, ISA_MIPS2, ISA_MIPS5 },
+  { ISA_MIPS32, ISA_MIPS32, ISA_MIPS64 },
+  { ISA_MIPS32R2, ISA_MIPS32R2, ISA_MIPS64R2 },
+  { ISA_MIPS32R3, ISA_MIPS32R3, ISA_MIPS64R3 },
+  { ISA_MIPS32R5, ISA_MIPS32R5, ISA_MIPS64R5 },
+  { ISA_MIPS32R6, ISA_MIPS32R6, ISA_MIPS64R6 },
+  { ISA_MIPS64, ISA_MIPS32, ISA_MIPS64 },
+  { ISA_MIPS64R2, ISA_MIPS32R2, ISA_MIPS64R2 },
+  { ISA_MIPS64R3, ISA_MIPS32R3, ISA_MIPS64R3 },
+  { ISA_MIPS64R5, ISA_MIPS32R5, ISA_MIPS64R5 },
+  { ISA_MIPS64R6, ISA_MIPS32R6, ISA_MIPS64R6 },
+  { 0, 0, 0 }
+};
+
 /* A table describing all the processors gas knows about.  Names are
    matched in the order listed.
 
@@ -20223,6 +20255,9 @@ static const struct mips_cpu_info *
 mips_parse_cpu (const char *option, const char *cpu_string)
 {
   const struct mips_cpu_info *p;
+  const struct mips_cpu_info *default_cpu;
+  int default_isa32 = ISA_MIPS1;
+  int default_isa64 = ISA_MIPS3;
 
   /* 'from-abi' selects the most compatible architecture for the given
      ABI: MIPS I for 32-bit ABIs and MIPS III for 64-bit ABIs.  For the
@@ -20236,19 +20271,26 @@ mips_parse_cpu (const char *option, const char *cpu_string)
      'mips64', just as we did in the days before 'from-abi'.  */
   if (strcasecmp (cpu_string, "from-abi") == 0)
     {
+	for (default_cpu = mips_cpu_info_table; default_cpu->name != 0; default_cpu++)
+	  if (mips_matching_cpu_name_p (default_cpu->name, MIPS_CPU_STRING_DEFAULT))
+	    {
+	      default_isa32 = mips_cpu_isa_32_64 (default_cpu->isa, 32);
+	      default_isa64 = mips_cpu_isa_32_64 (default_cpu->isa, 64);
+	      break;
+	    }
       if (ABI_NEEDS_32BIT_REGS (mips_abi))
-	return mips_cpu_info_from_isa (ISA_MIPS1);
+	return mips_cpu_info_from_isa (default_isa32);
 
       if (ABI_NEEDS_64BIT_REGS (mips_abi))
-	return mips_cpu_info_from_isa (ISA_MIPS3);
+	return mips_cpu_info_from_isa (default_isa64);
 
       if (file_mips_opts.gp >= 0)
 	return mips_cpu_info_from_isa (file_mips_opts.gp == 32
-				       ? ISA_MIPS1 : ISA_MIPS3);
+				       ? default_isa32 : default_isa64);
 
       return mips_cpu_info_from_isa (MIPS_DEFAULT_64BIT
-				     ? ISA_MIPS3
-				     : ISA_MIPS1);
+				     ? default_isa64
+				     : default_isa32);
     }
 
   /* 'default' has traditionally been a no-op.  Probably not very useful.  */
@@ -20263,6 +20305,24 @@ mips_parse_cpu (const char *option, const char *cpu_string)
   return 0;
 }
 
+/* Return the best matching 32bit/64bit ISA of a ISA, according the table
+   mips_isa_32_64_table */
+static int
+mips_cpu_isa_32_64(int isa, int bits)
+{
+  int i;
+
+  for (i = 0; mips_isa_32_64_table[i].isa != 0; i++)
+    if (isa != mips_isa_32_64_table[i].isa)
+      continue;
+    else if (bits == 32)
+      return mips_isa_32_64_table[i].isa_32;
+    else if (bits == 64)
+      return mips_isa_32_64_table[i].isa_64;
+
+  return 0;
+}
+
 /* Return the canonical processor information for ISA (a member of the
    ISA_MIPS* enumeration).  */
 
diff --git a/gas/configure b/gas/configure
index b56836998ef..11b0a56bbd4 100755
--- a/gas/configure
+++ b/gas/configure
@@ -12201,6 +12201,21 @@ _ACEOF
 	    as_fn_error $? "$target_cpu isn't a supported MIPS CPU name" "$LINENO" 5
 	    ;;
 	esac
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --with-arch" >&5
+$as_echo_n "checking for default configuration of --with-arch... " >&6; }
+	if test "x${with_arch}" != x; then
+	  case ${with_arch} in
+	    mips1 | mips2 | mips32 | mips32r2 | mips32r3 | mips32r5 | mips32r6 | \
+	    mips3 | mips4 | mips5 | mips64 | mips64r2 | mips64r3 | mips64r5 | mips64r6)
+	      mips_cpu=${with_arch}
+	      ;;
+	    *)
+	      as_fn_error $? "This kind of arch name does *NOT* exist!" "$LINENO" 5
+	      ;;
+	  esac
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_arch" >&5
+$as_echo "$with_arch" >&6; }
 	# See whether it's appropriate to set E_MIPS_ABI_O32 for o32
 	# binaries.  It's a GNU extension that some OSes don't understand.
 	case ${target} in
@@ -12223,7 +12238,10 @@ _ACEOF
 	esac
 	# Decide which ABI to target by default.
 	case ${target} in
-	  mips64*-linux* | mips-sgi-irix6* | mips64*-freebsd* \
+	  mips*64*-linux-gnuabi64)
+	    mips_default_abi=N64_ABI
+	    ;;
+	  mips*64*-linux* | mips-sgi-irix6* | mips64*-freebsd* \
 	  | mips64*-kfreebsd*-gnu | mips64*-ps2-elf*)
 	    mips_default_abi=N32_ABI
 	    ;;
diff --git a/gas/configure.ac b/gas/configure.ac
index 6a68fd7c4e6..a126a3fda5d 100644
--- a/gas/configure.ac
+++ b/gas/configure.ac
@@ -370,6 +370,19 @@ changequote([,])dnl
 	    AC_MSG_ERROR($target_cpu isn't a supported MIPS CPU name)
 	    ;;
 	esac
+	AC_MSG_CHECKING(for default configuration of --with-arch)
+	if test "x${with_arch}" != x; then
+	  case ${with_arch} in
+	    mips1 | mips2 | mips32 | mips32r2 | mips32r3 | mips32r5 | mips32r6 | \
+	    mips3 | mips4 | mips5 | mips64 | mips64r2 | mips64r3 | mips64r5 | mips64r6)
+	      mips_cpu=${with_arch}
+	      ;;
+	    *)
+	      AC_MSG_ERROR(This kind of arch name does *NOT* exist!)
+	      ;;
+	  esac
+	fi
+	AC_MSG_RESULT($with_arch)
 	# See whether it's appropriate to set E_MIPS_ABI_O32 for o32
 	# binaries.  It's a GNU extension that some OSes don't understand.
 	case ${target} in
@@ -392,7 +405,10 @@ changequote([,])dnl
 	esac
 	# Decide which ABI to target by default.
 	case ${target} in
-	  mips64*-linux* | mips-sgi-irix6* | mips64*-freebsd* \
+	  mips*64*-linux-gnuabi64)
+	    mips_default_abi=N64_ABI
+	    ;;
+	  mips*64*-linux* | mips-sgi-irix6* | mips64*-freebsd* \
 	  | mips64*-kfreebsd*-gnu | mips64*-ps2-elf*)
 	    mips_default_abi=N32_ABI
 	    ;;
diff --git a/gold/configure.tgt b/gold/configure.tgt
index 4b54e08d27f..ef47ce079f1 100644
--- a/gold/configure.tgt
+++ b/gold/configure.tgt
@@ -153,6 +153,13 @@ aarch64*-*)
  targ_big_endian=false
  targ_extra_big_endian=true
  ;;
+mips*64*el*-*-*|mips*64*le*-*-*)
+ targ_obj=mips
+ targ_machine=EM_MIPS_RS3_LE
+ targ_size=64
+ targ_big_endian=false
+ targ_extra_big_endian=true
+ ;;
 mips*el*-*-*|mips*le*-*-*)
  targ_obj=mips
  targ_machine=EM_MIPS_RS3_LE
@@ -160,6 +167,13 @@ mips*el*-*-*|mips*le*-*-*)
  targ_big_endian=false
  targ_extra_big_endian=true
  ;;
+mips*64*-*-*)
+ targ_obj=mips
+ targ_machine=EM_MIPS
+ targ_size=64
+ targ_big_endian=true
+ targ_extra_big_endian=false
+ ;;
 mips*-*-*)
  targ_obj=mips
  targ_machine=EM_MIPS
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 34c9d67c365..4a71f679e29 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -580,11 +580,19 @@ mips*-*-vxworks*)	targ_emul=elf32ebmipvxworks
 			;;
 mips*-*-windiss)	targ_emul=elf32mipswindiss
 			;;
-mips64*el-*-linux-*)	targ_emul=elf32ltsmipn32
+mips*64*el-*-linux-gnuabi64)	targ_emul=elf64ltsmip
+			targ_extra_emuls="elf32btsmipn32 elf32ltsmipn32 elf32ltsmip elf32btsmip elf64btsmip"
+			targ_extra_libpath=$targ_extra_emuls
+			;;
+mips*64*el-*-linux-*)	targ_emul=elf32ltsmipn32
 			targ_extra_emuls="elf32btsmipn32 elf32ltsmip elf32btsmip elf64ltsmip elf64btsmip"
 			targ_extra_libpath=$targ_extra_emuls
 			;;
-mips64*-*-linux-*)	targ_emul=elf32btsmipn32
+mips*64*-*-linux-gnuabi64)	targ_emul=elf64btsmip
+			targ_extra_emuls="elf32btsmipn32 elf32ltsmipn32 elf32btsmip elf32ltsmip elf64ltsmip"
+			targ_extra_libpath=$targ_extra_emuls
+			;;
+mips*64*-*-linux-*)	targ_emul=elf32btsmipn32
 			targ_extra_emuls="elf32ltsmipn32 elf32btsmip elf32ltsmip elf64btsmip elf64ltsmip"
 			targ_extra_libpath=$targ_extra_emuls
 			;;
-- 
2.30.2



More information about the Binutils mailing list