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 \