All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/25] target-openrisc improvements
@ 2016-06-13 23:58 Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 01/25] target-openrisc: Always enable OPENRISC_DISAS Richard Henderson
                   ` (24 more replies)
  0 siblings, 25 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

This is an update of a patch set last posted in September,
and partially reviewed by Bastian at the time.


r~


Richard Henderson (25):
  target-openrisc: Always enable OPENRISC_DISAS
  target-openrisc: Streamline arithmetic and OVE
  target-openrisc: Invert the decoding in dec_calc
  target-openrisc: Keep SR_F in a separate variable
  target-openrisc: Use movcond where appropriate
  target-openrisc: Put SR[OVE] in TB flags
  target-openrisc: Keep SR_CY and SR_OV in a separate variables
  target-openrisc: Set flags on helpers
  target-openrisc: Implement ff1 and fl1 for 64-bit
  target-openrisc: Represent MACHI:MACLO as a single unit
  target-openrisc: Rationalize immediate extraction
  target-openrisc: Enable m[tf]spr from user mode
  target-openrisc: Enable trap, csync, msync, psync for user mode
  target-openrisc: Implement muld, muldu, macu, msbu
  target-openrisc: Fix madd
  target-openrisc: Write back result before FPE exception
  target-openrisc: Implement lwa, swa
  target-openrisc: Implement l.adrp
  target-openrisc: Tidy ppc/npc implementation
  target-openrisc: Optimize l.jal to next
  target-openrisc: Tidy insn dumping
  target-openrisc: Tidy handling of delayed branches
  target-openrisc: Optimize for r0 being zero
  target-openrisc: Generate goto_tb for direct branches
  target-openrisc: Generate goto_tb for conditional branches

 linux-user/main.c                  |   45 +
 target-openrisc/cpu.c              |    1 +
 target-openrisc/cpu.h              |   54 +-
 target-openrisc/exception_helper.c |   32 +
 target-openrisc/fpu_helper.c       |  286 ++----
 target-openrisc/gdbstub.c          |   17 +-
 target-openrisc/helper.h           |   42 +-
 target-openrisc/int_helper.c       |   57 +-
 target-openrisc/interrupt.c        |    7 +-
 target-openrisc/interrupt_helper.c |    4 +-
 target-openrisc/machine.c          |    5 +-
 target-openrisc/mmu.c              |    1 +
 target-openrisc/sys_helper.c       |   90 +-
 target-openrisc/translate.c        | 1778 +++++++++++++++++-------------------
 14 files changed, 1108 insertions(+), 1311 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 01/25] target-openrisc: Always enable OPENRISC_DISAS
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 02/25] target-openrisc: Streamline arithmetic and OVE Richard Henderson
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Avoids warnings from unused variables etc.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index c08876b..97e8665 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -34,14 +34,9 @@
 #include "trace-tcg.h"
 #include "exec/log.h"
 
-
-#define OPENRISC_DISAS
-
-#ifdef OPENRISC_DISAS
-#  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
-#else
-#  define LOG_DIS(...) do { } while (0)
-#endif
+/* Set to 0 to completely disable.  */
+#define OPENRISC_DISAS  CPU_LOG_TB_IN_ASM
+#define LOG_DIS(...) qemu_log_mask(OPENRISC_DISAS, ## __VA_ARGS__)
 
 typedef struct DisasContext {
     TranslationBlock *tb;
@@ -715,9 +710,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0, op1;
     uint32_t ra, rb, rd;
-#ifdef OPENRISC_DISAS
     uint32_t L6, K5;
-#endif
     uint32_t I16, I5, I11, N26, tmp;
     TCGMemOp mop;
 
@@ -726,10 +719,8 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
     ra = extract32(insn, 16, 5);
     rb = extract32(insn, 11, 5);
     rd = extract32(insn, 21, 5);
-#ifdef OPENRISC_DISAS
     L6 = extract32(insn, 5, 6);
     K5 = extract32(insn, 0, 5);
-#endif
     I16 = extract32(insn, 0, 16);
     I5 = extract32(insn, 21, 5);
     I11 = extract32(insn, 0, 11);
@@ -1326,13 +1317,10 @@ static void dec_compi(DisasContext *dc, uint32_t insn)
 static void dec_sys(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
-#ifdef OPENRISC_DISAS
     uint32_t K16;
-#endif
+
     op0 = extract32(insn, 16, 10);
-#ifdef OPENRISC_DISAS
     K16 = extract32(insn, 0, 16);
-#endif
 
     switch (op0) {
     case 0x000:    /* l.sys */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 02/25] target-openrisc: Streamline arithmetic and OVE
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 01/25] target-openrisc: Always enable OPENRISC_DISAS Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 03/25] target-openrisc: Invert the decoding in dec_calc Richard Henderson
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Simplify overflow calculation.  Move overflow exception check
to a helper function, to eliminate inline branches.  Remove
some incorrect special casing of R0.  Implement multiply inline.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/exception_helper.c |  12 ++
 target-openrisc/helper.h           |   2 +-
 target-openrisc/int_helper.c       |  36 ----
 target-openrisc/translate.c        | 426 +++++++++++++++----------------------
 4 files changed, 190 insertions(+), 286 deletions(-)

diff --git a/target-openrisc/exception_helper.c b/target-openrisc/exception_helper.c
index 329a9e4..561384a 100644
--- a/target-openrisc/exception_helper.c
+++ b/target-openrisc/exception_helper.c
@@ -28,3 +28,15 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
 
     raise_exception(cpu, excp);
 }
+
+void HELPER(ove)(CPUOpenRISCState *env, target_ulong test)
+{
+    if (unlikely(test) && (env->sr & SR_OVE)) {
+        OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+        CPUState *cs = CPU(cpu);
+
+        cs->exception_index = EXCP_RANGE;
+        cpu_restore_state(cs, GETPC());
+        cpu_loop_exit(cs);
+    }
+}
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index f53fa21..1af2fab 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -19,6 +19,7 @@
 
 /* exception */
 DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+DEF_HELPER_FLAGS_2(ove, TCG_CALL_NO_WG, void, env, tl)
 
 /* float */
 DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64)
@@ -56,7 +57,6 @@ FOP_CMP(ge)
 /* int */
 DEF_HELPER_FLAGS_1(ff1, 0, tl, tl)
 DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
-DEF_HELPER_FLAGS_3(mul32, 0, i32, env, i32, i32)
 
 /* interrupt */
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
diff --git a/target-openrisc/int_helper.c b/target-openrisc/int_helper.c
index 4d1f958..6482f8c 100644
--- a/target-openrisc/int_helper.c
+++ b/target-openrisc/int_helper.c
@@ -42,39 +42,3 @@ target_ulong HELPER(fl1)(target_ulong x)
     return 32 - clz32(x);
 /*#endif*/
 }
-
-uint32_t HELPER(mul32)(CPUOpenRISCState *env,
-                       uint32_t ra, uint32_t rb)
-{
-    uint64_t result;
-    uint32_t high, cy;
-
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-
-    result = (uint64_t)ra * rb;
-    /* regisiers in or32 is 32bit, so 32 is NOT a magic number.
-       or64 is not handled in this function, and not implement yet,
-       TARGET_LONG_BITS for or64 is 64, it will break this function,
-       so, we didn't use TARGET_LONG_BITS here.  */
-    high = result >> 32;
-    cy = result >> (32 - 1);
-
-    if ((cy & 0x1) == 0x0) {
-        if (high == 0x0) {
-            return result;
-        }
-    }
-
-    if ((cy & 0x1) == 0x1) {
-        if (high == 0xffffffff) {
-            return result;
-        }
-    }
-
-    cpu->env.sr |= (SR_OV | SR_CY);
-    if (cpu->env.sr & SR_OVE) {
-        raise_exception(cpu, EXCP_RANGE);
-    }
-
-    return result;
-}
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 97e8665..e895c98 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -258,6 +258,166 @@ static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
     gen_sync_flags(dc);
 }
 
+static void gen_ove_cy(DisasContext *dc, TCGv cy)
+{
+    gen_helper_ove(cpu_env, cy);
+}
+
+static void gen_ove_ov(DisasContext *dc, TCGv ov)
+{
+    gen_helper_ove(cpu_env, ov);
+}
+
+static void gen_ove_cyov(DisasContext *dc, TCGv cy, TCGv ov)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_or_tl(t0, cy, ov);
+    gen_helper_ove(cpu_env, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
+{
+    TCGv t0 = tcg_const_tl(0);
+    TCGv res = tcg_temp_new();
+    TCGv sr_cy = tcg_temp_new();
+    TCGv sr_ov = tcg_temp_new();
+
+    tcg_gen_add2_tl(res, sr_cy, srca, t0, srcb, t0);
+    tcg_gen_xor_tl(sr_ov, srca, srcb);
+    tcg_gen_xor_tl(t0, res, srcb);
+    tcg_gen_andc_tl(sr_ov, t0, sr_ov);
+    tcg_temp_free(t0);
+
+    tcg_gen_mov_tl(dest, res);
+    tcg_temp_free(res);
+
+    tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1);
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
+
+    gen_ove_cyov(dc, sr_ov, sr_cy);
+    tcg_temp_free(sr_ov);
+    tcg_temp_free(sr_cy);
+}
+
+static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
+{
+    TCGv t0 = tcg_const_tl(0);
+    TCGv res = tcg_temp_new();
+    TCGv sr_cy = tcg_temp_new();
+    TCGv sr_ov = tcg_temp_new();
+
+    tcg_gen_shri_tl(sr_cy, cpu_sr, ctz32(SR_CY));
+    tcg_gen_andi_tl(sr_cy, sr_cy, 1);
+
+    tcg_gen_add2_tl(res, sr_cy, srca, t0, sr_cy, t0);
+    tcg_gen_add2_tl(res, sr_cy, res, sr_cy, srcb, t0);
+    tcg_gen_xor_tl(sr_ov, srca, srcb);
+    tcg_gen_xor_tl(t0, res, srcb);
+    tcg_gen_andc_tl(sr_ov, t0, sr_ov);
+    tcg_temp_free(t0);
+
+    tcg_gen_mov_tl(dest, res);
+    tcg_temp_free(res);
+
+    tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1);
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
+
+    gen_ove_cyov(dc, sr_ov, sr_cy);
+    tcg_temp_free(sr_ov);
+    tcg_temp_free(sr_cy);
+}
+
+static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
+{
+    TCGv res = tcg_temp_new();
+    TCGv sr_cy = tcg_temp_new();
+    TCGv sr_ov = tcg_temp_new();
+
+    tcg_gen_sub_tl(res, srca, srcb);
+    tcg_gen_xor_tl(sr_cy, srca, srcb);
+    tcg_gen_xor_tl(sr_ov, res, srcb);
+    tcg_gen_and_tl(sr_ov, sr_ov, sr_cy);
+    tcg_gen_setcond_tl(TCG_COND_LTU, sr_cy, srca, srcb);
+
+    tcg_gen_mov_tl(dest, res);
+    tcg_temp_free(res);
+
+    tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1);
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
+
+    gen_ove_cyov(dc, sr_ov, sr_cy);
+    tcg_temp_free(sr_ov);
+    tcg_temp_free(sr_cy);
+}
+
+static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
+{
+    TCGv sr_ov = tcg_temp_new();
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_muls2_tl(dest, sr_ov, srca, srcb);
+    tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
+    tcg_gen_setcond_tl(TCG_COND_NE, sr_ov, sr_ov, t0);
+    tcg_temp_free(t0);
+
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
+
+    gen_ove_ov(dc, sr_ov);
+    tcg_temp_free(sr_ov);
+}
+
+static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
+{
+    TCGv sr_cy = tcg_temp_new();
+
+    tcg_gen_muls2_tl(dest, sr_cy, srca, srcb);
+    tcg_gen_setcondi_tl(TCG_COND_NE, sr_cy, sr_cy, 0);
+
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
+
+    gen_ove_cy(dc, sr_cy);
+    tcg_temp_free(sr_cy);
+}
+
+static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
+{
+    TCGv sr_ov = tcg_temp_new();
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_setcondi_tl(TCG_COND_EQ, sr_ov, srcb, 0);
+    /* The result of divide-by-zero is undefined.
+       Supress the host-side exception by dividing by 1.  */
+    tcg_gen_or_tl(t0, srcb, sr_ov);
+    tcg_gen_div_tl(dest, srca, t0);
+    tcg_temp_free(t0);
+
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
+
+    gen_ove_ov(dc, sr_ov);
+    tcg_temp_free(sr_ov);
+}
+
+static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
+{
+    TCGv sr_cy = tcg_temp_new();
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_setcondi_tl(TCG_COND_EQ, sr_cy, srcb, 0);
+    /* The result of divide-by-zero is undefined.
+       Supress the host-side exception by dividing by 1.  */
+    tcg_gen_or_tl(t0, srcb, sr_cy);
+    tcg_gen_divu_tl(dest, srca, t0);
+    tcg_temp_free(t0);
+
+    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
+
+    gen_ove_cy(dc, sr_cy);
+    tcg_temp_free(sr_cy);
+}
 
 static void dec_calc(DisasContext *dc, uint32_t insn)
 {
@@ -275,34 +435,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         switch (op1) {
         case 0x00:    /* l.add */
             LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
-            {
-                TCGLabel *lab = gen_new_label();
-                TCGv_i64 ta = tcg_temp_new_i64();
-                TCGv_i64 tb = tcg_temp_new_i64();
-                TCGv_i64 td = tcg_temp_local_new_i64();
-                TCGv_i32 res = tcg_temp_local_new_i32();
-                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-                tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
-                tcg_gen_extu_i32_i64(tb, cpu_R[rb]);
-                tcg_gen_add_i64(td, ta, tb);
-                tcg_gen_extrl_i64_i32(res, td);
-                tcg_gen_shri_i64(td, td, 31);
-                tcg_gen_andi_i64(td, td, 0x3);
-                /* Jump to lab when no overflow.  */
-                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
-                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
-                tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
-                tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
-                gen_exception(dc, EXCP_RANGE);
-                gen_set_label(lab);
-                tcg_gen_mov_i32(cpu_R[rd], res);
-                tcg_temp_free_i64(ta);
-                tcg_temp_free_i64(tb);
-                tcg_temp_free_i64(td);
-                tcg_temp_free_i32(res);
-                tcg_temp_free_i32(sr_ove);
-            }
+            gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             break;
         default:
             gen_illegal_exception(dc);
@@ -314,42 +447,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         switch (op1) {
         case 0x00:
             LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
-            {
-                TCGLabel *lab = gen_new_label();
-                TCGv_i64 ta = tcg_temp_new_i64();
-                TCGv_i64 tb = tcg_temp_new_i64();
-                TCGv_i64 tcy = tcg_temp_local_new_i64();
-                TCGv_i64 td = tcg_temp_local_new_i64();
-                TCGv_i32 res = tcg_temp_local_new_i32();
-                TCGv_i32 sr_cy = tcg_temp_local_new_i32();
-                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-                tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
-                tcg_gen_extu_i32_i64(tb, cpu_R[rb]);
-                tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY);
-                tcg_gen_extu_i32_i64(tcy, sr_cy);
-                tcg_gen_shri_i64(tcy, tcy, 10);
-                tcg_gen_add_i64(td, ta, tb);
-                tcg_gen_add_i64(td, td, tcy);
-                tcg_gen_extrl_i64_i32(res, td);
-                tcg_gen_shri_i64(td, td, 32);
-                tcg_gen_andi_i64(td, td, 0x3);
-                /* Jump to lab when no overflow.  */
-                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
-                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
-                tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
-                tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
-                gen_exception(dc, EXCP_RANGE);
-                gen_set_label(lab);
-                tcg_gen_mov_i32(cpu_R[rd], res);
-                tcg_temp_free_i64(ta);
-                tcg_temp_free_i64(tb);
-                tcg_temp_free_i64(tcy);
-                tcg_temp_free_i64(td);
-                tcg_temp_free_i32(res);
-                tcg_temp_free_i32(sr_cy);
-                tcg_temp_free_i32(sr_ove);
-            }
+            gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             break;
         default:
             gen_illegal_exception(dc);
@@ -361,35 +459,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         switch (op1) {
         case 0x00:
             LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
-            {
-                TCGLabel *lab = gen_new_label();
-                TCGv_i64 ta = tcg_temp_new_i64();
-                TCGv_i64 tb = tcg_temp_new_i64();
-                TCGv_i64 td = tcg_temp_local_new_i64();
-                TCGv_i32 res = tcg_temp_local_new_i32();
-                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-
-                tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
-                tcg_gen_extu_i32_i64(tb, cpu_R[rb]);
-                tcg_gen_sub_i64(td, ta, tb);
-                tcg_gen_extrl_i64_i32(res, td);
-                tcg_gen_shri_i64(td, td, 31);
-                tcg_gen_andi_i64(td, td, 0x3);
-                /* Jump to lab when no overflow.  */
-                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
-                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
-                tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
-                tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
-                gen_exception(dc, EXCP_RANGE);
-                gen_set_label(lab);
-                tcg_gen_mov_i32(cpu_R[rd], res);
-                tcg_temp_free_i64(ta);
-                tcg_temp_free_i64(tb);
-                tcg_temp_free_i64(td);
-                tcg_temp_free_i32(res);
-                tcg_temp_free_i32(sr_ove);
-            }
+            gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             break;
         default:
             gen_illegal_exception(dc);
@@ -437,11 +507,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         switch (op1) {
         case 0x03:    /* l.mul */
             LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
-            if (ra != 0 && rb != 0) {
-                gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
-            } else {
-                tcg_gen_movi_tl(cpu_R[rd], 0x0);
-            }
+            gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             break;
         default:
             gen_illegal_exception(dc);
@@ -453,36 +519,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         switch (op1) {
         case 0x03:    /* l.div */
             LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
-            {
-                TCGLabel *lab0 = gen_new_label();
-                TCGLabel *lab1 = gen_new_label();
-                TCGLabel *lab2 = gen_new_label();
-                TCGLabel *lab3 = gen_new_label();
-                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-                if (rb == 0) {
-                    tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                    tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
-                    tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0);
-                    gen_exception(dc, EXCP_RANGE);
-                    gen_set_label(lab0);
-                } else {
-                    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[rb],
-                                       0x00000000, lab1);
-                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[ra],
-                                       0x80000000, lab2);
-                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb],
-                                       0xffffffff, lab2);
-                    gen_set_label(lab1);
-                    tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                    tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
-                    tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab3);
-                    gen_exception(dc, EXCP_RANGE);
-                    gen_set_label(lab2);
-                    tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                    gen_set_label(lab3);
-                }
-                tcg_temp_free_i32(sr_ove);
-            }
+            gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             break;
 
         default:
@@ -495,30 +532,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         switch (op1) {
         case 0x03:    /* l.divu */
             LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
-            {
-                TCGLabel *lab0 = gen_new_label();
-                TCGLabel *lab1 = gen_new_label();
-                TCGLabel *lab2 = gen_new_label();
-                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-                if (rb == 0) {
-                    tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                    tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
-                    tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0);
-                    gen_exception(dc, EXCP_RANGE);
-                    gen_set_label(lab0);
-                } else {
-                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb],
-                                       0x00000000, lab1);
-                    tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                    tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
-                    tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2);
-                    gen_exception(dc, EXCP_RANGE);
-                    gen_set_label(lab1);
-                    tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                    gen_set_label(lab2);
-                }
-                tcg_temp_free_i32(sr_ove);
-            }
+            gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             break;
 
         default:
@@ -531,34 +545,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         switch (op1) {
         case 0x03:    /* l.mulu */
             LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
-            if (rb != 0 && ra != 0) {
-                TCGv_i64 result = tcg_temp_local_new_i64();
-                TCGv_i64 tra = tcg_temp_local_new_i64();
-                TCGv_i64 trb = tcg_temp_local_new_i64();
-                TCGv_i64 high = tcg_temp_new_i64();
-                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-                TCGLabel *lab = gen_new_label();
-                /* Calculate each result. */
-                tcg_gen_extu_i32_i64(tra, cpu_R[ra]);
-                tcg_gen_extu_i32_i64(trb, cpu_R[rb]);
-                tcg_gen_mul_i64(result, tra, trb);
-                tcg_temp_free_i64(tra);
-                tcg_temp_free_i64(trb);
-                tcg_gen_shri_i64(high, result, TARGET_LONG_BITS);
-                /* Overflow or not. */
-                tcg_gen_brcondi_i64(TCG_COND_EQ, high, 0x00000000, lab);
-                tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE);
-                tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab);
-                gen_exception(dc, EXCP_RANGE);
-                gen_set_label(lab);
-                tcg_temp_free_i64(high);
-                tcg_gen_trunc_i64_tl(cpu_R[rd], result);
-                tcg_temp_free_i64(result);
-                tcg_temp_free_i32(sr_ove);
-            } else {
-                tcg_gen_movi_tl(cpu_R[rd], 0);
-            }
+            gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             break;
 
         default:
@@ -713,6 +700,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
     uint32_t L6, K5;
     uint32_t I16, I5, I11, N26, tmp;
     TCGMemOp mop;
+    TCGv t0;
 
     op0 = extract32(insn, 26, 6);
     op1 = extract32(insn, 24, 2);
@@ -889,72 +877,16 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x27:    /* l.addi */
         LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
-        {
-            if (I16 == 0) {
-                tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
-            } else {
-                TCGLabel *lab = gen_new_label();
-                TCGv_i64 ta = tcg_temp_new_i64();
-                TCGv_i64 td = tcg_temp_local_new_i64();
-                TCGv_i32 res = tcg_temp_local_new_i32();
-                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-                tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
-                tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
-                tcg_gen_extrl_i64_i32(res, td);
-                tcg_gen_shri_i64(td, td, 32);
-                tcg_gen_andi_i64(td, td, 0x3);
-                /* Jump to lab when no overflow.  */
-                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
-                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
-                tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-                tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
-                tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
-                gen_exception(dc, EXCP_RANGE);
-                gen_set_label(lab);
-                tcg_gen_mov_i32(cpu_R[rd], res);
-                tcg_temp_free_i64(ta);
-                tcg_temp_free_i64(td);
-                tcg_temp_free_i32(res);
-                tcg_temp_free_i32(sr_ove);
-            }
-        }
+        t0 = tcg_const_tl(I16);
+        gen_add(dc, cpu_R[rd], cpu_R[ra], t0);
+        tcg_temp_free(t0);
         break;
 
     case 0x28:    /* l.addic */
         LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
-        {
-            TCGLabel *lab = gen_new_label();
-            TCGv_i64 ta = tcg_temp_new_i64();
-            TCGv_i64 td = tcg_temp_local_new_i64();
-            TCGv_i64 tcy = tcg_temp_local_new_i64();
-            TCGv_i32 res = tcg_temp_local_new_i32();
-            TCGv_i32 sr_cy = tcg_temp_local_new_i32();
-            TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-            tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
-            tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY);
-            tcg_gen_shri_i32(sr_cy, sr_cy, 10);
-            tcg_gen_extu_i32_i64(tcy, sr_cy);
-            tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
-            tcg_gen_add_i64(td, td, tcy);
-            tcg_gen_extrl_i64_i32(res, td);
-            tcg_gen_shri_i64(td, td, 32);
-            tcg_gen_andi_i64(td, td, 0x3);
-            /* Jump to lab when no overflow.  */
-            tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
-            tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
-            tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-            tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
-            tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
-            gen_exception(dc, EXCP_RANGE);
-            gen_set_label(lab);
-            tcg_gen_mov_i32(cpu_R[rd], res);
-            tcg_temp_free_i64(ta);
-            tcg_temp_free_i64(td);
-            tcg_temp_free_i64(tcy);
-            tcg_temp_free_i32(res);
-            tcg_temp_free_i32(sr_cy);
-            tcg_temp_free_i32(sr_ove);
-        }
+        t0 = tcg_const_tl(I16);
+        gen_addc(dc, cpu_R[rd], cpu_R[ra], t0);
+        tcg_temp_free(t0);
         break;
 
     case 0x29:    /* l.andi */
@@ -974,13 +906,9 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x2c:    /* l.muli */
         LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
-        if (ra != 0 && I16 != 0) {
-            TCGv_i32 im = tcg_const_i32(I16);
-            gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], im);
-            tcg_temp_free_i32(im);
-        } else {
-            tcg_gen_movi_tl(cpu_R[rd], 0x0);
-        }
+        t0 = tcg_const_tl(I16);
+        gen_mul(dc, cpu_R[rd], cpu_R[ra], t0);
+        tcg_temp_free(t0);
         break;
 
     case 0x2d:    /* l.mfspr */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 03/25] target-openrisc: Invert the decoding in dec_calc
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 01/25] target-openrisc: Always enable OPENRISC_DISAS Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 02/25] target-openrisc: Streamline arithmetic and OVE Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 04/25] target-openrisc: Keep SR_F in a separate variable Richard Henderson
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Decoding the opcodes in the right order reduces by 100+ lines.
Also, it happens to put the opcodes in the same order as Chapter 17.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 300 ++++++++++++++------------------------------
 1 file changed, 94 insertions(+), 206 deletions(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index e895c98..8ccacc7 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -430,267 +430,155 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
     rb = extract32(insn, 11, 5);
     rd = extract32(insn, 21, 5);
 
-    switch (op0) {
-    case 0x0000:
-        switch (op1) {
-        case 0x00:    /* l.add */
+    switch (op1) {
+    case 0:
+        switch (op0) {
+        case 0x0: /* l.add */
             LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
             gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
+            return;
 
-    case 0x0001:    /* l.addc */
-        switch (op1) {
-        case 0x00:
+        case 0x1: /* l.addc */
             LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
             gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
+            return;
 
-    case 0x0002:    /* l.sub */
-        switch (op1) {
-        case 0x00:
+        case 0x2: /* l.sub */
             LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
             gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
+            return;
 
-    case 0x0003:    /* l.and */
-        switch (op1) {
-        case 0x00:
+        case 0x3: /* l.and */
             LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
             tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
+            return;
 
-    case 0x0004:    /* l.or */
-        switch (op1) {
-        case 0x00:
+        case 0x4: /* l.or */
             LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
             tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
+            return;
 
-    case 0x0005:
-        switch (op1) {
-        case 0x00:    /* l.xor */
+        case 0x5: /* l.xor */
             LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
             tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
-
-    case 0x0006:
-        switch (op1) {
-        case 0x03:    /* l.mul */
-            LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
-            gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
-
-    case 0x0009:
-        switch (op1) {
-        case 0x03:    /* l.div */
-            LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
-            gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
-
-    case 0x000a:
-        switch (op1) {
-        case 0x03:    /* l.divu */
-            LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
-            gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
-
-    case 0x000b:
-        switch (op1) {
-        case 0x03:    /* l.mulu */
-            LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
-            gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            break;
-
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
-
-    case 0x000e:
-        switch (op1) {
-        case 0x00:    /* l.cmov */
-            LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
-            {
-                TCGLabel *lab = gen_new_label();
-                TCGv res = tcg_temp_local_new();
-                TCGv sr_f = tcg_temp_new();
-                tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
-                tcg_gen_mov_tl(res, cpu_R[rb]);
-                tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
-                tcg_gen_mov_tl(res, cpu_R[ra]);
-                gen_set_label(lab);
-                tcg_gen_mov_tl(cpu_R[rd], res);
-                tcg_temp_free(sr_f);
-                tcg_temp_free(res);
-            }
-            break;
-
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
-
-    case 0x000f:
-        switch (op1) {
-        case 0x00:    /* l.ff1 */
-            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
-            gen_helper_ff1(cpu_R[rd], cpu_R[ra]);
-            break;
-        case 0x01:    /* l.fl1 */
-            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
-            gen_helper_fl1(cpu_R[rd], cpu_R[ra]);
-            break;
-
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
+            return;
 
-    case 0x0008:
-        switch (op1) {
-        case 0x00:
+        case 0x8:
             switch (op2) {
-            case 0x00:    /* l.sll */
+            case 0: /* l.sll */
                 LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
                 tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                break;
-            case 0x01:    /* l.srl */
+                return;
+            case 1: /* l.srl */
                 LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
                 tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                break;
-            case 0x02:    /* l.sra */
+                return;
+            case 2: /* l.sra */
                 LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
                 tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                break;
-            case 0x03:    /* l.ror */
+                return;
+            case 3: /* l.ror */
                 LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
                 tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                break;
-
-            default:
-                gen_illegal_exception(dc);
-                break;
+                return;
             }
             break;
 
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
-
-    case 0x000c:
-        switch (op1) {
-        case 0x00:
+        case 0xc:
             switch (op2) {
-            case 0x00:    /* l.exths */
+            case 0: /* l.exths */
                 LOG_DIS("l.exths r%d, r%d\n", rd, ra);
                 tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
-                break;
-            case 0x01:    /* l.extbs */
+                return;
+            case 1: /* l.extbs */
                 LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
                 tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
-                break;
-            case 0x02:    /* l.exthz */
+                return;
+            case 2: /* l.exthz */
                 LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
                 tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
-                break;
-            case 0x03:    /* l.extbz */
+                return;
+            case 3: /* l.extbz */
                 LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
                 tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
-                break;
-
-            default:
-                gen_illegal_exception(dc);
-                break;
+                return;
             }
             break;
 
-        default:
-            gen_illegal_exception(dc);
-            break;
-        }
-        break;
-
-    case 0x000d:
-        switch (op1) {
-        case 0x00:
+        case 0xd:
             switch (op2) {
-            case 0x00:    /* l.extws */
+            case 0: /* l.extws */
                 LOG_DIS("l.extws r%d, r%d\n", rd, ra);
                 tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
-                break;
-            case 0x01:    /* l.extwz */
+                return;
+            case 1: /* l.extwz */
                 LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
                 tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
-                break;
-
-            default:
-                gen_illegal_exception(dc);
-                break;
+                return;
             }
             break;
 
-        default:
-            gen_illegal_exception(dc);
-            break;
+        case 0xe: /* l.cmov */
+            LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
+            {
+                TCGLabel *lab = gen_new_label();
+                TCGv res = tcg_temp_local_new();
+                TCGv sr_f = tcg_temp_new();
+                tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+                tcg_gen_mov_tl(res, cpu_R[rb]);
+                tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+                tcg_gen_mov_tl(res, cpu_R[ra]);
+                gen_set_label(lab);
+                tcg_gen_mov_tl(cpu_R[rd], res);
+                tcg_temp_free(sr_f);
+                tcg_temp_free(res);
+            }
+            return;
+
+        case 0xf: /* l.ff1 */
+            LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_ff1(cpu_R[rd], cpu_R[ra]);
+            return;
         }
         break;
 
-    default:
-        gen_illegal_exception(dc);
+    case 1:
+        switch (op0) {
+        case 0xf: /* l.fl1 */
+            LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
+            gen_helper_fl1(cpu_R[rd], cpu_R[ra]);
+            return;
+        }
+        break;
+
+    case 2:
+        break;
+
+    case 3:
+        switch (op0) {
+        case 0x6: /* l.mul */
+            LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
+            gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            return;
+
+        case 0x9: /* l.div */
+            LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
+            gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            return;
+
+        case 0xa: /* l.divu */
+            LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
+            gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            return;
+
+        case 0xb: /* l.mulu */
+            LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
+            gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
+            return;
+        }
         break;
     }
+    gen_illegal_exception(dc);
 }
 
 static void dec_misc(DisasContext *dc, uint32_t insn)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 04/25] target-openrisc: Keep SR_F in a separate variable
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (2 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 03/25] target-openrisc: Invert the decoding in dec_calc Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 05/25] target-openrisc: Use movcond where appropriate Richard Henderson
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

This avoids having to keep merging and extracting the flag from SR.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/cpu.h              | 15 +++++-
 target-openrisc/gdbstub.c          |  4 +-
 target-openrisc/interrupt.c        |  2 +-
 target-openrisc/interrupt_helper.c |  2 +-
 target-openrisc/sys_helper.c       |  5 +-
 target-openrisc/translate.c        | 96 +++++++++++++++-----------------------
 6 files changed, 56 insertions(+), 68 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 810a280..1ea7607 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -286,7 +286,8 @@ typedef struct CPUOpenRISCState {
     target_ulong epcr;        /* Exception PC register */
     target_ulong eear;        /* Exception EA register */
 
-    uint32_t sr;              /* Supervisor register */
+    target_ulong sr_f;        /* the SR_F bit, values 0, 1.  */
+    uint32_t sr;              /* Supervisor register, without SR_F */
     uint32_t vr;              /* Version register */
     uint32_t upr;             /* Unit presence register */
     uint32_t cpucfgr;         /* CPU configure register */
@@ -298,7 +299,6 @@ typedef struct CPUOpenRISCState {
 
     uint32_t flags;           /* cpu_flags, we only use it for exception
                                  in solt so far.  */
-    uint32_t btaken;          /* the SR_F bit */
 
     CPU_COMMON
 
@@ -408,6 +408,17 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
     return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
 }
 
+static inline uint32_t cpu_get_sr(CPUOpenRISCState *env)
+{
+    return env->sr + env->sr_f * SR_F;
+}
+
+static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val)
+{
+    env->sr_f = (val & SR_F) != 0;
+    env->sr = (val & ~SR_F) | SR_FO;
+}
+
 #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
 
 #endif /* CPU_OPENRISC_H */
diff --git a/target-openrisc/gdbstub.c b/target-openrisc/gdbstub.c
index cb16e76..31ea013 100644
--- a/target-openrisc/gdbstub.c
+++ b/target-openrisc/gdbstub.c
@@ -38,7 +38,7 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
             return gdb_get_reg32(mem_buf, env->npc);
 
         case 34:    /* SR */
-            return gdb_get_reg32(mem_buf, env->sr);
+            return gdb_get_reg32(mem_buf, cpu_get_sr(env));
 
         default:
             break;
@@ -73,7 +73,7 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
             break;
 
         case 34: /* SR */
-            env->sr = tmp;
+            cpu_set_sr(env, tmp);
             break;
 
         default:
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 5fe3f11..36ca131 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -47,7 +47,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
        we need flush TLB when we enter&exit EXCP.  */
     tlb_flush(cs, 1);
 
-    env->esr = env->sr;
+    env->esr = cpu_get_sr(env);
     env->sr &= ~SR_DME;
     env->sr &= ~SR_IME;
     env->sr |= SR_SM;
diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c
index 116f910..71e14ce 100644
--- a/target-openrisc/interrupt_helper.c
+++ b/target-openrisc/interrupt_helper.c
@@ -33,7 +33,7 @@ void HELPER(rfe)(CPUOpenRISCState *env)
 #endif
     cpu->env.pc = cpu->env.epcr;
     cpu->env.npc = cpu->env.epcr;
-    cpu->env.sr = cpu->env.esr;
+    cpu_set_sr(&cpu->env, cpu->env.esr);
 
 #ifndef CONFIG_USER_ONLY
     if (cpu->env.sr & SR_DME) {
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index a719e45..8584ad0 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -49,8 +49,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
             (rb & (SR_IME | SR_DME | SR_SM))) {
             tlb_flush(cs, 1);
         }
-        env->sr = rb;
-        env->sr |= SR_FO;      /* FO is const equal to 1 */
+        cpu_set_sr(env, rb);
         if (env->sr & SR_DME) {
             env->tlb->cpu_openrisc_map_address_data =
                 &cpu_openrisc_get_phys_data;
@@ -200,7 +199,7 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
         return env->npc;
 
     case TO_SPR(0, 17): /* SR */
-        return env->sr;
+        return cpu_get_sr(env);
 
     case TO_SPR(0, 18): /* PPC */
         return env->ppc;
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 8ccacc7..2421b92 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -55,7 +55,7 @@ static TCGv cpu_pc;
 static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
 static TCGv cpu_npc;
 static TCGv cpu_ppc;
-static TCGv_i32 env_btaken;    /* bf/bnf , F flag taken */
+static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
 static TCGv_i32 fpcsr;
 static TCGv machi, maclo;
 static TCGv fpmaddhi, fpmaddlo;
@@ -86,9 +86,8 @@ void openrisc_translate_init(void)
                                  offsetof(CPUOpenRISCState, ppc), "ppc");
     jmp_pc = tcg_global_mem_new(cpu_env,
                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
-    env_btaken = tcg_global_mem_new_i32(cpu_env,
-                                        offsetof(CPUOpenRISCState, btaken),
-                                        "btaken");
+    cpu_sr_f = tcg_global_mem_new(cpu_env,
+                                 offsetof(CPUOpenRISCState, sr_f), "sr_f");
     fpcsr = tcg_global_mem_new_i32(cpu_env,
                                    offsetof(CPUOpenRISCState, fpcsr),
                                    "fpcsr");
@@ -111,16 +110,6 @@ void openrisc_translate_init(void)
     }
 }
 
-/* Writeback SR_F translation space to execution space.  */
-static inline void wb_SR_F(void)
-{
-    TCGLabel *label = gen_new_label();
-    tcg_gen_andi_tl(cpu_sr, cpu_sr, ~SR_F);
-    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, label);
-    tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_F);
-    gen_set_label(label);
-}
-
 static inline int zero_extend(unsigned int val, int width)
 {
     return val & ((1 << width) - 1);
@@ -231,14 +220,11 @@ static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
     case 0x04:     /* l.bf  */
         {
             TCGLabel *lab = gen_new_label();
-            TCGv sr_f = tcg_temp_new();
             tcg_gen_movi_tl(jmp_pc, dc->pc+8);
-            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
             tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
-                                sr_f, SR_F, lab);
+                                cpu_sr_f, SR_F, lab);
             tcg_gen_movi_tl(jmp_pc, tmp_pc);
             gen_set_label(lab);
-            tcg_temp_free(sr_f);
         }
         break;
     case 0x11:     /* l.jr */
@@ -523,14 +509,11 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
             {
                 TCGLabel *lab = gen_new_label();
                 TCGv res = tcg_temp_local_new();
-                TCGv sr_f = tcg_temp_new();
-                tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
                 tcg_gen_mov_tl(res, cpu_R[rb]);
-                tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab);
+                tcg_gen_brcondi_tl(TCG_COND_NE, cpu_sr_f, SR_F, lab);
                 tcg_gen_mov_tl(res, cpu_R[ra]);
                 gen_set_label(lab);
                 tcg_gen_mov_tl(cpu_R[rd], res);
-                tcg_temp_free(sr_f);
                 tcg_temp_free(res);
             }
             return;
@@ -997,7 +980,6 @@ static void dec_comp(DisasContext *dc, uint32_t insn)
     ra = extract32(insn, 16, 5);
     rb = extract32(insn, 11, 5);
 
-    tcg_gen_movi_i32(env_btaken, 0x0);
     /* unsigned integers  */
     tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
     tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
@@ -1005,59 +987,58 @@ static void dec_comp(DisasContext *dc, uint32_t insn)
     switch (op0) {
     case 0x0:    /* l.sfeq */
         LOG_DIS("l.sfeq  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x1:    /* l.sfne */
         LOG_DIS("l.sfne  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x2:    /* l.sfgtu */
         LOG_DIS("l.sfgtu  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x3:    /* l.sfgeu */
         LOG_DIS("l.sfgeu  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x4:    /* l.sfltu */
         LOG_DIS("l.sfltu  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x5:    /* l.sfleu */
         LOG_DIS("l.sfleu  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0xa:    /* l.sfgts */
         LOG_DIS("l.sfgts  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0xb:    /* l.sfges */
         LOG_DIS("l.sfges  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0xc:    /* l.sflts */
         LOG_DIS("l.sflts  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0xd:    /* l.sfles */
         LOG_DIS("l.sfles  r%d, r%d\n", ra, rb);
-        tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]);
+        tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
         break;
 
     default:
         gen_illegal_exception(dc);
         break;
     }
-    wb_SR_F();
 }
 
 static void dec_compi(DisasContext *dc, uint32_t insn)
@@ -1069,65 +1050,63 @@ static void dec_compi(DisasContext *dc, uint32_t insn)
     ra = extract32(insn, 16, 5);
     I16 = extract32(insn, 0, 16);
 
-    tcg_gen_movi_i32(env_btaken, 0x0);
     I16 = sign_extend(I16, 16);
 
     switch (op0) {
     case 0x0:    /* l.sfeqi */
         LOG_DIS("l.sfeqi  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0x1:    /* l.sfnei */
         LOG_DIS("l.sfnei  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_NE, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0x2:    /* l.sfgtui */
         LOG_DIS("l.sfgtui  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0x3:    /* l.sfgeui */
         LOG_DIS("l.sfgeui  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0x4:    /* l.sfltui */
         LOG_DIS("l.sfltui  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0x5:    /* l.sfleui */
         LOG_DIS("l.sfleui  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0xa:    /* l.sfgtsi */
         LOG_DIS("l.sfgtsi  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_GT, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0xb:    /* l.sfgesi */
         LOG_DIS("l.sfgesi  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_GE, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0xc:    /* l.sfltsi */
         LOG_DIS("l.sfltsi  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_LT, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     case 0xd:    /* l.sflesi */
         LOG_DIS("l.sflesi  r%d, %d\n", ra, I16);
-        tcg_gen_setcondi_tl(TCG_COND_LE, env_btaken, cpu_R[ra], I16);
+        tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16);
         break;
 
     default:
         gen_illegal_exception(dc);
         break;
     }
-    wb_SR_F();
 }
 
 static void dec_sys(DisasContext *dc, uint32_t insn)
@@ -1260,32 +1239,32 @@ static void dec_float(DisasContext *dc, uint32_t insn)
 
     case 0x08:    /* lf.sfeq.s */
         LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
-        gen_helper_float_eq_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x09:    /* lf.sfne.s */
         LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
-        gen_helper_float_ne_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_ne_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x0a:    /* lf.sfgt.s */
         LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
-        gen_helper_float_gt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_gt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x0b:    /* lf.sfge.s */
         LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
-        gen_helper_float_ge_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_ge_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x0c:    /* lf.sflt.s */
         LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
-        gen_helper_float_lt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x0d:    /* lf.sfle.s */
         LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
-        gen_helper_float_le_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
 /* not used yet, open it when we need or64.  */
@@ -1346,37 +1325,37 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     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(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_gt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     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(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_ge_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     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(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_ne_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     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(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 
     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(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
         break;
 #endif*/
 
@@ -1384,7 +1363,6 @@ static void dec_float(DisasContext *dc, uint32_t insn)
         gen_illegal_exception(dc);
         break;
     }
-    wb_SR_F();
 }
 
 static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 05/25] target-openrisc: Use movcond where appropriate
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (3 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 04/25] target-openrisc: Keep SR_F in a separate variable Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 06/25] target-openrisc: Put SR[OVE] in TB flags Richard Henderson
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 2421b92..48bd5f7 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -219,12 +219,16 @@ static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
     case 0x03:     /* l.bnf */
     case 0x04:     /* l.bf  */
         {
-            TCGLabel *lab = gen_new_label();
-            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
-            tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
-                                cpu_sr_f, SR_F, lab);
-            tcg_gen_movi_tl(jmp_pc, tmp_pc);
-            gen_set_label(lab);
+            TCGv t_next = tcg_const_tl(dc->pc + 8);
+            TCGv t_true = tcg_const_tl(tmp_pc);
+            TCGv t_zero = tcg_const_tl(0);
+
+            tcg_gen_movcond_tl(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
+                               jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
+
+            tcg_temp_free(t_next);
+            tcg_temp_free(t_true);
+            tcg_temp_free(t_zero);
         }
         break;
     case 0x11:     /* l.jr */
@@ -507,14 +511,10 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         case 0xe: /* l.cmov */
             LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
             {
-                TCGLabel *lab = gen_new_label();
-                TCGv res = tcg_temp_local_new();
-                tcg_gen_mov_tl(res, cpu_R[rb]);
-                tcg_gen_brcondi_tl(TCG_COND_NE, cpu_sr_f, SR_F, lab);
-                tcg_gen_mov_tl(res, cpu_R[ra]);
-                gen_set_label(lab);
-                tcg_gen_mov_tl(cpu_R[rd], res);
-                tcg_temp_free(res);
+                TCGv zero = tcg_const_tl(0);
+                tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero,
+                                   cpu_R[ra], cpu_R[rb]);
+                tcg_temp_free(zero);
             }
             return;
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 06/25] target-openrisc: Put SR[OVE] in TB flags
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (4 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 05/25] target-openrisc: Use movcond where appropriate Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 07/25] target-openrisc: Keep SR_CY and SR_OV in a separate variables Richard Henderson
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Removes a call at execution time for overflow exceptions.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/cpu.h              |  4 ++--
 target-openrisc/exception_helper.c |  2 +-
 target-openrisc/translate.c        | 24 +++++++++++++++---------
 3 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 1ea7607..af63f58 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -396,8 +396,8 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
 {
     *pc = env->pc;
     *cs_base = 0;
-    /* D_FLAG -- branch instruction exception */
-    *flags = (env->flags & D_FLAG);
+    /* D_FLAG -- branch instruction exception, OVE overflow trap enable.  */
+    *flags = (env->flags & D_FLAG) | (env->sr & SR_OVE);
 }
 
 static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
diff --git a/target-openrisc/exception_helper.c b/target-openrisc/exception_helper.c
index 561384a..6ae795f 100644
--- a/target-openrisc/exception_helper.c
+++ b/target-openrisc/exception_helper.c
@@ -31,7 +31,7 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
 
 void HELPER(ove)(CPUOpenRISCState *env, target_ulong test)
 {
-    if (unlikely(test) && (env->sr & SR_OVE)) {
+    if (unlikely(test)) {
         OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
         CPUState *cs = CPU(cpu);
 
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 48bd5f7..1cb726a 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -130,8 +130,8 @@ static inline int sign_extend(unsigned int val, int width)
 static inline void gen_sync_flags(DisasContext *dc)
 {
     /* Sync the tb dependent flag between translate and runtime.  */
-    if (dc->tb_flags != dc->synced_flags) {
-        tcg_gen_movi_tl(env_flags, dc->tb_flags);
+    if ((dc->tb_flags ^ dc->synced_flags) & D_FLAG) {
+        tcg_gen_movi_tl(env_flags, dc->tb_flags & D_FLAG);
         dc->synced_flags = dc->tb_flags;
     }
 }
@@ -250,20 +250,26 @@ static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
 
 static void gen_ove_cy(DisasContext *dc, TCGv cy)
 {
-    gen_helper_ove(cpu_env, cy);
+    if (dc->tb_flags & SR_OVE) {
+        gen_helper_ove(cpu_env, cy);
+    }
 }
 
 static void gen_ove_ov(DisasContext *dc, TCGv ov)
 {
-    gen_helper_ove(cpu_env, ov);
+    if (dc->tb_flags & SR_OVE) {
+        gen_helper_ove(cpu_env, ov);
+    }
 }
 
 static void gen_ove_cyov(DisasContext *dc, TCGv cy, TCGv ov)
 {
-    TCGv t0 = tcg_temp_new();
-    tcg_gen_or_tl(t0, cy, ov);
-    gen_helper_ove(cpu_env, t0);
-    tcg_temp_free(t0);
+    if (dc->tb_flags & SR_OVE) {
+        TCGv t0 = tcg_temp_new();
+        tcg_gen_or_tl(t0, cy, ov);
+        gen_helper_ove(cpu_env, t0);
+        tcg_temp_free(t0);
+    }
 }
 
 static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
@@ -1430,7 +1436,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     dc->flags = cpu->env.cpucfgr;
     dc->mem_idx = cpu_mmu_index(&cpu->env, false);
     dc->synced_flags = dc->tb_flags = tb->flags;
-    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
+    dc->delayed_branch = (dc->tb_flags & D_FLAG) != 0;
     dc->singlestep_enabled = cs->singlestep_enabled;
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("-----------------------------------------\n");
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 07/25] target-openrisc: Keep SR_CY and SR_OV in a separate variables
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (5 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 06/25] target-openrisc: Put SR[OVE] in TB flags Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 08/25] target-openrisc: Set flags on helpers Richard Henderson
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

This significantly streamlines carry and overflow production.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/cpu.h              |  13 +++-
 target-openrisc/exception_helper.c |  33 ++++++++---
 target-openrisc/helper.h           |   4 +-
 target-openrisc/translate.c        | 118 ++++++++++++-------------------------
 4 files changed, 78 insertions(+), 90 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index af63f58..37338c2 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -287,7 +287,9 @@ typedef struct CPUOpenRISCState {
     target_ulong eear;        /* Exception EA register */
 
     target_ulong sr_f;        /* the SR_F bit, values 0, 1.  */
-    uint32_t sr;              /* Supervisor register, without SR_F */
+    target_ulong sr_cy;       /* the SR_CY bit, values 0, 1.  */
+    target_ulong sr_ov;       /* the SR_OV bit (in the high bit only) */
+    uint32_t sr;              /* Supervisor register, without SR_{F,CY,OV} */
     uint32_t vr;              /* Version register */
     uint32_t upr;             /* Unit presence register */
     uint32_t cpucfgr;         /* CPU configure register */
@@ -410,13 +412,18 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
 
 static inline uint32_t cpu_get_sr(CPUOpenRISCState *env)
 {
-    return env->sr + env->sr_f * SR_F;
+    return (env->sr
+            + env->sr_f * SR_F
+            + env->sr_cy * SR_CY
+            + ((target_long)env->sr_ov < 0) * SR_OV);
 }
 
 static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val)
 {
     env->sr_f = (val & SR_F) != 0;
-    env->sr = (val & ~SR_F) | SR_FO;
+    env->sr_cy = (val & SR_CY) != 0;
+    env->sr_ov = (val & SR_OV ? -1 : 0);
+    env->sr = (val & ~(SR_F | SR_CY | SR_OV)) | SR_FO;
 }
 
 #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
diff --git a/target-openrisc/exception_helper.c b/target-openrisc/exception_helper.c
index 6ae795f..28b9d44 100644
--- a/target-openrisc/exception_helper.c
+++ b/target-openrisc/exception_helper.c
@@ -29,14 +29,33 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
     raise_exception(cpu, excp);
 }
 
-void HELPER(ove)(CPUOpenRISCState *env, target_ulong test)
+static void do_range(CPUOpenRISCState *env, uintptr_t pc)
 {
-    if (unlikely(test)) {
-        OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-        CPUState *cs = CPU(cpu);
+    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+
+    cs->exception_index = EXCP_RANGE;
+    cpu_restore_state(cs, pc);
+    cpu_loop_exit(cs);
+}
+
+void HELPER(ove_cy)(CPUOpenRISCState *env)
+{
+    if (env->sr_cy) {
+        do_range(env, GETPC());
+    }
+}
+
+void HELPER(ove_ov)(CPUOpenRISCState *env)
+{
+    if ((target_long)env->sr_ov < 0) {
+        do_range(env, GETPC());
+    }
+}
 
-        cs->exception_index = EXCP_RANGE;
-        cpu_restore_state(cs, GETPC());
-        cpu_loop_exit(cs);
+void HELPER(ove_cyov)(CPUOpenRISCState *env)
+{
+    if (env->sr_cy || (target_long)env->sr_ov < 0) {
+        do_range(env, GETPC());
     }
 }
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 1af2fab..136ec39 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -19,7 +19,9 @@
 
 /* exception */
 DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
-DEF_HELPER_FLAGS_2(ove, TCG_CALL_NO_WG, void, env, tl)
+DEF_HELPER_FLAGS_1(ove_cy, TCG_CALL_NO_WG, void, env)
+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, 0, i64, env, i64)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 1cb726a..f817f99 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -56,6 +56,8 @@ static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
 static TCGv cpu_npc;
 static TCGv cpu_ppc;
 static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
+static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
+static TCGv cpu_sr_ov;          /* signed overflow */
 static TCGv_i32 fpcsr;
 static TCGv machi, maclo;
 static TCGv fpmaddhi, fpmaddlo;
@@ -88,6 +90,10 @@ void openrisc_translate_init(void)
                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
     cpu_sr_f = tcg_global_mem_new(cpu_env,
                                  offsetof(CPUOpenRISCState, sr_f), "sr_f");
+    cpu_sr_cy = tcg_global_mem_new(cpu_env,
+                                 offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
+    cpu_sr_ov = tcg_global_mem_new(cpu_env,
+                                 offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
     fpcsr = tcg_global_mem_new_i32(cpu_env,
                                    offsetof(CPUOpenRISCState, fpcsr),
                                    "fpcsr");
@@ -248,27 +254,24 @@ static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
     gen_sync_flags(dc);
 }
 
-static void gen_ove_cy(DisasContext *dc, TCGv cy)
+static void gen_ove_cy(DisasContext *dc)
 {
     if (dc->tb_flags & SR_OVE) {
-        gen_helper_ove(cpu_env, cy);
+        gen_helper_ove_cy(cpu_env);
     }
 }
 
-static void gen_ove_ov(DisasContext *dc, TCGv ov)
+static void gen_ove_ov(DisasContext *dc)
 {
     if (dc->tb_flags & SR_OVE) {
-        gen_helper_ove(cpu_env, ov);
+        gen_helper_ove_ov(cpu_env);
     }
 }
 
-static void gen_ove_cyov(DisasContext *dc, TCGv cy, TCGv ov)
+static void gen_ove_cyov(DisasContext *dc)
 {
     if (dc->tb_flags & SR_OVE) {
-        TCGv t0 = tcg_temp_new();
-        tcg_gen_or_tl(t0, cy, ov);
-        gen_helper_ove(cpu_env, t0);
-        tcg_temp_free(t0);
+        gen_helper_ove_cyov(cpu_env);
     }
 }
 
@@ -276,143 +279,100 @@ static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 {
     TCGv t0 = tcg_const_tl(0);
     TCGv res = tcg_temp_new();
-    TCGv sr_cy = tcg_temp_new();
-    TCGv sr_ov = tcg_temp_new();
 
-    tcg_gen_add2_tl(res, sr_cy, srca, t0, srcb, t0);
-    tcg_gen_xor_tl(sr_ov, srca, srcb);
+    tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
+    tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
     tcg_gen_xor_tl(t0, res, srcb);
-    tcg_gen_andc_tl(sr_ov, t0, sr_ov);
+    tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
     tcg_temp_free(t0);
 
     tcg_gen_mov_tl(dest, res);
     tcg_temp_free(res);
 
-    tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1);
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
-
-    gen_ove_cyov(dc, sr_ov, sr_cy);
-    tcg_temp_free(sr_ov);
-    tcg_temp_free(sr_cy);
+    gen_ove_cyov(dc);
 }
 
 static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 {
     TCGv t0 = tcg_const_tl(0);
     TCGv res = tcg_temp_new();
-    TCGv sr_cy = tcg_temp_new();
-    TCGv sr_ov = tcg_temp_new();
-
-    tcg_gen_shri_tl(sr_cy, cpu_sr, ctz32(SR_CY));
-    tcg_gen_andi_tl(sr_cy, sr_cy, 1);
 
-    tcg_gen_add2_tl(res, sr_cy, srca, t0, sr_cy, t0);
-    tcg_gen_add2_tl(res, sr_cy, res, sr_cy, srcb, t0);
-    tcg_gen_xor_tl(sr_ov, srca, srcb);
+    tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
+    tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
+    tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
     tcg_gen_xor_tl(t0, res, srcb);
-    tcg_gen_andc_tl(sr_ov, t0, sr_ov);
+    tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
     tcg_temp_free(t0);
 
     tcg_gen_mov_tl(dest, res);
     tcg_temp_free(res);
 
-    tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1);
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
-
-    gen_ove_cyov(dc, sr_ov, sr_cy);
-    tcg_temp_free(sr_ov);
-    tcg_temp_free(sr_cy);
+    gen_ove_cyov(dc);
 }
 
 static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 {
     TCGv res = tcg_temp_new();
-    TCGv sr_cy = tcg_temp_new();
-    TCGv sr_ov = tcg_temp_new();
 
     tcg_gen_sub_tl(res, srca, srcb);
-    tcg_gen_xor_tl(sr_cy, srca, srcb);
-    tcg_gen_xor_tl(sr_ov, res, srcb);
-    tcg_gen_and_tl(sr_ov, sr_ov, sr_cy);
-    tcg_gen_setcond_tl(TCG_COND_LTU, sr_cy, srca, srcb);
+    tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
+    tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
+    tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
+    tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
 
     tcg_gen_mov_tl(dest, res);
     tcg_temp_free(res);
 
-    tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1);
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
-
-    gen_ove_cyov(dc, sr_ov, sr_cy);
-    tcg_temp_free(sr_ov);
-    tcg_temp_free(sr_cy);
+    gen_ove_cyov(dc);
 }
 
 static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 {
-    TCGv sr_ov = tcg_temp_new();
     TCGv t0 = tcg_temp_new();
 
-    tcg_gen_muls2_tl(dest, sr_ov, srca, srcb);
+    tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
-    tcg_gen_setcond_tl(TCG_COND_NE, sr_ov, sr_ov, t0);
+    tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
     tcg_temp_free(t0);
 
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
-
-    gen_ove_ov(dc, sr_ov);
-    tcg_temp_free(sr_ov);
+    tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
+    gen_ove_ov(dc);
 }
 
 static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 {
-    TCGv sr_cy = tcg_temp_new();
-
-    tcg_gen_muls2_tl(dest, sr_cy, srca, srcb);
-    tcg_gen_setcondi_tl(TCG_COND_NE, sr_cy, sr_cy, 0);
-
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
+    tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
+    tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
 
-    gen_ove_cy(dc, sr_cy);
-    tcg_temp_free(sr_cy);
+    gen_ove_cy(dc);
 }
 
 static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 {
-    TCGv sr_ov = tcg_temp_new();
     TCGv t0 = tcg_temp_new();
 
-    tcg_gen_setcondi_tl(TCG_COND_EQ, sr_ov, srcb, 0);
+    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
     /* The result of divide-by-zero is undefined.
        Supress the host-side exception by dividing by 1.  */
-    tcg_gen_or_tl(t0, srcb, sr_ov);
+    tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
     tcg_gen_div_tl(dest, srca, t0);
     tcg_temp_free(t0);
 
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1);
-
-    gen_ove_ov(dc, sr_ov);
-    tcg_temp_free(sr_ov);
+    gen_ove_ov(dc);
 }
 
 static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
 {
-    TCGv sr_cy = tcg_temp_new();
     TCGv t0 = tcg_temp_new();
 
-    tcg_gen_setcondi_tl(TCG_COND_EQ, sr_cy, srcb, 0);
+    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
     /* The result of divide-by-zero is undefined.
        Supress the host-side exception by dividing by 1.  */
-    tcg_gen_or_tl(t0, srcb, sr_cy);
+    tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
     tcg_gen_divu_tl(dest, srca, t0);
     tcg_temp_free(t0);
 
-    tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1);
-
-    gen_ove_cy(dc, sr_cy);
-    tcg_temp_free(sr_cy);
+    gen_ove_cy(dc);
 }
 
 static void dec_calc(DisasContext *dc, uint32_t insn)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 08/25] target-openrisc: Set flags on helpers
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (6 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 07/25] target-openrisc: Keep SR_CY and SR_OV in a separate variables Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 09/25] target-openrisc: Implement ff1 and fl1 for 64-bit Richard Henderson
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/helper.h | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 136ec39..4b0a935 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -18,26 +18,26 @@
  */
 
 /* exception */
-DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
+DEF_HELPER_FLAGS_2(exception, TCG_CALL_NO_WG, void, env, i32)
 DEF_HELPER_FLAGS_1(ove_cy, TCG_CALL_NO_WG, void, env)
 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, 0, i64, env, i64)
-DEF_HELPER_FLAGS_2(itofs, 0, i32, env, i32)
-DEF_HELPER_FLAGS_2(ftoid, 0, i64, env, i64)
-DEF_HELPER_FLAGS_2(ftois, 0, i32, env, i32)
+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)
 
 #define FOP_MADD(op)                                             \
-DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32)    \
-DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+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)
 FOP_MADD(muladd)
 #undef FOP_MADD
 
 #define FOP_CALC(op)                                            \
-DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32)    \
-DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+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)
 FOP_CALC(add)
 FOP_CALC(sub)
 FOP_CALC(mul)
@@ -46,8 +46,8 @@ FOP_CALC(rem)
 #undef FOP_CALC
 
 #define FOP_CMP(op)                                              \
-DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32)    \
-DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
+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)
 FOP_CMP(eq)
 FOP_CMP(lt)
 FOP_CMP(le)
@@ -57,12 +57,12 @@ FOP_CMP(ge)
 #undef FOP_CMP
 
 /* int */
-DEF_HELPER_FLAGS_1(ff1, 0, tl, tl)
-DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
+DEF_HELPER_FLAGS_1(ff1, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(fl1, TCG_CALL_NO_RWG_SE, tl, tl)
 
 /* interrupt */
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
 
 /* sys */
 DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
-DEF_HELPER_FLAGS_4(mfspr, 0, tl, env, tl, tl, tl)
+DEF_HELPER_FLAGS_4(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl, tl)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 09/25] target-openrisc: Implement ff1 and fl1 for 64-bit
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (7 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 08/25] target-openrisc: Set flags on helpers Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 10/25] target-openrisc: Represent MACHI:MACLO as a single unit Richard Henderson
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

True, this is unused so far, but commented out is worse than
actually implemented properly.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/int_helper.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/target-openrisc/int_helper.c b/target-openrisc/int_helper.c
index 6482f8c..64f837c 100644
--- a/target-openrisc/int_helper.c
+++ b/target-openrisc/int_helper.c
@@ -26,19 +26,20 @@
 
 target_ulong HELPER(ff1)(target_ulong x)
 {
-/*#ifdef TARGET_OPENRISC64
-    return x ? ctz64(x) + 1 : 0;
-#else*/
-    return x ? ctz32(x) + 1 : 0;
-/*#endif*/
+    if (x == 0) {
+        return 0;
+    } else if (TARGET_LONG_BITS == 64) {
+        return ctz64(x) + 1;
+    } else {
+        return ctz32(x) + 1;
+    }
 }
 
 target_ulong HELPER(fl1)(target_ulong x)
 {
-/* not used yet, open it when we need or64.  */
-/*#ifdef TARGET_OPENRISC64
-    return 64 - clz64(x);
-#else*/
-    return 32 - clz32(x);
-/*#endif*/
+    if (TARGET_LONG_BITS == 64) {
+        return 64 - clz64(x);
+    } else {
+        return 32 - clz32(x);
+    }
 }
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 10/25] target-openrisc: Represent MACHI:MACLO as a single unit
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (8 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 09/25] target-openrisc: Implement ff1 and fl1 for 64-bit Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 11/25] target-openrisc: Rationalize immediate extraction Richard Henderson
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Significantly simplifies the implementation of the use of MAC.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/cpu.h        |   3 +-
 target-openrisc/sys_helper.c |  13 +++++
 target-openrisc/translate.c  | 120 +++++++++++++++++++++++--------------------
 3 files changed, 78 insertions(+), 58 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 37338c2..37e0c00 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -277,8 +277,7 @@ typedef struct CPUOpenRISCState {
     target_ulong ppc;         /* Prev PC */
     target_ulong jmp_pc;      /* Jump PC */
 
-    target_ulong machi;       /* Multiply register MACHI */
-    target_ulong maclo;       /* Multiply register MACLO */
+    uint64_t mac;             /* Multiply registers MACHI:MACLO */
 
     target_ulong fpmaddhi;    /* Multiply and add float register FPMADDHI */
     target_ulong fpmaddlo;    /* Multiply and add float register FPMADDLO */
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index 8584ad0..e0d8893 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -120,6 +120,12 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
     case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
         break;
+    case TO_SPR(5, 1):  /* MACLO */
+        env->mac = deposit64(env->mac, 0, 32, rb);
+        break;
+    case TO_SPR(5, 2):  /* MACHI */
+        env->mac = deposit64(env->mac, 32, 32, rb);
+        break;
     case TO_SPR(9, 0):  /* PICMR */
         env->picmr |= rb;
         break;
@@ -245,6 +251,13 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
     case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
         break;
 
+    case TO_SPR(5, 1):  /* MACLO */
+        return (uint32_t)env->mac;
+        break;
+    case TO_SPR(5, 2):  /* MACHI */
+        return env->mac >> 32;
+        break;
+
     case TO_SPR(9, 0):  /* PICMR */
         return env->picmr;
 
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index f817f99..62129b8 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -59,7 +59,7 @@ static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
 static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
 static TCGv cpu_sr_ov;          /* signed overflow */
 static TCGv_i32 fpcsr;
-static TCGv machi, maclo;
+static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
 static TCGv fpmaddhi, fpmaddlo;
 static TCGv_i32 env_flags;
 #include "exec/gen-icount.h"
@@ -97,12 +97,9 @@ void openrisc_translate_init(void)
     fpcsr = tcg_global_mem_new_i32(cpu_env,
                                    offsetof(CPUOpenRISCState, fpcsr),
                                    "fpcsr");
-    machi = tcg_global_mem_new(cpu_env,
-                               offsetof(CPUOpenRISCState, machi),
-                               "machi");
-    maclo = tcg_global_mem_new(cpu_env,
-                               offsetof(CPUOpenRISCState, maclo),
-                               "maclo");
+    cpu_mac = tcg_global_mem_new_i64(cpu_env,
+                                     offsetof(CPUOpenRISCState, mac),
+                                     "mac");
     fpmaddhi = tcg_global_mem_new(cpu_env,
                                   offsetof(CPUOpenRISCState, fpmaddhi),
                                   "fpmaddhi");
@@ -375,6 +372,58 @@ static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
     gen_ove_cy(dc);
 }
 
+static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+
+    tcg_gen_ext_tl_i64(t1, srca);
+    tcg_gen_ext_tl_i64(t2, srcb);
+    tcg_gen_mul_i64(t1, t1, t2);
+
+    /* Note that overflow is only computed during addition stage.  */
+    tcg_gen_xor_i64(t2, cpu_mac, t1);
+    tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
+    tcg_gen_xor_i64(t1, t1, cpu_mac);
+    tcg_gen_andc_i64(t1, t1, t2);
+    tcg_temp_free_i64(t2);
+
+#if TARGET_LONG_BITS == 32
+    tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
+#else
+    tcg_gen_mov_i64(cpu_sr_ov, t1);
+#endif
+    tcg_temp_free_i64(t1);
+
+    gen_ove_ov(dc);
+}
+
+static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+
+    tcg_gen_ext_tl_i64(t1, srca);
+    tcg_gen_ext_tl_i64(t2, srcb);
+    tcg_gen_mul_i64(t1, t1, t2);
+
+    /* Note that overflow is only computed during subtraction stage.  */
+    tcg_gen_xor_i64(t2, cpu_mac, t1);
+    tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
+    tcg_gen_xor_i64(t1, t1, cpu_mac);
+    tcg_gen_and_i64(t1, t1, t2);
+    tcg_temp_free_i64(t2);
+
+#if TARGET_LONG_BITS == 32
+    tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
+#else
+    tcg_gen_mov_i64(cpu_sr_ov, t1);
+#endif
+    tcg_temp_free_i64(t1);
+
+    gen_ove_ov(dc);
+}
+
 static void dec_calc(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0, op1, op2;
@@ -596,23 +645,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         break;
 
     case 0x13:    /* l.maci */
-        LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11);
+        LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I16);
         {
-            TCGv_i64 t1 = tcg_temp_new_i64();
-            TCGv_i64 t2 = tcg_temp_new_i64();
-            TCGv_i32 dst = tcg_temp_new_i32();
-            TCGv ttmp = tcg_const_tl(tmp);
-            tcg_gen_mul_tl(dst, cpu_R[ra], ttmp);
-            tcg_gen_ext_i32_i64(t1, dst);
-            tcg_gen_concat_i32_i64(t2, maclo, machi);
-            tcg_gen_add_i64(t2, t2, t1);
-            tcg_gen_extrl_i64_i32(maclo, t2);
-            tcg_gen_shri_i64(t2, t2, 32);
-            tcg_gen_extrl_i64_i32(machi, t2);
-            tcg_temp_free_i32(dst);
-            tcg_temp_free(ttmp);
-            tcg_temp_free_i64(t1);
-            tcg_temp_free_i64(t2);
+            TCGv imm = tcg_const_tl(sign_extend(I16, 16));
+            gen_mac(dc, cpu_R[ra], imm);
+            tcg_temp_free(imm);
         }
         break;
 
@@ -832,40 +869,12 @@ static void dec_mac(DisasContext *dc, uint32_t insn)
     switch (op0) {
     case 0x0001:    /* l.mac */
         LOG_DIS("l.mac r%d, r%d\n", ra, rb);
-        {
-            TCGv_i32 t0 = tcg_temp_new_i32();
-            TCGv_i64 t1 = tcg_temp_new_i64();
-            TCGv_i64 t2 = tcg_temp_new_i64();
-            tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]);
-            tcg_gen_ext_i32_i64(t1, t0);
-            tcg_gen_concat_i32_i64(t2, maclo, machi);
-            tcg_gen_add_i64(t2, t2, t1);
-            tcg_gen_extrl_i64_i32(maclo, t2);
-            tcg_gen_shri_i64(t2, t2, 32);
-            tcg_gen_extrl_i64_i32(machi, t2);
-            tcg_temp_free_i32(t0);
-            tcg_temp_free_i64(t1);
-            tcg_temp_free_i64(t2);
-        }
+        gen_mac(dc, cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x0002:    /* l.msb */
         LOG_DIS("l.msb r%d, r%d\n", ra, rb);
-        {
-            TCGv_i32 t0 = tcg_temp_new_i32();
-            TCGv_i64 t1 = tcg_temp_new_i64();
-            TCGv_i64 t2 = tcg_temp_new_i64();
-            tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]);
-            tcg_gen_ext_i32_i64(t1, t0);
-            tcg_gen_concat_i32_i64(t2, maclo, machi);
-            tcg_gen_sub_i64(t2, t2, t1);
-            tcg_gen_extrl_i64_i32(maclo, t2);
-            tcg_gen_shri_i64(t2, t2, 32);
-            tcg_gen_extrl_i64_i32(machi, t2);
-            tcg_temp_free_i32(t0);
-            tcg_temp_free_i64(t1);
-            tcg_temp_free_i64(t2);
-        }
+        gen_msb(dc, cpu_R[ra], cpu_R[rb]);
         break;
 
     default:
@@ -926,9 +935,8 @@ static void dec_M(DisasContext *dc, uint32_t insn)
 
     case 0x1:    /* l.macrc */
         LOG_DIS("l.macrc  r%d\n", rd);
-        tcg_gen_mov_tl(cpu_R[rd], maclo);
-        tcg_gen_movi_tl(maclo, 0x0);
-        tcg_gen_movi_tl(machi, 0x0);
+        tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac);
+        tcg_gen_movi_i64(cpu_mac, 0);
         break;
 
     default:
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 11/25] target-openrisc: Rationalize immediate extraction
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (9 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 10/25] target-openrisc: Represent MACHI:MACLO as a single unit Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 12/25] target-openrisc: Enable m[tf]spr from user mode Richard Henderson
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

The architecture manual is consistent in using "I" for signed
fields and "K" for unsigned fields.  Mirror that.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 200 +++++++++++++++++---------------------------
 1 file changed, 75 insertions(+), 125 deletions(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 62129b8..6ca0420 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -113,23 +113,6 @@ void openrisc_translate_init(void)
     }
 }
 
-static inline int zero_extend(unsigned int val, int width)
-{
-    return val & ((1 << width) - 1);
-}
-
-static inline int sign_extend(unsigned int val, int width)
-{
-    int sval;
-
-    /* LSL */
-    val <<= TARGET_LONG_BITS - width;
-    sval = val;
-    /* ASR.  */
-    sval >>= TARGET_LONG_BITS - width;
-    return sval;
-}
-
 static inline void gen_sync_flags(DisasContext *dc)
 {
     /* Sync the tb dependent flag between translate and runtime.  */
@@ -153,29 +136,23 @@ static void gen_illegal_exception(DisasContext *dc)
     dc->is_jmp = DISAS_UPDATE;
 }
 
-/* not used yet, open it when we need or64.  */
-/*#ifdef TARGET_OPENRISC64
-static void check_ob64s(DisasContext *dc)
-{
-    if (!(dc->flags & CPUCFGR_OB64S)) {
-        gen_illegal_exception(dc);
-    }
-}
+#define check_ob64s(dc)                 \
+    do {                                \
+        gen_illegal_exception(dc);      \
+        return;                         \
+    } while (0)
 
-static void check_of64s(DisasContext *dc)
-{
-    if (!(dc->flags & CPUCFGR_OF64S)) {
-        gen_illegal_exception(dc);
-    }
-}
+#define check_of64s(dc)                 \
+    do {                                \
+        gen_illegal_exception(dc);      \
+        return;                         \
+    } while (0)
 
-static void check_ov64s(DisasContext *dc)
-{
-    if (!(dc->flags & CPUCFGR_OV64S)) {
-        gen_illegal_exception(dc);
-    }
-}
-#endif*/
+#define check_ov64s(dc)                 \
+    do {                                \
+        gen_illegal_exception(dc);      \
+        return;                         \
+    } while (0)
 
 static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
 {
@@ -205,11 +182,9 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
     }
 }
 
-static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
+static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0)
 {
-    target_ulong tmp_pc;
-    /* N26, 26bits imm */
-    tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
+    target_ulong tmp_pc = dc->pc + n26 * 4;
 
     switch (op0) {
     case 0x00:     /* l.j */
@@ -584,7 +559,8 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
     uint32_t op0, op1;
     uint32_t ra, rb, rd;
     uint32_t L6, K5;
-    uint32_t I16, I5, I11, N26, tmp;
+    uint32_t K16, K5_11;
+    int32_t I16, I5_11, N26;
     TCGMemOp mop;
     TCGv t0;
 
@@ -595,11 +571,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
     rd = extract32(insn, 21, 5);
     L6 = extract32(insn, 5, 6);
     K5 = extract32(insn, 0, 5);
-    I16 = extract32(insn, 0, 16);
-    I5 = extract32(insn, 21, 5);
-    I11 = extract32(insn, 0, 11);
-    N26 = extract32(insn, 0, 26);
-    tmp = (I5<<11) + I11;
+    K16 = extract32(insn, 0, 16);
+    I16 = (int16_t)K16;
+    N26 = sextract32(insn, 0, 26);
+    K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11);
+    I5_11 = (int16_t)K5_11;
 
     switch (op0) {
     case 0x00:    /* l.j */
@@ -645,12 +621,10 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         break;
 
     case 0x13:    /* l.maci */
-        LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I16);
-        {
-            TCGv imm = tcg_const_tl(sign_extend(I16, 16));
-            gen_mac(dc, cpu_R[ra], imm);
-            tcg_temp_free(imm);
-        }
+        LOG_DIS("l.maci r%d, %d\n", ra, I16);
+        t0 = tcg_const_tl(I16);
+        gen_mac(dc, cpu_R[ra], t0);
+        tcg_temp_free(t0);
         break;
 
     case 0x09:    /* l.rfe */
@@ -701,52 +675,40 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         LOG_DIS("l.cust8\n");
         break;
 
-/* not used yet, open it when we need or64.  */
-/*#ifdef TARGET_OPENRISC64
-    case 0x20:     l.ld
+    case 0x20:    /* l.ld */
         LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
         check_ob64s(dc);
         mop = MO_TEQ;
         goto do_load;
-#endif*/
-
     case 0x21:    /* l.lwz */
         LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
         mop = MO_TEUL;
         goto do_load;
-
     case 0x22:    /* l.lws */
         LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
         mop = MO_TESL;
         goto do_load;
-
     case 0x23:    /* l.lbz */
         LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
         mop = MO_UB;
         goto do_load;
-
     case 0x24:    /* l.lbs */
         LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
         mop = MO_SB;
         goto do_load;
-
     case 0x25:    /* l.lhz */
         LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
         mop = MO_TEUW;
         goto do_load;
-
     case 0x26:    /* l.lhs */
         LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
         mop = MO_TESW;
         goto do_load;
-
     do_load:
-        {
-            TCGv t0 = tcg_temp_new();
-            tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
-            tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
-            tcg_temp_free(t0);
-        }
+        t0 = tcg_temp_new();
+        tcg_gen_addi_tl(t0, cpu_R[ra], I16);
+        tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
+        tcg_temp_free(t0);
         break;
 
     case 0x27:    /* l.addi */
@@ -764,18 +726,18 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         break;
 
     case 0x29:    /* l.andi */
-        LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, I16);
-        tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16));
+        LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16);
+        tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16);
         break;
 
     case 0x2a:    /* l.ori */
-        LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, I16);
-        tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16));
+        LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16);
+        tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16);
         break;
 
     case 0x2b:    /* l.xori */
         LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
-        tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], sign_extend(I16, 16));
+        tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16);
         break;
 
     case 0x2c:    /* l.muli */
@@ -786,70 +748,57 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         break;
 
     case 0x2d:    /* l.mfspr */
-        LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
-        {
+        LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16);
 #if defined(CONFIG_USER_ONLY)
-            return;
+        return;
 #else
-            TCGv_i32 ti = tcg_const_i32(I16);
-            if (dc->mem_idx == MMU_USER_IDX) {
-                gen_illegal_exception(dc);
-                return;
-            }
-            gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
-            tcg_temp_free_i32(ti);
-#endif
+        if (dc->mem_idx == MMU_USER_IDX) {
+            gen_illegal_exception(dc);
+            return;
         }
+        t0 = tcg_const_i32(K16);
+        gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], t0);
+        tcg_temp_free(t0);
+#endif
         break;
 
     case 0x30:    /* l.mtspr */
-        LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
-        {
+        LOG_DIS("l.mtspr r%d, r%d, %d\n", ra, rb, K5_11);
 #if defined(CONFIG_USER_ONLY)
-            return;
+        return;
 #else
-            TCGv_i32 im = tcg_const_i32(tmp);
-            if (dc->mem_idx == MMU_USER_IDX) {
-                gen_illegal_exception(dc);
-                return;
-            }
-            gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
-            tcg_temp_free_i32(im);
-#endif
+        if (dc->mem_idx == MMU_USER_IDX) {
+            gen_illegal_exception(dc);
+            return;
         }
+        t0 = tcg_const_tl(K5_11);
+        gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], t0);
+        tcg_temp_free(t0);
+#endif
         break;
 
-/* not used yet, open it when we need or64.  */
-/*#ifdef TARGET_OPENRISC64
-    case 0x34:     l.sd
-        LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+    case 0x34:    /* l.sd */
+        LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11);
         check_ob64s(dc);
         mop = MO_TEQ;
         goto do_store;
-#endif*/
-
     case 0x35:    /* l.sw */
-        LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11);
         mop = MO_TEUL;
         goto do_store;
-
     case 0x36:    /* l.sb */
-        LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11);
         mop = MO_UB;
         goto do_store;
-
     case 0x37:    /* l.sh */
-        LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11);
         mop = MO_TEUW;
         goto do_store;
-
     do_store:
-        {
-            TCGv t0 = tcg_temp_new();
-            tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
-            tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop);
-            tcg_temp_free(t0);
-        }
+        t0 = tcg_temp_new();
+        tcg_gen_addi_tl(t0, cpu_R[ra], I5_11);
+        tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop);
+        tcg_temp_free(t0);
         break;
 
     default:
@@ -886,30 +835,32 @@ static void dec_mac(DisasContext *dc, uint32_t insn)
 static void dec_logic(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
-    uint32_t rd, ra, L6;
+    uint32_t rd, ra, L6, S6;
     op0 = extract32(insn, 6, 2);
     rd = extract32(insn, 21, 5);
     ra = extract32(insn, 16, 5);
     L6 = extract32(insn, 0, 6);
+    S6 = L6 & (TARGET_LONG_BITS - 1);
 
     switch (op0) {
     case 0x00:    /* l.slli */
         LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
-        tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6);
         break;
 
     case 0x01:    /* l.srli */
         LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
-        tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6);
         break;
 
     case 0x02:    /* l.srai */
         LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
-        tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); break;
+        tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6);
+        break;
 
     case 0x03:    /* l.rori */
         LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
-        tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f));
+        tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6);
         break;
 
     default:
@@ -1018,13 +969,12 @@ static void dec_comp(DisasContext *dc, uint32_t insn)
 static void dec_compi(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
-    uint32_t ra, I16;
+    uint32_t ra;
+    int32_t I16;
 
     op0 = extract32(insn, 21, 5);
     ra = extract32(insn, 16, 5);
-    I16 = extract32(insn, 0, 16);
-
-    I16 = sign_extend(I16, 16);
+    I16 = sextract32(insn, 0, 16);
 
     switch (op0) {
     case 0x0:    /* l.sfeqi */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 12/25] target-openrisc: Enable m[tf]spr from user mode
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (10 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 11/25] target-openrisc: Rationalize immediate extraction Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 13/25] target-openrisc: Enable trap, csync, msync, psync for " Richard Henderson
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

The architecture manual doesn't say these opcodes are user only.
Leaving them disabled excludes user mode from accessing interesting
SPRs like MACLO/MACHI.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/helper.h     |  4 +--
 target-openrisc/sys_helper.c | 77 +++++++++++++++++---------------------------
 target-openrisc/translate.c  | 32 +++++++-----------
 3 files changed, 43 insertions(+), 70 deletions(-)

diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 4b0a935..ef243cd 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -64,5 +64,5 @@ DEF_HELPER_FLAGS_1(fl1, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
 
 /* sys */
-DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
-DEF_HELPER_FLAGS_4(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl, tl)
+DEF_HELPER_FLAGS_3(mtspr, 0, void, env, i32, tl)
+DEF_HELPER_FLAGS_2(mfspr, TCG_CALL_NO_WG, tl, env, i32)
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index e0d8893..1530558 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -25,12 +25,11 @@
 
 #define TO_SPR(group, number) (((group) << 11) + (number))
 
-void HELPER(mtspr)(CPUOpenRISCState *env,
-                   target_ulong ra, target_ulong rb, target_ulong offset)
+void HELPER(mtspr)(CPUOpenRISCState *env, uint32_t spr, target_ulong rb)
 {
 #ifndef CONFIG_USER_ONLY
-    int spr = (ra | offset);
     int idx;
+#endif
 
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
     CPUState *cs = CPU(cpu);
@@ -50,6 +49,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
             tlb_flush(cs, 1);
         }
         cpu_set_sr(env, rb);
+#ifndef CONFIG_USER_ONLY
         if (env->sr & SR_DME) {
             env->tlb->cpu_openrisc_map_address_data =
                 &cpu_openrisc_get_phys_data;
@@ -65,6 +65,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
             env->tlb->cpu_openrisc_map_address_code =
                 &cpu_openrisc_get_phys_nommu;
         }
+#endif
         break;
 
     case TO_SPR(0, 18): /* PPC */
@@ -82,6 +83,15 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     case TO_SPR(0, 64): /* ESR */
         env->esr = rb;
         break;
+
+    case TO_SPR(5, 1):  /* MACLO */
+        env->mac = deposit64(env->mac, 0, 32, rb);
+        break;
+    case TO_SPR(5, 2):  /* MACHI */
+        env->mac = deposit64(env->mac, 32, 32, rb);
+        break;
+
+#ifndef CONFIG_USER_ONLY
     case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
         idx = spr - TO_SPR(1, 512);
         if (!(rb & 1)) {
@@ -89,7 +99,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         }
         env->tlb->dtlb[0][idx].mr = rb;
         break;
-
     case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
         idx = spr - TO_SPR(1, 640);
         env->tlb->dtlb[0][idx].tr = rb;
@@ -108,7 +117,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         }
         env->tlb->itlb[0][idx].mr = rb;
         break;
-
     case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
         idx = spr - TO_SPR(2, 640);
         env->tlb->itlb[0][idx].tr = rb;
@@ -120,12 +128,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
     case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
         break;
-    case TO_SPR(5, 1):  /* MACLO */
-        env->mac = deposit64(env->mac, 0, 32, rb);
-        break;
-    case TO_SPR(5, 2):  /* MACHI */
-        env->mac = deposit64(env->mac, 32, 32, rb);
-        break;
+
     case TO_SPR(9, 0):  /* PICMR */
         env->picmr |= rb;
         break;
@@ -169,21 +172,19 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         }
         cpu_openrisc_timer_update(cpu);
         break;
-    default:
+#endif
 
+    default:
         break;
     }
-#endif
 }
 
-target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
-                           target_ulong rd, target_ulong ra, uint32_t offset)
+target_ulong HELPER(mfspr)(CPUOpenRISCState *env, uint32_t spr)
 {
 #ifndef CONFIG_USER_ONLY
-    int spr = (ra | offset);
-    int idx;
-
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    int idx;
+#endif
 
     switch (spr) {
     case TO_SPR(0, 0): /* VR */
@@ -219,6 +220,14 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
     case TO_SPR(0, 64): /* ESR */
         return env->esr;
 
+    case TO_SPR(5, 1):  /* MACLO */
+        return (uint32_t)env->mac;
+        break;
+    case TO_SPR(5, 2):  /* MACHI */
+        return env->mac >> 32;
+        break;
+
+#ifndef CONFIG_USER_ONLY
     case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
         idx = spr - TO_SPR(1, 512);
         return env->tlb->dtlb[0][idx].mr;
@@ -251,13 +260,6 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
     case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
         break;
 
-    case TO_SPR(5, 1):  /* MACLO */
-        return (uint32_t)env->mac;
-        break;
-    case TO_SPR(5, 2):  /* MACHI */
-        return env->mac >> 32;
-        break;
-
     case TO_SPR(9, 0):  /* PICMR */
         return env->picmr;
 
@@ -270,31 +272,10 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
     case TO_SPR(10, 1): /* TTCR */
         cpu_openrisc_count_update(cpu);
         return env->ttcr;
+#endif
 
     default:
         break;
     }
-#endif
-
-/*If we later need to add tracepoints (or debug printfs) for the return
-value, it may be useful to structure the code like this:
-
-target_ulong ret = 0;
-
-switch() {
-case x:
- ret = y;
- break;
-case z:
- ret = 42;
- break;
-...
-}
-
-later something like trace_spr_read(ret);
-
-return ret;*/
-
-    /* for rd is passed in, if rd unchanged, just keep it back.  */
-    return rd;
+    return 0;
 }
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 6ca0420..4dde531 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -749,32 +749,24 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x2d:    /* l.mfspr */
         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16);
-#if defined(CONFIG_USER_ONLY)
-        return;
-#else
-        if (dc->mem_idx == MMU_USER_IDX) {
-            gen_illegal_exception(dc);
-            return;
+        {
+            TCGv_i32 tmp = tcg_temp_new_i32();
+            tcg_gen_trunc_tl_i32(tmp, cpu_R[ra]);
+            tcg_gen_ori_i32(tmp, tmp, K16);
+            gen_helper_mfspr(cpu_R[rd], cpu_env, tmp);
+            tcg_temp_free_i32(tmp);
         }
-        t0 = tcg_const_i32(K16);
-        gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], t0);
-        tcg_temp_free(t0);
-#endif
         break;
 
     case 0x30:    /* l.mtspr */
         LOG_DIS("l.mtspr r%d, r%d, %d\n", ra, rb, K5_11);
-#if defined(CONFIG_USER_ONLY)
-        return;
-#else
-        if (dc->mem_idx == MMU_USER_IDX) {
-            gen_illegal_exception(dc);
-            return;
+        {
+            TCGv_i32 tmp = tcg_temp_new_i32();
+            tcg_gen_trunc_tl_i32(tmp, cpu_R[ra]);
+            tcg_gen_ori_i32(tmp, tmp, K5_11);
+            gen_helper_mtspr(cpu_env, tmp, cpu_R[rb]);
+            tcg_temp_free_i32(tmp);
         }
-        t0 = tcg_const_tl(K5_11);
-        gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], t0);
-        tcg_temp_free(t0);
-#endif
         break;
 
     case 0x34:    /* l.sd */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 13/25] target-openrisc: Enable trap, csync, msync, psync for user mode
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (11 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 12/25] target-openrisc: Enable m[tf]spr from user mode Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 14/25] target-openrisc: Implement muld, muldu, macu, msbu Richard Henderson
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Not documented as disabled for user mode.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 32 --------------------------------
 1 file changed, 32 deletions(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 4dde531..d028612 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1043,52 +1043,20 @@ static void dec_sys(DisasContext *dc, uint32_t insn)
 
     case 0x100:    /* l.trap */
         LOG_DIS("l.trap %d\n", K16);
-#if defined(CONFIG_USER_ONLY)
-        return;
-#else
-        if (dc->mem_idx == MMU_USER_IDX) {
-            gen_illegal_exception(dc);
-            return;
-        }
         tcg_gen_movi_tl(cpu_pc, dc->pc);
         gen_exception(dc, EXCP_TRAP);
-#endif
         break;
 
     case 0x300:    /* l.csync */
         LOG_DIS("l.csync\n");
-#if defined(CONFIG_USER_ONLY)
-        return;
-#else
-        if (dc->mem_idx == MMU_USER_IDX) {
-            gen_illegal_exception(dc);
-            return;
-        }
-#endif
         break;
 
     case 0x200:    /* l.msync */
         LOG_DIS("l.msync\n");
-#if defined(CONFIG_USER_ONLY)
-        return;
-#else
-        if (dc->mem_idx == MMU_USER_IDX) {
-            gen_illegal_exception(dc);
-            return;
-        }
-#endif
         break;
 
     case 0x270:    /* l.psync */
         LOG_DIS("l.psync\n");
-#if defined(CONFIG_USER_ONLY)
-        return;
-#else
-        if (dc->mem_idx == MMU_USER_IDX) {
-            gen_illegal_exception(dc);
-            return;
-        }
-#endif
         break;
 
     default:
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 14/25] target-openrisc: Implement muld, muldu, macu, msbu
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (12 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 13/25] target-openrisc: Enable trap, csync, msync, psync for " Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 15/25] target-openrisc: Fix madd Richard Henderson
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 106 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index d028612..4ce51ea 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -347,6 +347,54 @@ static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
     gen_ove_cy(dc);
 }
 
+static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+
+    tcg_gen_ext_tl_i64(t1, srca);
+    tcg_gen_ext_tl_i64(t2, srcb);
+    if (TARGET_LONG_BITS == 32) {
+        tcg_gen_mul_i64(cpu_mac, t1, t2);
+    } else {
+        TCGv_i64 high = tcg_temp_new_i64();
+
+        tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
+        tcg_gen_sari_i64(t1, cpu_mac, 63);
+        tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
+        tcg_temp_free_i64(high);
+        tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
+        tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
+
+        gen_ove_ov(dc);
+    }
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+}
+
+static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+
+    tcg_gen_extu_tl_i64(t1, srca);
+    tcg_gen_extu_tl_i64(t2, srcb);
+    if (TARGET_LONG_BITS == 32) {
+        tcg_gen_mul_i64(cpu_mac, t1, t2);
+    } else {
+        TCGv_i64 high = tcg_temp_new_i64();
+
+        tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
+        tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
+        tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
+        tcg_temp_free_i64(high);
+
+        gen_ove_cy(dc);
+    }
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+}
+
 static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
 {
     TCGv_i64 t1 = tcg_temp_new_i64();
@@ -373,6 +421,25 @@ static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
     gen_ove_ov(dc);
 }
 
+static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+
+    tcg_gen_extu_tl_i64(t1, srca);
+    tcg_gen_extu_tl_i64(t2, srcb);
+    tcg_gen_mul_i64(t1, t1, t2);
+    tcg_temp_free_i64(t2);
+
+    /* Note that overflow is only computed during addition stage.  */
+    tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
+    tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
+    tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
+    tcg_temp_free_i64(t1);
+
+    gen_ove_cy(dc);
+}
+
 static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
 {
     TCGv_i64 t1 = tcg_temp_new_i64();
@@ -399,6 +466,25 @@ static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
     gen_ove_ov(dc);
 }
 
+static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+
+    tcg_gen_extu_tl_i64(t1, srca);
+    tcg_gen_extu_tl_i64(t2, srcb);
+    tcg_gen_mul_i64(t1, t1, t2);
+
+    /* Note that overflow is only computed during subtraction stage.  */
+    tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
+    tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
+    tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
+    tcg_temp_free_i64(t2);
+    tcg_temp_free_i64(t1);
+
+    gen_ove_cy(dc);
+}
+
 static void dec_calc(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0, op1, op2;
@@ -534,6 +620,11 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
             gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             return;
 
+        case 0x7: /* l.muld */
+            LOG_DIS("l.muld r%d, r%d\n", ra, rb);
+            gen_muld(dc, cpu_R[ra], cpu_R[rb]);
+            break;
+
         case 0x9: /* l.div */
             LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
             gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
@@ -548,6 +639,11 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
             LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
             gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
             return;
+
+        case 0xc: /* l.muldu */
+            LOG_DIS("l.muldu r%d, r%d\n", ra, rb);
+            gen_muldu(dc, cpu_R[ra], cpu_R[rb]);
+            return;
         }
         break;
     }
@@ -818,6 +914,16 @@ static void dec_mac(DisasContext *dc, uint32_t insn)
         gen_msb(dc, cpu_R[ra], cpu_R[rb]);
         break;
 
+    case 0x0003:    /* l.macu */
+        LOG_DIS("l.macu r%d, r%d\n", ra, rb);
+        gen_macu(dc, cpu_R[ra], cpu_R[rb]);
+        break;
+
+    case 0x0004:    /* l.msbu */
+        LOG_DIS("l.msbu r%d, r%d\n", ra, rb);
+        gen_msbu(dc, cpu_R[ra], cpu_R[rb]);
+        break;
+
     default:
         gen_illegal_exception(dc);
         break;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 15/25] target-openrisc: Fix madd
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (13 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 14/25] target-openrisc: Implement muld, muldu, macu, msbu Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 16/25] target-openrisc: Write back result before FPE exception Richard Henderson
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Note that the specification for lf.madd.s is confused.  It's
the only mention of supposed FPMADDHI/FPMADDLO special registers.
On the other hand, or1ksim implements a somewhat normal non-fused
multiply and add.  Mirror that.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/cpu.h        |  3 --
 target-openrisc/fpu_helper.c | 68 ++++++++++++++++----------------------------
 target-openrisc/helper.h     |  7 ++---
 target-openrisc/translate.c  | 13 +++------
 4 files changed, 30 insertions(+), 61 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 37e0c00..8c130da 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -279,9 +279,6 @@ typedef struct CPUOpenRISCState {
 
     uint64_t mac;             /* Multiply registers MACHI:MACLO */
 
-    target_ulong fpmaddhi;    /* Multiply and add float register FPMADDHI */
-    target_ulong fpmaddlo;    /* Multiply and add float register FPMADDLO */
-
     target_ulong epcr;        /* Exception PC register */
     target_ulong eear;        /* Exception EA register */
 
diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c
index c54404b..1375cea 100644
--- a/target-openrisc/fpu_helper.c
+++ b/target-openrisc/fpu_helper.c
@@ -146,52 +146,32 @@ FLOAT_CALC(div)
 FLOAT_CALC(rem)
 #undef FLOAT_CALC
 
-#define FLOAT_TERNOP(name1, name2)                                        \
-uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env,     \
-                                               uint64_t fdt0,             \
-                                               uint64_t fdt1)             \
-{                                                                         \
-    uint64_t result, temp, hi, lo;                                        \
-    uint32_t val1, val2;                                                  \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    hi = env->fpmaddhi;                                                   \
-    lo = env->fpmaddlo;                                                   \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status);          \
-    lo &= 0xffffffff;                                                     \
-    hi &= 0xffffffff;                                                     \
-    temp = (hi << 32) | lo;                                               \
-    result = float64_ ## name2(result, temp, &cpu->env.fp_status);        \
-    val1 = result >> 32;                                                  \
-    val2 = (uint32_t) (result & 0xffffffff);                              \
-    update_fpcsr(cpu);                                                    \
-    cpu->env.fpmaddlo = val2;                                             \
-    cpu->env.fpmaddhi = val1;                                             \
-    return 0;                                                             \
-}                                                                         \
-                                                                          \
-uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenRISCState *env,     \
-                                            uint32_t fdt0, uint32_t fdt1) \
-{                                                                         \
-    uint64_t result, temp, hi, lo;                                        \
-    uint32_t val1, val2;                                                  \
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);                         \
-    hi = cpu->env.fpmaddhi;                                               \
-    lo = cpu->env.fpmaddlo;                                               \
-    set_float_exception_flags(0, &cpu->env.fp_status);                    \
-    result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status);          \
-    temp = (hi << 32) | lo;                                               \
-    result = float64_ ## name2(result, temp, &cpu->env.fp_status);        \
-    val1 = result >> 32;                                                  \
-    val2 = (uint32_t) (result & 0xffffffff);                              \
-    update_fpcsr(cpu);                                                    \
-    cpu->env.fpmaddlo = val2;                                             \
-    cpu->env.fpmaddhi = val1;                                             \
-    return 0;                                                             \
+
+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;
 }
 
-FLOAT_TERNOP(mul, add)
-#undef FLOAT_TERNOP
+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;
+}
 
 
 #define FLOAT_CMP(name)                                                   \
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index ef243cd..58abeb8 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -29,11 +29,8 @@ 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)
 
-#define FOP_MADD(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)
-FOP_MADD(muladd)
-#undef FOP_MADD
+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)
 
 #define FOP_CALC(op)                                            \
 DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 4ce51ea..553bd67 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -60,7 +60,6 @@ static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
 static TCGv cpu_sr_ov;          /* signed overflow */
 static TCGv_i32 fpcsr;
 static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
-static TCGv fpmaddhi, fpmaddlo;
 static TCGv_i32 env_flags;
 #include "exec/gen-icount.h"
 
@@ -100,12 +99,6 @@ void openrisc_translate_init(void)
     cpu_mac = tcg_global_mem_new_i64(cpu_env,
                                      offsetof(CPUOpenRISCState, mac),
                                      "mac");
-    fpmaddhi = tcg_global_mem_new(cpu_env,
-                                  offsetof(CPUOpenRISCState, fpmaddhi),
-                                  "fpmaddhi");
-    fpmaddlo = tcg_global_mem_new(cpu_env,
-                                  offsetof(CPUOpenRISCState, fpmaddlo),
-                                  "fpmaddlo");
     for (i = 0; i < 32; i++) {
         cpu_R[i] = tcg_global_mem_new(cpu_env,
                                       offsetof(CPUOpenRISCState, gpr[i]),
@@ -1224,7 +1217,8 @@ static void dec_float(DisasContext *dc, uint32_t insn)
 
     case 0x07:    /* lf.madd.s */
         LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
-        gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd],
+                                cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x08:    /* lf.sfeq.s */
@@ -1309,7 +1303,8 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     case 0x17:     lf.madd.d
         LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
         check_of64s(dc);
-        gen_helper_float_muladd_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+        gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd],
+                                cpu_R[ra], cpu_R[rb]);
         break;
 
     case 0x18:     lf.sfeq.d
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 16/25] target-openrisc: Write back result before FPE exception
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (14 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 15/25] target-openrisc: Fix madd Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 17/25] target-openrisc: Implement lwa, swa Richard Henderson
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

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/fpu_helper.c | 252 +++++++++----------------------------------
 target-openrisc/helper.h     |  25 +++--
 target-openrisc/translate.c  | 118 +++++++++++---------
 3 files changed, 129 insertions(+), 266 deletions(-)

diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c
index 1375cea..ee1809d 100644
--- a/target-openrisc/fpu_helper.c
+++ b/target-openrisc/fpu_helper.c
@@ -23,121 +23,70 @@
 #include "exec/helper-proto.h"
 #include "exception.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));
-
-    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);
+    int tmp = get_float_exception_flags(&env->fp_status);
+
+    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)
@@ -150,132 +99,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/helper.h b/target-openrisc/helper.h
index 58abeb8..4bc2251 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
 
 /* int */
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 553bd67..e539693 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1174,175 +1174,193 @@ 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);
         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);
         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 */
+    case 0x02: /* lf.mul.s */
         LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
-        if (ra != 0 && rb != 0) {
-            gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
-        } else {
-            tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
-            tcg_gen_movi_i32(cpu_R[rd], 0x0);
-        }
+        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);
         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);
         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);
         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);
         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);
         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);
         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);
         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);
-        if (ra != 0 && rb != 0) {
-            gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
-        } else {
-            tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF);
-            tcg_gen_movi_i64(cpu_R[rd], 0x0);
-        }
+        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);
         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);
         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);
         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);
         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);
         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);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 17/25] target-openrisc: Implement lwa, swa
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (15 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 16/25] target-openrisc: Write back result before FPE exception Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 18/25] target-openrisc: Implement l.adrp Richard Henderson
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/main.c                  | 45 ++++++++++++++++++++++++
 target-openrisc/cpu.c              |  1 +
 target-openrisc/cpu.h              |  9 +++++
 target-openrisc/interrupt.c        |  1 +
 target-openrisc/interrupt_helper.c |  1 +
 target-openrisc/mmu.c              |  1 +
 target-openrisc/translate.c        | 70 ++++++++++++++++++++++++++++++++++++++
 7 files changed, 128 insertions(+)

diff --git a/linux-user/main.c b/linux-user/main.c
index f8a8764..51af5d1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2720,6 +2720,48 @@ error:
 #endif
 
 #ifdef TARGET_OPENRISC
+static void do_store_exclusive(CPUOpenRISCState *env)
+{
+    target_ulong addr, val, tmp;
+    target_siginfo_t info;
+    int ret = 0;
+
+    addr = env->lock_addr;
+    tmp = env->lock_st_addr;
+    env->lock_addr = -1;
+    env->lock_st_addr = 0;
+
+    start_exclusive();
+    mmap_lock();
+
+    if (addr == tmp) {
+        if (get_user_u32(val, addr)) {
+            goto do_sigsegv;
+        }
+        if (val == env->lock_value) {
+            if (put_user_u32(env->lock_st_value, addr)) {
+                goto do_sigsegv;
+            }
+            ret = 1;
+        }
+    }
+    env->sr_f = ret;
+    env->pc += 4;
+
+    mmap_unlock();
+    end_exclusive();
+    return;
+
+ do_sigsegv:
+    mmap_unlock();
+    end_exclusive();
+
+    info.si_signo = TARGET_SIGSEGV;
+    info.si_errno = 0;
+    info.si_code = TARGET_SEGV_MAPERR;
+    info._sifields._sigfault._addr = addr;
+    queue_signal(env, TARGET_SIGSEGV, &info);
+}
 
 void cpu_loop(CPUOpenRISCState *env)
 {
@@ -2795,6 +2837,9 @@ void cpu_loop(CPUOpenRISCState *env)
         case EXCP_NR:
             qemu_log_mask(CPU_LOG_INT, "\nNR\n");
             break;
+	case EXCP_SWA:
+            do_store_exclusive(env);
+            break;
         default:
             EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
                      trapnr);
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 155913f..e6f6186 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -55,6 +55,7 @@ static void openrisc_cpu_reset(CPUState *s)
 
     cpu->env.pc = 0x100;
     cpu->env.sr = SR_FO | SR_SM;
+    cpu->env.lock_addr = -1;
     s->exception_index = -1;
 
     cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 8c130da..bb9540f 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -169,6 +169,8 @@ enum {
     EXCP_FPE      = 0xd,
     EXCP_TRAP     = 0xe,
     EXCP_NR,
+    /* For usermode emulation.  */
+    EXCP_SWA,
 };
 
 /* Supervisor register */
@@ -295,6 +297,13 @@ typedef struct CPUOpenRISCState {
     uint32_t fpcsr;           /* Float register */
     float_status fp_status;
 
+    target_ulong lock_addr;
+    target_ulong lock_value;
+#ifdef CONFIG_USER_ONLY
+    target_ulong lock_st_addr;
+    target_ulong lock_st_value;
+#endif
+
     uint32_t flags;           /* cpu_flags, we only use it for exception
                                  in solt so far.  */
 
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 36ca131..77c2d00 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -55,6 +55,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
     env->sr &= ~SR_TEE;
     env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
     env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
+    env->lock_addr = -1;
 
     if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
         env->pc = (cs->exception_index << 8);
diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c
index 71e14ce..68d1598 100644
--- a/target-openrisc/interrupt_helper.c
+++ b/target-openrisc/interrupt_helper.c
@@ -34,6 +34,7 @@ void HELPER(rfe)(CPUOpenRISCState *env)
     cpu->env.pc = cpu->env.epcr;
     cpu->env.npc = cpu->env.epcr;
     cpu_set_sr(&cpu->env, cpu->env.esr);
+    cpu->env.lock_addr = -1;
 
 #ifndef CONFIG_USER_ONLY
     if (cpu->env.sr & SR_DME) {
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index 505dcdc..56b11d3 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -174,6 +174,7 @@ static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU *cpu,
 
     cs->exception_index = exception;
     cpu->env.eear = address;
+    cpu->env.lock_addr = -1;
 }
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index e539693..0ad0c39 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -58,6 +58,8 @@ static TCGv cpu_ppc;
 static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
 static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
 static TCGv cpu_sr_ov;          /* signed overflow */
+static TCGv cpu_lock_addr;
+static TCGv cpu_lock_value;
 static TCGv_i32 fpcsr;
 static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
 static TCGv_i32 env_flags;
@@ -93,6 +95,12 @@ void openrisc_translate_init(void)
                                  offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
     cpu_sr_ov = tcg_global_mem_new(cpu_env,
                                  offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
+    cpu_lock_addr = tcg_global_mem_new(cpu_env,
+                                       offsetof(CPUOpenRISCState, lock_addr),
+                                       "lock_addr");
+    cpu_lock_value = tcg_global_mem_new(cpu_env,
+                                        offsetof(CPUOpenRISCState, lock_value),
+                                        "lock_value");
     fpcsr = tcg_global_mem_new_i32(cpu_env,
                                    offsetof(CPUOpenRISCState, fpcsr),
                                    "fpcsr");
@@ -478,6 +486,58 @@ static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
     gen_ove_cy(dc);
 }
 
+static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
+{
+    TCGv ea = tcg_temp_new();
+
+    tcg_gen_addi_tl(ea, ra, ofs);
+    tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL);
+    tcg_gen_mov_tl(cpu_lock_addr, ea);
+    tcg_gen_mov_tl(cpu_lock_value, rd);
+    tcg_temp_free(ea);
+}
+
+static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs)
+{
+#ifdef CONFIG_USER_ONLY
+    TCGv ea = tcg_temp_new();
+    tcg_gen_addi_tl(ea, ra, ofs);
+    tcg_gen_st_tl(ea, cpu_env, offsetof(CPUOpenRISCState, lock_st_addr));
+    tcg_temp_free(ea);
+
+    tcg_gen_st32_tl(rb, cpu_env, offsetof(CPUOpenRISCState, lock_st_value));
+
+    tcg_gen_movi_tl(cpu_pc, dc->pc);
+    gen_exception(dc, EXCP_SWA);
+    dc->is_jmp = DISAS_UPDATE;
+#else
+    TCGv ea, val;
+    TCGLabel *lab_fail, *lab_done;
+
+    ea = tcg_temp_new();
+    tcg_gen_addi_tl(ea, ra, ofs);
+
+    lab_fail = gen_new_label();
+    lab_done = gen_new_label();
+    tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
+    tcg_temp_free(ea);
+
+    val = tcg_temp_new();
+    tcg_gen_qemu_ld_tl(val, cpu_lock_addr, dc->mem_idx, MO_TEUL);
+    tcg_gen_brcond_tl(TCG_COND_NE, val, cpu_lock_value, lab_fail);
+
+    tcg_gen_qemu_st_tl(rb, cpu_lock_addr, dc->mem_idx, MO_TEUL);
+    tcg_gen_movi_tl(cpu_sr_f, 1);
+    tcg_gen_br(lab_done);
+
+    gen_set_label(lab_fail);
+    tcg_gen_movi_tl(cpu_sr_f, 0);
+
+    gen_set_label(lab_done);
+    tcg_gen_movi_tl(cpu_lock_addr, -1);
+#endif
+}
+
 static void dec_calc(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0, op1, op2;
@@ -732,6 +792,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         }
         break;
 
+    case 0x1b: /* l.lwa */
+        LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
+        gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16);
+        break;
+
     case 0x1c:    /* l.cust1 */
         LOG_DIS("l.cust1\n");
         break;
@@ -858,6 +923,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         }
         break;
 
+    case 0x33: /* l.swa */
+        LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11);
+        gen_swa(dc, cpu_R[rb], cpu_R[ra], I5_11);
+        break;
+
     case 0x34:    /* l.sd */
         LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11);
         check_ob64s(dc);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 18/25] target-openrisc: Implement l.adrp
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (16 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 17/25] target-openrisc: Implement lwa, swa Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 19/25] target-openrisc: Tidy ppc/npc implementation Richard Henderson
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Not part of the v1.1 standard, but a proposed extension
to vastly simplify both PIC and 64-bit mode.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 0ad0c39..7804edd 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -709,7 +709,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
     uint32_t ra, rb, rd;
     uint32_t L6, K5;
     uint32_t K16, K5_11;
-    int32_t I16, I5_11, N26;
+    int32_t I16, I5_11, N21, N26;
     TCGMemOp mop;
     TCGv t0;
 
@@ -722,6 +722,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
     K5 = extract32(insn, 0, 5);
     K16 = extract32(insn, 0, 16);
     I16 = (int16_t)K16;
+    N21 = sextract32(insn, 0, 21);
     N26 = sextract32(insn, 0, 26);
     K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11);
     I5_11 = (int16_t)K5_11;
@@ -737,6 +738,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         gen_jump(dc, N26, 0, op0);
         break;
 
+    case 0x02:    /* l.adrp */
+        LOG_DIS("l.adrp r%d,%d\n", rd, N21);
+        tcg_gen_movi_tl(cpu_R[rd], ((dc->pc >> 13) + N21) << 13);
+        break;
+
     case 0x03:    /* l.bnf */
         LOG_DIS("l.bnf %d\n", N26);
         gen_jump(dc, N26, 0, op0);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 19/25] target-openrisc: Tidy ppc/npc implementation
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (17 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 18/25] target-openrisc: Implement l.adrp Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 20/25] target-openrisc: Optimize l.jal to next Richard Henderson
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

The NPC SPR is really only supposed to be used for FPGA debugging.
It contains the same contents as PC, unless one plays games.  Follow
the or1ksim implementation in flushing delayed branch state when it
is changed.

The PPC SPR need not be updated every instruction, merely when we
exit the TB or attempt to read its contents.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/cpu.h              |  2 +-
 target-openrisc/gdbstub.c          | 13 +++++++++----
 target-openrisc/interrupt_helper.c |  1 -
 target-openrisc/machine.c          |  5 ++---
 target-openrisc/sys_helper.c       | 23 ++++++++++++++++-------
 target-openrisc/translate.c        | 29 +++++++++++------------------
 6 files changed, 39 insertions(+), 34 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index bb9540f..70ac481 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -58,6 +58,7 @@ typedef struct OpenRISCCPUClass {
 } OpenRISCCPUClass;
 
 #define NB_MMU_MODES    3
+#define TARGET_INSN_START_EXTRA_WORDS 1
 
 enum {
     MMU_NOMMU_IDX = 0,
@@ -275,7 +276,6 @@ typedef struct CPUOpenRISCTLBContext {
 typedef struct CPUOpenRISCState {
     target_ulong gpr[32];     /* General registers */
     target_ulong pc;          /* Program counter */
-    target_ulong npc;         /* Next PC */
     target_ulong ppc;         /* Prev PC */
     target_ulong jmp_pc;      /* Jump PC */
 
diff --git a/target-openrisc/gdbstub.c b/target-openrisc/gdbstub.c
index 31ea013..2a4821f 100644
--- a/target-openrisc/gdbstub.c
+++ b/target-openrisc/gdbstub.c
@@ -34,8 +34,8 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
         case 32:    /* PPC */
             return gdb_get_reg32(mem_buf, env->ppc);
 
-        case 33:    /* NPC */
-            return gdb_get_reg32(mem_buf, env->npc);
+        case 33:    /* NPC (equals PC) */
+            return gdb_get_reg32(mem_buf, env->pc);
 
         case 34:    /* SR */
             return gdb_get_reg32(mem_buf, cpu_get_sr(env));
@@ -68,8 +68,13 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
             env->ppc = tmp;
             break;
 
-        case 33: /* NPC */
-            env->npc = tmp;
+        case 33: /* NPC (equals PC) */
+            /* If setting PC to something different,
+               also clear delayed branch status.  */
+            if (env->pc != tmp) {
+                env->pc = tmp;
+                env->flags = 0;
+            }
             break;
 
         case 34: /* SR */
diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c
index 68d1598..00817d8 100644
--- a/target-openrisc/interrupt_helper.c
+++ b/target-openrisc/interrupt_helper.c
@@ -32,7 +32,6 @@ void HELPER(rfe)(CPUOpenRISCState *env)
                          (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
 #endif
     cpu->env.pc = cpu->env.epcr;
-    cpu->env.npc = cpu->env.epcr;
     cpu_set_sr(&cpu->env, cpu->env.esr);
     cpu->env.lock_addr = -1;
 
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
index 17b0c77..a984929 100644
--- a/target-openrisc/machine.c
+++ b/target-openrisc/machine.c
@@ -26,8 +26,8 @@
 
 static const VMStateDescription vmstate_env = {
     .name = "env",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32),
         VMSTATE_UINT32(sr, CPUOpenRISCState),
@@ -36,7 +36,6 @@ static const VMStateDescription vmstate_env = {
         VMSTATE_UINT32(esr, CPUOpenRISCState),
         VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
         VMSTATE_UINT32(pc, CPUOpenRISCState),
-        VMSTATE_UINT32(npc, CPUOpenRISCState),
         VMSTATE_UINT32(ppc, CPUOpenRISCState),
         VMSTATE_END_OF_LIST()
     }
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index 1530558..1103a7b 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -27,20 +27,26 @@
 
 void HELPER(mtspr)(CPUOpenRISCState *env, uint32_t spr, target_ulong rb)
 {
+    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
 #ifndef CONFIG_USER_ONLY
     int idx;
 #endif
 
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
-
     switch (spr) {
     case TO_SPR(0, 0): /* VR */
         env->vr = rb;
         break;
 
     case TO_SPR(0, 16): /* NPC */
-        env->npc = rb;
+        cpu_restore_state(cs, GETPC());
+        /* ??? Mirror or1ksim in not trashing delayed branch state
+           when "jumping" to the current instruction.  */
+        if (env->pc != rb) {
+            env->pc = rb;
+            env->flags = 0;
+            cpu_loop_exit(cs);
+        }
         break;
 
     case TO_SPR(0, 17): /* SR */
@@ -181,8 +187,9 @@ void HELPER(mtspr)(CPUOpenRISCState *env, uint32_t spr, target_ulong rb)
 
 target_ulong HELPER(mfspr)(CPUOpenRISCState *env, uint32_t spr)
 {
-#ifndef CONFIG_USER_ONLY
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+#ifndef CONFIG_USER_ONLY
     int idx;
 #endif
 
@@ -202,13 +209,15 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, uint32_t spr)
     case TO_SPR(0, 4): /* IMMUCFGR */
         return env->immucfgr;
 
-    case TO_SPR(0, 16): /* NPC */
-        return env->npc;
+    case TO_SPR(0, 16): /* NPC (equals PC) */
+        cpu_restore_state(cs, GETPC());
+        return env->pc;
 
     case TO_SPR(0, 17): /* SR */
         return cpu_get_sr(env);
 
     case TO_SPR(0, 18): /* PPC */
+        cpu_restore_state(cs, GETPC());
         return env->ppc;
 
     case TO_SPR(0, 32): /* EPCR */
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 7804edd..70aadbc 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -40,7 +40,7 @@
 
 typedef struct DisasContext {
     TranslationBlock *tb;
-    target_ulong pc, ppc, npc;
+    target_ulong pc;
     uint32_t tb_flags, synced_flags, flags;
     uint32_t is_jmp;
     uint32_t mem_idx;
@@ -53,7 +53,6 @@ static TCGv cpu_sr;
 static TCGv cpu_R[32];
 static TCGv cpu_pc;
 static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
-static TCGv cpu_npc;
 static TCGv cpu_ppc;
 static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
 static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
@@ -83,8 +82,6 @@ void openrisc_translate_init(void)
                                        "flags");
     cpu_pc = tcg_global_mem_new(cpu_env,
                                 offsetof(CPUOpenRISCState, pc), "pc");
-    cpu_npc = tcg_global_mem_new(cpu_env,
-                                 offsetof(CPUOpenRISCState, npc), "npc");
     cpu_ppc = tcg_global_mem_new(cpu_env,
                                  offsetof(CPUOpenRISCState, ppc), "ppc");
     jmp_pc = tcg_global_mem_new(cpu_env,
@@ -1504,7 +1501,6 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     dc->tb = tb;
 
     dc->is_jmp = DISAS_NEXT;
-    dc->ppc = pc_start;
     dc->pc = pc_start;
     dc->flags = cpu->env.cpucfgr;
     dc->mem_idx = cpu_mmu_index(&cpu->env, false);
@@ -1530,7 +1526,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     gen_tb_start(tb);
 
     do {
-        tcg_gen_insn_start(dc->pc);
+        tcg_gen_insn_start(dc->pc, num_insns != 0);
         num_insns++;
 
         if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
@@ -1548,12 +1544,9 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
-        dc->ppc = dc->pc - 4;
-        dc->npc = dc->pc + 4;
-        tcg_gen_movi_tl(cpu_ppc, dc->ppc);
-        tcg_gen_movi_tl(cpu_npc, dc->npc);
         disas_openrisc_insn(dc, cpu);
-        dc->pc = dc->npc;
+        dc->pc = dc->pc + 4;
+
         /* delay slot */
         if (dc->delayed_branch) {
             dc->delayed_branch--;
@@ -1561,10 +1554,8 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
                 dc->tb_flags &= ~D_FLAG;
                 gen_sync_flags(dc);
                 tcg_gen_mov_tl(cpu_pc, jmp_pc);
-                tcg_gen_mov_tl(cpu_npc, jmp_pc);
-                tcg_gen_movi_tl(jmp_pc, 0);
-                tcg_gen_exit_tb(0);
-                dc->is_jmp = DISAS_JUMP;
+                tcg_gen_discard_tl(jmp_pc);
+                dc->is_jmp = DISAS_UPDATE;
                 break;
             }
         }
@@ -1578,14 +1569,13 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end();
     }
+
+    tcg_gen_movi_tl(cpu_ppc, dc->pc - 4);
     if (dc->is_jmp == DISAS_NEXT) {
         dc->is_jmp = DISAS_UPDATE;
         tcg_gen_movi_tl(cpu_pc, dc->pc);
     }
     if (unlikely(cs->singlestep_enabled)) {
-        if (dc->is_jmp == DISAS_NEXT) {
-            tcg_gen_movi_tl(cpu_pc, dc->pc);
-        }
         gen_exception(dc, EXCP_DEBUG);
     } else {
         switch (dc->is_jmp) {
@@ -1641,4 +1631,7 @@ void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
                           target_ulong *data)
 {
     env->pc = data[0];
+    if (data[1]) {
+        env->ppc = env->pc - 4;
+    }
 }
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 20/25] target-openrisc: Optimize l.jal to next
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (18 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 19/25] target-openrisc: Tidy ppc/npc implementation Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 21/25] target-openrisc: Tidy insn dumping Richard Henderson
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

This allows the tcg optimizer to see, and fold, all of the
constants involved in a GOT base register load sequence.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 70aadbc..31f4307 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -189,7 +189,11 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0)
         tcg_gen_movi_tl(jmp_pc, tmp_pc);
         break;
     case 0x01:     /* l.jal */
-        tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+        tcg_gen_movi_tl(cpu_R[9], dc->pc + 8);
+        /* Optimize jal being used to load the PC for PIC.  */
+        if (tmp_pc == dc->pc + 8) {
+            return;
+        }
         tcg_gen_movi_tl(jmp_pc, tmp_pc);
         break;
     case 0x03:     /* l.bnf */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 21/25] target-openrisc: Tidy insn dumping
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (19 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 20/25] target-openrisc: Optimize l.jal to next Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 22/25] target-openrisc: Tidy handling of delayed branches Richard Henderson
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 31f4307..3102190 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -36,7 +36,8 @@
 
 /* Set to 0 to completely disable.  */
 #define OPENRISC_DISAS  CPU_LOG_TB_IN_ASM
-#define LOG_DIS(...) qemu_log_mask(OPENRISC_DISAS, ## __VA_ARGS__)
+#define LOG_DIS(str, ...) \
+    qemu_log_mask(OPENRISC_DISAS, "%08x: " str, dc->pc, ## __VA_ARGS__)
 
 typedef struct DisasContext {
     TranslationBlock *tb;
@@ -1511,9 +1512,9 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     dc->synced_flags = dc->tb_flags = tb->flags;
     dc->delayed_branch = (dc->tb_flags & D_FLAG) != 0;
     dc->singlestep_enabled = cs->singlestep_enabled;
+
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
-        qemu_log("-----------------------------------------\n");
-        log_cpu_state(CPU(cpu), 0);
+        qemu_log("IN: %s\n", lookup_symbol(pc_start));
     }
 
     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 22/25] target-openrisc: Tidy handling of delayed branches
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (20 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 21/25] target-openrisc: Tidy insn dumping Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 23/25] target-openrisc: Optimize for r0 being zero Richard Henderson
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/cpu.h        | 12 +++++-------
 target-openrisc/gdbstub.c    |  2 +-
 target-openrisc/interrupt.c  |  4 ++--
 target-openrisc/sys_helper.c |  2 +-
 target-openrisc/translate.c  | 40 ++++++++++++++++------------------------
 5 files changed, 25 insertions(+), 35 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 70ac481..ca5181d 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -83,9 +83,6 @@ enum {
 /* Version Register */
 #define SPR_VR 0xFFFF003F
 
-/* Internal flags, delay slot flag */
-#define D_FLAG    1
-
 /* Interrupt */
 #define NR_IRQS  32
 
@@ -304,8 +301,7 @@ typedef struct CPUOpenRISCState {
     target_ulong lock_st_value;
 #endif
 
-    uint32_t flags;           /* cpu_flags, we only use it for exception
-                                 in solt so far.  */
+    uint32_t dflag;           /* In delay slot (boolean) */
 
     CPU_COMMON
 
@@ -397,14 +393,16 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
 
 #include "exec/cpu-all.h"
 
+#define TB_FLAGS_DFLAG 1
+#define TB_FLAGS_OVE   SR_OVE
+
 static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
                                         target_ulong *pc,
                                         target_ulong *cs_base, uint32_t *flags)
 {
     *pc = env->pc;
     *cs_base = 0;
-    /* D_FLAG -- branch instruction exception, OVE overflow trap enable.  */
-    *flags = (env->flags & D_FLAG) | (env->sr & SR_OVE);
+    *flags = env->dflag | (env->sr & SR_OVE);
 }
 
 static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
diff --git a/target-openrisc/gdbstub.c b/target-openrisc/gdbstub.c
index 2a4821f..b18c7e9 100644
--- a/target-openrisc/gdbstub.c
+++ b/target-openrisc/gdbstub.c
@@ -73,7 +73,7 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
                also clear delayed branch status.  */
             if (env->pc != tmp) {
                 env->pc = tmp;
-                env->flags = 0;
+                env->dflag = 0;
             }
             break;
 
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 77c2d00..cfd501d 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -34,8 +34,8 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
     CPUOpenRISCState *env = &cpu->env;
 
     env->epcr = env->pc;
-    if (env->flags & D_FLAG) {
-        env->flags &= ~D_FLAG;
+    if (env->dflag) {
+        env->dflag = 0;
         env->sr |= SR_DSX;
         env->epcr -= 4;
     }
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index 1103a7b..6cccc82 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -44,7 +44,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, uint32_t spr, target_ulong rb)
            when "jumping" to the current instruction.  */
         if (env->pc != rb) {
             env->pc = rb;
-            env->flags = 0;
+            env->dflag = 0;
             cpu_loop_exit(cs);
         }
         break;
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 3102190..95e12ef 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -42,11 +42,11 @@
 typedef struct DisasContext {
     TranslationBlock *tb;
     target_ulong pc;
-    uint32_t tb_flags, synced_flags, flags;
     uint32_t is_jmp;
     uint32_t mem_idx;
-    int singlestep_enabled;
+    uint32_t tb_flags;
     uint32_t delayed_branch;
+    bool singlestep_enabled;
 } DisasContext;
 
 static TCGv_env cpu_env;
@@ -62,7 +62,7 @@ static TCGv cpu_lock_addr;
 static TCGv cpu_lock_value;
 static TCGv_i32 fpcsr;
 static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
-static TCGv_i32 env_flags;
+static TCGv_i32 cpu_dflag;
 #include "exec/gen-icount.h"
 
 void openrisc_translate_init(void)
@@ -78,9 +78,9 @@ void openrisc_translate_init(void)
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
     cpu_sr = tcg_global_mem_new(cpu_env,
                                 offsetof(CPUOpenRISCState, sr), "sr");
-    env_flags = tcg_global_mem_new_i32(cpu_env,
-                                       offsetof(CPUOpenRISCState, flags),
-                                       "flags");
+    cpu_dflag = tcg_global_mem_new_i32(cpu_env,
+                                       offsetof(CPUOpenRISCState, dflag),
+                                       "dflag");
     cpu_pc = tcg_global_mem_new(cpu_env,
                                 offsetof(CPUOpenRISCState, pc), "pc");
     cpu_ppc = tcg_global_mem_new(cpu_env,
@@ -112,15 +112,6 @@ void openrisc_translate_init(void)
     }
 }
 
-static inline void gen_sync_flags(DisasContext *dc)
-{
-    /* Sync the tb dependent flag between translate and runtime.  */
-    if ((dc->tb_flags ^ dc->synced_flags) & D_FLAG) {
-        tcg_gen_movi_tl(env_flags, dc->tb_flags & D_FLAG);
-        dc->synced_flags = dc->tb_flags;
-    }
-}
-
 static void gen_exception(DisasContext *dc, unsigned int excp)
 {
     TCGv_i32 tmp = tcg_const_i32(excp);
@@ -225,8 +216,6 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0)
     }
 
     dc->delayed_branch = 2;
-    dc->tb_flags |= D_FLAG;
-    gen_sync_flags(dc);
 }
 
 static void gen_ove_cy(DisasContext *dc)
@@ -1507,10 +1496,9 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
-    dc->flags = cpu->env.cpucfgr;
     dc->mem_idx = cpu_mmu_index(&cpu->env, false);
-    dc->synced_flags = dc->tb_flags = tb->flags;
-    dc->delayed_branch = (dc->tb_flags & D_FLAG) != 0;
+    dc->tb_flags = tb->flags;
+    dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
     dc->singlestep_enabled = cs->singlestep_enabled;
 
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1531,7 +1519,8 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     gen_tb_start(tb);
 
     do {
-        tcg_gen_insn_start(dc->pc, num_insns != 0);
+        tcg_gen_insn_start(dc->pc, (dc->delayed_branch ? 1 : 0)
+			   | (num_insns ? 2 : 0));
         num_insns++;
 
         if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
@@ -1556,8 +1545,6 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         if (dc->delayed_branch) {
             dc->delayed_branch--;
             if (!dc->delayed_branch) {
-                dc->tb_flags &= ~D_FLAG;
-                gen_sync_flags(dc);
                 tcg_gen_mov_tl(cpu_pc, jmp_pc);
                 tcg_gen_discard_tl(jmp_pc);
                 dc->is_jmp = DISAS_UPDATE;
@@ -1575,6 +1562,10 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         gen_io_end();
     }
 
+    if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
+        tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
+    }
+
     tcg_gen_movi_tl(cpu_ppc, dc->pc - 4);
     if (dc->is_jmp == DISAS_NEXT) {
         dc->is_jmp = DISAS_UPDATE;
@@ -1636,7 +1627,8 @@ void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
                           target_ulong *data)
 {
     env->pc = data[0];
-    if (data[1]) {
+    env->dflag = data[1] & 1;
+    if (data[1] & 2) {
         env->ppc = env->pc - 4;
     }
 }
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 23/25] target-openrisc: Optimize for r0 being zero
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (21 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 22/25] target-openrisc: Tidy handling of delayed branches Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 24/25] target-openrisc: Generate goto_tb for direct branches Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 25/25] target-openrisc: Generate goto_tb for conditional branches Richard Henderson
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/cpu.h              |  5 +++-
 target-openrisc/exception_helper.c |  1 +
 target-openrisc/translate.c        | 47 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index ca5181d..16c1458 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -394,6 +394,7 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
 #include "exec/cpu-all.h"
 
 #define TB_FLAGS_DFLAG 1
+#define TB_FLAGS_R0_0  2
 #define TB_FLAGS_OVE   SR_OVE
 
 static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
@@ -402,7 +403,9 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
 {
     *pc = env->pc;
     *cs_base = 0;
-    *flags = env->dflag | (env->sr & SR_OVE);
+    *flags = (env->dflag
+              | (env->gpr[0] == 0 ? TB_FLAGS_R0_0 : 0)
+              | (env->sr & SR_OVE));
 }
 
 static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
diff --git a/target-openrisc/exception_helper.c b/target-openrisc/exception_helper.c
index 28b9d44..db77d30 100644
--- a/target-openrisc/exception_helper.c
+++ b/target-openrisc/exception_helper.c
@@ -19,6 +19,7 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 #include "exception.h"
 
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 95e12ef..cb9267d 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -52,6 +52,7 @@ typedef struct DisasContext {
 static TCGv_env cpu_env;
 static TCGv cpu_sr;
 static TCGv cpu_R[32];
+static TCGv cpu_R0;
 static TCGv cpu_pc;
 static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
 static TCGv cpu_ppc;
@@ -110,6 +111,7 @@ void openrisc_translate_init(void)
                                       offsetof(CPUOpenRISCState, gpr[i]),
                                       regnames[i]);
     }
+    cpu_R0 = cpu_R[0];
 }
 
 static void gen_exception(DisasContext *dc, unsigned int excp)
@@ -144,6 +146,15 @@ static void gen_illegal_exception(DisasContext *dc)
         return;                         \
     } while (0)
 
+/* We're about to write to REG.  On the off-chance that the user is
+   writing to R0, re-instate the architectural register.  */
+#define check_r0_write(reg)             \
+    do {                                \
+        if (unlikely(reg == 0)) {       \
+            cpu_R[0] = cpu_R0;          \
+        }                               \
+    } while (0)
+
 static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
 {
     if (unlikely(dc->singlestep_enabled)) {
@@ -731,6 +742,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x02:    /* l.adrp */
         LOG_DIS("l.adrp r%d,%d\n", rd, N21);
+        check_r0_write(rd);
         tcg_gen_movi_tl(cpu_R[rd], ((dc->pc >> 13) + N21) << 13);
         break;
 
@@ -791,6 +803,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x1b: /* l.lwa */
         LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
+        check_r0_write(rd);
         gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16);
         break;
 
@@ -856,6 +869,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         mop = MO_TESW;
         goto do_load;
     do_load:
+        check_r0_write(rd);
         t0 = tcg_temp_new();
         tcg_gen_addi_tl(t0, cpu_R[ra], I16);
         tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
@@ -864,6 +878,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x27:    /* l.addi */
         LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
+        check_r0_write(rd);
         t0 = tcg_const_tl(I16);
         gen_add(dc, cpu_R[rd], cpu_R[ra], t0);
         tcg_temp_free(t0);
@@ -871,6 +886,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x28:    /* l.addic */
         LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
+        check_r0_write(rd);
         t0 = tcg_const_tl(I16);
         gen_addc(dc, cpu_R[rd], cpu_R[ra], t0);
         tcg_temp_free(t0);
@@ -878,21 +894,25 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x29:    /* l.andi */
         LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16);
+        check_r0_write(rd);
         tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16);
         break;
 
     case 0x2a:    /* l.ori */
         LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16);
+        check_r0_write(rd);
         tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16);
         break;
 
     case 0x2b:    /* l.xori */
         LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
+        check_r0_write(rd);
         tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16);
         break;
 
     case 0x2c:    /* l.muli */
         LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
+        check_r0_write(rd);
         t0 = tcg_const_tl(I16);
         gen_mul(dc, cpu_R[rd], cpu_R[ra], t0);
         tcg_temp_free(t0);
@@ -900,6 +920,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x2d:    /* l.mfspr */
         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16);
+        check_r0_write(rd);
         {
             TCGv_i32 tmp = tcg_temp_new_i32();
             tcg_gen_trunc_tl_i32(tmp, cpu_R[ra]);
@@ -1000,6 +1021,7 @@ static void dec_logic(DisasContext *dc, uint32_t insn)
     L6 = extract32(insn, 0, 6);
     S6 = L6 & (TARGET_LONG_BITS - 1);
 
+    check_r0_write(rd);
     switch (op0) {
     case 0x00:    /* l.slli */
         LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
@@ -1036,6 +1058,7 @@ static void dec_M(DisasContext *dc, uint32_t insn)
     rd = extract32(insn, 21, 5);
     K16 = extract32(insn, 0, 16);
 
+    check_r0_write(rd);
     switch (op0) {
     case 0x0:    /* l.movhi */
         LOG_DIS("l.movhi  r%d, %d\n", rd, K16);
@@ -1243,48 +1266,56 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     switch (op0) {
     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 */
         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 */
         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 */
         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 */
         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 */
         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 */
         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);
@@ -1331,6 +1362,7 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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;
@@ -1338,6 +1370,7 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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;
@@ -1345,6 +1378,7 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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;
@@ -1352,6 +1386,7 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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;
@@ -1359,6 +1394,7 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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;
@@ -1366,6 +1402,7 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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;
@@ -1373,6 +1410,7 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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;
@@ -1380,6 +1418,7 @@ static void dec_float(DisasContext *dc, uint32_t insn)
     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);
@@ -1518,6 +1557,14 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
 
     gen_tb_start(tb);
 
+    /* Allow the TCG optimizer to see that R0 == 0,
+       when it's true, which is the common case.  */
+    if (dc->tb_flags & TB_FLAGS_R0_0) {
+        cpu_R[0] = tcg_const_tl(0);
+    } else {
+        cpu_R[0] = cpu_R0;
+    }
+
     do {
         tcg_gen_insn_start(dc->pc, (dc->delayed_branch ? 1 : 0)
 			   | (num_insns ? 2 : 0));
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 24/25] target-openrisc: Generate goto_tb for direct branches
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (22 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 23/25] target-openrisc: Optimize for r0 being zero Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 25/25] target-openrisc: Generate goto_tb for conditional branches Richard Henderson
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 348 ++++++++++++++++++++++----------------------
 1 file changed, 173 insertions(+), 175 deletions(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index cb9267d..4d29d22 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -39,14 +39,22 @@
 #define LOG_DIS(str, ...) \
     qemu_log_mask(OPENRISC_DISAS, "%08x: " str, dc->pc, ## __VA_ARGS__)
 
+typedef enum {
+    JMP_NONE,
+    JMP_EXCP,
+    JMP_VAR,
+    JMP_DIRECT,
+} JmpStatus;
+
 typedef struct DisasContext {
     TranslationBlock *tb;
     target_ulong pc;
-    uint32_t is_jmp;
     uint32_t mem_idx;
     uint32_t tb_flags;
-    uint32_t delayed_branch;
+    bool dflag;
     bool singlestep_enabled;
+    JmpStatus jmp_type;
+    target_ulong jmp_dest[2];
 } DisasContext;
 
 static TCGv_env cpu_env;
@@ -114,37 +122,33 @@ void openrisc_translate_init(void)
     cpu_R0 = cpu_R[0];
 }
 
-static void gen_exception(DisasContext *dc, unsigned int excp)
+static void gen_exception_1(unsigned int excp)
 {
     TCGv_i32 tmp = tcg_const_i32(excp);
     gen_helper_exception(cpu_env, tmp);
     tcg_temp_free_i32(tmp);
 }
 
-static void gen_illegal_exception(DisasContext *dc)
+static JmpStatus gen_exception(DisasContext *dc, unsigned int excp)
 {
     tcg_gen_movi_tl(cpu_pc, dc->pc);
-    gen_exception(dc, EXCP_ILLEGAL);
-    dc->is_jmp = DISAS_UPDATE;
+    gen_exception_1(excp);
+    return JMP_EXCP;
 }
 
-#define check_ob64s(dc)                 \
-    do {                                \
-        gen_illegal_exception(dc);      \
-        return;                         \
-    } while (0)
+static JmpStatus gen_illegal_exception(DisasContext *dc)
+{
+    return gen_exception(dc, EXCP_ILLEGAL);
+}
 
-#define check_of64s(dc)                 \
-    do {                                \
-        gen_illegal_exception(dc);      \
-        return;                         \
-    } while (0)
+#define check_ob64s(dc) \
+    do { return gen_illegal_exception(dc); } while (0)
 
-#define check_ov64s(dc)                 \
-    do {                                \
-        gen_illegal_exception(dc);      \
-        return;                         \
-    } while (0)
+#define check_of64s(dc) \
+    do { return gen_illegal_exception(dc); } while (0)
+
+#define check_ov64s(dc) \
+    do { return gen_illegal_exception(dc); } while (0)
 
 /* We're about to write to REG.  On the off-chance that the user is
    writing to R0, re-instate the architectural register.  */
@@ -171,34 +175,33 @@ static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
 {
     if (use_goto_tb(dc, dest)) {
-        tcg_gen_movi_tl(cpu_pc, dest);
         tcg_gen_goto_tb(n);
+        tcg_gen_movi_tl(cpu_pc, dest);
         tcg_gen_exit_tb((uintptr_t)dc->tb + n);
     } else {
         tcg_gen_movi_tl(cpu_pc, dest);
-        if (dc->singlestep_enabled) {
-            gen_exception(dc, EXCP_DEBUG);
-        }
         tcg_gen_exit_tb(0);
     }
 }
 
-static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0)
+static JmpStatus gen_jump(DisasContext *dc, int32_t n26,
+                          uint32_t reg, uint32_t op0)
 {
     target_ulong tmp_pc = dc->pc + n26 * 4;
 
     switch (op0) {
-    case 0x00:     /* l.j */
-        tcg_gen_movi_tl(jmp_pc, tmp_pc);
-        break;
     case 0x01:     /* l.jal */
         tcg_gen_movi_tl(cpu_R[9], dc->pc + 8);
         /* Optimize jal being used to load the PC for PIC.  */
         if (tmp_pc == dc->pc + 8) {
-            return;
+            return JMP_NONE;
         }
-        tcg_gen_movi_tl(jmp_pc, tmp_pc);
+        /* fallthru */
+    case 0x00:     /* l.j */
+        dc->jmp_dest[0] = tmp_pc;
+        dc->jmp_type = JMP_DIRECT;
         break;
+
     case 0x03:     /* l.bnf */
     case 0x04:     /* l.bf  */
         {
@@ -212,21 +215,27 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0)
             tcg_temp_free(t_next);
             tcg_temp_free(t_true);
             tcg_temp_free(t_zero);
+
+            dc->jmp_type = JMP_VAR;
         }
         break;
+
     case 0x11:     /* l.jr */
         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+        dc->jmp_type = JMP_VAR;
         break;
     case 0x12:     /* l.jalr */
-        tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
+        tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
+        dc->jmp_type = JMP_VAR;
         break;
+
     default:
-        gen_illegal_exception(dc);
-        break;
+        return gen_illegal_exception(dc);
     }
 
-    dc->delayed_branch = 2;
+    dc->dflag = true;
+    return JMP_NONE;
 }
 
 static void gen_ove_cy(DisasContext *dc)
@@ -509,9 +518,7 @@ static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs)
 
     tcg_gen_st32_tl(rb, cpu_env, offsetof(CPUOpenRISCState, lock_st_value));
 
-    tcg_gen_movi_tl(cpu_pc, dc->pc);
     gen_exception(dc, EXCP_SWA);
-    dc->is_jmp = DISAS_UPDATE;
 #else
     TCGv ea, val;
     TCGLabel *lab_fail, *lab_done;
@@ -540,7 +547,7 @@ static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs)
 #endif
 }
 
-static void dec_calc(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_calc(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0, op1, op2;
     uint32_t ra, rb, rd;
@@ -557,51 +564,53 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         case 0x0: /* l.add */
             LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
             gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0x1: /* l.addc */
             LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
             gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0x2: /* l.sub */
             LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
             gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0x3: /* l.and */
             LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
             tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0x4: /* l.or */
             LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
             tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0x5: /* l.xor */
             LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
             tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0x8:
             switch (op2) {
             case 0: /* l.sll */
                 LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
                 tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                return;
+                break;
             case 1: /* l.srl */
                 LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
                 tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                return;
+                break;
             case 2: /* l.sra */
                 LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
                 tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                return;
+                break;
             case 3: /* l.ror */
                 LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
                 tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-                return;
+                break;
+            default:
+                return gen_illegal_exception(dc);
             }
             break;
 
@@ -610,19 +619,21 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
             case 0: /* l.exths */
                 LOG_DIS("l.exths r%d, r%d\n", rd, ra);
                 tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
-                return;
+                break;
             case 1: /* l.extbs */
                 LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
                 tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
-                return;
+                break;
             case 2: /* l.exthz */
                 LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
                 tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
-                return;
+                break;
             case 3: /* l.extbz */
                 LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
                 tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
-                return;
+                break;
+            default:
+                return gen_illegal_exception(dc);
             }
             break;
 
@@ -631,11 +642,13 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
             case 0: /* l.extws */
                 LOG_DIS("l.extws r%d, r%d\n", rd, ra);
                 tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
-                return;
+                break;
             case 1: /* l.extwz */
                 LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
                 tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
-                return;
+                break;
+            default:
+                return gen_illegal_exception(dc);
             }
             break;
 
@@ -647,12 +660,15 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
                                    cpu_R[ra], cpu_R[rb]);
                 tcg_temp_free(zero);
             }
-            return;
+            break;
 
         case 0xf: /* l.ff1 */
             LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
             gen_helper_ff1(cpu_R[rd], cpu_R[ra]);
-            return;
+            break;
+
+        default:
+            return gen_illegal_exception(dc);
         }
         break;
 
@@ -661,19 +677,18 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         case 0xf: /* l.fl1 */
             LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
             gen_helper_fl1(cpu_R[rd], cpu_R[ra]);
-            return;
+            break;
+        default:
+            return gen_illegal_exception(dc);
         }
         break;
 
-    case 2:
-        break;
-
     case 3:
         switch (op0) {
         case 0x6: /* l.mul */
             LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
             gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0x7: /* l.muld */
             LOG_DIS("l.muld r%d, r%d\n", ra, rb);
@@ -683,29 +698,35 @@ static void dec_calc(DisasContext *dc, uint32_t insn)
         case 0x9: /* l.div */
             LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
             gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0xa: /* l.divu */
             LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
             gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0xb: /* l.mulu */
             LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
             gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
 
         case 0xc: /* l.muldu */
             LOG_DIS("l.muldu r%d, r%d\n", ra, rb);
             gen_muldu(dc, cpu_R[ra], cpu_R[rb]);
-            return;
+            break;
+
+        default:
+            return gen_illegal_exception(dc);
         }
         break;
+
+    default:
+        return gen_illegal_exception(dc);
     }
-    gen_illegal_exception(dc);
+    return JMP_NONE;
 }
 
-static void dec_misc(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_misc(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0, op1;
     uint32_t ra, rb, rd;
@@ -761,10 +782,8 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         case 0x01:    /* l.nop */
             LOG_DIS("l.nop %d\n", I16);
             break;
-
         default:
-            gen_illegal_exception(dc);
-            break;
+            return gen_illegal_exception(dc);
         }
         break;
 
@@ -787,19 +806,15 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x09:    /* l.rfe */
         LOG_DIS("l.rfe\n");
-        {
 #if defined(CONFIG_USER_ONLY)
-            return;
+        return gen_illegal_exception(dc);
 #else
-            if (dc->mem_idx == MMU_USER_IDX) {
-                gen_illegal_exception(dc);
-                return;
-            }
-            gen_helper_rfe(cpu_env);
-            dc->is_jmp = DISAS_UPDATE;
-#endif
+        if (dc->mem_idx == MMU_USER_IDX) {
+            return gen_illegal_exception(dc);
         }
-        break;
+        gen_helper_rfe(cpu_env);
+        return JMP_VAR;
+#endif
 
     case 0x1b: /* l.lwa */
         LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
@@ -971,12 +986,12 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
         break;
 
     default:
-        gen_illegal_exception(dc);
-        break;
+        return gen_illegal_exception(dc);
     }
+    return JMP_NONE;
 }
 
-static void dec_mac(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_mac(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
     uint32_t ra, rb;
@@ -1006,12 +1021,12 @@ static void dec_mac(DisasContext *dc, uint32_t insn)
         break;
 
     default:
-        gen_illegal_exception(dc);
-        break;
-   }
+        return gen_illegal_exception(dc);
+    }
+    return JMP_NONE;
 }
 
-static void dec_logic(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_logic(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
     uint32_t rd, ra, L6, S6;
@@ -1044,12 +1059,12 @@ static void dec_logic(DisasContext *dc, uint32_t insn)
         break;
 
     default:
-        gen_illegal_exception(dc);
-        break;
+        return gen_illegal_exception(dc);
     }
+    return JMP_NONE;
 }
 
-static void dec_M(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_M(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
     uint32_t rd;
@@ -1072,12 +1087,12 @@ static void dec_M(DisasContext *dc, uint32_t insn)
         break;
 
     default:
-        gen_illegal_exception(dc);
-        break;
+        return gen_illegal_exception(dc);
     }
+    return JMP_NONE;
 }
 
-static void dec_comp(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_comp(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
     uint32_t ra, rb;
@@ -1142,12 +1157,12 @@ static void dec_comp(DisasContext *dc, uint32_t insn)
         break;
 
     default:
-        gen_illegal_exception(dc);
-        break;
+        return gen_illegal_exception(dc);
     }
+    return JMP_NONE;
 }
 
-static void dec_compi(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_compi(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
     uint32_t ra;
@@ -1209,12 +1224,12 @@ static void dec_compi(DisasContext *dc, uint32_t insn)
         break;
 
     default:
-        gen_illegal_exception(dc);
-        break;
+        return gen_illegal_exception(dc);
     }
+    return JMP_NONE;
 }
 
-static void dec_sys(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_sys(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
     uint32_t K16;
@@ -1225,14 +1240,11 @@ static void dec_sys(DisasContext *dc, uint32_t insn)
     switch (op0) {
     case 0x000:    /* l.sys */
         LOG_DIS("l.sys %d\n", K16);
-        tcg_gen_movi_tl(cpu_pc, dc->pc);
         gen_exception(dc, EXCP_SYSCALL);
-        dc->is_jmp = DISAS_UPDATE;
         break;
 
     case 0x100:    /* l.trap */
         LOG_DIS("l.trap %d\n", K16);
-        tcg_gen_movi_tl(cpu_pc, dc->pc);
         gen_exception(dc, EXCP_TRAP);
         break;
 
@@ -1249,12 +1261,12 @@ static void dec_sys(DisasContext *dc, uint32_t insn)
         break;
 
     default:
-        gen_illegal_exception(dc);
-        break;
+        return gen_illegal_exception(dc);
     }
+    return JMP_NONE;
 }
 
-static void dec_float(DisasContext *dc, uint32_t insn)
+static JmpStatus dec_float(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0;
     uint32_t ra, rb, rd;
@@ -1469,12 +1481,12 @@ static void dec_float(DisasContext *dc, uint32_t insn)
 #endif
 
     default:
-        gen_illegal_exception(dc);
-        break;
+        return gen_illegal_exception(dc);
     }
+    return JMP_NONE;
 }
 
-static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
+static JmpStatus disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
 {
     uint32_t op0;
     uint32_t insn;
@@ -1483,40 +1495,23 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
 
     switch (op0) {
     case 0x06:
-        dec_M(dc, insn);
-        break;
-
+        return dec_M(dc, insn);
     case 0x08:
-        dec_sys(dc, insn);
-        break;
-
+        return dec_sys(dc, insn);
     case 0x2e:
-        dec_logic(dc, insn);
-        break;
-
+        return dec_logic(dc, insn);
     case 0x2f:
-        dec_compi(dc, insn);
-        break;
-
+        return dec_compi(dc, insn);
     case 0x31:
-        dec_mac(dc, insn);
-        break;
-
+        return dec_mac(dc, insn);
     case 0x32:
-        dec_float(dc, insn);
-        break;
-
+        return dec_float(dc, insn);
     case 0x38:
-        dec_calc(dc, insn);
-        break;
-
+        return dec_calc(dc, insn);
     case 0x39:
-        dec_comp(dc, insn);
-        break;
-
+        return dec_comp(dc, insn);
     default:
-        dec_misc(dc, insn);
-        break;
+        return dec_misc(dc, insn);
     }
 }
 
@@ -1529,16 +1524,17 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     uint32_t next_page_start;
     int num_insns;
     int max_insns;
+    JmpStatus exit;
 
     pc_start = tb->pc;
     dc->tb = tb;
 
-    dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
     dc->mem_idx = cpu_mmu_index(&cpu->env, false);
     dc->tb_flags = tb->flags;
-    dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
+    dc->dflag = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
     dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->jmp_type = JMP_VAR;
 
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
@@ -1566,14 +1562,12 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     }
 
     do {
-        tcg_gen_insn_start(dc->pc, (dc->delayed_branch ? 1 : 0)
-			   | (num_insns ? 2 : 0));
+        tcg_gen_insn_start(dc->pc, dc->dflag | (num_insns ? 2 : 0));
         num_insns++;
 
         if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
             tcg_gen_movi_tl(cpu_pc, dc->pc);
-            gen_exception(dc, EXCP_DEBUG);
-            dc->is_jmp = DISAS_UPDATE;
+            exit = gen_exception(dc, EXCP_DEBUG);
             /* The address covered by the breakpoint must be included in
                [tb->pc, tb->pc + tb->size) in order to for it to be
                properly cleared -- thus we increment the PC here so that
@@ -1585,20 +1579,19 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
-        disas_openrisc_insn(dc, cpu);
-        dc->pc = dc->pc + 4;
-
-        /* delay slot */
-        if (dc->delayed_branch) {
-            dc->delayed_branch--;
-            if (!dc->delayed_branch) {
-                tcg_gen_mov_tl(cpu_pc, jmp_pc);
-                tcg_gen_discard_tl(jmp_pc);
-                dc->is_jmp = DISAS_UPDATE;
-                break;
+
+        if (dc->dflag) {
+            /* In delay slot.  We will exit next.  */
+            exit = disas_openrisc_insn(dc, cpu);
+            dc->dflag = false;
+            if (exit != JMP_EXCP) {
+                exit = dc->jmp_type;
             }
+        } else {
+            exit = disas_openrisc_insn(dc, cpu);
         }
-    } while (!dc->is_jmp
+        dc->pc += 4;
+    } while (exit == JMP_NONE
              && !tcg_op_buf_full()
              && !cs->singlestep_enabled
              && !singlestep
@@ -1609,34 +1602,39 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         gen_io_end();
     }
 
-    if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
-        tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
+    if (dc->dflag != !!(dc->tb_flags & TB_FLAGS_DFLAG)) {
+        tcg_gen_movi_i32(cpu_dflag, dc->dflag);
     }
-
     tcg_gen_movi_tl(cpu_ppc, dc->pc - 4);
-    if (dc->is_jmp == DISAS_NEXT) {
-        dc->is_jmp = DISAS_UPDATE;
+
+    switch (exit) {
+    case JMP_NONE:
         tcg_gen_movi_tl(cpu_pc, dc->pc);
-    }
-    if (unlikely(cs->singlestep_enabled)) {
-        gen_exception(dc, EXCP_DEBUG);
-    } else {
-        switch (dc->is_jmp) {
-        case DISAS_NEXT:
-            gen_goto_tb(dc, 0, dc->pc);
-            break;
-        default:
-        case DISAS_JUMP:
-            break;
-        case DISAS_UPDATE:
-            /* indicate that the hash table must be used
-               to find the next TB */
+        if (unlikely(cs->singlestep_enabled)) {
+            gen_exception_1(EXCP_DEBUG);
+        } else {
             tcg_gen_exit_tb(0);
-            break;
-        case DISAS_TB_JUMP:
-            /* nothing more to generate */
-            break;
         }
+        break;
+    case JMP_VAR:
+        tcg_gen_mov_tl(cpu_pc, jmp_pc);
+        tcg_gen_discard_tl(jmp_pc);
+        if (unlikely(cs->singlestep_enabled)) {
+            gen_exception_1(EXCP_DEBUG);
+        } else {
+            tcg_gen_exit_tb(0);
+        }
+        break;
+    case JMP_DIRECT:
+        if (unlikely(cs->singlestep_enabled)) {
+            tcg_gen_movi_tl(cpu_pc, dc->jmp_dest[0]);
+            gen_exception_1(EXCP_DEBUG);
+        } else {
+            gen_goto_tb(dc, 0, dc->jmp_dest[0]);
+        }
+        break;
+    case JMP_EXCP:
+        break;
     }
 
     gen_tb_end(tb, num_insns);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 25/25] target-openrisc: Generate goto_tb for conditional branches
  2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
                   ` (23 preceding siblings ...)
  2016-06-13 23:58 ` [Qemu-devel] [PATCH 24/25] target-openrisc: Generate goto_tb for direct branches Richard Henderson
@ 2016-06-13 23:58 ` Richard Henderson
  24 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-06-13 23:58 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-openrisc/translate.c | 54 +++++++++++++++++++++++----------------------
 1 file changed, 28 insertions(+), 26 deletions(-)

diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 4d29d22..be95248 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -44,6 +44,7 @@ typedef enum {
     JMP_EXCP,
     JMP_VAR,
     JMP_DIRECT,
+    JMP_COND
 } JmpStatus;
 
 typedef struct DisasContext {
@@ -54,6 +55,7 @@ typedef struct DisasContext {
     bool dflag;
     bool singlestep_enabled;
     JmpStatus jmp_type;
+    TCGv jmp_cond;
     target_ulong jmp_dest[2];
 } DisasContext;
 
@@ -204,20 +206,11 @@ static JmpStatus gen_jump(DisasContext *dc, int32_t n26,
 
     case 0x03:     /* l.bnf */
     case 0x04:     /* l.bf  */
-        {
-            TCGv t_next = tcg_const_tl(dc->pc + 8);
-            TCGv t_true = tcg_const_tl(tmp_pc);
-            TCGv t_zero = tcg_const_tl(0);
-
-            tcg_gen_movcond_tl(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
-                               jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
-
-            tcg_temp_free(t_next);
-            tcg_temp_free(t_true);
-            tcg_temp_free(t_zero);
-
-            dc->jmp_type = JMP_VAR;
-        }
+        dc->jmp_type = JMP_COND;
+        dc->jmp_dest[op0 != 4] = tmp_pc;
+        dc->jmp_dest[op0 == 4] = dc->pc + 8;
+        dc->jmp_cond = tcg_temp_new();
+        tcg_gen_mov_tl(dc->jmp_cond, cpu_sr_f);
         break;
 
     case 0x11:     /* l.jr */
@@ -753,13 +746,11 @@ static JmpStatus dec_misc(DisasContext *dc, uint32_t insn)
     switch (op0) {
     case 0x00:    /* l.j */
         LOG_DIS("l.j %d\n", N26);
-        gen_jump(dc, N26, 0, op0);
-        break;
+        return gen_jump(dc, N26, 0, op0);
 
     case 0x01:    /* l.jal */
         LOG_DIS("l.jal %d\n", N26);
-        gen_jump(dc, N26, 0, op0);
-        break;
+        return gen_jump(dc, N26, 0, op0);
 
     case 0x02:    /* l.adrp */
         LOG_DIS("l.adrp r%d,%d\n", rd, N21);
@@ -769,13 +760,11 @@ static JmpStatus dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x03:    /* l.bnf */
         LOG_DIS("l.bnf %d\n", N26);
-        gen_jump(dc, N26, 0, op0);
-        break;
+        return gen_jump(dc, N26, 0, op0);
 
     case 0x04:    /* l.bf */
         LOG_DIS("l.bf %d\n", N26);
-        gen_jump(dc, N26, 0, op0);
-        break;
+        return gen_jump(dc, N26, 0, op0);
 
     case 0x05:
         switch (op1) {
@@ -789,13 +778,11 @@ static JmpStatus dec_misc(DisasContext *dc, uint32_t insn)
 
     case 0x11:    /* l.jr */
         LOG_DIS("l.jr r%d\n", rb);
-         gen_jump(dc, 0, rb, op0);
-         break;
+        return gen_jump(dc, 0, rb, op0);
 
     case 0x12:    /* l.jalr */
         LOG_DIS("l.jalr r%d\n", rb);
-        gen_jump(dc, 0, rb, op0);
-        break;
+        return gen_jump(dc, 0, rb, op0);
 
     case 0x13:    /* l.maci */
         LOG_DIS("l.maci r%d, %d\n", ra, I16);
@@ -1633,6 +1620,21 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
             gen_goto_tb(dc, 0, dc->jmp_dest[0]);
         }
         break;
+    case JMP_COND:
+        if (unlikely(cs->singlestep_enabled)) {
+            TCGv z = tcg_const_tl(0);
+            TCGv t = tcg_const_tl(dc->jmp_dest[0]);
+            TCGv f = tcg_const_tl(dc->jmp_dest[1]);
+            tcg_gen_movcond_tl(TCG_COND_NE, cpu_pc, dc->jmp_cond, z, t, f);
+            gen_exception_1(EXCP_DEBUG);
+        } else {
+            TCGLabel *lab = gen_new_label();
+            tcg_gen_brcondi_tl(TCG_COND_EQ, dc->jmp_cond, 0, lab);
+            gen_goto_tb(dc, 0, dc->jmp_dest[0]);
+            gen_set_label(lab);
+            gen_goto_tb(dc, 1, dc->jmp_dest[1]);
+        }
+        break;
     case JMP_EXCP:
         break;
     }
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2016-06-13 23:59 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-13 23:58 [Qemu-devel] [PATCH 00/25] target-openrisc improvements Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 01/25] target-openrisc: Always enable OPENRISC_DISAS Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 02/25] target-openrisc: Streamline arithmetic and OVE Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 03/25] target-openrisc: Invert the decoding in dec_calc Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 04/25] target-openrisc: Keep SR_F in a separate variable Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 05/25] target-openrisc: Use movcond where appropriate Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 06/25] target-openrisc: Put SR[OVE] in TB flags Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 07/25] target-openrisc: Keep SR_CY and SR_OV in a separate variables Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 08/25] target-openrisc: Set flags on helpers Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 09/25] target-openrisc: Implement ff1 and fl1 for 64-bit Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 10/25] target-openrisc: Represent MACHI:MACLO as a single unit Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 11/25] target-openrisc: Rationalize immediate extraction Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 12/25] target-openrisc: Enable m[tf]spr from user mode Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 13/25] target-openrisc: Enable trap, csync, msync, psync for " Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 14/25] target-openrisc: Implement muld, muldu, macu, msbu Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 15/25] target-openrisc: Fix madd Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 16/25] target-openrisc: Write back result before FPE exception Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 17/25] target-openrisc: Implement lwa, swa Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 18/25] target-openrisc: Implement l.adrp Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 19/25] target-openrisc: Tidy ppc/npc implementation Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 20/25] target-openrisc: Optimize l.jal to next Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 21/25] target-openrisc: Tidy insn dumping Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 22/25] target-openrisc: Tidy handling of delayed branches Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 23/25] target-openrisc: Optimize for r0 being zero Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 24/25] target-openrisc: Generate goto_tb for direct branches Richard Henderson
2016-06-13 23:58 ` [Qemu-devel] [PATCH 25/25] target-openrisc: Generate goto_tb for conditional branches Richard Henderson

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.