diff options
-rw-r--r-- | exec-all.h | 9 | ||||
-rw-r--r-- | target-arm/op.c | 8 | ||||
-rw-r--r-- | target-arm/translate.c | 25 | ||||
-rw-r--r-- | target-mips/op.c | 38 | ||||
-rw-r--r-- | target-mips/translate.c | 47 | ||||
-rw-r--r-- | target-ppc/op.c | 18 | ||||
-rw-r--r-- | target-ppc/translate.c | 31 |
7 files changed, 116 insertions, 60 deletions
diff --git a/exec-all.h b/exec-all.h index 5db83d368c..3803006987 100644 --- a/exec-all.h +++ b/exec-all.h @@ -365,15 +365,6 @@ dummy_label ## n: ;\ #endif -/* XXX: will be suppressed */ -#define JUMP_TB(opname, tbparam, n, eip)\ -do {\ - GOTO_TB(opname, tbparam, n);\ - T0 = (long)(tbparam) + (n);\ - EIP = (int32_t)eip;\ - EXIT_TB();\ -} while (0) - extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; diff --git a/target-arm/op.c b/target-arm/op.c index 8a82def79a..1d30b1bda0 100644 --- a/target-arm/op.c +++ b/target-arm/op.c @@ -346,14 +346,14 @@ void OPPROTO op_test_le(void) FORCE_RET(); } -void OPPROTO op_jmp0(void) +void OPPROTO op_goto_tb0(void) { - JUMP_TB(op_jmp0, PARAM1, 0, PARAM2); + GOTO_TB(op_goto_tb0, PARAM1, 0); } -void OPPROTO op_jmp1(void) +void OPPROTO op_goto_tb1(void) { - JUMP_TB(op_jmp1, PARAM1, 1, PARAM2); + GOTO_TB(op_goto_tb1, PARAM1, 1); } void OPPROTO op_exit_tb(void) diff --git a/target-arm/translate.c b/target-arm/translate.c index c3e8fe8268..f954de3f7d 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -43,6 +43,12 @@ typedef struct DisasContext { #define DISAS_JUMP_NEXT 4 +#ifdef USE_DIRECT_JUMP +#define TBPARAM(x) +#else +#define TBPARAM(x) (long)(x) +#endif + /* XXX: move that elsewhere */ static uint16_t *gen_opc_ptr; static uint32_t *gen_opparam_ptr; @@ -897,6 +903,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) return 0; } +static inline void gen_jmp_tb(long tb, int n, uint32_t dest) +{ + if (n == 0) + gen_op_goto_tb0(TBPARAM(tb)); + else + gen_op_goto_tb1(TBPARAM(tb)); + gen_op_movl_T0_im(dest); + gen_op_movl_r15_T0(); + gen_op_movl_T0_im(tb + n); + gen_op_exit_tb(); +} + static inline void gen_jmp (DisasContext *s, uint32_t dest) { if (__builtin_expect(s->singlestep_enabled, 0)) { @@ -906,7 +924,8 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest) gen_op_movl_T0_im(dest); gen_bx(s); } else { - gen_op_jmp0((long)s->tb, dest); + long tb = (long)s->tb; + gen_jmp_tb(tb, 0, dest); s->is_jmp = DISAS_TB_JUMP; } } @@ -2118,7 +2137,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, } else { switch(dc->is_jmp) { case DISAS_NEXT: - gen_op_jmp1((long)dc->tb, (long)dc->pc); + gen_jmp_tb((long)dc->tb, 1, dc->pc); break; default: case DISAS_JUMP: @@ -2133,7 +2152,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, } if (dc->condjmp) { gen_set_label(dc->condlabel); - gen_op_jmp1((long)dc->tb, (long)dc->pc); + gen_jmp_tb((long)dc->tb, 1, dc->pc); dc->condjmp = 0; } } diff --git a/target-mips/op.c b/target-mips/op.c index 32f7e4fc9b..029ce5d005 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -487,7 +487,16 @@ OP_COND(ltz, (int32_t)T0 < 0); /* Branchs */ //#undef USE_DIRECT_JUMP -#define EIP env->PC + +void OPPROTO op_goto_tb0(void) +{ + GOTO_TB(op_goto_tb0, PARAM1, 0); +} + +void OPPROTO op_goto_tb1(void) +{ + GOTO_TB(op_goto_tb1, PARAM1, 1); +} /* Branch to register */ void op_save_breg_target (void) @@ -506,13 +515,6 @@ void op_breg (void) RETURN(); } -/* Unconditional branch */ -void op_branch (void) -{ - JUMP_TB(branch, PARAM1, 0, PARAM2); - RETURN(); -} - void op_save_btarget (void) { env->btarget = PARAM1; @@ -538,24 +540,10 @@ void op_restore_bcond (void) RETURN(); } -void op_bcond (void) -{ - if (T2) { - JUMP_TB(bcond, PARAM1, 0, PARAM2); - } else { - JUMP_TB(bcond, PARAM1, 1, PARAM3); - } - RETURN(); -} - -/* Likely branch (used to skip the delay slot) */ -void op_blikely (void) +void op_jnz_T2 (void) { - /* If the test is false, skip the delay slot */ - if (T2 == 0) { - env->hflags = PARAM3; - JUMP_TB(blikely, PARAM1, 1, PARAM2); - } + if (T2) + GOTO_LABEL_PARAM(1); RETURN(); } diff --git a/target-mips/translate.c b/target-mips/translate.c index 7055775471..5e54dd84bf 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -31,6 +31,12 @@ #define MIPS_DEBUG_DISAS //#define MIPS_SINGLE_STEP +#ifdef USE_DIRECT_JUMP +#define TBPARAM(x) +#else +#define TBPARAM(x) (long)(x) +#endif + enum { #define DEF(s, n, copy_size) INDEX_op_ ## s, #include "opc.h" @@ -922,6 +928,17 @@ static void gen_trap (DisasContext *ctx, uint16_t opc, ctx->bstate = BS_STOP; } +static inline void gen_jmp_tb(long tb, int n, uint32_t dest) +{ + if (n == 0) + gen_op_goto_tb0(TBPARAM(tb)); + else + gen_op_goto_tb1(TBPARAM(tb)); + gen_op_save_pc(dest); + gen_op_set_T0(tb + n); + gen_op_exit_tb(); +} + /* Branches (before delay slot) */ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, int rs, int rt, int32_t offset) @@ -1018,7 +1035,7 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, case OPC_BLTZL: /* 0 < 0 likely */ /* Skip the instruction in the delay slot */ MIPS_DEBUG("bnever and skip"); - gen_op_branch((long)ctx->tb, ctx->pc + 4); + gen_jmp_tb((long)ctx->tb, 0, ctx->pc + 4); return; case OPC_J: ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; @@ -1255,6 +1272,15 @@ static void gen_arith64 (DisasContext *ctx, uint16_t opc) #endif +static void gen_blikely(DisasContext *ctx) +{ + int l1; + l1 = gen_new_label(); + gen_op_jnz_T2(l1); + gen_op_save_state(ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS)); + gen_jmp_tb((long)ctx->tb, 1, ctx->pc + 4); +} + static void decode_opc (DisasContext *ctx) { int32_t offset; @@ -1266,8 +1292,7 @@ static void decode_opc (DisasContext *ctx) (ctx->hflags & MIPS_HFLAG_BL)) { /* Handle blikely not taken case */ MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4); - gen_op_blikely((long)ctx->tb, ctx->pc + 4, - ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS)); + gen_blikely(ctx); } op = ctx->opcode >> 26; rs = ((ctx->opcode >> 21) & 0x1F); @@ -1477,17 +1502,24 @@ static void decode_opc (DisasContext *ctx) case MIPS_HFLAG_B: /* unconditional branch */ MIPS_DEBUG("unconditional branch"); - gen_op_branch((long)ctx->tb, ctx->btarget); + gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); break; case MIPS_HFLAG_BL: /* blikely taken case */ MIPS_DEBUG("blikely branch taken"); - gen_op_branch((long)ctx->tb, ctx->btarget); + gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); break; case MIPS_HFLAG_BC: /* Conditional branch */ MIPS_DEBUG("conditional branch"); - gen_op_bcond((long)ctx->tb, ctx->btarget, ctx->pc + 4); + { + int l1; + l1 = gen_new_label(); + gen_op_jnz_T2(l1); + gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); + gen_set_label(l1); + gen_jmp_tb((long)ctx->tb, 1, ctx->pc + 4); + } break; case MIPS_HFLAG_BR: /* unconditional branch to register */ @@ -1513,6 +1545,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opparam_ptr = gen_opparam_buf; + nb_gen_labels = 0; ctx.pc = pc_start; ctx.tb = tb; ctx.bstate = BS_NONE; @@ -1570,7 +1603,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) { save_cpu_state(ctxp, 0); - gen_op_branch((long)ctx.tb, ctx.pc); + gen_jmp_tb((long)ctx.tb, 0, ctx.pc); } gen_op_reset_T0(); /* Generate the return instruction */ diff --git a/target-ppc/op.c b/target-ppc/op.c index 0e37119dac..4b0af5587c 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -451,9 +451,14 @@ PPC_OP(setlr) regs->lr = PARAM1; } -PPC_OP(b) +PPC_OP(goto_tb0) { - JUMP_TB(b1, PARAM1, 0, PARAM2); + GOTO_TB(op_goto_tb0, PARAM1, 0); +} + +PPC_OP(goto_tb1) +{ + GOTO_TB(op_goto_tb1, PARAM1, 1); } PPC_OP(b_T1) @@ -461,13 +466,10 @@ PPC_OP(b_T1) regs->nip = T1 & ~3; } -PPC_OP(btest) +PPC_OP(jz_T0) { - if (T0) { - JUMP_TB(btest, PARAM1, 0, PARAM2); - } else { - JUMP_TB(btest, PARAM1, 1, PARAM3); - } + if (!T0) + GOTO_LABEL_PARAM(1); RETURN(); } diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 70f88637df..c04c0ef99a 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -30,6 +30,12 @@ //#define DO_SINGLE_STEP //#define PPC_DEBUG_DISAS +#ifdef USE_DIRECT_JUMP +#define TBPARAM(x) +#else +#define TBPARAM(x) (long)(x) +#endif + enum { #define DEF(s, n, copy_size) INDEX_op_ ## s, #include "opc.h" @@ -1721,6 +1727,18 @@ GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT) /*** Branch ***/ +static inline void gen_jmp_tb(long tb, int n, uint32_t dest) +{ + if (n == 0) + gen_op_goto_tb0(TBPARAM(tb)); + else + gen_op_goto_tb1(TBPARAM(tb)); + gen_op_set_T1(dest); + gen_op_b_T1(); + gen_op_set_T0(tb + n); + gen_op_exit_tb(); +} + /* b ba bl bla */ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) { @@ -1736,7 +1754,7 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) if (LK(ctx->opcode)) { gen_op_setlr(ctx->nip); } - gen_op_b((long)ctx->tb, target); + gen_jmp_tb((long)ctx->tb, 0, target); ctx->exception = EXCP_BRANCH; } @@ -1787,7 +1805,7 @@ static inline void gen_bcond(DisasContext *ctx, int type) case 4: case 6: if (type == BCOND_IM) { - gen_op_b((long)ctx->tb, target); + gen_jmp_tb((long)ctx->tb, 0, target); } else { gen_op_b_T1(); } @@ -1827,7 +1845,11 @@ static inline void gen_bcond(DisasContext *ctx, int type) } } if (type == BCOND_IM) { - gen_op_btest((long)ctx->tb, target, ctx->nip); + int l1 = gen_new_label(); + gen_op_jz_T0(l1); + gen_jmp_tb((long)ctx->tb, 0, target); + gen_set_label(l1); + gen_jmp_tb((long)ctx->tb, 1, ctx->nip); } else { gen_op_btest_T1(ctx->nip); } @@ -2459,6 +2481,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opparam_ptr = gen_opparam_buf; + nb_gen_labels = 0; ctx.nip = pc_start; ctx.tb = tb; ctx.exception = EXCP_NONE; @@ -2575,7 +2598,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, #endif } if (ctx.exception == EXCP_NONE) { - gen_op_b((unsigned long)ctx.tb, ctx.nip); + gen_jmp_tb((long)ctx.tb, 0, ctx.nip); } else if (ctx.exception != EXCP_BRANCH) { gen_op_set_T0(0); } |