提交 78723684 编写于 作者: T ths

Reduce use of fixed registers a bit more.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4786 c046a42c-6fe2-441c-8c8c-71466251a162
上级 a764a566
...@@ -1088,158 +1088,163 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, ...@@ -1088,158 +1088,163 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
int base, int16_t offset) int base, int16_t offset)
{ {
const char *opn = "ldst"; const char *opn = "ldst";
TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
if (base == 0) { if (base == 0) {
tcg_gen_movi_tl(cpu_T[0], offset); tcg_gen_movi_tl(t0, offset);
} else if (offset == 0) { } else if (offset == 0) {
gen_load_gpr(cpu_T[0], base); gen_load_gpr(t0, base);
} else { } else {
gen_load_gpr(cpu_T[0], base); gen_load_gpr(t0, base);
tcg_gen_movi_tl(cpu_T[1], offset); tcg_gen_movi_tl(t1, offset);
gen_op_addr_add(cpu_T[0], cpu_T[1]); gen_op_addr_add(t0, t1);
} }
/* Don't do NOP if destination is zero: we must perform the actual /* Don't do NOP if destination is zero: we must perform the actual
memory access. */ memory access. */
switch (opc) { switch (opc) {
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
case OPC_LWU: case OPC_LWU:
op_ldst_lwu(cpu_T[0], ctx); op_ldst_lwu(t0, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "lwu"; opn = "lwu";
break; break;
case OPC_LD: case OPC_LD:
op_ldst_ld(cpu_T[0], ctx); op_ldst_ld(t0, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "ld"; opn = "ld";
break; break;
case OPC_LLD: case OPC_LLD:
op_ldst_lld(cpu_T[0], cpu_T[1], ctx); op_ldst_lld(t0, t1, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "lld"; opn = "lld";
break; break;
case OPC_SD: case OPC_SD:
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
op_ldst_sd(cpu_T[0], cpu_T[1], ctx); op_ldst_sd(t0, t1, ctx);
opn = "sd"; opn = "sd";
break; break;
case OPC_SCD: case OPC_SCD:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
op_ldst_scd(cpu_T[0], cpu_T[1], ctx); op_ldst_scd(t0, t1, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "scd"; opn = "scd";
break; break;
case OPC_LDL: case OPC_LDL:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
tcg_gen_helper_1_2i(do_ldl, cpu_T[1], cpu_T[0], cpu_T[1], ctx->mem_idx); tcg_gen_helper_1_2i(do_ldl, t1, t0, t1, ctx->mem_idx);
gen_store_gpr(cpu_T[1], rt); gen_store_gpr(t1, rt);
opn = "ldl"; opn = "ldl";
break; break;
case OPC_SDL: case OPC_SDL:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
tcg_gen_helper_0_2i(do_sdl, cpu_T[0], cpu_T[1], ctx->mem_idx); tcg_gen_helper_0_2i(do_sdl, t0, t1, ctx->mem_idx);
opn = "sdl"; opn = "sdl";
break; break;
case OPC_LDR: case OPC_LDR:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
tcg_gen_helper_1_2i(do_ldr, cpu_T[1], cpu_T[0], cpu_T[1], ctx->mem_idx); tcg_gen_helper_1_2i(do_ldr, t1, t0, t1, ctx->mem_idx);
gen_store_gpr(cpu_T[1], rt); gen_store_gpr(t1, rt);
opn = "ldr"; opn = "ldr";
break; break;
case OPC_SDR: case OPC_SDR:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
tcg_gen_helper_0_2i(do_sdr, cpu_T[0], cpu_T[1], ctx->mem_idx); tcg_gen_helper_0_2i(do_sdr, t0, t1, ctx->mem_idx);
opn = "sdr"; opn = "sdr";
break; break;
#endif #endif
case OPC_LW: case OPC_LW:
op_ldst_lw(cpu_T[0], ctx); op_ldst_lw(t0, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "lw"; opn = "lw";
break; break;
case OPC_SW: case OPC_SW:
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
op_ldst_sw(cpu_T[0], cpu_T[1], ctx); op_ldst_sw(t0, t1, ctx);
opn = "sw"; opn = "sw";
break; break;
case OPC_LH: case OPC_LH:
op_ldst_lh(cpu_T[0], ctx); op_ldst_lh(t0, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "lh"; opn = "lh";
break; break;
case OPC_SH: case OPC_SH:
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
op_ldst_sh(cpu_T[0], cpu_T[1], ctx); op_ldst_sh(t0, t1, ctx);
opn = "sh"; opn = "sh";
break; break;
case OPC_LHU: case OPC_LHU:
op_ldst_lhu(cpu_T[0], ctx); op_ldst_lhu(t0, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "lhu"; opn = "lhu";
break; break;
case OPC_LB: case OPC_LB:
op_ldst_lb(cpu_T[0], ctx); op_ldst_lb(t0, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "lb"; opn = "lb";
break; break;
case OPC_SB: case OPC_SB:
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
op_ldst_sb(cpu_T[0], cpu_T[1], ctx); op_ldst_sb(t0, t1, ctx);
opn = "sb"; opn = "sb";
break; break;
case OPC_LBU: case OPC_LBU:
op_ldst_lbu(cpu_T[0], ctx); op_ldst_lbu(t0, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "lbu"; opn = "lbu";
break; break;
case OPC_LWL: case OPC_LWL:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
tcg_gen_helper_1_2i(do_lwl, cpu_T[1], cpu_T[0], cpu_T[1], ctx->mem_idx); tcg_gen_helper_1_2i(do_lwl, t1, t0, t1, ctx->mem_idx);
gen_store_gpr(cpu_T[1], rt); gen_store_gpr(t1, rt);
opn = "lwl"; opn = "lwl";
break; break;
case OPC_SWL: case OPC_SWL:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
tcg_gen_helper_0_2i(do_swl, cpu_T[0], cpu_T[1], ctx->mem_idx); tcg_gen_helper_0_2i(do_swl, t0, t1, ctx->mem_idx);
opn = "swr"; opn = "swr";
break; break;
case OPC_LWR: case OPC_LWR:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
tcg_gen_helper_1_2i(do_lwr, cpu_T[1], cpu_T[0], cpu_T[1], ctx->mem_idx); tcg_gen_helper_1_2i(do_lwr, t1, t0, t1, ctx->mem_idx);
gen_store_gpr(cpu_T[1], rt); gen_store_gpr(t1, rt);
opn = "lwr"; opn = "lwr";
break; break;
case OPC_SWR: case OPC_SWR:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
tcg_gen_helper_0_2i(do_swr, cpu_T[0], cpu_T[1], ctx->mem_idx); tcg_gen_helper_0_2i(do_swr, t0, t1, ctx->mem_idx);
opn = "swr"; opn = "swr";
break; break;
case OPC_LL: case OPC_LL:
op_ldst_ll(cpu_T[0], cpu_T[1], ctx); op_ldst_ll(t0, t1, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "ll"; opn = "ll";
break; break;
case OPC_SC: case OPC_SC:
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
op_ldst_sc(cpu_T[0], cpu_T[1], ctx); op_ldst_sc(t0, t1, ctx);
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
opn = "sc"; opn = "sc";
break; break;
default: default:
MIPS_INVAL(opn); MIPS_INVAL(opn);
generate_exception(ctx, EXCP_RI); generate_exception(ctx, EXCP_RI);
return; goto out;
} }
MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
out:
tcg_temp_free(t0);
tcg_temp_free(t1);
} }
/* Load and store */ /* Load and store */
...@@ -1247,45 +1252,51 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, ...@@ -1247,45 +1252,51 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
int base, int16_t offset) int base, int16_t offset)
{ {
const char *opn = "flt_ldst"; const char *opn = "flt_ldst";
TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
if (base == 0) { if (base == 0) {
tcg_gen_movi_tl(cpu_T[0], offset); tcg_gen_movi_tl(t0, offset);
} else if (offset == 0) { } else if (offset == 0) {
gen_load_gpr(cpu_T[0], base); gen_load_gpr(t0, base);
} else { } else {
gen_load_gpr(cpu_T[0], base); TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
tcg_gen_movi_tl(cpu_T[1], offset);
gen_op_addr_add(cpu_T[0], cpu_T[1]); gen_load_gpr(t0, base);
tcg_gen_movi_tl(t1, offset);
gen_op_addr_add(t0, t1);
tcg_temp_free(t1);
} }
/* Don't do NOP if destination is zero: we must perform the actual /* Don't do NOP if destination is zero: we must perform the actual
memory access. */ memory access. */
switch (opc) { switch (opc) {
case OPC_LWC1: case OPC_LWC1:
tcg_gen_qemu_ld32s(fpu32_T[0], cpu_T[0], ctx->mem_idx); tcg_gen_qemu_ld32s(fpu32_T[0], t0, ctx->mem_idx);
gen_store_fpr32(fpu32_T[0], ft); gen_store_fpr32(fpu32_T[0], ft);
opn = "lwc1"; opn = "lwc1";
break; break;
case OPC_SWC1: case OPC_SWC1:
gen_load_fpr32(fpu32_T[0], ft); gen_load_fpr32(fpu32_T[0], ft);
tcg_gen_qemu_st32(fpu32_T[0], cpu_T[0], ctx->mem_idx); tcg_gen_qemu_st32(fpu32_T[0], t0, ctx->mem_idx);
opn = "swc1"; opn = "swc1";
break; break;
case OPC_LDC1: case OPC_LDC1:
tcg_gen_qemu_ld64(fpu64_T[0], cpu_T[0], ctx->mem_idx); tcg_gen_qemu_ld64(fpu64_T[0], t0, ctx->mem_idx);
gen_store_fpr64(ctx, fpu64_T[0], ft); gen_store_fpr64(ctx, fpu64_T[0], ft);
opn = "ldc1"; opn = "ldc1";
break; break;
case OPC_SDC1: case OPC_SDC1:
gen_load_fpr64(ctx, fpu64_T[0], ft); gen_load_fpr64(ctx, fpu64_T[0], ft);
tcg_gen_qemu_st64(fpu64_T[0], cpu_T[0], ctx->mem_idx); tcg_gen_qemu_st64(fpu64_T[0], t0, ctx->mem_idx);
opn = "sdc1"; opn = "sdc1";
break; break;
default: default:
MIPS_INVAL(opn); MIPS_INVAL(opn);
generate_exception(ctx, EXCP_RI); generate_exception(ctx, EXCP_RI);
return; goto out;
} }
MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]); MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
out:
tcg_temp_free(t0);
} }
/* Arithmetic with immediate operand */ /* Arithmetic with immediate operand */
...@@ -1294,12 +1305,13 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1294,12 +1305,13 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
{ {
target_ulong uimm; target_ulong uimm;
const char *opn = "imm arith"; const char *opn = "imm arith";
TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
/* If no destination, treat it as a NOP. /* If no destination, treat it as a NOP.
For addi, we must generate the overflow exception when needed. */ For addi, we must generate the overflow exception when needed. */
MIPS_DEBUG("NOP"); MIPS_DEBUG("NOP");
return; goto out;
} }
uimm = (uint16_t)imm; uimm = (uint16_t)imm;
switch (opc) { switch (opc) {
...@@ -1316,10 +1328,10 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1316,10 +1328,10 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
case OPC_ANDI: case OPC_ANDI:
case OPC_ORI: case OPC_ORI:
case OPC_XORI: case OPC_XORI:
gen_load_gpr(cpu_T[0], rs); gen_load_gpr(t0, rs);
break; break;
case OPC_LUI: case OPC_LUI:
tcg_gen_movi_tl(cpu_T[0], imm << 16); tcg_gen_movi_tl(t0, imm << 16);
break; break;
case OPC_SLL: case OPC_SLL:
case OPC_SRA: case OPC_SRA:
...@@ -1333,7 +1345,7 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1333,7 +1345,7 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
case OPC_DSRL32: case OPC_DSRL32:
#endif #endif
uimm &= 0x1f; uimm &= 0x1f;
gen_load_gpr(cpu_T[0], rs); gen_load_gpr(t0, rs);
break; break;
} }
switch (opc) { switch (opc) {
...@@ -1344,12 +1356,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1344,12 +1356,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
int l1 = gen_new_label(); int l1 = gen_new_label();
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]); tcg_gen_ext32s_tl(r_tmp1, t0);
tcg_gen_addi_tl(cpu_T[0], r_tmp1, uimm); tcg_gen_addi_tl(t0, r_tmp1, uimm);
tcg_gen_xori_tl(r_tmp1, 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_tmp1, r_tmp1, -1);
tcg_gen_xori_tl(r_tmp2, cpu_T[0], uimm); tcg_gen_xori_tl(r_tmp2, t0, uimm);
tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_shri_tl(r_tmp1, r_tmp1, 31); tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
...@@ -1359,14 +1371,14 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1359,14 +1371,14 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
generate_exception(ctx, EXCP_OVERFLOW); generate_exception(ctx, EXCP_OVERFLOW);
gen_set_label(l1); gen_set_label(l1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
} }
opn = "addi"; opn = "addi";
break; break;
case OPC_ADDIU: case OPC_ADDIU:
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_addi_tl(t0, t0, uimm);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "addiu"; opn = "addiu";
break; break;
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
...@@ -1377,12 +1389,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1377,12 +1389,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
int l1 = gen_new_label(); int l1 = gen_new_label();
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
tcg_gen_mov_tl(r_tmp1, cpu_T[0]); tcg_gen_mov_tl(r_tmp1, t0);
tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_addi_tl(t0, t0, uimm);
tcg_gen_xori_tl(r_tmp1, 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_tmp1, r_tmp1, -1);
tcg_gen_xori_tl(r_tmp2, cpu_T[0], uimm); tcg_gen_xori_tl(r_tmp2, t0, uimm);
tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_shri_tl(r_tmp1, r_tmp1, 63); tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
...@@ -1395,51 +1407,51 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1395,51 +1407,51 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
opn = "daddi"; opn = "daddi";
break; break;
case OPC_DADDIU: case OPC_DADDIU:
tcg_gen_addi_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_addi_tl(t0, t0, uimm);
opn = "daddiu"; opn = "daddiu";
break; break;
#endif #endif
case OPC_SLTI: case OPC_SLTI:
gen_op_lti(cpu_T[0], uimm); gen_op_lti(t0, uimm);
opn = "slti"; opn = "slti";
break; break;
case OPC_SLTIU: case OPC_SLTIU:
gen_op_ltiu(cpu_T[0], uimm); gen_op_ltiu(t0, uimm);
opn = "sltiu"; opn = "sltiu";
break; break;
case OPC_ANDI: case OPC_ANDI:
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_andi_tl(t0, t0, uimm);
opn = "andi"; opn = "andi";
break; break;
case OPC_ORI: case OPC_ORI:
tcg_gen_ori_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_ori_tl(t0, t0, uimm);
opn = "ori"; opn = "ori";
break; break;
case OPC_XORI: case OPC_XORI:
tcg_gen_xori_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_xori_tl(t0, t0, uimm);
opn = "xori"; opn = "xori";
break; break;
case OPC_LUI: case OPC_LUI:
opn = "lui"; opn = "lui";
break; break;
case OPC_SLL: case OPC_SLL:
tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32u_tl(t0, t0);
tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_shli_tl(t0, t0, uimm);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "sll"; opn = "sll";
break; break;
case OPC_SRA: case OPC_SRA:
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_sari_tl(t0, t0, uimm);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "sra"; opn = "sra";
break; break;
case OPC_SRL: case OPC_SRL:
switch ((ctx->opcode >> 21) & 0x1f) { switch ((ctx->opcode >> 21) & 0x1f) {
case 0: case 0:
tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32u_tl(t0, t0);
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_shri_tl(t0, t0, uimm);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "srl"; opn = "srl";
break; break;
case 1: case 1:
...@@ -1449,21 +1461,21 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1449,21 +1461,21 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]); tcg_gen_trunc_tl_i32(r_tmp1, t0);
tcg_gen_movi_i32(r_tmp2, 0x20); tcg_gen_movi_i32(r_tmp2, 0x20);
tcg_gen_subi_i32(r_tmp2, r_tmp2, uimm); tcg_gen_subi_i32(r_tmp2, r_tmp2, uimm);
tcg_gen_shl_i32(r_tmp2, r_tmp1, r_tmp2); tcg_gen_shl_i32(r_tmp2, r_tmp1, r_tmp2);
tcg_gen_shri_i32(r_tmp1, r_tmp1, uimm); tcg_gen_shri_i32(r_tmp1, r_tmp1, uimm);
tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp2); tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp2);
tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1); tcg_gen_ext_i32_tl(t0, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
} }
opn = "rotr"; opn = "rotr";
} else { } else {
tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32u_tl(t0, t0);
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_shri_tl(t0, t0, uimm);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "srl"; opn = "srl";
} }
break; break;
...@@ -1475,17 +1487,17 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1475,17 +1487,17 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
break; break;
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
case OPC_DSLL: case OPC_DSLL:
tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_shli_tl(t0, t0, uimm);
opn = "dsll"; opn = "dsll";
break; break;
case OPC_DSRA: case OPC_DSRA:
tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_sari_tl(t0, t0, uimm);
opn = "dsra"; opn = "dsra";
break; break;
case OPC_DSRL: case OPC_DSRL:
switch ((ctx->opcode >> 21) & 0x1f) { switch ((ctx->opcode >> 21) & 0x1f) {
case 0: case 0:
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_shri_tl(t0, t0, uimm);
opn = "dsrl"; opn = "dsrl";
break; break;
case 1: case 1:
...@@ -1496,14 +1508,14 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1496,14 +1508,14 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
tcg_gen_movi_tl(r_tmp1, 0x40); tcg_gen_movi_tl(r_tmp1, 0x40);
tcg_gen_subi_tl(r_tmp1, r_tmp1, uimm); tcg_gen_subi_tl(r_tmp1, r_tmp1, uimm);
tcg_gen_shl_tl(r_tmp1, cpu_T[0], r_tmp1); tcg_gen_shl_tl(r_tmp1, t0, r_tmp1);
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_shri_tl(t0, t0, uimm);
tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1); tcg_gen_or_tl(t0, t0, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
} }
opn = "drotr"; opn = "drotr";
} else { } else {
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm); tcg_gen_shri_tl(t0, t0, uimm);
opn = "dsrl"; opn = "dsrl";
} }
break; break;
...@@ -1514,17 +1526,17 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1514,17 +1526,17 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
} }
break; break;
case OPC_DSLL32: case OPC_DSLL32:
tcg_gen_shli_tl(cpu_T[0], cpu_T[0], uimm + 32); tcg_gen_shli_tl(t0, t0, uimm + 32);
opn = "dsll32"; opn = "dsll32";
break; break;
case OPC_DSRA32: case OPC_DSRA32:
tcg_gen_sari_tl(cpu_T[0], cpu_T[0], uimm + 32); tcg_gen_sari_tl(t0, t0, uimm + 32);
opn = "dsra32"; opn = "dsra32";
break; break;
case OPC_DSRL32: case OPC_DSRL32:
switch ((ctx->opcode >> 21) & 0x1f) { switch ((ctx->opcode >> 21) & 0x1f) {
case 0: case 0:
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32); tcg_gen_shri_tl(t0, t0, uimm + 32);
opn = "dsrl32"; opn = "dsrl32";
break; break;
case 1: case 1:
...@@ -1537,14 +1549,14 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1537,14 +1549,14 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
tcg_gen_movi_tl(r_tmp2, 32); tcg_gen_movi_tl(r_tmp2, 32);
tcg_gen_addi_tl(r_tmp2, r_tmp2, uimm); tcg_gen_addi_tl(r_tmp2, r_tmp2, uimm);
tcg_gen_sub_tl(r_tmp1, r_tmp1, r_tmp2); tcg_gen_sub_tl(r_tmp1, r_tmp1, r_tmp2);
tcg_gen_shl_tl(r_tmp1, cpu_T[0], r_tmp1); tcg_gen_shl_tl(r_tmp1, t0, r_tmp1);
tcg_gen_shr_tl(cpu_T[0], cpu_T[0], r_tmp2); tcg_gen_shr_tl(t0, t0, r_tmp2);
tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1); tcg_gen_or_tl(t0, t0, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
opn = "drotr32"; opn = "drotr32";
} else { } else {
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], uimm + 32); tcg_gen_shri_tl(t0, t0, uimm + 32);
opn = "dsrl32"; opn = "dsrl32";
} }
break; break;
...@@ -1558,10 +1570,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1558,10 +1570,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
default: default:
MIPS_INVAL(opn); MIPS_INVAL(opn);
generate_exception(ctx, EXCP_RI); generate_exception(ctx, EXCP_RI);
return; goto out;
} }
gen_store_gpr(cpu_T[0], rt); gen_store_gpr(t0, rt);
MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
out:
tcg_temp_free(t0);
} }
/* Arithmetic */ /* Arithmetic */
...@@ -1569,22 +1583,24 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1569,22 +1583,24 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt) int rd, int rs, int rt)
{ {
const char *opn = "arith"; const char *opn = "arith";
TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
&& opc != OPC_DADD && opc != OPC_DSUB) { && opc != OPC_DADD && opc != OPC_DSUB) {
/* If no destination, treat it as a NOP. /* If no destination, treat it as a NOP.
For add & sub, we must generate the overflow exception when needed. */ For add & sub, we must generate the overflow exception when needed. */
MIPS_DEBUG("NOP"); MIPS_DEBUG("NOP");
return; goto out;
} }
gen_load_gpr(cpu_T[0], rs); gen_load_gpr(t0, rs);
/* Specialcase the conventional move operation. */ /* Specialcase the conventional move operation. */
if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
|| opc == OPC_SUBU || opc == OPC_DSUBU)) { || opc == OPC_SUBU || opc == OPC_DSUBU)) {
gen_store_gpr(cpu_T[0], rd); gen_store_gpr(t0, rd);
return; goto out;
} }
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
switch (opc) { switch (opc) {
case OPC_ADD: case OPC_ADD:
{ {
...@@ -1593,13 +1609,13 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1593,13 +1609,13 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
int l1 = gen_new_label(); int l1 = gen_new_label();
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]); tcg_gen_ext32s_tl(r_tmp1, t0);
tcg_gen_ext32s_tl(r_tmp2, cpu_T[1]); tcg_gen_ext32s_tl(r_tmp2, t1);
tcg_gen_add_tl(cpu_T[0], r_tmp1, r_tmp2); tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[1]); tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
tcg_gen_xori_tl(r_tmp1, r_tmp1, -1); tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
tcg_gen_xor_tl(r_tmp2, cpu_T[0], cpu_T[1]); tcg_gen_xor_tl(r_tmp2, t0, t1);
tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_shri_tl(r_tmp1, r_tmp1, 31); tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
...@@ -1609,15 +1625,15 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1609,15 +1625,15 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
generate_exception(ctx, EXCP_OVERFLOW); generate_exception(ctx, EXCP_OVERFLOW);
gen_set_label(l1); gen_set_label(l1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
} }
opn = "add"; opn = "add";
break; break;
case OPC_ADDU: case OPC_ADDU:
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_add_tl(t0, t0, t1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "addu"; opn = "addu";
break; break;
case OPC_SUB: case OPC_SUB:
...@@ -1627,12 +1643,12 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1627,12 +1643,12 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
int l1 = gen_new_label(); int l1 = gen_new_label();
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
tcg_gen_ext32s_tl(r_tmp1, cpu_T[0]); tcg_gen_ext32s_tl(r_tmp1, t0);
tcg_gen_ext32s_tl(r_tmp2, cpu_T[1]); tcg_gen_ext32s_tl(r_tmp2, t1);
tcg_gen_sub_tl(cpu_T[0], r_tmp1, r_tmp2); tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
tcg_gen_xor_tl(r_tmp2, r_tmp1, cpu_T[1]); tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[0]); tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_shri_tl(r_tmp1, r_tmp1, 31); tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
...@@ -1642,15 +1658,15 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1642,15 +1658,15 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
generate_exception(ctx, EXCP_OVERFLOW); generate_exception(ctx, EXCP_OVERFLOW);
gen_set_label(l1); gen_set_label(l1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
} }
opn = "sub"; opn = "sub";
break; break;
case OPC_SUBU: case OPC_SUBU:
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_sub_tl(t0, t0, t1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "subu"; opn = "subu";
break; break;
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
...@@ -1661,12 +1677,12 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1661,12 +1677,12 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
int l1 = gen_new_label(); int l1 = gen_new_label();
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
tcg_gen_mov_tl(r_tmp1, cpu_T[0]); tcg_gen_mov_tl(r_tmp1, t0);
tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_add_tl(t0, t0, t1);
tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[1]); tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
tcg_gen_xori_tl(r_tmp1, r_tmp1, -1); tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
tcg_gen_xor_tl(r_tmp2, cpu_T[0], cpu_T[1]); tcg_gen_xor_tl(r_tmp2, t0, t1);
tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_shri_tl(r_tmp1, r_tmp1, 63); tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
...@@ -1679,7 +1695,7 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1679,7 +1695,7 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
opn = "dadd"; opn = "dadd";
break; break;
case OPC_DADDU: case OPC_DADDU:
tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_add_tl(t0, t0, t1);
opn = "daddu"; opn = "daddu";
break; break;
case OPC_DSUB: case OPC_DSUB:
...@@ -1689,11 +1705,11 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1689,11 +1705,11 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
int l1 = gen_new_label(); int l1 = gen_new_label();
save_cpu_state(ctx, 1); save_cpu_state(ctx, 1);
tcg_gen_mov_tl(r_tmp1, cpu_T[0]); tcg_gen_mov_tl(r_tmp1, t0);
tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_sub_tl(t0, t0, t1);
tcg_gen_xor_tl(r_tmp2, r_tmp1, cpu_T[1]); tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
tcg_gen_xor_tl(r_tmp1, r_tmp1, cpu_T[0]); tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_shri_tl(r_tmp1, r_tmp1, 63); tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
...@@ -1706,48 +1722,48 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1706,48 +1722,48 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
opn = "dsub"; opn = "dsub";
break; break;
case OPC_DSUBU: case OPC_DSUBU:
tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_sub_tl(t0, t0, t1);
opn = "dsubu"; opn = "dsubu";
break; break;
#endif #endif
case OPC_SLT: case OPC_SLT:
gen_op_lt(cpu_T[0], cpu_T[1]); gen_op_lt(t0, t1);
opn = "slt"; opn = "slt";
break; break;
case OPC_SLTU: case OPC_SLTU:
gen_op_ltu(cpu_T[0], cpu_T[1]); gen_op_ltu(t0, t1);
opn = "sltu"; opn = "sltu";
break; break;
case OPC_AND: case OPC_AND:
tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_and_tl(t0, t0, t1);
opn = "and"; opn = "and";
break; break;
case OPC_NOR: case OPC_NOR:
tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_or_tl(t0, t0, t1);
tcg_gen_not_tl(cpu_T[0], cpu_T[0]); tcg_gen_not_tl(t0, t0);
opn = "nor"; opn = "nor";
break; break;
case OPC_OR: case OPC_OR:
tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_or_tl(t0, t0, t1);
opn = "or"; opn = "or";
break; break;
case OPC_XOR: case OPC_XOR:
tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_xor_tl(t0, t0, t1);
opn = "xor"; opn = "xor";
break; break;
case OPC_MUL: case OPC_MUL:
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_mul_tl(t0, t0, t1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "mul"; opn = "mul";
break; break;
case OPC_MOVN: case OPC_MOVN:
{ {
int l1 = gen_new_label(); int l1 = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1); tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
gen_store_gpr(cpu_T[0], rd); gen_store_gpr(t0, rd);
gen_set_label(l1); gen_set_label(l1);
} }
opn = "movn"; opn = "movn";
...@@ -1756,34 +1772,34 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1756,34 +1772,34 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
{ {
int l1 = gen_new_label(); int l1 = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[1], 0, l1); tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
gen_store_gpr(cpu_T[0], rd); gen_store_gpr(t0, rd);
gen_set_label(l1); gen_set_label(l1);
} }
opn = "movz"; opn = "movz";
goto print; goto print;
case OPC_SLLV: case OPC_SLLV:
tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32u_tl(t1, t1);
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); tcg_gen_andi_tl(t0, t0, 0x1f);
tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_shl_tl(t0, t1, t0);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "sllv"; opn = "sllv";
break; break;
case OPC_SRAV: case OPC_SRAV:
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); tcg_gen_andi_tl(t0, t0, 0x1f);
tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_sar_tl(t0, t1, t0);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "srav"; opn = "srav";
break; break;
case OPC_SRLV: case OPC_SRLV:
switch ((ctx->opcode >> 6) & 0x1f) { switch ((ctx->opcode >> 6) & 0x1f) {
case 0: case 0:
tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32u_tl(t1, t1);
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); tcg_gen_andi_tl(t0, t0, 0x1f);
tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_shr_tl(t0, t1, t0);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "srlv"; opn = "srlv";
break; break;
case 1: case 1:
...@@ -1792,35 +1808,35 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1792,35 +1808,35 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
int l1 = gen_new_label(); int l1 = gen_new_label();
int l2 = gen_new_label(); int l2 = gen_new_label();
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); tcg_gen_andi_tl(t0, t0, 0x1f);
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1); tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
{ {
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32); TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]); tcg_gen_trunc_tl_i32(r_tmp1, t0);
tcg_gen_trunc_tl_i32(r_tmp2, cpu_T[1]); tcg_gen_trunc_tl_i32(r_tmp2, t1);
tcg_gen_movi_i32(r_tmp3, 0x20); tcg_gen_movi_i32(r_tmp3, 0x20);
tcg_gen_sub_i32(r_tmp3, r_tmp3, r_tmp1); tcg_gen_sub_i32(r_tmp3, r_tmp3, r_tmp1);
tcg_gen_shl_i32(r_tmp3, r_tmp2, r_tmp3); tcg_gen_shl_i32(r_tmp3, r_tmp2, r_tmp3);
tcg_gen_shr_i32(r_tmp1, r_tmp2, r_tmp1); tcg_gen_shr_i32(r_tmp1, r_tmp2, r_tmp1);
tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp3); tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp3);
tcg_gen_ext_i32_tl(cpu_T[0], r_tmp1); tcg_gen_ext_i32_tl(t0, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_temp_free(r_tmp3); tcg_temp_free(r_tmp3);
tcg_gen_br(l2); tcg_gen_br(l2);
} }
gen_set_label(l1); gen_set_label(l1);
tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); tcg_gen_mov_tl(t0, t1);
gen_set_label(l2); gen_set_label(l2);
opn = "rotrv"; opn = "rotrv";
} else { } else {
tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32u_tl(t1, t1);
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x1f); tcg_gen_andi_tl(t0, t0, 0x1f);
tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_shr_tl(t0, t1, t0);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
opn = "srlv"; opn = "srlv";
} }
break; break;
...@@ -1832,20 +1848,20 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1832,20 +1848,20 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
break; break;
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
case OPC_DSLLV: case OPC_DSLLV:
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_shl_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_shl_tl(t0, t1, t0);
opn = "dsllv"; opn = "dsllv";
break; break;
case OPC_DSRAV: case OPC_DSRAV:
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_sar_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_sar_tl(t0, t1, t0);
opn = "dsrav"; opn = "dsrav";
break; break;
case OPC_DSRLV: case OPC_DSRLV:
switch ((ctx->opcode >> 6) & 0x1f) { switch ((ctx->opcode >> 6) & 0x1f) {
case 0: case 0:
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_shr_tl(t0, t1, t0);
opn = "dsrlv"; opn = "dsrlv";
break; break;
case 1: case 1:
...@@ -1854,26 +1870,26 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1854,26 +1870,26 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
int l1 = gen_new_label(); int l1 = gen_new_label();
int l2 = gen_new_label(); int l2 = gen_new_label();
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[0], 0, l1); tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
{ {
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
tcg_gen_movi_tl(r_tmp1, 0x40); tcg_gen_movi_tl(r_tmp1, 0x40);
tcg_gen_sub_tl(r_tmp1, r_tmp1, cpu_T[0]); tcg_gen_sub_tl(r_tmp1, r_tmp1, t0);
tcg_gen_shl_tl(r_tmp1, cpu_T[1], r_tmp1); tcg_gen_shl_tl(r_tmp1, t1, r_tmp1);
tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_shr_tl(t0, t1, t0);
tcg_gen_or_tl(cpu_T[0], cpu_T[0], r_tmp1); tcg_gen_or_tl(t0, t0, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_gen_br(l2); tcg_gen_br(l2);
} }
gen_set_label(l1); gen_set_label(l1);
tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); tcg_gen_mov_tl(t0, t1);
gen_set_label(l2); gen_set_label(l2);
opn = "drotrv"; opn = "drotrv";
} else { } else {
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x3f); tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_shr_tl(cpu_T[0], cpu_T[1], cpu_T[0]); tcg_gen_shr_tl(t0, t1, t0);
opn = "dsrlv"; opn = "dsrlv";
} }
break; break;
...@@ -1887,85 +1903,93 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, ...@@ -1887,85 +1903,93 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
default: default:
MIPS_INVAL(opn); MIPS_INVAL(opn);
generate_exception(ctx, EXCP_RI); generate_exception(ctx, EXCP_RI);
return; goto out;
} }
gen_store_gpr(cpu_T[0], rd); gen_store_gpr(t0, rd);
print: print:
MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
out:
tcg_temp_free(t0);
tcg_temp_free(t1);
} }
/* Arithmetic on HI/LO registers */ /* Arithmetic on HI/LO registers */
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
{ {
const char *opn = "hilo"; const char *opn = "hilo";
TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
/* Treat as NOP. */ /* Treat as NOP. */
MIPS_DEBUG("NOP"); MIPS_DEBUG("NOP");
return; goto out;
} }
switch (opc) { switch (opc) {
case OPC_MFHI: case OPC_MFHI:
gen_load_HI(cpu_T[0], 0); gen_load_HI(t0, 0);
gen_store_gpr(cpu_T[0], reg); gen_store_gpr(t0, reg);
opn = "mfhi"; opn = "mfhi";
break; break;
case OPC_MFLO: case OPC_MFLO:
gen_load_LO(cpu_T[0], 0); gen_load_LO(t0, 0);
gen_store_gpr(cpu_T[0], reg); gen_store_gpr(t0, reg);
opn = "mflo"; opn = "mflo";
break; break;
case OPC_MTHI: case OPC_MTHI:
gen_load_gpr(cpu_T[0], reg); gen_load_gpr(t0, reg);
gen_store_HI(cpu_T[0], 0); gen_store_HI(t0, 0);
opn = "mthi"; opn = "mthi";
break; break;
case OPC_MTLO: case OPC_MTLO:
gen_load_gpr(cpu_T[0], reg); gen_load_gpr(t0, reg);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
opn = "mtlo"; opn = "mtlo";
break; break;
default: default:
MIPS_INVAL(opn); MIPS_INVAL(opn);
generate_exception(ctx, EXCP_RI); generate_exception(ctx, EXCP_RI);
return; goto out;
} }
MIPS_DEBUG("%s %s", opn, regnames[reg]); MIPS_DEBUG("%s %s", opn, regnames[reg]);
out:
tcg_temp_free(t0);
} }
static void gen_muldiv (DisasContext *ctx, uint32_t opc, static void gen_muldiv (DisasContext *ctx, uint32_t opc,
int rs, int rt) int rs, int rt)
{ {
const char *opn = "mul/div"; const char *opn = "mul/div";
TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
gen_load_gpr(cpu_T[0], rs); gen_load_gpr(t0, rs);
gen_load_gpr(cpu_T[1], rt); gen_load_gpr(t1, rt);
switch (opc) { switch (opc) {
case OPC_DIV: case OPC_DIV:
{ {
int l1 = gen_new_label(); int l1 = gen_new_label();
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1); tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
{ {
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); tcg_gen_ext_tl_i64(r_tmp1, t0);
tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); tcg_gen_ext_tl_i64(r_tmp2, t1);
tcg_gen_div_i64(r_tmp3, r_tmp1, r_tmp2); tcg_gen_div_i64(r_tmp3, r_tmp1, r_tmp2);
tcg_gen_rem_i64(r_tmp2, r_tmp1, r_tmp2); tcg_gen_rem_i64(r_tmp2, r_tmp1, r_tmp2);
tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp3); tcg_gen_trunc_i64_tl(t0, r_tmp3);
tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp2); tcg_gen_trunc_i64_tl(t1, r_tmp2);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_temp_free(r_tmp3); tcg_temp_free(r_tmp3);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
} }
gen_set_label(l1); gen_set_label(l1);
} }
...@@ -1975,24 +1999,24 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -1975,24 +1999,24 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{ {
int l1 = gen_new_label(); int l1 = gen_new_label();
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1); tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
{ {
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32); TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
tcg_gen_trunc_tl_i32(r_tmp1, cpu_T[0]); tcg_gen_trunc_tl_i32(r_tmp1, t0);
tcg_gen_trunc_tl_i32(r_tmp2, cpu_T[1]); tcg_gen_trunc_tl_i32(r_tmp2, t1);
tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2); tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2); tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
tcg_gen_ext_i32_tl(cpu_T[0], r_tmp3); tcg_gen_ext_i32_tl(t0, r_tmp3);
tcg_gen_ext_i32_tl(cpu_T[1], r_tmp1); tcg_gen_ext_i32_tl(t1, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_temp_free(r_tmp3); tcg_temp_free(r_tmp3);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
} }
gen_set_label(l1); gen_set_label(l1);
} }
...@@ -2003,20 +2027,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2003,20 +2027,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp2 = 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(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); tcg_gen_ext_tl_i64(r_tmp1, t0);
tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); tcg_gen_ext_tl_i64(r_tmp2, t1);
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); tcg_gen_trunc_i64_tl(t0, r_tmp1);
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); tcg_gen_trunc_i64_tl(t1, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
} }
opn = "mult"; opn = "mult";
break; break;
...@@ -2025,20 +2049,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2025,20 +2049,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp2 = 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(t0, t0);
tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32u_tl(t1, t1);
tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); tcg_gen_extu_tl_i64(r_tmp1, t0);
tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); tcg_gen_extu_tl_i64(r_tmp2, t1);
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); tcg_gen_trunc_i64_tl(t0, r_tmp1);
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); tcg_gen_trunc_i64_tl(t1, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
} }
opn = "multu"; opn = "multu";
break; break;
...@@ -2047,16 +2071,16 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2047,16 +2071,16 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{ {
int l1 = gen_new_label(); int l1 = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1); tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
{ {
int l2 = gen_new_label(); int l2 = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], -1LL << 63, l2); tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[1], -1LL, l2); tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
{ {
tcg_gen_movi_tl(cpu_T[1], 0); tcg_gen_movi_tl(t1, 0);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
tcg_gen_br(l1); tcg_gen_br(l1);
} }
gen_set_label(l2); gen_set_label(l2);
...@@ -2064,8 +2088,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2064,8 +2088,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
tcg_gen_div_i64(r_tmp1, cpu_T[0], cpu_T[1]); tcg_gen_div_i64(r_tmp1, t0, t1);
tcg_gen_rem_i64(r_tmp2, cpu_T[0], cpu_T[1]); tcg_gen_rem_i64(r_tmp2, t0, t1);
gen_store_LO(r_tmp1, 0); gen_store_LO(r_tmp1, 0);
gen_store_HI(r_tmp2, 0); gen_store_HI(r_tmp2, 0);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
...@@ -2080,13 +2104,13 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2080,13 +2104,13 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{ {
int l1 = gen_new_label(); int l1 = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1); tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
{ {
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
tcg_gen_divu_i64(r_tmp1, cpu_T[0], cpu_T[1]); tcg_gen_divu_i64(r_tmp1, t0, t1);
tcg_gen_remu_i64(r_tmp2, cpu_T[0], cpu_T[1]); tcg_gen_remu_i64(r_tmp2, t0, t1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
gen_store_LO(r_tmp1, 0); gen_store_LO(r_tmp1, 0);
...@@ -2097,11 +2121,11 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2097,11 +2121,11 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
opn = "ddivu"; opn = "ddivu";
break; break;
case OPC_DMULT: case OPC_DMULT:
tcg_gen_helper_0_2(do_dmult, cpu_T[0], cpu_T[1]); tcg_gen_helper_0_2(do_dmult, t0, t1);
opn = "dmult"; opn = "dmult";
break; break;
case OPC_DMULTU: case OPC_DMULTU:
tcg_gen_helper_0_2(do_dmultu, cpu_T[0], cpu_T[1]); tcg_gen_helper_0_2(do_dmultu, t0, t1);
opn = "dmultu"; opn = "dmultu";
break; break;
#endif #endif
...@@ -2111,28 +2135,28 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2111,28 +2135,28 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp3 = 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(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); tcg_gen_ext_tl_i64(r_tmp1, t0);
tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); tcg_gen_ext_tl_i64(r_tmp2, t1);
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
gen_load_LO(cpu_T[0], 0); gen_load_LO(t0, 0);
gen_load_HI(cpu_T[1], 0); gen_load_HI(t1, 0);
tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); tcg_gen_extu_tl_i64(r_tmp2, t0);
tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); tcg_gen_extu_tl_i64(r_tmp3, t1);
tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
tcg_temp_free(r_tmp3); tcg_temp_free(r_tmp3);
tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); tcg_gen_trunc_i64_tl(t0, r_tmp1);
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); tcg_gen_trunc_i64_tl(t1, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
} }
opn = "madd"; opn = "madd";
break; break;
...@@ -2142,28 +2166,28 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2142,28 +2166,28 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp3 = 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(t0, t0);
tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32u_tl(t1, t1);
tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); tcg_gen_extu_tl_i64(r_tmp1, t0);
tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); tcg_gen_extu_tl_i64(r_tmp2, t1);
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
gen_load_LO(cpu_T[0], 0); gen_load_LO(t0, 0);
gen_load_HI(cpu_T[1], 0); gen_load_HI(t1, 0);
tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); tcg_gen_extu_tl_i64(r_tmp2, t0);
tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); tcg_gen_extu_tl_i64(r_tmp3, t1);
tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
tcg_temp_free(r_tmp3); tcg_temp_free(r_tmp3);
tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); tcg_gen_trunc_i64_tl(t0, r_tmp1);
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); tcg_gen_trunc_i64_tl(t1, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
} }
opn = "maddu"; opn = "maddu";
break; break;
...@@ -2173,28 +2197,28 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2173,28 +2197,28 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp3 = 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(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); tcg_gen_ext_tl_i64(r_tmp1, t0);
tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); tcg_gen_ext_tl_i64(r_tmp2, t1);
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
gen_load_LO(cpu_T[0], 0); gen_load_LO(t0, 0);
gen_load_HI(cpu_T[1], 0); gen_load_HI(t1, 0);
tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); tcg_gen_extu_tl_i64(r_tmp2, t0);
tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); tcg_gen_extu_tl_i64(r_tmp3, t1);
tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
tcg_temp_free(r_tmp3); tcg_temp_free(r_tmp3);
tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); tcg_gen_trunc_i64_tl(t0, r_tmp1);
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); tcg_gen_trunc_i64_tl(t1, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
} }
opn = "msub"; opn = "msub";
break; break;
...@@ -2204,37 +2228,40 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, ...@@ -2204,37 +2228,40 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
TCGv r_tmp3 = 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(t0, t0);
tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32u_tl(t1, t1);
tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); tcg_gen_extu_tl_i64(r_tmp1, t0);
tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); tcg_gen_extu_tl_i64(r_tmp2, t1);
tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
gen_load_LO(cpu_T[0], 0); gen_load_LO(t0, 0);
gen_load_HI(cpu_T[1], 0); gen_load_HI(t1, 0);
tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); tcg_gen_extu_tl_i64(r_tmp2, t0);
tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); tcg_gen_extu_tl_i64(r_tmp3, t1);
tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
tcg_temp_free(r_tmp3); tcg_temp_free(r_tmp3);
tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2); tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); tcg_gen_trunc_i64_tl(t0, r_tmp1);
tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); tcg_gen_trunc_i64_tl(t1, r_tmp1);
tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp1);
tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); tcg_gen_ext32s_tl(t0, t0);
tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); tcg_gen_ext32s_tl(t1, t1);
gen_store_LO(cpu_T[0], 0); gen_store_LO(t0, 0);
gen_store_HI(cpu_T[1], 0); gen_store_HI(t1, 0);
} }
opn = "msubu"; opn = "msubu";
break; break;
default: default:
MIPS_INVAL(opn); MIPS_INVAL(opn);
generate_exception(ctx, EXCP_RI); generate_exception(ctx, EXCP_RI);
return; goto out;
} }
MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
out:
tcg_temp_free(t0);
tcg_temp_free(t1);
} }
static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc, static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册