From 1f75cba8f8e0acb079b196e73874595b9523094f Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 21 Mar 2016 09:03:01 +0100 Subject: [PATCH 01/10] target-tricore: add missing break in insn decode switch stmt After decoding/translating a RRR_DIVIDE/RRRR_EXTRACT_INSERT type instruction we would simply fall through and would decode/translate another unintended RRR2_MADD/RRRW_EXTRACT_INSERT instruction. Signed-off-by: Bastian Koppelmann Message-Id: <1458547383-23102-2-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index d13e5c8c62..66f798a9b9 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -8632,6 +8632,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) break; case OPCM_32_RRR_DIVIDE: decode_rrr_divide(env, ctx); + break; /* RRR2 Format */ case OPCM_32_RRR2_MADD: decode_rrr2_madd(env, ctx); @@ -8661,6 +8662,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) /* RRRR format */ case OPCM_32_RRRR_EXTRACT_INSERT: decode_rrrr_extract_insert(env, ctx); + break; /* RRRW format */ case OPCM_32_RRRW_EXTRACT_INSERT: decode_rrrw_extract_insert(env, ctx); From 9029710b9ead9c11649ec142d18581412d8f3e68 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 21 Mar 2016 09:03:02 +0100 Subject: [PATCH 02/10] target-tricore: Fix helper_msub64_q_ssov not reseting OVF bit When this instruction does not produce an overflow the corresponding bit has to be reset. Signed-off-by: Bastian Koppelmann Message-Id: <1458547383-23102-3-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/op_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 55f6724da8..40656c357c 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -1045,6 +1045,8 @@ uint64_t helper_msub64_q_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2, } else { result = INT64_MIN; } + } else { + env->PSW_USB_V = 0; } } else { if (ovf < 0) { From 1bd3e2fc3de683941f18e346a1793b81b20cab2d Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 21 Mar 2016 09:03:03 +0100 Subject: [PATCH 03/10] target-tricore: Fix psw_read() clearing too many bits psw_read() ought to sync the PSW value with the cached status bits (C,V,SV,AV,SAV). For this the bits are cleared in the PSW before they are written from the cached bits. The clear mask is too big and clears two additional bits. Signed-off-by: Bastian Koppelmann Message-Id: <1458547383-23102-4-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-tricore/helper.c b/target-tricore/helper.c index 7d96daddb1..adbb6db10d 100644 --- a/target-tricore/helper.c +++ b/target-tricore/helper.c @@ -113,7 +113,7 @@ void tricore_cpu_list(FILE *f, fprintf_function cpu_fprintf) uint32_t psw_read(CPUTriCoreState *env) { /* clear all USB bits */ - env->PSW &= 0xffffff; + env->PSW &= 0x6ffffff; /* now set them from the cache */ env->PSW |= ((env->PSW_USB_C != 0) << 31); env->PSW |= ((env->PSW_USB_V & (1 << 31)) >> 1); From 996a729f9b7f93fb921891bf0e07757a29d0c68a Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 11 Mar 2016 16:03:11 +0100 Subject: [PATCH 04/10] target-tricore: Add FPU infrastructure This patch adds a file for all the FPU related helpers with all the includes, useful defines, and a function to update the status bits. Additionally it adds a mask for the rounding mode bits of PSW as well as all the opcodes for the FPU instructions. Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-Id: <1457708597-3025-2-git-send-email-kbastian@mail.uni-paderborn.de> --- fpu/softfloat-specialize.h | 2 +- target-tricore/Makefile.objs | 2 +- target-tricore/cpu.h | 6 ++- target-tricore/fpu_helper.c | 81 ++++++++++++++++++++++++++++++++ target-tricore/helper.c | 10 ++++ target-tricore/translate.c | 1 + target-tricore/tricore-opcodes.h | 18 +++++++ 7 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 target-tricore/fpu_helper.c diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 0875436b83..a4cbdad452 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -113,7 +113,7 @@ const float16 float16_default_nan = const_float16(0xFE00); #if defined(TARGET_SPARC) const float32 float32_default_nan = const_float32(0x7FFFFFFF); #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \ - defined(TARGET_XTENSA) || defined(TARGET_S390X) + defined(TARGET_XTENSA) || defined(TARGET_S390X) || defined(TARGET_TRICORE) const float32 float32_default_nan = const_float32(0x7FC00000); #elif SNAN_BIT_IS_ONE const float32 float32_default_nan = const_float32(0x7FBFFFFF); diff --git a/target-tricore/Makefile.objs b/target-tricore/Makefile.objs index 21e820d8f9..7a05670718 100644 --- a/target-tricore/Makefile.objs +++ b/target-tricore/Makefile.objs @@ -1 +1 @@ -obj-y += translate.o helper.o cpu.o op_helper.o +obj-y += translate.o helper.o cpu.o op_helper.o fpu_helper.o diff --git a/target-tricore/cpu.h b/target-tricore/cpu.h index 5fee376674..90045a93d2 100644 --- a/target-tricore/cpu.h +++ b/target-tricore/cpu.h @@ -183,8 +183,7 @@ struct CPUTriCoreState { uint32_t M2CNT; uint32_t M3CNT; /* Floating Point Registers */ - /* XXX: */ - + float_status fp_status; /* QEMU */ int error_code; uint32_t hflags; /* CPU State */ @@ -217,6 +216,7 @@ struct CPUTriCoreState { #define MASK_PSW_GW 0x00000100 #define MASK_PSW_CDE 0x00000080 #define MASK_PSW_CDC 0x0000007f +#define MASK_PSW_FPU_RM 0x3000000 #define MASK_SYSCON_PRO_TEN 0x2 #define MASK_SYSCON_FCD_SF 0x1 @@ -339,6 +339,8 @@ enum { uint32_t psw_read(CPUTriCoreState *env); void psw_write(CPUTriCoreState *env, uint32_t val); +void fpu_set_state(CPUTriCoreState *env); + #include "cpu-qom.h" #define MMU_USER_IDX 2 diff --git a/target-tricore/fpu_helper.c b/target-tricore/fpu_helper.c new file mode 100644 index 0000000000..7c79c9c6df --- /dev/null +++ b/target-tricore/fpu_helper.c @@ -0,0 +1,81 @@ +/* + * TriCore emulation for qemu: fpu helper. + * + * Copyright (c) 2016 Bastian Koppelmann University of Paderborn + * + * 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 + * 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 "qemu/osdep.h" +#include "cpu.h" +#include "exec/helper-proto.h" + +#define ADD_NAN 0x7cf00001 +#define DIV_NAN 0x7fc00008 +#define MUL_NAN 0x7fc00002 +#define FPU_FS PSW_USB_C +#define FPU_FI PSW_USB_V +#define FPU_FV PSW_USB_SV +#define FPU_FZ PSW_USB_AV +#define FPU_FU PSW_USB_SAV + +/* we don't care about input_denormal */ +static inline uint8_t f_get_excp_flags(CPUTriCoreState *env) +{ + return get_float_exception_flags(&env->fp_status) + & (float_flag_invalid + | float_flag_overflow + | float_flag_underflow + | float_flag_output_denormal + | float_flag_divbyzero + | float_flag_inexact); +} + +static inline bool f_is_denormal(float32 arg) +{ + return float32_is_zero_or_denormal(arg) && !float32_is_zero(arg); +} + +static inline void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags) +{ + uint8_t some_excp = 0; + set_float_exception_flags(0, &env->fp_status); + + if (flags & float_flag_invalid) { + env->FPU_FI = 1 << 31; + some_excp = 1; + } + + if (flags & float_flag_overflow) { + env->FPU_FV = 1 << 31; + some_excp = 1; + } + + if (flags & float_flag_underflow || flags & float_flag_output_denormal) { + env->FPU_FU = 1 << 31; + some_excp = 1; + } + + if (flags & float_flag_divbyzero) { + env->FPU_FZ = 1 << 31; + some_excp = 1; + } + + if (flags & float_flag_inexact || flags & float_flag_output_denormal) { + env->PSW |= 1 << 26; + some_excp = 1; + } + + env->FPU_FS = some_excp; +} diff --git a/target-tricore/helper.c b/target-tricore/helper.c index adbb6db10d..71b31cdb9b 100644 --- a/target-tricore/helper.c +++ b/target-tricore/helper.c @@ -110,6 +110,14 @@ void tricore_cpu_list(FILE *f, fprintf_function cpu_fprintf) g_slist_free(list); } +void fpu_set_state(CPUTriCoreState *env) +{ + set_float_rounding_mode(env->PSW & MASK_PSW_FPU_RM, &env->fp_status); + set_flush_inputs_to_zero(1, &env->fp_status); + set_flush_to_zero(1, &env->fp_status); + set_default_nan_mode(1, &env->fp_status); +} + uint32_t psw_read(CPUTriCoreState *env) { /* clear all USB bits */ @@ -132,4 +140,6 @@ void psw_write(CPUTriCoreState *env, uint32_t val) env->PSW_USB_AV = (val & MASK_USB_AV) << 3; env->PSW_USB_SAV = (val & MASK_USB_SAV) << 4; env->PSW = val; + + fpu_set_state(env); } diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 66f798a9b9..8c429c5387 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -8773,6 +8773,7 @@ void cpu_state_reset(CPUTriCoreState *env) { /* Reset Regs to Default Value */ env->PSW = 0xb80; + fpu_set_state(env); } static void tricore_tcg_init_csfr(void) diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 1bfed0ce48..df666b081f 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -1126,6 +1126,20 @@ enum { OPC2_32_RR_CRC32 = 0x03, OPC2_32_RR_DIV = 0x20, OPC2_32_RR_DIV_U = 0x21, + OPC2_32_RR_MUL_F = 0x04, + OPC2_32_RR_DIV_F = 0x05, + OPC2_32_RR_FTOI = 0x10, + OPC2_32_RR_ITOF = 0x14, + OPC2_32_RR_CMP_F = 0x00, + OPC2_32_RR_FTOIZ = 0x13, + OPC2_32_RR_FTOQ31 = 0x11, + OPC2_32_RR_FTOQ31Z = 0x18, + OPC2_32_RR_FTOU = 0x12, + OPC2_32_RR_FTOUZ = 0x17, + OPC2_32_RR_Q31TOF = 0x15, + OPC2_32_RR_QSEED_F = 0x19, + OPC2_32_RR_UPDFL = 0x0c, + OPC2_32_RR_UTOF = 0x16, }; /* OPCM_32_RR_IDIRECT */ enum { @@ -1209,6 +1223,10 @@ enum { OPC2_32_RRR_IXMIN = 0x08, OPC2_32_RRR_IXMIN_U = 0x09, OPC2_32_RRR_PACK = 0x00, + OPC2_32_RRR_ADD_F = 0x02, + OPC2_32_RRR_SUB_F = 0x03, + OPC2_32_RRR_MADD_F = 0x06, + OPC2_32_RRR_MSUB_F = 0x07, }; /* * RRR1 Format From c433a17141fb2a400ecb656e55d8d21caa2e2390 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 11 Mar 2016 16:03:12 +0100 Subject: [PATCH 05/10] target-tricore: Move general CHECK_REG_PAIR of decode_rrr_divide The add.f and sub.f to be implemented don't use 64 bit registers and a general usage of CHECK_REG_PAIR would always generate an exception for them. Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-Id: <1457708597-3025-3-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/translate.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 8c429c5387..bccdcc3ecf 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -7013,45 +7013,51 @@ static void decode_rrr_divide(CPUTriCoreState *env, DisasContext *ctx) r3 = MASK_OP_RRR_S3(ctx->opcode); r4 = MASK_OP_RRR_D(ctx->opcode); - CHECK_REG_PAIR(r3); - switch (op2) { case OPC2_32_RRR_DVADJ: + CHECK_REG_PAIR(r3); CHECK_REG_PAIR(r4); GEN_HELPER_RRR(dvadj, cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]); break; case OPC2_32_RRR_DVSTEP: + CHECK_REG_PAIR(r3); CHECK_REG_PAIR(r4); GEN_HELPER_RRR(dvstep, cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]); break; case OPC2_32_RRR_DVSTEP_U: + CHECK_REG_PAIR(r3); CHECK_REG_PAIR(r4); GEN_HELPER_RRR(dvstep_u, cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]); break; case OPC2_32_RRR_IXMAX: + CHECK_REG_PAIR(r3); CHECK_REG_PAIR(r4); GEN_HELPER_RRR(ixmax, cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]); break; case OPC2_32_RRR_IXMAX_U: + CHECK_REG_PAIR(r3); CHECK_REG_PAIR(r4); GEN_HELPER_RRR(ixmax_u, cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]); break; case OPC2_32_RRR_IXMIN: + CHECK_REG_PAIR(r3); CHECK_REG_PAIR(r4); GEN_HELPER_RRR(ixmin, cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]); break; case OPC2_32_RRR_IXMIN_U: + CHECK_REG_PAIR(r3); CHECK_REG_PAIR(r4); GEN_HELPER_RRR(ixmin_u, cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]); break; case OPC2_32_RRR_PACK: + CHECK_REG_PAIR(r3); gen_helper_pack(cpu_gpr_d[r4], cpu_PSW_C, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); break; From baf410dccac82f446d83bb10509608f59adbd8ee Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 11 Mar 2016 16:03:13 +0100 Subject: [PATCH 06/10] target-tricore: add add.f/sub.f instructions Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-Id: <1457708597-3025-4-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/fpu_helper.c | 29 ++++++++++++++++++++++++++++- target-tricore/helper.h | 2 ++ target-tricore/translate.c | 6 ++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/target-tricore/fpu_helper.c b/target-tricore/fpu_helper.c index 7c79c9c6df..747d897525 100644 --- a/target-tricore/fpu_helper.c +++ b/target-tricore/fpu_helper.c @@ -47,7 +47,7 @@ static inline bool f_is_denormal(float32 arg) return float32_is_zero_or_denormal(arg) && !float32_is_zero(arg); } -static inline void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags) +static void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags) { uint8_t some_excp = 0; set_float_exception_flags(0, &env->fp_status); @@ -79,3 +79,30 @@ static inline void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags) env->FPU_FS = some_excp; } + +#define FADD_SUB(op) \ +uint32_t helper_f##op(CPUTriCoreState *env, uint32_t r1, uint32_t r2) \ +{ \ + float32 arg1 = make_float32(r1); \ + float32 arg2 = make_float32(r2); \ + uint32_t flags; \ + float32 f_result; \ + \ + f_result = float32_##op(arg2, arg1, &env->fp_status); \ + flags = f_get_excp_flags(env); \ + if (flags) { \ + /* If the output is a NaN, but the inputs aren't, \ + we return a unique value. */ \ + if ((flags & float_flag_invalid) \ + && !float32_is_any_nan(arg1) \ + && !float32_is_any_nan(arg2)) { \ + f_result = ADD_NAN; \ + } \ + f_update_psw_flags(env, flags); \ + } else { \ + env->FPU_FS = 0; \ + } \ + return (uint32_t)f_result; \ +} +FADD_SUB(add) +FADD_SUB(sub) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 2c8ed78940..2f4a2bb639 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -105,6 +105,8 @@ DEF_HELPER_FLAGS_1(parity, TCG_CALL_NO_RWG_SE, i32, i32) /* float */ DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32) DEF_HELPER_1(unpack, i64, i32) +DEF_HELPER_3(fadd, i32, env, i32, i32) +DEF_HELPER_3(fsub, i32, env, i32, i32) /* dvinit */ DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index bccdcc3ecf..c4c7717bdb 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -7061,6 +7061,12 @@ static void decode_rrr_divide(CPUTriCoreState *env, DisasContext *ctx) gen_helper_pack(cpu_gpr_d[r4], cpu_PSW_C, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); break; + case OPC2_32_RRR_ADD_F: + gen_helper_fadd(cpu_gpr_d[r4], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r3]); + break; + case OPC2_32_RRR_SUB_F: + gen_helper_fsub(cpu_gpr_d[r4], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r3]); + break; default: generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } From daab3f7fa8c9b29ed6dff9160a6a87e0ea09d705 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 11 Mar 2016 16:03:14 +0100 Subject: [PATCH 07/10] target-tricore: Add mul.f instruction Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-Id: <1457708597-3025-5-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/fpu_helper.c | 26 ++++++++++++++++++++++++++ target-tricore/helper.h | 1 + target-tricore/translate.c | 3 +++ 3 files changed, 30 insertions(+) diff --git a/target-tricore/fpu_helper.c b/target-tricore/fpu_helper.c index 747d897525..21459bca1a 100644 --- a/target-tricore/fpu_helper.c +++ b/target-tricore/fpu_helper.c @@ -106,3 +106,29 @@ uint32_t helper_f##op(CPUTriCoreState *env, uint32_t r1, uint32_t r2) \ } FADD_SUB(add) FADD_SUB(sub) + +uint32_t helper_fmul(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + uint32_t flags; + float32 arg1 = make_float32(r1); + float32 arg2 = make_float32(r2); + float32 f_result; + + f_result = float32_mul(arg1, arg2, &env->fp_status); + + flags = f_get_excp_flags(env); + if (flags) { + /* If the output is a NaN, but the inputs aren't, + we return a unique value. */ + if ((flags & float_flag_invalid) + && !float32_is_any_nan(arg1) + && !float32_is_any_nan(arg2)) { + f_result = MUL_NAN; + } + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + return (uint32_t)f_result; + +} diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 2f4a2bb639..ac41190810 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -107,6 +107,7 @@ DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32) DEF_HELPER_1(unpack, i64, i32) DEF_HELPER_3(fadd, i32, env, i32, i32) DEF_HELPER_3(fsub, i32, env, i32, i32) +DEF_HELPER_3(fmul, i32, env, i32, i32) /* dvinit */ DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index c4c7717bdb..3dadb17b39 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -6672,6 +6672,9 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; + case OPC2_32_RR_MUL_F: + gen_helper_fmul(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; default: generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } From 446ee5b2a86766bc5cc9d23a106f364bd8ce01b4 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 11 Mar 2016 16:03:15 +0100 Subject: [PATCH 08/10] target-tricore: Add div.f instruction Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-Id: <1457708597-3025-6-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/fpu_helper.c | 26 ++++++++++++++++++++++++++ target-tricore/helper.h | 1 + target-tricore/translate.c | 3 +++ 3 files changed, 30 insertions(+) diff --git a/target-tricore/fpu_helper.c b/target-tricore/fpu_helper.c index 21459bca1a..5ae56e07f6 100644 --- a/target-tricore/fpu_helper.c +++ b/target-tricore/fpu_helper.c @@ -132,3 +132,29 @@ uint32_t helper_fmul(CPUTriCoreState *env, uint32_t r1, uint32_t r2) return (uint32_t)f_result; } + +uint32_t helper_fdiv(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + uint32_t flags; + float32 arg1 = make_float32(r1); + float32 arg2 = make_float32(r2); + float32 f_result; + + f_result = float32_div(arg1, arg2 , &env->fp_status); + + flags = f_get_excp_flags(env); + if (flags) { + /* If the output is a NaN, but the inputs aren't, + we return a unique value. */ + if ((flags & float_flag_invalid) + && !float32_is_any_nan(arg1) + && !float32_is_any_nan(arg2)) { + f_result = DIV_NAN; + } + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + + return (uint32_t)f_result; +} diff --git a/target-tricore/helper.h b/target-tricore/helper.h index ac41190810..f5eff3625a 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -108,6 +108,7 @@ DEF_HELPER_1(unpack, i64, i32) DEF_HELPER_3(fadd, i32, env, i32, i32) DEF_HELPER_3(fsub, i32, env, i32, i32) DEF_HELPER_3(fmul, i32, env, i32, i32) +DEF_HELPER_3(fdiv, i32, env, i32, i32) /* dvinit */ DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 3dadb17b39..eaa7dd515f 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -6675,6 +6675,9 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) case OPC2_32_RR_MUL_F: gen_helper_fmul(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; + case OPC2_32_RR_DIV_F: + gen_helper_fdiv(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; default: generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } From 743cd09dd7775aaffb7f57444bef0d052bed9691 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 11 Mar 2016 16:03:16 +0100 Subject: [PATCH 09/10] target-tricore: Add cmp.f instruction Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-Id: <1457708597-3025-7-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/fpu_helper.c | 23 +++++++++++++++++++++++ target-tricore/helper.h | 1 + target-tricore/translate.c | 3 +++ 3 files changed, 27 insertions(+) diff --git a/target-tricore/fpu_helper.c b/target-tricore/fpu_helper.c index 5ae56e07f6..a60bf29625 100644 --- a/target-tricore/fpu_helper.c +++ b/target-tricore/fpu_helper.c @@ -158,3 +158,26 @@ uint32_t helper_fdiv(CPUTriCoreState *env, uint32_t r1, uint32_t r2) return (uint32_t)f_result; } + +uint32_t helper_fcmp(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + uint32_t result, flags; + float32 arg1 = make_float32(r1); + float32 arg2 = make_float32(r2); + + set_flush_inputs_to_zero(0, &env->fp_status); + + result = 1 << (float32_compare_quiet(arg1, arg2, &env->fp_status) + 1); + result |= f_is_denormal(arg1) << 4; + result |= f_is_denormal(arg2) << 5; + + flags = f_get_excp_flags(env); + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + + set_flush_inputs_to_zero(1, &env->fp_status); + return result; +} diff --git a/target-tricore/helper.h b/target-tricore/helper.h index f5eff3625a..489530fc6a 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -109,6 +109,7 @@ DEF_HELPER_3(fadd, i32, env, i32, i32) DEF_HELPER_3(fsub, i32, env, i32, i32) DEF_HELPER_3(fmul, i32, env, i32, i32) DEF_HELPER_3(fdiv, i32, env, i32, i32) +DEF_HELPER_3(fcmp, i32, env, i32, i32) /* dvinit */ DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index eaa7dd515f..34cae632e5 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -6678,6 +6678,9 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) case OPC2_32_RR_DIV_F: gen_helper_fdiv(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; + case OPC2_32_RR_CMP_F: + gen_helper_fcmp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; default: generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } From 0d4c3b8010320a8ebb4061d88510e082b06ed2cc Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 11 Mar 2016 16:03:17 +0100 Subject: [PATCH 10/10] target-tricore: Add ftoi and itof instructions Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-Id: <1457708597-3025-8-git-send-email-kbastian@mail.uni-paderborn.de> --- target-tricore/fpu_helper.c | 34 ++++++++++++++++++++++++++++++++++ target-tricore/helper.h | 2 ++ target-tricore/translate.c | 6 ++++++ 3 files changed, 42 insertions(+) diff --git a/target-tricore/fpu_helper.c b/target-tricore/fpu_helper.c index a60bf29625..98fe9472b1 100644 --- a/target-tricore/fpu_helper.c +++ b/target-tricore/fpu_helper.c @@ -181,3 +181,37 @@ uint32_t helper_fcmp(CPUTriCoreState *env, uint32_t r1, uint32_t r2) set_flush_inputs_to_zero(1, &env->fp_status); return result; } + +uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg) +{ + float32 f_arg = make_float32(arg); + int32_t result, flags; + + result = float32_to_int32(f_arg, &env->fp_status); + + flags = f_get_excp_flags(env); + if (flags) { + if (float32_is_any_nan(f_arg)) { + result = 0; + } + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + return (uint32_t)result; +} + +uint32_t helper_itof(CPUTriCoreState *env, uint32_t arg) +{ + float32 f_result; + uint32_t flags; + f_result = int32_to_float32(arg, &env->fp_status); + + flags = f_get_excp_flags(env); + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + return (uint32_t)f_result; +} diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 489530fc6a..9333e161ab 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -110,6 +110,8 @@ DEF_HELPER_3(fsub, i32, env, i32, i32) DEF_HELPER_3(fmul, i32, env, i32, i32) DEF_HELPER_3(fdiv, i32, env, i32, i32) DEF_HELPER_3(fcmp, i32, env, i32, i32) +DEF_HELPER_2(ftoi, i32, env, i32) +DEF_HELPER_2(itof, i32, env, i32) /* dvinit */ DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 34cae632e5..912bf226be 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -6681,6 +6681,12 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) case OPC2_32_RR_CMP_F: gen_helper_fcmp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; + case OPC2_32_RR_FTOI: + gen_helper_ftoi(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + break; + case OPC2_32_RR_ITOF: + gen_helper_itof(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + break; default: generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); }