mirror of https://github.com/xemu-project/xemu.git
target/alpha: Implement CF_PCREL
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20240503072014.24751-10-philmd@linaro.org>
This commit is contained in:
parent
b1a3eacf31
commit
23bb086350
|
@ -38,12 +38,27 @@ static vaddr alpha_cpu_get_pc(CPUState *cs)
|
|||
return env->pc;
|
||||
}
|
||||
|
||||
static void alpha_cpu_synchronize_from_tb(CPUState *cs,
|
||||
const TranslationBlock *tb)
|
||||
{
|
||||
/* The program counter is always up to date with CF_PCREL. */
|
||||
if (!(tb_cflags(tb) & CF_PCREL)) {
|
||||
CPUAlphaState *env = cpu_env(cs);
|
||||
env->pc = tb->pc;
|
||||
}
|
||||
}
|
||||
|
||||
static void alpha_restore_state_to_opc(CPUState *cs,
|
||||
const TranslationBlock *tb,
|
||||
const uint64_t *data)
|
||||
{
|
||||
CPUAlphaState *env = cpu_env(cs);
|
||||
env->pc = data[0];
|
||||
|
||||
if (tb_cflags(tb) & CF_PCREL) {
|
||||
env->pc = (env->pc & TARGET_PAGE_MASK) | data[0];
|
||||
} else {
|
||||
env->pc = data[0];
|
||||
}
|
||||
}
|
||||
|
||||
static bool alpha_cpu_has_work(CPUState *cs)
|
||||
|
@ -78,6 +93,11 @@ static void alpha_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
AlphaCPUClass *acc = ALPHA_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* Use pc-relative instructions in system-mode */
|
||||
cs->tcg_cflags |= CF_PCREL;
|
||||
#endif
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
|
@ -190,6 +210,7 @@ static const struct SysemuCPUOps alpha_sysemu_ops = {
|
|||
|
||||
static const TCGCPUOps alpha_tcg_ops = {
|
||||
.initialize = alpha_translate_init,
|
||||
.synchronize_from_tb = alpha_cpu_synchronize_from_tb,
|
||||
.restore_state_to_opc = alpha_restore_state_to_opc,
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
|
|
@ -54,6 +54,9 @@ struct DisasContext {
|
|||
uint32_t tbflags;
|
||||
int mem_idx;
|
||||
|
||||
/* True if generating pc-relative code. */
|
||||
bool pcrel;
|
||||
|
||||
/* implver and amask values for this CPU. */
|
||||
int implver;
|
||||
int amask;
|
||||
|
@ -254,7 +257,12 @@ static void st_flag_byte(TCGv val, unsigned shift)
|
|||
|
||||
static void gen_pc_disp(DisasContext *ctx, TCGv dest, int32_t disp)
|
||||
{
|
||||
tcg_gen_movi_i64(dest, ctx->base.pc_next + disp);
|
||||
uint64_t addr = ctx->base.pc_next + disp;
|
||||
if (ctx->pcrel) {
|
||||
tcg_gen_addi_i64(dest, cpu_pc, addr - ctx->base.pc_first);
|
||||
} else {
|
||||
tcg_gen_movi_i64(dest, addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_excp_1(int exception, int error_code)
|
||||
|
@ -433,8 +441,14 @@ static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb,
|
|||
static void gen_goto_tb(DisasContext *ctx, int idx, int32_t disp)
|
||||
{
|
||||
if (translator_use_goto_tb(&ctx->base, ctx->base.pc_next + disp)) {
|
||||
tcg_gen_goto_tb(idx);
|
||||
gen_pc_disp(ctx, cpu_pc, disp);
|
||||
/* With PCREL, PC must always be up-to-date. */
|
||||
if (ctx->pcrel) {
|
||||
gen_pc_disp(ctx, cpu_pc, disp);
|
||||
tcg_gen_goto_tb(idx);
|
||||
} else {
|
||||
tcg_gen_goto_tb(idx);
|
||||
gen_pc_disp(ctx, cpu_pc, disp);
|
||||
}
|
||||
tcg_gen_exit_tb(ctx->base.tb, idx);
|
||||
} else {
|
||||
gen_pc_disp(ctx, cpu_pc, disp);
|
||||
|
@ -2852,6 +2866,7 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
|
|||
|
||||
ctx->tbflags = ctx->base.tb->flags;
|
||||
ctx->mem_idx = alpha_env_mmu_index(env);
|
||||
ctx->pcrel = ctx->base.tb->cflags & CF_PCREL;
|
||||
ctx->implver = env->implver;
|
||||
ctx->amask = env->amask;
|
||||
|
||||
|
@ -2887,7 +2902,13 @@ static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu)
|
|||
|
||||
static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
|
||||
{
|
||||
tcg_gen_insn_start(dcbase->pc_next);
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
|
||||
if (ctx->pcrel) {
|
||||
tcg_gen_insn_start(dcbase->pc_next & ~TARGET_PAGE_MASK);
|
||||
} else {
|
||||
tcg_gen_insn_start(dcbase->pc_next);
|
||||
}
|
||||
}
|
||||
|
||||
static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||
|
|
Loading…
Reference in New Issue