* [Qemu-devel] [PATCH 1/8] target/alpha: Remove amask from tb->flags
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
@ 2017-07-14 0:18 ` Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 2/8] target/alpha: Copy tb->flags into DisasContext Richard Henderson
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2017-07-14 0:18 UTC (permalink / raw)
To: qemu-devel
This value is constant for the cpu and does not need
to be stored within the TB.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target/alpha/cpu.h | 9 -------
target/alpha/translate.c | 70 ++++++++++++++++++++++++++----------------------
2 files changed, 38 insertions(+), 41 deletions(-)
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 691ac00..aa83417 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -487,14 +487,6 @@ enum {
TB_FLAGS_PAL_MODE = 1,
TB_FLAGS_FEN = 2,
TB_FLAGS_USER_MODE = 8,
-
- TB_FLAGS_AMASK_SHIFT = 4,
- TB_FLAGS_AMASK_BWX = AMASK_BWX << TB_FLAGS_AMASK_SHIFT,
- TB_FLAGS_AMASK_FIX = AMASK_FIX << TB_FLAGS_AMASK_SHIFT,
- TB_FLAGS_AMASK_CIX = AMASK_CIX << TB_FLAGS_AMASK_SHIFT,
- TB_FLAGS_AMASK_MVI = AMASK_MVI << TB_FLAGS_AMASK_SHIFT,
- TB_FLAGS_AMASK_TRAP = AMASK_TRAP << TB_FLAGS_AMASK_SHIFT,
- TB_FLAGS_AMASK_PREFETCH = AMASK_PREFETCH << TB_FLAGS_AMASK_SHIFT,
};
static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
@@ -513,7 +505,6 @@ static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
if (env->fen) {
flags |= TB_FLAGS_FEN;
}
- flags |= env->amask << TB_FLAGS_AMASK_SHIFT;
*pflags = flags;
}
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 232af9e..4a627fc 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -51,14 +51,15 @@ struct DisasContext {
#endif
int mem_idx;
+ /* implver and amask values for this CPU. */
+ int implver;
+ int amask;
+
/* Current rounding mode for this TB. */
int tb_rm;
/* Current flush-to-zero setting for this TB. */
int tb_ftz;
- /* implver value for this CPU. */
- int implver;
-
/* The set of registers active in the current context. */
TCGv *ir;
@@ -1442,6 +1443,13 @@ static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
} \
} while (0)
+#define REQUIRE_AMASK(FLAG) \
+ do { \
+ if ((ctx->amask & AMASK_##FLAG) == 0) { \
+ goto invalid_opc; \
+ } \
+ } while (0)
+
#define REQUIRE_TB_FLAG(FLAG) \
do { \
if ((ctx->tb->flags & (FLAG)) == 0) { \
@@ -1532,7 +1540,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x0A:
/* LDBU */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+ REQUIRE_AMASK(BWX);
gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
break;
case 0x0B:
@@ -1541,17 +1549,17 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x0C:
/* LDWU */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+ REQUIRE_AMASK(BWX);
gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
break;
case 0x0D:
/* STW */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+ REQUIRE_AMASK(BWX);
gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
break;
case 0x0E:
/* STB */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+ REQUIRE_AMASK(BWX);
gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
break;
case 0x0F:
@@ -1832,10 +1840,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x61:
/* AMASK */
REQUIRE_REG_31(ra);
- {
- uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
- tcg_gen_andi_i64(vc, vb, ~amask);
- }
+ tcg_gen_andi_i64(vc, vb, ~ctx->amask);
break;
case 0x64:
/* CMOVLE */
@@ -2048,7 +2053,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x14:
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+ REQUIRE_AMASK(FIX);
vc = dest_fpr(ctx, rc);
switch (fpfn) { /* fn11 & 0x3F */
case 0x04:
@@ -2525,14 +2530,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
vc = dest_gpr(ctx, rc);
if (fn7 == 0x70) {
/* FTOIT */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+ REQUIRE_AMASK(FIX);
REQUIRE_REG_31(rb);
va = load_fpr(ctx, ra);
tcg_gen_mov_i64(vc, va);
break;
} else if (fn7 == 0x78) {
/* FTOIS */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+ REQUIRE_AMASK(FIX);
REQUIRE_REG_31(rb);
t32 = tcg_temp_new_i32();
va = load_fpr(ctx, ra);
@@ -2546,117 +2551,117 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
switch (fn7) {
case 0x00:
/* SEXTB */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+ REQUIRE_AMASK(BWX);
REQUIRE_REG_31(ra);
tcg_gen_ext8s_i64(vc, vb);
break;
case 0x01:
/* SEXTW */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+ REQUIRE_AMASK(BWX);
REQUIRE_REG_31(ra);
tcg_gen_ext16s_i64(vc, vb);
break;
case 0x30:
/* CTPOP */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+ REQUIRE_AMASK(CIX);
REQUIRE_REG_31(ra);
REQUIRE_NO_LIT;
tcg_gen_ctpop_i64(vc, vb);
break;
case 0x31:
/* PERR */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
REQUIRE_NO_LIT;
va = load_gpr(ctx, ra);
gen_helper_perr(vc, va, vb);
break;
case 0x32:
/* CTLZ */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+ REQUIRE_AMASK(CIX);
REQUIRE_REG_31(ra);
REQUIRE_NO_LIT;
tcg_gen_clzi_i64(vc, vb, 64);
break;
case 0x33:
/* CTTZ */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+ REQUIRE_AMASK(CIX);
REQUIRE_REG_31(ra);
REQUIRE_NO_LIT;
tcg_gen_ctzi_i64(vc, vb, 64);
break;
case 0x34:
/* UNPKBW */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
REQUIRE_REG_31(ra);
REQUIRE_NO_LIT;
gen_helper_unpkbw(vc, vb);
break;
case 0x35:
/* UNPKBL */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
REQUIRE_REG_31(ra);
REQUIRE_NO_LIT;
gen_helper_unpkbl(vc, vb);
break;
case 0x36:
/* PKWB */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
REQUIRE_REG_31(ra);
REQUIRE_NO_LIT;
gen_helper_pkwb(vc, vb);
break;
case 0x37:
/* PKLB */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
REQUIRE_REG_31(ra);
REQUIRE_NO_LIT;
gen_helper_pklb(vc, vb);
break;
case 0x38:
/* MINSB8 */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
va = load_gpr(ctx, ra);
gen_helper_minsb8(vc, va, vb);
break;
case 0x39:
/* MINSW4 */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
va = load_gpr(ctx, ra);
gen_helper_minsw4(vc, va, vb);
break;
case 0x3A:
/* MINUB8 */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
va = load_gpr(ctx, ra);
gen_helper_minub8(vc, va, vb);
break;
case 0x3B:
/* MINUW4 */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
va = load_gpr(ctx, ra);
gen_helper_minuw4(vc, va, vb);
break;
case 0x3C:
/* MAXUB8 */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
va = load_gpr(ctx, ra);
gen_helper_maxub8(vc, va, vb);
break;
case 0x3D:
/* MAXUW4 */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
va = load_gpr(ctx, ra);
gen_helper_maxuw4(vc, va, vb);
break;
case 0x3E:
/* MAXSB8 */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
va = load_gpr(ctx, ra);
gen_helper_maxsb8(vc, va, vb);
break;
case 0x3F:
/* MAXSW4 */
- REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+ REQUIRE_AMASK(MVI);
va = load_gpr(ctx, ra);
gen_helper_maxsw4(vc, va, vb);
break;
@@ -2929,6 +2934,7 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
ctx.pc = pc_start;
ctx.mem_idx = cpu_mmu_index(env, false);
ctx.implver = env->implver;
+ ctx.amask = env->amask;
ctx.singlestep_enabled = cs->singlestep_enabled;
#ifdef CONFIG_USER_ONLY
--
2.9.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 2/8] target/alpha: Copy tb->flags into DisasContext
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 1/8] target/alpha: Remove amask from tb->flags Richard Henderson
@ 2017-07-14 0:18 ` Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 3/8] target/alpha: Merge several flag bytes into ENV->FLAGS Richard Henderson
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2017-07-14 0:18 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target/alpha/translate.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 4a627fc..48be19a 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -49,6 +49,7 @@ struct DisasContext {
#ifndef CONFIG_USER_ONLY
uint64_t palbr;
#endif
+ uint32_t tbflags;
int mem_idx;
/* implver and amask values for this CPU. */
@@ -452,7 +453,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
static bool in_superpage(DisasContext *ctx, int64_t addr)
{
#ifndef CONFIG_USER_ONLY
- return ((ctx->tb->flags & TB_FLAGS_USER_MODE) == 0
+ return ((ctx->tbflags & TB_FLAGS_USER_MODE) == 0
&& addr >> TARGET_VIRT_ADDR_SPACE_BITS == -1
&& ((addr >> 41) & 3) == 2);
#else
@@ -1167,7 +1168,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
#ifndef CONFIG_USER_ONLY
/* Privileged PAL code */
- if (palcode < 0x40 && (ctx->tb->flags & TB_FLAGS_USER_MODE) == 0) {
+ if (palcode < 0x40 && (ctx->tbflags & TB_FLAGS_USER_MODE) == 0) {
TCGv tmp;
switch (palcode) {
case 0x01:
@@ -1258,7 +1259,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
uint64_t exc_addr = ctx->pc;
uint64_t entry = ctx->palbr;
- if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
+ if (ctx->tbflags & TB_FLAGS_PAL_MODE) {
exc_addr |= 1;
} else {
tcg_gen_movi_i64(tmp, 1);
@@ -1452,7 +1453,7 @@ static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
#define REQUIRE_TB_FLAG(FLAG) \
do { \
- if ((ctx->tb->flags & (FLAG)) == 0) { \
+ if ((ctx->tbflags & (FLAG)) == 0) { \
goto invalid_opc; \
} \
} while (0)
@@ -2932,6 +2933,7 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
ctx.tb = tb;
ctx.pc = pc_start;
+ ctx.tbflags = tb->flags;
ctx.mem_idx = cpu_mmu_index(env, false);
ctx.implver = env->implver;
ctx.amask = env->amask;
@@ -2941,7 +2943,7 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
ctx.ir = cpu_std_ir;
#else
ctx.palbr = env->palbr;
- ctx.ir = (tb->flags & TB_FLAGS_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
+ ctx.ir = (ctx.tbflags & TB_FLAGS_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
#endif
/* ??? Every TB begins with unset rounding mode, to be initialized on
--
2.9.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 3/8] target/alpha: Merge several flag bytes into ENV->FLAGS
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 1/8] target/alpha: Remove amask from tb->flags Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 2/8] target/alpha: Copy tb->flags into DisasContext Richard Henderson
@ 2017-07-14 0:18 ` Richard Henderson
2017-07-18 1:53 ` Emilio G. Cota
2017-07-14 0:18 ` [Qemu-devel] [PATCH 4/8] target/alpha: Fix temp leak in gen_bcond Richard Henderson
` (5 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2017-07-14 0:18 UTC (permalink / raw)
To: qemu-devel
The flags are arranged such that we can manipulate them either
a whole, or as individual bytes. The computation within
cpu_get_tb_cpu_state is now reduced to a single load and mask.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target/alpha/cpu.h | 70 +++++++++++++++++--------------------
hw/alpha/dp264.c | 1 -
linux-user/main.c | 25 +++++++------
target/alpha/cpu.c | 7 ++--
target/alpha/helper.c | 12 +++----
target/alpha/machine.c | 10 ++----
target/alpha/translate.c | 91 +++++++++++++++++++++++++++++++-----------------
7 files changed, 117 insertions(+), 99 deletions(-)
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index aa83417..e95be2b 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -242,13 +242,11 @@ struct CPUAlphaState {
uint8_t fpcr_dyn_round;
uint8_t fpcr_flush_to_zero;
- /* The Internal Processor Registers. Some of these we assume always
- exist for use in user-mode. */
- uint8_t ps;
- uint8_t intr_flag;
- uint8_t pal_mode;
- uint8_t fen;
+ /* Mask of PALmode, Processor State et al. Most of this gets copied
+ into the TranslatorBlock flags and controls code generation. */
+ uint32_t flags;
+ /* The high 32-bits of the processor cycle counter. */
uint32_t pcc_ofs;
/* These pass data from the exception logic in the translator and
@@ -398,24 +396,37 @@ enum {
};
/* Processor status constants. */
-enum {
- /* Low 3 bits are interrupt mask level. */
- PS_INT_MASK = 7,
+/* Low 3 bits are interrupt mask level. */
+#define PS_INT_MASK 7u
- /* Bits 4 and 5 are the mmu mode. The VMS PALcode uses all 4 modes;
- The Unix PALcode only uses bit 4. */
- PS_USER_MODE = 8
-};
+/* Bits 4 and 5 are the mmu mode. The VMS PALcode uses all 4 modes;
+ The Unix PALcode only uses bit 4. */
+#define PS_USER_MODE 8u
+
+/* CPUAlphaState->flags constants. These are layed out so that we
+ can set or reset the pieces individually by assigning to the byte,
+ or manipulated as a whole. */
+
+#define ENV_FLAG_PAL_SHIFT 0
+#define ENV_FLAG_PS_SHIFT 8
+#define ENV_FLAG_RX_SHIFT 16
+#define ENV_FLAG_FEN_SHIFT 24
+
+#define ENV_FLAG_PAL_MODE (1u << ENV_FLAG_PAL_SHIFT)
+#define ENV_FLAG_PS_USER (PS_USER_MODE << ENV_FLAG_PS_SHIFT)
+#define ENV_FLAG_RX_FLAG (1u << ENV_FLAG_RX_SHIFT)
+#define ENV_FLAG_FEN (1u << ENV_FLAG_FEN_SHIFT)
+
+#define ENV_FLAG_TB_MASK \
+ (ENV_FLAG_PAL_MODE | ENV_FLAG_PS_USER | ENV_FLAG_FEN)
static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
{
- if (env->pal_mode) {
- return MMU_KERNEL_IDX;
- } else if (env->ps & PS_USER_MODE) {
- return MMU_USER_IDX;
- } else {
- return MMU_KERNEL_IDX;
+ int ret = env->flags & ENV_FLAG_PS_USER ? MMU_USER_IDX : MMU_KERNEL_IDX;
+ if (env->flags & ENV_FLAG_PAL_MODE) {
+ ret = MMU_KERNEL_IDX;
}
+ return ret;
}
enum {
@@ -482,31 +493,12 @@ QEMU_NORETURN void alpha_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
int unused, unsigned size);
#endif
-/* Bits in TB->FLAGS that control how translation is processed. */
-enum {
- TB_FLAGS_PAL_MODE = 1,
- TB_FLAGS_FEN = 2,
- TB_FLAGS_USER_MODE = 8,
-};
-
static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags)
{
- int flags = 0;
-
*pc = env->pc;
*cs_base = 0;
-
- if (env->pal_mode) {
- flags = TB_FLAGS_PAL_MODE;
- } else {
- flags = env->ps & PS_USER_MODE;
- }
- if (env->fen) {
- flags |= TB_FLAGS_FEN;
- }
-
- *pflags = flags;
+ *pflags = env->flags & ENV_FLAG_TB_MASK;
}
#endif /* ALPHA_CPU_H */
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 85405da..3b307ad 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -123,7 +123,6 @@ static void clipper_init(MachineState *machine)
/* Start all cpus at the PALcode RESET entry point. */
for (i = 0; i < smp_cpus; ++i) {
- cpus[i]->env.pal_mode = 1;
cpus[i]->env.pc = palcode_entry;
cpus[i]->env.palbr = palcode_entry;
}
diff --git a/linux-user/main.c b/linux-user/main.c
index ad03c9e..2b38d39 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3037,16 +3037,13 @@ void cpu_loop(CPUAlphaState *env)
abi_long sysret;
while (1) {
+ bool arch_interrupt = true;
+
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
process_queued_cpu_work(cs);
- /* All of the traps imply a transition through PALcode, which
- implies an REI instruction has been executed. Which means
- that the intr_flag should be cleared. */
- env->intr_flag = 0;
-
switch (trapnr) {
case EXCP_RESET:
fprintf(stderr, "Reset requested. Exit\n");
@@ -3063,7 +3060,6 @@ void cpu_loop(CPUAlphaState *env)
exit(EXIT_FAILURE);
break;
case EXCP_MMFAULT:
- env->lock_addr = -1;
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
@@ -3072,7 +3068,6 @@ void cpu_loop(CPUAlphaState *env)
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case EXCP_UNALIGN:
- env->lock_addr = -1;
info.si_signo = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
@@ -3081,7 +3076,6 @@ void cpu_loop(CPUAlphaState *env)
break;
case EXCP_OPCDEC:
do_sigill:
- env->lock_addr = -1;
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC;
@@ -3089,7 +3083,6 @@ void cpu_loop(CPUAlphaState *env)
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case EXCP_ARITH:
- env->lock_addr = -1;
info.si_signo = TARGET_SIGFPE;
info.si_errno = 0;
info.si_code = TARGET_FPE_FLTINV;
@@ -3100,7 +3093,6 @@ void cpu_loop(CPUAlphaState *env)
/* No-op. Linux simply re-enables the FPU. */
break;
case EXCP_CALL_PAL:
- env->lock_addr = -1;
switch (env->error_code) {
case 0x80:
/* BPT */
@@ -3197,10 +3189,11 @@ void cpu_loop(CPUAlphaState *env)
case EXCP_DEBUG:
info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP);
if (info.si_signo) {
- env->lock_addr = -1;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ } else {
+ arch_interrupt = false;
}
break;
case EXCP_INTERRUPT:
@@ -3208,6 +3201,7 @@ void cpu_loop(CPUAlphaState *env)
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
+ arch_interrupt = false;
break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
@@ -3215,6 +3209,15 @@ void cpu_loop(CPUAlphaState *env)
exit(EXIT_FAILURE);
}
process_pending_signals (env);
+
+ /* Most of the traps imply a transition through PALcode, which
+ implies an REI instruction has been executed. Which means
+ that RX and LOCK_ADDR should be cleared. But there are a
+ few exceptions for traps internal to QEMU. */
+ if (arch_interrupt) {
+ env->flags &= ~ENV_FLAG_RX_FLAG;
+ env->lock_addr = -1;
+ }
}
}
#endif /* TARGET_ALPHA */
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index 8186c9d..76150f4 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -276,14 +276,15 @@ static void alpha_cpu_initfn(Object *obj)
alpha_translate_init();
+ env->lock_addr = -1;
#if defined(CONFIG_USER_ONLY)
- env->ps = PS_USER_MODE;
+ env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
| FPCR_UNFD | FPCR_INED | FPCR_DNOD
| FPCR_DYN_NORMAL));
+#else
+ env->flags = ENV_FLAG_PAL_MODE | ENV_FLAG_FEN;
#endif
- env->lock_addr = -1;
- env->fen = 1;
}
static void alpha_cpu_class_init(ObjectClass *oc, void *data)
diff --git a/target/alpha/helper.c b/target/alpha/helper.c
index a5c3088..34121f4 100644
--- a/target/alpha/helper.c
+++ b/target/alpha/helper.c
@@ -81,7 +81,7 @@ void helper_store_fpcr(CPUAlphaState *env, uint64_t val)
static uint64_t *cpu_alpha_addr_gr(CPUAlphaState *env, unsigned reg)
{
#ifndef CONFIG_USER_ONLY
- if (env->pal_mode) {
+ if (env->flags & ENV_FLAG_PAL_MODE) {
if (reg >= 8 && reg <= 14) {
return &env->shadow[reg - 8];
} else if (reg == 25) {
@@ -364,13 +364,13 @@ void alpha_cpu_do_interrupt(CPUState *cs)
/* Remember where the exception happened. Emulate real hardware in
that the low bit of the PC indicates PALmode. */
- env->exc_addr = env->pc | env->pal_mode;
+ env->exc_addr = env->pc | (env->flags & ENV_FLAG_PAL_MODE);
/* Continue execution at the PALcode entry point. */
env->pc = env->palbr + i;
/* Switch to PALmode. */
- env->pal_mode = 1;
+ env->flags |= ENV_FLAG_PAL_MODE;
#endif /* !USER_ONLY */
}
@@ -381,14 +381,14 @@ bool alpha_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
int idx = -1;
/* We never take interrupts while in PALmode. */
- if (env->pal_mode) {
+ if (env->flags & ENV_FLAG_PAL_MODE) {
return false;
}
/* Fall through the switch, collecting the highest priority
interrupt that isn't masked by the processor status IPL. */
/* ??? This hard-codes the OSF/1 interrupt levels. */
- switch (env->ps & PS_INT_MASK) {
+ switch ((env->flags >> ENV_FLAG_PS_SHIFT) & PS_INT_MASK) {
case 0 ... 3:
if (interrupt_request & CPU_INTERRUPT_HARD) {
idx = EXCP_DEV_INTERRUPT;
@@ -432,7 +432,7 @@ void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int i;
cpu_fprintf(f, " PC " TARGET_FMT_lx " PS %02x\n",
- env->pc, env->ps);
+ env->pc, extract32(env->flags, ENV_FLAG_PS_SHIFT, 8));
for (i = 0; i < 31; i++) {
cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
linux_reg_names[i], cpu_alpha_load_gr(env, i));
diff --git a/target/alpha/machine.c b/target/alpha/machine.c
index a102645..0914ba5 100644
--- a/target/alpha/machine.c
+++ b/target/alpha/machine.c
@@ -48,11 +48,7 @@ static VMStateField vmstate_env_fields[] = {
VMSTATE_UINTTL(lock_addr, CPUAlphaState),
VMSTATE_UINTTL(lock_value, CPUAlphaState),
- VMSTATE_UINT8(ps, CPUAlphaState),
- VMSTATE_UINT8(intr_flag, CPUAlphaState),
- VMSTATE_UINT8(pal_mode, CPUAlphaState),
- VMSTATE_UINT8(fen, CPUAlphaState),
-
+ VMSTATE_UINT32(flags, CPUAlphaState),
VMSTATE_UINT32(pcc_ofs, CPUAlphaState),
VMSTATE_UINTTL(trap_arg0, CPUAlphaState),
@@ -74,8 +70,8 @@ static VMStateField vmstate_env_fields[] = {
static const VMStateDescription vmstate_env = {
.name = "env",
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 3,
+ .minimum_version_id = 3,
.fields = vmstate_env_fields,
};
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 48be19a..140d6f3 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -269,6 +269,27 @@ static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
}
}
+static int get_flag_ofs(unsigned shift)
+{
+ int ofs = offsetof(CPUAlphaState, flags);
+#ifdef HOST_WORDS_BIGENDIAN
+ ofs += 3 - (shift / 8);
+#else
+ ofs += shift / 8;
+#endif
+ return ofs;
+}
+
+static void ld_flag_byte(TCGv val, unsigned shift)
+{
+ tcg_gen_ld8u_i64(val, cpu_env, get_flag_ofs(shift));
+}
+
+static void st_flag_byte(TCGv val, unsigned shift)
+{
+ tcg_gen_st8_i64(val, cpu_env, get_flag_ofs(shift));
+}
+
static void gen_excp_1(int exception, int error_code)
{
TCGv_i32 tmp1, tmp2;
@@ -453,7 +474,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
static bool in_superpage(DisasContext *ctx, int64_t addr)
{
#ifndef CONFIG_USER_ONLY
- return ((ctx->tbflags & TB_FLAGS_USER_MODE) == 0
+ return ((ctx->tbflags & ENV_FLAG_PS_USER) == 0
&& addr >> TARGET_VIRT_ADDR_SPACE_BITS == -1
&& ((addr >> 41) & 3) == 2);
#else
@@ -1125,16 +1146,15 @@ static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
static void gen_rx(DisasContext *ctx, int ra, int set)
{
- TCGv_i32 tmp;
+ TCGv tmp;
if (ra != 31) {
- tcg_gen_ld8u_i64(ctx->ir[ra], cpu_env,
- offsetof(CPUAlphaState, intr_flag));
+ ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
}
- tmp = tcg_const_i32(set);
- tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUAlphaState, intr_flag));
- tcg_temp_free_i32(tmp);
+ tmp = tcg_const_i64(set);
+ st_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
+ tcg_temp_free(tmp);
}
static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
@@ -1168,7 +1188,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
#ifndef CONFIG_USER_ONLY
/* Privileged PAL code */
- if (palcode < 0x40 && (ctx->tbflags & TB_FLAGS_USER_MODE) == 0) {
+ if (palcode < 0x40 && (ctx->tbflags & ENV_FLAG_PS_USER) == 0) {
TCGv tmp;
switch (palcode) {
case 0x01:
@@ -1199,13 +1219,12 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
/* SWPIPL */
/* 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(ctx->ir[IR_V0], cpu_env,
- offsetof(CPUAlphaState, ps));
+ ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
/* But make sure and store only the 3 IPL bits from the user. */
tmp = tcg_temp_new();
tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
- tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, ps));
+ st_flag_byte(tmp, ENV_FLAG_PS_SHIFT);
tcg_temp_free(tmp);
/* Allow interrupts to be recognized right away. */
@@ -1214,9 +1233,9 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
case 0x36:
/* RDPS */
- tcg_gen_ld8u_i64(ctx->ir[IR_V0], cpu_env,
- offsetof(CPUAlphaState, ps));
+ ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
break;
+
case 0x38:
/* WRUSP */
tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
@@ -1259,11 +1278,11 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
uint64_t exc_addr = ctx->pc;
uint64_t entry = ctx->palbr;
- if (ctx->tbflags & TB_FLAGS_PAL_MODE) {
+ if (ctx->tbflags & ENV_FLAG_PAL_MODE) {
exc_addr |= 1;
} else {
tcg_gen_movi_i64(tmp, 1);
- tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
+ st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
}
tcg_gen_movi_i64(tmp, exc_addr);
@@ -1293,14 +1312,11 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
#ifndef CONFIG_USER_ONLY
-#define PR_BYTE 0x100000
#define PR_LONG 0x200000
static int cpu_pr_data(int pr)
{
switch (pr) {
- case 0: return offsetof(CPUAlphaState, ps) | PR_BYTE;
- case 1: return offsetof(CPUAlphaState, fen) | PR_BYTE;
case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
case 3: return offsetof(CPUAlphaState, trap_arg0);
case 4: return offsetof(CPUAlphaState, trap_arg1);
@@ -1350,14 +1366,19 @@ static ExitStatus gen_mfpr(DisasContext *ctx, TCGv va, int regno)
}
break;
+ case 0: /* PS */
+ ld_flag_byte(va, ENV_FLAG_PS_SHIFT);
+ break;
+ case 1: /* FEN */
+ ld_flag_byte(va, ENV_FLAG_FEN_SHIFT);
+ break;
+
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 {
@@ -1417,14 +1438,19 @@ static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
tcg_gen_mov_i64(cpu_std_ir[regno], vb);
break;
+ case 0: /* PS */
+ st_flag_byte(vb, ENV_FLAG_PS_SHIFT);
+ break;
+ case 1: /* FEN */
+ st_flag_byte(vb, ENV_FLAG_FEN_SHIFT);
+ break;
+
default:
/* The basic registers are data only, and unknown registers
are read-zero, write-ignore. */
data = cpu_pr_data(regno);
if (data != 0) {
- if (data & PR_BYTE) {
- tcg_gen_st8_i64(vb, cpu_env, data & ~PR_BYTE);
- } else if (data & PR_LONG) {
+ if (data & PR_LONG) {
tcg_gen_st32_i64(vb, cpu_env, data & ~PR_LONG);
} else {
tcg_gen_st_i64(vb, cpu_env, data);
@@ -2430,7 +2456,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x19:
/* HW_MFPR (PALcode) */
#ifndef CONFIG_USER_ONLY
- REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+ REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
va = dest_gpr(ctx, ra);
ret = gen_mfpr(ctx, va, insn & 0xffff);
break;
@@ -2452,7 +2478,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x1B:
/* HW_LD (PALcode) */
#ifndef CONFIG_USER_ONLY
- REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+ REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
{
TCGv addr = tcg_temp_new();
vb = load_gpr(ctx, rb);
@@ -2674,7 +2700,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x1D:
/* HW_MTPR (PALcode) */
#ifndef CONFIG_USER_ONLY
- REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+ REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
vb = load_gpr(ctx, rb);
ret = gen_mtpr(ctx, vb, insn & 0xffff);
break;
@@ -2685,7 +2711,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x1E:
/* HW_RET (PALcode) */
#ifndef CONFIG_USER_ONLY
- REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+ REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
if (rb == 31) {
/* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
address from EXC_ADDR. This turns out to be useful for our
@@ -2695,12 +2721,13 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
} else {
vb = load_gpr(ctx, rb);
}
+ tcg_gen_movi_i64(cpu_lock_addr, -1);
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);
+ st_flag_byte(tmp, ENV_FLAG_RX_SHIFT);
tcg_gen_andi_i64(tmp, vb, 1);
- tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
+ st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
+ tcg_temp_free(tmp);
tcg_gen_andi_i64(cpu_pc, vb, ~3);
/* Allow interrupts to be recognized right away. */
ret = EXIT_PC_UPDATED_NOCHAIN;
@@ -2712,7 +2739,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x1F:
/* HW_ST (PALcode) */
#ifndef CONFIG_USER_ONLY
- REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+ REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
{
switch ((insn >> 12) & 0xF) {
case 0x0:
@@ -2943,7 +2970,7 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
ctx.ir = cpu_std_ir;
#else
ctx.palbr = env->palbr;
- ctx.ir = (ctx.tbflags & TB_FLAGS_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
+ ctx.ir = (ctx.tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
#endif
/* ??? Every TB begins with unset rounding mode, to be initialized on
--
2.9.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH 3/8] target/alpha: Merge several flag bytes into ENV->FLAGS
2017-07-14 0:18 ` [Qemu-devel] [PATCH 3/8] target/alpha: Merge several flag bytes into ENV->FLAGS Richard Henderson
@ 2017-07-18 1:53 ` Emilio G. Cota
2017-07-18 3:04 ` Richard Henderson
0 siblings, 1 reply; 12+ messages in thread
From: Emilio G. Cota @ 2017-07-18 1:53 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Thu, Jul 13, 2017 at 14:18:14 -1000, Richard Henderson wrote:
> The flags are arranged such that we can manipulate them either
> a whole, or as individual bytes. The computation within
> cpu_get_tb_cpu_state is now reduced to a single load and mask.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target/alpha/cpu.h | 70 +++++++++++++++++--------------------
> hw/alpha/dp264.c | 1 -
> linux-user/main.c | 25 +++++++------
> target/alpha/cpu.c | 7 ++--
> target/alpha/helper.c | 12 +++----
> target/alpha/machine.c | 10 ++----
> target/alpha/translate.c | 91 +++++++++++++++++++++++++++++++-----------------
> 7 files changed, 117 insertions(+), 99 deletions(-)
>
> diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
> index aa83417..e95be2b 100644
> --- a/target/alpha/cpu.h
> +++ b/target/alpha/cpu.h
> @@ -242,13 +242,11 @@ struct CPUAlphaState {
> uint8_t fpcr_dyn_round;
> uint8_t fpcr_flush_to_zero;
>
> - /* The Internal Processor Registers. Some of these we assume always
> - exist for use in user-mode. */
> - uint8_t ps;
> - uint8_t intr_flag;
> - uint8_t pal_mode;
> - uint8_t fen;
> + /* Mask of PALmode, Processor State et al. Most of this gets copied
> + into the TranslatorBlock flags and controls code generation. */
> + uint32_t flags;
Did you consider doing something like the appended? I don't like it
because it messes with endianness, which is always a pain. But it
lets you preserve the code that only touches the u8's as-is; this
comes at the price of requiring a fast-path swap in big-endian hosts.
An alternative would be to store the u8's in an order dependent on
the endianness of the host -- but that would break vmstate saving,
I guess.
Emilio
---8<---
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index aa83417..22c52ac 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -244,10 +244,15 @@ struct CPUAlphaState {
/* The Internal Processor Registers. Some of these we assume always
exist for use in user-mode. */
- uint8_t ps;
- uint8_t intr_flag;
- uint8_t pal_mode;
- uint8_t fen;
+ union {
+ struct {
+ uint8_t pal_mode;
+ uint8_t ps;
+ uint8_t intr_flag;
+ uint8_t fen;
+ };
+ uint32_t flags;
+ };
uint32_t pcc_ofs;
@@ -397,15 +402,35 @@ enum {
EXC_M_IOV = 64 /* Integer Overflow */
};
-/* Processor status constants. */
-enum {
- /* Low 3 bits are interrupt mask level. */
- PS_INT_MASK = 7,
- /* Bits 4 and 5 are the mmu mode. The VMS PALcode uses all 4 modes;
- The Unix PALcode only uses bit 4. */
- PS_USER_MODE = 8
-};
+/* Low 3 bits are interrupt mask level. */
+#define PS_INT_MASK 7u
+/* Bits 4 and 5 are the mmu mode. The VMS PALcode uses all 4 modes;
+ The Unix PALcode only uses bit 4. */
+#define PS_USER_MODE 8u
+
+/* CPUAlphaState->flags constants. These are layed out so that we
+ can set or reset the pieces individually by assigning to the byte,
+ or manipulated as a whole. */
+
+#define ENV_FLAG_PAL_SHIFT 0
+#define ENV_FLAG_PS_SHIFT 8
+#define ENV_FLAG_RX_SHIFT 16
+#define ENV_FLAG_FEN_SHIFT 24
+
+#define ENV_FLAG_PAL_MODE (1u << ENV_FLAG_PAL_SHIFT)
+#define ENV_FLAG_PS_USER (PS_USER_MODE << ENV_FLAG_PS_SHIFT)
+#define ENV_FLAG_RX_FLAG (1u << ENV_FLAG_RX_SHIFT)
+#define ENV_FLAG_FEN (1u << ENV_FLAG_FEN_SHIFT)
+
+#define ENV_FLAG_TB_MASK \
+ (ENV_FLAG_PAL_MODE | ENV_FLAG_PS_USER | ENV_FLAG_FEN)
+
+#ifdef HOST_WORDS_BIGENDIAN
+#define ENV_FLAG_TB(flags) (bswap32(flags) & ENV_FLAG_TB_MASK)
+#else
+#define ENV_FLAG_TB(flags) ((flags) & ENV_FLAG_TB_MASK)
+#endif
static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
{
@@ -492,21 +517,10 @@ enum {
static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags)
{
- int flags = 0;
-
*pc = env->pc;
*cs_base = 0;
- if (env->pal_mode) {
- flags = TB_FLAGS_PAL_MODE;
- } else {
- flags = env->ps & PS_USER_MODE;
- }
- if (env->fen) {
- flags |= TB_FLAGS_FEN;
- }
-
- *pflags = flags;
+ *pflags = ENV_FLAG_TB(env->flags);
}
#endif /* ALPHA_CPU_H */
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH 3/8] target/alpha: Merge several flag bytes into ENV->FLAGS
2017-07-18 1:53 ` Emilio G. Cota
@ 2017-07-18 3:04 ` Richard Henderson
0 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2017-07-18 3:04 UTC (permalink / raw)
To: Emilio G. Cota; +Cc: qemu-devel
On 07/17/2017 03:53 PM, Emilio G. Cota wrote:
> On Thu, Jul 13, 2017 at 14:18:14 -1000, Richard Henderson wrote:
>> The flags are arranged such that we can manipulate them either
>> a whole, or as individual bytes. The computation within
>> cpu_get_tb_cpu_state is now reduced to a single load and mask.
>>
>> Signed-off-by: Richard Henderson <rth@twiddle.net>
>> ---
>> target/alpha/cpu.h | 70 +++++++++++++++++--------------------
>> hw/alpha/dp264.c | 1 -
>> linux-user/main.c | 25 +++++++------
>> target/alpha/cpu.c | 7 ++--
>> target/alpha/helper.c | 12 +++----
>> target/alpha/machine.c | 10 ++----
>> target/alpha/translate.c | 91 +++++++++++++++++++++++++++++++-----------------
>> 7 files changed, 117 insertions(+), 99 deletions(-)
>>
>> diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
>> index aa83417..e95be2b 100644
>> --- a/target/alpha/cpu.h
>> +++ b/target/alpha/cpu.h
>> @@ -242,13 +242,11 @@ struct CPUAlphaState {
>> uint8_t fpcr_dyn_round;
>> uint8_t fpcr_flush_to_zero;
>>
>> - /* The Internal Processor Registers. Some of these we assume always
>> - exist for use in user-mode. */
>> - uint8_t ps;
>> - uint8_t intr_flag;
>> - uint8_t pal_mode;
>> - uint8_t fen;
>> + /* Mask of PALmode, Processor State et al. Most of this gets copied
>> + into the TranslatorBlock flags and controls code generation. */
>> + uint32_t flags;
>
> Did you consider doing something like the appended? I don't like it
> because it messes with endianness, which is always a pain. But it
> lets you preserve the code that only touches the u8's as-is; this
> comes at the price of requiring a fast-path swap in big-endian hosts.
>
> An alternative would be to store the u8's in an order dependent on
> the endianness of the host -- but that would break vmstate saving,
> I guess.
>
> Emilio
>
> ---8<---
>
> diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
> index aa83417..22c52ac 100644
> --- a/target/alpha/cpu.h
> +++ b/target/alpha/cpu.h
> @@ -244,10 +244,15 @@ struct CPUAlphaState {
>
> /* The Internal Processor Registers. Some of these we assume always
> exist for use in user-mode. */
> - uint8_t ps;
> - uint8_t intr_flag;
> - uint8_t pal_mode;
> - uint8_t fen;
> + union {
> + struct {
> + uint8_t pal_mode;
> + uint8_t ps;
> + uint8_t intr_flag;
> + uint8_t fen;
> + };
> + uint32_t flags;
> + };
I did consider this.
Doing things this way requires that I consider host endianness when forming the
bit masks. As opposed to only needing to consider host endianness while
computing byte offsets within the translator.
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 4/8] target/alpha: Fix temp leak in gen_bcond
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
` (2 preceding siblings ...)
2017-07-14 0:18 ` [Qemu-devel] [PATCH 3/8] target/alpha: Merge several flag bytes into ENV->FLAGS Richard Henderson
@ 2017-07-14 0:18 ` Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 5/8] target/alpha: Fix temp leak in gen_mtpr Richard Henderson
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2017-07-14 0:18 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target/alpha/translate.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 140d6f3..d684a7b 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -565,16 +565,16 @@ static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
int32_t disp, int mask)
{
- TCGv cmp_tmp;
-
if (mask) {
- cmp_tmp = tcg_temp_new();
- tcg_gen_andi_i64(cmp_tmp, load_gpr(ctx, ra), 1);
- } else {
- cmp_tmp = load_gpr(ctx, ra);
- }
+ TCGv tmp = tcg_temp_new();
+ ExitStatus ret;
- return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
+ tcg_gen_andi_i64(tmp, load_gpr(ctx, ra), 1);
+ ret = gen_bcond_internal(ctx, cond, tmp, disp);
+ tcg_temp_free(tmp);
+ return ret;
+ }
+ return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra), disp);
}
/* Fold -0.0 for comparison with COND. */
--
2.9.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 5/8] target/alpha: Fix temp leak in gen_mtpr
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
` (3 preceding siblings ...)
2017-07-14 0:18 ` [Qemu-devel] [PATCH 4/8] target/alpha: Fix temp leak in gen_bcond Richard Henderson
@ 2017-07-14 0:18 ` Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 6/8] target/alpha: Fix temp leak in gen_call_pal Richard Henderson
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2017-07-14 0:18 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target/alpha/translate.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index d684a7b..5e37b1a 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -1392,7 +1392,6 @@ static ExitStatus gen_mfpr(DisasContext *ctx, TCGv va, int regno)
static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
{
- TCGv tmp;
int data;
switch (regno) {
@@ -1408,9 +1407,12 @@ static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
case 253:
/* WAIT */
- tmp = tcg_const_i64(1);
- tcg_gen_st32_i64(tmp, cpu_env, -offsetof(AlphaCPU, env) +
- offsetof(CPUState, halted));
+ {
+ TCGv_i32 tmp = tcg_const_i32(1);
+ tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
+ offsetof(CPUState, halted));
+ tcg_temp_free_i32(tmp);
+ }
return gen_excp(ctx, EXCP_HALTED, 0);
case 252:
--
2.9.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 6/8] target/alpha: Fix temp leak in gen_call_pal
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
` (4 preceding siblings ...)
2017-07-14 0:18 ` [Qemu-devel] [PATCH 5/8] target/alpha: Fix temp leak in gen_mtpr Richard Henderson
@ 2017-07-14 0:18 ` Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 7/8] target/alpha: Fix temp leak in gen_fbcond Richard Henderson
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2017-07-14 0:18 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target/alpha/translate.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 5e37b1a..326af7f 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -1189,7 +1189,6 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
#ifndef CONFIG_USER_ONLY
/* Privileged PAL code */
if (palcode < 0x40 && (ctx->tbflags & ENV_FLAG_PS_USER) == 0) {
- TCGv tmp;
switch (palcode) {
case 0x01:
/* CFLUSH */
@@ -1222,10 +1221,12 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
/* But make sure and store only the 3 IPL bits from the user. */
- tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
- st_flag_byte(tmp, ENV_FLAG_PS_SHIFT);
- tcg_temp_free(tmp);
+ {
+ TCGv tmp = tcg_temp_new();
+ tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
+ st_flag_byte(tmp, ENV_FLAG_PS_SHIFT);
+ tcg_temp_free(tmp);
+ }
/* Allow interrupts to be recognized right away. */
tcg_gen_movi_i64(cpu_pc, ctx->pc);
@@ -1254,9 +1255,12 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
case 0x3E:
/* WTINT */
- tmp = tcg_const_i64(1);
- tcg_gen_st32_i64(tmp, cpu_env, -offsetof(AlphaCPU, env) +
- offsetof(CPUState, halted));
+ {
+ TCGv_i32 tmp = tcg_const_i32(1);
+ tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
+ offsetof(CPUState, halted));
+ tcg_temp_free_i32(tmp);
+ }
tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
return gen_excp(ctx, EXCP_HALTED, 0);
--
2.9.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 7/8] target/alpha: Fix temp leak in gen_fbcond
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
` (5 preceding siblings ...)
2017-07-14 0:18 ` [Qemu-devel] [PATCH 6/8] target/alpha: Fix temp leak in gen_call_pal Richard Henderson
@ 2017-07-14 0:18 ` Richard Henderson
2017-07-14 0:18 ` [Qemu-devel] [PATCH 8/8] target/alpha: Log temp leaks Richard Henderson
2017-07-18 22:02 ` [Qemu-devel] [PATCH 0/8] target/alpha cleanups Emilio G. Cota
8 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2017-07-14 0:18 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target/alpha/translate.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 326af7f..aaaf28f 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -613,8 +613,12 @@ static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
int32_t disp)
{
TCGv cmp_tmp = tcg_temp_new();
+ ExitStatus ret;
+
gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra));
- return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
+ ret = gen_bcond_internal(ctx, cond, cmp_tmp, disp);
+ tcg_temp_free(cmp_tmp);
+ return ret;
}
static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
--
2.9.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 8/8] target/alpha: Log temp leaks
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
` (6 preceding siblings ...)
2017-07-14 0:18 ` [Qemu-devel] [PATCH 7/8] target/alpha: Fix temp leak in gen_fbcond Richard Henderson
@ 2017-07-14 0:18 ` Richard Henderson
2017-07-18 22:02 ` [Qemu-devel] [PATCH 0/8] target/alpha cleanups Emilio G. Cota
8 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2017-07-14 0:18 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target/alpha/translate.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index aaaf28f..90e6d52 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -3013,6 +3013,8 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
}
gen_tb_start(tb);
+ tcg_clear_temp_count();
+
do {
tcg_gen_insn_start(ctx.pc);
num_insns++;
@@ -3035,6 +3037,10 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
ret = translate_one(ctxp, insn);
free_context_temps(ctxp);
+ if (tcg_check_temp_count()) {
+ qemu_log("TCG temporary leak before "TARGET_FMT_lx"\n", ctx.pc);
+ }
+
/* If we reach a page boundary, are single stepping,
or exhaust instruction count, stop generation. */
if (ret == NO_EXIT
--
2.9.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH 0/8] target/alpha cleanups
2017-07-14 0:18 [Qemu-devel] [PATCH 0/8] target/alpha cleanups Richard Henderson
` (7 preceding siblings ...)
2017-07-14 0:18 ` [Qemu-devel] [PATCH 8/8] target/alpha: Log temp leaks Richard Henderson
@ 2017-07-18 22:02 ` Emilio G. Cota
8 siblings, 0 replies; 12+ messages in thread
From: Emilio G. Cota @ 2017-07-18 22:02 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Thu, Jul 13, 2017 at 14:18:11 -1000, Richard Henderson wrote:
> The new title holder for perf top is helper_lookup_tb_ptr.
> Those targets that have a complicated cpu_get_tb_cpu_state
> function are going to regret that.
>
>
> This cleans up the Alpha version of that function such that it is
> just two loads and one mask. Which is one practically-free mask
> away from being as minimal as one can get.
Tested-by: Emilio G. Cota <cota@braap.org>
for the series.
I tried to get some perf numbers but really booting linux
doesn't spend much time in lookup_tb_ptr, nor does dbt-bench; so
I get very similar before/after numbers (slight perf decrease for
booting, tiny perf increase for dbt-bench). Numbers are below, FWIW.
Emilio
* I modified the gentoo-alpha image I'm using [1] to shut down once
it has fully booted. Results before/after this patchset:
Performance counter stats for 'taskset -c 0 alpha-softmmu/qemu-system-alpha \
-m 512 -drive \
file=../img/alpha/die-on-boot.img,media=disk,format=raw,index=0 \
-kernel ../img/alpha/vmlinux -append root=/dev/sda2 \
-accel accel=tcg,thread=single -smp 1 -nographic' (10 runs):
Before:
30586.631281 task-clock (msec) # 0.883 CPUs utilized ( +- 0.56% )
16,373 context-switches # 0.535 K/sec ( +- 1.16% )
1 cpu-migrations # 0.000 K/sec
10,269 page-faults # 0.336 K/sec ( +- 1.39% )
128,287,167,139 cycles # 4.194 GHz ( +- 0.55% )
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
244,179,137,606 instructions # 1.90 insns per cycle ( +- 0.66% )
45,088,775,217 branches # 1474.133 M/sec ( +- 0.61% )
267,065,722 branch-misses # 0.59% of all branches ( +- 0.84% )
34.639115913 seconds time elapsed ( +- 0.50% )
After:
31358.851235 task-clock (msec) # 0.892 CPUs utilized ( +- 1.07% )
16,352 context-switches # 0.521 K/sec ( +- 1.59% )
1 cpu-migrations # 0.000 K/sec
10,643 page-faults # 0.339 K/sec ( +- 1.18% )
131,620,007,449 cycles # 4.197 GHz ( +- 1.07% )
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
249,714,336,126 instructions # 1.90 insns per cycle ( +- 1.35% )
46,259,663,064 branches # 1475.171 M/sec ( +- 1.27% )
269,500,888 branch-misses # 0.58% of all branches ( +- 0.71% )
35.136529309 seconds time elapsed ( +- 0.99% )
perf diff doesn't show anything interesting (all differences, <1%, are due to kernel code)
* DBT-bench before/after:
NBench score, higher is better
100 +-+---+-----+-----+----+-----+-----+-----+-----+-----+----+-----+---+-+
| ***## ***## |
90 +-+..................*+*.#.......*.*.#.................before +-+
| * * # * * # after |
| ***# * * # +++++ * * # |
80 +-+.......***##.*.*#.*.*.#.***##.*.*.#..............................+-+
| * * # * *# * * # * * # * * # |
70 +-+.......*.*.#.*.*#.*.*.#.*.*.#.*.*.#..............................+-+
| * * # * *# * * # * * # * * # |
| * * # * *# * * # * * # * * # |
60 +-+.......*.*.#.*.*#.*.*.#.*.*.#.*.*.#..............................+-+
| * * # * *# * * # * * # * * # ***## |
50 +-+.......*.*.#.*.*#.*.*.#.*.*.#.*.*.#.*.*.#........................+-+
| * * # * *# * * # * * # * * # * * # |
| * * # * *# * * # * * # * * # * * # |
40 +-+.......*.*.#.*.*#.*.*.#.*.*.#.*.*.#.*.*.#........................+-+
| ***## * * # * *# * * # * * # * * # * * # |
30 +-+.*.*.#.*.*.#.*.*#.*.*.#.*.*.#.*.*.#.*.*.#........................+-+
| * * # * * # * *# * * # * * # * * # * * # ***## |
| * * # * * # * *# * * # * * # * * # * * # * * # |
20 +-+.*.*.#.*.*.#.*.*#.*.*.#.*.*.#.*.*.#.*.*.#..................*.*.#.+-+
| * * # * * # * *# * * # * * # * * # * * # * * # |
10 +-+.*.*.#.*.*.#.*.*#.*.*.#.*.*.#.*.*.#.*.*.#..................*.*.#.+-+
| * * # * * # * *# * * # * * # * * # * * # * * # |
| * * # * * # * *# * * # * * # * * # * * # ***# ***## * * # |
0 +-+-***##-***##-***#-***##-***##-***##-***##-***##-***#-***##-***##-+-+
STRING SOBFP EMULAASSIGNMENT IDEHUFFMAFOLU DECOMPOSITION gmean
png: http://imgur.com/oFFYSKd
[1] https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg00630.html
^ permalink raw reply [flat|nested] 12+ messages in thread