diff options
Diffstat (limited to 'target/alpha/helper.c')
| -rw-r--r-- | target/alpha/helper.c | 64 |
1 files changed, 32 insertions, 32 deletions
diff --git a/target/alpha/helper.c b/target/alpha/helper.c index 19cda0a2db..55d7274d94 100644 --- a/target/alpha/helper.c +++ b/target/alpha/helper.c @@ -36,53 +36,53 @@ uint64_t cpu_alpha_load_fpcr(CPUAlphaState *env) void cpu_alpha_store_fpcr(CPUAlphaState *env, uint64_t val) { + static const uint8_t rm_map[] = { + [FPCR_DYN_NORMAL >> FPCR_DYN_SHIFT] = float_round_nearest_even, + [FPCR_DYN_CHOPPED >> FPCR_DYN_SHIFT] = float_round_to_zero, + [FPCR_DYN_MINUS >> FPCR_DYN_SHIFT] = float_round_down, + [FPCR_DYN_PLUS >> FPCR_DYN_SHIFT] = float_round_up, + }; + uint32_t fpcr = val >> 32; uint32_t t = 0; + /* Record the raw value before adjusting for linux-user. */ + env->fpcr = fpcr; + +#ifdef CONFIG_USER_ONLY + /* + * Override some of these bits with the contents of ENV->SWCR. + * In system mode, some of these would trap to the kernel, at + * which point the kernel's handler would emulate and apply + * the software exception mask. + */ + uint32_t soft_fpcr = alpha_ieee_swcr_to_fpcr(env->swcr) >> 32; + fpcr |= soft_fpcr & (FPCR_STATUS_MASK | FPCR_DNZ); + + /* + * The IOV exception is disabled by the kernel with SWCR_TRAP_ENABLE_INV, + * which got mapped by alpha_ieee_swcr_to_fpcr to FPCR_INVD. + * Add FPCR_IOV to fpcr_exc_enable so that it is handled identically. + */ + t |= CONVERT_BIT(soft_fpcr, FPCR_INVD, FPCR_IOV); +#endif + t |= CONVERT_BIT(fpcr, FPCR_INED, FPCR_INE); t |= CONVERT_BIT(fpcr, FPCR_UNFD, FPCR_UNF); t |= CONVERT_BIT(fpcr, FPCR_OVFD, FPCR_OVF); t |= CONVERT_BIT(fpcr, FPCR_DZED, FPCR_DZE); t |= CONVERT_BIT(fpcr, FPCR_INVD, FPCR_INV); - env->fpcr = fpcr; env->fpcr_exc_enable = ~t & FPCR_STATUS_MASK; - switch (fpcr & FPCR_DYN_MASK) { - case FPCR_DYN_NORMAL: - default: - t = float_round_nearest_even; - break; - case FPCR_DYN_CHOPPED: - t = float_round_to_zero; - break; - case FPCR_DYN_MINUS: - t = float_round_down; - break; - case FPCR_DYN_PLUS: - t = float_round_up; - break; - } - env->fpcr_dyn_round = t; - - env->fpcr_flush_to_zero = (fpcr & FPCR_UNFD) && (fpcr & FPCR_UNDZ); + env->fpcr_dyn_round = rm_map[(fpcr & FPCR_DYN_MASK) >> FPCR_DYN_SHIFT]; env->fp_status.flush_inputs_to_zero = (fpcr & FPCR_DNZ) != 0; + t = (fpcr & FPCR_UNFD) && (fpcr & FPCR_UNDZ); #ifdef CONFIG_USER_ONLY - /* - * Override some of these bits with the contents of ENV->SWCR. - * In system mode, some of these would trap to the kernel, at - * which point the kernel's handler would emulate and apply - * the software exception mask. - */ - if (env->swcr & SWCR_MAP_DMZ) { - env->fp_status.flush_inputs_to_zero = 1; - } - if (env->swcr & SWCR_MAP_UMZ) { - env->fp_status.flush_to_zero = 1; - } - env->fpcr_exc_enable &= ~(alpha_ieee_swcr_to_fpcr(env->swcr) >> 32); + t |= (env->swcr & SWCR_MAP_UMZ) != 0; #endif + env->fpcr_flush_to_zero = t; } uint64_t helper_load_fpcr(CPUAlphaState *env) |