提交 48d38ca5 编写于 作者: T ths

Switch most MIPS logical and arithmetic instructions to TCG.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4496 c046a42c-6fe2-441c-8c8c-71466251a162
上级 8c99506c
......@@ -118,8 +118,6 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
void cpu_loop_exit(void);
void do_raise_exception_err (uint32_t exception, int error_code);
void do_raise_exception (uint32_t exception);
void do_raise_exception_direct_err (uint32_t exception, int error_code);
void do_raise_exception_direct (uint32_t exception);
void cpu_dump_state(CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
......
......@@ -167,251 +167,7 @@
#undef MEMSUFFIX
#endif
/* Addresses computation */
void op_addr_add (void)
{
/* For compatibility with 32-bit code, data reference in user mode
with Status_UX = 0 should be casted to 32-bit and sign extended.
See the MIPS64 PRA manual, section 4.10. */
#if defined(TARGET_MIPS64)
if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
!(env->CP0_Status & (1 << CP0St_UX)))
T0 = (int64_t)(int32_t)(T0 + T1);
else
#endif
T0 += T1;
FORCE_RET();
}
/* Arithmetic */
void op_add (void)
{
T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
FORCE_RET();
}
void op_addo (void)
{
target_ulong tmp;
tmp = (int32_t)T0;
T0 = (int32_t)T0 + (int32_t)T1;
if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
/* operands of same sign, result different sign */
CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
}
T0 = (int32_t)T0;
FORCE_RET();
}
void op_sub (void)
{
T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
FORCE_RET();
}
void op_subo (void)
{
target_ulong tmp;
tmp = (int32_t)T0;
T0 = (int32_t)T0 - (int32_t)T1;
if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
/* operands of different sign, first operand and result different sign */
CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
}
T0 = (int32_t)T0;
FORCE_RET();
}
void op_mul (void)
{
T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
FORCE_RET();
}
#if HOST_LONG_BITS < 64
void op_div (void)
{
CALL_FROM_TB0(do_div);
FORCE_RET();
}
#else
void op_div (void)
{
if (T1 != 0) {
env->LO[env->current_tc][0] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
env->HI[env->current_tc][0] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
}
FORCE_RET();
}
#endif
void op_divu (void)
{
if (T1 != 0) {
env->LO[env->current_tc][0] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
env->HI[env->current_tc][0] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
}
FORCE_RET();
}
#if defined(TARGET_MIPS64)
/* Arithmetic */
void op_dadd (void)
{
T0 += T1;
FORCE_RET();
}
void op_daddo (void)
{
target_long tmp;
tmp = T0;
T0 += T1;
if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
/* operands of same sign, result different sign */
CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
}
FORCE_RET();
}
void op_dsub (void)
{
T0 -= T1;
FORCE_RET();
}
void op_dsubo (void)
{
target_long tmp;
tmp = T0;
T0 = (int64_t)T0 - (int64_t)T1;
if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
/* operands of different sign, first operand and result different sign */
CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
}
FORCE_RET();
}
void op_dmul (void)
{
T0 = (int64_t)T0 * (int64_t)T1;
FORCE_RET();
}
/* Those might call libgcc functions. */
void op_ddiv (void)
{
do_ddiv();
FORCE_RET();
}
#if TARGET_LONG_BITS > HOST_LONG_BITS
void op_ddivu (void)
{
do_ddivu();
FORCE_RET();
}
#else
void op_ddivu (void)
{
if (T1 != 0) {
env->LO[env->current_tc][0] = T0 / T1;
env->HI[env->current_tc][0] = T0 % T1;
}
FORCE_RET();
}
#endif
#endif /* TARGET_MIPS64 */
/* Logical */
void op_and (void)
{
T0 &= T1;
FORCE_RET();
}
void op_nor (void)
{
T0 = ~(T0 | T1);
FORCE_RET();
}
void op_or (void)
{
T0 |= T1;
FORCE_RET();
}
void op_xor (void)
{
T0 ^= T1;
FORCE_RET();
}
void op_sll (void)
{
T0 = (int32_t)((uint32_t)T0 << T1);
FORCE_RET();
}
void op_sra (void)
{
T0 = (int32_t)((int32_t)T0 >> T1);
FORCE_RET();
}
void op_srl (void)
{
T0 = (int32_t)((uint32_t)T0 >> T1);
FORCE_RET();
}
void op_rotr (void)
{
target_ulong tmp;
if (T1) {
tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
}
FORCE_RET();
}
void op_sllv (void)
{
T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
FORCE_RET();
}
void op_srav (void)
{
T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
FORCE_RET();
}
void op_srlv (void)
{
T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
FORCE_RET();
}
void op_rotrv (void)
{
target_ulong tmp;
T0 &= 0x1F;
if (T0) {
tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
} else
T0 = T1;
FORCE_RET();
}
void op_clo (void)
{
T0 = clo32(T0);
......@@ -428,78 +184,6 @@ void op_clz (void)
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* Those might call libgcc functions. */
void op_dsll (void)
{
CALL_FROM_TB0(do_dsll);
FORCE_RET();
}
void op_dsll32 (void)
{
CALL_FROM_TB0(do_dsll32);
FORCE_RET();
}
void op_dsra (void)
{
CALL_FROM_TB0(do_dsra);
FORCE_RET();
}
void op_dsra32 (void)
{
CALL_FROM_TB0(do_dsra32);
FORCE_RET();
}
void op_dsrl (void)
{
CALL_FROM_TB0(do_dsrl);
FORCE_RET();
}
void op_dsrl32 (void)
{
CALL_FROM_TB0(do_dsrl32);
FORCE_RET();
}
void op_drotr (void)
{
CALL_FROM_TB0(do_drotr);
FORCE_RET();
}
void op_drotr32 (void)
{
CALL_FROM_TB0(do_drotr32);
FORCE_RET();
}
void op_dsllv (void)
{
CALL_FROM_TB0(do_dsllv);
FORCE_RET();
}
void op_dsrav (void)
{
CALL_FROM_TB0(do_dsrav);
FORCE_RET();
}
void op_dsrlv (void)
{
CALL_FROM_TB0(do_dsrlv);
FORCE_RET();
}
void op_drotrv (void)
{
CALL_FROM_TB0(do_drotrv);
FORCE_RET();
}
void op_dclo (void)
{
CALL_FROM_TB0(do_dclo);
......@@ -514,93 +198,6 @@ void op_dclz (void)
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
void op_dsll (void)
{
T0 = T0 << T1;
FORCE_RET();
}
void op_dsll32 (void)
{
T0 = T0 << (T1 + 32);
FORCE_RET();
}
void op_dsra (void)
{
T0 = (int64_t)T0 >> T1;
FORCE_RET();
}
void op_dsra32 (void)
{
T0 = (int64_t)T0 >> (T1 + 32);
FORCE_RET();
}
void op_dsrl (void)
{
T0 = T0 >> T1;
FORCE_RET();
}
void op_dsrl32 (void)
{
T0 = T0 >> (T1 + 32);
FORCE_RET();
}
void op_drotr (void)
{
target_ulong tmp;
if (T1) {
tmp = T0 << (0x40 - T1);
T0 = (T0 >> T1) | tmp;
}
FORCE_RET();
}
void op_drotr32 (void)
{
target_ulong tmp;
tmp = T0 << (0x40 - (32 + T1));
T0 = (T0 >> (32 + T1)) | tmp;
FORCE_RET();
}
void op_dsllv (void)
{
T0 = T1 << (T0 & 0x3F);
FORCE_RET();
}
void op_dsrav (void)
{
T0 = (int64_t)T1 >> (T0 & 0x3F);
FORCE_RET();
}
void op_dsrlv (void)
{
T0 = T1 >> (T0 & 0x3F);
FORCE_RET();
}
void op_drotrv (void)
{
target_ulong tmp;
T0 &= 0x3F;
if (T0) {
tmp = T1 << (0x40 - T0);
T0 = (T1 >> T0) | tmp;
} else
T0 = T1;
FORCE_RET();
}
void op_dclo (void)
{
T0 = clo64(T0);
......@@ -3063,31 +2660,6 @@ void op_save_pc64 (void)
}
#endif
void op_interrupt_restart (void)
{
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM) &&
(env->CP0_Status & (1 << CP0St_IE)) &&
(env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
}
FORCE_RET();
}
void op_raise_exception (void)
{
CALL_FROM_TB1(do_raise_exception, PARAM1);
FORCE_RET();
}
void op_raise_exception_err (void)
{
CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
FORCE_RET();
}
void op_wait (void)
{
env->halted = 1;
......@@ -3154,15 +2726,3 @@ void op_dshd(void)
FORCE_RET();
}
#endif
void op_seb(void)
{
T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
FORCE_RET();
}
void op_seh(void)
{
T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
FORCE_RET();
}
......@@ -48,6 +48,18 @@ void do_raise_exception (uint32_t exception)
do_raise_exception_err(exception, 0);
}
void do_interrupt_restart (void)
{
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM) &&
(env->CP0_Status & (1 << CP0St_IE)) &&
(env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
do_raise_exception(EXCP_EXT_INTERRUPT);
}
}
void do_restore_state (void *pc_ptr)
{
TranslationBlock *tb;
......@@ -59,17 +71,6 @@ void do_restore_state (void *pc_ptr)
}
}
void do_raise_exception_direct_err (uint32_t exception, int error_code)
{
do_restore_state (GETPC ());
do_raise_exception_err (exception, error_code);
}
void do_raise_exception_direct (uint32_t exception)
{
do_raise_exception_direct_err (exception, 0);
}
#if defined(TARGET_MIPS64)
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* Those might call libgcc functions. */
......@@ -300,45 +301,6 @@ void do_mulshiu (void)
}
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
#if HOST_LONG_BITS < 64
void do_div (void)
{
/* 64bit datatypes because we may see overflow/underflow. */
if (T1 != 0) {
env->LO[env->current_tc][0] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
env->HI[env->current_tc][0] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
}
}
#endif
#if defined(TARGET_MIPS64)
void do_ddiv (void)
{
if (T1 != 0) {
int64_t arg0 = (int64_t)T0;
int64_t arg1 = (int64_t)T1;
if (arg0 == ((int64_t)-1 << 63) && arg1 == (int64_t)-1) {
env->LO[env->current_tc][0] = arg0;
env->HI[env->current_tc][0] = 0;
} else {
lldiv_t res = lldiv(arg0, arg1);
env->LO[env->current_tc][0] = res.quot;
env->HI[env->current_tc][0] = res.rem;
}
}
}
#if TARGET_LONG_BITS > HOST_LONG_BITS
void do_ddivu (void)
{
if (T1 != 0) {
env->LO[env->current_tc][0] = T0 / T1;
env->HI[env->current_tc][0] = T0 % T1;
}
}
#endif
#endif /* TARGET_MIPS64 */
#if defined(CONFIG_USER_ONLY)
void do_mfc0_random (void)
{
......
此差异已折叠。
......@@ -1553,8 +1553,12 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
#endif
#if TCG_TARGET_REG_BITS == 32
#define tcg_gen_add_ptr tcg_gen_add_i32
#define tcg_gen_addi_ptr tcg_gen_addi_i32
#define tcg_gen_ext_i32_ptr tcg_gen_mov_i32
#else /* TCG_TARGET_REG_BITS == 32 */
#define tcg_gen_add_ptr tcg_gen_add_i64
#define tcg_gen_addi_ptr tcg_gen_addi_i64
#define tcg_gen_ext_i32_ptr tcg_gen_ext_i32_i64
#endif /* TCG_TARGET_REG_BITS != 32 */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册