Re: [Qemu-devel] [PATCH v9 09/10] target-mips: Implement FCR31's R/W bitmask and related functionalities

2016-06-14 Thread Leon Alrae
On Fri, Jun 10, 2016 at 11:57:36AM +0200, Aleksandar Markovic wrote:
> From: Aleksandar Markovic 
> 
> 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 
> Signed-off-by: Maciej W. Rozycki 
> Signed-off-by: Aleksandar Markovic 
> ---
>  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(-)

Reviewed-by: Leon Alrae 



[Qemu-devel] [PATCH v9 09/10] target-mips: Implement FCR31's R/W bitmask and related functionalities

2016-06-10 Thread Aleksandar Markovic
From: Aleksandar Markovic 

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 
Signed-off-by: Maciej W. Rozycki 
Signed-off-by: Aleksandar Markovic 
---
 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 5f3ec97..cc21057 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4608,6 +4608,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 6478420..7c81c41 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -110,6 +110,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
@@ -817,10 +818,17 @@ static inline void restore_flush_mode(CPUMIPSState *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,
+>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 b0b4a32..aacc721 100644
--- a/target-mips/gdbstub.c
+++ b/target-mips/gdbstub.c
@@ -89,11 +89,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 & 0xFF83;
-/* 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 753916d..62776a3 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2576,21 +2576,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 = 0xfefc;
-env->active_fpu.fcr31 = (arg1 & ~mask) |
-(env->active_fpu.fcr31 & mask);
-} else if (!(arg1 & 0x007c)) {
-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);
+