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]

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


Richard Sandiford <rdsandiford@googlemail.com> writes:
> Matthew Fortune <Matthew.Fortune@imgtec.com> writes:
> > 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?
> 
> Hmm, it sounds likely to surprise people.  Maybe this is one of
> the few cases where GCC and GAS should have different defaults.
> In the GCC case it's controlling whether the code uses odd
> registers, so -mno-oddspreg is the safe choice.  But in the
> GAS code it controls a warning, so -moddspreg is the safe choice.

I agree it will surprise people. Though I would like to keep the
defaults for GCC and GAS the same, see below.

> Maybe we should define ISA_HAS_ODD_SINGLE_FPR so that it takes
> the mips_opts.arch as well as the mips_opts.isa, then make it
> true for CPU_R5900 and false for CPU_LOONGSON_3A.  Then the error:
> 
> > +  if (opts->fp != 64 && opts->arch == CPU_LOONGSON_3A && !opts-
> >nooddspreg)
> > +    as_bad (_("`arch=loongson3a' requires `nooddspreg' when using "
> > +	      "`fp=32' or `fp=xx'"));
> 
> could apply whenever !ISA_HAS_ODD_SINGLE_FPR.  The default could also
> be set based on ISA_HAS_ODD_SINGLE_FPR.

Given the way that the assembler handles odd-numbered registers today
I don't actually think we need an error at all. If the architecture
does not support odd-numbered singles then you will get a warning
during code generation anyway so -modd-spreg with loongson-3a can just
have no effect and a warning will be seen if odd singles are used.

In order to keep GCC and GAS defaults the same (and avoid having to
set defaults in GCC specs which would be unpleasant) then I'd define
-mno-odd-spreg to be on by default for -mips* -mfpxx and do this for
both GCC and GAS. FPXX is after all the way to achieve compatible code
so it makes sense to just tie this default up with -mfpxx. A user can
still do -mips* -mfpxx -modd-spreg if they wish as well.

The patch for this is below and I will modify the odd-spreg GCC patch
to match. I had to change the way single precision moves/memory ops are
detected as the existing code did not cover micromips and it seemed
bad practice to add the existing INSN* macros to micromips when the
micromips instructions have no COPRO DELAY requirements etc.

Regards,
Matthew

gas/

	* config/tc-mips.c (mips_set_options): Add nooddspreg field.
	(file_mips_opts, mips_opts): Set nooddspreg to -1.
	(ISA_HAS_ODD_SINGLE_FPR): Add CPU argument and handle r5900 and
	loongson-3a.
	(enum options): Add OPTION_ODD_SPREG and OPTION_NO_ODD_SPREG.
	(file_mips_check_options): Infer nooddspreg from the cpu and ABI.
	(mips_oddfpreg_ok): Use nooddspreg and INSN_FP_32_MOVE.
	(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/fpxx-oddfpreg.d: New.
	* gas/mips/mips.exp: Add new tests, add oddspreg property.
	* gas/mips/module-set-mfpxx.s: Set oddspreg.

include/

	* opcode/mips.h (INSN_FP_32_MOVE): New macro.

opcodes/

	* micromips-opc.c (F32M) New macro.
	(micromips_opcodes): Use F32M.
	* mips-opc.c: (F32M) New macro.
	(mips_builtin_opcodes): Use F32M.
---
 gas/config/tc-mips.c                      |   65 ++++++++++++++++++++++-------
 gas/doc/as.texinfo                        |    8 ++++
 gas/doc/c-mips.texi                       |    8 ++++
 gas/testsuite/gas/mips/fpxx-oddfpreg.d    |   12 +++++
 gas/testsuite/gas/mips/mips.exp           |   21 +++++++---
 gas/testsuite/gas/mips/module-set-mfpxx.s |    1 +
 include/opcode/mips.h                     |    2 +
 opcodes/micromips-opc.c                   |   25 ++++++-----
 opcodes/mips-opc.c                        |   25 ++++++-----
 9 files changed, 122 insertions(+), 45 deletions(-)
 create mode 100644 gas/testsuite/gas/mips/fpxx-oddfpreg.d

diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index d51a91c..ee0b7fd 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.  */
@@ -393,15 +397,17 @@ static int mips_32bitmode = 0;
    )
 
 /* Return true if ISA supports single-precision floats in odd registers.  */
-#define ISA_HAS_ODD_SINGLE_FPR(ISA)	\
-  ((ISA) == ISA_MIPS32			\
-   || (ISA) == ISA_MIPS32R2		\
-   || (ISA) == ISA_MIPS32R3		\
-   || (ISA) == ISA_MIPS32R5		\
-   || (ISA) == ISA_MIPS64		\
-   || (ISA) == ISA_MIPS64R2		\
-   || (ISA) == ISA_MIPS64R3		\
-   || (ISA) == ISA_MIPS64R5)
+#define ISA_HAS_ODD_SINGLE_FPR(ISA, CPU)\
+  (((ISA) == ISA_MIPS32			\
+    || (ISA) == ISA_MIPS32R2		\
+    || (ISA) == ISA_MIPS32R3		\
+    || (ISA) == ISA_MIPS32R5		\
+    || (ISA) == ISA_MIPS64		\
+    || (ISA) == ISA_MIPS64R2		\
+    || (ISA) == ISA_MIPS64R3		\
+    || (ISA) == ISA_MIPS64R5		\
+    || (CPU) == CPU_R5900)		\
+   && (CPU) != CPU_LOONGSON_3A)
 
 /* Return true if ISA supports move to/from high part of a 64-bit
    floating-point register. */
@@ -1436,6 +1442,8 @@ enum options
     OPTION_NO_PDR,
     OPTION_MVXWORKS_PIC,
     OPTION_NAN,
+    OPTION_ODD_SPREG,
+    OPTION_NO_ODD_SPREG,
     OPTION_END_OF_ENUM
   };
 
@@ -1542,6 +1550,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
@@ -3820,6 +3830,20 @@ 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 when using the FPXX ABI.  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.fp == 0)
+	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
@@ -4469,8 +4493,8 @@ static bfd_boolean
 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);
+  bfd_boolean oddspreg = ISA_HAS_ODD_SINGLE_FPR (mips_opts.isa, mips_opts.arch)
+			 && !mips_opts.nooddspreg;
 
   if (insn->pinfo == INSN_MACRO)
     /* Let a macro pass, we'll catch it later when it is expanded.  */
@@ -4499,8 +4523,7 @@ mips_oddfpreg_ok (const struct mips_opcode *insn, int opnum)
 
   /* Single-precision coprocessor loads and moves are OK too.  */
   if ((insn->pinfo & FP_S)
-      && (insn->pinfo & (INSN_COPROC_MEMORY_DELAY | INSN_STORE_MEMORY
-			 | INSN_LOAD_COPROC_DELAY | INSN_COPROC_MOVE_DELAY)))
+      && (insn->pinfo & INSN_FP_32_MOVE))
     {
       if (FPR_SIZE == 0 && !oddspreg)
 	as_bad (_("unsupported access to the upper half of double-precision "
@@ -14058,6 +14081,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 +15189,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..a8a9517 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,13 @@ 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.  By default @samp{-modd-spreg} is
+selected except when targetting a generic MIPS architecture in combination
+with @samp{-mfpxx} then @samp{-mno-odd-spreg} is selected.
+
 @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..938d744 100644
--- a/gas/doc/c-mips.texi
+++ b/gas/doc/c-mips.texi
@@ -135,6 +135,14 @@ 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.  By default @samp{-modd-spreg} is
+selected except when targetting a generic MIPS architecture in combination
+with @samp{-mfpxx} then @samp{-mno-odd-spreg} is selected.
+
 @item -mips16
 @itemx -no-mips16
 Generate code for the MIPS 16 processor.  This is equivalent to putting
diff --git a/gas/testsuite/gas/mips/fpxx-oddfpreg.d b/gas/testsuite/gas/mips/fpxx-oddfpreg.d
new file mode 100644
index 0000000..89f2e9b
--- /dev/null
+++ b/gas/testsuite/gas/mips/fpxx-oddfpreg.d
@@ -0,0 +1,12 @@
+#as: -32 -mfpxx
+#objdump: -d
+#name: FPXX with odd-singles test
+.*:     file format .*
+
+Disassembly of section .text:
+
+[ 0-9a-f]+ <.text>:
+[ 0-9a-f]+:	44840800 	mtc1	a0,\$f1
+[ 0-9a-f]+:	44040800 	mfc1	a0,\$f1
+[ 0-9a-f]+:	c4610000 	lwc1	\$f1,0\(v1\)
+[ 0-9a-f]+:	e4610000 	swc1	\$f1,0\(v1\)
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index e7604b1..9b68b3d 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -86,6 +86,10 @@
 #	nollsc
 #		The CPU doesn't support ll, sc, lld and scd instructions.
 #
+#	oddspreg
+#		The CPU has odd-numbered single-precision registers
+#		available and GAS enables use of them by default.
+#
 # as_flags: The assembler flags used when assembling tests for this
 # architecture.
 #
@@ -452,19 +456,19 @@ mips_arch_create r4000 	64	mips3	{} \
 			{ -march=r4000 -mtune=r4000 } { -mmips:4000 }
 mips_arch_create vr5400	64	mips4	{ ror } \
 			{ -march=vr5400 -mtune=vr5400 } { -mmips:5400 }
-mips_arch_create sb1 	64	mips64	{ mips3d } \
+mips_arch_create sb1 	64	mips64	{ mips3d oddspreg } \
 			{ -march=sb1 -mtune=sb1 } { -mmips:sb1 } \
 			{ mipsisa64sb1-*-* mipsisa64sb1el-*-* }
-mips_arch_create octeon 64	mips64r2 {} \
+mips_arch_create octeon 64	mips64r2 { oddspreg } \
 			{ -march=octeon -mtune=octeon } { -mmips:octeon } \
 			{ mips64octeon*-*-* }
-mips_arch_create octeonp 64	octeon {} \
+mips_arch_create octeonp 64	octeon { oddspreg } \
 			{ -march=octeon+ -mtune=octeon+ } { -mmips:octeon+ } \
 			{ }
-mips_arch_create octeon2 64	octeonp {} \
+mips_arch_create octeon2 64	octeonp { oddspreg } \
 			{ -march=octeon2 -mtune=octeon2 } { -mmips:octeon2 } \
 			{ }
-mips_arch_create xlr 	64	mips64	{} \
+mips_arch_create xlr 	64	mips64	{ oddspreg } \
 			{ -march=xlr -mtune=xlr } { -mmips:xlr }
 mips_arch_create r5900 	64	mips3	{ gpr_ilocks singlefloat nollsc } \
 			{ -march=r5900 -mtune=r5900 } { -mmips:5900 } \
@@ -1338,7 +1342,12 @@ if { [istarget mips*-*-vxworks*] } {
     }
 
     run_dump_test "module-set-mfpxx"
-    run_list_test "fpxx-oddfpreg" "-32 -mips2 -mfpxx"
+    run_list_test_arches "fpxx-oddfpreg" "-32 -mfpxx" \
+			[mips_arch_list_matching mips2 !singlefloat !oddspreg]
+    run_list_test_arches "fpxx-oddfpreg" "-32 -mfpxx -mno-odd-spreg" \
+			[mips_arch_list_matching oddspreg]
+    run_dump_test_arches "fpxx-oddfpreg" "-32 -mfpxx" \
+			[mips_arch_list_matching oddspreg]
     run_dump_test "module-check"
     run_list_test "module-check-warn" "-32"
 
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
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index 6ae1f3a..13ebba7 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -1010,6 +1010,8 @@ struct mips_opcode
 #define INSN_WRITE_GPR_24           0x10000000
 /* A user-defined instruction.  */
 #define INSN_UDI                    0x20000000
+/* Is mtc1, mfc1, swc1, lwc1.  */
+#define INSN_FP_32_MOVE		    0x40000000
 /* Instruction is actually a macro.  It should be ignored by the
    disassembler, and requires special treatment by the assembler.  */
 #define INSN_MACRO                  0xffffffff
diff --git a/opcodes/micromips-opc.c b/opcodes/micromips-opc.c
index af7cbf6..2ceeb83 100644
--- a/opcodes/micromips-opc.c
+++ b/opcodes/micromips-opc.c
@@ -204,6 +204,7 @@ decode_micromips_operand (const char *p)
 #define SM	INSN_STORE_MEMORY
 #define BD16	INSN2_BRANCH_DELAY_16BIT	/* Used in pinfo2.  */
 #define BD32	INSN2_BRANCH_DELAY_32BIT	/* Used in pinfo2.  */
+#define F32M	INSN_FP_32_MOVE
 
 #define WR_1	INSN_WRITE_1
 #define WR_2	INSN_WRITE_2
@@ -789,13 +790,13 @@ const struct mips_opcode micromips_opcodes[] =
 {"lw",			"md,mA(ma)",        0x6400,     0xfc00,	WR_1|RD_3|LM,		0,		I1,		0,	0 }, /* lwgp */
 {"lw",			"t,o(b)",	0xfc000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I1,		0,	0 },
 {"lw",			"t,A(b)",	0,    (int) M_LW_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"lwc1",		"T,o(b)",	0x9c000000, 0xfc000000,	WR_1|RD_3|FP_S|LM,	0,		I1,		0,	0 },
-{"lwc1",		"E,o(b)",	0x9c000000, 0xfc000000,	WR_1|RD_3|FP_S|LM,	0,		I1,		0,	0 },
+{"lwc1",		"T,o(b)",	0x9c000000, 0xfc000000,	WR_1|RD_3|FP_S|LM|F32M,	0,		I1,		0,	0 },
+{"lwc1",		"E,o(b)",	0x9c000000, 0xfc000000,	WR_1|RD_3|FP_S|LM|F32M,	0,		I1,		0,	0 },
 {"lwc1",		"T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"lwc1",		"E,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"lwc2",		"E,~(b)",	0x20000000, 0xfc00f000,	RD_3|WR_CC|LM,		0,		I1,		0,	0 },
 {"lwc2",		"E,A(b)",	0,    (int) M_LWC2_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"l.s",			"T,o(b)",	0x9c000000, 0xfc000000,	WR_1|RD_3|FP_S|LM,	0,		I1,		0,	0 }, /* lwc1 */
+{"l.s",			"T,o(b)",	0x9c000000, 0xfc000000,	WR_1|RD_3|FP_S|LM|F32M,	0,		I1,		0,	0 }, /* lwc1 */
 {"l.s",			"T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"lwl",			"t,~(b)",	0x60000000, 0xfc00f000,	WR_1|RD_3|LM,		0,		I1,		0,	0 },
 {"lwl",			"t,A(b)",	0,    (int) M_LWL_AB,	INSN_MACRO,		0,		I1,		0,	0 },
@@ -810,7 +811,7 @@ const struct mips_opcode micromips_opcodes[] =
 {"lwr",			"t,A(b)",	0,    (int) M_LWR_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"lwu",			"t,~(b)",	0x6000e000, 0xfc00f000,	WR_1|RD_3|LM,		0,		I3,		0,	0 },
 {"lwu",			"t,A(b)",	0,    (int) M_LWU_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"lwxc1",		"D,t(b)",	0x54000048, 0xfc0007ff,	WR_1|RD_2|RD_3|FP_S|LM, 0,		I1,		0,	0 },
+{"lwxc1",		"D,t(b)",	0x54000048, 0xfc0007ff,	WR_1|RD_2|RD_3|FP_S|LM|F32M, 0,		I1,		0,	0 },
 {"flush",		"t,~(b)",	0x60001000, 0xfc00f000,	WR_1|RD_3,		0,		I1,		0,	0 }, /* same */
 {"flush",		"t,A(b)",	0,    (int) M_LWR_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"lwxs",		"d,t(b)",	0x00000118, 0xfc0007ff,	WR_1|RD_2|RD_3|LM,	0,		I1,		0,	0 },
@@ -823,8 +824,8 @@ const struct mips_opcode micromips_opcodes[] =
 {"maddu",		"7,s,t",	0x00001abc, 0xfc003fff,	RD_2|RD_3|MOD_a,	0,		0,		D32,	0 },
 {"mfc0",		"t,G",		0x000000fc, 0xfc00ffff,	WR_1|RD_C0,		0,		I1,		0,	0 },
 {"mfc0",		"t,G,H",	0x000000fc, 0xfc00c7ff,	WR_1|RD_C0,		0,		I1,		0,	0 },
-{"mfc1",		"t,S",		0x5400203b, 0xfc00ffff,	WR_1|RD_2|FP_S,		0,		I1,		0,	0 },
-{"mfc1",		"t,G",		0x5400203b, 0xfc00ffff,	WR_1|RD_2|FP_S,		0,		I1,		0,	0 },
+{"mfc1",		"t,S",		0x5400203b, 0xfc00ffff,	WR_1|RD_2|FP_S|F32M,	0,		I1,		0,	0 },
+{"mfc1",		"t,G",		0x5400203b, 0xfc00ffff,	WR_1|RD_2|FP_S|F32M,	0,		I1,		0,	0 },
 {"mfc2",		"t,G",		0x00004d3c, 0xfc00ffff,	WR_1|RD_C2,		0,		I1,		0,	0 },
 {"mfgc0",		"t,G",		0x000004fc, 0xfc00ffff,	WR_1|RD_C0,		0,		0,		IVIRT,	0 },
 {"mfgc0",		"t,G,H",	0x000004fc, 0xfc00c7ff,	WR_1|RD_C0,		0,		0,		IVIRT,	0 },
@@ -869,8 +870,8 @@ const struct mips_opcode micromips_opcodes[] =
 {"msubu",		"7,s,t",	0x00003abc, 0xfc003fff,	RD_2|RD_3|MOD_a,	0,		0,		D32,	0 },
 {"mtc0",		"t,G",		0x000002fc, 0xfc00ffff,	RD_1|WR_C0|WR_CC,	0,		I1,		0,	0 },
 {"mtc0",		"t,G,H",	0x000002fc, 0xfc00c7ff,	RD_1|WR_C0|WR_CC,	0,		I1,		0,	0 },
-{"mtc1",		"t,S",		0x5400283b, 0xfc00ffff,	RD_1|WR_2|FP_S,		0,		I1,		0,	0 },
-{"mtc1",		"t,G",		0x5400283b, 0xfc00ffff,	RD_1|WR_2|FP_S,		0,		I1,		0,	0 },
+{"mtc1",		"t,S",		0x5400283b, 0xfc00ffff,	RD_1|WR_2|FP_S|F32M,	0,		I1,		0,	0 },
+{"mtc1",		"t,G",		0x5400283b, 0xfc00ffff,	RD_1|WR_2|FP_S|F32M,	0,		I1,		0,	0 },
 {"mtc2",		"t,G",		0x00005d3c, 0xfc00ffff,	RD_1|WR_C2|WR_CC,	0,		I1,		0,	0 },
 {"mtgc0",		"t,G",		0x000006fc, 0xfc00ffff,	RD_1|WR_C0|WR_CC,	0,		0,		IVIRT,	0 },
 {"mtgc0",		"t,G,H",	0x000006fc, 0xfc00c7ff,	RD_1|WR_C0|WR_CC,	0,		0,		IVIRT,	0 },
@@ -1037,13 +1038,13 @@ const struct mips_opcode micromips_opcodes[] =
 {"sw",			"mp,mU(ms)",	    0xc800,     0xfc00,	RD_1|RD_3|SM,		0,		I1,		0,	0 }, /* swsp */
 {"sw",			"t,o(b)",	0xf8000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I1,		0,	0 },
 {"sw",			"t,A(b)",	0,    (int) M_SW_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"swc1",		"T,o(b)",	0x98000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 },
-{"swc1",		"E,o(b)",	0x98000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 },
+{"swc1",		"T,o(b)",	0x98000000, 0xfc000000,	RD_1|RD_3|SM|FP_S|F32M,	0,		I1,		0,	0 },
+{"swc1",		"E,o(b)",	0x98000000, 0xfc000000,	RD_1|RD_3|SM|FP_S|F32M,	0,		I1,		0,	0 },
 {"swc1",		"T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"swc1",		"E,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"swc2",		"E,~(b)",	0x20008000, 0xfc00f000,	RD_3|RD_C2|SM,		0,		I1,		0,	0 },
 {"swc2",		"E,A(b)",	0,    (int) M_SWC2_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"s.s",			"T,o(b)",	0x98000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 }, /* swc1 */
+{"s.s",			"T,o(b)",	0x98000000, 0xfc000000,	RD_1|RD_3|SM|FP_S|F32M,	0,		I1,		0,	0 }, /* swc1 */
 {"s.s",			"T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"swl",			"t,~(b)",	0x60008000, 0xfc00f000,	RD_1|RD_3|SM,		0,		I1,		0,	0 },
 {"swl",			"t,A(b)",	0,    (int) M_SWL_AB,	INSN_MACRO,		0,		I1,		0,	0 },
@@ -1058,7 +1059,7 @@ const struct mips_opcode micromips_opcodes[] =
 {"swr",			"t,A(b)",	0,    (int) M_SWR_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"invalidate",		"t,~(b)",	0x60009000, 0xfc00f000,	RD_1|RD_3|SM,		0,		I1,		0,	0 }, /* same */
 {"invalidate",		"t,A(b)",	0,    (int) M_SWR_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"swxc1",		"D,t(b)",	0x54000088, 0xfc0007ff,	RD_1|RD_2|RD_3|SM|FP_S,	0,		I1,		0,	0 },
+{"swxc1",		"D,t(b)",	0x54000088, 0xfc0007ff,	RD_1|RD_2|RD_3|SM|FP_S|F32M, 0,		I1,		0,	0 },
 {"sync_acquire",	"",		0x00116b7c, 0xffffffff,	NODS,			0,		I1,		0,	0 },
 {"sync_mb",		"",		0x00106b7c, 0xffffffff,	NODS,			0,		I1,		0,	0 },
 {"sync_release",	"",		0x00126b7c, 0xffffffff,	NODS,			0,		I1,		0,	0 },
diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c
index e2c258c..671f20b 100644
--- a/opcodes/mips-opc.c
+++ b/opcodes/mips-opc.c
@@ -200,6 +200,7 @@ decode_mips_operand (const char *p)
 #define TRAP	INSN_NO_DELAY_SLOT
 #define LM	INSN_LOAD_MEMORY
 #define SM	INSN_STORE_MEMORY
+#define F32M	INSN_FP_32_MOVE
 
 #define WR_1	INSN_WRITE_1
 #define WR_2	INSN_WRITE_2
@@ -1208,11 +1209,11 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"lw",			"t,A(b)",	0,    (int) M_LW_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"lwc0",		"E,o(b)",	0xc0000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
 {"lwc0",		"E,A(b)",	0,    (int) M_LWC0_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
-{"lwc1",		"T,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S,	0,		I1,		0,	0 },
-{"lwc1",		"E,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S,	0,		I1,		0,	0 },
+{"lwc1",		"T,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S|F32M,0,		I1,		0,	0 },
+{"lwc1",		"E,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S|F32M,0,		I1,		0,	0 },
 {"lwc1",		"T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"lwc1",		"E,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
-{"l.s",			"T,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S,	0,		I1,		0,	0 }, /* lwc1 */
+{"l.s",			"T,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S|F32M,0,		I1,		0,	0 }, /* lwc1 */
 {"l.s",			"T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"lwc2",		"E,o(b)",	0xc8000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
 {"lwc2",		"E,A(b)",	0,    (int) M_LWC2_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
@@ -1229,7 +1230,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"fork",		"d,s,t",	0x7c000008, 0xfc0007ff, WR_1|RD_2|RD_3|TRAP,	0,		0,		MT32,	0 },
 {"lwu",			"t,o(b)",	0x9c000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I3,		0,	0 },
 {"lwu",			"t,A(b)",	0,    (int) M_LWU_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"lwxc1",		"D,t(b)",	0x4c000000, 0xfc00f83f, WR_1|RD_2|RD_3|LM|FP_S,     0,		I4_33,		0,	0 },
+{"lwxc1",		"D,t(b)",	0x4c000000, 0xfc00f83f, WR_1|RD_2|RD_3|LM|FP_S|F32M, 0,		I4_33,		0,	0 },
 {"lwxs",		"d,t(b)",	0x70000088, 0xfc0007ff,	WR_1|RD_2|RD_3|LM,	     0,		0,		SMT,	0 },
 {"macc",		"d,s,t",	0x00000028, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO,	     0,		N412,		0,	0 },
 {"macc",		"d,s,t",	0x00000158, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO,	     0,		N5,		0,	0 },
@@ -1310,8 +1311,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"mfhc0",		"t,G,H",	0x40400000, 0xffe007f8,	WR_1|RD_C0|LCD,		0,		I33,		XPA,	0 },
 {"mfhgc0",		"t,G",		0x40600400, 0xffe007ff,	WR_1|RD_C0|LCD,		0,		I33,		IVIRT|XPA,	0 },
 {"mfhgc0",		"t,G,H",	0x40600400, 0xffe007f8,	WR_1|RD_C0|LCD,		0,		I33,		IVIRT|XPA,	0 },
-{"mfc1",		"t,S",		0x44000000, 0xffe007ff,	WR_1|RD_2|LCD|FP_S,	0,		I1,		0,	0 },
-{"mfc1",		"t,G",		0x44000000, 0xffe007ff,	WR_1|RD_2|LCD|FP_S,	0,		I1,		0,	0 },
+{"mfc1",		"t,S",		0x44000000, 0xffe007ff,	WR_1|RD_2|LCD|FP_S|F32M,0,		I1,		0,	0 },
+{"mfc1",		"t,G",		0x44000000, 0xffe007ff,	WR_1|RD_2|LCD|FP_S|F32M,0,		I1,		0,	0 },
 {"mfhc1",		"t,S",		0x44600000, 0xffe007ff,	WR_1|RD_2|LCD|FP_D,	0,		I33,		0,	0 },
 {"mfhc1",		"t,G",		0x44600000, 0xffe007ff,	WR_1|RD_2|LCD|FP_D,	0,		I33,		0,	0 },
 /* mfc2 is at the bottom of the table.  */
@@ -1407,8 +1408,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"mthc0",		"t,G,H",	0x40c00000, 0xffe007f8,	RD_1|WR_C0|WR_CC|COD,	0,		I33,		XPA,	0 },
 {"mthgc0",		"t,G",		0x40600600, 0xffe007ff,	RD_1|WR_C0|WR_CC|COD,	0,		I33,		IVIRT|XPA,	0 },
 {"mthgc0",		"t,G,H",	0x40600600, 0xffe007f8,	RD_1|WR_C0|WR_CC|COD,	0,		I33,		IVIRT|XPA,	0 },
-{"mtc1",		"t,S",		0x44800000, 0xffe007ff,	RD_1|WR_2|COD|FP_S,	0,		I1,		0,	0 },
-{"mtc1",		"t,G",		0x44800000, 0xffe007ff,	RD_1|WR_2|COD|FP_S,	0,		I1,		0,	0 },
+{"mtc1",		"t,S",		0x44800000, 0xffe007ff,	RD_1|WR_2|COD|FP_S|F32M,0,		I1,		0,	0 },
+{"mtc1",		"t,G",		0x44800000, 0xffe007ff,	RD_1|WR_2|COD|FP_S|F32M,0,		I1,		0,	0 },
 {"mthc1",		"t,S",		0x44e00000, 0xffe007ff,	RD_1|WR_2|COD|FP_D,	0,		I33,		0,	0 },
 {"mthc1",		"t,G",		0x44e00000, 0xffe007ff,	RD_1|WR_2|COD|FP_D,	0,		I33,		0,	0 },
 /* mtc2 is at the bottom of the table.  */
@@ -1848,11 +1849,11 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"swapd",		"t,b",		0x70000016, 0xfc00ffff, MOD_1|RD_2|LM|SM,	0,		XLR,		0,	0 },
 {"swc0",		"E,o(b)",	0xe0000000, 0xfc000000,	RD_3|RD_C0|SM,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
 {"swc0",		"E,A(b)",	0,    (int) M_SWC0_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
-{"swc1",		"T,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 },
-{"swc1",		"E,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 },
+{"swc1",		"T,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S|F32M,	0,		I1,		0,	0 },
+{"swc1",		"E,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S|F32M,	0,		I1,		0,	0 },
 {"swc1",		"T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"swc1",		"E,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
-{"s.s",			"T,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 }, /* swc1 */
+{"s.s",			"T,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S|F32M,	0,		I1,		0,	0 }, /* swc1 */
 {"s.s",			"T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"swc2",		"E,o(b)",	0xe8000000, 0xfc000000,	RD_3|RD_C2|SM,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
 {"swc2",		"E,A(b)",	0,    (int) M_SWC2_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
@@ -1866,7 +1867,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"swr",			"t,A(b)",	0,    (int) M_SWR_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"invalidate",		"t,o(b)",	0xb8000000, 0xfc000000,	RD_1|RD_3,		0,		I2,		0,	0 }, /* same */
 {"invalidate",		"t,A(b)",	0,    (int) M_SWR_AB,	INSN_MACRO,		0,		I2,		0,	0 }, /* as swr */
-{"swxc1",		"S,t(b)",	0x4c000008, 0xfc0007ff, RD_1|RD_2|RD_3|SM|FP_S,	0,		I4_33,		0,	0 },
+{"swxc1",		"S,t(b)",	0x4c000008, 0xfc0007ff, RD_1|RD_2|RD_3|SM|FP_S|F32M, 0,		I4_33,		0,	0 },
 {"synciobdma",		"",		0x0000008f, 0xffffffff,	NODS,			0,		IOCT,		0,	0 },
 {"syncs",		"",		0x0000018f, 0xffffffff,	NODS,			0,		IOCT,		0,	0 },
 {"syncw",		"",		0x0000010f, 0xffffffff,	NODS,			0,		IOCT,		0,	0 },
-- 
1.7.1


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