From patchwork Sat Oct 31 16:59:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chen Gang X-Patchwork-Id: 538665 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id C8FBD141393 for ; Sun, 1 Nov 2015 04:00:23 +1100 (AEDT) Received: from localhost ([::1]:56433 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZsZVt-0001AG-88 for incoming@patchwork.ozlabs.org; Sat, 31 Oct 2015 13:00:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52390) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZsZVR-0000nU-VL for qemu-devel@nongnu.org; Sat, 31 Oct 2015 12:59:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZsZVO-0003C9-KP for qemu-devel@nongnu.org; Sat, 31 Oct 2015 12:59:53 -0400 Received: from col004-omc2s13.hotmail.com ([65.55.34.87]:54206) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZsZVO-0003Bu-1F for qemu-devel@nongnu.org; Sat, 31 Oct 2015 12:59:50 -0400 Received: from COL130-W6 ([65.55.34.73]) by COL004-OMC2S13.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Sat, 31 Oct 2015 09:59:49 -0700 X-TMN: [+EMCsWRApit80mtpA28y6Q2Lpz2GM6HB] X-Originating-Email: [xili_gchen_5257@hotmail.com] Message-ID: From: Chen Gang To: "rth@twiddle.net" , Peter Maydell , Chris Metcalf Date: Sun, 1 Nov 2015 00:59:48 +0800 Importance: Normal MIME-Version: 1.0 X-OriginalArrivalTime: 31 Oct 2015 16:59:49.0037 (UTC) FILETIME=[8D65D5D0:01D113FD] X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 65.55.34.87 Cc: qemu-devel Subject: [Qemu-devel] [PATCH] target-tilegx: Implement floating point instructions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From 42733d085bfcb4882cfa4eb25a9387e3d953a64f Mon Sep 17 00:00:00 2001 From: Chen Gang 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 ---  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 --  1.9.3 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 + * + */ + +#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 . + */ +#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 + * + */ + +#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;