target/sh4: move DELAY_SLOT_TRUE flag into a separate global
Instead of using one bit of the env flags to store the condition of the next delay slot, use a separate global. It simplifies reading and writing the flags variable and also removes some confusion between ctx->envflags and env->flags. Note that the global is first transfered to a temp in order to be able to discard the global before the brcond. Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
24b09d9d8b
commit
47b9f4d5a4
|
@ -92,13 +92,6 @@
|
||||||
|
|
||||||
#define DELAY_SLOT (1 << 0)
|
#define DELAY_SLOT (1 << 0)
|
||||||
#define DELAY_SLOT_CONDITIONAL (1 << 1)
|
#define DELAY_SLOT_CONDITIONAL (1 << 1)
|
||||||
#define DELAY_SLOT_TRUE (1 << 2)
|
|
||||||
/* The dynamic value of the DELAY_SLOT_TRUE flag determines whether the jump
|
|
||||||
* after the delay slot should be taken or not. It is calculated from SR_T.
|
|
||||||
*
|
|
||||||
* It is unclear if it is permitted to modify the SR_T flag in a delay slot.
|
|
||||||
* The use of DELAY_SLOT_TRUE flag makes us accept such SR_T modification.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct tlb_t {
|
typedef struct tlb_t {
|
||||||
uint32_t vpn; /* virtual page number */
|
uint32_t vpn; /* virtual page number */
|
||||||
|
@ -148,7 +141,8 @@ typedef struct CPUSH4State {
|
||||||
uint32_t sgr; /* saved global register 15 */
|
uint32_t sgr; /* saved global register 15 */
|
||||||
uint32_t dbr; /* debug base register */
|
uint32_t dbr; /* debug base register */
|
||||||
uint32_t pc; /* program counter */
|
uint32_t pc; /* program counter */
|
||||||
uint32_t delayed_pc; /* target of delayed jump */
|
uint32_t delayed_pc; /* target of delayed branch */
|
||||||
|
uint32_t delayed_cond; /* condition of delayed branch */
|
||||||
uint32_t mach; /* multiply and accumulate high */
|
uint32_t mach; /* multiply and accumulate high */
|
||||||
uint32_t macl; /* multiply and accumulate low */
|
uint32_t macl; /* multiply and accumulate low */
|
||||||
uint32_t pr; /* procedure register */
|
uint32_t pr; /* procedure register */
|
||||||
|
|
|
@ -168,7 +168,7 @@ void superh_cpu_do_interrupt(CPUState *cs)
|
||||||
/* Branch instruction should be executed again before delay slot. */
|
/* Branch instruction should be executed again before delay slot. */
|
||||||
env->spc -= 2;
|
env->spc -= 2;
|
||||||
/* Clear flags for exception/interrupt routine. */
|
/* Clear flags for exception/interrupt routine. */
|
||||||
env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL | DELAY_SLOT_TRUE);
|
env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_exp) {
|
if (do_exp) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_ldst;
|
||||||
static TCGv cpu_fregs[32];
|
static TCGv cpu_fregs[32];
|
||||||
|
|
||||||
/* internal register indexes */
|
/* internal register indexes */
|
||||||
static TCGv cpu_flags, cpu_delayed_pc;
|
static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond;
|
||||||
|
|
||||||
#include "exec/gen-icount.h"
|
#include "exec/gen-icount.h"
|
||||||
|
|
||||||
|
@ -147,6 +147,10 @@ void sh4_translate_init(void)
|
||||||
cpu_delayed_pc = tcg_global_mem_new_i32(cpu_env,
|
cpu_delayed_pc = tcg_global_mem_new_i32(cpu_env,
|
||||||
offsetof(CPUSH4State, delayed_pc),
|
offsetof(CPUSH4State, delayed_pc),
|
||||||
"_delayed_pc_");
|
"_delayed_pc_");
|
||||||
|
cpu_delayed_cond = tcg_global_mem_new_i32(cpu_env,
|
||||||
|
offsetof(CPUSH4State,
|
||||||
|
delayed_cond),
|
||||||
|
"_delayed_cond_");
|
||||||
cpu_ldst = tcg_global_mem_new_i32(cpu_env,
|
cpu_ldst = tcg_global_mem_new_i32(cpu_env,
|
||||||
offsetof(CPUSH4State, ldst), "_ldst_");
|
offsetof(CPUSH4State, ldst), "_ldst_");
|
||||||
|
|
||||||
|
@ -252,11 +256,12 @@ static void gen_jump(DisasContext * ctx)
|
||||||
|
|
||||||
static inline void gen_branch_slot(uint32_t delayed_pc, int t)
|
static inline void gen_branch_slot(uint32_t delayed_pc, int t)
|
||||||
{
|
{
|
||||||
TCGLabel *label = gen_new_label();
|
|
||||||
tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
|
tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
|
||||||
tcg_gen_brcondi_i32(t ? TCG_COND_EQ : TCG_COND_NE, cpu_sr_t, 0, label);
|
if (t) {
|
||||||
tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
|
tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
|
||||||
gen_set_label(label);
|
} else {
|
||||||
|
tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Immediate conditional jump (bt or bf) */
|
/* Immediate conditional jump (bt or bf) */
|
||||||
|
@ -278,18 +283,17 @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
|
||||||
|
|
||||||
l1 = gen_new_label();
|
l1 = gen_new_label();
|
||||||
ds = tcg_temp_new();
|
ds = tcg_temp_new();
|
||||||
tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE);
|
tcg_gen_mov_i32(ds, cpu_delayed_cond);
|
||||||
|
tcg_gen_discard_i32(cpu_delayed_cond);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
|
tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
|
||||||
gen_goto_tb(ctx, 1, ctx->pc + 2);
|
gen_goto_tb(ctx, 1, ctx->pc + 2);
|
||||||
gen_set_label(l1);
|
gen_set_label(l1);
|
||||||
tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
|
|
||||||
gen_jump(ctx);
|
gen_jump(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_store_flags(uint32_t flags)
|
static inline void gen_store_flags(uint32_t flags)
|
||||||
{
|
{
|
||||||
tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
|
tcg_gen_movi_i32(cpu_flags, flags);
|
||||||
tcg_gen_ori_i32(cpu_flags, cpu_flags, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_load_fpr64(TCGv_i64 t, int reg)
|
static inline void gen_load_fpr64(TCGv_i64 t, int reg)
|
||||||
|
|
Loading…
Reference in a new issue