diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-18 22:50:49 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-18 22:50:49 +0000 |
commit | 48d38ca52b6d9c33066e139226eba2966d0c88d3 (patch) | |
tree | a49cb7ec85b954a2d7154eacb1f5f1b338af05c4 /target-mips | |
parent | 8c99506cfbf61da72fa007b972636b43db21fb2e (diff) | |
download | qemu-48d38ca52b6d9c33066e139226eba2966d0c88d3.zip |
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
Diffstat (limited to 'target-mips')
-rw-r--r-- | target-mips/exec.h | 2 | ||||
-rw-r--r-- | target-mips/op.c | 440 | ||||
-rw-r--r-- | target-mips/op_helper.c | 62 | ||||
-rw-r--r-- | target-mips/translate.c | 509 |
4 files changed, 436 insertions, 577 deletions
diff --git a/target-mips/exec.h b/target-mips/exec.h index c353af06ea..f10a35df03 100644 --- a/target-mips/exec.h +++ b/target-mips/exec.h @@ -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, ...), diff --git a/target-mips/op.c b/target-mips/op.c index fda0c38966..c7162d6850 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -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(); -} diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index c126a7768e..3bb80954e8 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -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) { diff --git a/target-mips/translate.c b/target-mips/translate.c index e3b1a66de6..dbd9c9f715 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -29,6 +29,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "helper.h" #include "tcg-op.h" #include "qemu-common.h" @@ -833,40 +834,47 @@ static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx) } static always_inline void -generate_tcg_exception_err (DisasContext *ctx, int excp, int err) +generate_exception_err (DisasContext *ctx, int excp, int err) { save_cpu_state(ctx, 1); - if (err == 0) - gen_op_raise_exception(excp); - else - gen_op_raise_exception_err(excp, err); - gen_op_interrupt_restart(); + tcg_gen_helper_0_2(do_raise_exception_err, tcg_const_i32(excp), tcg_const_i32(err)); + tcg_gen_helper_0_0(do_interrupt_restart); tcg_gen_exit_tb(0); } static always_inline void -generate_tcg_exception (DisasContext *ctx, int excp) +generate_exception (DisasContext *ctx, int excp) { - generate_tcg_exception_err (ctx, excp, 0); -} - -static always_inline void generate_exception_err (DisasContext *ctx, int excp, int err) -{ -#if defined MIPS_DEBUG_DISAS - if (loglevel & CPU_LOG_TB_IN_ASM) - fprintf(logfile, "%s: raise exception %d\n", __func__, excp); -#endif save_cpu_state(ctx, 1); - if (err == 0) - gen_op_raise_exception(excp); - else - gen_op_raise_exception_err(excp, err); - ctx->bstate = BS_EXCP; + tcg_gen_helper_0_1(do_raise_exception, tcg_const_i32(excp)); + tcg_gen_helper_0_0(do_interrupt_restart); + tcg_gen_exit_tb(0); } -static always_inline void generate_exception (DisasContext *ctx, int excp) +/* Addresses computation */ +static inline void gen_op_addr_add (void) { - generate_exception_err (ctx, excp, 0); + tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + +#if defined(TARGET_MIPS64) + /* 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. */ + { + TCGv r_tmp = new_tmp(); + int l1 = gen_new_label(); + + tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, hflags)); + tcg_gen_andi_i32(r_tmp, r_tmp, MIPS_HFLAG_KSU); + tcg_gen_brcond_i32(TCG_COND_NE, r_tmp, tcg_const_i32(MIPS_HFLAG_UM), l1); + tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_Status)); + tcg_gen_andi_i32(r_tmp, r_tmp, (1 << CP0St_UX)); + tcg_gen_brcond_i32(TCG_COND_NE, r_tmp, tcg_const_i32(0), l1); + tcg_gen_ext32s_i64(cpu_T[0], cpu_T[0]); + gen_set_label(l1); + dead_tmp(r_tmp); + } +#endif } static always_inline void check_cp0_enabled(DisasContext *ctx) @@ -1024,7 +1032,7 @@ void inline op_ldst_##insn(DisasContext *ctx) \ tcg_gen_andi_tl(r_tmp, cpu_T[0], almask); \ tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp, tcg_const_tl(0), l1); \ tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr)); \ - generate_tcg_exception(ctx, EXCP_AdES); \ + generate_exception(ctx, EXCP_AdES); \ gen_set_label(l1); \ tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ tcg_gen_brcond_tl(TCG_COND_NE, cpu_T[0], r_tmp, l2); \ @@ -1282,12 +1290,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, case OPC_SLTI: case OPC_SLTIU: uimm = (target_long)imm; /* Sign extend to 32/64 bits */ + GEN_LOAD_IMM_TN(T1, uimm); /* Fall through. */ case OPC_ANDI: case OPC_ORI: case OPC_XORI: GEN_LOAD_REG_T0(rs); - GEN_LOAD_IMM_TN(T1, uimm); break; case OPC_LUI: GEN_LOAD_IMM_TN(T0, imm << 16); @@ -1305,27 +1313,64 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, #endif uimm &= 0x1f; GEN_LOAD_REG_T0(rs); - GEN_LOAD_IMM_TN(T1, uimm); break; } switch (opc) { case OPC_ADDI: - save_cpu_state(ctx, 1); - gen_op_addo(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL); + int l1 = gen_new_label(); + + save_cpu_state(ctx, 1); + tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]); + tcg_gen_addi_tl(cpu_T[0], r_tmp1, uimm); + + tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm); + tcg_gen_xori_tl(r_tmp1, r_tmp1, -1); + tcg_gen_xori_tl(r_tmp2, cpu_T[0], uimm); + tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_shri_tl(r_tmp1, r_tmp1, 31); + tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp1, tcg_const_tl(0), l1); + /* operands of same sign, result different sign */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + } opn = "addi"; break; case OPC_ADDIU: - gen_op_add(); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "addiu"; break; #if defined(TARGET_MIPS64) case OPC_DADDI: - save_cpu_state(ctx, 1); - gen_op_daddo(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL); + int l1 = gen_new_label(); + + save_cpu_state(ctx, 1); + tcg_gen_mov_tl(r_tmp1, cpu_T[0]); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm); + + tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm); + tcg_gen_xori_tl(r_tmp1, r_tmp1, -1); + tcg_gen_xori_tl(r_tmp2, cpu_T[0], uimm); + tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_shri_tl(r_tmp1, r_tmp1, 63); + tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp1, tcg_const_tl(0), l1); + /* operands of same sign, result different sign */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + } opn = "daddi"; break; case OPC_DADDIU: - gen_op_dadd(); + tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm); opn = "daddiu"; break; #endif @@ -1338,41 +1383,62 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, opn = "sltiu"; break; case OPC_ANDI: - gen_op_and(); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], uimm); opn = "andi"; break; case OPC_ORI: - gen_op_or(); + tcg_gen_ori_tl(cpu_T[0], cpu_T[0], uimm); opn = "ori"; break; case OPC_XORI: - gen_op_xor(); + tcg_gen_xori_tl(cpu_T[0], cpu_T[0], uimm); opn = "xori"; break; case OPC_LUI: opn = "lui"; break; case OPC_SLL: - gen_op_sll(); + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); + tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "sll"; break; case OPC_SRA: - gen_op_sra(); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "sra"; break; case OPC_SRL: switch ((ctx->opcode >> 21) & 0x1f) { case 0: - gen_op_srl(); + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); + tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "srl"; break; case 1: /* rotr is decoded as srl on non-R2 CPUs */ if (env->insn_flags & ISA_MIPS32R2) { - gen_op_rotr(); + if (uimm != 0) { + TCGv r_tmp1 = new_tmp(); + TCGv r_tmp2 = new_tmp(); + + tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]); + tcg_gen_movi_i32(r_tmp2, 0x20); + tcg_gen_subi_i32(r_tmp2, r_tmp2, uimm); + tcg_gen_shl_i32(r_tmp2, r_tmp1, r_tmp2); + tcg_gen_shri_i32(r_tmp1, r_tmp1, uimm); + tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_ext_i32_tl(r_tmp1, cpu_T[0]); + dead_tmp(r_tmp1); + dead_tmp(r_tmp2); + } opn = "rotr"; } else { - gen_op_srl(); + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); + tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "srl"; } break; @@ -1384,26 +1450,34 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, break; #if defined(TARGET_MIPS64) case OPC_DSLL: - gen_op_dsll(); + tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm); opn = "dsll"; break; case OPC_DSRA: - gen_op_dsra(); + tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm); opn = "dsra"; break; case OPC_DSRL: switch ((ctx->opcode >> 21) & 0x1f) { case 0: - gen_op_dsrl(); + tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); opn = "dsrl"; break; case 1: /* drotr is decoded as dsrl on non-R2 CPUs */ if (env->insn_flags & ISA_MIPS32R2) { - gen_op_drotr(); + if (uimm != 0) { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + + tcg_gen_movi_tl(r_tmp1, 0x40); + tcg_gen_subi_tl(r_tmp1, r_tmp1, uimm); + tcg_gen_shl_tl(r_tmp1, cpu_T[0], r_tmp1); + tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); + tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1); + } opn = "drotr"; } else { - gen_op_dsrl(); + tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); opn = "dsrl"; } break; @@ -1414,26 +1488,35 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, } break; case OPC_DSLL32: - gen_op_dsll32(); + tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm + 32); opn = "dsll32"; break; case OPC_DSRA32: - gen_op_dsra32(); + tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm + 32); opn = "dsra32"; break; case OPC_DSRL32: switch ((ctx->opcode >> 21) & 0x1f) { case 0: - gen_op_dsrl32(); + tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32); opn = "dsrl32"; break; case 1: /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ if (env->insn_flags & ISA_MIPS32R2) { - gen_op_drotr32(); + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL); + + tcg_gen_movi_tl(r_tmp1, 0x40); + tcg_gen_movi_tl(r_tmp2, 32); + tcg_gen_addi_tl(r_tmp2, r_tmp2, uimm); + tcg_gen_sub_tl(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_shl_tl(r_tmp1, cpu_T[0], r_tmp1); + tcg_gen_shr_tl(cpu_T[0], cpu_T[0], r_tmp2); + tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1); opn = "drotr32"; } else { - gen_op_dsrl32(); + tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32); opn = "dsrl32"; } break; @@ -1476,40 +1559,118 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, GEN_LOAD_REG_T1(rt); switch (opc) { case OPC_ADD: - save_cpu_state(ctx, 1); - gen_op_addo(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL); + int l1 = gen_new_label(); + + save_cpu_state(ctx, 1); + tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]); + tcg_gen_ext32s_tl(r_tmp2, cpu_T[1]); + tcg_gen_add_tl(cpu_T[0], r_tmp1, r_tmp2); + + tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[1]); + tcg_gen_xori_tl(r_tmp1, r_tmp1, -1); + tcg_gen_xor_tl(r_tmp2, cpu_T[0], cpu_T[1]); + tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_shri_tl(r_tmp1, r_tmp1, 31); + tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp1, tcg_const_tl(0), l1); + /* operands of same sign, result different sign */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + } opn = "add"; break; case OPC_ADDU: - gen_op_add(); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "addu"; break; case OPC_SUB: - save_cpu_state(ctx, 1); - gen_op_subo(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL); + int l1 = gen_new_label(); + + save_cpu_state(ctx, 1); + tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]); + tcg_gen_ext32s_tl(r_tmp2, cpu_T[1]); + tcg_gen_sub_tl(cpu_T[0], r_tmp1, r_tmp2); + + tcg_gen_xor_tl(r_tmp2, r_tmp1, cpu_T[1]); + tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[0]); + tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_shri_tl(r_tmp1, r_tmp1, 31); + tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp1, tcg_const_tl(0), l1); + /* operands of different sign, first operand and result different sign */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + } opn = "sub"; break; case OPC_SUBU: - gen_op_sub(); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "subu"; break; #if defined(TARGET_MIPS64) case OPC_DADD: - save_cpu_state(ctx, 1); - gen_op_daddo(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL); + int l1 = gen_new_label(); + + save_cpu_state(ctx, 1); + tcg_gen_mov_tl(r_tmp1, cpu_T[0]); + tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + + tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[1]); + tcg_gen_xori_tl(r_tmp1, r_tmp1, -1); + tcg_gen_xor_tl(r_tmp2, cpu_T[0], cpu_T[1]); + tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_shri_tl(r_tmp1, r_tmp1, 63); + tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp1, tcg_const_tl(0), l1); + /* operands of same sign, result different sign */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + } opn = "dadd"; break; case OPC_DADDU: - gen_op_dadd(); + tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); opn = "daddu"; break; case OPC_DSUB: - save_cpu_state(ctx, 1); - gen_op_dsubo(); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL); + int l1 = gen_new_label(); + + save_cpu_state(ctx, 1); + tcg_gen_mov_tl(r_tmp1, cpu_T[0]); + tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + + tcg_gen_xor_tl(r_tmp2, r_tmp1, cpu_T[1]); + tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[0]); + tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_shri_tl(r_tmp1, r_tmp1, 63); + tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp1, tcg_const_tl(0), l1); + /* operands of different sign, first operand and result different sign */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + } opn = "dsub"; break; case OPC_DSUBU: - gen_op_dsub(); + tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); opn = "dsubu"; break; #endif @@ -1522,23 +1683,27 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, opn = "sltu"; break; case OPC_AND: - gen_op_and(); + tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); opn = "and"; break; case OPC_NOR: - gen_op_nor(); + tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + tcg_gen_not_tl(cpu_T[0], cpu_T[0]); opn = "nor"; break; case OPC_OR: - gen_op_or(); + tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); opn = "or"; break; case OPC_XOR: - gen_op_xor(); + tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); opn = "xor"; break; case OPC_MUL: - gen_op_mul(); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "mul"; break; case OPC_MOVN: @@ -1550,26 +1715,64 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, opn = "movz"; goto print; case OPC_SLLV: - gen_op_sllv(); + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); + tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "sllv"; break; case OPC_SRAV: - gen_op_srav(); + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); + tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "srav"; break; case OPC_SRLV: switch ((ctx->opcode >> 6) & 0x1f) { case 0: - gen_op_srlv(); + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); + tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "srlv"; break; case 1: /* rotrv is decoded as srlv on non-R2 CPUs */ if (env->insn_flags & ISA_MIPS32R2) { - gen_op_rotrv(); + int l1 = gen_new_label(); + int l2 = gen_new_label(); + + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[0], tcg_const_tl(0), l1); + { + TCGv r_tmp1 = new_tmp(); + TCGv r_tmp2 = new_tmp(); + TCGv r_tmp3 = new_tmp(); + + tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]); + tcg_gen_trunc_tl_i32(r_tmp2, cpu_T[1]); + tcg_gen_movi_i32(r_tmp3, 0x20); + tcg_gen_sub_i32(r_tmp3, r_tmp3, r_tmp1); + tcg_gen_shl_i32(r_tmp3, r_tmp2, r_tmp3); + tcg_gen_shr_i32(r_tmp1, r_tmp2, r_tmp1); + tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp3); + tcg_gen_ext_i32_tl(r_tmp1, cpu_T[0]); + dead_tmp(r_tmp1); + dead_tmp(r_tmp2); + dead_tmp(r_tmp3); + tcg_gen_br(l2); + } + gen_set_label(l1); + tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); + gen_set_label(l2); opn = "rotrv"; } else { - gen_op_srlv(); + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); + tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); opn = "srlv"; } break; @@ -1581,26 +1784,47 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, break; #if defined(TARGET_MIPS64) case OPC_DSLLV: - gen_op_dsllv(); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); + tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]); opn = "dsllv"; break; case OPC_DSRAV: - gen_op_dsrav(); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); + tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]); opn = "dsrav"; break; case OPC_DSRLV: switch ((ctx->opcode >> 6) & 0x1f) { case 0: - gen_op_dsrlv(); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); + tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); opn = "dsrlv"; break; case 1: /* drotrv is decoded as dsrlv on non-R2 CPUs */ if (env->insn_flags & ISA_MIPS32R2) { - gen_op_drotrv(); + int l1 = gen_new_label(); + int l2 = gen_new_label(); + + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[0], tcg_const_tl(0), l1); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); + + tcg_gen_movi_tl(r_tmp1, 0x40); + tcg_gen_sub_tl(r_tmp1, r_tmp1, cpu_T[0]); + tcg_gen_shl_tl(r_tmp1, cpu_T[1], r_tmp1); + tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); + tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1); + tcg_gen_br(l2); + } + gen_set_label(l1); + tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); + gen_set_label(l2); opn = "drotrv"; } else { - gen_op_dsrlv(); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); + tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); opn = "dsrlv"; } break; @@ -1669,11 +1893,71 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, GEN_LOAD_REG_T1(rt); switch (opc) { case OPC_DIV: - gen_op_div(); + { + int l1 = gen_new_label(); + + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[1], tcg_const_tl(0), l1); + { + TCGv r_tmp1 = new_tmp(); + TCGv r_tmp2 = new_tmp(); + TCGv r_tmp3 = new_tmp(); + TCGv r_tc_off = new_tmp(); + TCGv r_tc_off_tl = tcg_temp_new(TCG_TYPE_TL); + TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR); + + tcg_gen_ext_i32_tl(r_tmp1, cpu_T[0]); + tcg_gen_ext_i32_tl(r_tmp2, cpu_T[1]); + tcg_gen_div_i32(r_tmp3, r_tmp1, r_tmp2); + tcg_gen_rem_i32(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_trunc_tl_i32(cpu_T[0], r_tmp3); + tcg_gen_trunc_tl_i32(cpu_T[1], r_tmp1); + dead_tmp(r_tmp1); + dead_tmp(r_tmp2); + dead_tmp(r_tmp3); + tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc)); + tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong)); + tcg_gen_ext_i32_ptr(r_tc_off_tl, r_tc_off); + tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_tl); + tcg_gen_st_tl(cpu_T[0], r_ptr, offsetof(CPUState, LO)); + tcg_gen_st_tl(cpu_T[1], r_ptr, offsetof(CPUState, HI)); + dead_tmp(r_tc_off); + } + gen_set_label(l1); + } opn = "div"; break; case OPC_DIVU: - gen_op_divu(); + { + int l1 = gen_new_label(); + + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[1], tcg_const_tl(0), l1); + { + TCGv r_tmp1 = new_tmp(); + TCGv r_tmp2 = new_tmp(); + TCGv r_tmp3 = new_tmp(); + TCGv r_tc_off = new_tmp(); + TCGv r_tc_off_tl = tcg_temp_new(TCG_TYPE_TL); + TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR); + + tcg_gen_ext_i32_tl(r_tmp1, cpu_T[0]); + tcg_gen_ext_i32_tl(r_tmp2, cpu_T[1]); + tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2); + tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2); + tcg_gen_trunc_tl_i32(cpu_T[0], r_tmp3); + tcg_gen_trunc_tl_i32(cpu_T[1], r_tmp1); + dead_tmp(r_tmp1); + dead_tmp(r_tmp2); + dead_tmp(r_tmp3); + tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc)); + tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong)); + tcg_gen_ext_i32_ptr(r_tc_off_tl, r_tc_off); + tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_tl); + tcg_gen_st_tl(cpu_T[0], r_ptr, offsetof(CPUState, LO)); + tcg_gen_st_tl(cpu_T[1], r_ptr, offsetof(CPUState, HI)); + dead_tmp(r_tc_off); + } + gen_set_label(l1); + } opn = "divu"; break; case OPC_MULT: @@ -1686,11 +1970,63 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, break; #if defined(TARGET_MIPS64) case OPC_DDIV: - gen_op_ddiv(); + { + int l1 = gen_new_label(); + + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[1], tcg_const_tl(0), l1); + { + TCGv r_tc_off = new_tmp(); + TCGv r_tc_off_tl = tcg_temp_new(TCG_TYPE_TL); + TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR); + int l2 = gen_new_label(); + int l3 = gen_new_label(); + + tcg_gen_brcond_tl(TCG_COND_NE, cpu_T[0], tcg_const_tl(1ULL << 63), l2); + tcg_gen_brcond_tl(TCG_COND_NE, cpu_T[1], tcg_const_tl(-1ULL), l2); + tcg_gen_div_i64(cpu_T[0], cpu_T[0], cpu_T[1]); + tcg_gen_movi_tl(cpu_T[1], 0); + tcg_gen_br(l3); + gen_set_label(l2); + tcg_gen_div_i64(cpu_T[0], cpu_T[0], cpu_T[1]); + tcg_gen_rem_i64(cpu_T[1], cpu_T[0], cpu_T[1]); + gen_set_label(l3); + + tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc)); + tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong)); + tcg_gen_ext_i32_ptr(r_tc_off_tl, r_tc_off); + tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_tl); + tcg_gen_st_tl(cpu_T[0], r_ptr, offsetof(CPUState, LO)); + tcg_gen_st_tl(cpu_T[1], r_ptr, offsetof(CPUState, HI)); + dead_tmp(r_tc_off); + } + gen_set_label(l1); + } opn = "ddiv"; break; case OPC_DDIVU: - gen_op_ddivu(); + { + int l1 = gen_new_label(); + + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[1], tcg_const_tl(0), l1); + { + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); + TCGv r_tc_off = new_tmp(); + TCGv r_tc_off_tl = tcg_temp_new(TCG_TYPE_TL); + TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR); + + tcg_gen_divu_i64(r_tmp1, cpu_T[0], cpu_T[1]); + tcg_gen_remu_i64(r_tmp2, cpu_T[0], cpu_T[1]); + tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc)); + tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong)); + tcg_gen_ext_i32_ptr(r_tc_off_tl, r_tc_off); + tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_tl); + tcg_gen_st_tl(r_tmp1, r_ptr, offsetof(CPUState, LO)); + tcg_gen_st_tl(r_tmp2, r_ptr, offsetof(CPUState, HI)); + dead_tmp(r_tc_off); + } + gen_set_label(l1); + } opn = "ddivu"; break; case OPC_DMULT: @@ -6424,11 +6760,11 @@ static void decode_opc (CPUState *env, DisasContext *ctx) break; case OPC_SEB: GEN_LOAD_REG_T1(rt); - gen_op_seb(); + tcg_gen_ext8s_tl(cpu_T[0], cpu_T[1]); break; case OPC_SEH: GEN_LOAD_REG_T1(rt); - gen_op_seh(); + tcg_gen_ext16s_tl(cpu_T[0], cpu_T[1]); break; default: /* Invalid */ MIPS_INVAL("bshfl"); @@ -6837,6 +7173,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, num_temps = 0; memset(temps, 0, sizeof(temps)); + num_temps = 0; + memset(temps, 0, sizeof(temps)); + pc_start = tb->pc; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; ctx.pc = pc_start; @@ -6915,7 +7254,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } else { switch (ctx.bstate) { case BS_STOP: - gen_op_interrupt_restart(); + tcg_gen_helper_0_0(do_interrupt_restart); gen_goto_tb(&ctx, 0, ctx.pc); break; case BS_NONE: @@ -6923,7 +7262,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_goto_tb(&ctx, 0, ctx.pc); break; case BS_EXCP: - gen_op_interrupt_restart(); + tcg_gen_helper_0_0(do_interrupt_restart); tcg_gen_exit_tb(0); break; case BS_BRANCH: |