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] Add support for CPUs with no FPU


This patch adds support for soft-float targets and generalizes single-float
support.

CPU targets can now be marked as single-float or soft-float.  These are used
by default and can be overridden with command-line options or asm directives.
So that we don't have to remember another set of options I used the GCC names:
-msoft-float/-mhard-float -msingle-float/-mdouble-float.

Instructions in the optable are marked with FP_S or FP_D if they require
single-precision or a double-precision FPU.  (Two instructions prefx and cop1
were missing this marking.)  I use these flags to decide whether the
instruction should be enabled for single-float or soft-float.

The code to check the flags is in a new function encapsulating
OPCODE_IS_MEMBER in tc-mips.c.  One consequence of not doing this inside
OPCODE_IS_MEMBER in mips.h which is shared with the disassembler is that even
for a soft-float target we will disassemble fp instructions.  This matches how
r4650 used to work WRT dfp instruction.  If I did it other way then we would
need matching command-line options in the disassembler to revert the CPU
defaults.  I am not sure it would be worth the complication.

I added support for marking macros as requiring single-float or double-float
support.  The bits to track this are in the pinfo2 field.  Another option
would be to use the match field which as far as I know should always be zero
for macros.  (Confusingly enough, the drem macros have 3 as their match field.
Is that a typo?)

There were four tests where I had to split out the fp instructions into a
separate file and disable the corresponding dump test for soft-float.  Using
the fp .s file I created list tests for soft-float to check that fp
instructions a properly diagnosed.  I added four new tests to check for dfp
and sfp macros and for various combinations of the new command-line flags and
directives.

I updated the documentation to cover the new flags and directives.

Regression-tested on mips64octeon-linux-gnu with the gas testsuite.  All the
new tests pass.  Tested documentation changes with make info.

OK?

Adam

include/opcode/

	* mips.h (INSN_MACRO): Move it up to the the pinfo macros.
	(INSN2_M_FP_S, INSN2_M_FP_D): New pinfo2 macros.

opcodes/

	* mips.h (INSN_MACRO): Move it up to the the pinfo macros.
	(INSN2_M_FP_S, INSN2_M_FP_D): New pinfo2 macros.

gas/

	* config/tc-mips.c (struct mips_set_options): New fields
	soft_float and single_float.
	(mips_opts): Initialized them.
	(file_mips_soft_float, file_mips_single_float): New statics.
	(struct mips_cpu_info): Update comment for field flags.
	(MIPS_CPU_FLOAT_OPS_NONE, MIPS_CPU_FLOAT_OPS_SINGLE): New macros
	for cpu_info flags.
	(mips_cpu_info_table): Set MIPS_CPU_FLOAT_OPS_NONE for Octeon.  Set
	MIPS_CPU_FLOAT_OPS_SINGLE for r4650.
	(CPU_SOFT_FLOAT, CPU_SINGLE_FLOAT): New macros to check if CPU is
	soft-float or single-float.
	(is_opcode_valid): New function to invoke OPCODE_IS_MEMBER.
	Handle single-float and soft-float instructions here.
	(macro_build, mips_ip): Use it instead of OPCODE_IS_MEMBER.
	(is_opcode_valid_16): New function.
	(mips16_ip): Use it instead of OPCODE_IS_MEMBER.
	(macro) <M_LDC1_AB, M_SDC1_AB, M_L_DOB, M_L_DAB, M_S_DAB,
	M_S_DOB>: Remove special-casing of r4650.
	(OPTION_SOFT_FLOAT, OPTION_HARD_FLOAT, OPTION_SINGLE_FLOAT,
	OPTION_DOUBLE_FLOAT): New option macros.
	(md_longopts): Add msoft-float, mhard-float, msingle-float and
	mdouble-float.
	(OPTION_ELF_BASE): Make room for new option macros.
	(md_parse_option): Handle OPTION_SINGLE_FLOAT,
	OPTION_DOUBLE_FLOAT, OPTION_SOFT_FLOAT and OPTION_HARD_FLOAT.
	(mips_after_parse_args): Set defaults for _mips_soft_float and
	file_mips_single_float.
	(s_mipsset): Add support for `.set softfloat', `.set hardfloat',
	`.set singlefloat' and `.set doublefloat'.  Reinitialize
	mips_opts.soft_float and mips_opts.single_float after `.set
	arch=...'.
	(md_show_usage): Add -msoft-float, -mhard-float, -msingle-float
	and -mdouble-float.

	* doc/c-mips.texi (-march=): Add Octeon.
	(MIPS Opts): Document -msoft-float and -mhard-float.  Document
	-msingle-float and -mdouble-float.
	(MIPS floating-point): New section.  Document `.set softfloat' and
	`.set hardfloat'.  Document `.set singlefloat' and `.set
	doublefloat'.

gas/testsuite/

	* gas/mips/mips4.s: Split out fp instruction from here ...
	* gas/mips/mips4-fp.s: ... to here.
	* gas/mips/mips4.d: Update.
	* gas/mips/mips4-fp.l: New file. Check error messages for
	soft-float targets.
	* gas/mips/mips4-fp.d: New file. Check disassembly for hard-float
	targets.

	* gas/mips/mips32r2.s: Split out fp instructions from here ...
	* gas/mips/mips32r2-fp32.s: ... to here.
	* gas/mips/mips32r2.d: Update.
	* gas/mips/mips32r2-fp32.l: New file.  Check error messages for
	soft-float targets.
	* gas/mips/mips32r2-fp32.d: New file.  Check disassembly for
	hard-float targets.

	* gas/mips/mips32r2-ill-nofp.s, gas/mips/mips32r2-ill-nofp.l: New
	test derived from mips32r2-ill.

	* gas/mips/mips32-sf32.l: New list test for mips32-sf32.s to check
	error messages for soft-float targets.

	* gas/mips/mips-macro-ill-sfp.s, gas/mips/mips-macro-ill-sfp.l:
	New test.
	* gas/mips/mips-macro-ill-nofp.s, gas/mips/mips-macro-ill-nofp.l:
	New test.
	* gas/mips/mips-hard-float-flag.s,
	gas/mips/mips-hard-float-flag.l: New test.
	* gas/mips/mips-double-float-flag.s,
	gas/mips/mips-double-float-flag.l: New test.

	* gas/mips/mips.exp: Document new properties soft_float,
	single_float.  Add new arch for r4650 with single_float.  Add
	soft_float to Octeon.  Don't run mips5 for soft-float targets.
	Run new mips4-fp and mips32r2-fp dump and list tests depending
	whether target is hard-float or soft-float.  Run new
	mips32r2-ill-nofp for soft-float targets rather than mips32r2-ill
	and mips32r2-ill-fp64.  Run new mips32-sf32 list test for
	soft-float targets rather than the dump test.  Compile test
	illegal for mip1.  Don't run elf$(el)-rel2) for either
	single-float or soft-float.  Run new mips-macro-ill-sfp test for
	single-float targets or with -msingle-float for double-float
	targets.  Run new mips-macro-ill-nofp test for soft-float targets
	or with -msoft-float for hard-float targets. Run new
	mips-hard-float-flag and mips-double-float-flag tests.

	* gas/mips/fpr-names-32.d (#as): New.  Pass -mips1 -32.
	* gas/mips/fpr-names-64.d (#as): New.  Pass -mips64 -64.
	* gas/mips/fpr-names-n32.d (#as): New.  Pass -mips64 -n32.
	* gas/mips/fpr-names-numeric.d (#as): New.  Pass -mips1 -32.

Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.382
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.382 tc-mips.c
--- gas/config/tc-mips.c	4 Feb 2008 19:20:16 -0000	1.382
+++ gas/config/tc-mips.c	15 Feb 2008 21:08:30 -0000
@@ -235,6 +235,17 @@ struct mips_set_options
   int arch;
   /* True if ".set sym32" is in effect.  */
   bfd_boolean sym32;
+  /* Non-zero if floating-point operations are not allowed.  Changed
+     by .set softfloat or .set hardfloat, by command line options
+     -msoft-float or -mhard-float.  The default is set based on the
+     CPU target.*/
+  int soft_float;
+
+  /* Non-zero if only single-precision floating-point operations are
+     allowed.  Changed by .set singlefloat or .set doublefloat,
+     command-line options -msoft-float or -mhard-float.  The default
+     is set based on the CPU target. */
+  int single_float;
 };
 
 /* True if -mgp32 was passed.  */
@@ -243,13 +254,30 @@ static int file_mips_gp32 = -1;
 /* True if -mfp32 was passed.  */
 static int file_mips_fp32 = -1;
 
+/* 1 if -msoft-float, 0 if -mhard-float and -1 if neither was
+   passed.  */
+static int file_mips_soft_float = -1;
+
+/* Return non-zero if CPU has no FPU.  */
+#define CPU_SOFT_FLOAT(CPU_INFO_FLAGS)		\
+  ((CPU_INFO_FLAGS) & MIPS_CPU_FLOAT_OPS_NONE)
+
+/* 1 if -msingle-float, 0 if -mdouble-float and -1 if neither was
+   passed */
+static int file_mips_single_float = -1;
+
+/* Return non-zero if CPU support only single-precision operations.  */
+#define CPU_SINGLE_FLOAT(CPU_INFO_FLAGS)		\
+  ((CPU_INFO_FLAGS) & MIPS_CPU_FLOAT_OPS_SINGLE)
+
 /* This is the struct we use to hold the current set of options.  Note
    that we must set the isa field to ISA_UNKNOWN and the ASE fields to
    -1 to indicate that they have not been initialized.  */
 
 static struct mips_set_options mips_opts =
 {
-  ISA_UNKNOWN, -1, -1, 0, -1, -1, -1, -1, 0, ATREG, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN, FALSE
+  ISA_UNKNOWN, -1, -1, 0, -1, -1, -1, -1, 0, ATREG, 0, 0, 0, 0, 0, 0,
+  CPU_UNKNOWN, FALSE, FALSE, FALSE
 };
 
 /* These variables are filled in with the masks of registers used.
@@ -1055,18 +1083,20 @@ static int validate_mips_insn (const str
 struct mips_cpu_info
 {
   const char *name;           /* CPU or ISA name.  */
-  int flags;                  /* ASEs available, or ISA flag.  */
+  int flags;                  /* ASEs available, FPU capability, ISA flag.  */
   int isa;                    /* ISA level.  */
   int cpu;                    /* CPU number (default CPU if ISA).  */
 };
 
-#define MIPS_CPU_IS_ISA		0x0001	/* Is this an ISA?  (If 0, a CPU.) */
-#define MIPS_CPU_ASE_SMARTMIPS	0x0002	/* CPU implements SmartMIPS ASE */
-#define MIPS_CPU_ASE_DSP	0x0004	/* CPU implements DSP ASE */
-#define MIPS_CPU_ASE_MT		0x0008	/* CPU implements MT ASE */
-#define MIPS_CPU_ASE_MIPS3D	0x0010	/* CPU implements MIPS-3D ASE */
-#define MIPS_CPU_ASE_MDMX	0x0020	/* CPU implements MDMX ASE */
-#define MIPS_CPU_ASE_DSPR2	0x0040	/* CPU implements DSP R2 ASE */
+#define MIPS_CPU_IS_ISA		  0x0001 /* Is this an ISA?  (If 0, a CPU.) */
+#define MIPS_CPU_ASE_SMARTMIPS	  0x0002 /* CPU implements SmartMIPS ASE */
+#define MIPS_CPU_ASE_DSP	  0x0004 /* CPU implements DSP ASE */
+#define MIPS_CPU_ASE_MT		  0x0008 /* CPU implements MT ASE */
+#define MIPS_CPU_ASE_MIPS3D	  0x0010 /* CPU implements MIPS-3D ASE */
+#define MIPS_CPU_ASE_MDMX	  0x0020 /* CPU implements MDMX ASE */
+#define MIPS_CPU_ASE_DSPR2	  0x0040 /* CPU implements DSP R2 ASE */
+#define MIPS_CPU_FLOAT_OPS_NONE	  0x0080 /* CPU has no FPU */
+#define MIPS_CPU_FLOAT_OPS_SINGLE 0x0100 /* CPU has no 64-bit FPU */
 
 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);
@@ -1750,6 +1780,68 @@ reg_lookup (char **s, unsigned int types
   return reg >= 0;
 }
 
+/* Return TRUE if opcode MO is valid on the currently selected ISA and
+   architecture.  If EXPANSIONP is TRUE then this check is done while
+   expanding a macro.  Use is_opcode_valid_16 for MIPS16 opcodes.  */
+
+static bfd_boolean
+is_opcode_valid (const struct mips_opcode *mo, bfd_boolean expansionp)
+{
+  int isa = mips_opts.isa;
+  int fp_s, fp_d;
+
+  if (mips_opts.ase_mdmx)
+    isa |= INSN_MDMX;
+  if (mips_opts.ase_dsp)
+    isa |= INSN_DSP;
+  if (mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE)
+    isa |= INSN_DSP64;
+  if (mips_opts.ase_dspr2)
+    isa |= INSN_DSPR2;
+  if (mips_opts.ase_mt)
+    isa|= INSN_MT;
+  if (mips_opts.ase_mips3d)
+    isa |= INSN_MIPS3D;
+  if (mips_opts.ase_smartmips)
+    isa |= INSN_SMARTMIPS;
+
+  /* For user code we don't check for mips_opts.mips16 since we want
+     to allow jalx if -mips16 was specified on the command line.  */
+  if (expansionp ? mips_opts.mips16 : file_ase_mips16)
+    isa |= INSN_MIPS16;
+
+  if (!OPCODE_IS_MEMBER (mo, isa, mips_opts.arch))
+    return FALSE;
+
+  if (mo->pinfo == INSN_MACRO)
+    {
+      fp_s = mo->pinfo2 & INSN2_M_FP_S;
+      fp_d = mo->pinfo2 & INSN2_M_FP_D;
+    }
+  else
+    {
+      fp_s = mo->pinfo & FP_S;
+      fp_d = mo->pinfo & FP_D;
+    }
+
+  if (fp_d && (mips_opts.soft_float || mips_opts.single_float))
+    return FALSE;
+
+  if (fp_s && mips_opts.soft_float)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Return TRUE if the MIPS16 opcode MO is valid on the currently
+   selected ISA and architecture.  */
+
+static bfd_boolean
+is_opcode_valid_16 (const struct mips_opcode *mo)
+{
+  return OPCODE_IS_MEMBER (mo, mips_opts.isa, mips_opts.arch) ? TRUE : FALSE;
+}
+
 /* This function is called once, at assembler startup time.  It should set up
    all the tables, etc. that the MD part of the assembler will need.  */
 
@@ -3367,16 +3459,7 @@ macro_build (expressionS *ep, const char
 	 macros will never generate MDMX, MIPS-3D, or MT instructions.  */
       if (strcmp (fmt, mo->args) == 0
 	  && mo->pinfo != INSN_MACRO
-	  && OPCODE_IS_MEMBER (mo,
-			       (mips_opts.isa
-				| (mips_opts.mips16 ? INSN_MIPS16 : 0)
-				| (mips_opts.ase_dsp ? INSN_DSP : 0)
-				| ((mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE)
-				   ? INSN_DSP64 : 0)
-				| (mips_opts.ase_dspr2 ? INSN_DSPR2 : 0)
-				| (mips_opts.ase_smartmips ? INSN_SMARTMIPS : 0)),
-			       mips_opts.arch)
-	  && (mips_opts.arch != CPU_R4650 || (mo->pinfo & FP_D) == 0))
+	  && is_opcode_valid (mo, TRUE))
 	break;
 
       ++mo;
@@ -6120,11 +6203,6 @@ macro (struct mips_cl_insn *ip)
       lr = 1;
       goto ld;
     case M_LDC1_AB:
-      if (mips_opts.arch == CPU_R4650)
-	{
-	  as_bad (_("opcode not supported on this processor"));
-	  break;
-	}
       s = "ldc1";
       /* Itbl support may require additional care here.  */
       coproc = 1;
@@ -6211,11 +6289,6 @@ macro (struct mips_cl_insn *ip)
       s = "cache";
       goto st;
     case M_SDC1_AB:
-      if (mips_opts.arch == CPU_R4650)
-	{
-	  as_bad (_("opcode not supported on this processor"));
-	  break;
-	}
       s = "sdc1";
       coproc = 1;
       /* Itbl support may require additional care here.  */
@@ -6757,11 +6830,6 @@ macro (struct mips_cl_insn *ip)
 	}
 
     case M_L_DOB:
-      if (mips_opts.arch == CPU_R4650)
-	{
-	  as_bad (_("opcode not supported on this processor"));
-	  break;
-	}
       /* Even on a big endian machine $fn comes before $fn+1.  We have
 	 to adjust when loading from memory.  */
       r = BFD_RELOC_LO16;
@@ -6788,11 +6856,6 @@ macro (struct mips_cl_insn *ip)
        * But, the resulting address is the same after relocation so why
        * generate the extra instruction?
        */
-      if (mips_opts.arch == CPU_R4650)
-	{
-	  as_bad (_("opcode not supported on this processor"));
-	  break;
-	}
       /* Itbl support may require additional care here.  */
       coproc = 1;
       if (mips_opts.isa != ISA_MIPS1)
@@ -6806,12 +6869,6 @@ macro (struct mips_cl_insn *ip)
       goto ldd_std;
 
     case M_S_DAB:
-      if (mips_opts.arch == CPU_R4650)
-	{
-	  as_bad (_("opcode not supported on this processor"));
-	  break;
-	}
-
       if (mips_opts.isa != ISA_MIPS1)
 	{
 	  s = "sdc1";
@@ -7456,11 +7513,6 @@ macro2 (struct mips_cl_insn *ip)
       break;
 
     case M_S_DOB:
-      if (mips_opts.arch == CPU_R4650)
-	{
-	  as_bad (_("opcode not supported on this processor"));
-	  break;
-	}
       assert (mips_opts.isa == ISA_MIPS1);
       /* Even on a big endian machine $fn comes before $fn+1.  We have
 	 to adjust when storing to memory.  */
@@ -8452,31 +8504,7 @@ mips_ip (char *str, struct mips_cl_insn 
 
       assert (strcmp (insn->name, str) == 0);
 
-      if (OPCODE_IS_MEMBER (insn,
-			    (mips_opts.isa
-			     /* We don't check for mips_opts.mips16 here since
-			        we want to allow jalx if -mips16 was specified
-			        on the command line.  */
-			     | (file_ase_mips16 ? INSN_MIPS16 : 0)
-	      		     | (mips_opts.ase_mdmx ? INSN_MDMX : 0)
-	      		     | (mips_opts.ase_dsp ? INSN_DSP : 0)
-	      		     | ((mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE)
-				? INSN_DSP64 : 0)
-	      		     | (mips_opts.ase_dspr2 ? INSN_DSPR2 : 0)
-	      		     | (mips_opts.ase_mt ? INSN_MT : 0)
-			     | (mips_opts.ase_mips3d ? INSN_MIPS3D : 0)
-			     | (mips_opts.ase_smartmips ? INSN_SMARTMIPS : 0)),
-			    mips_opts.arch))
-	ok = TRUE;
-      else
-	ok = FALSE;
-
-      if (insn->pinfo != INSN_MACRO)
-	{
-	  if (mips_opts.arch == CPU_R4650 && (insn->pinfo & FP_D) != 0)
-	    ok = FALSE;
-	}
-
+      ok = is_opcode_valid (insn, FALSE);
       if (! ok)
 	{
 	  if (insn + 1 < &mips_opcodes[NUMOPCODES]
@@ -9824,11 +9852,7 @@ mips16_ip (char *str, struct mips_cl_ins
 
       assert (strcmp (insn->name, str) == 0);
 
-      if (OPCODE_IS_MEMBER (insn, mips_opts.isa, mips_opts.arch))
-	ok = TRUE;
-      else
-	ok = FALSE;
-
+      ok = is_opcode_valid_16 (insn);
       if (! ok)
 	{
 	  if (insn + 1 < &mips16_opcodes[bfd_mips16_num_opcodes]
@@ -10957,10 +10981,18 @@ #define OPTION_MSYM32 (OPTION_MISC_BASE 
 #define OPTION_MNO_SYM32 (OPTION_MISC_BASE + 15)
   {"msym32", no_argument, NULL, OPTION_MSYM32},
   {"mno-sym32", no_argument, NULL, OPTION_MNO_SYM32},
-
+#define OPTION_SOFT_FLOAT (OPTION_MISC_BASE + 16)
+#define OPTION_HARD_FLOAT (OPTION_MISC_BASE + 17)
+  {"msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT},
+  {"mhard-float", no_argument, NULL, OPTION_HARD_FLOAT},
+#define OPTION_SINGLE_FLOAT (OPTION_MISC_BASE + 18)
+#define OPTION_DOUBLE_FLOAT (OPTION_MISC_BASE + 19)
+  {"msingle-float", no_argument, NULL, OPTION_SINGLE_FLOAT},
+  {"mdouble-float", no_argument, NULL, OPTION_DOUBLE_FLOAT},
+  
   /* ELF-specific options.  */
 #ifdef OBJ_ELF
-#define OPTION_ELF_BASE    (OPTION_MISC_BASE + 16)
+#define OPTION_ELF_BASE    (OPTION_MISC_BASE + 20)
 #define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
   {"KPIC",        no_argument, NULL, OPTION_CALL_SHARED},
   {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
@@ -11320,6 +11352,22 @@ md_parse_option (int c, char *arg)
       file_mips_fp32 = 0;
       break;
 
+    case OPTION_SINGLE_FLOAT:
+      file_mips_single_float = 1;
+      break;
+
+    case OPTION_DOUBLE_FLOAT:
+      file_mips_single_float = 0;
+      break;
+
+    case OPTION_SOFT_FLOAT:
+      file_mips_soft_float = 1;
+      break;
+
+    case OPTION_HARD_FLOAT:
+      file_mips_soft_float = 0;
+      break;
+
 #ifdef OBJ_ELF
     case OPTION_MABI:
       if (!IS_ELF)
@@ -11534,6 +11582,12 @@ mips_after_parse_args (void)
 
   /* End of GCC-shared inference code.  */
 
+  if (file_mips_soft_float == -1)
+    file_mips_soft_float = CPU_SOFT_FLOAT (arch_info->flags);
+
+  if (file_mips_single_float == -1)
+    file_mips_single_float = CPU_SINGLE_FLOAT (arch_info->flags);
+
   /* This flag is set when we have a 64-bit capable CPU but use only
      32-bit wide registers.  Note that EABI does not use it.  */
   if (ISA_HAS_64BIT_REGS (mips_opts.isa)
@@ -11597,6 +11651,8 @@ mips_after_parse_args (void)
   file_ase_mt = mips_opts.ase_mt;
   mips_opts.gp32 = file_mips_gp32;
   mips_opts.fp32 = file_mips_fp32;
+  mips_opts.soft_float = file_mips_soft_float;
+  mips_opts.single_float = file_mips_single_float;
 
   if (mips_flag_mdebug < 0)
     {
@@ -12473,6 +12529,14 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
 		 mips_cpu_info_from_isa (mips_opts.isa)->name);
       mips_opts.fp32 = 0;
     }
+  else if (strcmp (name, "softfloat") == 0)
+    mips_opts.soft_float = 1;
+  else if (strcmp (name, "hardfloat") == 0)
+    mips_opts.soft_float = 0;
+  else if (strcmp (name, "singlefloat") == 0)
+    mips_opts.single_float = 1;
+  else if (strcmp (name, "doublefloat") == 0)
+    mips_opts.single_float = 0;
   else if (strcmp (name, "mips16") == 0
 	   || strcmp (name, "MIPS-16") == 0)
     mips_opts.mips16 = 1;
@@ -12534,6 +12598,7 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
   else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0)
     {
       int reset = 0;
+      const struct mips_cpu_info *arch_info;
 
       /* Permit the user to change the ISA and architecture on the fly.
 	 Needless to say, misuse can cause serious problems.  */
@@ -12545,28 +12610,24 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
 	}
       else if (strncmp (name, "arch=", 5) == 0)
 	{
-	  const struct mips_cpu_info *p;
-
-	  p = mips_parse_cpu("internal use", name + 5);
-	  if (!p)
+	  arch_info = mips_parse_cpu("internal use", name + 5);
+	  if (!arch_info)
 	    as_bad (_("unknown architecture %s"), name + 5);
 	  else
 	    {
-	      mips_opts.arch = p->cpu;
-	      mips_opts.isa = p->isa;
+	      mips_opts.arch = arch_info->cpu;
+	      mips_opts.isa = arch_info->isa;
 	    }
 	}
       else if (strncmp (name, "mips", 4) == 0)
 	{
-	  const struct mips_cpu_info *p;
-
-	  p = mips_parse_cpu("internal use", name);
-	  if (!p)
+	  arch_info = mips_parse_cpu("internal use", name);
+	  if (!arch_info)
 	    as_bad (_("unknown ISA level %s"), name + 4);
 	  else
 	    {
-	      mips_opts.arch = p->cpu;
-	      mips_opts.isa = p->isa;
+	      mips_opts.arch = arch_info->cpu;
+	      mips_opts.isa = arch_info->isa;
 	    }
 	}
       else
@@ -12595,10 +12656,16 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
 	  as_bad (_("unknown ISA level %s"), name + 4);
 	  break;
 	}
+
+      mips_opts.soft_float = CPU_SOFT_FLOAT (arch_info->flags);
+      mips_opts.single_float = CPU_SINGLE_FLOAT (arch_info->flags);
+
       if (reset)
 	{
 	  mips_opts.gp32 = file_mips_gp32;
 	  mips_opts.fp32 = file_mips_fp32;
+	  mips_opts.soft_float = file_mips_soft_float;
+	  mips_opts.single_float = file_mips_single_float;
 	}
     }
   else if (strcmp (name, "autoextend") == 0)
@@ -14770,7 +14837,7 @@ static const struct mips_cpu_info mips_c
   { "r4400",          0,			ISA_MIPS3,      CPU_R4400 },
   { "r4600",          0,			ISA_MIPS3,      CPU_R4600 },
   { "orion",          0,			ISA_MIPS3,      CPU_R4600 },
-  { "r4650",          0,			ISA_MIPS3,      CPU_R4650 },
+  { "r4650",          MIPS_CPU_FLOAT_OPS_SINGLE, ISA_MIPS3,      CPU_R4650 },
 
   /* MIPS IV */
   { "r8000",          0,			ISA_MIPS4,      CPU_R8000 },
@@ -14866,7 +14933,8 @@ static const struct mips_cpu_info mips_c
   { "loongson2f",     0,      ISA_MIPS3,      CPU_LOONGSON_2F },
 
   /* Cavium Networks Octeon CPU core */
-  { "octeon",	      0,      ISA_MIPS64R2,   CPU_OCTEON },
+  { "octeon",	      MIPS_CPU_FLOAT_OPS_NONE,
+					      ISA_MIPS64R2,   CPU_OCTEON },
 
   /* End marker */
   { NULL, 0, 0, 0 }
@@ -15094,9 +15162,15 @@ MIPS options:\n\
 -msym32			assume all symbols have 32-bit values\n\
 -O0			remove unneeded NOPs, do not swap branches\n\
 -O			remove unneeded NOPs and swap branches\n\
---[no-]construct-floats [dis]allow floating point values to be constructed\n\
 --trap, --no-break	trap exception on div by 0 and mult overflow\n\
 --break, --no-trap	break exception on div by 0 and mult overflow\n"));
+  fprintf (stream, _("\
+-mhard-float		allow floating-point instructions\n\
+-msoft-float		do not allow floating-point instructions\n\
+-msingle-float		only allow 32-bit floating-point operations\n\
+-mdouble-float		allow 32-bit and 64-bit floating-point operations\n\
+--[no-]construct-floats [dis]allow floating point values to be constructed\n"
+		     ));
 #ifdef OBJ_ELF
   fprintf (stream, _("\
 -KPIC, -call_shared	generate SVR4 position independent code\n\
Index: gas/doc/c-mips.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-mips.texi,v
retrieving revision 1.44
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.44 c-mips.texi
--- gas/doc/c-mips.texi	29 Nov 2007 12:23:44 -0000	1.44
+++ gas/doc/c-mips.texi	15 Feb 2008 21:08:30 -0000
@@ -32,6 +32,7 @@ Assembly Language Programming'' in the s
 * MIPS option stack::	Directives to save and restore options
 * MIPS ASE instruction generation overrides:: Directives to control
   			generation of MIPS ASE instructions
+* MIPS floating-point:: Directives to override floating-point options
 @end menu
 
 @node MIPS Opts
@@ -272,7 +273,8 @@ 25kf,
 sb1,
 sb1a,
 loongson2e,
-loongson2f
+loongson2f,
+octeon
 @end quotation
 
 For compatibility reasons, @samp{@var{n}x} and @samp{@var{b}fx} are
@@ -301,10 +303,19 @@ other assemblers, which use it to turn o
 @sc{gnu} @code{@value{AS}}, there is no need for @samp{-nocpp}, because the
 @sc{gnu} assembler itself never runs the C preprocessor.
 
+@item -msoft-float
+@itemx -mhard-float
+Disable or enable floating-point instructions.  The default is set based
+on the CPU target.  These options are provided to override the default.
+
+@item -msingle-float
+@itemx -mdouble-float
+Disable or enable double-precision floating-point operations.  The
+default is set based on the CPU target.  These options are provided to
+override the default.
+
 @item --construct-floats
 @itemx --no-construct-floats
-@cindex --construct-floats
-@cindex --no-construct-floats
 The @code{--no-construct-floats} option disables the construction of
 double width floating point constants by loading the two halves of the
 value into the two single width floating point registers that make up
@@ -579,3 +590,24 @@ in the assembly.  The @code{.set nomt} d
 instructions from being accepted.
 
 Traditional @sc{mips} assemblers do not support these directives.
+
+@node MIPS floating-point
+@section Directives to override floating-point options
+
+@cindex Disable floating-point instructions
+@kindex @code{.set softfloat}
+@kindex @code{.set hardfloat}
+Regardless of the selected ISA or CPU target the directive @code{.set
+softfloat} disables all floating-point operations.  @code{.set
+hardfloat} makes the assembler accept all floating-point instructions
+according to the selected ISA or CPU target.
+
+@cindex Disable single-precision floating-point operations
+@kindex @code{.set softfloat}
+@kindex @code{.set hardfloat}
+Regardless of the selected ISA or CPU target the directive @code{.set
+singlefloat} disables double-precision floatig-point operations.
+@code{.set doublefloat} makes the assembler accept both single- and
+double-precision operations.
+
+Traditional @sc{mips} assemblers do not support these directives.
Index: gas/testsuite/gas/mips/fpr-names-32.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/fpr-names-32.d,v
retrieving revision 1.1
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.1 fpr-names-32.d
--- gas/testsuite/gas/mips/fpr-names-32.d	27 Dec 2002 08:00:30 -0000	1.1
+++ gas/testsuite/gas/mips/fpr-names-32.d	15 Feb 2008 21:08:30 -0000
@@ -1,6 +1,7 @@
 #objdump: -dr --prefix-addresses --show-raw-insn -M gpr-names=numeric,fpr-names=32
 #name: MIPS FPR disassembly (32)
 #source: fpr-names.s
+#as: -mips1 -32
 
 # Check objdump's handling of -M fpr-names=foo options.
 
Index: gas/testsuite/gas/mips/fpr-names-64.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/fpr-names-64.d,v
retrieving revision 1.1
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.1 fpr-names-64.d
--- gas/testsuite/gas/mips/fpr-names-64.d	27 Dec 2002 08:00:30 -0000	1.1
+++ gas/testsuite/gas/mips/fpr-names-64.d	15 Feb 2008 21:08:30 -0000
@@ -1,6 +1,7 @@
 #objdump: -dr --prefix-addresses --show-raw-insn -M gpr-names=numeric,fpr-names=64
 #name: MIPS FPR disassembly (64)
 #source: fpr-names.s
+#as: -mips64 -64
 
 # Check objdump's handling of -M fpr-names=foo options.
 
Index: gas/testsuite/gas/mips/fpr-names-n32.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/fpr-names-n32.d,v
retrieving revision 1.1
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.1 fpr-names-n32.d
--- gas/testsuite/gas/mips/fpr-names-n32.d	27 Dec 2002 08:00:30 -0000	1.1
+++ gas/testsuite/gas/mips/fpr-names-n32.d	15 Feb 2008 21:08:31 -0000
@@ -1,6 +1,7 @@
 #objdump: -dr --prefix-addresses --show-raw-insn -M gpr-names=numeric,fpr-names=n32
 #name: MIPS FPR disassembly (n32)
 #source: fpr-names.s
+#as: -mips64 -n32
 
 # Check objdump's handling of -M fpr-names=foo options.
 
Index: gas/testsuite/gas/mips/fpr-names-numeric.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/fpr-names-numeric.d,v
retrieving revision 1.1
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.1 fpr-names-numeric.d
--- gas/testsuite/gas/mips/fpr-names-numeric.d	27 Dec 2002 08:00:30 -0000	1.1
+++ gas/testsuite/gas/mips/fpr-names-numeric.d	15 Feb 2008 21:08:31 -0000
@@ -1,6 +1,7 @@
 #objdump: -dr --prefix-addresses --show-raw-insn -M gpr-names=numeric,fpr-names=numeric
 #name: MIPS FPR disassembly (numeric)
 #source: fpr-names.s
+#as: -mips1 -32
 
 # Check objdump's handling of -M fpr-names=foo options.
 
Index: gas/testsuite/gas/mips/mips-double-float-flag.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips-double-float-flag.l
diff -N gas/testsuite/gas/mips/mips-double-float-flag.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips-double-float-flag.l	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*:8: Error: opcode not supported on this processor: .* \(.*\) `add.d \$f2,\$f2,\$f2'
+.*:17: Error: opcode not supported on this processor: .* \(.*\) `add.d \$f2,\$f2,\$f2'
Index: gas/testsuite/gas/mips/mips-double-float-flag.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips-double-float-flag.s
diff -N gas/testsuite/gas/mips/mips-double-float-flag.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips-double-float-flag.s	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,17 @@
+	.text
+foo:
+	add.s	$f2,$f2,$f2
+	add.d	$f2,$f2,$f2
+
+	.set singlefloat
+	add.s	$f2,$f2,$f2
+	add.d	$f2,$f2,$f2
+	.set push
+
+	.set doublefloat
+	add.s	$f2,$f2,$f2
+	add.d	$f2,$f2,$f2
+
+	.set pop
+	add.s	$f2,$f2,$f2
+	add.d	$f2,$f2,$f2
Index: gas/testsuite/gas/mips/mips-hard-float-flag.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips-hard-float-flag.l
diff -N gas/testsuite/gas/mips/mips-hard-float-flag.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips-hard-float-flag.l	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,5 @@
+.*: Assembler messages:
+.*:7: Error: opcode not supported on this processor: .* \(.*\) `add.s \$f2,\$f2,\$f2'
+.*:8: Error: opcode not supported on this processor: .* \(.*\) `add.d \$f2,\$f2,\$f2'
+.*:16: Error: opcode not supported on this processor: .* \(.*\) `add.s \$f2,\$f2,\$f2'
+.*:17: Error: opcode not supported on this processor: .* \(.*\) `add.d \$f2,\$f2,\$f2'
Index: gas/testsuite/gas/mips/mips-hard-float-flag.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips-hard-float-flag.s
diff -N gas/testsuite/gas/mips/mips-hard-float-flag.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips-hard-float-flag.s	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,17 @@
+	.text
+foo:
+	add.s	$f2,$f2,$f2
+	add.d	$f2,$f2,$f2
+	
+	.set softfloat
+	add.s	$f2,$f2,$f2
+	add.d	$f2,$f2,$f2
+	.set push
+
+	.set hardfloat
+	add.s	$f2,$f2,$f2
+	add.d	$f2,$f2,$f2
+
+	.set pop
+	add.s	$f2,$f2,$f2
+	add.d	$f2,$f2,$f2
Index: gas/testsuite/gas/mips/mips-macro-ill-nofp.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips-macro-ill-nofp.l
diff -N gas/testsuite/gas/mips/mips-macro-ill-nofp.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips-macro-ill-nofp.l	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,19 @@
+.*: Assembler messages:
+.*:5: Error: opcode not supported on this processor: .* \(.*\) `ldc1 \$f2,d'
+.*:6: Error: opcode not supported on this processor: .* \(.*\) `ldc1 \$22,d'
+.*:7: Error: opcode not supported on this processor: .* \(.*\) `l.d \$f2,d'
+.*:8: Error: opcode not supported on this processor: .* \(.*\) `li.d \$f2,1.2'
+.*:9: Error: opcode not supported on this processor: .* \(.*\) `li.d \$22,1.2'
+.*:11: Error: opcode not supported on this processor: .* \(.*\) `sdc1 \$f2,d'
+.*:12: Error: opcode not supported on this processor: .* \(.*\) `sdc1 \$22,d'
+.*:13: Error: opcode not supported on this processor: .* \(.*\) `s.d \$f2,d'
+.*:15: Error: opcode not supported on this processor: .* \(.*\) `trunc.w.d \$f4,\$f6,\$4'
+.*:18: Error: opcode not supported on this processor: .* \(.*\) `lwc1 \$f2,d'
+.*:19: Error: opcode not supported on this processor: .* \(.*\) `lwc1 \$22,d'
+.*:20: Error: opcode not supported on this processor: .* \(.*\) `l.s \$f2,d'
+.*:21: Error: opcode not supported on this processor: .* \(.*\) `li.s \$f2,1.2'
+.*:22: Error: opcode not supported on this processor: .* \(.*\) `li.s \$22,1.2'
+.*:24: Error: opcode not supported on this processor: .* \(.*\) `sdc1 \$f2,d'
+.*:25: Error: opcode not supported on this processor: .* \(.*\) `sdc1 \$22,d'
+.*:26: Error: opcode not supported on this processor: .* \(.*\) `s.d \$f2,d'
+.*:28: Error: opcode not supported on this processor: .* \(.*\) `trunc.w.s \$f4,\$f6,\$4'
Index: gas/testsuite/gas/mips/mips-macro-ill-nofp.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips-macro-ill-nofp.s
diff -N gas/testsuite/gas/mips/mips-macro-ill-nofp.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips-macro-ill-nofp.s	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,32 @@
+# Macros that are disabled for chips without an FPU.
+	
+	.text
+double_float:
+	ldc1	$f2, d
+	ldc1	$22, d
+	l.d	$f2, d
+	li.d	$f2, 1.2 
+	li.d	$22, 1.2
+
+	sdc1	$f2, d
+	sdc1	$22, d
+	s.d	$f2, d
+
+	trunc.w.d $f4,$f6,$4
+
+single_float:
+	lwc1	$f2, d
+	lwc1	$22, d
+	l.s	$f2, d
+	li.s	$f2, 1.2 
+	li.s	$22, 1.2
+
+	sdc1	$f2, d
+	sdc1	$22, d
+	s.d	$f2, d
+
+	trunc.w.s $f4,$f6,$4
+
+d:
+	.word 0
+	.word 0
Index: gas/testsuite/gas/mips/mips-macro-ill-sfp.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips-macro-ill-sfp.l
diff -N gas/testsuite/gas/mips/mips-macro-ill-sfp.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips-macro-ill-sfp.l	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,10 @@
+.*: Assembler messages:
+.*:5: Error: opcode not supported on this processor: .* \(.*\) `ldc1 \$f2,d'
+.*:6: Error: opcode not supported on this processor: .* \(.*\) `ldc1 \$22,d'
+.*:7: Error: opcode not supported on this processor: .* \(.*\) `l.d \$f2,d'
+.*:8: Error: opcode not supported on this processor: .* \(.*\) `li.d \$f2,1.2'
+.*:9: Error: opcode not supported on this processor: .* \(.*\) `li.d \$22,1.2'
+.*:11: Error: opcode not supported on this processor: .* \(.*\) `sdc1 \$f2,d'
+.*:12: Error: opcode not supported on this processor: .* \(.*\) `sdc1 \$22,d'
+.*:13: Error: opcode not supported on this processor: .* \(.*\) `s.d \$f2,d'
+.*:15: Error: opcode not supported on this processor: .* \(.*\) `trunc.w.d \$f4,\$f6,\$4'
Index: gas/testsuite/gas/mips/mips-macro-ill-sfp.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips-macro-ill-sfp.s
diff -N gas/testsuite/gas/mips/mips-macro-ill-sfp.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips-macro-ill-sfp.s	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,19 @@
+# Macros that are disabled for chips without a 64-bit FPU.
+	
+	.text
+double_float:
+	ldc1	$f2, d
+	ldc1	$22, d
+	l.d	$f2, d
+	li.d	$f2, 1.2 
+	li.d	$22, 1.2
+
+	sdc1	$f2, d
+	sdc1	$22, d
+	s.d	$f2, d
+
+	trunc.w.d $f4,$f6,$4
+
+d:
+	.word 0
+	.word 0
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.137
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.137 mips.exp
--- gas/testsuite/gas/mips/mips.exp	6 Feb 2008 05:29:03 -0000	1.137
+++ gas/testsuite/gas/mips/mips.exp	15 Feb 2008 21:08:31 -0000
@@ -67,6 +67,12 @@
 #		The architecture provides 32- or 64-bit General Purpose
 #		Registers.
 #
+#       soft_float
+#               The architecture provides no FPU.
+#
+#       single_float
+#               The architecture provides a single-precision FPU.
+#
 # as_flags: The assembler flags used when assembling tests for this
 # architecture.
 #
@@ -356,12 +362,14 @@ mips_arch_create r3900 	32	mips1	{ gpr_i
 			{ mipstx39-*-* mipstx39el-*-* }
 mips_arch_create r4000 	64	mips3	{} \
 			{ -march=r4000 -mtune=r4000 } { -mmips:4000 }
+mips_arch_create r4650 	64	mips3	{ single_float } \
+			{ -march=r4650 -mtune=r4650 } { -mmips:4650 }
 mips_arch_create vr5400	64	mips4	{ ror } \
 			{ -march=vr5400 -mtune=vr5400 } { -mmips:5400 }
 mips_arch_create sb1 	64	mips64	{ mips3d } \
 			{ -march=sb1 -mtune=sb1 } { -mmips:sb1 } \
 			{ mipsisa64sb1-*-* mipsisa64sb1el-*-* }
-mips_arch_create octeon 64	mips64r2 {} \
+mips_arch_create octeon 64	mips64r2 { soft_float } \
 			{ -march=octeon -mtune=octeon } { -mmips:octeon } \
 			{ mips64octeon*-*-* }
 
@@ -475,7 +483,12 @@ if { [istarget mips*-*-vxworks*] } {
     if $elf { run_dump_test "lif-svr4pic" }
     if $elf { run_dump_test "lif-xgot" }
     run_dump_test_arches "mips4"	[mips_arch_list_matching mips4]
-    run_dump_test_arches "mips5"	[mips_arch_list_matching mips5]
+    run_dump_test_arches "mips4-fp"	[mips_arch_list_matching mips4 \
+					     !soft_float]
+    run_list_test_arches "mips4-fp" "-32" [mips_arch_list_matching mips4 \
+					     soft_float]
+    run_dump_test_arches "mips5"	[mips_arch_list_matching mips5 \
+					     !soft_float]
     if $ilocks {
 	run_dump_test "mul-ilocks"
     } else {
@@ -545,13 +558,22 @@ if { [istarget mips*-*-vxworks*] } {
 
     run_dump_test_arches "mips32"	[mips_arch_list_matching mips32]
 
-    run_dump_test_arches "mips32-sf32"	[mips_arch_list_matching mips32]
+    run_dump_test_arches "mips32-sf32" \
+	[mips_arch_list_matching mips32 !soft_float]
+    run_list_test_arches "mips32-sf32" "-32" \
+	[mips_arch_list_matching mips32 soft_float]
 
     run_dump_test_arches "mips32r2"	[mips_arch_list_matching mips32r2]
+    run_dump_test_arches "mips32r2-fp32" \
+	[mips_arch_list_matching mips32r2 !soft_float]
+    run_list_test_arches "mips32r2-fp32" "-32" \
+	[mips_arch_list_matching mips32r2 soft_float]
     run_list_test_arches "mips32r2-ill" "-32" \
-			 [mips_arch_list_matching mips32r2 gpr32]
+	[mips_arch_list_matching mips32r2 gpr32 !soft_float]
     run_list_test_arches "mips32r2-ill-fp64" "-mabi=o64" \
-			 [mips_arch_list_matching mips32r2 gpr64]
+	[mips_arch_list_matching mips32r2 gpr64 !soft_float]
+    run_list_test_arches "mips32r2-ill-nofp" "-32" \
+	[mips_arch_list_matching mips32r2 soft_float]
 
     run_dump_test_arches "mips64"	[mips_arch_list_matching mips64]
 
@@ -574,7 +596,7 @@ if { [istarget mips*-*-vxworks*] } {
     run_dump_test "relax-swap1-mips2"
     run_dump_test "relax-swap2"
 
-    run_list_test "illegal" "-32"
+    run_list_test "illegal" "-mips1 -32"
     run_list_test "baddata1" "-32"
     run_list_test "jalr" ""
 
@@ -622,7 +644,8 @@ if { [istarget mips*-*-vxworks*] } {
   	run_dump_test "mips-abi32-pic2"
 
 	run_dump_test "elf${el}-rel"
-	run_dump_test_arches "elf${el}-rel2" [mips_arch_list_matching gpr64]
+	run_dump_test_arches "elf${el}-rel2" \
+	    [mips_arch_list_matching gpr64 !soft_float !single_float]
 	run_dump_test "e32${el}-rel2"
 	run_dump_test "elf${el}-rel3"
 	run_dump_test_arches "elf-rel4" [mips_arch_list_matching gpr64]
@@ -795,4 +818,18 @@ if { [istarget mips*-*-vxworks*] } {
     run_dump_test "align2"
     run_dump_test "align2-el"
     run_dump_test "odd-float"
+
+    run_list_test_arches "mips-macro-ill-sfp" "" \
+	[mips_arch_list_matching single_float]
+    run_list_test_arches "mips-macro-ill-sfp" "-32 -msingle-float" \
+	[mips_arch_list_matching !single_float]
+    run_list_test_arches "mips-macro-ill-nofp" "" \
+	[mips_arch_list_matching soft_float]
+    run_list_test_arches "mips-macro-ill-nofp" "-32 -msoft-float" \
+	[mips_arch_list_matching !soft_float]
+
+    run_list_test_arches "mips-hard-float-flag" "-mhard-float" \
+	[mips_arch_list_matching soft_float]
+    run_list_test_arches "mips-double-float-flag" "-mdouble-float" \
+	[mips_arch_list_matching single_float]
 }
Index: gas/testsuite/gas/mips/mips32-sf32.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips32-sf32.l
diff -N gas/testsuite/gas/mips/mips32-sf32.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32-sf32.l	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,8 @@
+.*: Assembler messages:
+.*:5: Error: opcode not supported on this processor: .* \(.*\) `li.s \$f1,1.0'
+.*:6: Error: opcode not supported on this processor: .* \(.*\) `li.s \$f3,1.9'
+.*:7: Error: opcode not supported on this processor: .* \(.*\) `add.s \$f5,\$f1,\$f3'
+.*:8: Error: opcode not supported on this processor: .* \(.*\) `cvt.d.s \$f8,\$f7'
+.*:9: Error: opcode not supported on this processor: .* \(.*\) `cvt.d.w \$f8,\$f7'
+.*:10: Error: opcode not supported on this processor: .* \(.*\) `cvt.s.d \$f7,\$f8'
+.*:11: Error: opcode not supported on this processor: .* \(.*\) `trunc.w.d \$f7,\$f8'
Index: gas/testsuite/gas/mips/mips32r2-fp32.d
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2-fp32.d
diff -N gas/testsuite/gas/mips/mips32r2-fp32.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2-fp32.d	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,12 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -M reg-names=numeric
+#name: MIPS MIPS32r2 fp instructions
+#as: -32
+
+# Check MIPS32 Release 2 (mips32r2) FP instruction assembly
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> 44710000 	mfhc1	\$17,\$f0
+0+0004 <[^>]*> 44f10000 	mthc1	\$17,\$f0
+#pass
Index: gas/testsuite/gas/mips/mips32r2-fp32.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2-fp32.l
diff -N gas/testsuite/gas/mips/mips32r2-fp32.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2-fp32.l	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*:12: Error: opcode not supported on this processor: .* \(.*\) `mfhc1 \$17,\$f0'
+.*:13: Error: opcode not supported on this processor: .* \(.*\) `mthc1 \$17,\$f0'
Index: gas/testsuite/gas/mips/mips32r2-fp32.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2-fp32.s
diff -N gas/testsuite/gas/mips/mips32r2-fp32.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2-fp32.s	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,13 @@
+# source file to test assembly of mips32r2 FP instructions
+
+	.text
+text_label:
+
+      # FPU (cp1) instructions
+      #
+      # Even registers are supported w/ 32-bit FPU, odd
+      # registers supported only for 64-bit FPU.
+      # Only the 32-bit FPU instructions are tested here.
+     
+	mfhc1	$17, $f0
+	mthc1	$17, $f0
Index: gas/testsuite/gas/mips/mips32r2-ill-nofp.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2-ill-nofp.l
diff -N gas/testsuite/gas/mips/mips32r2-ill-nofp.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2-ill-nofp.l	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,13 @@
+.*: Assembler messages:
+.*:12: Error: Improper position \([0-9]*\)
+.*:15: Error: Improper position \(32\)
+.*:18: Error: Improper extract size \(0, position 0\)
+.*:21: Error: Improper extract size \(33, position 0\)
+.*:24: Error: Improper extract size \(0, position 0\)
+.*:27: Error: Improper extract size \(2, position 31\)
+.*:30: Error: Improper position \([0-9]*\)
+.*:33: Error: Improper position \(32\)
+.*:36: Error: Improper insert size \(0, position 0\)
+.*:39: Error: Improper insert size \(33, position 0\)
+.*:42: Error: Improper insert size \(0, position 0\)
+.*:45: Error: Improper insert size \(2, position 31\)
Index: gas/testsuite/gas/mips/mips32r2-ill-nofp.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2-ill-nofp.s
diff -N gas/testsuite/gas/mips/mips32r2-ill-nofp.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2-ill-nofp.s	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,48 @@
+# source file to test illegal mips32r2 instructions
+
+        .set noreorder
+      .set noat
+
+      .text
+text_label:
+
+      # insert and extract position/size checks:
+
+	# ext constraint: 0 <= pos < 32
+	ext	$4, $5, -1, 1		# error
+	ext	$4, $5, 0, 1
+	ext	$4, $5, 31, 1
+	ext	$4, $5, 32, 1		# error
+
+	# ext constraint: 0 < size <= 32
+	ext	$4, $5, 0, 0		# error
+	ext	$4, $5, 0, 1
+	ext	$4, $5, 0, 32
+	ext	$4, $5, 0, 33		# error
+
+	# ext constraint: 0 < (pos+size) <= 32
+	ext	$4, $5, 0, 0		# error
+	ext	$4, $5, 0, 1
+	ext	$4, $5, 31, 1
+	ext	$4, $5, 31, 2		# error
+
+	# ins constraint: 0 <= pos < 32
+	ins	$4, $5, -1, 1		# error
+	ins	$4, $5, 0, 1
+	ins	$4, $5, 31, 1
+	ins	$4, $5, 32, 1		# error
+
+	# ins constraint: 0 < size <= 32
+	ins	$4, $5, 0, 0		# error
+	ins	$4, $5, 0, 1
+	ins	$4, $5, 0, 32
+	ins	$4, $5, 0, 33		# error
+
+	# ins constraint: 0 < (pos+size) <= 32
+	ins	$4, $5, 0, 0		# error
+	ins	$4, $5, 0, 1
+	ins	$4, $5, 31, 1
+	ins	$4, $5, 31, 2		# error
+
+# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
+	.space  8
Index: gas/testsuite/gas/mips/mips32r2.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips32r2.d,v
retrieving revision 1.3
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.3 mips32r2.d
--- gas/testsuite/gas/mips/mips32r2.d	7 May 2003 05:08:20 -0000	1.3
+++ gas/testsuite/gas/mips/mips32r2.d	15 Feb 2008 21:08:31 -0000
@@ -1,8 +1,8 @@
 #objdump: -dr --prefix-addresses --show-raw-insn -M reg-names=numeric
-#name: MIPS MIPS32r2 instructions
+#name: MIPS MIPS32r2 non-fp instructions
 #as: -32
 
-# Check MIPS32 Release 2 (mips32r2) instruction assembly
+# Check MIPS32 Release 2 (mips32r2) *non-fp* instruction assembly
 
 .*: +file format .*mips.*
 
@@ -40,8 +40,6 @@ 0+0074 <[^>]*> 41606020 	ei
 0+0078 <[^>]*> 416a6020 	ei	\$10
 0+007c <[^>]*> 41595000 	rdpgpr	\$10,\$25
 0+0080 <[^>]*> 41d95000 	wrpgpr	\$10,\$25
-0+0084 <[^>]*> 44710000 	mfhc1	\$17,\$f0
-0+0088 <[^>]*> 44f10000 	mthc1	\$17,\$f0
-0+008c <[^>]*> 48715555 	mfhc2	\$17,0x5555
-0+0090 <[^>]*> 48f15555 	mthc2	\$17,0x5555
+0+0084 <[^>]*> 48715555 	mfhc2	\$17,0x5555
+0+0088 <[^>]*> 48f15555 	mthc2	\$17,0x5555
 	...
Index: gas/testsuite/gas/mips/mips32r2.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips32r2.s,v
retrieving revision 1.1
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.1 mips32r2.s
--- gas/testsuite/gas/mips/mips32r2.s	31 Dec 2002 07:29:28 -0000	1.1
+++ gas/testsuite/gas/mips/mips32r2.s	15 Feb 2008 21:08:31 -0000
@@ -1,4 +1,4 @@
-# source file to test assembly of mips32r2 instructions
+# source file to test assembly of mips32r2 *non-fp* instructions
 
         .set noreorder
 	.set noat
@@ -63,15 +63,6 @@ text_label:
 
 	wrpgpr	$10, $25
 
-      # FPU (cp1) instructions
-      #
-      # Even registers are supported w/ 32-bit FPU, odd
-      # registers supported only for 64-bit FPU.
-      # Only the 32-bit FPU instructions are tested here.
-     
-	mfhc1	$17, $f0
-	mthc1	$17, $f0
-
       # cp2 instructions
 
 	mfhc2	$17, 0x5555
Index: gas/testsuite/gas/mips/mips4-fp.d
===================================================================
RCS file: gas/testsuite/gas/mips/mips4-fp.d
diff -N gas/testsuite/gas/mips/mips4-fp.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips4-fp.d	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,48 @@
+#objdump: -dr --prefix-addresses
+#name: MIPS mips4 fp
+
+# Test mips4 fp instructions.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> bc1f	00000000+ <text_label>
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> bc1f	\$fcc1,00000000+ <text_label>
+0+000c <[^>]*> nop
+0+0010 <[^>]*> bc1fl	\$fcc1,00000000+ <text_label>
+0+0014 <[^>]*> nop
+0+0018 <[^>]*> bc1t	\$fcc1,00000000+ <text_label>
+0+001c <[^>]*> nop
+0+0020 <[^>]*> bc1tl	\$fcc2,00000000+ <text_label>
+0+0024 <[^>]*> nop
+0+0028 <[^>]*> c.f.d	\$f4,\$f6
+0+002c <[^>]*> c.f.d	\$fcc1,\$f4,\$f6
+0+0030 <[^>]*> ldxc1	\$f2,a0\(a1\)
+0+0034 <[^>]*> lwxc1	\$f2,a0\(a1\)
+0+0038 <[^>]*> madd.d	\$f0,\$f2,\$f4,\$f6
+0+003c <[^>]*> madd.s	\$f10,\$f8,\$f2,\$f0
+0+0040 <[^>]*> movf	a0,a1,\$fcc4
+0+0044 <[^>]*> movf.d	\$f4,\$f6,\$fcc0
+0+0048 <[^>]*> movf.s	\$f4,\$f6,\$fcc0
+0+004c <[^>]*> movn.d	\$f4,\$f6,a2
+0+0050 <[^>]*> movn.s	\$f4,\$f6,a2
+0+0054 <[^>]*> movt	a0,a1,\$fcc4
+0+0058 <[^>]*> movt.d	\$f4,\$f6,\$fcc0
+0+005c <[^>]*> movt.s	\$f4,\$f6,\$fcc0
+0+0060 <[^>]*> movz.d	\$f4,\$f6,a2
+0+0064 <[^>]*> movz.s	\$f4,\$f6,a2
+0+0068 <[^>]*> msub.d	\$f0,\$f2,\$f4,\$f6
+0+006c <[^>]*> msub.s	\$f0,\$f2,\$f4,\$f6
+0+0070 <[^>]*> nmadd.d	\$f0,\$f2,\$f4,\$f6
+0+0074 <[^>]*> nmadd.s	\$f0,\$f2,\$f4,\$f6
+0+0078 <[^>]*> nmsub.d	\$f0,\$f2,\$f4,\$f6
+0+007c <[^>]*> nmsub.s	\$f0,\$f2,\$f4,\$f6
+0+0080 <[^>]*> prefx	0x4,a0\(a1\)
+0+0084 <[^>]*> recip.d	\$f4,\$f6
+0+0088 <[^>]*> recip.s	\$f4,\$f6
+0+008c <[^>]*> rsqrt.d	\$f4,\$f6
+0+0090 <[^>]*> rsqrt.s	\$f4,\$f6
+0+0094 <[^>]*> sdxc1	\$f4,a0\(a1\)
+0+0098 <[^>]*> swxc1	\$f4,a0\(a1\)
+	...
Index: gas/testsuite/gas/mips/mips4-fp.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips4-fp.l
diff -N gas/testsuite/gas/mips/mips4-fp.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips4-fp.l	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,35 @@
+.*: Assembler messages:
+.*:4: Error: opcode not supported on this processor: .* \(.*\) `bc1f text_label'
+.*:5: Error: opcode not supported on this processor: .* \(.*\) `bc1f \$fcc1,text_label'
+.*:6: Error: opcode not supported on this processor: .* \(.*\) `bc1fl \$fcc1,text_label'
+.*:7: Error: opcode not supported on this processor: .* \(.*\) `bc1t \$fcc1,text_label'
+.*:8: Error: opcode not supported on this processor: .* \(.*\) `bc1tl \$fcc2,text_label'
+.*:9: Error: opcode not supported on this processor: .* \(.*\) `c.f.d \$f4,\$f6'
+.*:10: Error: opcode not supported on this processor: .* \(.*\) `c.f.d \$fcc1,\$f4,\$f6'
+.*:11: Error: opcode not supported on this processor: .* \(.*\) `ldxc1 \$f2,\$4\(\$5\)'
+.*:12: Error: opcode not supported on this processor: .* \(.*\) `lwxc1 \$f2,\$4\(\$5\)'
+.*:13: Error: opcode not supported on this processor: .* \(.*\) `madd.d \$f0,\$f2,\$f4,\$f6'
+.*:15: Error: opcode not supported on this processor: .* \(.*\) `madd.s \$f10,\$f8,\$f2,\$f0'
+.*:16: Error: opcode not supported on this processor: .* \(.*\) `movf \$4,\$5,\$fcc4'
+.*:17: Error: opcode not supported on this processor: .* \(.*\) `movf.d \$f4,\$f6,\$fcc0'
+.*:18: Error: opcode not supported on this processor: .* \(.*\) `movf.s \$f4,\$f6,\$fcc0'
+.*:19: Error: opcode not supported on this processor: .* \(.*\) `movn.d \$f4,\$f6,\$6'
+.*:20: Error: opcode not supported on this processor: .* \(.*\) `movn.s \$f4,\$f6,\$6'
+.*:21: Error: opcode not supported on this processor: .* \(.*\) `movt \$4,\$5,\$fcc4'
+.*:22: Error: opcode not supported on this processor: .* \(.*\) `movt.d \$f4,\$f6,\$fcc0'
+.*:23: Error: opcode not supported on this processor: .* \(.*\) `movt.s \$f4,\$f6,\$fcc0'
+.*:24: Error: opcode not supported on this processor: .* \(.*\) `movz.d \$f4,\$f6,\$6'
+.*:25: Error: opcode not supported on this processor: .* \(.*\) `movz.s \$f4,\$f6,\$6'
+.*:26: Error: opcode not supported on this processor: .* \(.*\) `msub.d \$f0,\$f2,\$f4,\$f6'
+.*:27: Error: opcode not supported on this processor: .* \(.*\) `msub.s \$f0,\$f2,\$f4,\$f6'
+.*:28: Error: opcode not supported on this processor: .* \(.*\) `nmadd.d \$f0,\$f2,\$f4,\$f6'
+.*:29: Error: opcode not supported on this processor: .* \(.*\) `nmadd.s \$f0,\$f2,\$f4,\$f6'
+.*:30: Error: opcode not supported on this processor: .* \(.*\) `nmsub.d \$f0,\$f2,\$f4,\$f6'
+.*:31: Error: opcode not supported on this processor: .* \(.*\) `nmsub.s \$f0,\$f2,\$f4,\$f6'
+.*:33: Error: opcode not supported on this processor: .* \(.*\) `prefx 4,\$4\(\$5\)'
+.*:34: Error: opcode not supported on this processor: .* \(.*\) `recip.d \$f4,\$f6'
+.*:35: Error: opcode not supported on this processor: .* \(.*\) `recip.s \$f4,\$f6'
+.*:36: Error: opcode not supported on this processor: .* \(.*\) `rsqrt.d \$f4,\$f6'
+.*:37: Error: opcode not supported on this processor: .* \(.*\) `rsqrt.s \$f4,\$f6'
+.*:38: Error: opcode not supported on this processor: .* \(.*\) `sdxc1 \$f4,\$4\(\$5\)'
+.*:39: Error: opcode not supported on this processor: .* \(.*\) `swxc1 \$f4,\$4\(\$5\)'
Index: gas/testsuite/gas/mips/mips4-fp.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips4-fp.s
diff -N gas/testsuite/gas/mips/mips4-fp.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips4-fp.s	15 Feb 2008 21:08:31 -0000
@@ -0,0 +1,44 @@
+# Source file used to test -mips4 fp instructions.
+
+text_label:	
+	bc1f	text_label
+	bc1f	$fcc1,text_label
+	bc1fl	$fcc1,text_label
+	bc1t	$fcc1,text_label
+	bc1tl	$fcc2,text_label
+	c.f.d	$f4,$f6
+	c.f.d	$fcc1,$f4,$f6
+	ldxc1	$f2,$4($5)
+	lwxc1	$f2,$4($5)
+	madd.d	$f0,$f2,$f4,$f6
+	# This choice of arguments is so that it matches bc3f on pre-mips4.
+	madd.s	$f10,$f8,$f2,$f0
+	movf	$4,$5,$fcc4
+	movf.d	$f4,$f6,$fcc0
+	movf.s	$f4,$f6,$fcc0
+	movn.d	$f4,$f6,$6
+	movn.s	$f4,$f6,$6
+	movt	$4,$5,$fcc4
+	movt.d	$f4,$f6,$fcc0
+	movt.s	$f4,$f6,$fcc0
+	movz.d	$f4,$f6,$6
+	movz.s	$f4,$f6,$6
+	msub.d	$f0,$f2,$f4,$f6
+	msub.s	$f0,$f2,$f4,$f6
+	nmadd.d	$f0,$f2,$f4,$f6
+	nmadd.s	$f0,$f2,$f4,$f6
+	nmsub.d	$f0,$f2,$f4,$f6
+	nmsub.s	$f0,$f2,$f4,$f6
+	# It used to be disabled due to a clash with lwc3.
+	prefx	4,$4($5)
+	recip.d	$f4,$f6
+	recip.s	$f4,$f6
+	rsqrt.d	$f4,$f6
+	rsqrt.s	$f4,$f6
+	sdxc1	$f4,$4($5)
+	swxc1	$f4,$4($5)
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+	nop
+	nop
+	nop
Index: gas/testsuite/gas/mips/mips4.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips4.d,v
retrieving revision 1.6
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.6 mips4.d
--- gas/testsuite/gas/mips/mips4.d	18 Jul 2006 14:06:10 -0000	1.6
+++ gas/testsuite/gas/mips/mips4.d	15 Feb 2008 21:08:31 -0000
@@ -1,51 +1,12 @@
 #objdump: -dr --prefix-addresses
-#name: MIPS mips4
+#name: MIPS mips4 non-fp
 
-# Test the mips4 macros.
+# Test mips4 *non-fp* insturctions.
 
 .*: +file format .*mips.*
 
 Disassembly of section .text:
-0+0000 <[^>]*> bc1f	00000000+ <text_label>
-0+0004 <[^>]*> nop
-0+0008 <[^>]*> bc1f	\$fcc1,00000000+ <text_label>
-0+000c <[^>]*> nop
-0+0010 <[^>]*> bc1fl	\$fcc1,00000000+ <text_label>
-0+0014 <[^>]*> nop
-0+0018 <[^>]*> bc1t	\$fcc1,00000000+ <text_label>
-0+001c <[^>]*> nop
-0+0020 <[^>]*> bc1tl	\$fcc2,00000000+ <text_label>
-0+0024 <[^>]*> nop
-0+0028 <[^>]*> c.f.d	\$f4,\$f6
-0+002c <[^>]*> c.f.d	\$fcc1,\$f4,\$f6
-0+0030 <[^>]*> ldxc1	\$f2,a0\(a1\)
-0+0034 <[^>]*> lwxc1	\$f2,a0\(a1\)
-0+0038 <[^>]*> madd.d	\$f0,\$f2,\$f4,\$f6
-0+003c <[^>]*> madd.s	\$f10,\$f8,\$f2,\$f0
-0+0040 <[^>]*> movf	a0,a1,\$fcc4
-0+0044 <[^>]*> movf.d	\$f4,\$f6,\$fcc0
-0+0048 <[^>]*> movf.s	\$f4,\$f6,\$fcc0
-0+004c <[^>]*> movn	a0,a2,a2
-0+0050 <[^>]*> movn.d	\$f4,\$f6,a2
-0+0054 <[^>]*> movn.s	\$f4,\$f6,a2
-0+0058 <[^>]*> movt	a0,a1,\$fcc4
-0+005c <[^>]*> movt.d	\$f4,\$f6,\$fcc0
-0+0060 <[^>]*> movt.s	\$f4,\$f6,\$fcc0
-0+0064 <[^>]*> movz	a0,a2,a2
-0+0068 <[^>]*> movz.d	\$f4,\$f6,a2
-0+006c <[^>]*> movz.s	\$f4,\$f6,a2
-0+0070 <[^>]*> msub.d	\$f0,\$f2,\$f4,\$f6
-0+0074 <[^>]*> msub.s	\$f0,\$f2,\$f4,\$f6
-0+0078 <[^>]*> nmadd.d	\$f0,\$f2,\$f4,\$f6
-0+007c <[^>]*> nmadd.s	\$f0,\$f2,\$f4,\$f6
-0+0080 <[^>]*> nmsub.d	\$f0,\$f2,\$f4,\$f6
-0+0084 <[^>]*> nmsub.s	\$f0,\$f2,\$f4,\$f6
-0+0088 <[^>]*> pref	0x4,0\(a0\)
-0+008c <[^>]*> prefx	0x4,a0\(a1\)
-0+0090 <[^>]*> recip.d	\$f4,\$f6
-0+0094 <[^>]*> recip.s	\$f4,\$f6
-0+0098 <[^>]*> rsqrt.d	\$f4,\$f6
-0+009c <[^>]*> rsqrt.s	\$f4,\$f6
-0+00a0 <[^>]*> sdxc1	\$f4,a0\(a1\)
-0+00a4 <[^>]*> swxc1	\$f4,a0\(a1\)
+0+0000 <[^>]*> movn	a0,a2,a2
+0+0004 <[^>]*> movz	a0,a2,a2
+0+0008 <[^>]*> pref	0x4,0\(a0\)
 	...
Index: gas/testsuite/gas/mips/mips4.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips4.s,v
retrieving revision 1.3
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.3 mips4.s
--- gas/testsuite/gas/mips/mips4.s	18 Jul 2006 14:06:10 -0000	1.3
+++ gas/testsuite/gas/mips/mips4.s	15 Feb 2008 21:08:31 -0000
@@ -1,45 +1,10 @@
-# Source file used to test -mips4 instructions.
+# Source file used to test -mips4 *non-fp* instructions.
 
 text_label:	
-	bc1f	text_label
-	bc1f	$fcc1,text_label
-	bc1fl	$fcc1,text_label
-	bc1t	$fcc1,text_label
-	bc1tl	$fcc2,text_label
-	c.f.d	$f4,$f6
-	c.f.d	$fcc1,$f4,$f6
-	ldxc1	$f2,$4($5)
-	lwxc1	$f2,$4($5)
-	madd.d	$f0,$f2,$f4,$f6
-	# This choice of arguments is so that it matches bc3f on pre-mips4.
-	madd.s	$f10,$f8,$f2,$f0
-	movf	$4,$5,$fcc4
-	movf.d	$f4,$f6,$fcc0
-	movf.s	$f4,$f6,$fcc0
 	movn	$4,$6,$6
-	movn.d	$f4,$f6,$6
-	movn.s	$f4,$f6,$6
-	movt	$4,$5,$fcc4
-	movt.d	$f4,$f6,$fcc0
-	movt.s	$f4,$f6,$fcc0
 	movz	$4,$6,$6
-	movz.d	$f4,$f6,$6
-	movz.s	$f4,$f6,$6
-	msub.d	$f0,$f2,$f4,$f6
-	msub.s	$f0,$f2,$f4,$f6
-	nmadd.d	$f0,$f2,$f4,$f6
-	nmadd.s	$f0,$f2,$f4,$f6
-	nmsub.d	$f0,$f2,$f4,$f6
-	nmsub.s	$f0,$f2,$f4,$f6
 	# It used to be disabled due to a clash with lwc3.
 	pref	4,0($4)
-	prefx	4,$4($5)
-	recip.d	$f4,$f6
-	recip.s	$f4,$f6
-	rsqrt.d	$f4,$f6
-	rsqrt.s	$f4,$f6
-	sdxc1	$f4,$4($5)
-	swxc1	$f4,$4($5)
 
 # Round to a 16 byte boundary, for ease in testing multiple targets.
 	nop
Index: include/opcode/mips.h
===================================================================
RCS file: /cvs/src/src/include/opcode/mips.h,v
retrieving revision 1.56
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.56 mips.h
--- include/opcode/mips.h	4 Feb 2008 19:25:05 -0000	1.56
+++ include/opcode/mips.h	15 Feb 2008 21:08:37 -0000
@@ -456,6 +456,9 @@ #define FP_D			    0x20000000
 #define INSN_MULT                   0x40000000
 /* Instruction synchronize shared memory.  */
 #define INSN_SYNC		    0x80000000
+/* Instruction is actually a macro.  It should be ignored by the
+   disassembler, and requires special treatment by the assembler.  */
+#define INSN_MACRO                  0xffffffff
 
 /* These are the bits which may be set in the pinfo2 field of an
    instruction. */
@@ -466,10 +469,14 @@ #define	INSN2_ALIAS		    0x00000001
 #define INSN2_READ_MDMX_ACC	    0x00000002
 /* Instruction writes MDMX accumulator. */
 #define INSN2_WRITE_MDMX_ACC	    0x00000004
-
-/* Instruction is actually a macro.  It should be ignored by the
-   disassembler, and requires special treatment by the assembler.  */
-#define INSN_MACRO                  0xffffffff
+/* Macro is only valid on a chip with an FPU.  It should only be set
+   for macros.  For instructions, FP_S in pinfo carries the same
+   information.  */
+#define INSN2_M_FP_S		    0x00000008
+/* Macro is only valid on a chip with an 64-bit FPU.  It should only
+   be set for macros.  For instructions, FP_D in pinfo carries the
+   same information.  */
+#define INSN2_M_FP_D		    0x00000010
 
 /* Masks used to mark instructions to indicate which MIPS ISA level
    they were introduced in.  INSN_ISA_MASK masks an enumeration that
Index: opcodes/mips-opc.c
===================================================================
RCS file: /cvs/src/src/opcodes/mips-opc.c,v
retrieving revision 1.65
diff -F^\([(a-zA-Z0-9_]\|#define\) -u -p -r1.65 mips-opc.c
--- opcodes/mips-opc.c	4 Feb 2008 19:26:11 -0000	1.65
+++ opcodes/mips-opc.c	15 Feb 2008 21:08:50 -0000
@@ -184,7 +184,7 @@ const struct mips_opcode mips_builtin_op
    instruction name anyhow.  */
 /* name,    args,	match,	    mask,	pinfo,          	pinfo2,		membership */
 {"pref",    "k,o(b)",   0xcc000000, 0xfc000000, RD_b,           	0,		I4_32|G3	},
-{"prefx",   "h,t(b)",	0x4c00000f, 0xfc0007ff, RD_b|RD_t,		0,		I4_33	},
+{"prefx",   "h,t(b)",	0x4c00000f, 0xfc0007ff, RD_b|RD_t|FP_S,		0,		I4_33	},
 {"nop",     "",         0x00000000, 0xffffffff, 0,              	INSN2_ALIAS,	I1      }, /* sll */
 {"ssnop",   "",         0x00000040, 0xffffffff, 0,              	INSN2_ALIAS,	I32|N55	}, /* sll */
 {"ehb",     "",         0x000000c0, 0xffffffff, 0,              	INSN2_ALIAS,	I33	}, /* sll */
@@ -733,11 +733,11 @@ const struct mips_opcode mips_builtin_op
 {"ld",      "t,A(b)",	0,    (int) M_LD_AB,	INSN_MACRO,		0,		I1	},
 {"ldc1",    "T,o(b)",	0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D,	0,		I2	},
 {"ldc1",    "E,o(b)",	0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D,	0,		I2	},
-{"ldc1",    "T,A(b)",	0,    (int) M_LDC1_AB,	INSN_MACRO,		0,		I2	},
-{"ldc1",    "E,A(b)",	0,    (int) M_LDC1_AB,	INSN_MACRO,		0,		I2	},
+{"ldc1",    "T,A(b)",	0,    (int) M_LDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2	},
+{"ldc1",    "E,A(b)",	0,    (int) M_LDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2	},
 {"l.d",     "T,o(b)",	0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D,	0,		I2	}, /* ldc1 */
-{"l.d",     "T,o(b)",	0,    (int) M_L_DOB,	INSN_MACRO,		0,		I1	},
-{"l.d",     "T,A(b)",	0,    (int) M_L_DAB,	INSN_MACRO,		0,		I1	},
+{"l.d",     "T,o(b)",	0,    (int) M_L_DOB,	INSN_MACRO,		INSN2_M_FP_D,	I1	},
+{"l.d",     "T,A(b)",	0,    (int) M_L_DAB,	INSN_MACRO,		INSN2_M_FP_D,	I1	},
 {"ldc2",    "E,o(b)",	0xd8000000, 0xfc000000, CLD|RD_b|WR_CC,		0,		I2	},
 {"ldc2",    "E,A(b)",	0,    (int) M_LDC2_AB,	INSN_MACRO,		0,		I2	},
 {"ldc3",    "E,o(b)",	0xdc000000, 0xfc000000, CLD|RD_b|WR_CC,		0,		I2	},
@@ -752,10 +752,10 @@ const struct mips_opcode mips_builtin_op
 {"lhu",     "t,o(b)",	0x94000000, 0xfc000000,	LDD|RD_b|WR_t,		0,		I1	},
 {"lhu",     "t,A(b)",	0,    (int) M_LHU_AB,	INSN_MACRO,		0,		I1	},
 /* li is at the start of the table.  */
-{"li.d",    "t,F",	0,    (int) M_LI_D,	INSN_MACRO,		0,		I1	},
-{"li.d",    "T,L",	0,    (int) M_LI_DD,	INSN_MACRO,		0,		I1	},
-{"li.s",    "t,f",	0,    (int) M_LI_S,	INSN_MACRO,		0,		I1	},
-{"li.s",    "T,l",	0,    (int) M_LI_SS,	INSN_MACRO,		0,		I1	},
+{"li.d",    "t,F",	0,    (int) M_LI_D,	INSN_MACRO,		INSN2_M_FP_D,	I1	},
+{"li.d",    "T,L",	0,    (int) M_LI_DD,	INSN_MACRO,		INSN2_M_FP_D,	I1	},
+{"li.s",    "t,f",	0,    (int) M_LI_S,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
+{"li.s",    "T,l",	0,    (int) M_LI_SS,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
 {"ll",	    "t,o(b)",	0xc0000000, 0xfc000000, LDD|RD_b|WR_t,		0,		I2	},
 {"ll",	    "t,A(b)",	0,    (int) M_LL_AB,	INSN_MACRO,		0,		I2	},
 {"lld",	    "t,o(b)",	0xd0000000, 0xfc000000, LDD|RD_b|WR_t,		0,		I3	},
@@ -768,10 +768,10 @@ const struct mips_opcode mips_builtin_op
 {"lwc0",    "E,A(b)",	0,    (int) M_LWC0_AB,	INSN_MACRO,		0,		I1	},
 {"lwc1",    "T,o(b)",	0xc4000000, 0xfc000000,	CLD|RD_b|WR_T|FP_S,	0,		I1	},
 {"lwc1",    "E,o(b)",	0xc4000000, 0xfc000000,	CLD|RD_b|WR_T|FP_S,	0,		I1	},
-{"lwc1",    "T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		0,		I1	},
-{"lwc1",    "E,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		0,		I1	},
+{"lwc1",    "T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
+{"lwc1",    "E,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
 {"l.s",     "T,o(b)",	0xc4000000, 0xfc000000,	CLD|RD_b|WR_T|FP_S,	0,		I1	}, /* lwc1 */
-{"l.s",     "T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		0,		I1	},
+{"l.s",     "T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
 {"lwc2",    "E,o(b)",	0xc8000000, 0xfc000000,	CLD|RD_b|WR_CC,		0,		I1	},
 {"lwc2",    "E,A(b)",	0,    (int) M_LWC2_AB,	INSN_MACRO,		0,		I1	},
 {"lwc3",    "E,o(b)",	0xcc000000, 0xfc000000,	CLD|RD_b|WR_CC,		0,		I1	},
@@ -1151,15 +1151,15 @@ const struct mips_opcode mips_builtin_op
 {"sdbbp",   "B",        0x7000003f, 0xfc00003f, TRAP,           	0,		I32     },
 {"sdc1",    "T,o(b)",	0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D,	0,		I2	},
 {"sdc1",    "E,o(b)",	0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D,	0,		I2	},
-{"sdc1",    "T,A(b)",	0,    (int) M_SDC1_AB,	INSN_MACRO,		0,		I2	},
-{"sdc1",    "E,A(b)",	0,    (int) M_SDC1_AB,	INSN_MACRO,		0,		I2	},
+{"sdc1",    "T,A(b)",	0,    (int) M_SDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2	},
+{"sdc1",    "E,A(b)",	0,    (int) M_SDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2	},
 {"sdc2",    "E,o(b)",	0xf8000000, 0xfc000000, SM|RD_C2|RD_b,		0,		I2	},
 {"sdc2",    "E,A(b)",	0,    (int) M_SDC2_AB,	INSN_MACRO,		0,		I2	},
 {"sdc3",    "E,o(b)",	0xfc000000, 0xfc000000, SM|RD_C3|RD_b,		0,		I2	},
 {"sdc3",    "E,A(b)",	0,    (int) M_SDC3_AB,	INSN_MACRO,		0,		I2	},
 {"s.d",     "T,o(b)",	0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D,	0,		I2	},
-{"s.d",     "T,o(b)",	0,    (int) M_S_DOB,	INSN_MACRO,		0,		I1	},
-{"s.d",     "T,A(b)",	0,    (int) M_S_DAB,	INSN_MACRO,		0,		I1	},
+{"s.d",     "T,o(b)",	0,    (int) M_S_DOB,	INSN_MACRO,		INSN2_M_FP_D,	I1	},
+{"s.d",     "T,A(b)",	0,    (int) M_S_DAB,	INSN_MACRO,		INSN2_M_FP_D,	I1	},
 {"sdl",     "t,o(b)",	0xb0000000, 0xfc000000,	SM|RD_t|RD_b,		0,		I3	},
 {"sdl",     "t,A(b)",	0,    (int) M_SDL_AB,	INSN_MACRO,		0,		I3	},
 {"sdr",     "t,o(b)",	0xb4000000, 0xfc000000,	SM|RD_t|RD_b,		0,		I3	},
@@ -1275,10 +1275,10 @@ const struct mips_opcode mips_builtin_op
 {"swc0",    "E,A(b)",	0,    (int) M_SWC0_AB,	INSN_MACRO,		0,		I1	},
 {"swc1",    "T,o(b)",	0xe4000000, 0xfc000000,	SM|RD_T|RD_b|FP_S,	0,		I1	},
 {"swc1",    "E,o(b)",	0xe4000000, 0xfc000000,	SM|RD_T|RD_b|FP_S,	0,		I1	},
-{"swc1",    "T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		0,		I1	},
-{"swc1",    "E,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		0,		I1	},
+{"swc1",    "T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
+{"swc1",    "E,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
 {"s.s",     "T,o(b)",	0xe4000000, 0xfc000000,	SM|RD_T|RD_b|FP_S,	0,		I1	}, /* swc1 */
-{"s.s",     "T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		0,		I1	},
+{"s.s",     "T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
 {"swc2",    "E,o(b)",	0xe8000000, 0xfc000000,	SM|RD_C2|RD_b,		0,		I1	},
 {"swc2",    "E,A(b)",	0,    (int) M_SWC2_AB,	INSN_MACRO,		0,		I1	},
 {"swc3",    "E,o(b)",	0xec000000, 0xfc000000,	SM|RD_C3|RD_b,		0,		I1	},
@@ -1337,10 +1337,10 @@ const struct mips_opcode mips_builtin_op
 {"trunc.l.s", "D,S",	0x46000009, 0xffff003f,	WR_D|RD_S|FP_S|FP_D,	0,		I3_33	},
 {"trunc.w.d", "D,S",	0x4620000d, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I2	},
 {"trunc.w.d", "D,S,x",	0x4620000d, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I2	},
-{"trunc.w.d", "D,S,t",	0,    (int) M_TRUNCWD,	INSN_MACRO,		0,		I1	},
+{"trunc.w.d", "D,S,t",	0,    (int) M_TRUNCWD,	INSN_MACRO,		INSN2_M_FP_S|INSN2_M_FP_D, I1 },
 {"trunc.w.s", "D,S",	0x4600000d, 0xffff003f,	WR_D|RD_S|FP_S,		0,		I2	},
 {"trunc.w.s", "D,S,x",	0x4600000d, 0xffff003f,	WR_D|RD_S|FP_S,		0,		I2	},
-{"trunc.w.s", "D,S,t",	0,    (int) M_TRUNCWS,	INSN_MACRO,		0,		I1	},
+{"trunc.w.s", "D,S,t",	0,    (int) M_TRUNCWS,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
 {"uld",     "t,o(b)",	0,    (int) M_ULD,	INSN_MACRO,		0,		I3	},
 {"uld",     "t,A(b)",	0,    (int) M_ULD_A,	INSN_MACRO,		0,		I3	},
 {"ulh",     "t,o(b)",	0,    (int) M_ULH,	INSN_MACRO,		0,		I1	},
@@ -1927,11 +1927,11 @@ const struct mips_opcode mips_builtin_op
    user to put in nops as necessary.  These are at the end so that the
    disassembler recognizes more specific versions first.  */
 {"c0",      "C",	0x42000000, 0xfe000000,	0,			0,		I1	},
-{"c1",      "C",	0x46000000, 0xfe000000,	0,			0,		I1	},
+{"c1",      "C",	0x46000000, 0xfe000000,	FP_S,			0,		I1	},
 {"c2",      "C",	0x4a000000, 0xfe000000,	0,			0,		I1	},
 {"c3",      "C",	0x4e000000, 0xfe000000,	0,			0,		I1	},
 {"cop0",     "C",	0,    (int) M_COP0,	INSN_MACRO,		0,		I1	},
-{"cop1",     "C",	0,    (int) M_COP1,	INSN_MACRO,		0,		I1	},
+{"cop1",     "C",	0,    (int) M_COP1,	INSN_MACRO,		INSN2_M_FP_S,	I1	},
 {"cop2",     "C",	0,    (int) M_COP2,	INSN_MACRO,		0,		I1	},
 {"cop3",     "C",	0,    (int) M_COP3,	INSN_MACRO,		0,		I1	}
 };


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