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,13 +38,28 @@ static vaddr alpha_cpu_get_pc(CPUState *cs)
|
||||||
return env->pc;
|
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,
|
static void alpha_restore_state_to_opc(CPUState *cs,
|
||||||
const TranslationBlock *tb,
|
const TranslationBlock *tb,
|
||||||
const uint64_t *data)
|
const uint64_t *data)
|
||||||
{
|
{
|
||||||
CPUAlphaState *env = cpu_env(cs);
|
CPUAlphaState *env = cpu_env(cs);
|
||||||
|
|
||||||
|
if (tb_cflags(tb) & CF_PCREL) {
|
||||||
|
env->pc = (env->pc & TARGET_PAGE_MASK) | data[0];
|
||||||
|
} else {
|
||||||
env->pc = data[0];
|
env->pc = data[0];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool alpha_cpu_has_work(CPUState *cs)
|
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);
|
AlphaCPUClass *acc = ALPHA_CPU_GET_CLASS(dev);
|
||||||
Error *local_err = NULL;
|
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);
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
@ -190,6 +210,7 @@ static const struct SysemuCPUOps alpha_sysemu_ops = {
|
||||||
|
|
||||||
static const TCGCPUOps alpha_tcg_ops = {
|
static const TCGCPUOps alpha_tcg_ops = {
|
||||||
.initialize = alpha_translate_init,
|
.initialize = alpha_translate_init,
|
||||||
|
.synchronize_from_tb = alpha_cpu_synchronize_from_tb,
|
||||||
.restore_state_to_opc = alpha_restore_state_to_opc,
|
.restore_state_to_opc = alpha_restore_state_to_opc,
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
|
|
@ -54,6 +54,9 @@ struct DisasContext {
|
||||||
uint32_t tbflags;
|
uint32_t tbflags;
|
||||||
int mem_idx;
|
int mem_idx;
|
||||||
|
|
||||||
|
/* True if generating pc-relative code. */
|
||||||
|
bool pcrel;
|
||||||
|
|
||||||
/* implver and amask values for this CPU. */
|
/* implver and amask values for this CPU. */
|
||||||
int implver;
|
int implver;
|
||||||
int amask;
|
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)
|
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)
|
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)
|
static void gen_goto_tb(DisasContext *ctx, int idx, int32_t disp)
|
||||||
{
|
{
|
||||||
if (translator_use_goto_tb(&ctx->base, ctx->base.pc_next + disp)) {
|
if (translator_use_goto_tb(&ctx->base, ctx->base.pc_next + 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);
|
tcg_gen_goto_tb(idx);
|
||||||
gen_pc_disp(ctx, cpu_pc, disp);
|
gen_pc_disp(ctx, cpu_pc, disp);
|
||||||
|
}
|
||||||
tcg_gen_exit_tb(ctx->base.tb, idx);
|
tcg_gen_exit_tb(ctx->base.tb, idx);
|
||||||
} else {
|
} else {
|
||||||
gen_pc_disp(ctx, cpu_pc, disp);
|
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->tbflags = ctx->base.tb->flags;
|
||||||
ctx->mem_idx = alpha_env_mmu_index(env);
|
ctx->mem_idx = alpha_env_mmu_index(env);
|
||||||
|
ctx->pcrel = ctx->base.tb->cflags & CF_PCREL;
|
||||||
ctx->implver = env->implver;
|
ctx->implver = env->implver;
|
||||||
ctx->amask = env->amask;
|
ctx->amask = env->amask;
|
||||||
|
|
||||||
|
@ -2887,8 +2902,14 @@ static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu)
|
||||||
|
|
||||||
static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
|
static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
{
|
{
|
||||||
|
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);
|
tcg_gen_insn_start(dcbase->pc_next);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue