[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 07/17] target-openrisc: Keep SR_CY and SR_OV in a se
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH 07/17] target-openrisc: Keep SR_CY and SR_OV in a separate variables |
Date: |
Wed, 2 Sep 2015 17:17:33 -0700 |
This significantly streamlines carry and overflow production.
Signed-off-by: Richard Henderson <address@hidden>
---
target-openrisc/cpu.h | 13 +++-
target-openrisc/exception_helper.c | 33 ++++++++---
target-openrisc/helper.h | 5 +-
target-openrisc/int_helper.c | 36 -----------
target-openrisc/translate.c | 118 ++++++++++++-------------------------
5 files changed, 78 insertions(+), 127 deletions(-)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 8be53e4..99e6e08 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -289,7 +289,9 @@ typedef struct CPUOpenRISCState {
target_ulong eear; /* Exception EA register */
target_ulong sr_f; /* the SR_F bit */
- uint32_t sr; /* Supervisor register, without SR_F */
+ target_ulong sr_cy; /* the SR_CY bit */
+ 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 */
@@ -413,13 +415,18 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env)
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 efa3639..a08cf2d 100644
--- a/target-openrisc/exception_helper.c
+++ b/target-openrisc/exception_helper.c
@@ -28,14 +28,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 9711f42..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)
@@ -57,7 +59,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 6e27aeb..f75e1b3 100644
--- a/target-openrisc/int_helper.c
+++ b/target-openrisc/int_helper.c
@@ -41,39 +41,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 5813fde..c3eb3b1 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -55,6 +55,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;
@@ -87,6 +89,10 @@ void openrisc_translate_init(void)
offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
cpu_sr_f = tcg_global_mem_new(TCG_AREG0,
offsetof(CPUOpenRISCState, sr_f), "sr_f");
+ cpu_sr_cy = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
+ cpu_sr_ov = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
fpcsr = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUOpenRISCState, fpcsr),
"fpcsr");
@@ -237,27 +243,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);
}
}
@@ -265,143 +268,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.4.3
- Re: [Qemu-devel] [PATCH 05/17] target-openrisc: Use movcond where appropriate, (continued)
- [Qemu-devel] [PATCH 06/17] target-openrisc: Put SR[OVE] in TB flags, Richard Henderson, 2015/09/02
- [Qemu-devel] [PATCH 04/17] target-openrisc: Keep SR_F in a separate variable, Richard Henderson, 2015/09/02
- [Qemu-devel] [PATCH 08/17] target-openrisc: Set flags on helpers, Richard Henderson, 2015/09/02
- [Qemu-devel] [PATCH 09/17] target-openrisc: Implement ff1 and fl1 for 64-bit, Richard Henderson, 2015/09/02
- [Qemu-devel] [PATCH 07/17] target-openrisc: Keep SR_CY and SR_OV in a separate variables,
Richard Henderson <=
- [Qemu-devel] [PATCH 13/17] target-openrisc: Enable trap, csync, msync, psync for user mode, Richard Henderson, 2015/09/02
- [Qemu-devel] [PATCH 10/17] target-openrisc: Represent MACHI:MACLO as a single unit, Richard Henderson, 2015/09/02
- [Qemu-devel] [PATCH 12/17] target-openrisc: Enable m[tf]spr from user mode, Richard Henderson, 2015/09/02