[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 09/10] target-mips: Implement FCR31's R/W bitmask and
From: |
Leon Alrae |
Subject: |
[Qemu-devel] [PULL 09/10] target-mips: Implement FCR31's R/W bitmask and related functionalities |
Date: |
Sun, 26 Jun 2016 14:38:41 +0100 |
From: Aleksandar Markovic <address@hidden>
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 <address@hidden>
Signed-off-by: Maciej W. Rozycki <address@hidden>
Signed-off-by: Aleksandar Markovic <address@hidden>
Reviewed-by: Leon Alrae <address@hidden>
Signed-off-by: Leon Alrae <address@hidden>
---
linux-user/main.c | 14 ++++++++++++++
target-mips/cpu.h | 8 ++++++++
target-mips/gdbstub.c | 8 +++-----
target-mips/op_helper.c | 14 +++-----------
target-mips/translate.c | 5 ++---
target-mips/translate_init.c | 26 ++++++++++++++++++++++++++
6 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index fd88e22..78d8d04 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4687,6 +4687,20 @@ int main(int argc, char **argv, char **envp)
if (regs->cp0_epc & 1) {
env->hflags |= MIPS_HFLAG_M16;
}
+ if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
+ ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
+ if ((env->active_fpu.fcr31_rw_bitmask &
+ (1 << FCR31_NAN2008)) == 0) {
+ fprintf(stderr, "ELF binary's NaN mode not supported by
CPU\n");
+ exit(1);
+ }
+ if ((info->elf_flags & EF_MIPS_NAN2008) != 0) {
+ env->active_fpu.fcr31 |= (1 << FCR31_NAN2008);
+ } else {
+ env->active_fpu.fcr31 &= ~(1 << FCR31_NAN2008);
+ }
+ restore_snan_bit_mode(env);
+ }
}
#elif defined(TARGET_OPENRISC)
{
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index b593f3b..bc0c905 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 2707ff5..7c68228 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 7f6e821..69daade 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 01b42d2..cc321e9 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 a37d8bb..b10284c 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,
--
2.7.4
- [Qemu-devel] [PULL 00/10] target-mips queue, Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 02/10] softfloat: Clean code format in fpu/softfloat-specialize.h, Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 03/10] softfloat: For Mips only, correct default NaN values, Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 04/10] softfloat: Handle snan_bit_is_one == 0 in MIPS pickNaNMulAdd(), Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 05/10] linux-user: Update preprocessor constants for Mips-specific e_flags bits, Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 06/10] target-mips: Activate IEEE 754-2008 signaling NaN bit meaning for MSA, Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 07/10] target-mips: Add abs2008 flavor of <ABS|NEG>.<S|D>, Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 01/10] softfloat: Implement run-time-configurable meaning of signaling NaN bit, Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 08/10] target-mips: Add nan2008 flavor of <CEIL|CVT|FLOOR|ROUND|TRUNC>.<L|W>.<S|D>, Leon Alrae, 2016/06/26
- [Qemu-devel] [PULL 09/10] target-mips: Implement FCR31's R/W bitmask and related functionalities,
Leon Alrae <=
- [Qemu-devel] [PULL 10/10] target-mips: Add FCR31's FS bit definition, Leon Alrae, 2016/06/26
- Re: [Qemu-devel] [PULL 00/10] target-mips queue, Peter Maydell, 2016/06/27