This is the mail archive of the binutils@sourceware.org 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]

[PATCH][MIPS] Optionally disable odd-numbered single-precision registers


Hi Richard,

This patch adds support for disabling the use of odd-numbered
single-precision registers for arithmetic options. It aims
to implement the restriction on loongson-3a where these registers
cannot be used for single-precision operations (in FR=0/FP32 mode).
We have also decided to limit the number of single-precision
registers usable by default for generic MIPS architectures so that
generic code can run on the loongson-3a. Targeting a specific
architecture will however allow access to all registers by default.

The corresponding (as yet un-committed) GCC patch is:
http://gcc.gnu.org/ml/gcc-patches/2014-04/msg01975.html

After this patch is applied then pre-existing GCC compilers will
end up with warnings from the assembler when building mips32 or
mips32r2 code as the pre-existing compilers will use 32 single-
precision registers. Is this acceptable? The GCC patch will need
some specs changes to pass through -m[no-]odd-spreg and I guess
it could do a feature test on the assembler to decide whether
to limit the odd registers by default or not.

The -mno-odd-spreg option also forms part of an ABI check for
FPXX as when -mno-odd-spreg is set then all accesses to
odd-numbered single-precision registers become illegal (including
mtc1,mfc1,swc1,lwc1).

The patch applies on top of O32 FPXX:
http://sourceware.org/ml/binutils/2014-05/msg00199.html

I believe this to be the last major patch for binutils in this
current batch of work. Thank-you for all your help in improving
these features.

Regards,
Matthew

gas/

	* config/tc-mips.c (mips_set_options): Add nooddspreg field.
	(file_mips_opts, mips_opts): Set nooddspreg to -1.
	(enum options): Add OPTION_ODD_SPREG and OPTION_NO_ODD_SPREG.
	(mips_check_options): Check the loongson-3a restrictions.
	(file_mips_check_options): Infer nooddspreg from the cpu.
	(mips_oddfpreg_ok): Use nooddspreg.
	(md_parse_option): Handle -modd-spreg options.
	(parse_code_option): Handle oddspreg and nooddspreg.
	* doc/as.texinfo: Document -modd-spreg.
	* doc/c-mips.texi: Likewise.

gas/testsuite/

	* gas/mips/micromips@mips32-sf32-warn.d: New.
	* gas/mips/mips32-sf32-warn.d: Likewise.
	* gas/mips/mips32-sf32-warn.l: Likewise.
	* gas/mips/micromips@mips32-sf32.d: Set -modd-spreg.
	* gas/mips/mips16-intermix.d: Likewise.
	* gas/mips/mips32-sf32.d: Likewise.
	* gas/mips/module-set-mfpxx.s: Set .module oddspreg.
	* gas/mips/mips.exp: Add new test.
---
 gas/config/tc-mips.c                               |   47 ++++++++++++++++++-
 gas/doc/as.texinfo                                 |    7 +++
 gas/doc/c-mips.texi                                |    7 +++
 .../gas/mips/micromips@mips32-sf32-warn.d          |   21 +++++++++
 gas/testsuite/gas/mips/micromips@mips32-sf32.d     |    2 +-
 gas/testsuite/gas/mips/mips.exp                    |    2 +
 gas/testsuite/gas/mips/mips16-intermix.d           |    2 +-
 gas/testsuite/gas/mips/mips32-sf32-warn.d          |   21 +++++++++
 gas/testsuite/gas/mips/mips32-sf32-warn.l          |    8 +++
 gas/testsuite/gas/mips/mips32-sf32.d               |    2 +-
 gas/testsuite/gas/mips/module-set-mfpxx.s          |    1 +
 11 files changed, 114 insertions(+), 6 deletions(-)
 create mode 100644 gas/testsuite/gas/mips/micromips@mips32-sf32-warn.d
 create mode 100644 gas/testsuite/gas/mips/mips32-sf32-warn.d
 create mode 100644 gas/testsuite/gas/mips/mips32-sf32-warn.l

diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index acc772a..aa88946 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -258,6 +258,10 @@ struct mips_set_options
      Changed by .set singlefloat or .set doublefloat, command-line options
      -msingle-float or -mdouble-float.  The default is false.  */
   bfd_boolean single_float;
+
+  /* 1 if single-precision operations on odd-numbered registers are
+     not allowed (even if supported by ISA_HAS_ODD_SINGLE_FPR).  */
+  int nooddspreg;
 };
 
 /* Specifies whether module level options have been checked yet.  */
@@ -276,7 +280,7 @@ static struct mips_set_options file_mips_opts =
   /* noreorder */ 0,  /* at */ ATREG, /* warn_about_macros */ 0,
   /* nomove */ 0, /* nobopt */ 0, /* noautoextend */ 0, /* insn32 */ FALSE,
   /* gp */ -1, /* fp */ -1, /* arch */ CPU_UNKNOWN, /* sym32 */ FALSE,
-  /* soft_float */ FALSE, /* single_float */ FALSE
+  /* soft_float */ FALSE, /* single_float */ FALSE, /* nooddspreg */ -1
 };
 
 /* This is similar to file_mips_opts, but for the current set of options.  */
@@ -287,7 +291,7 @@ static struct mips_set_options mips_opts =
   /* noreorder */ 0,  /* at */ ATREG, /* warn_about_macros */ 0,
   /* nomove */ 0, /* nobopt */ 0, /* noautoextend */ 0, /* insn32 */ FALSE,
   /* gp */ -1, /* fp */ -1, /* arch */ CPU_UNKNOWN, /* sym32 */ FALSE,
-  /* soft_float */ FALSE, /* single_float */ FALSE
+  /* soft_float */ FALSE, /* single_float */ FALSE, /* nooddspreg */ -1
 };
 
 /* Which bits of file_ase were explicitly set or cleared by ASE options.  */
@@ -1436,6 +1440,8 @@ enum options
     OPTION_NO_PDR,
     OPTION_MVXWORKS_PIC,
     OPTION_NAN,
+    OPTION_ODD_SPREG,
+    OPTION_NO_ODD_SPREG,
     OPTION_END_OF_ENUM
   };
 
@@ -1542,6 +1548,8 @@ struct option md_longopts[] =
   {"mhard-float", no_argument, NULL, OPTION_HARD_FLOAT},
   {"msingle-float", no_argument, NULL, OPTION_SINGLE_FLOAT},
   {"mdouble-float", no_argument, NULL, OPTION_DOUBLE_FLOAT},
+  {"modd-spreg", no_argument, NULL, OPTION_ODD_SPREG},
+  {"mno-odd-spreg", no_argument, NULL, OPTION_NO_ODD_SPREG},
 
   /* Strictly speaking this next option is ELF specific,
      but we allow it for other ports as well in order to
@@ -3763,6 +3771,10 @@ mips_check_options (struct mips_set_options *opts, bfd_boolean abi_checks)
       break;
     }
 
+  if (opts->fp != 64 && opts->arch == CPU_LOONGSON_3A && !opts->nooddspreg)
+    as_bad (_("`arch=loongson3a' requires `nooddspreg' when using "
+	      "`fp=32' or `fp=xx'"));
+
   if (opts->micromips == 1 && opts->mips16 == 1)
     as_bad (_("`mips16' cannot be used with `micromips'"));
 }
@@ -3820,6 +3832,22 @@ file_mips_check_options (void)
 
   arch_info = mips_cpu_info_from_arch (file_mips_opts.arch);
 
+  /* Disable operations on odd-numbered floating-point registers by default
+     for generic mips cores and loongson-3a which does not support the
+     operations anyway.  This only applies when targetting 32-bit
+     floating-point registers.  */
+  if (file_mips_opts.nooddspreg < 0)
+    {
+      /* This check is valid as long as all MIPS_CPU_IS_ISA entries for
+         MIPS 32 and above are associated with dummy CPU entries rather
+	 than specific implementations.  */
+      if ((arch_info->flags & MIPS_CPU_IS_ISA)
+	  || file_mips_opts.arch == CPU_LOONGSON_3A)
+	file_mips_opts.nooddspreg = 1;
+      else
+	file_mips_opts.nooddspreg = 0;
+    }
+
   /* End of GCC-shared inference code.  */
 
   /* This flag is set when we have a 64-bit capable CPU but use only
@@ -4470,7 +4498,8 @@ mips_oddfpreg_ok (const struct mips_opcode *insn, int opnum)
 {
   const char *s = insn->name;
   bfd_boolean oddspreg = (ISA_HAS_ODD_SINGLE_FPR (mips_opts.isa)
-			  || mips_opts.arch == CPU_R5900);
+			  || mips_opts.arch == CPU_R5900)
+			 && !mips_opts.nooddspreg;
 
   if (insn->pinfo == INSN_MACRO)
     /* Let a macro pass, we'll catch it later when it is expanded.  */
@@ -14058,6 +14087,14 @@ md_parse_option (int c, char *arg)
       file_mips_opts.fp = 64;
       break;
 
+    case OPTION_ODD_SPREG:
+      file_mips_opts.nooddspreg = 0;
+      break;
+
+    case OPTION_NO_ODD_SPREG:
+      file_mips_opts.nooddspreg = 1;
+      break;
+
     case OPTION_SINGLE_FLOAT:
       file_mips_opts.single_float = 1;
       break;
@@ -15158,6 +15195,10 @@ parse_code_option (char * name)
     mips_opts.single_float = 1;
   else if (strcmp (name, "doublefloat") == 0)
     mips_opts.single_float = 0;
+  else if (strcmp (name, "nooddspreg") == 0)
+    mips_opts.nooddspreg = 1;
+  else if (strcmp (name, "oddspreg") == 0)
+    mips_opts.nooddspreg = 0;
   else if (strcmp (name, "mips16") == 0
 	   || strcmp (name, "MIPS-16") == 0)
     mips_opts.mips16 = 1;
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 04757df..121671c 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -400,6 +400,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
    [@b{-non_shared}] [@b{-xgot} [@b{-mvxworks-pic}]
    [@b{-mabi}=@var{ABI}] [@b{-32}] [@b{-n32}] [@b{-64}] [@b{-mfp32}] [@b{-mgp32}]
    [@b{-mfp64}] [@b{-mgp64}] [@b{-mfpxx}]
+   [@b{-modd-spreg}] [@b{-mno-odd-spreg}]
    [@b{-march}=@var{CPU}] [@b{-mtune}=@var{CPU}] [@b{-mips1}] [@b{-mips2}]
    [@b{-mips3}] [@b{-mips4}] [@b{-mips5}] [@b{-mips32}] [@b{-mips32r2}]
    [@b{-mips32r3}] [@b{-mips32r5}] [@b{-mips64}] [@b{-mips64r2}]
@@ -1335,6 +1336,12 @@ this flag in combination with @samp{-mabi=32} enables an ABI variant
 which will operate correctly with floating-point registers which are
 32 or 64 bits wide.
 
+@item -modd-spreg
+@itemx -mno-odd-spreg
+Enable use of floating-point operations on odd-numbered single-precision
+registers when supported by the ISA.  When targetting generic MIPS
+architectures @samp{-mno-odd-spreg} is set by default.
+
 @item -mips16
 @itemx -no-mips16
 Generate code for the MIPS 16 processor.  This is equivalent to putting
diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi
index 8ed4d51..a789c9a 100644
--- a/gas/doc/c-mips.texi
+++ b/gas/doc/c-mips.texi
@@ -135,6 +135,13 @@ only be used with MIPS II and above.
 The @code{.set fp=xx} directive allows a part of an object to be marked
 as not making assumptions about 32-bit or 64-bita FP registers.  The
 default value is restored by @code{.set fp=default}.
+
+@item -modd-spreg
+@itemx -mno-odd-spreg
+Enable use of floating-point operations on odd-numbered single-precision
+registers when supported by the ISA.  When targetting generic MIPS
+architectures @samp{-mno-odd-spreg} is set by default.
+
 @item -mips16
 @itemx -no-mips16
 Generate code for the MIPS 16 processor.  This is equivalent to putting
diff --git a/gas/testsuite/gas/mips/micromips@mips32-sf32-warn.d b/gas/testsuite/gas/mips/micromips@mips32-sf32-warn.d
new file mode 100644
index 0000000..619699d
--- /dev/null
+++ b/gas/testsuite/gas/mips/micromips@mips32-sf32-warn.d
@@ -0,0 +1,21 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -M reg-names=numeric
+#name: MIPS32 odd single-precision float registers
+#source: mips32-sf32.s
+#stderr: mips32-sf32-warn.l
+#as: -32
+
+# Check MIPS32 instruction assembly (microMIPS).
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 41a1 3f80 	lui	\$1,0x3f80
+[0-9a-f]+ <[^>]*> 5421 283b 	mtc1	\$1,\$f1
+[0-9a-f]+ <[^>]*> 9c7c 0000 	lwc1	\$f3,0\(\$28\)
+[ 	]*[0-9a-f]+: R_MICROMIPS_LITERAL	\.lit4
+[0-9a-f]+ <[^>]*> 5461 2830 	add\.s	\$f5,\$f1,\$f3
+[0-9a-f]+ <[^>]*> 5507 137b 	cvt\.d\.s	\$f8,\$f7
+[0-9a-f]+ <[^>]*> 5507 337b 	cvt\.d\.w	\$f8,\$f7
+[0-9a-f]+ <[^>]*> 54e8 1b7b 	cvt\.s\.d	\$f7,\$f8
+[0-9a-f]+ <[^>]*> 54e8 6b3b 	trunc\.w\.d	\$f7,\$f8
+	\.\.\.
diff --git a/gas/testsuite/gas/mips/micromips@mips32-sf32.d b/gas/testsuite/gas/mips/micromips@mips32-sf32.d
index e44e257..9be6af3 100644
--- a/gas/testsuite/gas/mips/micromips@mips32-sf32.d
+++ b/gas/testsuite/gas/mips/micromips@mips32-sf32.d
@@ -1,7 +1,7 @@
 #objdump: -dr --prefix-addresses --show-raw-insn -M reg-names=numeric
 #name: MIPS32 odd single-precision float registers
 #source: mips32-sf32.s
-#as: -32
+#as: -32 -modd-spreg
 
 # Check MIPS32 instruction assembly (microMIPS).
 
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index bfae18f..3fb05dc 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -742,6 +742,8 @@ if { [istarget mips*-*-vxworks*] } {
     run_dump_test_arches "mips32"	[mips_arch_list_matching mips32]
     run_dump_test_arches "mips32-imm"	[mips_arch_list_matching mips32]
 
+    run_dump_test_arches "mips32-sf32-warn" \
+					[mips_arch_list_matching mips32]
     run_dump_test_arches "mips32-sf32"	[mips_arch_list_matching mips32]
     run_list_test_arches "mips32-sf32" "-32 -msoft-float" \
 					[mips_arch_list_matching mips32]
diff --git a/gas/testsuite/gas/mips/mips16-intermix.d b/gas/testsuite/gas/mips/mips16-intermix.d
index 0242d9c..0904aaf 100644
--- a/gas/testsuite/gas/mips/mips16-intermix.d
+++ b/gas/testsuite/gas/mips/mips16-intermix.d
@@ -1,5 +1,5 @@
 #PROG: nm
-#as: -mips32r2 -32
+#as: -mips32r2 -32 -modd-spreg
 #name: MIPS16 intermix
 
 0+[0-9a-f]+ t __call_stub_fp_m16_static16_d_d
diff --git a/gas/testsuite/gas/mips/mips32-sf32-warn.d b/gas/testsuite/gas/mips/mips32-sf32-warn.d
new file mode 100644
index 0000000..245046f
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips32-sf32-warn.d
@@ -0,0 +1,21 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -M reg-names=numeric
+#name: MIPS32 odd single-precision float registers
+#stderr: mips32-sf32-warn.l
+#source: mips32-sf32.s
+#as: -32
+
+# Check MIPS32 instruction assembly
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> 3c013f80 	lui	\$1,0x3f80
+0+0004 <[^>]*> 44810800 	mtc1	\$1,\$f1
+0+0008 <[^>]*> c7830000 	lwc1	\$f3,0\(\$28\)
+			8:.*LITERAL	\.lit4
+0+000c <[^>]*> 46030940 	add.s	\$f5,\$f1,\$f3
+0+0010 <[^>]*> 46003a21 	cvt.d.s	\$f8,\$f7
+0+0014 <[^>]*> 46803a21 	cvt.d.w	\$f8,\$f7
+0+0018 <[^>]*> 462041e0 	cvt.s.d	\$f7,\$f8
+0+001c <[^>]*> 462041cd 	trunc.w.d	\$f7,\$f8
+	\.\.\.
diff --git a/gas/testsuite/gas/mips/mips32-sf32-warn.l b/gas/testsuite/gas/mips/mips32-sf32-warn.l
new file mode 100644
index 0000000..950bb45
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips32-sf32-warn.l
@@ -0,0 +1,8 @@
+.*: Assembler messages:
+.*:7: Warning: float register should be even, was 5
+.*:7: Warning: float register should be even, was 1
+.*:7: Warning: float register should be even, was 3
+.*:8: Warning: float register should be even, was 7
+.*:9: Warning: float register should be even, was 7
+.*:10: Warning: float register should be even, was 7
+.*:11: Warning: float register should be even, was 7
diff --git a/gas/testsuite/gas/mips/mips32-sf32.d b/gas/testsuite/gas/mips/mips32-sf32.d
index c4057ae..6c277c7 100644
--- a/gas/testsuite/gas/mips/mips32-sf32.d
+++ b/gas/testsuite/gas/mips/mips32-sf32.d
@@ -1,6 +1,6 @@
 #objdump: -dr --prefix-addresses --show-raw-insn -M reg-names=numeric
 #name: MIPS32 odd single-precision float registers
-#as: -32 
+#as: -32 -modd-spreg
 
 # Check MIPS32 instruction assembly
 
diff --git a/gas/testsuite/gas/mips/module-set-mfpxx.s b/gas/testsuite/gas/mips/module-set-mfpxx.s
index 47593e4..313d768 100644
--- a/gas/testsuite/gas/mips/module-set-mfpxx.s
+++ b/gas/testsuite/gas/mips/module-set-mfpxx.s
@@ -2,6 +2,7 @@
 .module fp=xx
 .module doublefloat
 .module hardfloat
+.module oddspreg
 
 add.s $f1,$f1,$f1
 .set push
-- 
1.7.1


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