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
This commit is contained in:
Aleksandar Markovic 2018-02-24 21:15:35 -05:00 committed by Lioncash
parent 84b516d9db
commit 4a540f88de
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
4 changed files with 43 additions and 17 deletions

View file

@ -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)

View file

@ -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());

View file

@ -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;
}

View file

@ -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,