diff mbox

[v4,2/4] target-tilegx: Add single floating point implementation

Message ID 1450907315-10135-3-git-send-email-chengang@emindsoft.com.cn
State New
Headers show

Commit Message

Chen Gang Dec. 23, 2015, 9:48 p.m. UTC
From: Chen Gang <chengang@emindsoft.com.cn>

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
---
 target-tilegx/helper-fsingle.c | 211 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 211 insertions(+)
 create mode 100644 target-tilegx/helper-fsingle.c

Comments

Richard Henderson Dec. 23, 2015, 11:07 p.m. UTC | #1
On 12/23/2015 01:48 PM, chengang@emindsoft.com.cn wrote:
> +static float32 sfmt_to_float32(uint64_t sfmt)
> +{
> +    uint32_t sign = get_fsingle_sign(sfmt);
> +    uint32_t man = get_fsingle_man(sfmt);
> +    uint32_t exp = get_fsingle_exp(sfmt);
> +    float32 f;
> +
> +    if (get_fsingle_calc(sfmt) == TILEGX_F_CALC_CVT) {
> +        if (sign) {
> +            f = int32_to_float32(0 - man, &fp_status);
> +        } else {
> +            f = uint32_to_float32(man, &fp_status);
> +        }
> +        exp += get_f32_exp(f) - 0x9e;
> +        if ((int32_t) exp < 0) {
> +            return float32_infinity | float32_set_sign(float32_zero, sign);
> +        } else if (exp >= 0xff) {
> +            return float32_zero | float32_set_sign(float32_zero, sign);
> +        } else {
> +            set_f32_exp(&f, exp);
> +        }


What in the world are you attempting to do here?
This is not normalization.  This is not even remotely
correct with respect to zero or infinity.

Moreover, I thought we agreed to do away with that CALC bit.


r~

> +    } else {
> +        f = create_f32_man(man >> 8);
> +        set_f32_exp(&f, exp);
> +    }
> +
> +    f = float32_set_sign(f, sign);
> +    return f;
> +}
> +
> +uint64_t helper_fsingle_pack2(uint64_t srca)
> +{
> +    return float32_val(sfmt_to_float32(srca));
> +}
> +
> +static uint64_t main_calc(float32 fsrca, float32 fsrcb,
> +                          float32 (*calc)(float32, float32, float_status *))
> +{
> +    uint64_t sfmt = float32_to_sfmt(calc(fsrca, fsrcb, &fp_status));
> +
> +    if (float32_eq(fsrca, fsrcb, &fp_status)) {
> +        sfmt |= create_fsfd_flag_eq();
> +    } else {
> +        sfmt |= create_fsfd_flag_ne();
> +    }
> +
> +    if (float32_lt(fsrca, fsrcb, &fp_status)) {
> +        sfmt |= create_fsfd_flag_lt();
> +    }
> +    if (float32_le(fsrca, fsrcb, &fp_status)) {
> +        sfmt |= create_fsfd_flag_le();
> +    }
> +
> +    if (float32_lt(fsrcb, fsrca, &fp_status)) {
> +        sfmt |= create_fsfd_flag_gt();
> +    }
> +    if (float32_le(fsrcb, fsrca, &fp_status)) {
> +        sfmt |= create_fsfd_flag_ge();
> +    }
> +
> +    if (float32_unordered(fsrca, fsrcb, &fp_status)) {
> +        sfmt |= create_fsfd_flag_un();
> +    }
> +
> +    set_fsingle_calc(&sfmt, TILEGX_F_CALC_NCVT);
> +    return sfmt;
> +}
> +
> +uint64_t helper_fsingle_add1(uint64_t srca, uint64_t srcb)
> +{
> +    return main_calc(make_float32(srca), make_float32(srcb), float32_add);
> +}
> +
> +uint64_t helper_fsingle_sub1(uint64_t srca, uint64_t srcb)
> +{
> +    return main_calc(make_float32(srca), make_float32(srcb), float32_sub);
> +}
> +
> +uint64_t helper_fsingle_mul1(uint64_t srca, uint64_t srcb)
> +{
> +    return main_calc(make_float32(srca), make_float32(srcb), float32_mul);
> +}
>
Chen Gang Dec. 24, 2015, 3:52 p.m. UTC | #2
On 12/24/15 07:07, Richard Henderson wrote:
> On 12/23/2015 01:48 PM, chengang@emindsoft.com.cn wrote:
>> +static float32 sfmt_to_float32(uint64_t sfmt)
>> +{
>> +    uint32_t sign = get_fsingle_sign(sfmt);
>> +    uint32_t man = get_fsingle_man(sfmt);
>> +    uint32_t exp = get_fsingle_exp(sfmt);
>> +    float32 f;
>> +
>> +    if (get_fsingle_calc(sfmt) == TILEGX_F_CALC_CVT) {
>> +        if (sign) {
>> +            f = int32_to_float32(0 - man, &fp_status);
>> +        } else {
>> +            f = uint32_to_float32(man, &fp_status);
>> +        }
>> +        exp += get_f32_exp(f) - 0x9e;
>> +        if ((int32_t) exp < 0) {
>> +            return float32_infinity | float32_set_sign(float32_zero, sign);
>> +        } else if (exp >= 0xff) {
>> +            return float32_zero | float32_set_sign(float32_zero, sign);
>> +        } else {
>> +            set_f32_exp(&f, exp);
>> +        }
> 
> 
> What in the world are you attempting to do here?
> This is not normalization.  This is not even remotely
> correct with respect to zero or infinity.
> 

For fdouble, I use almost the same way, but can get the correct result (
pass gcc testsuite for fdouble, include inf and zero tests). But tests
will never enough, we can not say the fdouble implementation must be OK.

So please help check the fdouble implementation in details, again, when
you have time, it may still have issues.

> Moreover, I thought we agreed to do away with that CALC bit.
> 

OK, I will try, next.

I will copy and reconstruct related code from qemu fpu implementation
instead of (u)int32/64_to_float32/64 functions (just like you said, I
guess).

Hope I can finish within 2015-12-31.

Thanks.
Chen Gang Dec. 27, 2015, 8:31 a.m. UTC | #3
On 12/24/15 23:52, Chen Gang wrote:
> On 12/24/15 07:07, Richard Henderson wrote:
> 
>> Moreover, I thought we agreed to do away with that CALC bit.
>>

After check again, I guess, we can stil reserve CALC bit:

 - Then we can remove float32_to_sfmt (use high 32-bit to save float32
   directly). And in helper_fsingle_pack2, for CALC, we can return high
   32-bit directly.  Only for NCALC, we need process it in details.

 - I guess, most cases are for CALC, so it will let the performance a
   little better (need float32_to_sfmt, then sfmt_to_float32 again).

Then we can only focus on NCAL in helper_fsingle_pack2.

Thanks.

> 
> OK, I will try, next.
> 
> I will copy and reconstruct related code from qemu fpu implementation
> instead of (u)int32/64_to_float32/64 functions (just like you said, I
> guess).
> 
> Hope I can finish within 2015-12-31.
> 
> Thanks.
>
diff mbox

Patch

diff --git a/target-tilegx/helper-fsingle.c b/target-tilegx/helper-fsingle.c
new file mode 100644
index 0000000..b6c3b0e
--- /dev/null
+++ b/target-tilegx/helper-fsingle.c
@@ -0,0 +1,211 @@ 
+/*
+ * QEMU TILE-Gx helpers
+ *
+ *  Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+
+#include "helper-fshared.h"
+
+/*
+ * FSingle instructions implemenation:
+ *
+ * fsingle_add1         ; calc srca and srcb,
+ *                      ; convert float_32 to TileGXFPSFmt result.
+ *                      ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_sub1         ; calc srca and srcb.
+ *                      ; convert float_32 to TileGXFPSFmt result.
+ *                      ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_addsub2      ; nop.
+ *
+ * fsingle_mul1         ; calc srca and srcb.
+ *                      ; convert float_32 value to TileGXFPSFmt result.
+ *                      ; move TileGXFPSFmt result to dest.
+ *
+ * fsingle_mul2         ; move srca to dest.
+ *
+ * fsingle_pack1        ; nop
+ *
+ * fsingle_pack2        ; treate srca as TileGXFPSFmt result.
+ *                      ; convert TileGXFPSFmt result to float_32 value.
+ *                      ; move float_32 value to dest.
+ */
+
+#define TILEGX_F_CALC_CVT   0     /* convert int to fsingle */
+#define TILEGX_F_CALC_NCVT  1     /* Not convertion */
+
+static uint32_t get_f32_exp(float32 f)
+{
+    return extract32(float32_val(f), 23, 8);
+}
+
+static void set_f32_exp(float32 *f, uint32_t exp)
+{
+    *f = make_float32(deposit32(float32_val(*f), 23, 8, exp));
+}
+
+static uint32_t get_f32_man(float32 f)
+{
+    return float32_val(f) & 0x7fffff;
+}
+
+static float32 create_f32_man(uint32_t man)
+{
+     return make_float32(man & 0x7fffff);
+}
+
+static inline uint32_t get_fsingle_exp(uint64_t n)
+{
+    return n & 0xff;
+}
+
+static inline uint64_t create_fsingle_exp(uint32_t exp)
+{
+    return exp & 0xff;
+}
+
+static inline uint32_t get_fsingle_sign(uint64_t n)
+{
+    return test_bit(10, &n);
+}
+
+static inline void set_fsingle_sign(uint64_t *n)
+{
+    set_bit(10, n);
+}
+
+static inline unsigned int get_fsingle_calc(uint64_t n)
+{
+    return test_bit(11, &n);
+}
+
+static inline void set_fsingle_calc(uint64_t *n, uint32_t calc)
+{
+    set_bit(11, n);
+}
+
+static inline unsigned int get_fsingle_man(uint64_t n)
+{
+    return n >> 32;
+}
+
+static inline uint64_t create_fsingle_man(uint32_t man)
+{
+    return (uint64_t)man << 32;
+}
+
+static uint64_t float32_to_sfmt(float32 f)
+{
+    uint64_t sfmt = 0;
+
+    if (float32_is_neg(f)) {
+        set_fsingle_sign(&sfmt);
+    }
+    sfmt |= create_fsingle_exp(get_f32_exp(f));
+    sfmt |= create_fsingle_man((get_f32_man(f) << 8) | (1 << 31));
+
+    return sfmt;
+}
+
+static float32 sfmt_to_float32(uint64_t sfmt)
+{
+    uint32_t sign = get_fsingle_sign(sfmt);
+    uint32_t man = get_fsingle_man(sfmt);
+    uint32_t exp = get_fsingle_exp(sfmt);
+    float32 f;
+
+    if (get_fsingle_calc(sfmt) == TILEGX_F_CALC_CVT) {
+        if (sign) {
+            f = int32_to_float32(0 - man, &fp_status);
+        } else {
+            f = uint32_to_float32(man, &fp_status);
+        }
+        exp += get_f32_exp(f) - 0x9e;
+        if ((int32_t) exp < 0) {
+            return float32_infinity | float32_set_sign(float32_zero, sign);
+        } else if (exp >= 0xff) {
+            return float32_zero | float32_set_sign(float32_zero, sign);
+        } else {
+            set_f32_exp(&f, exp);
+        }
+    } else {
+        f = create_f32_man(man >> 8);
+        set_f32_exp(&f, exp);
+    }
+
+    f = float32_set_sign(f, sign);
+    return f;
+}
+
+uint64_t helper_fsingle_pack2(uint64_t srca)
+{
+    return float32_val(sfmt_to_float32(srca));
+}
+
+static uint64_t main_calc(float32 fsrca, float32 fsrcb,
+                          float32 (*calc)(float32, float32, float_status *))
+{
+    uint64_t sfmt = float32_to_sfmt(calc(fsrca, fsrcb, &fp_status));
+
+    if (float32_eq(fsrca, fsrcb, &fp_status)) {
+        sfmt |= create_fsfd_flag_eq();
+    } else {
+        sfmt |= create_fsfd_flag_ne();
+    }
+
+    if (float32_lt(fsrca, fsrcb, &fp_status)) {
+        sfmt |= create_fsfd_flag_lt();
+    }
+    if (float32_le(fsrca, fsrcb, &fp_status)) {
+        sfmt |= create_fsfd_flag_le();
+    }
+
+    if (float32_lt(fsrcb, fsrca, &fp_status)) {
+        sfmt |= create_fsfd_flag_gt();
+    }
+    if (float32_le(fsrcb, fsrca, &fp_status)) {
+        sfmt |= create_fsfd_flag_ge();
+    }
+
+    if (float32_unordered(fsrca, fsrcb, &fp_status)) {
+        sfmt |= create_fsfd_flag_un();
+    }
+
+    set_fsingle_calc(&sfmt, TILEGX_F_CALC_NCVT);
+    return sfmt;
+}
+
+uint64_t helper_fsingle_add1(uint64_t srca, uint64_t srcb)
+{
+    return main_calc(make_float32(srca), make_float32(srcb), float32_add);
+}
+
+uint64_t helper_fsingle_sub1(uint64_t srca, uint64_t srcb)
+{
+    return main_calc(make_float32(srca), make_float32(srcb), float32_sub);
+}
+
+uint64_t helper_fsingle_mul1(uint64_t srca, uint64_t srcb)
+{
+    return main_calc(make_float32(srca), make_float32(srcb), float32_mul);
+}