* [Qemu-devel] [PATCH 3/3] target-alpha: Inline hw_ret
2015-06-09 21:12 Richard Henderson
@ 2015-06-09 21:12 ` Richard Henderson
0 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2015-06-09 21:12 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 2 --
target-alpha/sys_helper.c | 8 --------
target-alpha/translate.c | 15 ++++++++++-----
3 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index e7f0450..42bb247 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -91,8 +91,6 @@ DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_2(ieee_input_s, TCG_CALL_NO_WG, void, env, i64)
#if !defined (CONFIG_USER_ONLY)
-DEF_HELPER_2(hw_ret, void, env, i64)
-
DEF_HELPER_2(ldl_phys, i64, env, i64)
DEF_HELPER_2(ldq_phys, i64, env, i64)
DEF_HELPER_2(ldl_l_phys, i64, env, i64)
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
index 211991d..22e5b08 100644
--- a/target-alpha/sys_helper.c
+++ b/target-alpha/sys_helper.c
@@ -40,14 +40,6 @@ uint64_t helper_load_pcc(CPUAlphaState *env)
/* PALcode support special instructions */
#ifndef CONFIG_USER_ONLY
-void helper_hw_ret(CPUAlphaState *env, uint64_t a)
-{
- env->pc = a & ~3;
- env->intr_flag = 0;
- env->lock_addr = -1;
- env->pal_mode = a & 1;
-}
-
void helper_tbia(CPUAlphaState *env)
{
tlb_flush(CPU(alpha_env_get_cpu(env)), 1);
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 04c42fc..82d492b 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2635,13 +2635,18 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
address from EXC_ADDR. This turns out to be useful for our
emulation PALcode, so continue to accept it. */
- tmp = tcg_temp_new();
- tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
- gen_helper_hw_ret(cpu_env, tmp);
- tcg_temp_free(tmp);
+ ctx->lit = vb = tcg_temp_new();
+ tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr));
} else {
- gen_helper_hw_ret(cpu_env, load_gpr(ctx, rb));
+ vb = load_gpr(ctx, rb);
}
+ tmp = tcg_temp_new();
+ tcg_gen_movi_i64(tmp, 0);
+ tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, intr_flag));
+ tcg_gen_movi_i64(cpu_lock_addr, -1);
+ tcg_gen_andi_i64(tmp, vb, 1);
+ tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
+ tcg_gen_andi_i64(cpu_pc, vb, ~3);
ret = EXIT_PC_UPDATED;
break;
#else
--
2.1.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements
@ 2015-06-09 21:13 Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 1/3] target-alpha: Use separate TCGv temporaries for the shadow registers Richard Henderson
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Richard Henderson @ 2015-06-09 21:13 UTC (permalink / raw)
To: qemu-devel
Rather than copying around a block of 8 registers when we swap modes,
let the translator map code generated for PALmode to the shadow regs
directly. This simplifies PALmode entry and exit sufficiently to
allow these insns to be performed inline.
Sadly, the speedup for this is in the noise. But I still think it
makes sense.
r~
Richard Henderson (3):
target-alpha: Use separate TCGv temporaries for the shadow registers
target-alpha: Inline call_pal
target-alpha: Inline hw_ret
target-alpha/cpu.h | 3 +-
target-alpha/gdbstub.c | 4 +-
target-alpha/helper.c | 63 ++++++---------
target-alpha/helper.h | 3 -
target-alpha/machine.c | 4 +-
target-alpha/sys_helper.c | 22 -----
target-alpha/translate.c | 201 ++++++++++++++++++++++++++++++----------------
7 files changed, 166 insertions(+), 134 deletions(-)
--
2.1.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 1/3] target-alpha: Use separate TCGv temporaries for the shadow registers
2015-06-09 21:13 [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements Richard Henderson
@ 2015-06-09 21:13 ` Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 2/3] target-alpha: Inline call_pal Richard Henderson
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2015-06-09 21:13 UTC (permalink / raw)
To: qemu-devel
This avoids having to manually swap them around when swapping to and
from PALmode. We simply encode the shadow registers into the translation.
The VMStateDescription version changes, because the meaning of "shadow"
changes in the save file when in PALmode. It would be possible to fix
this, but I don't think it's worth the effort.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 3 +-
target-alpha/gdbstub.c | 4 +-
target-alpha/helper.c | 63 ++++++++-----------
target-alpha/machine.c | 4 +-
target-alpha/sys_helper.c | 10 +--
target-alpha/translate.c | 153 ++++++++++++++++++++++++++++++----------------
6 files changed, 134 insertions(+), 103 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 2a4d5cb..402e3ac 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -445,8 +445,9 @@ void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
+uint64_t cpu_alpha_load_gr(CPUAlphaState *env, unsigned reg);
+void cpu_alpha_store_gr(CPUAlphaState *env, unsigned reg, uint64_t val);
#ifndef CONFIG_USER_ONLY
-void swap_shadow_regs(CPUAlphaState *env);
QEMU_NORETURN void alpha_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
bool is_write, bool is_exec,
int unused, unsigned size);
diff --git a/target-alpha/gdbstub.c b/target-alpha/gdbstub.c
index 980f140..99a4051 100644
--- a/target-alpha/gdbstub.c
+++ b/target-alpha/gdbstub.c
@@ -30,7 +30,7 @@ int alpha_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
switch (n) {
case 0 ... 30:
- val = env->ir[n];
+ val = cpu_alpha_load_gr(env, n);
break;
case 32 ... 62:
d.d = env->fir[n - 32];
@@ -66,7 +66,7 @@ int alpha_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
switch (n) {
case 0 ... 30:
- env->ir[n] = tmp;
+ cpu_alpha_store_gr(env, n, tmp);
break;
case 32 ... 62:
d.ll = tmp;
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 46b8ef9..5a85335 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -79,6 +79,30 @@ void helper_store_fpcr(CPUAlphaState *env, uint64_t val)
cpu_alpha_store_fpcr(env, val);
}
+static uint64_t *cpu_alpha_addr_gr(CPUAlphaState *env, unsigned reg)
+{
+#ifndef CONFIG_USER_ONLY
+ if (env->pal_mode) {
+ if (reg >= 8 && reg <= 14) {
+ return &env->shadow[reg - 8];
+ } else if (reg == 25) {
+ return &env->shadow[7];
+ }
+ }
+#endif
+ return &env->ir[reg];
+}
+
+uint64_t cpu_alpha_load_gr(CPUAlphaState *env, unsigned reg)
+{
+ return *cpu_alpha_addr_gr(env, reg);
+}
+
+void cpu_alpha_store_gr(CPUAlphaState *env, unsigned reg, uint64_t val)
+{
+ *cpu_alpha_addr_gr(env, reg) = val;
+}
+
#if defined(CONFIG_USER_ONLY)
int alpha_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
int rw, int mmu_idx)
@@ -90,38 +114,6 @@ int alpha_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
return 1;
}
#else
-void swap_shadow_regs(CPUAlphaState *env)
-{
- uint64_t i0, i1, i2, i3, i4, i5, i6, i7;
-
- i0 = env->ir[8];
- i1 = env->ir[9];
- i2 = env->ir[10];
- i3 = env->ir[11];
- i4 = env->ir[12];
- i5 = env->ir[13];
- i6 = env->ir[14];
- i7 = env->ir[25];
-
- env->ir[8] = env->shadow[0];
- env->ir[9] = env->shadow[1];
- env->ir[10] = env->shadow[2];
- env->ir[11] = env->shadow[3];
- env->ir[12] = env->shadow[4];
- env->ir[13] = env->shadow[5];
- env->ir[14] = env->shadow[6];
- env->ir[25] = env->shadow[7];
-
- env->shadow[0] = i0;
- env->shadow[1] = i1;
- env->shadow[2] = i2;
- env->shadow[3] = i3;
- env->shadow[4] = i4;
- env->shadow[5] = i5;
- env->shadow[6] = i6;
- env->shadow[7] = i7;
-}
-
/* Returns the OSF/1 entMM failure indication, or -1 on success. */
static int get_physical_address(CPUAlphaState *env, target_ulong addr,
int prot_need, int mmu_idx,
@@ -375,10 +367,7 @@ void alpha_cpu_do_interrupt(CPUState *cs)
env->pc = env->palbr + i;
/* Switch to PALmode. */
- if (!env->pal_mode) {
- env->pal_mode = 1;
- swap_shadow_regs(env);
- }
+ env->pal_mode = 1;
#endif /* !USER_ONLY */
}
@@ -443,7 +432,7 @@ void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
env->pc, env->ps);
for (i = 0; i < 31; i++) {
cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
- linux_reg_names[i], env->ir[i]);
+ linux_reg_names[i], cpu_alpha_load_gr(env, i));
if ((i % 3) == 2)
cpu_fprintf(f, "\n");
}
diff --git a/target-alpha/machine.c b/target-alpha/machine.c
index e796bbe..d9bf977 100644
--- a/target-alpha/machine.c
+++ b/target-alpha/machine.c
@@ -70,8 +70,8 @@ static VMStateField vmstate_env_fields[] = {
static const VMStateDescription vmstate_env = {
.name = "env",
- .version_id = 1,
- .minimum_version_id = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
.fields = vmstate_env_fields,
};
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
index ae2e174..fab1aa0 100644
--- a/target-alpha/sys_helper.c
+++ b/target-alpha/sys_helper.c
@@ -45,10 +45,7 @@ void helper_hw_ret(CPUAlphaState *env, uint64_t a)
env->pc = a & ~3;
env->intr_flag = 0;
env->lock_addr = -1;
- if ((a & 1) == 0) {
- env->pal_mode = 0;
- swap_shadow_regs(env);
- }
+ env->pal_mode = a & 1;
}
void helper_call_pal(CPUAlphaState *env, uint64_t pc, uint64_t entry_ofs)
@@ -56,10 +53,7 @@ void helper_call_pal(CPUAlphaState *env, uint64_t pc, uint64_t entry_ofs)
int pal_mode = env->pal_mode;
env->exc_addr = pc | pal_mode;
env->pc = env->palbr + entry_ofs;
- if (!pal_mode) {
- env->pal_mode = 1;
- swap_shadow_regs(env);
- }
+ env->pal_mode = 1;
}
void helper_tbia(CPUAlphaState *env)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index e9927b5..4d78c4c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -52,6 +52,9 @@ struct DisasContext {
/* implver value for this CPU. */
int implver;
+ /* The set of registers active in the current context. */
+ TCGv *ir;
+
/* Temporaries for $31 and $f31 as source and destination. */
TCGv zero;
TCGv sink;
@@ -86,13 +89,17 @@ typedef enum {
/* global register indexes */
static TCGv_ptr cpu_env;
-static TCGv cpu_ir[31];
+static TCGv cpu_std_ir[31];
static TCGv cpu_fir[31];
static TCGv cpu_pc;
static TCGv cpu_lock_addr;
static TCGv cpu_lock_st_addr;
static TCGv cpu_lock_value;
+#ifndef CONFIG_USER_ONLY
+static TCGv cpu_pal_ir[31];
+#endif
+
#include "exec/gen-icount.h"
void alpha_translate_init(void)
@@ -122,6 +129,12 @@ void alpha_translate_init(void)
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30"
};
+#ifndef CONFIG_USER_ONLY
+ static const char shadow_names[8][8] = {
+ "pal_t7", "pal_s0", "pal_s1", "pal_s2",
+ "pal_s3", "pal_s4", "pal_s5", "pal_t11"
+ };
+#endif
static bool done_init = 0;
int i;
@@ -134,9 +147,9 @@ void alpha_translate_init(void)
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
for (i = 0; i < 31; i++) {
- cpu_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
- offsetof(CPUAlphaState, ir[i]),
- greg_names[i]);
+ cpu_std_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUAlphaState, ir[i]),
+ greg_names[i]);
}
for (i = 0; i < 31; i++) {
@@ -145,6 +158,17 @@ void alpha_translate_init(void)
freg_names[i]);
}
+#ifndef CONFIG_USER_ONLY
+ memcpy(cpu_pal_ir, cpu_std_ir, sizeof(cpu_pal_ir));
+ for (i = 0; i < 8; i++) {
+ int r = (i == 7 ? 25 : i + 8);
+ cpu_pal_ir[r] = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUAlphaState,
+ shadow[i]),
+ shadow_names[i]);
+ }
+#endif
+
for (i = 0; i < ARRAY_SIZE(vars); ++i) {
const GlobalVar *v = &vars[i];
*v->var = tcg_global_mem_new_i64(TCG_AREG0, v->ofs, v->name);
@@ -170,7 +194,7 @@ static TCGv dest_sink(DisasContext *ctx)
static TCGv load_gpr(DisasContext *ctx, unsigned reg)
{
if (likely(reg < 31)) {
- return cpu_ir[reg];
+ return ctx->ir[reg];
} else {
return load_zero(ctx);
}
@@ -183,7 +207,7 @@ static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
ctx->lit = tcg_const_i64(lit);
return ctx->lit;
} else if (likely(reg < 31)) {
- return cpu_ir[reg];
+ return ctx->ir[reg];
} else {
return load_zero(ctx);
}
@@ -192,7 +216,7 @@ static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
{
if (likely(reg < 31)) {
- return cpu_ir[reg];
+ return ctx->ir[reg];
} else {
return dest_sink(ctx);
}
@@ -304,7 +328,7 @@ static inline void gen_load_mem(DisasContext *ctx,
addr = tmp;
}
- va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
+ va = (fp ? cpu_fir[ra] : ctx->ir[ra]);
tcg_gen_qemu_load(va, addr, ctx->mem_idx);
tcg_temp_free(tmp);
@@ -399,13 +423,13 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, quad ? MO_LEQ : MO_LESL);
tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
- tcg_gen_qemu_st_i64(cpu_ir[ra], addr, ctx->mem_idx,
+ tcg_gen_qemu_st_i64(ctx->ir[ra], addr, ctx->mem_idx,
quad ? MO_LEQ : MO_LEUL);
- tcg_gen_movi_i64(cpu_ir[ra], 1);
+ tcg_gen_movi_i64(ctx->ir[ra], 1);
tcg_gen_br(lab_done);
gen_set_label(lab_fail);
- tcg_gen_movi_i64(cpu_ir[ra], 0);
+ tcg_gen_movi_i64(ctx->ir[ra], 0);
gen_set_label(lab_done);
tcg_gen_movi_i64(cpu_lock_addr, -1);
@@ -444,7 +468,7 @@ static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
uint64_t dest = ctx->pc + (disp << 2);
if (ra != 31) {
- tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
+ tcg_gen_movi_i64(ctx->ir[ra], ctx->pc);
}
/* Notice branch-to-next; used to initialize RA with the PC. */
@@ -1059,12 +1083,13 @@ static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
}
}
-static void gen_rx(int ra, int set)
+static void gen_rx(DisasContext *ctx, int ra, int set)
{
TCGv_i32 tmp;
if (ra != 31) {
- tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUAlphaState, intr_flag));
+ tcg_gen_ld8u_i64(ctx->ir[ra], cpu_env,
+ offsetof(CPUAlphaState, intr_flag));
}
tmp = tcg_const_i32(set);
@@ -1086,12 +1111,12 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
break;
case 0x9E:
/* RDUNIQUE */
- tcg_gen_ld_i64(cpu_ir[IR_V0], cpu_env,
+ tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
offsetof(CPUAlphaState, unique));
break;
case 0x9F:
/* WRUNIQUE */
- tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
+ tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
offsetof(CPUAlphaState, unique));
break;
default:
@@ -1115,17 +1140,17 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
break;
case 0x2D:
/* WRVPTPTR */
- tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
+ tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
offsetof(CPUAlphaState, vptptr));
break;
case 0x31:
/* WRVAL */
- tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
+ tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
offsetof(CPUAlphaState, sysval));
break;
case 0x32:
/* RDVAL */
- tcg_gen_ld_i64(cpu_ir[IR_V0], cpu_env,
+ tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
offsetof(CPUAlphaState, sysval));
break;
@@ -1135,12 +1160,12 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
/* Note that we already know we're in kernel mode, so we know
that PS only contains the 3 IPL bits. */
- tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env,
+ tcg_gen_ld8u_i64(ctx->ir[IR_V0], cpu_env,
offsetof(CPUAlphaState, ps));
/* But make sure and store only the 3 IPL bits from the user. */
tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, cpu_ir[IR_A0], PS_INT_MASK);
+ tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, ps));
tcg_temp_free(tmp);
break;
@@ -1148,22 +1173,22 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
case 0x36:
/* RDPS */
- tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env,
+ tcg_gen_ld8u_i64(ctx->ir[IR_V0], cpu_env,
offsetof(CPUAlphaState, ps));
break;
case 0x38:
/* WRUSP */
- tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
+ tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
offsetof(CPUAlphaState, usp));
break;
case 0x3A:
/* RDUSP */
- tcg_gen_ld_i64(cpu_ir[IR_V0], cpu_env,
+ tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
offsetof(CPUAlphaState, usp));
break;
case 0x3C:
/* WHAMI */
- tcg_gen_ld32s_i64(cpu_ir[IR_V0], cpu_env,
+ tcg_gen_ld32s_i64(ctx->ir[IR_V0], cpu_env,
-offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index));
break;
@@ -1228,8 +1253,6 @@ static int cpu_pr_data(int pr)
case 11: return offsetof(CPUAlphaState, sysval);
case 12: return offsetof(CPUAlphaState, usp);
- case 32 ... 39:
- return offsetof(CPUAlphaState, shadow[pr - 32]);
case 40 ... 63:
return offsetof(CPUAlphaState, scratch[pr - 40]);
@@ -1241,36 +1264,48 @@ static int cpu_pr_data(int pr)
static ExitStatus gen_mfpr(DisasContext *ctx, TCGv va, int regno)
{
- int data = cpu_pr_data(regno);
-
- /* Special help for VMTIME and WALLTIME. */
- if (regno == 250 || regno == 249) {
- void (*helper)(TCGv) = gen_helper_get_walltime;
- if (regno == 249) {
- helper = gen_helper_get_vmtime;
- }
- if (ctx->tb->cflags & CF_USE_ICOUNT) {
+ void (*helper)(TCGv);
+ int data;
+
+ switch (regno) {
+ case 32 ... 39:
+ /* Accessing the "non-shadow" general registers. */
+ regno = regno == 39 ? 25 : regno - 32 + 8;
+ tcg_gen_mov_i64(va, cpu_std_ir[regno]);
+ break;
+
+ case 250: /* WALLTIME */
+ helper = gen_helper_get_walltime;
+ goto do_helper;
+ case 249: /* VMTIME */
+ helper = gen_helper_get_vmtime;
+ do_helper:
+ if (use_icount) {
gen_io_start();
helper(va);
gen_io_end();
return EXIT_PC_STALE;
} else {
helper(va);
- return NO_EXIT;
}
- }
+ break;
- /* The basic registers are data only, and unknown registers
- are read-zero, write-ignore. */
- if (data == 0) {
- tcg_gen_movi_i64(va, 0);
- } else if (data & PR_BYTE) {
- tcg_gen_ld8u_i64(va, cpu_env, data & ~PR_BYTE);
- } else if (data & PR_LONG) {
- tcg_gen_ld32s_i64(va, cpu_env, data & ~PR_LONG);
- } else {
- tcg_gen_ld_i64(va, cpu_env, data);
+ default:
+ /* The basic registers are data only, and unknown registers
+ are read-zero, write-ignore. */
+ data = cpu_pr_data(regno);
+ if (data == 0) {
+ tcg_gen_movi_i64(va, 0);
+ } else if (data & PR_BYTE) {
+ tcg_gen_ld8u_i64(va, cpu_env, data & ~PR_BYTE);
+ } else if (data & PR_LONG) {
+ tcg_gen_ld32s_i64(va, cpu_env, data & ~PR_LONG);
+ } else {
+ tcg_gen_ld_i64(va, cpu_env, data);
+ }
+ break;
}
+
return NO_EXIT;
}
@@ -1316,6 +1351,12 @@ static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
gen_helper_tb_flush(cpu_env);
return EXIT_PC_STALE;
+ case 32 ... 39:
+ /* Accessing the "non-shadow" general registers. */
+ regno = regno == 39 ? 25 : regno - 32 + 8;
+ tcg_gen_mov_i64(cpu_std_ir[regno], vb);
+ break;
+
default:
/* The basic registers are data only, and unknown registers
are read-zero, write-ignore. */
@@ -2295,14 +2336,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0xE000:
/* RC */
- gen_rx(ra, 0);
+ gen_rx(ctx, ra, 0);
break;
case 0xE800:
/* ECB */
break;
case 0xF000:
/* RS */
- gen_rx(ra, 1);
+ gen_rx(ctx, ra, 1);
break;
case 0xF800:
/* WH64 */
@@ -2334,7 +2375,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
vb = load_gpr(ctx, rb);
tcg_gen_andi_i64(cpu_pc, vb, ~3);
if (ra != 31) {
- tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
+ tcg_gen_movi_i64(ctx->ir[ra], ctx->pc);
}
ret = EXIT_PC_UPDATED;
break;
@@ -2374,10 +2415,10 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
goto invalid_opc;
break;
case 0x6:
- /* Incpu_ir[ra]id */
+ /* Invalid */
goto invalid_opc;
case 0x7:
- /* Incpu_ir[ra]id */
+ /* Invaliid */
goto invalid_opc;
case 0x8:
/* Longword virtual access (hw_ldl) */
@@ -2817,6 +2858,12 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
ctx.implver = env->implver;
ctx.singlestep_enabled = cs->singlestep_enabled;
+#ifdef CONFIG_USER_ONLY
+ ctx.ir = cpu_std_ir;
+#else
+ ctx.ir = (tb->flags & TB_FLAGS_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
+#endif
+
/* ??? Every TB begins with unset rounding mode, to be initialized on
the first fp insn of the TB. Alternately we could define a proper
default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
--
2.1.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 2/3] target-alpha: Inline call_pal
2015-06-09 21:13 [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 1/3] target-alpha: Use separate TCGv temporaries for the shadow registers Richard Henderson
@ 2015-06-09 21:13 ` Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 3/3] target-alpha: Inline hw_ret Richard Henderson
2015-06-12 22:12 ` [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements Aurelien Jarno
3 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2015-06-09 21:13 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 1 -
target-alpha/sys_helper.c | 8 --------
target-alpha/translate.c | 33 ++++++++++++++++++++++++---------
3 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index d221f0d..e7f0450 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -92,7 +92,6 @@ DEF_HELPER_FLAGS_2(ieee_input_s, TCG_CALL_NO_WG, void, env, i64)
#if !defined (CONFIG_USER_ONLY)
DEF_HELPER_2(hw_ret, void, env, i64)
-DEF_HELPER_3(call_pal, void, env, i64, i64)
DEF_HELPER_2(ldl_phys, i64, env, i64)
DEF_HELPER_2(ldq_phys, i64, env, i64)
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
index fab1aa0..211991d 100644
--- a/target-alpha/sys_helper.c
+++ b/target-alpha/sys_helper.c
@@ -48,14 +48,6 @@ void helper_hw_ret(CPUAlphaState *env, uint64_t a)
env->pal_mode = a & 1;
}
-void helper_call_pal(CPUAlphaState *env, uint64_t pc, uint64_t entry_ofs)
-{
- int pal_mode = env->pal_mode;
- env->exc_addr = pc | pal_mode;
- env->pc = env->palbr + entry_ofs;
- env->pal_mode = 1;
-}
-
void helper_tbia(CPUAlphaState *env)
{
tlb_flush(CPU(alpha_env_get_cpu(env)), 1);
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 4d78c4c..04c42fc 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -42,6 +42,9 @@ typedef struct DisasContext DisasContext;
struct DisasContext {
struct TranslationBlock *tb;
uint64_t pc;
+#ifndef CONFIG_USER_ONLY
+ uint64_t palbr;
+#endif
int mem_idx;
/* Current rounding mode for this TB. */
@@ -1206,15 +1209,24 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
return gen_excp(ctx, EXCP_CALL_PAL, palcode);
#else
{
- TCGv pc = tcg_const_i64(ctx->pc);
- TCGv entry = tcg_const_i64(palcode & 0x80
- ? 0x2000 + (palcode - 0x80) * 64
- : 0x1000 + palcode * 64);
+ TCGv tmp = tcg_temp_new();
+ uint64_t exc_addr = ctx->pc;
+ uint64_t entry = ctx->palbr;
+
+ if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
+ exc_addr |= 1;
+ } else {
+ tcg_gen_movi_i64(tmp, 1);
+ tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
+ }
- gen_helper_call_pal(cpu_env, pc, entry);
+ tcg_gen_movi_i64(tmp, exc_addr);
+ tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
+ tcg_temp_free(tmp);
- tcg_temp_free(entry);
- tcg_temp_free(pc);
+ entry += (palcode & 0x80
+ ? 0x2000 + (palcode - 0x80) * 64
+ : 0x1000 + palcode * 64);
/* Since the destination is running in PALmode, we don't really
need the page permissions check. We'll see the existence of
@@ -1222,11 +1234,13 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
we change the PAL base register. */
if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
tcg_gen_goto_tb(0);
+ tcg_gen_movi_i64(cpu_pc, entry);
tcg_gen_exit_tb((uintptr_t)ctx->tb);
return EXIT_GOTO_TB;
+ } else {
+ tcg_gen_movi_i64(cpu_pc, entry);
+ return EXIT_PC_UPDATED;
}
-
- return EXIT_PC_UPDATED;
}
#endif
}
@@ -2861,6 +2875,7 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
#ifdef CONFIG_USER_ONLY
ctx.ir = cpu_std_ir;
#else
+ ctx.palbr = env->palbr;
ctx.ir = (tb->flags & TB_FLAGS_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
#endif
--
2.1.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 3/3] target-alpha: Inline hw_ret
2015-06-09 21:13 [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 1/3] target-alpha: Use separate TCGv temporaries for the shadow registers Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 2/3] target-alpha: Inline call_pal Richard Henderson
@ 2015-06-09 21:13 ` Richard Henderson
2015-06-12 22:12 ` [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements Aurelien Jarno
3 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2015-06-09 21:13 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 2 --
target-alpha/sys_helper.c | 8 --------
target-alpha/translate.c | 15 ++++++++++-----
3 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index e7f0450..42bb247 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -91,8 +91,6 @@ DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_2(ieee_input_s, TCG_CALL_NO_WG, void, env, i64)
#if !defined (CONFIG_USER_ONLY)
-DEF_HELPER_2(hw_ret, void, env, i64)
-
DEF_HELPER_2(ldl_phys, i64, env, i64)
DEF_HELPER_2(ldq_phys, i64, env, i64)
DEF_HELPER_2(ldl_l_phys, i64, env, i64)
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
index 211991d..22e5b08 100644
--- a/target-alpha/sys_helper.c
+++ b/target-alpha/sys_helper.c
@@ -40,14 +40,6 @@ uint64_t helper_load_pcc(CPUAlphaState *env)
/* PALcode support special instructions */
#ifndef CONFIG_USER_ONLY
-void helper_hw_ret(CPUAlphaState *env, uint64_t a)
-{
- env->pc = a & ~3;
- env->intr_flag = 0;
- env->lock_addr = -1;
- env->pal_mode = a & 1;
-}
-
void helper_tbia(CPUAlphaState *env)
{
tlb_flush(CPU(alpha_env_get_cpu(env)), 1);
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 04c42fc..82d492b 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2635,13 +2635,18 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
address from EXC_ADDR. This turns out to be useful for our
emulation PALcode, so continue to accept it. */
- tmp = tcg_temp_new();
- tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
- gen_helper_hw_ret(cpu_env, tmp);
- tcg_temp_free(tmp);
+ ctx->lit = vb = tcg_temp_new();
+ tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr));
} else {
- gen_helper_hw_ret(cpu_env, load_gpr(ctx, rb));
+ vb = load_gpr(ctx, rb);
}
+ tmp = tcg_temp_new();
+ tcg_gen_movi_i64(tmp, 0);
+ tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, intr_flag));
+ tcg_gen_movi_i64(cpu_lock_addr, -1);
+ tcg_gen_andi_i64(tmp, vb, 1);
+ tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
+ tcg_gen_andi_i64(cpu_pc, vb, ~3);
ret = EXIT_PC_UPDATED;
break;
#else
--
2.1.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements
2015-06-09 21:13 [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements Richard Henderson
` (2 preceding siblings ...)
2015-06-09 21:13 ` [Qemu-devel] [PATCH 3/3] target-alpha: Inline hw_ret Richard Henderson
@ 2015-06-12 22:12 ` Aurelien Jarno
3 siblings, 0 replies; 6+ messages in thread
From: Aurelien Jarno @ 2015-06-12 22:12 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 2015-06-09 14:13, Richard Henderson wrote:
> Rather than copying around a block of 8 registers when we swap modes,
> let the translator map code generated for PALmode to the shadow regs
> directly. This simplifies PALmode entry and exit sufficiently to
> allow these insns to be performed inline.
>
> Sadly, the speedup for this is in the noise. But I still think it
> makes sense.
That's usually the case nowadays. It seems all TCG related part are
already well optimized, and that most targets are now limited by the MMU
emulation. That said I agree it makes sense, and also makes the code
cleaner (even if bigger).
>
> r~
>
>
> Richard Henderson (3):
> target-alpha: Use separate TCGv temporaries for the shadow registers
> target-alpha: Inline call_pal
> target-alpha: Inline hw_ret
>
> target-alpha/cpu.h | 3 +-
> target-alpha/gdbstub.c | 4 +-
> target-alpha/helper.c | 63 ++++++---------
> target-alpha/helper.h | 3 -
> target-alpha/machine.c | 4 +-
> target-alpha/sys_helper.c | 22 -----
> target-alpha/translate.c | 201 ++++++++++++++++++++++++++++++----------------
> 7 files changed, 166 insertions(+), 134 deletions(-)
The whole series is:
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 4096R/1DDD8C9B
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-06-12 22:12 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-09 21:13 [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 1/3] target-alpha: Use separate TCGv temporaries for the shadow registers Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 2/3] target-alpha: Inline call_pal Richard Henderson
2015-06-09 21:13 ` [Qemu-devel] [PATCH 3/3] target-alpha: Inline hw_ret Richard Henderson
2015-06-12 22:12 ` [Qemu-devel] [PATCH 0/3] target-alpha PALcode improvements Aurelien Jarno
-- strict thread matches above, loose matches on Subject: below --
2015-06-09 21:12 Richard Henderson
2015-06-09 21:12 ` [Qemu-devel] [PATCH 3/3] target-alpha: Inline hw_ret Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).