This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH][MIPS] Optionally disable odd-numbered single-precision registers
- From: Matthew Fortune <Matthew dot Fortune at imgtec dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>
- Cc: "binutils at sourceware dot org" <binutils at sourceware dot org>, "macro at codesourcery dot com" <macro at codesourcery dot com>, "Joseph Myers (joseph at codesourcery dot com)" <joseph at codesourcery dot com>, Rich Fuhler <Rich dot Fuhler at imgtec dot com>, "qiuji at loongson dot cn" <qiuji at loongson dot cn>
- Date: Wed, 21 May 2014 22:20:28 +0000
- Subject: [PATCH][MIPS] Optionally disable odd-numbered single-precision registers
- Authentication-results: sourceware.org; auth=none
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