From 4a540f88deee46a1eb0d625046fce53a872be7ce Mon Sep 17 00:00:00 2001 From: Aleksandar Markovic Date: Sat, 24 Feb 2018 21:15:35 -0500 Subject: [PATCH] target-mips: Implement FCR31's R/W bitmask and related functionalities This patch implements read and write access rules for Mips floating point control and status register (FCR31). The change can be divided into following parts: - Add fields that will keep FCR31's R/W bitmask in procesor definitions and processor float_status structure. - Add appropriate value for FCR31's R/W bitmask for each supported processor. - Add function for setting snan_bit_is_one, and integrate it in appropriate places. - Modify handling of CTC1 (case 31) instruction to use FCR31's R/W bitmask. - Modify handling user mode executables for Mips, in relation to the bit EF_MIPS_NAN2008 from ELF header, that is in turn related to reading and writing to FCR31. - Modify gdb behavior in relation to FCR31. Backports commit 599bc5e89c46f95f86ccad0d747d041c89a28806 from qemu --- qemu/target-mips/cpu.h | 8 ++++++++ qemu/target-mips/op_helper.c | 14 +++---------- qemu/target-mips/translate.c | 5 ++--- qemu/target-mips/translate_init.c | 33 ++++++++++++++++++++++++++++--- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/qemu/target-mips/cpu.h b/qemu/target-mips/cpu.h index 63a1dc00..a6bccb6c 100644 --- a/qemu/target-mips/cpu.h +++ b/qemu/target-mips/cpu.h @@ -112,6 +112,7 @@ struct CPUMIPSFPUContext { #define FCR0_PRID 8 #define FCR0_REV 0 /* fcsr */ + uint32_t fcr31_rw_bitmask; uint32_t fcr31; #define FCR31_ABS2008 19 #define FCR31_NAN2008 18 @@ -843,10 +844,17 @@ static inline void restore_flush_mode(CPUMIPSState *env) &env->active_fpu.fp_status); } +static inline void restore_snan_bit_mode(CPUMIPSState *env) +{ + set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0, + &env->active_fpu.fp_status); +} + static inline void restore_fp_status(CPUMIPSState *env) { restore_rounding_mode(env); restore_flush_mode(env); + restore_snan_bit_mode(env); } static inline void restore_msa_fp_status(CPUMIPSState *env) diff --git a/qemu/target-mips/op_helper.c b/qemu/target-mips/op_helper.c index 5435af40..1d9d2212 100644 --- a/qemu/target-mips/op_helper.c +++ b/qemu/target-mips/op_helper.c @@ -2560,21 +2560,13 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) ((arg1 & 0x4) << 22); break; case 31: - if (env->insn_flags & ISA_MIPS32R6) { - uint32_t mask = 0xfefc0000; - env->active_fpu.fcr31 = (arg1 & ~mask) | - (env->active_fpu.fcr31 & mask); - } else if (!(arg1 & 0x007c0000)) { - env->active_fpu.fcr31 = arg1; - } + env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) | + (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask)); break; default: return; } - /* set rounding mode */ - restore_rounding_mode(env); - /* set flush-to-zero mode */ - restore_flush_mode(env); + restore_fp_status(env); set_float_exception_flags(0, &env->active_fpu.fp_status); if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31)) do_raise_exception(env, EXCP_FPE, GETPC()); diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 042fec00..10d635d6 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -20377,8 +20377,8 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; + env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask; env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; - set_snan_bit_is_one(1, &env->active_fpu.fp_status); env->msair = env->cpu_model->MSAIR; env->insn_flags = env->cpu_model->insn_flags; @@ -20484,8 +20484,7 @@ void cpu_state_reset(CPUMIPSState *env) } compute_hflags(env); - restore_rounding_mode(env); - restore_flush_mode(env); + restore_fp_status(env); restore_pamask(env); cs->exception_index = EXCP_NONE; } diff --git a/qemu/target-mips/translate_init.c b/qemu/target-mips/translate_init.c index 69f3f4df..90024b7b 100644 --- a/qemu/target-mips/translate_init.c +++ b/qemu/target-mips/translate_init.c @@ -84,6 +84,7 @@ struct mips_def_t { int32_t CP0_TCStatus_rw_bitmask; int32_t CP0_SRSCtl; int32_t CP1_fcr0; + int32_t CP1_fcr31_rw_bitmask; int32_t CP1_fcr31; int32_t MSAIR; int32_t SEGBITS; @@ -130,6 +131,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -164,6 +166,7 @@ static const mips_def_t mips_defs[] = 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -194,6 +197,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -224,6 +228,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -255,6 +260,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -286,6 +292,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -318,6 +325,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -351,6 +359,7 @@ static const mips_def_t mips_defs[] = 0, (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), + 0xFF83FFFF, 0, 0, 32, @@ -383,12 +392,13 @@ static const mips_def_t mips_defs[] = (0x3 << CP0TCSt_TKSU) | (1 << CP0TCSt_IXMT) | (0xff << CP0TCSt_TASID), (0xf << CP0SRSCtl_HSS), - 0, - 32, - 32, (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID), + 0xFF83FFFF, 0, + 0, + 32, + 32, 0x3fffffff, (1U << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) | (0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1), @@ -433,6 +443,7 @@ static const mips_def_t mips_defs[] = 0, (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), + 0xFF83FFFF, 0, 0, 32, @@ -463,6 +474,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -494,6 +506,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 32, @@ -540,6 +553,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_FREP) | (1 << FCR0_UFRP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x03 << FCR0_PRID), + 0xFF83FFFF, (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), 0, 32, @@ -582,6 +596,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_HAS2008) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + 0x0103FFFF, (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), 0, 32, @@ -619,6 +634,7 @@ static const mips_def_t mips_defs[] = 0, /* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */ (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), + 0x0183FFFF, 0, 0, 40, @@ -648,6 +664,7 @@ static const mips_def_t mips_defs[] = 0, /* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */ (0x54 << FCR0_PRID) | (0x0 << FCR0_REV), + 0xFF83FFFF, 0, 0, 40, @@ -679,6 +696,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 42, @@ -713,6 +731,7 @@ static const mips_def_t mips_defs[] = /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ (1 << FCR0_D) | (1 << FCR0_S) | (0x81 << FCR0_PRID) | (0x0 << FCR0_REV), + 0xFF83FFFF, 0, 0, 42, @@ -749,6 +768,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_3D) | (1 << FCR0_PS) | (1 << FCR0_D) | (1 << FCR0_S) | (0x82 << FCR0_PRID) | (0x0 << FCR0_REV), + 0xFF83FFFF, 0, 0, 40, @@ -784,6 +804,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + 0xFF83FFFF, 0, 0, 42, @@ -827,6 +848,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + 0x0103FFFF, (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), 0, 48, @@ -863,6 +885,7 @@ static const mips_def_t mips_defs[] = 0, 0, 0, // CP1_fcr0 + 0, 0, // CP1_fcr31 0, 42, @@ -900,6 +923,7 @@ static const mips_def_t mips_defs[] = (0x89 << FCR0_PRID) | (0x0 << FCR0_REV), 0, 0, + 0, 42, 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, @@ -928,6 +952,7 @@ static const mips_def_t mips_defs[] = 0, 0, (0x5 << FCR0_PRID) | (0x1 << FCR0_REV), + 0xFF83FFFF, 0, 0, 40, @@ -958,6 +983,7 @@ static const mips_def_t mips_defs[] = 0, 0, (0x5 << FCR0_PRID) | (0x1 << FCR0_REV), + 0xFF83FFFF, 0, 0, 40, @@ -994,6 +1020,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + 0xFF83FFFF, 0, 0, 42,