diff options
author | Aleksandar Markovic <aleksandar.markovic@imgtec.com> | 2016-06-10 11:57:36 +0200 |
---|---|---|
committer | Leon Alrae <leon.alrae@imgtec.com> | 2016-06-24 13:43:52 +0100 |
commit | 599bc5e89c46f95f86ccad0d747d041c89a28806 (patch) | |
tree | ac0fde39e6c036c145a5beba89e3a8b9975e0e50 /target-mips | |
parent | 87552089b62fa229d2ff86906e4e779177fb5835 (diff) |
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.
Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
Diffstat (limited to 'target-mips')
-rw-r--r-- | target-mips/cpu.h | 8 | ||||
-rw-r--r-- | target-mips/gdbstub.c | 8 | ||||
-rw-r--r-- | target-mips/op_helper.c | 14 | ||||
-rw-r--r-- | target-mips/translate.c | 5 | ||||
-rw-r--r-- | target-mips/translate_init.c | 26 |
5 files changed, 42 insertions, 19 deletions
diff --git a/target-mips/cpu.h b/target-mips/cpu.h index b593f3b7b9..bc0c905041 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -111,6 +111,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 @@ -853,10 +854,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/target-mips/gdbstub.c b/target-mips/gdbstub.c index 2707ff5c2b..7c682289c2 100644 --- a/target-mips/gdbstub.c +++ b/target-mips/gdbstub.c @@ -90,11 +90,9 @@ int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) { switch (n) { case 70: - env->active_fpu.fcr31 = tmp & 0xFF83FFFF; - /* set rounding mode */ - restore_rounding_mode(env); - /* set flush-to-zero mode */ - restore_flush_mode(env); + env->active_fpu.fcr31 = (tmp & env->active_fpu.fcr31_rw_bitmask) | + (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask)); + restore_fp_status(env); break; case 71: /* FIR is read-only. Ignore writes. */ diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 7f6e8217b2..69daade24e 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2575,21 +2575,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/target-mips/translate.c b/target-mips/translate.c index 01b42d22bb..cc321e9cce 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -20241,8 +20241,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; @@ -20352,8 +20352,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/target-mips/translate_init.c b/target-mips/translate_init.c index a37d8bb60c..b10284cc5d 100644 --- a/target-mips/translate_init.c +++ b/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; @@ -273,6 +274,8 @@ static const mips_def_t mips_defs[] = .CP0_Status_rw_bitmask = 0x3678FF1F, .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 32, .PABITS = 32, .insn_flags = CPU_MIPS32R2 | ASE_MIPS16, @@ -303,6 +306,8 @@ static const mips_def_t mips_defs[] = (0xff << CP0TCSt_TASID), .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .CP0_SRSCtl = (0xf << CP0SRSCtl_HSS), .CP0_SRSConf0_rw_bitmask = 0x3fffffff, .CP0_SRSConf0 = (1U << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) | @@ -343,6 +348,8 @@ static const mips_def_t mips_defs[] = .CP0_Status_rw_bitmask = 0x3778FF1F, .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 32, .PABITS = 32, .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2, @@ -427,6 +434,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x03 << FCR0_PRID), .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 32, .PABITS = 40, .insn_flags = CPU_MIPS32R5 | ASE_MSA, @@ -465,6 +473,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), + .CP1_fcr31_rw_bitmask = 0x0103FFFF, .SEGBITS = 32, .PABITS = 32, .insn_flags = CPU_MIPS32R6 | ASE_MICROMIPS, @@ -485,6 +494,8 @@ static const mips_def_t mips_defs[] = .CP0_Status_rw_bitmask = 0x3678FFFF, /* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */ .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0x0183FFFF, .SEGBITS = 40, .PABITS = 36, .insn_flags = CPU_MIPS3, @@ -503,6 +514,8 @@ static const mips_def_t mips_defs[] = .CP0_Status_rw_bitmask = 0x3678FFFF, /* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */ .CP1_fcr0 = (0x54 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 40, .PABITS = 32, .insn_flags = CPU_VR54XX, @@ -548,6 +561,8 @@ static const mips_def_t mips_defs[] = /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) | (0x81 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 42, .PABITS = 36, .insn_flags = CPU_MIPS64, @@ -575,6 +590,8 @@ static const mips_def_t mips_defs[] = .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) | (1 << FCR0_D) | (1 << FCR0_S) | (0x82 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 40, .PABITS = 36, .insn_flags = CPU_MIPS64 | ASE_MIPS3D, @@ -601,6 +618,8 @@ static const mips_def_t mips_defs[] = .CP1_fcr0 = (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), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 42, .PABITS = 36, .insn_flags = CPU_MIPS64R2 | ASE_MIPS3D, @@ -686,6 +705,7 @@ static const mips_def_t mips_defs[] = (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), + .CP1_fcr31_rw_bitmask = 0x0103FFFF, .SEGBITS = 48, .PABITS = 48, .insn_flags = CPU_MIPS64R6 | ASE_MSA, @@ -704,6 +724,8 @@ static const mips_def_t mips_defs[] = .CCRes = 2, .CP0_Status_rw_bitmask = 0x35D0FFFF, .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 40, .PABITS = 40, .insn_flags = CPU_LOONGSON2E, @@ -722,6 +744,8 @@ static const mips_def_t mips_defs[] = .CCRes = 2, .CP0_Status_rw_bitmask = 0xF5D0FF1F, /* Bits 7:5 not writable. */ .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 40, .PABITS = 40, .insn_flags = CPU_LOONGSON2F, @@ -749,6 +773,8 @@ static const mips_def_t mips_defs[] = .CP1_fcr0 = (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), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 42, .PABITS = 36, .insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2, |