Skip to content

Commit

Permalink
target-sparc: Move sdivx and udivx out of line
Browse files Browse the repository at this point in the history
The branches around the exception are maintaining an otherwise
unnecessary use of local temps for the cpu destination.

Signed-off-by: Richard Henderson <[email protected]>
Signed-off-by: Blue Swirl <[email protected]>
  • Loading branch information
rth7680 authored and blueswirl committed Oct 7, 2012
1 parent 6131674 commit c28ae41
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 52 deletions.
1 change: 1 addition & 0 deletions target-sparc/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@ trap_state* cpu_tsptr(CPUSPARCState* env);
void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr,
int is_write, int is_user,
uintptr_t retaddr);
void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr);

#define TB_FLAG_FPU_ENABLED (1 << 4)
#define TB_FLAG_AM_ENABLED (1 << 5)
Expand Down
28 changes: 28 additions & 0 deletions target-sparc/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
x1 = (b & 0xffffffff);

if (x1 == 0) {
cpu_restore_state2(env, GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}

Expand Down Expand Up @@ -113,6 +114,7 @@ static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
x1 = (b & 0xffffffff);

if (x1 == 0) {
cpu_restore_state2(env, GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}

Expand All @@ -139,3 +141,29 @@ target_ulong helper_sdiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
{
return helper_sdiv_common(env, a, b, 1);
}

#ifdef TARGET_SPARC64
int64_t helper_sdivx(CPUSPARCState *env, int64_t a, int64_t b)
{
if (b == 0) {
/* Raise divide by zero trap. */
cpu_restore_state2(env, GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
} else if (b == -1) {
/* Avoid overflow trap with i386 divide insn. */
return -a;
} else {
return a / b;
}
}

uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
{
if (b == 0) {
/* Raise divide by zero trap. */
cpu_restore_state2(env, GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}
return a / b;
}
#endif
4 changes: 4 additions & 0 deletions target-sparc/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
DEF_HELPER_3(sdiv, tl, env, tl, tl)
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
#ifdef TARGET_SPARC64
DEF_HELPER_3(sdivx, s64, env, s64, s64)
DEF_HELPER_3(udivx, i64, env, i64, i64)
#endif
DEF_HELPER_3(ldqf, void, env, tl, int)
DEF_HELPER_3(stqf, void, env, tl, int)
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
Expand Down
4 changes: 2 additions & 2 deletions target-sparc/ldst_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -2390,9 +2390,8 @@ void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
#endif
#endif

#if !defined(CONFIG_USER_ONLY)
/* XXX: make it generic ? */
static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
{
TranslationBlock *tb;

Expand All @@ -2407,6 +2406,7 @@ static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
}
}

#if !defined(CONFIG_USER_ONLY)
void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
int is_user, uintptr_t retaddr)
{
Expand Down
52 changes: 2 additions & 50 deletions target-sparc/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,44 +768,6 @@ static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
gen_op_multiply(dst, src1, src2, 1);
}

#ifdef TARGET_SPARC64
static inline void gen_trap_ifdivzero_tl(TCGv divisor)
{
TCGv_i32 r_const;
int l1;

l1 = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1);
r_const = tcg_const_i32(TT_DIV_ZERO);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
gen_set_label(l1);
}

static inline void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2)
{
int l1, l2;
TCGv r_temp1, r_temp2;

l1 = gen_new_label();
l2 = gen_new_label();
r_temp1 = tcg_temp_local_new();
r_temp2 = tcg_temp_local_new();
tcg_gen_mov_tl(r_temp1, src1);
tcg_gen_mov_tl(r_temp2, src2);
gen_trap_ifdivzero_tl(r_temp2);
tcg_gen_brcondi_tl(TCG_COND_NE, r_temp1, INT64_MIN, l1);
tcg_gen_brcondi_tl(TCG_COND_NE, r_temp2, -1, l1);
tcg_gen_movi_i64(dst, INT64_MIN);
tcg_gen_br(l2);
gen_set_label(l1);
tcg_gen_div_i64(dst, r_temp1, r_temp2);
gen_set_label(l2);
tcg_temp_free(r_temp1);
tcg_temp_free(r_temp2);
}
#endif

// 1
static inline void gen_op_eval_ba(TCGv dst)
{
Expand Down Expand Up @@ -3591,17 +3553,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
#ifdef TARGET_SPARC64
case 0xd: /* V9 udivx */
{
TCGv r_temp1, r_temp2;
r_temp1 = tcg_temp_local_new();
r_temp2 = tcg_temp_local_new();
tcg_gen_mov_tl(r_temp1, cpu_src1);
tcg_gen_mov_tl(r_temp2, cpu_src2);
gen_trap_ifdivzero_tl(r_temp2);
tcg_gen_divu_i64(cpu_dst, r_temp1, r_temp2);
tcg_temp_free(r_temp1);
tcg_temp_free(r_temp2);
}
gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
break;
#endif
case 0xe: /* udiv */
Expand Down Expand Up @@ -4102,7 +4054,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
}
case 0x2d: /* V9 sdivx */
gen_op_sdivx(cpu_dst, cpu_src1, cpu_src2);
gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x2e: /* V9 popc */
Expand Down

0 comments on commit c28ae41

Please sign in to comment.