Commit 88f091f5 by Ulrich Weigand Committed by Ulrich Weigand

real.c (spu_single_format): New variable.

ChangeLog:

	* real.c (spu_single_format): New variable.
	* real.h (spu_single_format): Declare.

	* config/spu/spu.c (spu_override_options): Install SFmode format.
	(spu_split_immediate): Use integer mode to operate on pieces of
	floating-point values in all cases.

	* config/spu/spu.md (UNSPEC_FLOAT_EXTEND, UNSPEC_FLOAT_TRUNCATE): New.
	("extendsfdf2"): Use UNSPEC_FLOAT_EXTEND instead of FLOAT_EXTEND.
	("truncdfsf2"): Use UNSPEC_FLOAT_TRUNCATE instead of FLOAT_TRUNCATE.

testsuite/ChangeLog:

	* gcc.c-torture/execute/ieee/inf-2.c (testf): Skip on the SPU.

Co-Authored-By: Trevor Smigiel <Trevor_Smigiel@playstation.sony.com>

From-SVN: r139013
parent 4230d0fe
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> 2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Trevor Smigiel <trevor_smigiel@playstation.sony.com>
* real.c (spu_single_format): New variable.
* real.h (spu_single_format): Declare.
* config/spu/spu.c (spu_override_options): Install SFmode format.
(spu_split_immediate): Use integer mode to operate on pieces of
floating-point values in all cases.
* config/spu/spu.md (UNSPEC_FLOAT_EXTEND, UNSPEC_FLOAT_TRUNCATE): New.
("extendsfdf2"): Use UNSPEC_FLOAT_EXTEND instead of FLOAT_EXTEND.
("truncdfsf2"): Use UNSPEC_FLOAT_TRUNCATE instead of FLOAT_TRUNCATE.
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
* config/spu/spu.c (spu_safe_dma): Respect TARGET_SAFE_DMA. * config/spu/spu.c (spu_safe_dma): Respect TARGET_SAFE_DMA.
......
...@@ -352,6 +352,8 @@ spu_override_options (void) ...@@ -352,6 +352,8 @@ spu_override_options (void)
else else
error ("Unknown architecture '%s'", &spu_tune_string[0]); error ("Unknown architecture '%s'", &spu_tune_string[0]);
} }
REAL_MODE_FORMAT (SFmode) = &spu_single_format;
} }
/* Handle an attribute requiring a FUNCTION_DECL; arguments as in /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
...@@ -1519,10 +1521,18 @@ spu_split_immediate (rtx * ops) ...@@ -1519,10 +1521,18 @@ spu_split_immediate (rtx * ops)
{ {
unsigned char arrhi[16]; unsigned char arrhi[16];
unsigned char arrlo[16]; unsigned char arrlo[16];
rtx to, hi, lo; rtx to, temp, hi, lo;
int i; int i;
enum machine_mode imode = mode;
/* We need to do reals as ints because the constant used in the
IOR might not be a legitimate real constant. */
imode = int_mode_for_mode (mode);
constant_to_array (mode, ops[1], arrhi); constant_to_array (mode, ops[1], arrhi);
to = !can_create_pseudo_p () ? ops[0] : gen_reg_rtx (mode); if (imode != mode)
to = simplify_gen_subreg (imode, ops[0], mode, 0);
else
to = ops[0];
temp = !can_create_pseudo_p () ? to : gen_reg_rtx (imode);
for (i = 0; i < 16; i += 4) for (i = 0; i < 16; i += 4)
{ {
arrlo[i + 2] = arrhi[i + 2]; arrlo[i + 2] = arrhi[i + 2];
...@@ -1530,11 +1540,11 @@ spu_split_immediate (rtx * ops) ...@@ -1530,11 +1540,11 @@ spu_split_immediate (rtx * ops)
arrlo[i + 0] = arrlo[i + 1] = 0; arrlo[i + 0] = arrlo[i + 1] = 0;
arrhi[i + 2] = arrhi[i + 3] = 0; arrhi[i + 2] = arrhi[i + 3] = 0;
} }
hi = array_to_constant (mode, arrhi); hi = array_to_constant (imode, arrhi);
lo = array_to_constant (mode, arrlo); lo = array_to_constant (imode, arrlo);
emit_move_insn (to, hi); emit_move_insn (temp, hi);
emit_insn (gen_rtx_SET emit_insn (gen_rtx_SET
(VOIDmode, ops[0], gen_rtx_IOR (mode, to, lo))); (VOIDmode, to, gen_rtx_IOR (imode, temp, lo)));
return 1; return 1;
} }
case IC_FSMBI2: case IC_FSMBI2:
......
...@@ -153,6 +153,8 @@ ...@@ -153,6 +153,8 @@
(UNSPEC_SPU_REALIGN_LOAD 49) (UNSPEC_SPU_REALIGN_LOAD 49)
(UNSPEC_SPU_MASK_FOR_LOAD 50) (UNSPEC_SPU_MASK_FOR_LOAD 50)
(UNSPEC_DFTSV 51) (UNSPEC_DFTSV 51)
(UNSPEC_FLOAT_EXTEND 52)
(UNSPEC_FLOAT_TRUNCATE 53)
]) ])
(include "predicates.md") (include "predicates.md")
...@@ -648,14 +650,16 @@ ...@@ -648,14 +650,16 @@
(define_insn "extendsfdf2" (define_insn "extendsfdf2"
[(set (match_operand:DF 0 "spu_reg_operand" "=r") [(set (match_operand:DF 0 "spu_reg_operand" "=r")
(float_extend:DF (match_operand:SF 1 "spu_reg_operand" "r")))] (unspec:DF [(match_operand:SF 1 "spu_reg_operand" "r")]
UNSPEC_FLOAT_EXTEND))]
"" ""
"fesd\t%0,%1" "fesd\t%0,%1"
[(set_attr "type" "fpd")]) [(set_attr "type" "fpd")])
(define_insn "truncdfsf2" (define_insn "truncdfsf2"
[(set (match_operand:SF 0 "spu_reg_operand" "=r") [(set (match_operand:SF 0 "spu_reg_operand" "=r")
(float_truncate:SF (match_operand:DF 1 "spu_reg_operand" "r")))] (unspec:SF [(match_operand:DF 1 "spu_reg_operand" "r")]
UNSPEC_FLOAT_TRUNCATE))]
"" ""
"frds\t%0,%1" "frds\t%0,%1"
[(set_attr "type" "fpd")]) [(set_attr "type" "fpd")])
......
...@@ -2862,6 +2862,36 @@ const struct real_format motorola_single_format = ...@@ -2862,6 +2862,36 @@ const struct real_format motorola_single_format =
true, true,
true true
}; };
/* SPU Single Precision (Extended-Range Mode) 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.
- The range of non-zero numbers in binary is
(001)[1.]000...000 to (255)[1.]111...111.
- Denormals can be represented, but are treated as +0.0 when
used as an operand and are never generated as a result.
- -0.0 can be represented, but a zero result is always +0.0.
- the only supported rounding mode is trunction (towards zero). */
const struct real_format spu_single_format =
{
encode_ieee_single,
decode_ieee_single,
2,
24,
24,
-125,
129,
31,
31,
false,
false,
true,
true,
false,
false
};
/* IEEE double-precision format. */ /* IEEE double-precision format. */
......
...@@ -259,6 +259,7 @@ extern unsigned int real_hash (const REAL_VALUE_TYPE *); ...@@ -259,6 +259,7 @@ extern unsigned int real_hash (const REAL_VALUE_TYPE *);
extern const struct real_format ieee_single_format; extern const struct real_format ieee_single_format;
extern const struct real_format mips_single_format; extern const struct real_format mips_single_format;
extern const struct real_format motorola_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; extern const struct real_format ieee_double_format;
extern const struct real_format mips_double_format; extern const struct real_format mips_double_format;
extern const struct real_format motorola_double_format; extern const struct real_format motorola_double_format;
......
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
* gcc.c-torture/execute/ieee/inf-2.c (testf): Skip on the SPU.
2008-08-12 Jakub Jelinek <jakub@redhat.com> 2008-08-12 Jakub Jelinek <jakub@redhat.com>
PR c++/36688 PR c++/36688
......
...@@ -25,6 +25,9 @@ void test(double f, double i) ...@@ -25,6 +25,9 @@ void test(double f, double i)
void testf(float f, float i) void testf(float f, float i)
{ {
#ifndef __SPU__
/* The SPU single-precision floating point format does not support Inf. */
if (f == __builtin_inff()) if (f == __builtin_inff())
abort (); abort ();
if (f == -__builtin_inff()) if (f == -__builtin_inff())
...@@ -44,6 +47,7 @@ void testf(float f, float i) ...@@ -44,6 +47,7 @@ void testf(float f, float i)
abort (); abort ();
if (f < -__builtin_inff()) if (f < -__builtin_inff())
abort (); abort ();
#endif
} }
void testl(long double f, long double i) void testl(long double f, long double i)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment