All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <laurent@vivier.eu>
To: qemu-devel@nongnu.org
Cc: Aurelien Jarno <aurelien@aurel32.net>,
	Richard Henderson <rth@twiddle.net>,
	Laurent Vivier <laurent@vivier.eu>
Subject: [Qemu-devel] [PATCH v3 07/16] target-m68k: manage FPU exceptions
Date: Tue,  7 Feb 2017 01:59:21 +0100	[thread overview]
Message-ID: <20170207005930.28327-8-laurent@vivier.eu> (raw)
In-Reply-To: <20170207005930.28327-1-laurent@vivier.eu>

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target/m68k/cpu.h        |  28 +++++++++++++
 target/m68k/fpu_helper.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++-
 target/m68k/helper.h     |   1 +
 target/m68k/translate.c  |  27 ++++++++++++
 4 files changed, 162 insertions(+), 1 deletion(-)

diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 6b3cb26..7985dc3 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -57,6 +57,15 @@
 #define EXCP_TRAP15         47   /* User trap #15.  */
 #define EXCP_UNSUPPORTED    61
 #define EXCP_ICE            13
+#define EXCP_FP_BSUN        48 /* Branch Set on Unordered */
+#define EXCP_FP_INEX        49 /* Inexact result */
+#define EXCP_FP_DZ          50 /* Divide by Zero */
+#define EXCP_FP_UNFL        51 /* Underflow */
+#define EXCP_FP_OPERR       52 /* Operand Error */
+#define EXCP_FP_OVFL        53 /* Overflow */
+#define EXCP_FP_SNAN        54 /* Signaling Not-A-Number */
+#define EXCP_FP_UNIMP       55 /* Unimplemented Data type */
+
 
 #define EXCP_RTE            0x100
 #define EXCP_HALT_INSN      0x101
@@ -222,6 +231,25 @@ typedef enum {
 #define FPSR_CC_Z     0x04000000 /* Zero */
 #define FPSR_CC_N     0x08000000 /* Negative */
 
+/* Exception Status */
+#define FPSR_ES_MASK  0x0000ff00
+#define FPSR_ES_BSUN  0x00008000 /* Branch Set on Unordered */
+#define FPSR_ES_SNAN  0x00004000 /* Signaling Not-A-Number */
+#define FPSR_ES_OPERR 0x00002000 /* Operand Error */
+#define FPSR_ES_OVFL  0x00001000 /* Overflow */
+#define FPSR_ES_UNFL  0x00000800 /* Underflow */
+#define FPSR_ES_DZ    0x00000400 /* Divide by Zero */
+#define FPSR_ES_INEX2 0x00000200 /* Inexact operation */
+#define FPSR_ES_INEX  0x00000100 /* Inexact decimal input */
+
+/* Accrued Exception */
+#define FPSR_AE_MASK  0x000000ff
+#define FPSR_AE_IOP   0x00000080 /* Invalid Operation */
+#define FPSR_AE_OVFL  0x00000040 /* Overflow */
+#define FPSR_AE_UNFL  0x00000020 /* Underflow */
+#define FPSR_AE_DZ    0x00000010 /* Divide by Zero */
+#define FPSR_AE_INEX  0x00000008 /* Inexact */
+
 /* Quotient */
 
 #define FPSR_QT_MASK  0x00ff0000
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 9d39118..1e68c41 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -177,6 +177,70 @@ static void restore_rounding_mode(CPUM68KState *env)
     }
 }
 
+static void set_fpsr_exception(CPUM68KState *env)
+{
+    uint32_t fpsr = 0;
+    int flags;
+
+    flags = get_float_exception_flags(&env->fp_status);
+    if (flags == 0) {
+        return;
+    }
+    set_float_exception_flags(0, &env->fp_status);
+
+    if (flags & float_flag_invalid) {
+        fpsr |= FPSR_AE_IOP;
+    }
+    if (flags & float_flag_divbyzero) {
+        fpsr |= FPSR_AE_DZ;
+    }
+    if (flags & float_flag_overflow) {
+        fpsr |= FPSR_AE_OVFL;
+    }
+    if (flags & float_flag_underflow) {
+        fpsr |= FPSR_AE_UNFL;
+    }
+    if (flags & float_flag_inexact) {
+        fpsr |= FPSR_AE_INEX;
+    }
+
+    env->fpsr = (env->fpsr & ~FPSR_AE_MASK) | fpsr;
+}
+
+static void fpu_exception(CPUM68KState *env, uint32_t exception)
+{
+    CPUState *cs = CPU(m68k_env_get_cpu(env));
+
+    env->fpsr = (env->fpsr & ~FPSR_ES_MASK) | exception;
+    if (env->fpcr & exception) {
+        switch (exception) {
+        case FPSR_ES_BSUN:
+            cs->exception_index = EXCP_FP_BSUN;
+            break;
+        case FPSR_ES_SNAN:
+            cs->exception_index = EXCP_FP_SNAN;
+            break;
+        case FPSR_ES_OPERR:
+            cs->exception_index = EXCP_FP_OPERR;
+            break;
+        case FPSR_ES_OVFL:
+            cs->exception_index = EXCP_FP_OVFL;
+            break;
+        case FPSR_ES_UNFL:
+            cs->exception_index = EXCP_FP_UNFL;
+            break;
+        case FPSR_ES_DZ:
+            cs->exception_index = EXCP_FP_DZ;
+            break;
+        case FPSR_ES_INEX:
+        case FPSR_ES_INEX2:
+            cs->exception_index = EXCP_FP_INEX;
+            break;
+        }
+        cpu_loop_exit_restore(cs, GETPC());
+    }
+}
+
 void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val)
 {
     env->fpcr = val & 0xffff;
@@ -292,10 +356,16 @@ void HELPER(cmp_FP0_FP1)(CPUM68KState *env)
 {
     floatx80 fp0 = FP0_to_floatx80(env);
     floatx80 fp1 = FP1_to_floatx80(env);
-    int float_compare;
+    int flags, float_compare;
 
     float_compare = floatx80_compare(fp1, fp0, &env->fp_status);
     env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | float_comp_to_cc(float_compare);
+
+    flags = get_float_exception_flags(&env->fp_status);
+    if (flags & float_flag_invalid) {
+        fpu_exception(env, FPSR_ES_OPERR);
+   }
+   set_fpsr_exception(env);
 }
 
 void HELPER(tst_FP0)(CPUM68KState *env)
@@ -315,4 +385,39 @@ void HELPER(tst_FP0)(CPUM68KState *env)
         fpsr |= FPSR_CC_Z;
     }
     env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | fpsr;
+
+    set_fpsr_exception(env);
+}
+
+void HELPER(update_fpstatus)(CPUM68KState *env)
+{
+    int flags = get_float_exception_flags(&env->fp_status);
+
+    if (env->fpsr & FPSR_AE_IOP) {
+        flags |= float_flag_invalid;
+    } else {
+        flags &= ~float_flag_invalid;
+    }
+    if (env->fpsr & FPSR_AE_DZ) {
+        flags |= float_flag_divbyzero;
+    } else {
+        flags &= ~float_flag_divbyzero;
+    }
+    if (env->fpsr & FPSR_AE_OVFL) {
+        flags |= float_flag_overflow;
+    } else {
+        flags &= ~float_flag_overflow;
+    }
+    if (env->fpsr & FPSR_AE_UNFL) {
+        flags |= float_flag_underflow;
+    } else {
+        flags &= ~float_flag_underflow;
+    }
+    if (env->fpsr & FPSR_AE_INEX) {
+        flags |= float_flag_inexact;
+    } else {
+        flags &= ~float_flag_inexact;
+    }
+
+    set_float_exception_flags(flags, &env->fp_status);
 }
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 03fb268..072a6d0 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -30,6 +30,7 @@ DEF_HELPER_1(div_FP0_FP1, void, env)
 DEF_HELPER_1(cmp_FP0_FP1, void, env)
 DEF_HELPER_2(set_fpcr, void, env, i32)
 DEF_HELPER_1(tst_FP0, void, env)
+DEF_HELPER_1(update_fpstatus, void, env)
 
 DEF_HELPER_3(mac_move, void, env, i32, i32)
 DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index cce8a8f..f9c64ff 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -4388,6 +4388,7 @@ static void gen_load_fcr(DisasContext *s, TCGv addr, int reg)
     switch (reg) {
     case 0: /* FPSR */
         tcg_gen_qemu_ld32u(QEMU_FPSR, addr, index);
+        gen_helper_update_fpstatus(cpu_env);
         break;
     case 1: /* FPIAR */
         break;
@@ -4431,6 +4432,7 @@ static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s,
         case 2: /* FPSR */
             SRC_EA(env, val, OS_LONG, 0, NULL);
             tcg_gen_mov_i32(QEMU_FPSR, val);
+            gen_helper_update_fpstatus(cpu_env);
             break;
         case 4: /* FPCR */
             SRC_EA(env, val, OS_LONG, 0, NULL);
@@ -5481,6 +5483,21 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                 (env->fpsr & FPSR_CC_I) ? 'I' : '-',
                 (env->fpsr & FPSR_CC_Z) ? 'Z' : '-',
                 (env->fpsr & FPSR_CC_N) ? 'N' : '-');
+    cpu_fprintf(f, "%c%c%c%c%c%c%c%c ",
+                (env->fpsr & FPSR_ES_BSUN) ? 'B' : '-',
+                (env->fpsr & FPSR_ES_SNAN) ? 'A' : '-',
+                (env->fpsr & FPSR_ES_OPERR) ? 'O' : '-',
+                (env->fpsr & FPSR_ES_OVFL) ? 'V' : '-',
+                (env->fpsr & FPSR_ES_UNFL) ? 'U' : '-',
+                (env->fpsr & FPSR_ES_DZ) ? 'Z' : '-',
+                (env->fpsr & FPSR_ES_INEX2) ? '2' : '-',
+                (env->fpcr & FPSR_ES_INEX) ? 'I' : '-');
+    cpu_fprintf(f, "%c%c%c%c%c",
+                (env->fpsr & FPSR_AE_IOP) ? 'O' : '-',
+                (env->fpsr & FPSR_AE_OVFL) ? 'V' : '-',
+                (env->fpsr & FPSR_AE_UNFL) ? 'U' : '-',
+                (env->fpsr & FPSR_AE_DZ) ? 'Z' : '-',
+                (env->fpcr & FPSR_ES_INEX) ? 'I' : '-');
     cpu_fprintf(f, "\n                                "
                    "FPCR =     %04x ", env->fpcr);
     switch (env->fpcr & FPCR_PREC_MASK) {
@@ -5508,6 +5525,16 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
         cpu_fprintf(f, "RP ");
         break;
     }
+    /* FPCR exception mask uses the same bitmask as FPSR */
+    cpu_fprintf(f, "%c%c%c%c%c%c%c%c\n",
+                (env->fpcr & FPSR_ES_BSUN) ? 'B' : '-',
+                (env->fpcr & FPSR_ES_SNAN) ? 'A' : '-',
+                (env->fpcr & FPSR_ES_OPERR) ? 'O' : '-',
+                (env->fpcr & FPSR_ES_OVFL) ? 'V' : '-',
+                (env->fpcr & FPSR_ES_UNFL) ? 'U' : '-',
+                (env->fpcr & FPSR_ES_DZ) ? 'Z' : '-',
+                (env->fpcr & FPSR_ES_INEX2) ? '2' : '-',
+                (env->fpcr & FPSR_ES_INEX) ? 'I' : '-');
 }
 
 void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb,
-- 
2.9.3

  parent reply	other threads:[~2017-02-07  1:00 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-07  0:59 [Qemu-devel] [PATCH v3 00/16] target-m68k: implement 680x0 FPU Laurent Vivier
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 01/16] softfloat: define 680x0 specific values Laurent Vivier
2017-02-08 21:30   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 02/16] softloat: disable floatx80_invalid_encoding() for m68k Laurent Vivier
2017-02-08 21:32   ` Richard Henderson
2017-02-08 22:58   ` Peter Maydell
2017-02-09  8:07     ` Laurent Vivier
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 03/16] target-m68k: move FPU helpers to fpu_helper.c Laurent Vivier
2017-02-08 21:33   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 04/16] target-m68k: define ext_opsize Laurent Vivier
2017-02-08 21:33   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 05/16] target-m68k: use floatx80 internally Laurent Vivier
2017-02-15 22:59   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 06/16] target-m68k: add FPCR and FPSR Laurent Vivier
2017-02-16  1:10   ` Richard Henderson
2017-02-07  0:59 ` Laurent Vivier [this message]
2017-02-16  1:16   ` [Qemu-devel] [PATCH v3 07/16] target-m68k: manage FPU exceptions Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 08/16] target-m68k: define 96bit FP registers for gdb on 680x0 Laurent Vivier
2017-02-16  1:17   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 09/16] target-m68k: add fmovem Laurent Vivier
2017-02-16  1:22   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 10/16] target-m68k: add fscc Laurent Vivier
2017-02-16  1:27   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 11/16] target-m68k: add fmovecr Laurent Vivier
2017-02-16  1:28   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 12/16] target-m68k: add fscale, fgetman, fgetexp and fmod Laurent Vivier
2017-02-16  1:34   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 13/16] target-m68k: add fsglmul and fsgldiv Laurent Vivier
2017-02-16  1:36   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 14/16] target-m68k: add explicit single and double precision operations Laurent Vivier
2017-02-16  1:41   ` Richard Henderson
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 15/16] target-m68k: add more FPU instructions Laurent Vivier
2017-02-16  1:46   ` Richard Henderson
2017-02-16 10:18     ` Andreas Schwab
2017-02-16 21:01       ` Richard Henderson
2017-02-17  9:06         ` Andreas Schwab
2017-02-07  0:59 ` [Qemu-devel] [PATCH v3 16/16] target-m68k: add fsincos Laurent Vivier
2017-02-07  1:25 ` [Qemu-devel] [PATCH v3 00/16] target-m68k: implement 680x0 FPU no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170207005930.28327-8-laurent@vivier.eu \
    --to=laurent@vivier.eu \
    --cc=aurelien@aurel32.net \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.