On Mon, May 21, 2007 at 04:52:05PM +0300, Blue Swirl wrote: > I don't know MIPS, but perhaps you could try this trick used in Sparc: > static inline void gen_jmp_im(target_ulong pc) > { > #ifdef TARGET_SPARC64 > if (pc == (uint32_t)pc) { > gen_op_jmp_im(pc); > } else { > gen_op_jmp_im64(pc >> 32, pc); > } > #else > gen_op_jmp_im(pc); > #endif > } >
Here is a new patch using the same trick as the one used in Sparc. It renders the code clearer. Sorry for the delay. Index: target-mips/op.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/op.c,v retrieving revision 1.62 diff -u -d -p -r1.62 op.c --- target-mips/op.c 23 May 2007 08:24:25 -0000 1.62 +++ target-mips/op.c 26 May 2007 21:12:05 -0000 @@ -976,6 +976,14 @@ void op_save_btarget (void) RETURN(); } +#ifdef TARGET_MIPS64 +void op_save_btarget64 (void) +{ + env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2; + RETURN(); +} +#endif + /* Conditional branch */ void op_set_bcond (void) { @@ -2409,6 +2417,14 @@ void op_save_pc (void) RETURN(); } +#ifdef TARGET_MIPS64 +void op_save_pc64 (void) +{ + env->PC = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2; + RETURN(); +} +#endif + void op_interrupt_restart (void) { if (!(env->CP0_Status & (1 << CP0St_EXL)) && Index: target-mips/op_template.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/op_template.c,v retrieving revision 1.5 diff -u -d -p -r1.5 op_template.c --- target-mips/op_template.c 29 Apr 2007 21:19:03 -0000 1.5 +++ target-mips/op_template.c 26 May 2007 21:12:05 -0000 @@ -68,4 +68,20 @@ SET_RESET(T1, _T1) SET_RESET(T2, _T2) #undef SET_RESET + +#ifdef TARGET_MIPS64 +#define SET64(treg, tregname) \ + void glue(op_set64, tregname)(void) \ + { \ + treg = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2; \ + RETURN(); \ + } + +SET64(T0, _T0) +SET64(T1, _T1) +SET64(T2, _T2) + +#undef SET64 + +#endif #endif Index: target-mips/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/translate.c,v retrieving revision 1.87 diff -u -d -p -r1.87 translate.c --- target-mips/translate.c 23 May 2007 08:24:25 -0000 1.87 +++ target-mips/translate.c 26 May 2007 21:12:05 -0000 @@ -569,6 +569,18 @@ do { } \ } while (0) +#ifdef TARGET_MIPS64 +#define GEN_LOAD_IMM_TN(Tn, Imm) \ +do { \ + if (Imm == 0) { \ + glue(gen_op_reset_, Tn)(); \ + } else if ((int32_t)Imm == Imm) { \ + glue(gen_op_set_, Tn)(Imm); \ + } else { \ + glue(gen_op_set64_, Tn)(((uint64_t)Imm) >> 32, (uint32_t)Imm); \ + } \ +} while (0) +#else #define GEN_LOAD_IMM_TN(Tn, Imm) \ do { \ if (Imm == 0) { \ @@ -577,6 +589,7 @@ do { glue(gen_op_set_, Tn)(Imm); \ } \ } while (0) +#endif #define GEN_STORE_TN_REG(Rn, Tn) \ do { \ @@ -595,6 +608,32 @@ do { glue(gen_op_store_fpr_, FTn)(Fn); \ } while (0) +static inline void gen_save_pc(target_ulong pc) +{ +#ifdef TARGET_MIPS64 + if (pc == (int32_t)pc) { + gen_op_save_pc(pc); + } else { + gen_op_save_pc64(pc >> 32, (uint32_t)pc); + } +#else + gen_op_save_pc(pc); +#endif +} + +static inline void gen_save_btarget(target_ulong btarget) +{ +#ifdef TARGET_MIPS64 + if (btarget == (int32_t)btarget) { + gen_op_save_btarget(btarget); + } else { + gen_op_save_btarget64(btarget >> 32, (uint32_t)btarget); + } +#else + gen_op_save_btarget(btarget); +#endif +} + static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) { #if defined MIPS_DEBUG_DISAS @@ -604,7 +643,7 @@ static inline void save_cpu_state (Disas } #endif if (do_save_pc && ctx->pc != ctx->saved_pc) { - gen_op_save_pc(ctx->pc); + gen_save_pc(ctx->pc); ctx->saved_pc = ctx->pc; } if (ctx->hflags != ctx->saved_hflags) { @@ -621,7 +660,7 @@ static inline void save_cpu_state (Disas /* bcond was already saved by the BL insn */ /* fall through */ case MIPS_HFLAG_B: - gen_op_save_btarget(ctx->btarget); + gen_save_btarget(ctx->btarget); break; } } @@ -946,7 +985,7 @@ static void gen_arith_imm (DisasContext GEN_LOAD_IMM_TN(T1, uimm); break; case OPC_LUI: - GEN_LOAD_IMM_TN(T0, uimm << 16); + GEN_LOAD_IMM_TN(T0, imm << 16); break; case OPC_SLL: case OPC_SRA: @@ -1491,10 +1530,10 @@ static inline void gen_goto_tb(DisasCont gen_op_goto_tb0(TBPARAM(tb)); else gen_op_goto_tb1(TBPARAM(tb)); - gen_op_save_pc(dest); + gen_save_pc(dest); gen_op_set_T0((long)tb + n); } else { - gen_op_save_pc(dest); + gen_save_pc(dest); gen_op_reset_T0(); } gen_op_exit_tb(); @@ -1556,7 +1595,7 @@ static void gen_compute_branch (DisasCon case OPC_J: case OPC_JAL: /* Jump to immediate */ - btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | offset; + btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset; break; case OPC_JR: case OPC_JALR: @@ -1602,12 +1641,12 @@ static void gen_compute_branch (DisasCon MIPS_DEBUG("bnever (NOP)"); return; case OPC_BLTZAL: /* 0 < 0 */ - gen_op_set_T0(ctx->pc + 8); + GEN_LOAD_IMM_TN(T0, ctx->pc + 8); gen_op_store_T0_gpr(31); MIPS_DEBUG("bnever and link"); return; case OPC_BLTZALL: /* 0 < 0 likely */ - gen_op_set_T0(ctx->pc + 8); + GEN_LOAD_IMM_TN(T0, ctx->pc + 8); gen_op_store_T0_gpr(31); /* Skip the instruction in the delay slot */ MIPS_DEBUG("bnever, link and skip"); @@ -1732,9 +1771,10 @@ static void gen_compute_branch (DisasCon } MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx, blink, ctx->hflags, btarget); + ctx->btarget = btarget; if (blink > 0) { - gen_op_set_T0(ctx->pc + 8); + GEN_LOAD_IMM_TN(T0, ctx->pc + 8); gen_op_store_T0_gpr(blink); } } -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [EMAIL PROTECTED] | [EMAIL PROTECTED] `- people.debian.org/~aurel32 | www.aurel32.net