Hello Richard,

I used the SPU code in GCC as example for creating an r5900_single_format 
structure. The patch is attached to the e-mail. I want to submit this patch.

> >> * removing the ISA_HAS_LDC1_SDC1 setting.  I realise what you did
> >>   describes the reality of the processor, but the problem is that
> >>   the patch doesn't provide an alternative for 64-bit loads and
> >>   stores when -mfp64 is used.  That combination also isn't rejected,
> >>   so we're likely to get an internal compiler error instead.
> >>
> >>   This change shouldn't affect the soft-float case you describe.
> >>   It also shouldn't be important for the single-float code.

I needed to patch ISA_HAS_LDC1_SDC1, because the GCC uses the instructions also 
for single float to store FPRs on the stack. To get around the missing 
alternative, I reject in the code the following combinations, because it would 
never work:
-march=r5900 -mfp64 -mhard-float
-march=r5900 -mdouble-float -mhard-float

> >> FWIW, the Cygnus/Red Hat version of the port just stuck with the R5900
> >> behaviour and made GCC understand it (MODE_HAS_* & various other bits).
> >> This code was then updated and extended for the SPU.  I'd have expected
> >> the support to be in reasonably good shape because of the SPU.
> >
> > I assume that you mean the cell processor of the PS3 and not the Sound
> > Processing Unit of the PS2.
>
> :-)
>
> > The macros MODE_HAS_* in the GCC look promising.
>
> You've probably already seen it, but there's also spu_single_format.

To be able to use it, you need to use mipsr5900el and "--with-float=single". 
"--with-float=hard" results in double float because of MIPS ISA III.
I didn't changed the default in config.gcc. It is still soft float, because 
floating point doesn't behave as defined by IEEE 754. I don't see much 
improvement. This is the case on the PS2 and the PS3. For example inf minus inf 
should be NaN, but on both systems it is 0. I tested it on r5900 and the PS3 
SPU. Both calculates the same result despite the MODE_HAS_* implementation. 
This means that there is a patch needed in the generic part (i.e. not  mips) of 
the GCC. Currently I only provide a simple patch, so that the GCC knows the 
missing stuff, even if it is not correctly handled in the generic GCC part. I 
thought that Linux is running on SPU, but this is not the case, because it just 
a simple coprocessor. It seems that SPU is not used for complex floating point 
calculations in homebrew software. I am pretty sure that nearly nobody knows 
that floating point in GCC behaves this way on SPU.

Best regards
Jürgen
Index: gcc/real.c
===================================================================
--- gcc/real.c	(Revision 200583)
+++ gcc/real.c	(Arbeitskopie)
@@ -3028,6 +3028,34 @@
     true
   };
 
+/*  r5900 Single precision format is the same as IEEE
+    single precision with the following differences:
+      - Infinities are not supported.  Instead MAX_FLOAT or MIN_FLOAT
+	are generated.
+      - NaNs are not supported.
+      - Denormals are not supported.
+      - the only supported rounding mode is trunction (towards zero).  */
+const struct real_format r5900_single_format =
+  {
+    encode_ieee_single,
+    decode_ieee_single,
+    2,
+    24,
+    24,
+    -125,
+    128,
+    31,
+    31,
+    true,
+    true,
+    false,
+    false,
+    false,
+    true,
+    false,
+    true
+  };
+
 const struct real_format motorola_single_format =
   {
     encode_ieee_single,
Index: gcc/real.h
===================================================================
--- gcc/real.h	(Revision 200583)
+++ gcc/real.h	(Arbeitskopie)
@@ -303,6 +303,7 @@
 /* Target formats defined in real.c.  */
 extern const struct real_format ieee_single_format;
 extern const struct real_format mips_single_format;
+extern const struct real_format r5900_single_format;
 extern const struct real_format motorola_single_format;
 extern const struct real_format spu_single_format;
 extern const struct real_format ieee_double_format;
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(Revision 200583)
+++ gcc/config.gcc	(Arbeitskopie)
@@ -3472,7 +3475,7 @@
 		supported_defaults="abi arch arch_32 arch_64 float tune tune_32 tune_64 divide llsc mips-plt synci"
 
 		case ${with_float} in
-		"" | soft | hard)
+		"" | soft | hard | single | double)
 			# OK
 			;;
 		*)
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	(Revision 200583)
+++ gcc/config/mips/mips.c	(Arbeitskopie)
@@ -16830,6 +16830,19 @@
 	target_flags &= ~MASK_FLOAT64;
     }
 
+  if (TARGET_HARD_FLOAT_ABI && TARGET_FLOAT64 && TARGET_MIPS5900)
+    {
+      /* FPU of r5900 only supports 32 bit. */
+      error ("unsupported combination: %s", "-march=r5900 -mfp64 -mhard-float");
+    }
+
+  if (TARGET_HARD_FLOAT_ABI && TARGET_DOUBLE_FLOAT && TARGET_MIPS5900)
+    {
+      /* FPU of r5900 only supports 32 bit. */
+      error ("unsupported combination: %s",
+             "-march=r5900 -mdouble-float -mhard-float");
+    }
+
   /* End of code shared with GAS.  */
 
   /* If a -mlong* option was given, check that it matches the ABI,
@@ -17139,6 +17152,11 @@
      filling.  Registering the pass must be done at start up.  It's
      convenient to do it here.  */
   register_pass (&insert_pass_mips_machine_reorg2);
+
+  if (TARGET_MIPS5900)
+    {
+      REAL_MODE_FORMAT (SFmode) = &r5900_single_format;
+    }
 }
 
 /* Swap the register information for registers I and I + 1, which
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	(Revision 200583)
+++ gcc/config/mips/mips.h	(Arbeitskopie)
@@ -859,7 +859,9 @@
 				 || TARGET_LOONGSON_2EF)
 
 /* ISA has LDC1 and SDC1.  */
-#define ISA_HAS_LDC1_SDC1	(!ISA_MIPS1 && !TARGET_MIPS16)
+#define ISA_HAS_LDC1_SDC1	(!ISA_MIPS1                             \
+                                  && !TARGET_MIPS16                     \
+				  && !TARGET_MIPS5900)			\
 
 /* ISA has the mips4 FP condition code instructions: FP-compare to CC,
    branch on CC, and move (both FP and non-FP) on CC.  */
@@ -989,7 +991,7 @@
 /* True if trunc.w.s and trunc.w.d are real (not synthetic)
    instructions.  Both require TARGET_HARD_FLOAT, and trunc.w.d
    also requires TARGET_DOUBLE_FLOAT.  */
-#define ISA_HAS_TRUNC_W		(!ISA_MIPS1)
+#define ISA_HAS_TRUNC_W		(!ISA_MIPS1 || TARGET_MIPS5900)
 
 /* ISA includes the MIPS32r2 seb and seh instructions.  */
 #define ISA_HAS_SEB_SEH		((ISA_MIPS32R2		\

Reply via email to