From: Chen Gang <cheng...@emindsoft.com.cn> Signed-off-by: Chen Gang <gang.chen.5...@gmail.com> --- target-tilegx/helper-fsingle.c | 201 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 target-tilegx/helper-fsingle.c
diff --git a/target-tilegx/helper-fsingle.c b/target-tilegx/helper-fsingle.c new file mode 100644 index 0000000..68b0396 --- /dev/null +++ b/target-tilegx/helper-fsingle.c @@ -0,0 +1,201 @@ +/* + * 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 "qemu/osdep.h" +#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); +} -- 1.9.3