diff mbox

[v5,3/5] target-tilegx/helper-fsingle.c: Implement single floating point

Message ID 1451773519-10134-4-git-send-email-chengang@emindsoft.com.cn
State New
Headers show

Commit Message

Chen Gang Jan. 2, 2016, 10:25 p.m. UTC
From: Chen Gang <gang.chen.5i5j@gmail.com>

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

Patch

diff --git a/target-tilegx/helper-fsingle.c b/target-tilegx/helper-fsingle.c
new file mode 100644
index 0000000..997d40e
--- /dev/null
+++ b/target-tilegx/helper-fsingle.c
@@ -0,0 +1,200 @@ 
+/*
+ * 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"
+
+#define IMPL_FULL
+
+/*
+ * 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.
+ */
+
+static inline uint32_t get_fsingle_exp(uint64_t n)
+{
+    return n & 0xff;
+}
+
+static inline uint32_t get_fsingle_sign(uint64_t n)
+{
+    return test_bit(10, &n);
+}
+
+static inline unsigned int get_fsingle_man(uint64_t n)
+{
+    return n >> 32;
+}
+
+#ifdef IMPL_FULL
+
+static uint32_t get_f32_exp(float32 f)
+{
+    return extract32(float32_val(f), 23, 8);
+}
+
+static uint32_t get_f32_man(float32 f)
+{
+    return float32_val(f) & 0x7fffff;
+}
+
+static inline void set_fsingle_sign(uint64_t *n)
+{
+    set_bit(10, n);
+}
+
+static inline uint64_t create_fsingle_exp(float32 f)
+{
+    return  get_f32_exp(f) & 0xff;
+}
+
+static inline uint64_t create_fsingle_man(float32 f)
+{
+    if (get_f32_exp(f)) {
+        return (uint64_t)get_f32_man(f) << 40 | (1ULL << 63);
+    }
+    return (uint64_t)get_f32_man(f) << 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(f);
+    sfmt |= create_fsingle_man(f);
+
+    return sfmt;
+}
+
+#else
+
+#define TILEGX_F_CALC_CVT   0     /* convert int to fsingle */
+#define TILEGX_F_CALC_NCVT  1     /* Not convertion */
+
+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 uint64_t float32_to_sfmt(float32 f)
+{
+    return (uint64_t)float32_val(f) << 32;
+}
+
+#endif
+
+uint64_t helper_fsingle_pack2(uint64_t srca)
+{
+    DEC_INIT_FPSTATUS;
+
+#ifndef IMPL_FULL
+    if (get_fsingle_calc(srca) == TILEGX_F_CALC_NCVT) {
+        return srca >> 32;
+    }
+#endif
+    return float32_val(normalize_roundpack_float32(get_fsingle_sign(srca),
+                                                   get_fsingle_exp(srca),
+                                                   get_fsingle_man(srca),
+                                                   &fp_status));
+}
+
+static uint64_t main_calc(float32 fsrca, float32 fsrcb,
+                          float32 (*calc)(float32, float32, float_status*))
+{
+    DEC_INIT_FPSTATUS;
+    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();
+    }
+
+#ifndef IMPL_FULL
+    set_fsingle_calc(&sfmt, TILEGX_F_CALC_NCVT);
+#endif
+    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);
+}