aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/spu/spu.c22
-rw-r--r--gcc/config/spu/spu.md8
-rw-r--r--gcc/real.c30
-rw-r--r--gcc/real.h1
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c4
7 files changed, 75 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 42afad2..cbd499e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,18 @@
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.
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 230f4c0..1021a91 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -352,6 +352,8 @@ spu_override_options (void)
else
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
@@ -1519,10 +1521,18 @@ spu_split_immediate (rtx * ops)
{
unsigned char arrhi[16];
unsigned char arrlo[16];
- rtx to, hi, lo;
+ rtx to, temp, hi, lo;
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);
- 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)
{
arrlo[i + 2] = arrhi[i + 2];
@@ -1530,11 +1540,11 @@ spu_split_immediate (rtx * ops)
arrlo[i + 0] = arrlo[i + 1] = 0;
arrhi[i + 2] = arrhi[i + 3] = 0;
}
- hi = array_to_constant (mode, arrhi);
- lo = array_to_constant (mode, arrlo);
- emit_move_insn (to, hi);
+ hi = array_to_constant (imode, arrhi);
+ lo = array_to_constant (imode, arrlo);
+ emit_move_insn (temp, hi);
emit_insn (gen_rtx_SET
- (VOIDmode, ops[0], gen_rtx_IOR (mode, to, lo)));
+ (VOIDmode, to, gen_rtx_IOR (imode, temp, lo)));
return 1;
}
case IC_FSMBI2:
diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md
index c267efd..e50a65a 100644
--- a/gcc/config/spu/spu.md
+++ b/gcc/config/spu/spu.md
@@ -153,6 +153,8 @@
(UNSPEC_SPU_REALIGN_LOAD 49)
(UNSPEC_SPU_MASK_FOR_LOAD 50)
(UNSPEC_DFTSV 51)
+ (UNSPEC_FLOAT_EXTEND 52)
+ (UNSPEC_FLOAT_TRUNCATE 53)
])
(include "predicates.md")
@@ -648,14 +650,16 @@
(define_insn "extendsfdf2"
[(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"
[(set_attr "type" "fpd")])
(define_insn "truncdfsf2"
[(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"
[(set_attr "type" "fpd")])
diff --git a/gcc/real.c b/gcc/real.c
index b071756..49eb97d 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -2862,6 +2862,36 @@ const struct real_format motorola_single_format =
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. */
diff --git a/gcc/real.h b/gcc/real.h
index 6332299..39522b6 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -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 mips_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 mips_double_format;
extern const struct real_format motorola_double_format;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d6f2811..8653a14 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+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>
PR c++/36688
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c b/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c
index 40270c0..1823b35 100644
--- a/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c
@@ -25,6 +25,9 @@ void test(double f, double i)
void testf(float f, float i)
{
+#ifndef __SPU__
+ /* The SPU single-precision floating point format does not support Inf. */
+
if (f == __builtin_inff())
abort ();
if (f == -__builtin_inff())
@@ -44,6 +47,7 @@ void testf(float f, float i)
abort ();
if (f < -__builtin_inff())
abort ();
+#endif
}
void testl(long double f, long double i)