diff mbox series

[01/13] target-openrisc: Write back result before FPE exception

Message ID 20180504054030.24527-2-richard.henderson@linaro.org
State Superseded
Headers show
Series target/openrisc: Convert to decodetree.py | expand

Commit Message

Richard Henderson May 4, 2018, 5:40 a.m. UTC
From: Richard Henderson <rth@twiddle.net>


The architecture manual is unclear about this, but the or1ksim
does writeback before the exception.  This requires splitting
the helpers in half, with the exception raised by the second.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>

Signed-off-by: Richard Henderson <rth@twiddle.net>

---
 target/openrisc/helper.h     |  25 +++--
 target/openrisc/fpu_helper.c | 250 +++++++++----------------------------------
 target/openrisc/translate.c  | 101 ++++++++++-------
 3 files changed, 125 insertions(+), 251 deletions(-)

-- 
2.14.3

Comments

Stafford Horne May 5, 2018, 5:19 a.m. UTC | #1
On Thu, May 03, 2018 at 10:40:18PM -0700, Richard Henderson wrote:
> From: Richard Henderson <rth@twiddle.net>

> 

> The architecture manual is unclear about this, but the or1ksim

> does writeback before the exception.  This requires splitting

> the helpers in half, with the exception raised by the second.


I dont really see a problem with this, ccing bandvig who did a lot of the fpu
hardware implementation in mor1kx.

> Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>

> Signed-off-by: Richard Henderson <rth@twiddle.net>


Acked-by: Stafford Horne <shorne@gmail.com>


> ---

>  target/openrisc/helper.h     |  25 +++--

>  target/openrisc/fpu_helper.c | 250 +++++++++----------------------------------

>  target/openrisc/translate.c  | 101 ++++++++++-------

>  3 files changed, 125 insertions(+), 251 deletions(-)

>
Zhijian Li (Fujitsu)" via May 5, 2018, 11:08 a.m. UTC | #2
I've read architecture manual again and found that my actual implementation 
differs from it.

How it should be (my updated view, thanks to your note).
The "Exception Processing" chapters stays than "EPCR (no delay slot)" should 
be "Address of next not executed instruction". And there is nothing about 
write-back discard.  It looks like it makes sense taking into account that 
IEEE-754 typically requires to return specially prepared value if an FPE 
occurs. As I remember correctly there are two approaches to compute the 
returned value. On of them is much simpler than another. For example, for 
overflow the value should be just +(-)Inf for simple approach but specially 
re-scaled for more complex one.

How it is implemented in CAPPUCCINO and MAROCCHINO pipes.
It look like till now I haven't been attentively enough. That's why my 
actual implementation follows "Synchronous/precise" approach that is 
write-back is discarded and "EPCR (no delay slot)" <= "Address of 
instruction that caused exception".

Currently I'm focused on implementation snoop-invalidation logic in 
MAROCCHINO and could not estimate when I could change FPE behavior. However, 
I'm voting to keep QEMU algorithms in consistent with actual HW- 
implementation. I remember that there is at list one QEMU to HW 
inconsistency that is implementation SPR_SR_DX. So Linux could run normally 
only in "SPR_SR_DX emulation" mode on HW SoCs. If we implement FPE 
processing in according to architecture manual now we increase number of 
QEMU-vs-HW inconsistencies.

PS. As I'm not a participant of QEMU developers mailing list, the letter 
could be rejected. Fill free to forward the answer there.

BR
Andrey Bacherov


-----Исходное сообщение----- 
From: Stafford Horne

Sent: Saturday, May 05, 2018 8:19 AM
To: Richard Henderson
Cc: qemu-devel@nongnu.org ; Richard Henderson ; bandvig@mail.ru
Subject: Re: [PATCH 01/13] target-openrisc: Write back result before FPE 
exception

On Thu, May 03, 2018 at 10:40:18PM -0700, Richard Henderson wrote:
> From: Richard Henderson <rth@twiddle.net>

>

> The architecture manual is unclear about this, but the or1ksim

> does writeback before the exception.  This requires splitting

> the helpers in half, with the exception raised by the second.


I dont really see a problem with this, ccing bandvig who did a lot of the 
fpu
hardware implementation in mor1kx.

> Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>

> Signed-off-by: Richard Henderson <rth@twiddle.net>


Acked-by: Stafford Horne <shorne@gmail.com>


> ---

>  target/openrisc/helper.h     |  25 +++--

>  target/openrisc/fpu_helper.c | 250 

> +++++++++----------------------------------

>  target/openrisc/translate.c  | 101 ++++++++++-------

>  3 files changed, 125 insertions(+), 251 deletions(-)

>
diff mbox series

Patch

diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h
index 4fd1a6bb8e..e37dabc77a 100644
--- a/target/openrisc/helper.h
+++ b/target/openrisc/helper.h
@@ -24,17 +24,19 @@  DEF_HELPER_FLAGS_1(ove_ov, TCG_CALL_NO_WG, void, env)
 DEF_HELPER_FLAGS_1(ove_cyov, TCG_CALL_NO_WG, void, env)
 
 /* float */
-DEF_HELPER_FLAGS_2(itofd, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_WG, i32, env, i32)
-DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_WG, i32, env, i32)
+DEF_HELPER_FLAGS_1(update_fpcsr, TCG_CALL_NO_WG, void, env)
 
-DEF_HELPER_FLAGS_4(float_madd_s, TCG_CALL_NO_WG, i32, env, i32, i32, i32)
-DEF_HELPER_FLAGS_4(float_madd_d, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
+DEF_HELPER_FLAGS_2(itofd, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_RWG, i32, env, i32)
+DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_RWG, i32, env, i32)
+
+DEF_HELPER_FLAGS_4(float_madd_s, TCG_CALL_NO_RWG, i32, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(float_madd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
 
 #define FOP_CALC(op)                                            \
-DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \
-DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_RWG, i32, env, i32, i32) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_RWG, i64, env, i64, i64)
 FOP_CALC(add)
 FOP_CALC(sub)
 FOP_CALC(mul)
@@ -43,14 +45,11 @@  FOP_CALC(rem)
 #undef FOP_CALC
 
 #define FOP_CMP(op)                                              \
-DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \
-DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_RWG, tl, env, i32, i32) \
+DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_RWG, tl, env, i64, i64)
 FOP_CMP(eq)
 FOP_CMP(lt)
 FOP_CMP(le)
-FOP_CMP(ne)
-FOP_CMP(gt)
-FOP_CMP(ge)
 #undef FOP_CMP
 
 /* interrupt */
diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c
index 977a1e8e55..265ce13337 100644
--- a/target/openrisc/fpu_helper.c
+++ b/target/openrisc/fpu_helper.c
@@ -24,121 +24,70 @@ 
 #include "exception.h"
 #include "fpu/softfloat.h"
 
-static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp)
+static int ieee_ex_to_openrisc(int fexcp)
 {
     int ret = 0;
-    if (fexcp) {
-        if (fexcp & float_flag_invalid) {
-            cpu->env.fpcsr |= FPCSR_IVF;
-            ret = 1;
-        }
-        if (fexcp & float_flag_overflow) {
-            cpu->env.fpcsr |= FPCSR_OVF;
-            ret = 1;
-        }
-        if (fexcp & float_flag_underflow) {
-            cpu->env.fpcsr |= FPCSR_UNF;
-            ret = 1;
-        }
-        if (fexcp & float_flag_divbyzero) {
-            cpu->env.fpcsr |= FPCSR_DZF;
-            ret = 1;
-        }
-        if (fexcp & float_flag_inexact) {
-            cpu->env.fpcsr |= FPCSR_IXF;
-            ret = 1;
-        }
+    if (fexcp & float_flag_invalid) {
+        ret |= FPCSR_IVF;
+    }
+    if (fexcp & float_flag_overflow) {
+        ret |= FPCSR_OVF;
+    }
+    if (fexcp & float_flag_underflow) {
+        ret |= FPCSR_UNF;
+    }
+    if (fexcp & float_flag_divbyzero) {
+        ret |= FPCSR_DZF;
+    }
+    if (fexcp & float_flag_inexact) {
+        ret |= FPCSR_IXF;
     }
-
     return ret;
 }
 
-static inline void update_fpcsr(OpenRISCCPU *cpu)
+void HELPER(update_fpcsr)(CPUOpenRISCState *env)
 {
-    int tmp = ieee_ex_to_openrisc(cpu,
-                              get_float_exception_flags(&cpu->env.fp_status));
+    int tmp = get_float_exception_flags(&env->fp_status);
 
-    SET_FP_CAUSE(cpu->env.fpcsr, tmp);
-    if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) &&
-        (cpu->env.fpcsr & FPCSR_FPEE)) {
-        helper_exception(&cpu->env, EXCP_FPE);
-    } else {
-        UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp);
+    if (tmp) {
+        set_float_exception_flags(0, &env->fp_status);
+        tmp = ieee_ex_to_openrisc(tmp);
+        if (tmp) {
+            env->fpcsr |= tmp;
+            if (env->fpcsr & FPCSR_FPEE) {
+                helper_exception(env, EXCP_FPE);
+            }
+        }
     }
 }
 
 uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
 {
-    uint64_t itofd;
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-
-    set_float_exception_flags(0, &cpu->env.fp_status);
-    itofd = int32_to_float64(val, &cpu->env.fp_status);
-    update_fpcsr(cpu);
-
-    return itofd;
+    return int32_to_float64(val, &env->fp_status);
 }
 
 uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
 {
-    uint32_t itofs;
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-
-    set_float_exception_flags(0, &cpu->env.fp_status);
-    itofs = int32_to_float32(val, &cpu->env.fp_status);
-    update_fpcsr(cpu);
-
-    return itofs;
+    return int32_to_float32(val, &env->fp_status);
 }
 
 uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
 {
-    uint64_t ftoid;
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-
-    set_float_exception_flags(0, &cpu->env.fp_status);
-    ftoid = float32_to_int64(val, &cpu->env.fp_status);
-    update_fpcsr(cpu);
-
-    return ftoid;
+    return float32_to_int64(val, &env->fp_status);
 }
 
 uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
 {
-    uint32_t ftois;
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-
-    set_float_exception_flags(0, &cpu->env.fp_status);
-    ftois = float32_to_int32(val, &cpu->env.fp_status);
-    update_fpcsr(cpu);
-
-    return ftois;
+    return float32_to_int32(val, &env->fp_status);
 }
 
-#define FLOAT_OP(name, p) void helper_float_##_##p(void)
-
 #define FLOAT_CALC(name)                                                  \
 uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
                                      uint64_t fdt0, uint64_t fdt1)        \
-{                                                                         \
-    uint64_t result;                                                      \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status);           \
-    update_fpcsr(cpu);                                                    \
-    return result;                                                        \
-}                                                                         \
-                                                                          \
+{ return float64_ ## name(fdt0, fdt1, &env->fp_status); }                 \
 uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
                                      uint32_t fdt0, uint32_t fdt1)        \
-{                                                                         \
-    uint32_t result;                                                      \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status);           \
-    update_fpcsr(cpu);                                                    \
-    return result;                                                        \
-}                                                                         \
+{ return float32_ ## name(fdt0, fdt1, &env->fp_status); }
 
 FLOAT_CALC(add)
 FLOAT_CALC(sub)
@@ -151,132 +100,29 @@  FLOAT_CALC(rem)
 uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a,
                              uint64_t b, uint64_t c)
 {
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-    uint64_t result;
-    set_float_exception_flags(0, &cpu->env.fp_status);
-    /* Note that or1ksim doesn't use merged operation.  */
-    result = float64_mul(b, c, &cpu->env.fp_status);
-    result = float64_add(result, a, &cpu->env.fp_status);
-    update_fpcsr(cpu);
-    return result;
+    /* Note that or1ksim doesn't use fused operation.  */
+    b = float64_mul(b, c, &env->fp_status);
+    return float64_add(a, b, &env->fp_status);
 }
 
 uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a,
                              uint32_t b, uint32_t c)
 {
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-    uint32_t result;
-    set_float_exception_flags(0, &cpu->env.fp_status);
-    /* Note that or1ksim doesn't use merged operation.  */
-    result = float32_mul(b, c, &cpu->env.fp_status);
-    result = float32_add(result, a, &cpu->env.fp_status);
-    update_fpcsr(cpu);
-    return result;
+    /* Note that or1ksim doesn't use fused operation.  */
+    b = float32_mul(b, c, &env->fp_status);
+    return float32_add(a, b, &env->fp_status);
 }
 
 
-#define FLOAT_CMP(name)                                                   \
-uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
-                                     uint64_t fdt0, uint64_t fdt1)        \
-{                                                                         \
-    int res;                                                              \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status);              \
-    update_fpcsr(cpu);                                                    \
-    return res;                                                           \
-}                                                                         \
-                                                                          \
-uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
-                                             uint32_t fdt0, uint32_t fdt1)\
-{                                                                         \
-    int res;                                                              \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status);              \
-    update_fpcsr(cpu);                                                    \
-    return res;                                                           \
-}
+#define FLOAT_CMP(name, impl)                                             \
+target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env,           \
+                                         uint64_t fdt0, uint64_t fdt1)    \
+{ return float64_ ## impl(fdt0, fdt1, &env->fp_status); }                 \
+target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env,           \
+                                         uint32_t fdt0, uint32_t fdt1)    \
+{ return float32_ ## impl(fdt0, fdt1, &env->fp_status); }
 
-FLOAT_CMP(le)
-FLOAT_CMP(eq)
-FLOAT_CMP(lt)
+FLOAT_CMP(le, le)
+FLOAT_CMP(lt, lt)
+FLOAT_CMP(eq, eq_quiet)
 #undef FLOAT_CMP
-
-
-#define FLOAT_CMPNE(name)                                                 \
-uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
-                                     uint64_t fdt0, uint64_t fdt1)        \
-{                                                                         \
-    int res;                                                              \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status);             \
-    update_fpcsr(cpu);                                                    \
-    return res;                                                           \
-}                                                                         \
-                                                                          \
-uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
-                                     uint32_t fdt0, uint32_t fdt1)        \
-{                                                                         \
-    int res;                                                              \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status);             \
-    update_fpcsr(cpu);                                                    \
-    return res;                                                           \
-}
-
-FLOAT_CMPNE(ne)
-#undef FLOAT_CMPNE
-
-#define FLOAT_CMPGT(name)                                                 \
-uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
-                                     uint64_t fdt0, uint64_t fdt1)        \
-{                                                                         \
-    int res;                                                              \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    res = !float64_le(fdt0, fdt1, &cpu->env.fp_status);                   \
-    update_fpcsr(cpu);                                                    \
-    return res;                                                           \
-}                                                                         \
-                                                                          \
-uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
-                                     uint32_t fdt0, uint32_t fdt1)        \
-{                                                                         \
-    int res;                                                              \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    res = !float32_le(fdt0, fdt1, &cpu->env.fp_status);                   \
-    update_fpcsr(cpu);                                                    \
-    return res;                                                           \
-}
-FLOAT_CMPGT(gt)
-#undef FLOAT_CMPGT
-
-#define FLOAT_CMPGE(name)                                                 \
-uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env,               \
-                                     uint64_t fdt0, uint64_t fdt1)        \
-{                                                                         \
-    int res;                                                              \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status);                   \
-    update_fpcsr(cpu);                                                    \
-    return res;                                                           \
-}                                                                         \
-                                                                          \
-uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env,               \
-                                     uint32_t fdt0, uint32_t fdt1)        \
-{                                                                         \
-    int res;                                                              \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status);                   \
-    update_fpcsr(cpu);                                                    \
-    return res;                                                           \
-}
-
-FLOAT_CMPGE(ge)
-#undef FLOAT_CMPGE
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index 2747b24cf0..6876317971 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1294,180 +1294,209 @@  static void dec_float(DisasContext *dc, uint32_t insn)
     rd = extract32(insn, 21, 5);
 
     switch (op0) {
-    case 0x00:    /* lf.add.s */
+    case 0x00: /* lf.add.s */
         LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
         check_r0_write(rd);
         gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x01:    /* lf.sub.s */
+    case 0x01: /* lf.sub.s */
         LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
         check_r0_write(rd);
         gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
     case 0x02:    /* lf.mul.s */
         LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
         check_r0_write(rd);
         gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x03:    /* lf.div.s */
+    case 0x03: /* lf.div.s */
         LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
         check_r0_write(rd);
         gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x04:    /* lf.itof.s */
+    case 0x04: /* lf.itof.s */
         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
         check_r0_write(rd);
         gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x05:    /* lf.ftoi.s */
+    case 0x05: /* lf.ftoi.s */
         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
         check_r0_write(rd);
         gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x06:    /* lf.rem.s */
+    case 0x06: /* lf.rem.s */
         LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
         check_r0_write(rd);
         gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x07:    /* lf.madd.s */
+    case 0x07: /* lf.madd.s */
         LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
         check_r0_write(rd);
         gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd],
                                 cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x08:    /* lf.sfeq.s */
+    case 0x08: /* lf.sfeq.s */
         LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
         gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x09:    /* lf.sfne.s */
+    case 0x09: /* lf.sfne.s */
         LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
-        gen_helper_float_ne_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x0a:    /* lf.sfgt.s */
+    case 0x0a: /* lf.sfgt.s */
         LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
-        gen_helper_float_gt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x0b:    /* lf.sfge.s */
+    case 0x0b: /* lf.sfge.s */
         LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
-        gen_helper_float_ge_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x0c:    /* lf.sflt.s */
+    case 0x0c: /* lf.sflt.s */
         LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
         gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x0d:    /* lf.sfle.s */
+    case 0x0d: /* lf.sfle.s */
         LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
         gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-/* not used yet, open it when we need or64.  */
-/*#ifdef TARGET_OPENRISC64
-    case 0x10:     lf.add.d
+#ifdef TARGET_OPENRISC64
+    case 0x10: /* lf.add.d */
         LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
         check_of64s(dc);
         check_r0_write(rd);
         gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x11:     lf.sub.d
+    case 0x11: /* lf.sub.d */
         LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
         check_of64s(dc);
         check_r0_write(rd);
         gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x12:     lf.mul.d
+    case 0x12: /* lf.mul.d */
         LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
         check_of64s(dc);
         check_r0_write(rd);
         gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x13:     lf.div.d
+    case 0x13: /* lf.div.d */
         LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
         check_of64s(dc);
         check_r0_write(rd);
         gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x14:     lf.itof.d
+    case 0x14: /* lf.itof.d */
         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
         check_of64s(dc);
         check_r0_write(rd);
         gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x15:     lf.ftoi.d
+    case 0x15: /* lf.ftoi.d */
         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
         check_of64s(dc);
         check_r0_write(rd);
         gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x16:     lf.rem.d
+    case 0x16: /* lf.rem.d */
         LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
         check_of64s(dc);
         check_r0_write(rd);
         gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x17:     lf.madd.d
+    case 0x17: /* lf.madd.d */
         LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
         check_of64s(dc);
         check_r0_write(rd);
         gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd],
                                 cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x18:     lf.sfeq.d
+    case 0x18: /* lf.sfeq.d */
         LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
         check_of64s(dc);
         gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x1a:     lf.sfgt.d
+    case 0x1a: /* lf.sfgt.d */
         LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
         check_of64s(dc);
-        gen_helper_float_gt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x1b:     lf.sfge.d
+    case 0x1b: /* lf.sfge.d */
         LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
         check_of64s(dc);
-        gen_helper_float_ge_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x19:     lf.sfne.d
+    case 0x19: /* lf.sfne.d */
         LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
         check_of64s(dc);
-        gen_helper_float_ne_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x1c:     lf.sflt.d
+    case 0x1c: /* lf.sflt.d */
         LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
         check_of64s(dc);
         gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
 
-    case 0x1d:     lf.sfle.d
+    case 0x1d: /* lf.sfle.d */
         LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
         check_of64s(dc);
         gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_update_fpcsr(cpu_env);
         break;
-#endif*/
+#endif
 
     default:
         gen_illegal_exception(dc);