This significantly streamlines carry and overflow production. Signed-off-by: Richard Henderson <r...@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