>From 3270485ebd56429f6f62f0a4f967009d8a1b14d6 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 8 Nov 2015 09:08:40 +0800 Subject: [PATCH 2/4] target-tilegx: Implement fpu single floating point  instructions Signed-off-by: Chen Gang ---  target-tilegx/fsingle_helper.c | 168 +++++++++++++++++++++++++++++++++++++++++  1 file changed, 168 insertions(+)  create mode 100644 target-tilegx/fsingle_helper.c diff --git a/target-tilegx/fsingle_helper.c b/target-tilegx/fsingle_helper.c new file mode 100644 index 0000000..f8f6b69 --- /dev/null +++ b/target-tilegx/fsingle_helper.c @@ -0,0 +1,168 @@ +/* + * 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, float_status *fp_status) +{ +    F32Fmt f; + +    if (sfmt.calc == TILEGX_F_CALC_CVT) { +        if (sfmt.sign) +            f.f = int32_to_float32(0 - sfmt.mantissa, fp_status); +        else +            f.f = uint32_to_float32(sfmt.mantissa, fp_status); +    } else { +        f.bits.sign = sfmt.sign; +        f.bits.exp = sfmt.exp; +        f.bits.frac = sfmt.mantissa>> 8; +    } + +    return f.f; +} + +uint64_t helper_fsingle_pack2(CPUTLGState *env, uint64_t srca) +{ +    return float32_val(sfmt_to_float32(uint64_to_sfmt(srca), &env->fp_status)); +} + +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); + +    if (calc == float32_add) +        sfmt.calc = TILEGX_F_CALC_ADD; +    else if (calc == float32_sub) +        sfmt.calc = TILEGX_F_CALC_SUB; +    else +        sfmt.calc = TILEGX_F_CALC_MUL; + +    sfmt_to_float32(sfmt, fp_status); + +    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); +} --  1.9.3