[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] target-tilegx: Implement floating point instruction
From: |
Chen Gang |
Subject: |
[Qemu-devel] [PATCH] target-tilegx: Implement floating point instructions |
Date: |
Sun, 1 Nov 2015 00:59:48 +0800 |
>From 42733d085bfcb4882cfa4eb25a9387e3d953a64f Mon Sep 17 00:00:00 2001
From: Chen Gang <address@hidden>
Date: Sun, 1 Nov 2015 00:50:33 +0800
Subject: [PATCH] target-tilegx: Implement floating point instructions
It is implenented in a normal way, and passed unit tests (8 test cases).
Signed-off-by: Chen Gang <address@hidden>
---
target-tilegx/Makefile.objs | 3 +-
target-tilegx/cpu.h | 2 +
target-tilegx/fdouble_helper.c | 234 +++++++++++++++++++++++++++++++++++++++++
target-tilegx/fpu.h | 217 ++++++++++++++++++++++++++++++++++++++
target-tilegx/fsingle_helper.c | 157 +++++++++++++++++++++++++++
target-tilegx/helper.h | 12 +++
target-tilegx/translate.c | 68 ++++++++++--
7 files changed, 683 insertions(+), 10 deletions(-)
create mode 100644 target-tilegx/fdouble_helper.c
create mode 100644 target-tilegx/fpu.h
create mode 100644 target-tilegx/fsingle_helper.c
diff --git a/target-tilegx/Makefile.objs b/target-tilegx/Makefile.objs
index 0db778f..c2cf2f1 100644
--- a/target-tilegx/Makefile.objs
+++ b/target-tilegx/Makefile.objs
@@ -1 +1,2 @@
-obj-y += cpu.o translate.o helper.o simd_helper.o
+obj-y += cpu.o translate.o helper.o simd_helper.o \
+ fsingle_helper.o fdouble_helper.o
diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h
index 03df107..445a606 100644
--- a/target-tilegx/cpu.h
+++ b/target-tilegx/cpu.h
@@ -88,6 +88,8 @@ typedef struct CPUTLGState {
uint64_t spregs[TILEGX_SPR_COUNT]; /* Special used registers by outside */
uint64_t pc; /* Current pc */
+ float_status fp_status; /* floating point status */
+
#if defined(CONFIG_USER_ONLY)
uint64_t excaddr; /* exception address */
uint64_t atomic_srca; /* Arguments to atomic "exceptions" */
diff --git a/target-tilegx/fdouble_helper.c b/target-tilegx/fdouble_helper.c
new file mode 100644
index 0000000..b3b0588
--- /dev/null
+++ b/target-tilegx/fdouble_helper.c
@@ -0,0 +1,234 @@
+/*
+ * 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 "fpu.h"
+
+#define TILEGX_F_MAN_HBIT (1ULL << 59)
+
+#pragma pack(push, 1)
+typedef union F64Fmt {
+ float64 d;
+ struct {
+#if defined(HOST_WORDS_BIGENDIAN)
+ uint64_t sign : 1;
+ uint64_t exp : 11;
+ uint64_t frac : 52;
+#else
+ uint64_t frac : 52;
+ uint64_t exp : 11;
+ uint64_t sign : 1;
+#endif
+ } bits;
+} F64Fmt;
+#pragma pack(pop)
+
+static uint64_t fr_to_man(F64Fmt v)
+{
+ uint64_t val = (uint64_t)v.bits.frac << 7;
+
+ if (v.bits.exp)
+ val |= TILEGX_F_MAN_HBIT;
+
+ return val;
+}
+
+uint64_t helper_fdouble_unpack_min(CPUTLGState *env,
+ uint64_t srca, uint64_t srcb)
+{
+ F64Fmt va, vb;
+ TileGXFPDFmtV v;
+
+ va.d = make_float64(srca);
+ vb.d = make_float64(srcb);
+ v.ll = 0; /* also cause v.fmt.overflow = 0 */
+
+ if (va.bits.exp> vb.bits.exp)
+ v.fmt.mantissa = fr_to_man(vb)>> (va.bits.exp - vb.bits.exp);
+ else if (va.bits.exp < vb.bits.exp)
+ v.fmt.mantissa = fr_to_man(va)>> (vb.bits.exp - va.bits.exp);
+ else if (va.bits.frac> vb.bits.frac)
+ v.fmt.mantissa = fr_to_man(vb);
+ else
+ v.fmt.mantissa = fr_to_man(va);
+
+ return v.ll;
+}
+
+uint64_t helper_fdouble_unpack_max(CPUTLGState *env,
+ uint64_t srca, uint64_t srcb)
+{
+ F64Fmt va, vb;
+ TileGXFPDFmtV v;
+
+ va.d = make_float64(srca);
+ vb.d = make_float64(srcb);
+ v.ll = 0; /* also cause v.fmt.overflow = 0 */
+
+ if (va.bits.exp> vb.bits.exp)
+ v.fmt.mantissa = fr_to_man(va);
+ else if (va.bits.exp < vb.bits.exp)
+ v.fmt.mantissa = fr_to_man(vb);
+ else if (va.bits.frac> vb.bits.frac)
+ v.fmt.mantissa = fr_to_man(va);
+ else
+ v.fmt.mantissa = fr_to_man(vb);
+
+ return v.ll;
+}
+
+uint64_t helper_fdouble_addsub(CPUTLGState *env,
+ uint64_t dest, uint64_t srca, uint64_t srcb)
+{
+ TileGXFPDFmtF flags;
+ TileGXFPDFmtV v;
+
+ flags.ll = srcb;
+ if (flags.fmt.addsub == TILEGX_F_ADDSUB_ADD) {
+ v.ll = dest + srca; /* maybe set addsub overflow bit */
+ } else
+ v.ll = dest - srca;
+
+ return v.ll;
+}
+
+uint64_t helper_fdouble_pack2(CPUTLGState *env,
+ uint64_t dest, uint64_t srca, uint64_t srcb)
+{
+ TileGXFPDFmtF flags;
+ TileGXFPDFmtV v;
+ F64Fmt d;
+
+ flags.ll = dest;
+ v.ll = srca;
+
+ /*
+ * Assume fdouble_add_flags, fdouble_sub_flags, or fdouble_mul_flags
+ * already processed any exceptions.
+ */
+
+ /* only absolute-add can cause addsub overflow, it may not be exception */
+ if (v.fmt.overflow && (flags.fmt.exp < TILEGX_F_EXP_DMAX)) {
+ flags.fmt.exp++;
+ srcb>>= 1;
+ srcb |= (uint64_t)v.fmt.mantissa << 63;
+ v.fmt.mantissa>>= 1;
+ v.fmt.mantissa |= TILEGX_F_MAN_HBIT;
+ }
+
+ while (flags.fmt.exp && !(v.fmt.mantissa & TILEGX_F_MAN_HBIT)) {
+ flags.fmt.exp--;
+ v.fmt.mantissa <<= 1;
+ v.fmt.mantissa |= srcb>> 63;
+ srcb <<= 1;
+ }
+
+ d.bits.sign = flags.fmt.sign;
+ d.bits.exp = flags.fmt.exp;
+ d.bits.frac = v.fmt.mantissa>> 7;
+
+ return float64_val(d.d);
+}
+
+static void ana_bits(float_status *fp_status,
+ float64 fsrca, float64 fsrcb, TileGXFPDFmtF *dfmt)
+{
+ if (float64_eq(fsrca, fsrcb, fp_status)) {
+ dfmt->fmt.eq = 1;
+ } else {
+ dfmt->fmt.neq = 1;
+ }
+
+ if (float64_lt(fsrca, fsrcb, fp_status)) {
+ dfmt->fmt.lt = 1;
+ }
+ if (float64_le(fsrca, fsrcb, fp_status)) {
+ dfmt->fmt.le = 1;
+ }
+
+ if (float64_lt(fsrcb, fsrca, fp_status)) {
+ dfmt->fmt.gt = 1;
+ }
+ if (float64_le(fsrcb, fsrca, fp_status)) {
+ dfmt->fmt.ge = 1;
+ }
+
+ if (float64_unordered(fsrca, fsrcb, fp_status)) {
+ dfmt->fmt.unordered = 1;
+ }
+}
+
+static uint64_t main_calc(float_status *fp_status,
+ float64 fsrca, float64 fsrcb,
+ float64 (*calc)(float64, float64, float_status *))
+{
+ F64Fmt va, vb, vf;
+ TileGXFPDFmtF flags;
+
+ flags.ll = 0;
+ ana_bits(fp_status, fsrca, fsrcb, &flags);
+
+ vf.d = calc(fsrca, fsrcb, fp_status); /* also check exceptions */
+ flags.fmt.sign = vf.bits.sign;
+
+ va.d = fsrca;
+ vb.d = fsrcb;
+ if (calc == float64_add) {
+ flags.fmt.exp = (va.bits.exp> vb.bits.exp) ? va.bits.exp : vb.bits.exp;
+ flags.fmt.addsub = (va.bits.sign == vb.bits.sign)
+ ? TILEGX_F_ADDSUB_ADD : TILEGX_F_ADDSUB_SUB;
+
+ } else if (calc == float64_sub) {
+ flags.fmt.exp = (va.bits.exp> vb.bits.exp) ? va.bits.exp : vb.bits.exp;
+ flags.fmt.addsub = (va.bits.sign != vb.bits.sign)
+ ? TILEGX_F_ADDSUB_ADD : TILEGX_F_ADDSUB_SUB;
+
+ } else /* It's float64_mul, don't need flags.addsub */
+ flags.fmt.exp = ((uint64_t)va.bits.exp + (uint64_t)vb.bits.exp
+ <= TILEGX_F_EXP_DMAX)
+ ? va.bits.exp + vb.bits.exp : vf.bits.exp;
+
+ return flags.ll;
+}
+
+uint64_t helper_fdouble_add_flags(CPUTLGState *env,
+ uint64_t srca, uint64_t srcb)
+{
+ return main_calc(&env->fp_status,
+ make_float64(srca), make_float64(srcb), float64_add);
+}
+
+uint64_t helper_fdouble_sub_flags(CPUTLGState *env,
+ uint64_t srca, uint64_t srcb)
+{
+ return main_calc(&env->fp_status,
+ make_float64(srca), make_float64(srcb), float64_sub);
+}
+
+uint64_t helper_fdouble_mul_flags(CPUTLGState *env,
+ uint64_t srca, uint64_t srcb)
+{
+ return main_calc(&env->fp_status,
+ make_float64(srca), make_float64(srcb), float64_mul);
+}
diff --git a/target-tilegx/fpu.h b/target-tilegx/fpu.h
new file mode 100644
index 0000000..3421c05
--- /dev/null
+++ b/target-tilegx/fpu.h
@@ -0,0 +1,217 @@
+/*
+ * TILE-Gx virtual FPU header
+ *
+ * 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 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
+ * 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/>.
+ */
+#ifndef FPU_TILEGX_H
+#define FPU_TILEGX_H
+
+/*
+ * From IEEE standard, exp of float is 8-bits, exp of double is 11-bits.
+ */
+#define TILEGX_F_EXP_FZERO 0x7f /* Zero exp for single 8-bits */
+#define TILEGX_F_EXP_DZERO 0x3ff /* Zero exp for double 11-bits */
+#define TILEGX_F_EXP_DMAX 0x7ff /* max exp for double 11-bits */
+
+/*
+ * For fdouble addsub bit
+ */
+#define TILEGX_F_ADDSUB_ADD 0 /* Perform absolute add operation */
+#define TILEGX_F_ADDSUB_SUB 1 /* Perform absolute sub operation */
+
+#pragma pack(push, 1)
+
+/*
+ * Single format, it is 64-bit.
+ *
+ * Single exp analyzing: 0x9e - 0x1e(30) = 0x80
+ *
+ * 7 6 5 4 3 2 1 0
+ *
+ * 1 0 0 1 1 1 1 0
+ *
+ * 0 0 0 1 1 1 1 1 => 0x1f(31)
+ *
+ * 0 1 1 1 1 1 1 1 => 0x7f
+ */
+typedef struct TileGXFPSFmt {
+
+#if !defined(HOST_WORDS_BIGENDIAN)
+ /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */
+ uint64_t exp : 8; /* exp, 0x9e: 31 + TILEGX_F_EXP_FZERO */
+ uint64_t uiknown0 : 1; /* unknown */
+ uint64_t sign : 1; /* Sign bit for the total value */
+ uint64_t unknown1 : 15; /* unknown */
+
+ /* Come from TILE-Gx ISA document, Table 7-2 for floating point */
+ uint64_t unordered : 1; /* The two are unordered */
+ uint64_t lt : 1; /* 1st is less than 2nd */
+ uint64_t le : 1; /* 1st is less than or equal to 2nd */
+ uint64_t gt : 1; /* 1st is greater than 2nd */
+ uint64_t ge : 1; /* 1st is greater than or equal to 2nd */
+ uint64_t eq : 1; /* The two operands are equal */
+ uint64_t neq : 1; /* The two operands are not equal */
+
+ /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */
+ uint64_t mantissa : 32; /* mantissa */
+#else
+ uint64_t mantissa : 32; /* mantissa */
+ uint64_t neq : 1; /* The two operands are not equal */
+ uint64_t eq : 1; /* The two operands are equal */
+ uint64_t ge : 1; /* 1st is greater than or equal to 2nd */
+ uint64_t gt : 1; /* 1st is greater than 2nd */
+ uint64_t le : 1; /* 1st is less than or equal to 2nd */
+ uint64_t lt : 1; /* 1st is less than 2nd */
+ uint64_t unordered : 1; /* The two are unordered */
+ uint64_t unknown1 : 15; /* unknown */
+ uint64_t sign : 1; /* Sign bit for the total value */
+ uint64_t unknown0 : 1; /* unknown */
+ uint64_t exp : 8; /* exp, 0x9e: 31 + TILEGX_F_EXP_FZERO */
+#endif
+} TileGXFPSFmt;
+/*
+ * 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.
+ */
+
+/*
+ * Dobule format. flag: 64 bits, value: 64 bits.
+ *
+ * Double exp analyzing: (0x21b00 << 1) - 0x36(54) = 0x400
+ *
+ * 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ *
+ * 1 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0
+ *
+ * 0 0 0 0 0 1 1 0 1 1 1 => 0x37(55)
+ *
+ * 0 1 1 1 1 1 1 1 1 1 1 => 0x3ff
+ *
+ */
+typedef union TileGXFPDFmtF {
+
+ struct {
+#if !defined(HOST_WORDS_BIGENDIAN)
+ uint64_t unknown0 : 7; /* unknown */
+ uint64_t exp : 11; /* exp, 0x21b << 1: 55 + TILEGX_F_EXP_DZERO
*/
+ uint64_t unknown1 : 2; /* unknown */
+ uint64_t sign : 1; /* Sign bit for the total value */
+
+ uint64_t addsub: 1; /* add or sub bit */
+ uint64_t unknown2: 3; /* unknown */
+
+ /* Come from TILE-Gx ISA document, Table 7-2 for floating point */
+ uint64_t unordered : 1; /* The two are unordered */
+ uint64_t lt : 1; /* 1st is less than 2nd */
+ uint64_t le : 1; /* 1st is less than or equal to 2nd */
+ uint64_t gt : 1; /* 1st is greater than 2nd */
+ uint64_t ge : 1; /* 1st is greater than or equal to 2nd */
+ uint64_t eq : 1; /* The two operands are equal */
+ uint64_t neq : 1; /* The two operands are not equal */
+
+ uint64_t unknown3 : 32; /* unknown */
+#else
+ uint64_t unknown3 : 32; /* unknown */
+ uint64_t neq : 1; /* The two operands are not equal */
+ uint64_t eq : 1; /* The two operands are equal */
+ uint64_t ge : 1; /* 1st is greater than or equal to 2nd */
+ uint64_t gt : 1; /* 1st is greater than 2nd */
+ uint64_t le : 1; /* 1st is less than or equal to 2nd */
+ uint64_t lt : 1; /* 1st is less than 2nd */
+ uint64_t unordered : 1; /* The two are unordered */
+ uint64_t unknown2: 3; /* unknown */
+ uint64_t addsub: 1; /* add or sub bit */
+ uint64_t sign : 1; /* Sign bit for the total value */
+ uint64_t unknown1 : 2; /* unknown */
+ uint64_t exp : 11; /* exp, 0x21b << 1: 55 + TILEGX_F_EXP_DZERO
*/
+ uint64_t unknown0 : 7; /* unknown */
+#endif
+ } fmt;
+ uint64_t ll; /* only for easy using */
+} TileGXFPDFmtF;
+
+typedef union TileGXFPDFmtV {
+ struct {
+#if !defined(HOST_WORDS_BIGENDIAN)
+ uint64_t mantissa : 60; /* mantissa */
+ uint64_t overflow : 1; /* overflow bit for addsub */
+ uint64_t unknown1 : 3; /* unknown */
+#else
+ uint64_t unknown1 : 3; /* unknown */
+ uint64_t overflow : 1; /* overflow bit for addsub */
+ uint64_t mantissa : 60; /* mantissa */
+#endif
+ } fmt;
+ uint64_t ll; /* only for easy using */
+} TileGXFPDFmtV;
+/*
+ * FDouble instructions implemenation:
+ *
+ * fdouble_unpack_min ; srca and srcb are float_64 value.
+ * ; get the min absolute value's mantissa.
+ * ; move "mantissa>> (exp_max - exp_min)" to dest.
+ *
+ * fdouble_unpack_max ; srca and srcb are float_64 value.
+ * ; get the max absolute value's mantissa.
+ * ; move mantissa to dest.
+ *
+ * fdouble_add_flags ; srca and srcb are float_64 value.
+ * ; calc exp (exp_max), sign, and comp bits for flags.
+ * ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_sub_flags ; srca and srcb are float_64 value.
+ * ; calc exp (exp_max), sign, and comp bits for flags.
+ * ; set addsub bit to flags and move flags to dest.
+ *
+ * fdouble_addsub: ; dest, srca (max, min mantissa), and srcb (flags).
+ * ; "dest +/- srca" depend on the add/sub bit of flags.
+ * ; move result mantissa to dest.
+ *
+ * fdouble_mul_flags: ; srca and srcb are float_64 value.
+ * ; calc sign (xor), exp (exp_min + exp_max), and comp
bits.
+ * ; mix sign, exp, and comp bits as flags to dest.
+ *
+ * fdouble_pack1 ; move srcb (flags) to dest.
+ *
+ * fdouble_pack2 ; srca, srcb (high, low mantissa), and dest (flags)
+ * ; normalize and pack result from srca, srcb, and dest.
+ * ; move result to dest.
+ */
+
+#pragma pack(pop)
+
+#endif /* FPU_TILEGX_H */
diff --git a/target-tilegx/fsingle_helper.c b/target-tilegx/fsingle_helper.c
new file mode 100644
index 0000000..95ff9f4
--- /dev/null
+++ b/target-tilegx/fsingle_helper.c
@@ -0,0 +1,157 @@
+/*
+ * 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 "fpu.h"
+
+#pragma pack(push, 1)
+typedef union F32Fmt {
+ uint32_t f;
+ struct {
+#if defined(HOST_WORDS_BIGENDIAN)
+ uint32_t sign : 1;
+ uint32_t exp : 8;
+ uint32_t frac : 23;
+#else
+ uint32_t frac : 23;
+ uint32_t exp : 8;
+ uint32_t sign : 1;
+#endif
+ } bits;
+} F32Fmt;
+#pragma pack(pop)
+
+static uint64_t sfmt_to_uint64(TileGXFPSFmt a)
+{
+ union {
+ TileGXFPSFmt a;
+ uint64_t v;
+ } t;
+ t.a = a;
+ return t.v;
+}
+
+static TileGXFPSFmt uint64_to_sfmt(uint64 v)
+{
+ union {
+ TileGXFPSFmt a;
+ uint64_t v;
+ } t;
+ t.v = v;
+ return t.a;
+}
+
+static TileGXFPSFmt float32_to_sfmt(float32 f)
+{
+ F32Fmt tmp = {f};
+ union {
+ TileGXFPSFmt fmt;
+ uint64_t v;
+ } sfmt;
+
+ sfmt.v = 0;
+ sfmt.fmt.sign = tmp.bits.sign;
+ sfmt.fmt.exp = tmp.bits.exp;
+ sfmt.fmt.mantissa = (tmp.bits.frac << 8) | (1 << 31);
+
+ return sfmt.fmt;
+}
+
+static float32 sfmt_to_float32(TileGXFPSFmt sfmt)
+{
+ F32Fmt f;
+
+ while (sfmt.exp && !(sfmt.mantissa & (1ULL << 31))) {
+ sfmt.exp--;
+ sfmt.mantissa <<= 1;
+ }
+
+ f.bits.sign = sfmt.sign;
+ f.bits.exp = sfmt.exp;
+ f.bits.frac = sfmt.mantissa>> 8;
+
+ return f.f;
+}
+
+uint64_t helper_fsingle_pack2(uint64_t srca)
+{
+ return float32_val(sfmt_to_float32(uint64_to_sfmt(srca)));
+}
+
+static void ana_bits(float_status *fp_status,
+ float32 fsrca, float32 fsrcb, TileGXFPSFmt *sfmt)
+{
+ if (float32_eq(fsrca, fsrcb, fp_status)) {
+ sfmt->eq = 1;
+ } else {
+ sfmt->neq = 1;
+ }
+
+ if (float32_lt(fsrca, fsrcb, fp_status)) {
+ sfmt->lt = 1;
+ }
+ if (float32_le(fsrca, fsrcb, fp_status)) {
+ sfmt->le = 1;
+ }
+
+ if (float32_lt(fsrcb, fsrca, fp_status)) {
+ sfmt->gt = 1;
+ }
+ if (float32_le(fsrcb, fsrca, fp_status)) {
+ sfmt->ge = 1;
+ }
+
+ if (float32_unordered(fsrca, fsrcb, fp_status)) {
+ sfmt->unordered = 1;
+ }
+}
+
+static uint64_t main_calc(float_status *fp_status,
+ float32 fsrca, float32 fsrcb,
+ float32 (*calc)(float32, float32, float_status *))
+{
+ TileGXFPSFmt sfmt = float32_to_sfmt(calc(fsrca, fsrcb, fp_status));
+
+ ana_bits(fp_status, fsrca, fsrcb, &sfmt);
+
+ return sfmt_to_uint64(sfmt);
+}
+
+uint64_t helper_fsingle_add1(CPUTLGState *env, uint64_t srca, uint64_t srcb)
+{
+ return main_calc(&env->fp_status,
+ make_float32(srca), make_float32(srcb), float32_add);
+}
+
+uint64_t helper_fsingle_sub1(CPUTLGState *env, uint64_t srca, uint64_t srcb)
+{
+ return main_calc(&env->fp_status,
+ make_float32(srca), make_float32(srcb), float32_sub);
+}
+
+uint64_t helper_fsingle_mul1(CPUTLGState *env, uint64_t srca, uint64_t srcb)
+{
+ return main_calc(&env->fp_status,
+ make_float32(srca), make_float32(srcb), float32_mul);
+}
diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h
index 9281d0f..6c40762 100644
--- a/target-tilegx/helper.h
+++ b/target-tilegx/helper.h
@@ -24,3 +24,15 @@ DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+
+DEF_HELPER_3(fsingle_add1, i64, env, i64, i64)
+DEF_HELPER_3(fsingle_sub1, i64, env, i64, i64)
+DEF_HELPER_3(fsingle_mul1, i64, env, i64, i64)
+DEF_HELPER_1(fsingle_pack2, i64, i64)
+DEF_HELPER_3(fdouble_unpack_min, i64, env, i64, i64)
+DEF_HELPER_3(fdouble_unpack_max, i64, env, i64, i64)
+DEF_HELPER_3(fdouble_add_flags, i64, env, i64, i64)
+DEF_HELPER_3(fdouble_sub_flags, i64, env, i64, i64)
+DEF_HELPER_4(fdouble_addsub, i64, env, i64, i64, i64)
+DEF_HELPER_3(fdouble_mul_flags, i64, env, i64, i64)
+DEF_HELPER_4(fdouble_pack2, i64, env, i64, i64, i64)
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index b8ca401..4c6f07c 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -597,6 +597,11 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned
opext,
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]);
return ret;
+
+ case OE_RR_X0(FSINGLE_PACK1):
+ case OE_RR_Y0(FSINGLE_PACK1):
+ mnemonic = "fsingle_pack1";
+ goto done2;
}
tdest = dest_gr(dc, dest);
@@ -613,9 +618,6 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned
opext,
gen_helper_cnttz(tdest, tsrca);
mnemonic = "cnttz";
break;
- case OE_RR_X0(FSINGLE_PACK1):
- case OE_RR_Y0(FSINGLE_PACK1):
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RR_X1(LD1S):
memop = MO_SB;
mnemonic = "ld1s"; /* prefetch_l1_fault */
@@ -734,6 +736,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned
opext,
return TILEGX_EXCP_OPCODE_UNKNOWN;
}
+done2:
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,
reg_names[dest], reg_names[srca]);
return ret;
@@ -742,13 +745,21 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned
opext,
static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
unsigned dest, unsigned srca, unsigned srcb)
{
- TCGv tdest = dest_gr(dc, dest);
- TCGv tsrca = load_gr(dc, srca);
- TCGv tsrcb = load_gr(dc, srcb);
+ TCGv tdest, tsrca, tsrcb;
TCGv t0;
const char *mnemonic;
switch (opext) {
+ case OE_RRR(FSINGLE_ADDSUB2, 0, X0):
+ mnemonic = "fsingle_addsub2";
+ goto done2;
+ }
+
+ tdest = dest_gr(dc, dest);
+ tsrca = load_gr(dc, srca);
+ tsrcb = load_gr(dc, srcb);
+
+ switch (opext) {
case OE_RRR(ADDXSC, 0, X0):
case OE_RRR(ADDXSC, 0, X1):
gen_saturate_op(tdest, tsrca, tsrcb, tcg_gen_add_tl);
@@ -906,14 +917,39 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned
opext,
mnemonic = "exch";
break;
case OE_RRR(FDOUBLE_ADDSUB, 0, X0):
+ gen_helper_fdouble_addsub(tdest, cpu_env,
+ load_gr(dc, dest),tsrca, tsrcb);
+ mnemonic = "fdouble_addsub";
+ break;
case OE_RRR(FDOUBLE_ADD_FLAGS, 0, X0):
+ gen_helper_fdouble_add_flags(tdest, cpu_env, tsrca, tsrcb);
+ mnemonic = "fdouble_add_flags";
+ break;
case OE_RRR(FDOUBLE_MUL_FLAGS, 0, X0):
+ gen_helper_fdouble_mul_flags(tdest, cpu_env, tsrca, tsrcb);
+ mnemonic = "fdouble_mul_flags";
+ break;
case OE_RRR(FDOUBLE_PACK1, 0, X0):
+ tcg_gen_mov_i64(tdest, tsrcb);
+ mnemonic = "fdouble_pack1";
+ break;
case OE_RRR(FDOUBLE_PACK2, 0, X0):
+ gen_helper_fdouble_pack2(tdest, cpu_env,
+ load_gr(dc, dest), tsrca, tsrcb);
+ mnemonic = "fdouble_pack2";
+ break;
case OE_RRR(FDOUBLE_SUB_FLAGS, 0, X0):
+ gen_helper_fdouble_sub_flags(tdest, cpu_env, tsrca, tsrcb);
+ mnemonic = "fdouble_sub_flags";
+ break;
case OE_RRR(FDOUBLE_UNPACK_MAX, 0, X0):
+ gen_helper_fdouble_unpack_max(tdest, cpu_env, tsrca, tsrcb);
+ mnemonic = "fdouble_unpack_max";
+ break;
case OE_RRR(FDOUBLE_UNPACK_MIN, 0, X0):
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ gen_helper_fdouble_unpack_min(tdest, cpu_env, tsrca, tsrcb);
+ mnemonic = "fdouble_unpack_min";
+ break;
case OE_RRR(FETCHADD4, 0, X1):
gen_atomic_excp(dc, dest, tdest, tsrca, tsrcb,
TILEGX_EXCP_OPCODE_FETCHADD4);
@@ -955,12 +991,25 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned
opext,
mnemonic = "fetchor";
break;
case OE_RRR(FSINGLE_ADD1, 0, X0):
- case OE_RRR(FSINGLE_ADDSUB2, 0, X0):
+ gen_helper_fsingle_add1(tdest, cpu_env, tsrca, tsrcb);
+ mnemonic = "fsingle_add1";
+ break;
case OE_RRR(FSINGLE_MUL1, 0, X0):
+ gen_helper_fsingle_mul1(tdest, cpu_env, tsrca, tsrcb);
+ mnemonic = "fsingle_mul1";
+ break;
case OE_RRR(FSINGLE_MUL2, 0, X0):
+ tcg_gen_mov_i64(tdest, tsrca);
+ mnemonic = "fsingle_mul2";
+ break;
case OE_RRR(FSINGLE_PACK2, 0, X0):
+ gen_helper_fsingle_pack2(tdest, tsrca);
+ mnemonic = "fsingle_pack2";
+ break;
case OE_RRR(FSINGLE_SUB1, 0, X0):
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ gen_helper_fsingle_sub1(tdest, cpu_env, tsrca, tsrcb);
+ mnemonic = "fsingle_sub1";
+ break;
case OE_RRR(MNZ, 0, X0):
case OE_RRR(MNZ, 0, X1):
case OE_RRR(MNZ, 4, Y0):
@@ -1464,6 +1513,7 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned
opext,
return TILEGX_EXCP_OPCODE_UNKNOWN;
}
+done2:
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %s", mnemonic,
reg_names[dest], reg_names[srca], reg_names[srcb]);
return TILEGX_EXCP_NONE;
--
1.9.3
0001-target-tilegx-Implement-floating-point-instructions.patch
Description: Binary data
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] target-tilegx: Implement floating point instructions,
Chen Gang <=