From bed634d94459e3677a00156567e53bae62ee48f1 Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Mon, 22 Feb 2021 16:05:10 +0200 Subject: [PATCH] e2k: Use %pfpfr for f32 and f64 operations. %fpcr and %fpsr have been used for the operations but %pfpfr must be used instead. Signed-off-by: Denis Drakhnya --- linux-user/e2k/signal.c | 2 +- target/e2k/cpu.c | 5 +- target/e2k/cpu.h | 42 +++++-- target/e2k/helper-tcg.h | 5 + target/e2k/helper_fpu.c | 262 +++++++++++++++++++++------------------- target/e2k/helper_int.c | 12 +- target/e2k/helper_vec.c | 2 +- 7 files changed, 186 insertions(+), 144 deletions(-) diff --git a/linux-user/e2k/signal.c b/linux-user/e2k/signal.c index 98dc3cb1cc..140b07e7f4 100644 --- a/linux-user/e2k/signal.c +++ b/linux-user/e2k/signal.c @@ -156,7 +156,7 @@ static abi_long setup_sigcontext(CPUE2KState *env, __put_user(env->fpcr.raw, &extra->fpcr); __put_user(env->fpsr.raw, &extra->fpsr); - __put_user(env->pfpfr, &extra->pfpfr); + __put_user(env->pfpfr.raw, &extra->pfpfr); __put_user(env->ctprs[0].raw, &extra->ctpr1); __put_user(env->ctprs[1].raw, &extra->ctpr2); diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index a5a000a2db..76e1bd570d 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -55,8 +55,11 @@ static void e2k_cpu_reset(DeviceState *dev) env->aau.incrs[0] = 1; /* always one */ env->fpcr._one = 1; env->fpcr.pc = FPCR_PC_XP; - + env->fpcr.em = FP_EM; + env->pfpfr.em = FP_EM; + e2k_update_fp_status(env); + e2k_update_fx_status(env); // FIXME: testing env->idr = 0x3a207; /* mimic 8c */ diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index bcc63b94a9..2dabba6dca 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -583,12 +583,12 @@ typedef union { } E2KCtpr; /* E2K FPU regs are compatible with x87 regs */ -#define FPSR_IE (1U << 0) /* invalid operation */ -#define FPSR_DE (1U << 1) /* denormalized operand */ -#define FPSR_ZE (1U << 2) /* zero divide */ -#define FPSR_OE (1U << 3) /* overflow */ -#define FPSR_UE (1U << 4) /* underflow */ -#define FPSR_PE (1U << 5) /* precision */ +#define FP_IE (1U << 0) /* invalid operation */ +#define FP_DE (1U << 1) /* denormalized operand */ +#define FP_ZE (1U << 2) /* zero divide */ +#define FP_OE (1U << 3) /* overflow */ +#define FP_UE (1U << 4) /* underflow */ +#define FP_PE (1U << 5) /* precision */ typedef union { struct { @@ -605,17 +605,17 @@ typedef union { uint32_t raw; } E2KFpsrState; -#define FPCR_EM (FPSR_IE|FPSR_DE|FPSR_ZE|FPSR_OE|FPSR_UE|FPSR_PE) +#define FP_EM (FP_IE|FP_DE|FP_ZE|FP_OE|FP_UE|FP_PE) #define FPCR_PC_SP 0 /* single precision (32 bits) */ #define FPCR_PC_RESERVED 1 /* reserved */ #define FPCR_PC_DP 2 /* double precision (64 bits) */ #define FPCR_PC_XP 3 /* extended precision (80 bits) */ -#define FPCR_RC_NEAR 0 /* round to nearest */ -#define FPCR_RC_DOWN 1 /* round down */ -#define FPCR_RC_UP 2 /* round up */ -#define FPCR_RC_CHOP 3 /* round toward zero (truncate) */ +#define FP_RC_NEAR 0 /* round to nearest */ +#define FP_RC_DOWN 1 /* round down */ +#define FP_RC_UP 2 /* round up */ +#define FP_RC_CHOP 3 /* round toward zero (truncate) */ typedef union { struct { @@ -630,6 +630,22 @@ typedef union { uint32_t raw; } E2KFpcrState; +/* + * Packed Floating Point Flag Register (PFPFR) + */ +typedef union { + struct { + uint32_t ef: 6; /* 5:0 */ + uint32_t zero1: 1; /* 6 */ + uint32_t em: 6; /* 12:7 */ + uint32_t rc: 2; /* 14:13 */ + uint32_t fz: 1; /* 15 */ + uint32_t zero2: 10; /* 25:16 */ + uint32_t dm: 6; /* 31:26 */ + }; + uint32_t raw; +} E2KPfpfr; + typedef struct { union { uint64_t lo; @@ -725,11 +741,12 @@ typedef struct CPUArchState { uint64_t upsr; uint64_t idr; - uint32_t pfpfr; // Packed Floating Point Flag Register (PFPFR) + E2KPfpfr pfpfr; // Packed Floating Point Flag Register (PFPFR) E2KFpsrState fpsr; // Floating point state register (FPSR) E2KFpcrState fpcr; // Floating point control register (FPCR) float_status fp_status; + float_status fx_status; E2KAauState aau; @@ -793,6 +810,7 @@ bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); void e2k_update_fp_status(CPUE2KState *env); +void e2k_update_fx_status(CPUE2KState *env); void e2k_pcs_new(E2KPcsState *pcs); void e2k_ps_new(E2KPsState *ps); diff --git a/target/e2k/helper-tcg.h b/target/e2k/helper-tcg.h index 913a99e7aa..09ead4b265 100644 --- a/target/e2k/helper-tcg.h +++ b/target/e2k/helper-tcg.h @@ -29,6 +29,11 @@ #include "cpu.h" #include "exec/exec-all.h" +#define glue3(x, y, z) glue(glue(x, y), z) +#define glue4(x, y, z, w) glue(glue3(x, y, z), w) +#define deref(x) *(x) +#define ident(x) (x) + /* helper.c */ void G_NORETURN raise_exception(CPUE2KState *env, int exception_index); void G_NORETURN raise_exception_ra(CPUE2KState *env, int exception_index, diff --git a/target/e2k/helper_fpu.c b/target/e2k/helper_fpu.c index 8c6bf7fb1f..b7c96dc94a 100644 --- a/target/e2k/helper_fpu.c +++ b/target/e2k/helper_fpu.c @@ -1,68 +1,61 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "cpu.h" +#include "helper-tcg.h" #include "exec/exec-all.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" -#define glue3(x, y, z) glue(glue(x, y), z) -#define glue4(x, y, z, w) glue(glue3(x, y, z), w) -#define deref(x) *(x) -#define no_cvt(x) (x) /* when in correct type */ +static FloatRoundMode rm[] = { + float_round_nearest_even, + float_round_down, + float_round_up, + float_round_to_zero, +}; -static inline void fpu_set_exception(CPUE2KState *env, int mask) +static inline int fpu_flags(int flags) { - env->fpsr.ef |= mask; - if (env->fpsr.ef & (~env->fpcr.em & FPCR_EM)) { + return (flags & float_flag_invalid ? FP_IE : 0) | + (flags & float_flag_divbyzero ? FP_ZE : 0) | + (flags & float_flag_overflow ? FP_OE : 0) | + (flags & float_flag_underflow ? FP_UE : 0) | + (flags & float_flag_inexact ? FP_PE : 0) | + (flags & float_flag_input_denormal ? FP_DE : 0); +} + +static inline void fx_merge_exception_flags(CPUE2KState *env, int old_flags) +{ + int new_flags = get_float_exception_flags(&env->fx_status); + float_raise(old_flags, &env->fx_status); + env->fpsr.ef |= fpu_flags(new_flags); + if (env->fpsr.ef & (~env->fpcr.em & FP_EM)) { env->fpsr.es = 1; env->fpsr.b = 1; } } -static inline int save_exception_flags(CPUE2KState *env) +static inline void fp_merge_exception_flags(CPUE2KState *env, int old_flags) { - int old_flags = get_float_exception_flags(&env->fp_status); - set_float_exception_flags(0, &env->fp_status); + int new_flags = get_float_exception_flags(&env->fp_status); + float_raise(old_flags, &env->fp_status); + env->pfpfr.ef |= fpu_flags(new_flags); +} + +static inline int save_exception_flags(float_status *s) +{ + int old_flags = get_float_exception_flags(s); + set_float_exception_flags(0, s); return old_flags; } -static inline void merge_exception_flags(CPUE2KState *env, int old_flags) -{ - int new_flags = get_float_exception_flags(&env->fp_status); - float_raise((uint8_t)old_flags, &env->fp_status); - fpu_set_exception(env, - ((new_flags & float_flag_invalid ? FPSR_IE : 0) | - (new_flags & float_flag_divbyzero ? FPSR_ZE : 0) | - (new_flags & float_flag_overflow ? FPSR_OE : 0) | - (new_flags & float_flag_underflow ? FPSR_UE : 0) | - (new_flags & float_flag_inexact ? FPSR_PE : 0) | - (new_flags & float_flag_input_denormal ? FPSR_DE : 0))); -} +#define fx_save_exception_flags(e) save_exception_flags(&(e)->fx_status) +#define fp_save_exception_flags(e) save_exception_flags(&(e)->fp_status) -void e2k_update_fp_status(CPUE2KState *env) +void e2k_update_fx_status(CPUE2KState *env) { - FloatRoundMode rm; int x; - switch(env->fpcr.rc) { - case FPCR_RC_UP: - rm = float_round_up; - break; - case FPCR_RC_DOWN: - rm = float_round_down; - break; - case FPCR_RC_CHOP: - rm = float_round_to_zero; - break; - case FPCR_RC_NEAR: - rm = float_round_nearest_even; - break; - default: - qemu_log_mask(LOG_UNIMP, "unknown rounding mode 0x%x\n", env->fpcr.rc); - abort(); - } - - set_float_rounding_mode(rm, &env->fp_status); + set_float_rounding_mode(rm[env->fpcr.rc], &env->fx_status); switch(env->fpcr.pc) { case FPCR_PC_XP: x = floatx80_precision_x; break; @@ -74,15 +67,20 @@ void e2k_update_fp_status(CPUE2KState *env) abort(); } - set_floatx80_rounding_precision(x, &env->fp_status); + set_floatx80_rounding_precision(x, &env->fx_status); +} + +void e2k_update_fp_status(CPUE2KState *env) +{ + set_float_rounding_mode(rm[env->pfpfr.rc], &env->fp_status); } #define GENERATE_SIMPLE_FLOAT2_OP(name, function, size) \ uint##size##_t HELPER(name)(CPUE2KState *env, uint##size##_t x, uint##size##_t y) \ { \ - int old_flags = save_exception_flags(env); \ + int old_flags = fp_save_exception_flags(env); \ float##size z = float##size##_##function (make_float##size (x), make_float##size (y), &env->fp_status); \ - merge_exception_flags(env, old_flags); \ + fp_merge_exception_flags(env, old_flags); \ return float##size##_val(z); \ } @@ -93,23 +91,41 @@ void e2k_update_fp_status(CPUE2KState *env) #define GENERATE_CMP_FLOAT2_OP(ret_type, name, expr, op, in_type, cvt_macro) \ ret_type HELPER(name)(CPUE2KState *env, in_type x, in_type y) \ { \ - int old_flags = save_exception_flags(env); \ + int old_flags = fp_save_exception_flags(env); \ ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fp_status); \ - merge_exception_flags(env, old_flags); \ + fp_merge_exception_flags(env, old_flags); \ + return z ? -1 : 0; \ + } + +#define GENERATE_CMP_XFLOAT2_OP(ret_type, name, expr, op, in_type, cvt_macro) \ + ret_type HELPER(name)(CPUE2KState *env, in_type x, in_type y) \ + { \ + int old_flags = fx_save_exception_flags(env); \ + ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fx_status); \ + fx_merge_exception_flags(env, old_flags); \ return z ? -1 : 0; \ } #define GENERATE_CMP_FLOAT2_OPS_32_64_80(name, expr, op) \ GENERATE_CMP_FLOAT2_OP(uint32_t, glue3(f, name, s), expr, glue(float32_, op), uint32_t, make_float32) \ GENERATE_CMP_FLOAT2_OP(uint64_t, glue3(f, name, d), expr, glue(float64_, op), uint64_t, make_float32) \ - GENERATE_CMP_FLOAT2_OP(uint64_t, glue3(fx, name, x), expr, glue(floatx80_, op), floatx80*, deref) + GENERATE_CMP_XFLOAT2_OP(uint64_t, glue3(fx, name, x), expr, glue(floatx80_, op), floatx80*, deref) #define GENERATE_CVT_FLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \ size_to HELPER(name)(CPUE2KState *env, size_from x) \ {\ - int old_flags = save_exception_flags(env); \ + int old_flags = fp_save_exception_flags(env); \ size_to z = func_to( glue3(from_t, _to_, to_t) (func_from(x), &env->fp_status) );\ - merge_exception_flags(env, old_flags); \ + fp_merge_exception_flags(env, old_flags); \ + return z; \ + } + +#define GENERATE_CVT_XFLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \ + size_to HELPER(name)(CPUE2KState *env, size_from x) \ + {\ + int old_flags = fx_save_exception_flags(env); \ + size_to z = func_to( glue3(from_t, _to_, to_t) (func_from(x), &env->fx_status) );\ + fx_merge_exception_flags(env, old_flags); \ return z; \ } @@ -128,66 +144,66 @@ GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpnlt, !, lt) GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpuod, , unordered) GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpod, !, unordered) -GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, uint32_t, uint32_t, make_float32, no_cvt) -GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, uint32_t, uint32_t, no_cvt, float32_val) -GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, uint32_t, uint32_t, make_float32, no_cvt) +GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, uint32_t, uint32_t, make_float32, ident) +GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, uint32_t, uint32_t, ident, float32_val) +GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, uint32_t, uint32_t, make_float32, ident) -GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, uint64_t, uint64_t, make_float64, no_cvt) -GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, uint64_t, uint64_t, no_cvt, float64_val) -GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, uint64_t, uint64_t, make_float64, no_cvt) +GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, uint64_t, uint64_t, make_float64, ident) +GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, uint64_t, uint64_t, ident, float64_val) +GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, uint64_t, uint64_t, make_float64, ident) GENERATE_CVT_FLOAT1_OP(fstofd, float32, float64, uint32_t, uint64_t, make_float32, float64_val) -GENERATE_CVT_FLOAT1_OP(fstoid, float32, int64, uint32_t, uint64_t, make_float32, no_cvt) -GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, uint32_t, uint64_t, no_cvt, float64_val) -GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, uint32_t, uint64_t, make_float32, no_cvt) +GENERATE_CVT_FLOAT1_OP(fstoid, float32, int64, uint32_t, uint64_t, make_float32, ident) +GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, uint32_t, uint64_t, ident, float64_val) +GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, uint32_t, uint64_t, make_float32, ident) GENERATE_CVT_FLOAT1_OP(fdtofs, float64, float32, uint64_t, uint32_t, make_float64, float32_val) -GENERATE_CVT_FLOAT1_OP(fdtois, float64, int32, uint64_t, uint32_t, make_float64, no_cvt) -GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, uint64_t, uint32_t, no_cvt, float32_val) -GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, uint64_t, uint32_t, make_float64, no_cvt) +GENERATE_CVT_FLOAT1_OP(fdtois, float64, int32, uint64_t, uint32_t, make_float64, ident) +GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, uint64_t, uint32_t, ident, float32_val) +GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, uint64_t, uint32_t, make_float64, ident) -GENERATE_CVT_FLOAT1_OP(fxtofs, floatx80, float32, floatx80*, uint32_t, deref, float32_val) -GENERATE_CVT_FLOAT1_OP(fxtois, floatx80, int32, floatx80*, uint32_t, deref, no_cvt) -GENERATE_CVT_FLOAT1_OP(fxtoistr, floatx80, int32_round_to_zero, floatx80*, uint32_t, deref, no_cvt) +GENERATE_CVT_XFLOAT1_OP(fxtofs, floatx80, float32, floatx80*, uint32_t, deref, float32_val) +GENERATE_CVT_XFLOAT1_OP(fxtois, floatx80, int32, floatx80*, uint32_t, deref, ident) +GENERATE_CVT_XFLOAT1_OP(fxtoistr, floatx80, int32_round_to_zero, floatx80*, uint32_t, deref, ident) -GENERATE_CVT_FLOAT1_OP(fxtofd, floatx80, float64, floatx80*, uint64_t, deref, float64_val) -GENERATE_CVT_FLOAT1_OP(fxtoid, floatx80, int64, floatx80*, uint64_t, deref, no_cvt) -GENERATE_CVT_FLOAT1_OP(fxtoidtr, floatx80, int64_round_to_zero, floatx80*, uint64_t, deref, no_cvt) +GENERATE_CVT_XFLOAT1_OP(fxtofd, floatx80, float64, floatx80*, uint64_t, deref, float64_val) +GENERATE_CVT_XFLOAT1_OP(fxtoid, floatx80, int64, floatx80*, uint64_t, deref, ident) +GENERATE_CVT_XFLOAT1_OP(fxtoidtr, floatx80, int64_round_to_zero, floatx80*, uint64_t, deref, ident) void HELPER(fstofx)(floatx80 *ret, CPUE2KState *env, uint32_t x) { - int old_flags = save_exception_flags(env); + int old_flags = fp_save_exception_flags(env); *ret = float32_to_floatx80(make_float32(x), &env->fp_status); - merge_exception_flags(env, old_flags); + fp_merge_exception_flags(env, old_flags); } void HELPER(fdtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x) { - int old_flags = save_exception_flags(env); + int old_flags = fp_save_exception_flags(env); *ret = float64_to_floatx80(make_float64(x), &env->fp_status); - merge_exception_flags(env, old_flags); + fp_merge_exception_flags(env, old_flags); } void HELPER(istofx)(floatx80 *ret, CPUE2KState *env, uint32_t x) { - int old_flags = save_exception_flags(env); - *ret = int32_to_floatx80(no_cvt(x), &env->fp_status); - merge_exception_flags(env, old_flags); + int old_flags = fx_save_exception_flags(env); + *ret = int32_to_floatx80(x, &env->fx_status); + fx_merge_exception_flags(env, old_flags); } void HELPER(idtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x) { - int old_flags = save_exception_flags(env); - *ret = int64_to_floatx80(no_cvt(x), &env->fp_status); - merge_exception_flags(env, old_flags); + int old_flags = fx_save_exception_flags(env); + *ret = int64_to_floatx80(x, &env->fx_status); + fx_merge_exception_flags(env, old_flags); } #define GEN_OP2_XX(name, op) \ void HELPER(name)(CPUE2KState *env, floatx80 *x, floatx80 *y) \ { \ - int old_flags = save_exception_flags(env); \ - *x = glue(floatx80_, op)(*x, *y, &env->fp_status); \ - merge_exception_flags(env, old_flags); \ + int old_flags = fx_save_exception_flags(env); \ + *x = glue(floatx80_, op)(*x, *y, &env->fx_status); \ + fx_merge_exception_flags(env, old_flags); \ } GEN_OP2_XX(fxaddxx, add) @@ -197,22 +213,22 @@ GEN_OP2_XX(fxdivxx, div) void HELPER(fxrsubxx)(CPUE2KState *env, floatx80 *x, floatx80 *y) { - int old_flags = save_exception_flags(env); - *x = floatx80_sub(*y, *x, &env->fp_status); - merge_exception_flags(env, old_flags); + int old_flags = fx_save_exception_flags(env); + *x = floatx80_sub(*y, *x, &env->fx_status); + fx_merge_exception_flags(env, old_flags); } -#define GENERATE_FCMPODF(op, IN, F, cvt_macro) \ +#define GENERATE_FCMPODF(op, IN, F, cvt_macro, status, save_flags, merge_flags) \ uint32_t HELPER(op)(CPUE2KState *env, IN _x, IN _y) \ { \ - int old_flags = save_exception_flags(env); \ + int old_flags = save_flags(env); \ uint32_t ret; \ F x = cvt_macro(_x); \ F y = cvt_macro(_y); \ if (glue(F, _is_any_nan)(x) || glue(F, _is_any_nan)(y)) { \ ret = 0x45; \ } else { \ - FloatRelation relation = glue(F, _compare_quiet)(x, y, &env->fp_status); \ + FloatRelation relation = glue(F, _compare_quiet)(x, y, status); \ switch(relation) \ { \ case float_relation_less: \ @@ -230,12 +246,15 @@ void HELPER(fxrsubxx)(CPUE2KState *env, floatx80 *x, floatx80 *y) break; \ } \ } \ - merge_exception_flags(env, old_flags); \ + merge_flags(env, old_flags); \ return ret; \ } -GENERATE_FCMPODF(fcmpodsf, uint32_t, float32, make_float32) -GENERATE_FCMPODF(fcmpoddf, uint64_t, float64, make_float64) -GENERATE_FCMPODF(fxcmpodxf, floatx80 *, floatx80, deref) +GENERATE_FCMPODF(fcmpodsf, uint32_t, float32, make_float32, &env->fp_status, + fp_save_exception_flags, fp_merge_exception_flags) +GENERATE_FCMPODF(fcmpoddf, uint64_t, float64, make_float64, &env->fp_status, + fp_save_exception_flags, fp_merge_exception_flags) +GENERATE_FCMPODF(fxcmpodxf, floatx80 *, floatx80, deref, &env->fx_status, + fx_save_exception_flags, fx_merge_exception_flags) /* didn't found any difference between these instruction so keep it that way for now */ @@ -257,79 +276,74 @@ uint32_t HELPER(fxcmpudxf)(CPUE2KState *env, floatx80 *x, floatx80 *y) #define TOIF_RC_CURRENT 0x4 #define TOIF_RC_IGNORE_INEXACT 0x8 -static inline void toif_set_round_mode(CPUE2KState *env, uint32_t flags) +static inline void toif_set_round_mode(CPUE2KState *env, uint32_t flags, + float_status *s) { - if(flags <= FPCR_RC_CHOP) { - FloatRoundMode rm; - switch(flags) { - case FPCR_RC_NEAR: rm = float_round_nearest_even; break; - case FPCR_RC_DOWN: rm = float_round_down; break; - case FPCR_RC_UP: rm = float_round_up; break; - case FPCR_RC_CHOP: rm = float_round_to_zero; break; - } - set_float_rounding_mode(rm, &env->fp_status); + if ((flags & TOIF_RC_CURRENT) == 0) { + set_float_rounding_mode(rm[flags & FP_RC_CHOP], s); } } -static inline void toif_clear_inexact(CPUE2KState *env, uint32_t flags) +static inline void toif_clear_inexact(CPUE2KState *env, uint32_t flags, + float_status *s) { if(flags & TOIF_RC_IGNORE_INEXACT) { - int new_flags = get_float_exception_flags(&env->fp_status); + int new_flags = get_float_exception_flags(s); new_flags = new_flags & (~float_flag_inexact); - set_float_exception_flags(new_flags, &env->fp_status); + set_float_exception_flags(new_flags, s); } } uint32_t HELPER(fstoifs)(CPUE2KState *env, uint32_t flags, uint32_t f) { - int old_flags = save_exception_flags(env); + int old_flags = fp_save_exception_flags(env); FloatRoundMode oldrm = get_float_rounding_mode(&env->fp_status); uint32_t ret; - toif_set_round_mode(env, flags); + toif_set_round_mode(env, flags, &env->fp_status); ret = float32_val(float32_round_to_int(make_float32(f), &env->fp_status)); set_float_rounding_mode(oldrm, &env->fp_status); - toif_clear_inexact(env, flags); - merge_exception_flags(env, old_flags); + toif_clear_inexact(env, flags, &env->fp_status); + fp_merge_exception_flags(env, old_flags); return ret; } uint64_t HELPER(fdtoifd)(CPUE2KState *env, uint64_t flags, uint64_t f) { - int old_flags = save_exception_flags(env); + int old_flags = fp_save_exception_flags(env); FloatRoundMode oldrm = get_float_rounding_mode(&env->fp_status); uint64_t ret; - toif_set_round_mode(env, flags); + toif_set_round_mode(env, flags, &env->fp_status); ret = float64_val(float64_round_to_int(make_float64(f), &env->fp_status)); set_float_rounding_mode(oldrm, &env->fp_status); - toif_clear_inexact(env, flags); - merge_exception_flags(env, old_flags); + toif_clear_inexact(env, flags, &env->fp_status); + fp_merge_exception_flags(env, old_flags); return ret; } /* TODO: test if valid, test exception flags */ uint32_t HELPER(frcps)(CPUE2KState *env, uint32_t x) { - int old_flags = save_exception_flags(env); + int old_flags = fp_save_exception_flags(env); uint32_t y = float32_div(float32_one, make_float32(x), &env->fp_status); - merge_exception_flags(env, old_flags); + fp_merge_exception_flags(env, old_flags); return float32_val(y); } uint32_t HELPER(fsqrts)(CPUE2KState *env, uint32_t x) { - int old_flags = save_exception_flags(env); + int old_flags = fp_save_exception_flags(env); uint32_t y = float32_sqrt(make_float32(x), &env->fp_status); - merge_exception_flags(env, old_flags); + fp_merge_exception_flags(env, old_flags); return float32_val(y); } uint32_t HELPER(frsqrts)(CPUE2KState *env, uint32_t x) { - int old_flags = save_exception_flags(env); + int old_flags = fp_save_exception_flags(env); uint32_t y = float32_div(float32_one, float32_sqrt(make_float32(x), &env->fp_status), &env->fp_status); - merge_exception_flags(env, old_flags); + fp_merge_exception_flags(env, old_flags); return float32_val(y); } @@ -343,17 +357,17 @@ uint64 HELPER(fsqrtid)(CPUE2KState *env, uint64_t x) uint64_t HELPER(fsqrttd)(CPUE2KState *env, uint64_t x, uint64_t unused) { - int old_flags = save_exception_flags(env); + int old_flags = fp_save_exception_flags(env); uint64_t y = float64_sqrt(make_float64(x), &env->fp_status); - merge_exception_flags(env, old_flags); + fp_merge_exception_flags(env, old_flags); return float64_val(y); } void HELPER(fxsqrttxx)(CPUE2KState *env, floatx80 *x, floatx80 *unused) { - int old_flags = save_exception_flags(env); - *x = floatx80_sqrt(*x, &env->fp_status); - merge_exception_flags(env, old_flags); + int old_flags = fx_save_exception_flags(env); + *x = floatx80_sqrt(*x, &env->fx_status); + fx_merge_exception_flags(env, old_flags); } #define IMPL_FSCALE(name, ty, exp_len, exp_off, mul, cvt) \ diff --git a/target/e2k/helper_int.c b/target/e2k/helper_int.c index 134edfd977..1a1db52e8c 100644 --- a/target/e2k/helper_int.c +++ b/target/e2k/helper_int.c @@ -64,7 +64,7 @@ uint64_t helper_state_reg_read_i64(CPUE2KState *env, int idx) lsr = deposit64(lsr, LSR_STRMD_OFF, LSR_STRMD_LEN, env->lsr_strmd); return lsr; } - case 0x84: return env->pfpfr; /* %pfpfr */ + case 0x84: return env->pfpfr.raw; /* %pfpfr */ case 0x85: return env->fpcr.raw; /* %fpcr */ case 0x86: return env->fpsr.raw; /* %fpsr */ case 0x8a: return env->idr; /* %idr */ @@ -96,11 +96,12 @@ void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val) env->lsr_strmd = extract64(val, LSR_STRMD_OFF, LSR_STRMD_LEN); break; case 0x84: /* %pfpfr */ - env->pfpfr = val; + env->pfpfr.raw = val; + e2k_update_fp_status(env); break; case 0x85: /* %fpcr */ env->fpcr.raw = val; - e2k_update_fp_status(env); + e2k_update_fx_status(env); break; case 0x86: env->fpsr.raw = val; break; /* %fpsr */ default: @@ -119,11 +120,12 @@ void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val) env->lsr_lcnt = val; break; case 0x84: /* %pfpfr */ - env->pfpfr = deposit64(env->pfpfr, 0, 32, val); + env->pfpfr.raw = val; + e2k_update_fp_status(env); break; case 0x85: /* %fpcr */ env->fpcr.raw = val; - e2k_update_fp_status(env); + e2k_update_fx_status(env); break; case 0x86: env->fpsr.raw = val; break; /* %fpsr */ default: diff --git a/target/e2k/helper_vec.c b/target/e2k/helper_vec.c index 76beb74bbb..e4a33f8bf8 100644 --- a/target/e2k/helper_vec.c +++ b/target/e2k/helper_vec.c @@ -1,6 +1,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "cpu.h" +#include "helper-tcg.h" #include "exec/exec-all.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" @@ -37,7 +38,6 @@ typedef union { int64_t sd[vec64_ud]; } vec64; -#define ident(x) x #define shr16(x) ((x) >> 16) #define shr14_add1_shr1(x) ((((x) >> 14) + 1) >> 1) #define and16(x) ((x) & 0xffff)