diff options
author | ths <ths> | 2008-06-12 12:43:29 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-06-12 12:43:29 +0000 |
commit | f63c12c00a7249b642c48789ef66cd111deef82e (patch) | |
tree | cdf4b216c28dcb2f0f631bd0baedf451116baae5 /qemu/target-mips | |
parent | 18b59826e2eb51ca67ad80feb5a9e02f88ec5179 (diff) |
Switch the standard multiplication instructions to TCG.
Diffstat (limited to 'qemu/target-mips')
-rw-r--r-- | qemu/target-mips/exec.h | 2 | ||||
-rw-r--r-- | qemu/target-mips/helper.h | 2 | ||||
-rw-r--r-- | qemu/target-mips/op.c | 74 | ||||
-rw-r--r-- | qemu/target-mips/op_helper.c | 22 | ||||
-rw-r--r-- | qemu/target-mips/translate.c | 160 |
5 files changed, 166 insertions, 94 deletions
diff --git a/qemu/target-mips/exec.h b/qemu/target-mips/exec.h index 1aa4851c..782d7f8c 100644 --- a/qemu/target-mips/exec.h +++ b/qemu/target-mips/exec.h @@ -49,8 +49,6 @@ register target_ulong T1 asm(AREG2); #endif /* !defined(CONFIG_USER_ONLY) */ #if TARGET_LONG_BITS > HOST_LONG_BITS -void do_mult (void); -void do_multu (void); void do_madd (void); void do_maddu (void); void do_msub (void); diff --git a/qemu/target-mips/helper.h b/qemu/target-mips/helper.h index 246270a5..1092f873 100644 --- a/qemu/target-mips/helper.h +++ b/qemu/target-mips/helper.h @@ -11,6 +11,8 @@ DEF_HELPER(void, do_clz, (void)) #ifdef TARGET_MIPS64 DEF_HELPER(void, do_dclo, (void)) DEF_HELPER(void, do_dclz, (void)) +DEF_HELPER(void, do_dmult, (void)) +DEF_HELPER(void, do_dmultu, (void)) #endif /* CP0 helpers */ diff --git a/qemu/target-mips/op.c b/qemu/target-mips/op.c index 254973f5..2c99ad75 100644 --- a/qemu/target-mips/op.c +++ b/qemu/target-mips/op.c @@ -68,18 +68,6 @@ /* 64 bits arithmetic */ #if TARGET_LONG_BITS > HOST_LONG_BITS -void op_mult (void) -{ - CALL_FROM_TB0(do_mult); - FORCE_RET(); -} - -void op_multu (void) -{ - CALL_FROM_TB0(do_multu); - FORCE_RET(); -} - void op_madd (void) { CALL_FROM_TB0(do_madd); @@ -214,54 +202,6 @@ static always_inline void set_HI_LOT0 (uint64_t HILO) env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); } -void op_mult (void) -{ - set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); - FORCE_RET(); -} - -void op_multu (void) -{ - set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); - FORCE_RET(); -} - -void op_madd (void) -{ - int64_t tmp; - - tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); - set_HILO((int64_t)get_HILO() + tmp); - FORCE_RET(); -} - -void op_maddu (void) -{ - uint64_t tmp; - - tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); - set_HILO(get_HILO() + tmp); - FORCE_RET(); -} - -void op_msub (void) -{ - int64_t tmp; - - tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); - set_HILO((int64_t)get_HILO() - tmp); - FORCE_RET(); -} - -void op_msubu (void) -{ - uint64_t tmp; - - tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); - set_HILO(get_HILO() - tmp); - FORCE_RET(); -} - /* Multiplication variants of the vr54xx. */ void op_muls (void) { @@ -349,20 +289,6 @@ void op_mulshiu (void) #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */ -#if defined(TARGET_MIPS64) -void op_dmult (void) -{ - CALL_FROM_TB4(muls64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1); - FORCE_RET(); -} - -void op_dmultu (void) -{ - CALL_FROM_TB4(mulu64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1); - FORCE_RET(); -} -#endif - /* CP1 functions */ #if 0 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env) diff --git a/qemu/target-mips/op_helper.c b/qemu/target-mips/op_helper.c index 93cd55e0..c5a4c936 100644 --- a/qemu/target-mips/op_helper.c +++ b/qemu/target-mips/op_helper.c @@ -192,16 +192,6 @@ static always_inline void set_HI_LOT0 (uint64_t HILO) env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); } -void do_mult (void) -{ - set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); -} - -void do_multu (void) -{ - set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); -} - void do_madd (void) { int64_t tmp; @@ -306,6 +296,18 @@ void do_mulshiu (void) } #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */ +#ifdef TARGET_MIPS64 +void do_dmult (void) +{ + muls64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1); +} + +void do_dmultu (void) +{ + mulu64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1); +} +#endif + #ifdef CONFIG_USER_ONLY void do_mfc0_random (void) { diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 82e629e8..b7e3967c 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -1941,11 +1941,47 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, opn = "divu"; break; case OPC_MULT: - gen_op_mult(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); + tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); + tcg_temp_free(r_tmp2); + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); + tcg_temp_free(r_tmp1); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + gen_store_LO(cpu_T[0], 0); + gen_store_HI(cpu_T[1], 0); + } opn = "mult"; break; case OPC_MULTU: - gen_op_multu(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); + tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); + tcg_temp_free(r_tmp2); + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); + tcg_temp_free(r_tmp1); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + gen_store_LO(cpu_T[0], 0); + gen_store_HI(cpu_T[1], 0); + } opn = "multu"; break; #if defined(TARGET_MIPS64) @@ -2003,28 +2039,136 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, opn = "ddivu"; break; case OPC_DMULT: - gen_op_dmult(); + tcg_gen_helper_0_0(do_dmult); opn = "dmult"; break; case OPC_DMULTU: - gen_op_dmultu(); + tcg_gen_helper_0_0(do_dmultu); opn = "dmultu"; break; #endif case OPC_MADD: - gen_op_madd(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); + tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); + gen_load_LO(cpu_T[0], 0); + gen_load_HI(cpu_T[1], 0); + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); + tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); + tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); + tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); + tcg_temp_free(r_tmp3); + tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2); + tcg_temp_free(r_tmp2); + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); + tcg_temp_free(r_tmp1); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + gen_store_LO(cpu_T[0], 0); + gen_store_HI(cpu_T[1], 0); + } opn = "madd"; break; case OPC_MADDU: - gen_op_maddu(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); + tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); + gen_load_LO(cpu_T[0], 0); + gen_load_HI(cpu_T[1], 0); + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); + tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); + tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); + tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); + tcg_temp_free(r_tmp3); + tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2); + tcg_temp_free(r_tmp2); + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); + tcg_temp_free(r_tmp1); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + gen_store_LO(cpu_T[0], 0); + gen_store_HI(cpu_T[1], 0); + } opn = "maddu"; break; case OPC_MSUB: - gen_op_msub(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); + tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); + gen_load_LO(cpu_T[0], 0); + gen_load_HI(cpu_T[1], 0); + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); + tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); + tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); + tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); + tcg_temp_free(r_tmp3); + tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2); + tcg_temp_free(r_tmp2); + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); + tcg_temp_free(r_tmp1); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + gen_store_LO(cpu_T[0], 0); + gen_store_HI(cpu_T[1], 0); + } opn = "msub"; break; case OPC_MSUBU: - gen_op_msubu(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); + tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); + gen_load_LO(cpu_T[0], 0); + gen_load_HI(cpu_T[1], 0); + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); + tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); + tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); + tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); + tcg_temp_free(r_tmp3); + tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2); + tcg_temp_free(r_tmp2); + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); + tcg_temp_free(r_tmp1); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + gen_store_LO(cpu_T[0], 0); + gen_store_HI(cpu_T[1], 0); + } opn = "msubu"; break; default: |