* [Qemu-devel] [PATCH 10/13] target-alpha: Enable NPTL.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
@ 2010-03-25 0:13 ` Richard Henderson
2010-04-10 0:54 ` Aurelien Jarno
2010-03-29 17:48 ` [Qemu-devel] [PATCH 09/13] target-alpha: Update commentary for opcode 0x1A Richard Henderson
` (12 subsequent siblings)
13 siblings, 1 reply; 32+ messages in thread
From: Richard Henderson @ 2010-03-25 0:13 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
configure | 1 +
linux-user/syscall.c | 2 +-
target-alpha/cpu.h | 28 +++++++++++++++++-----------
3 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/configure b/configure
index 1d5fb17..37f2ba7 100755
--- a/configure
+++ b/configure
@@ -2430,6 +2430,7 @@ case "$target_arch2" in
;;
alpha)
target_phys_bits=64
+ target_nptl="yes"
;;
arm|armeb)
TARGET_ARCH=arm
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a03e432..050a418 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5768,7 +5768,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(fsync(arg1));
break;
case TARGET_NR_clone:
-#if defined(TARGET_SH4)
+#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
#elif defined(TARGET_CRIS)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 8afe16d..3dd9888 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -411,15 +411,6 @@ static inline int cpu_mmu_index (CPUState *env)
return (env->ps >> 3) & 3;
}
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
-{
- if (newsp)
- env->ir[30] = newsp;
- /* FIXME: Zero syscall return value. */
-}
-#endif
-
#include "cpu-all.h"
#include "exec-all.h"
@@ -477,7 +468,7 @@ enum {
IR_S4 = 13,
IR_S5 = 14,
IR_S6 = 15,
-#define IR_FP IR_S6
+ IR_FP = IR_S6,
IR_A0 = 16,
IR_A1 = 17,
IR_A2 = 18,
@@ -490,7 +481,7 @@ enum {
IR_T11 = 25,
IR_RA = 26,
IR_T12 = 27,
-#define IR_PV IR_T12
+ IR_PV = IR_T12,
IR_AT = 28,
IR_GP = 29,
IR_SP = 30,
@@ -531,4 +522,19 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
*flags = env->ps;
}
+#if defined(CONFIG_USER_ONLY)
+static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+{
+ if (newsp)
+ env->ir[IR_SP] = newsp;
+ env->ir[IR_V0] = 0;
+ env->ir[IR_A3] = 0;
+}
+
+static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+{
+ env->unique = newtls;
+}
+#endif
+
#endif /* !defined (__CPU_ALPHA_H__) */
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [Qemu-devel] [PATCH 10/13] target-alpha: Enable NPTL.
2010-03-25 0:13 ` [Qemu-devel] [PATCH 10/13] target-alpha: Enable NPTL Richard Henderson
@ 2010-04-10 0:54 ` Aurelien Jarno
0 siblings, 0 replies; 32+ messages in thread
From: Aurelien Jarno @ 2010-04-10 0:54 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Wed, Mar 24, 2010 at 05:13:07PM -0700, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> configure | 1 +
> linux-user/syscall.c | 2 +-
> target-alpha/cpu.h | 28 +++++++++++++++++-----------
> 3 files changed, 19 insertions(+), 12 deletions(-)
>
> diff --git a/configure b/configure
> index 1d5fb17..37f2ba7 100755
> --- a/configure
> +++ b/configure
> @@ -2430,6 +2430,7 @@ case "$target_arch2" in
> ;;
> alpha)
> target_phys_bits=64
> + target_nptl="yes"
> ;;
> arm|armeb)
> TARGET_ARCH=arm
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index a03e432..050a418 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -5768,7 +5768,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
> ret = get_errno(fsync(arg1));
> break;
> case TARGET_NR_clone:
> -#if defined(TARGET_SH4)
> +#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
> ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
> #elif defined(TARGET_CRIS)
> ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
> diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
> index 8afe16d..3dd9888 100644
> --- a/target-alpha/cpu.h
> +++ b/target-alpha/cpu.h
> @@ -411,15 +411,6 @@ static inline int cpu_mmu_index (CPUState *env)
> return (env->ps >> 3) & 3;
> }
>
> -#if defined(CONFIG_USER_ONLY)
> -static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
> -{
> - if (newsp)
> - env->ir[30] = newsp;
> - /* FIXME: Zero syscall return value. */
> -}
> -#endif
> -
> #include "cpu-all.h"
> #include "exec-all.h"
>
> @@ -477,7 +468,7 @@ enum {
> IR_S4 = 13,
> IR_S5 = 14,
> IR_S6 = 15,
> -#define IR_FP IR_S6
> + IR_FP = IR_S6,
> IR_A0 = 16,
> IR_A1 = 17,
> IR_A2 = 18,
> @@ -490,7 +481,7 @@ enum {
> IR_T11 = 25,
> IR_RA = 26,
> IR_T12 = 27,
> -#define IR_PV IR_T12
> + IR_PV = IR_T12,
> IR_AT = 28,
> IR_GP = 29,
> IR_SP = 30,
> @@ -531,4 +522,19 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
> *flags = env->ps;
> }
>
> +#if defined(CONFIG_USER_ONLY)
> +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
> +{
> + if (newsp)
> + env->ir[IR_SP] = newsp;
You need curly braces here.
> + env->ir[IR_V0] = 0;
> + env->ir[IR_A3] = 0;
> +}
> +
> +static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
> +{
> + env->unique = newtls;
> +}
> +#endif
> +
> #endif /* !defined (__CPU_ALPHA_H__) */
> --
> 1.6.6.1
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 09/13] target-alpha: Update commentary for opcode 0x1A.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
2010-03-25 0:13 ` [Qemu-devel] [PATCH 10/13] target-alpha: Enable NPTL Richard Henderson
@ 2010-03-29 17:48 ` Richard Henderson
2010-04-07 17:17 ` [Qemu-devel] [PATCH 05/13] target-alpha: Implement cvtlq inline Richard Henderson
` (11 subsequent siblings)
13 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-03-29 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index dfe55c3..2360a0e 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2534,13 +2534,16 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
#endif
case 0x1A:
- if (rb != 31)
+ /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
+ prediction stack action, which of course we don't implement. */
+ if (rb != 31) {
tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
- else
+ } else {
tcg_gen_movi_i64(cpu_pc, 0);
- if (ra != 31)
+ }
+ if (ra != 31) {
tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
- /* Those four jumps only differ by the branch prediction hint */
+ }
ret = EXIT_PC_UPDATED;
break;
case 0x1B:
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 05/13] target-alpha: Implement cvtlq inline.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
2010-03-25 0:13 ` [Qemu-devel] [PATCH 10/13] target-alpha: Enable NPTL Richard Henderson
2010-03-29 17:48 ` [Qemu-devel] [PATCH 09/13] target-alpha: Update commentary for opcode 0x1A Richard Henderson
@ 2010-04-07 17:17 ` Richard Henderson
2010-04-07 20:32 ` [Qemu-devel] [PATCH 11/13] target-alpha: Indicate NORETURN status when raising exception Richard Henderson
` (10 subsequent siblings)
13 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 17:17 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
It's a simple shift and mask sequence.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 1 -
target-alpha/op_helper.c | 7 -------
target-alpha/translate.c | 23 ++++++++++++++++++++++-
3 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 10c78d0..ccf6a2a 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -83,7 +83,6 @@ DEF_HELPER_FLAGS_1(cvtqf, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtgf, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtgq, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtqg, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtlq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index f9cd07a..a209130 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1152,13 +1152,6 @@ uint64_t helper_cvtqg (uint64_t a)
return float64_to_g(fr);
}
-uint64_t helper_cvtlq (uint64_t a)
-{
- int32_t lo = a >> 29;
- int32_t hi = a >> 32;
- return (lo & 0x3FFFFFFF) | (hi & 0xc0000000);
-}
-
/* PALcode support special instructions */
#if !defined (CONFIG_USER_ONLY)
void helper_hw_rei (void)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 44ce830..dff03ef 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -597,6 +597,28 @@ static inline void gen_fp_exc_raise(int rc, int fn11)
gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
}
+static void gen_fcvtlq(int rb, int rc)
+{
+ if (unlikely(rc == 31)) {
+ return;
+ }
+ if (unlikely(rb == 31)) {
+ tcg_gen_movi_i64(cpu_fir[rc], 0);
+ } else {
+ TCGv tmp = tcg_temp_new();
+
+ /* The arithmetic right shift here, plus the sign-extended mask below
+ yields a sign-extended result without an explicit ext32s_i64. */
+ tcg_gen_sari_i64(tmp, cpu_fir[rb], 32);
+ tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29);
+ tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
+ tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rc], 0x3fffffff);
+ tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
+
+ tcg_temp_free(tmp);
+ }
+}
+
static void gen_fcvtql(int rb, int rc)
{
if (unlikely(rc == 31)) {
@@ -646,7 +668,6 @@ static inline void glue(gen_f, name)(int rb, int rc) \
tcg_temp_free(tmp); \
} \
}
-FARITH2(cvtlq)
/* ??? VAX instruction qualifiers ignored. */
FARITH2(sqrtf)
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 11/13] target-alpha: Indicate NORETURN status when raising exception.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (2 preceding siblings ...)
2010-04-07 17:17 ` [Qemu-devel] [PATCH 05/13] target-alpha: Implement cvtlq inline Richard Henderson
@ 2010-04-07 20:32 ` Richard Henderson
2010-04-07 22:42 ` [Qemu-devel] [PATCH 12/13] target-alpha: Fix load-locked/store-conditional Richard Henderson
` (9 subsequent siblings)
13 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 20:32 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
When (indirectly) calling raise_exception, don't emit cleanup
code at the end of the TB, as it is unused.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 27 ++++++++++++++-------------
1 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 2360a0e..5636f60 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -74,7 +74,11 @@ typedef enum {
/* We are exiting the TB, but have neither emitted a goto_tb, nor
updated the PC for the next instruction to be executed. */
- EXIT_PC_STALE
+ EXIT_PC_STALE,
+
+ /* We are ending the TB with a noreturn function call, e.g. longjmp.
+ No following code will be executed. */
+ EXIT_NORETURN,
} ExitStatus;
/* global register indexes */
@@ -134,7 +138,7 @@ static void alpha_translate_init(void)
done_init = 1;
}
-static inline void gen_excp(DisasContext *ctx, int exception, int error_code)
+static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
{
TCGv_i32 tmp1, tmp2;
@@ -144,11 +148,13 @@ static inline void gen_excp(DisasContext *ctx, int exception, int error_code)
gen_helper_excp(tmp1, tmp2);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp1);
+
+ return EXIT_NORETURN;
}
-static inline void gen_invalid(DisasContext *ctx)
+static inline ExitStatus gen_invalid(DisasContext *ctx)
{
- gen_excp(ctx, EXCP_OPCDEC, 0);
+ return gen_excp(ctx, EXCP_OPCDEC, 0);
}
static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
@@ -1458,9 +1464,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
#endif
if (palcode >= 0x80 && palcode < 0xC0) {
/* Unprivileged PAL call */
- gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
- /* PC updated by gen_excp. */
- ret = EXIT_PC_UPDATED;
+ ret = gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
break;
}
#ifndef CONFIG_USER_ONLY
@@ -1468,9 +1472,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* Privileged PAL code */
if (ctx->mem_idx & 1)
goto invalid_opc;
- gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
- /* PC updated by gen_excp. */
- ret = EXIT_PC_UPDATED;
+ ret = gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
}
#endif
/* Invalid PAL call */
@@ -3078,9 +3080,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
break;
invalid_opc:
- gen_invalid(ctx);
- /* PC updated by gen_excp. */
- ret = EXIT_PC_UPDATED;
+ ret = gen_invalid(ctx);
break;
}
@@ -3184,6 +3184,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
switch (ret) {
case EXIT_GOTO_TB:
+ case EXIT_NORETURN:
break;
case EXIT_PC_STALE:
tcg_gen_movi_i64(cpu_pc, ctx.pc);
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 12/13] target-alpha: Fix load-locked/store-conditional.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (3 preceding siblings ...)
2010-04-07 20:32 ` [Qemu-devel] [PATCH 11/13] target-alpha: Indicate NORETURN status when raising exception Richard Henderson
@ 2010-04-07 22:42 ` Richard Henderson
2010-04-07 22:42 ` [Qemu-devel] [PATCH 13/13] target-alpha: Implement RPCC Richard Henderson
` (8 subsequent siblings)
13 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:42 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Use an exception plus start_exclusive to implement the compare-and-swap.
This follows the example set by the MIPS and PPC ports.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/main.c | 55 +++++++++++++
target-alpha/cpu.h | 6 +-
target-alpha/helper.c | 7 +-
target-alpha/op_helper.c | 2 +
target-alpha/translate.c | 202 ++++++++++++++++++++++++++++-----------------
5 files changed, 193 insertions(+), 79 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 5252881..61c3ed9 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2348,6 +2348,51 @@ void cpu_loop(CPUM68KState *env)
#endif /* TARGET_M68K */
#ifdef TARGET_ALPHA
+static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
+{
+ target_ulong addr, val, tmp;
+ target_siginfo_t info;
+ int ret = 0;
+
+ addr = env->lock_addr;
+ tmp = env->lock_st_addr;
+ env->lock_addr = -1;
+ env->lock_st_addr = 0;
+
+ start_exclusive();
+ mmap_lock();
+
+ if (addr == tmp) {
+ if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
+ goto do_sigsegv;
+ }
+
+ if (val == env->lock_value) {
+ tmp = env->ir[reg];
+ if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) {
+ goto do_sigsegv;
+ }
+ ret = 1;
+ }
+ }
+ env->ir[reg] = ret;
+ env->pc += 4;
+
+ mmap_unlock();
+ end_exclusive();
+ return;
+
+ do_sigsegv:
+ mmap_unlock();
+ end_exclusive();
+
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = addr;
+ queue_signal(env, TARGET_SIGSEGV, &info);
+}
+
void cpu_loop (CPUState *env)
{
int trapnr;
@@ -2372,6 +2417,7 @@ void cpu_loop (CPUState *env)
exit(1);
break;
case EXCP_ARITH:
+ env->lock_addr = -1;
info.si_signo = TARGET_SIGFPE;
info.si_errno = 0;
info.si_code = TARGET_FPE_FLTINV;
@@ -2383,6 +2429,7 @@ void cpu_loop (CPUState *env)
exit(1);
break;
case EXCP_DFAULT:
+ env->lock_addr = -1;
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = 0; /* ??? SEGV_MAPERR vs SEGV_ACCERR. */
@@ -2406,6 +2453,7 @@ void cpu_loop (CPUState *env)
exit(1);
break;
case EXCP_UNALIGN:
+ env->lock_addr = -1;
info.si_signo = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
@@ -2414,6 +2462,7 @@ void cpu_loop (CPUState *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;
@@ -2424,6 +2473,7 @@ void cpu_loop (CPUState *env)
/* No-op. Linux simply re-enables the FPU. */
break;
case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
+ env->lock_addr = -1;
switch ((trapnr >> 6) | 0x80) {
case 0x80:
/* BPT */
@@ -2513,11 +2563,16 @@ void cpu_loop (CPUState *env)
case EXCP_DEBUG:
info.si_signo = gdb_handlesig (env, 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, &info);
}
break;
+ case EXCP_STL_C:
+ case EXCP_STQ_C:
+ do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C);
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 3dd9888..dae23e2 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -355,11 +355,13 @@ struct CPUAlphaState {
uint64_t ir[31];
float64 fir[31];
uint64_t pc;
- uint64_t lock;
uint32_t pcc[2];
uint64_t ipr[IPR_LAST];
uint64_t ps;
uint64_t unique;
+ uint64_t lock_addr;
+ uint64_t lock_st_addr;
+ uint64_t lock_value;
float_status fp_status;
/* The following fields make up the FPCR, but in FP_STATUS format. */
uint8_t fpcr_exc_status;
@@ -440,6 +442,8 @@ enum {
/* Pseudo exception for console */
EXCP_CONSOLE_DISPATCH = 0x4001,
EXCP_CONSOLE_FIXUP = 0x4002,
+ EXCP_STL_C = 0x4003,
+ EXCP_STQ_C = 0x4004,
};
/* Arithmetic exception */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 46335cd..1ed7ea3 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -556,12 +556,15 @@ void cpu_dump_state (CPUState *env, FILE *f,
if ((i % 3) == 2)
cpu_fprintf(f, "\n");
}
- cpu_fprintf(f, "\n");
+
+ cpu_fprintf(f, "lock_a " TARGET_FMT_lx " lock_v " TARGET_FMT_lx "\n",
+ env->lock_addr, env->lock_value);
+
for (i = 0; i < 31; i++) {
cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i,
*((uint64_t *)(&env->fir[i])));
if ((i % 3) == 2)
cpu_fprintf(f, "\n");
}
- cpu_fprintf(f, "\nlock " TARGET_FMT_lx "\n", env->lock);
+ cpu_fprintf(f, "\n");
}
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index a209130..bfc095c 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1159,6 +1159,7 @@ void helper_hw_rei (void)
env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
env->intr_flag = 0;
+ env->lock_addr = -1;
/* XXX: re-enable interrupts and memory mapping */
}
@@ -1167,6 +1168,7 @@ void helper_hw_ret (uint64_t a)
env->pc = a & ~3;
env->ipr[IPR_EXC_ADDR] = a & 1;
env->intr_flag = 0;
+ env->lock_addr = -1;
/* XXX: re-enable interrupts and memory mapping */
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 5636f60..5a440bc 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -86,7 +86,9 @@ static TCGv_ptr cpu_env;
static TCGv cpu_ir[31];
static TCGv cpu_fir[31];
static TCGv cpu_pc;
-static TCGv cpu_lock;
+static TCGv cpu_lock_addr;
+static TCGv cpu_lock_st_addr;
+static TCGv cpu_lock_value;
#ifdef CONFIG_USER_ONLY
static TCGv cpu_uniq;
#endif
@@ -123,8 +125,15 @@ static void alpha_translate_init(void)
cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
offsetof(CPUState, pc), "pc");
- cpu_lock = tcg_global_mem_new_i64(TCG_AREG0,
- offsetof(CPUState, lock), "lock");
+ cpu_lock_addr = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, lock_addr),
+ "lock_addr");
+ cpu_lock_st_addr = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, lock_st_addr),
+ "lock_st_addr");
+ cpu_lock_value = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, lock_value),
+ "lock_value");
#ifdef CONFIG_USER_ONLY
cpu_uniq = tcg_global_mem_new_i64(TCG_AREG0,
@@ -189,14 +198,16 @@ static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
{
- tcg_gen_mov_i64(cpu_lock, t1);
tcg_gen_qemu_ld32s(t0, t1, flags);
+ tcg_gen_mov_i64(cpu_lock_addr, t1);
+ tcg_gen_mov_i64(cpu_lock_value, t0);
}
static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
{
- tcg_gen_mov_i64(cpu_lock, t1);
tcg_gen_qemu_ld64(t0, t1, flags);
+ tcg_gen_mov_i64(cpu_lock_addr, t1);
+ tcg_gen_mov_i64(cpu_lock_value, t0);
}
static inline void gen_load_mem(DisasContext *ctx,
@@ -205,25 +216,31 @@ static inline void gen_load_mem(DisasContext *ctx,
int ra, int rb, int32_t disp16, int fp,
int clear)
{
- TCGv addr;
+ TCGv addr, va;
- if (unlikely(ra == 31))
+ /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
+ prefetches, which we can treat as nops. No worries about
+ missed exceptions here. */
+ if (unlikely(ra == 31)) {
return;
+ }
addr = tcg_temp_new();
if (rb != 31) {
tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
- if (clear)
+ if (clear) {
tcg_gen_andi_i64(addr, addr, ~0x7);
+ }
} else {
- if (clear)
+ if (clear) {
disp16 &= ~0x7;
+ }
tcg_gen_movi_i64(addr, disp16);
}
- if (fp)
- tcg_gen_qemu_load(cpu_fir[ra], addr, ctx->mem_idx);
- else
- tcg_gen_qemu_load(cpu_ir[ra], addr, ctx->mem_idx);
+
+ va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
+ tcg_gen_qemu_load(va, addr, ctx->mem_idx);
+
tcg_temp_free(addr);
}
@@ -257,73 +274,105 @@ static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
tcg_temp_free_i32(tmp32);
}
-static inline void gen_qemu_stl_c(TCGv t0, TCGv t1, int flags)
-{
- int l1, l2;
-
- l1 = gen_new_label();
- l2 = gen_new_label();
- tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
- tcg_gen_qemu_st32(t0, t1, flags);
- tcg_gen_movi_i64(t0, 1);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_movi_i64(t0, 0);
- gen_set_label(l2);
- tcg_gen_movi_i64(cpu_lock, -1);
-}
-
-static inline void gen_qemu_stq_c(TCGv t0, TCGv t1, int flags)
-{
- int l1, l2;
-
- l1 = gen_new_label();
- l2 = gen_new_label();
- tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
- tcg_gen_qemu_st64(t0, t1, flags);
- tcg_gen_movi_i64(t0, 1);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_movi_i64(t0, 0);
- gen_set_label(l2);
- tcg_gen_movi_i64(cpu_lock, -1);
-}
-
static inline void gen_store_mem(DisasContext *ctx,
void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
int flags),
int ra, int rb, int32_t disp16, int fp,
- int clear, int local)
+ int clear)
{
- TCGv addr;
- if (local)
- addr = tcg_temp_local_new();
- else
- addr = tcg_temp_new();
+ TCGv addr, va;
+
+ addr = tcg_temp_new();
if (rb != 31) {
tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
- if (clear)
+ if (clear) {
tcg_gen_andi_i64(addr, addr, ~0x7);
+ }
} else {
- if (clear)
+ if (clear) {
disp16 &= ~0x7;
+ }
tcg_gen_movi_i64(addr, disp16);
}
- if (ra != 31) {
- if (fp)
- tcg_gen_qemu_store(cpu_fir[ra], addr, ctx->mem_idx);
- else
- tcg_gen_qemu_store(cpu_ir[ra], addr, ctx->mem_idx);
+
+ if (ra == 31) {
+ va = tcg_const_i64(0);
} else {
- TCGv zero;
- if (local)
- zero = tcg_const_local_i64(0);
- else
- zero = tcg_const_i64(0);
- tcg_gen_qemu_store(zero, addr, ctx->mem_idx);
- tcg_temp_free(zero);
+ va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
}
+ tcg_gen_qemu_store(va, addr, ctx->mem_idx);
+
tcg_temp_free(addr);
+ if (ra == 31) {
+ tcg_temp_free(va);
+ }
+}
+
+static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
+ int32_t disp16, int quad)
+{
+ TCGv addr;
+
+ if (ra == 31) {
+ /* ??? Don't bother storing anything. The user can't tell
+ the difference, since the zero register always reads zero. */
+ return NO_EXIT;
+ }
+
+#if defined(CONFIG_USER_ONLY)
+ addr = cpu_lock_st_addr;
+#else
+ addr = tcg_local_new();
+#endif
+
+ if (rb != 31) {
+ tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
+ } else {
+ tcg_gen_movi_i64(addr, disp16);
+ }
+
+#if defined(CONFIG_USER_ONLY)
+ /* ??? This is handled via a complicated version of compare-and-swap
+ in the cpu_loop. Hopefully one day we'll have a real CAS opcode
+ in TCG so that this isn't necessary. */
+ return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
+#else
+ /* ??? In system mode we are never multi-threaded, so CAS can be
+ implemented via a non-atomic load-compare-store sequence. */
+ {
+ int lab_fail, lab_done;
+ TCGv val;
+
+ lab_fail = gen_new_label();
+ lab_done = gen_new_label();
+ tcg_gen_brcond(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
+
+ val = tcg_temp_new();
+ if (quad) {
+ tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
+ } else {
+ tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
+ }
+ tcg_gen_brcond(TCG_COND_NE, val, cpu_lock_value, lab_fail);
+
+ if (quad) {
+ tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
+ } else {
+ tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
+ }
+ tcg_gen_movi_i64(cpu_ir[ra], 1);
+ tcg_gen_br(lab_done);
+
+ gen_set_label(lab_fail);
+ tcg_gen_movi_i64(cpu_ir[ra], 0);
+
+ gen_set_label(lab_done);
+ tcg_gen_movi_i64(cpu_lock_addr, -1);
+
+ tcg_temp_free(addr);
+ return NO_EXIT;
+ }
+#endif
}
static int use_goto_tb(DisasContext *ctx, uint64_t dest)
@@ -1534,15 +1583,15 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x0D:
/* STW */
- gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
break;
case 0x0E:
/* STB */
- gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
break;
case 0x0F:
/* STQ_U */
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
break;
case 0x10:
switch (fn7) {
@@ -2975,19 +3024,19 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x24:
/* STF */
- gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0, 0);
+ gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
break;
case 0x25:
/* STG */
- gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0, 0);
+ gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
break;
case 0x26:
/* STS */
- gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0, 0);
+ gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
break;
case 0x27:
/* STT */
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
break;
case 0x28:
/* LDL */
@@ -3007,19 +3056,19 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2C:
/* STL */
- gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
break;
case 0x2D:
/* STQ */
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
break;
case 0x2E:
/* STL_C */
- gen_store_mem(ctx, &gen_qemu_stl_c, ra, rb, disp16, 0, 0, 1);
+ ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
break;
case 0x2F:
/* STQ_C */
- gen_store_mem(ctx, &gen_qemu_stq_c, ra, rb, disp16, 0, 0, 1);
+ ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
break;
case 0x30:
/* BR */
@@ -3285,6 +3334,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
#else
pal_init(env);
#endif
+ env->lock_addr = -1;
/* Initialize IPR */
#if defined (CONFIG_USER_ONLY)
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 13/13] target-alpha: Implement RPCC.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (4 preceding siblings ...)
2010-04-07 22:42 ` [Qemu-devel] [PATCH 12/13] target-alpha: Fix load-locked/store-conditional Richard Henderson
@ 2010-04-07 22:42 ` Richard Henderson
2010-04-10 1:09 ` Aurelien Jarno
2010-04-07 22:49 ` [Qemu-devel] [PATCH 02/13] target-alpha: Implement cpys{, n, e} inline Richard Henderson
` (7 subsequent siblings)
13 siblings, 1 reply; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:42 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
A minimal implementation that more or less corresponds to the
user-level version used by target-i386. More hoops will want
to be jumped through when alpha gets system-level emulation.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
qemu-timer.h | 13 +++++++++++++
target-alpha/cpu.h | 1 -
target-alpha/op_helper.c | 5 +++--
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/qemu-timer.h b/qemu-timer.h
index d2e15f4..6e2d2e1 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -209,6 +209,19 @@ static inline int64_t cpu_get_real_ticks(void)
return (int64_t)(count * cyc_per_count);
}
+#elif defined(__alpha__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+ uint64_t cc;
+ uint32_t cur, ofs;
+
+ asm volatile("rpcc %0" : "=r"(cc));
+ cur = cc;
+ ofs = cc >> 32;
+ return cur - ofs;
+}
+
#else
/* The host CPU doesn't have an easily accessible cycle counter.
Just return a monotonically increasing value. This will be
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index dae23e2..c2f6a50 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -355,7 +355,6 @@ struct CPUAlphaState {
uint64_t ir[31];
float64 fir[31];
uint64_t pc;
- uint32_t pcc[2];
uint64_t ipr[IPR_LAST];
uint64_t ps;
uint64_t unique;
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index bfc095c..ff5ae26 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -21,6 +21,7 @@
#include "host-utils.h"
#include "softfloat.h"
#include "helper.h"
+#include "qemu-timer.h"
/*****************************************************************************/
/* Exceptions processing helpers */
@@ -33,8 +34,8 @@ void QEMU_NORETURN helper_excp (int excp, int error)
uint64_t helper_load_pcc (void)
{
- /* XXX: TODO */
- return 0;
+ /* ??? This isn't a timer for which we have any rate info. */
+ return (uint32_t)cpu_get_real_ticks();
}
uint64_t helper_load_fpcr (void)
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [Qemu-devel] [PATCH 13/13] target-alpha: Implement RPCC.
2010-04-07 22:42 ` [Qemu-devel] [PATCH 13/13] target-alpha: Implement RPCC Richard Henderson
@ 2010-04-10 1:09 ` Aurelien Jarno
0 siblings, 0 replies; 32+ messages in thread
From: Aurelien Jarno @ 2010-04-10 1:09 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Wed, Apr 07, 2010 at 03:42:54PM -0700, Richard Henderson wrote:
> A minimal implementation that more or less corresponds to the
> user-level version used by target-i386. More hoops will want
> to be jumped through when alpha gets system-level emulation.
This patch looks ok, but it mixed host and target changes. Can you
please split it?
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> qemu-timer.h | 13 +++++++++++++
> target-alpha/cpu.h | 1 -
> target-alpha/op_helper.c | 5 +++--
> 3 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/qemu-timer.h b/qemu-timer.h
> index d2e15f4..6e2d2e1 100644
> --- a/qemu-timer.h
> +++ b/qemu-timer.h
> @@ -209,6 +209,19 @@ static inline int64_t cpu_get_real_ticks(void)
> return (int64_t)(count * cyc_per_count);
> }
>
> +#elif defined(__alpha__)
> +
> +static inline int64_t cpu_get_real_ticks(void)
> +{
> + uint64_t cc;
> + uint32_t cur, ofs;
> +
> + asm volatile("rpcc %0" : "=r"(cc));
> + cur = cc;
> + ofs = cc >> 32;
> + return cur - ofs;
> +}
> +
> #else
> /* The host CPU doesn't have an easily accessible cycle counter.
> Just return a monotonically increasing value. This will be
> diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
> index dae23e2..c2f6a50 100644
> --- a/target-alpha/cpu.h
> +++ b/target-alpha/cpu.h
> @@ -355,7 +355,6 @@ struct CPUAlphaState {
> uint64_t ir[31];
> float64 fir[31];
> uint64_t pc;
> - uint32_t pcc[2];
> uint64_t ipr[IPR_LAST];
> uint64_t ps;
> uint64_t unique;
> diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
> index bfc095c..ff5ae26 100644
> --- a/target-alpha/op_helper.c
> +++ b/target-alpha/op_helper.c
> @@ -21,6 +21,7 @@
> #include "host-utils.h"
> #include "softfloat.h"
> #include "helper.h"
> +#include "qemu-timer.h"
>
> /*****************************************************************************/
> /* Exceptions processing helpers */
> @@ -33,8 +34,8 @@ void QEMU_NORETURN helper_excp (int excp, int error)
>
> uint64_t helper_load_pcc (void)
> {
> - /* XXX: TODO */
> - return 0;
> + /* ??? This isn't a timer for which we have any rate info. */
> + return (uint32_t)cpu_get_real_ticks();
> }
>
> uint64_t helper_load_fpcr (void)
> --
> 1.6.6.1
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 02/13] target-alpha: Implement cpys{, n, e} inline.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (5 preceding siblings ...)
2010-04-07 22:42 ` [Qemu-devel] [PATCH 13/13] target-alpha: Implement RPCC Richard Henderson
@ 2010-04-07 22:49 ` Richard Henderson
2010-04-10 0:39 ` Aurelien Jarno
2010-04-07 22:49 ` [Qemu-devel] [PATCH 04/13] target-alpha: Implement cvtql inline Richard Henderson
` (6 subsequent siblings)
13 siblings, 1 reply; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:49 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 4 --
target-alpha/op_helper.c | 18 ----------
target-alpha/translate.c | 78 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 74 insertions(+), 26 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index a508077..8e11304 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -77,10 +77,6 @@ DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cpys, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cpysn, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cpyse, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-
DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 4d2c2ee..2419dc4 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -921,24 +921,6 @@ uint64_t helper_sqrtt (uint64_t a)
return float64_to_t(fr);
}
-
-/* Sign copy */
-uint64_t helper_cpys(uint64_t a, uint64_t b)
-{
- return (a & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
-}
-
-uint64_t helper_cpysn(uint64_t a, uint64_t b)
-{
- return ((~a) & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
-}
-
-uint64_t helper_cpyse(uint64_t a, uint64_t b)
-{
- return (a & 0xFFF0000000000000ULL) | (b & ~0xFFF0000000000000ULL);
-}
-
-
/* Comparisons */
uint64_t helper_cmptun (uint64_t a, uint64_t b)
{
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 719b423..b677378 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -741,6 +741,80 @@ static inline void glue(gen_f, name)(DisasContext *ctx, \
IEEE_INTCVT(cvtqs)
IEEE_INTCVT(cvtqt)
+static void gen_cpys_internal(int ra, int rb, int rc, int inv_a, uint64_t mask)
+{
+ TCGv va, vb, vmask;
+ int za = 0, zb = 0;
+
+ if (unlikely(rc == 31)) {
+ return;
+ }
+
+ vmask = tcg_const_i64(mask);
+
+ TCGV_UNUSED_I64(va);
+ if (ra == 31) {
+ if (inv_a) {
+ va = vmask;
+ } else {
+ za = 1;
+ }
+ } else {
+ va = tcg_temp_new_i64();
+ tcg_gen_mov_i64(va, cpu_fir[ra]);
+ if (inv_a) {
+ tcg_gen_not_i64(va, va);
+ }
+ tcg_gen_and_i64(va, va, vmask);
+ }
+
+ TCGV_UNUSED_I64(vb);
+ if (rb == 31) {
+ zb = 1;
+ } else {
+ vb = tcg_temp_new_i64();
+ tcg_gen_andc_i64(vb, cpu_fir[rb], vmask);
+ }
+
+ switch (za * 2 + zb) {
+ case 0:
+ tcg_gen_or_i64(cpu_fir[rc], va, vb);
+ break;
+ case 1:
+ tcg_gen_mov_i64(cpu_fir[rc], va);
+ break;
+ case 2:
+ tcg_gen_mov_i64(cpu_fir[rc], vb);
+ break;
+ case 3:
+ tcg_gen_movi_i64(cpu_fir[rc], 0);
+ break;
+ }
+
+ tcg_temp_free(vmask);
+ if (ra != 31) {
+ tcg_temp_free(va);
+ }
+ if (rb != 31) {
+ tcg_temp_free(vb);
+ }
+}
+
+static inline void gen_fcpys(int ra, int rb, int rc)
+{
+ gen_cpys_internal(ra, rb, rc, 0, 0x8000000000000000ULL);
+}
+
+static inline void gen_fcpysn(int ra, int rb, int rc)
+{
+ gen_cpys_internal(ra, rb, rc, 1, 0x8000000000000000ULL);
+}
+
+static inline void gen_fcpyse(int ra, int rb, int rc)
+{
+ gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
+}
+
#define FARITH3(name) \
static inline void glue(gen_f, name)(int ra, int rb, int rc) \
{ \
@@ -769,10 +843,6 @@ static inline void glue(gen_f, name)(int ra, int rb, int rc) \
tcg_temp_free(vb); \
} \
}
-/* ??? Ought to expand these inline; simple masking operations. */
-FARITH3(cpys)
-FARITH3(cpysn)
-FARITH3(cpyse)
/* ??? VAX instruction qualifiers ignored. */
FARITH3(addf)
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [Qemu-devel] [PATCH 02/13] target-alpha: Implement cpys{, n, e} inline.
2010-04-07 22:49 ` [Qemu-devel] [PATCH 02/13] target-alpha: Implement cpys{, n, e} inline Richard Henderson
@ 2010-04-10 0:39 ` Aurelien Jarno
0 siblings, 0 replies; 32+ messages in thread
From: Aurelien Jarno @ 2010-04-10 0:39 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Fri, Mar 12, 2010 at 11:22:45AM -0800, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-alpha/helper.h | 4 --
> target-alpha/op_helper.c | 18 ----------
> target-alpha/translate.c | 78 +++++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 74 insertions(+), 26 deletions(-)
>
> diff --git a/target-alpha/helper.h b/target-alpha/helper.h
> index a508077..8e11304 100644
> --- a/target-alpha/helper.h
> +++ b/target-alpha/helper.h
> @@ -77,10 +77,6 @@ DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
>
> -DEF_HELPER_FLAGS_2(cpys, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> -DEF_HELPER_FLAGS_2(cpysn, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> -DEF_HELPER_FLAGS_2(cpyse, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> -
> DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
> DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
> DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
> diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
> index 4d2c2ee..2419dc4 100644
> --- a/target-alpha/op_helper.c
> +++ b/target-alpha/op_helper.c
> @@ -921,24 +921,6 @@ uint64_t helper_sqrtt (uint64_t a)
> return float64_to_t(fr);
> }
>
> -
> -/* Sign copy */
> -uint64_t helper_cpys(uint64_t a, uint64_t b)
> -{
> - return (a & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
> -}
> -
> -uint64_t helper_cpysn(uint64_t a, uint64_t b)
> -{
> - return ((~a) & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
> -}
> -
> -uint64_t helper_cpyse(uint64_t a, uint64_t b)
> -{
> - return (a & 0xFFF0000000000000ULL) | (b & ~0xFFF0000000000000ULL);
> -}
> -
> -
> /* Comparisons */
> uint64_t helper_cmptun (uint64_t a, uint64_t b)
> {
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index 719b423..b677378 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -741,6 +741,80 @@ static inline void glue(gen_f, name)(DisasContext *ctx, \
> IEEE_INTCVT(cvtqs)
> IEEE_INTCVT(cvtqt)
>
> +static void gen_cpys_internal(int ra, int rb, int rc, int inv_a, uint64_t mask)
> +{
> + TCGv va, vb, vmask;
> + int za = 0, zb = 0;
> +
> + if (unlikely(rc == 31)) {
> + return;
> + }
> +
> + vmask = tcg_const_i64(mask);
> +
> + TCGV_UNUSED_I64(va);
> + if (ra == 31) {
> + if (inv_a) {
> + va = vmask;
> + } else {
> + za = 1;
> + }
> + } else {
> + va = tcg_temp_new_i64();
> + tcg_gen_mov_i64(va, cpu_fir[ra]);
> + if (inv_a) {
> + tcg_gen_not_i64(va, va);
> + }
> + tcg_gen_and_i64(va, va, vmask);
You can use instead:
if (inv_a) {
tcg_gen_andc_i64(va, vmask, va);
} else {
tcg_gen_and_i64(va, vmask, va);
}
> + }
> +
> + TCGV_UNUSED_I64(vb);
> + if (rb == 31) {
> + zb = 1;
> + } else {
> + vb = tcg_temp_new_i64();
> + tcg_gen_andc_i64(vb, cpu_fir[rb], vmask);
> + }
> +
> + switch (za * 2 + zb) {
> + case 0:
> + tcg_gen_or_i64(cpu_fir[rc], va, vb);
> + break;
> + case 1:
> + tcg_gen_mov_i64(cpu_fir[rc], va);
> + break;
> + case 2:
> + tcg_gen_mov_i64(cpu_fir[rc], vb);
> + break;
> + case 3:
> + tcg_gen_movi_i64(cpu_fir[rc], 0);
> + break;
> + }
It's probably more clear here if you use switch(za << 1 | zb) and later
case 0 | 0:, case 0 | 1:, case 2 | 0 and case 2 | 1:.
> + tcg_temp_free(vmask);
> + if (ra != 31) {
> + tcg_temp_free(va);
> + }
> + if (rb != 31) {
> + tcg_temp_free(vb);
> + }
> +}
> +
> +static inline void gen_fcpys(int ra, int rb, int rc)
> +{
> + gen_cpys_internal(ra, rb, rc, 0, 0x8000000000000000ULL);
> +}
> +
> +static inline void gen_fcpysn(int ra, int rb, int rc)
> +{
> + gen_cpys_internal(ra, rb, rc, 1, 0x8000000000000000ULL);
> +}
> +
> +static inline void gen_fcpyse(int ra, int rb, int rc)
> +{
> + gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
> +}
> +
> #define FARITH3(name) \
> static inline void glue(gen_f, name)(int ra, int rb, int rc) \
> { \
> @@ -769,10 +843,6 @@ static inline void glue(gen_f, name)(int ra, int rb, int rc) \
> tcg_temp_free(vb); \
> } \
> }
> -/* ??? Ought to expand these inline; simple masking operations. */
> -FARITH3(cpys)
> -FARITH3(cpysn)
> -FARITH3(cpyse)
>
> /* ??? VAX instruction qualifiers ignored. */
> FARITH3(addf)
> --
> 1.6.6.1
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 04/13] target-alpha: Implement cvtql inline.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (6 preceding siblings ...)
2010-04-07 22:49 ` [Qemu-devel] [PATCH 02/13] target-alpha: Implement cpys{, n, e} inline Richard Henderson
@ 2010-04-07 22:49 ` Richard Henderson
2010-04-07 22:49 ` [Qemu-devel] [PATCH 06/13] target-alpha: Use setcond for int comparisons Richard Henderson
` (5 subsequent siblings)
13 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:49 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
It's a simple mask and shift sequence.
Also, fix a typo in the actual masks used.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 4 ----
target-alpha/op_helper.c | 20 --------------------
target-alpha/translate.c | 45 +++++++++++++++++++++++++++++++++++++++------
3 files changed, 39 insertions(+), 30 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index c378195..10c78d0 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -89,10 +89,6 @@ DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvttq_svic, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtql, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
-DEF_HELPER_1(cvtql_v, i64, i64)
-DEF_HELPER_1(cvtql_sv, i64, i64)
-
DEF_HELPER_FLAGS_1(setroundmode, TCG_CALL_CONST, void, i32)
DEF_HELPER_FLAGS_1(setflushzero, TCG_CALL_CONST, void, i32)
DEF_HELPER_FLAGS_0(fp_exc_clear, TCG_CALL_CONST, void)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 84867b8..f9cd07a 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1159,26 +1159,6 @@ uint64_t helper_cvtlq (uint64_t a)
return (lo & 0x3FFFFFFF) | (hi & 0xc0000000);
}
-uint64_t helper_cvtql (uint64_t a)
-{
- return ((a & 0xC0000000) << 32) | ((a & 0x7FFFFFFF) << 29);
-}
-
-uint64_t helper_cvtql_v (uint64_t a)
-{
- if ((int32_t)a != (int64_t)a)
- helper_excp(EXCP_ARITH, EXC_M_IOV);
- return helper_cvtql(a);
-}
-
-uint64_t helper_cvtql_sv (uint64_t a)
-{
- /* ??? I'm pretty sure there's nothing that /sv needs to do that /v
- doesn't do. The only thing I can think is that /sv is a valid
- instruction merely for completeness in the ISA. */
- return helper_cvtql_v(a);
-}
-
/* PALcode support special instructions */
#if !defined (CONFIG_USER_ONLY)
void helper_hw_rei (void)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 188e76c..44ce830 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -597,6 +597,41 @@ static inline void gen_fp_exc_raise(int rc, int fn11)
gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
}
+static void gen_fcvtql(int rb, int rc)
+{
+ if (unlikely(rc == 31)) {
+ return;
+ }
+ if (unlikely(rb == 31)) {
+ tcg_gen_movi_i64(cpu_fir[rc], 0);
+ } else {
+ TCGv tmp = tcg_temp_new();
+
+ tcg_gen_andi_i64(tmp, cpu_fir[rb], 0xC0000000);
+ tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rb], 0x3FFFFFFF);
+ tcg_gen_shli_i64(tmp, tmp, 32);
+ tcg_gen_shli_i64(cpu_fir[rc], cpu_fir[rc], 29);
+ tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
+
+ tcg_temp_free(tmp);
+ }
+}
+
+static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc)
+{
+ if (rb != 31) {
+ int lab = gen_new_label();
+ TCGv tmp = tcg_temp_new();
+
+ tcg_gen_ext32s_i64(tmp, cpu_fir[rb]);
+ tcg_gen_brcond_i64(TCG_COND_EQ, tmp, cpu_fir[rb], lab);
+ gen_excp(ctx, EXCP_ARITH, EXC_M_IOV);
+
+ gen_set_label(lab);
+ }
+ gen_fcvtql(rb, rc);
+}
+
#define FARITH2(name) \
static inline void glue(gen_f, name)(int rb, int rc) \
{ \
@@ -612,9 +647,6 @@ static inline void glue(gen_f, name)(int rb, int rc) \
} \
}
FARITH2(cvtlq)
-FARITH2(cvtql)
-FARITH2(cvtql_v)
-FARITH2(cvtql_sv)
/* ??? VAX instruction qualifiers ignored. */
FARITH2(sqrtf)
@@ -2327,11 +2359,12 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x130:
/* CVTQL/V */
- gen_fcvtql_v(rb, rc);
- break;
case 0x530:
/* CVTQL/SV */
- gen_fcvtql_sv(rb, rc);
+ /* ??? I'm pretty sure there's nothing that /sv needs to do that
+ /v doesn't do. The only thing I can think is that /sv is a
+ valid instruction merely for completeness in the ISA. */
+ gen_fcvtql_v(ctx, rb, rc);
break;
default:
goto invalid_opc;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 06/13] target-alpha: Use setcond for int comparisons.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (7 preceding siblings ...)
2010-04-07 22:49 ` [Qemu-devel] [PATCH 04/13] target-alpha: Implement cvtql inline Richard Henderson
@ 2010-04-07 22:49 ` Richard Henderson
2010-04-10 1:05 ` Aurelien Jarno
2010-04-07 22:49 ` [Qemu-devel] [PATCH 01/13] target-alpha: Add flags markups to helpers.h Richard Henderson
` (4 subsequent siblings)
13 siblings, 1 reply; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:49 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 43 ++++++++++++++++++++++---------------------
1 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index dff03ef..adeff0a 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1290,33 +1290,34 @@ MVIOP2(pkwb)
MVIOP2(unpkbl)
MVIOP2(unpkbw)
-static inline void gen_cmp(TCGCond cond, int ra, int rb, int rc, int islit,
- uint8_t lit)
+static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
+ int islit, uint8_t lit)
{
- int l1, l2;
- TCGv tmp;
+ TCGv va, vb;
- if (unlikely(rc == 31))
+ if (unlikely(rc == 31)) {
return;
+ }
- l1 = gen_new_label();
- l2 = gen_new_label();
+ if (ra == 31) {
+ va = tcg_const_i64(0);
+ } else {
+ va = cpu_ir[ra];
+ }
+ if (islit) {
+ vb = tcg_const_i64(lit);
+ } else {
+ vb = cpu_ir[rb];
+ }
- if (ra != 31) {
- tmp = tcg_temp_new();
- tcg_gen_mov_i64(tmp, cpu_ir[ra]);
- } else
- tmp = tcg_const_i64(0);
- if (islit)
- tcg_gen_brcondi_i64(cond, tmp, lit, l1);
- else
- tcg_gen_brcond_i64(cond, tmp, cpu_ir[rb], l1);
+ tcg_gen_setcond_i64(cond, cpu_ir[rc], va, vb);
- tcg_gen_movi_i64(cpu_ir[rc], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_movi_i64(cpu_ir[rc], 1);
- gen_set_label(l2);
+ if (ra == 31) {
+ tcg_temp_free(va);
+ }
+ if (islit) {
+ tcg_temp_free(vb);
+ }
}
static void gen_rx(int ra, int set)
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [Qemu-devel] [PATCH 06/13] target-alpha: Use setcond for int comparisons.
2010-04-07 22:49 ` [Qemu-devel] [PATCH 06/13] target-alpha: Use setcond for int comparisons Richard Henderson
@ 2010-04-10 1:05 ` Aurelien Jarno
0 siblings, 0 replies; 32+ messages in thread
From: Aurelien Jarno @ 2010-04-10 1:05 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Mar 16, 2010 at 01:04:34PM -0700, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-alpha/translate.c | 43 ++++++++++++++++++++++---------------------
> 1 files changed, 22 insertions(+), 21 deletions(-)
Thanks, applied.
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index dff03ef..adeff0a 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -1290,33 +1290,34 @@ MVIOP2(pkwb)
> MVIOP2(unpkbl)
> MVIOP2(unpkbw)
>
> -static inline void gen_cmp(TCGCond cond, int ra, int rb, int rc, int islit,
> - uint8_t lit)
> +static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
> + int islit, uint8_t lit)
> {
> - int l1, l2;
> - TCGv tmp;
> + TCGv va, vb;
>
> - if (unlikely(rc == 31))
> + if (unlikely(rc == 31)) {
> return;
> + }
>
> - l1 = gen_new_label();
> - l2 = gen_new_label();
> + if (ra == 31) {
> + va = tcg_const_i64(0);
> + } else {
> + va = cpu_ir[ra];
> + }
> + if (islit) {
> + vb = tcg_const_i64(lit);
> + } else {
> + vb = cpu_ir[rb];
> + }
>
> - if (ra != 31) {
> - tmp = tcg_temp_new();
> - tcg_gen_mov_i64(tmp, cpu_ir[ra]);
> - } else
> - tmp = tcg_const_i64(0);
> - if (islit)
> - tcg_gen_brcondi_i64(cond, tmp, lit, l1);
> - else
> - tcg_gen_brcond_i64(cond, tmp, cpu_ir[rb], l1);
> + tcg_gen_setcond_i64(cond, cpu_ir[rc], va, vb);
>
> - tcg_gen_movi_i64(cpu_ir[rc], 0);
> - tcg_gen_br(l2);
> - gen_set_label(l1);
> - tcg_gen_movi_i64(cpu_ir[rc], 1);
> - gen_set_label(l2);
> + if (ra == 31) {
> + tcg_temp_free(va);
> + }
> + if (islit) {
> + tcg_temp_free(vb);
> + }
> }
>
> static void gen_rx(int ra, int set)
> --
> 1.6.6.1
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 01/13] target-alpha: Add flags markups to helpers.h.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (8 preceding siblings ...)
2010-04-07 22:49 ` [Qemu-devel] [PATCH 06/13] target-alpha: Use setcond for int comparisons Richard Henderson
@ 2010-04-07 22:49 ` Richard Henderson
2010-04-10 1:05 ` Aurelien Jarno
2010-04-07 22:49 ` [Qemu-devel] [PATCH 07/13] target-alpha: Use non-inverted arguments to gen_{f}cmov Richard Henderson
` (3 subsequent siblings)
13 siblings, 1 reply; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:49 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Almost all alpha helpers are at least TCG_CALL_CONST
and a fair few are also TCG_CALL_PURE.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 184 ++++++++++++++++++++++++------------------------
1 files changed, 92 insertions(+), 92 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 79cf375..a508077 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,9 +1,9 @@
#include "def-helper.h"
DEF_HELPER_2(excp, void, int, int)
-DEF_HELPER_0(load_pcc, i64)
-DEF_HELPER_0(rc, i64)
-DEF_HELPER_0(rs, i64)
+DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
+DEF_HELPER_FLAGS_0(rc, TCG_CALL_CONST, i64)
+DEF_HELPER_FLAGS_0(rs, TCG_CALL_CONST, i64)
DEF_HELPER_2(addqv, i64, i64, i64)
DEF_HELPER_2(addlv, i64, i64, i64)
@@ -11,98 +11,98 @@ DEF_HELPER_2(subqv, i64, i64, i64)
DEF_HELPER_2(sublv, i64, i64, i64)
DEF_HELPER_2(mullv, i64, i64, i64)
DEF_HELPER_2(mulqv, i64, i64, i64)
-DEF_HELPER_2(umulh, i64, i64, i64)
-
-DEF_HELPER_1(ctpop, i64, i64)
-DEF_HELPER_1(ctlz, i64, i64)
-DEF_HELPER_1(cttz, i64, i64)
-
-DEF_HELPER_2(zap, i64, i64, i64)
-DEF_HELPER_2(zapnot, i64, i64, i64)
-
-DEF_HELPER_2(cmpbge, i64, i64, i64)
-
-DEF_HELPER_2(minub8, i64, i64, i64)
-DEF_HELPER_2(minsb8, i64, i64, i64)
-DEF_HELPER_2(minuw4, i64, i64, i64)
-DEF_HELPER_2(minsw4, i64, i64, i64)
-DEF_HELPER_2(maxub8, i64, i64, i64)
-DEF_HELPER_2(maxsb8, i64, i64, i64)
-DEF_HELPER_2(maxuw4, i64, i64, i64)
-DEF_HELPER_2(maxsw4, i64, i64, i64)
-DEF_HELPER_2(perr, i64, i64, i64)
-DEF_HELPER_1(pklb, i64, i64)
-DEF_HELPER_1(pkwb, i64, i64)
-DEF_HELPER_1(unpkbl, i64, i64)
-DEF_HELPER_1(unpkbw, i64, i64)
-
-DEF_HELPER_0(load_fpcr, i64)
-DEF_HELPER_1(store_fpcr, void, i64)
-
-DEF_HELPER_1(f_to_memory, i32, i64)
-DEF_HELPER_1(memory_to_f, i64, i32)
-DEF_HELPER_2(addf, i64, i64, i64)
-DEF_HELPER_2(subf, i64, i64, i64)
-DEF_HELPER_2(mulf, i64, i64, i64)
-DEF_HELPER_2(divf, i64, i64, i64)
-DEF_HELPER_1(sqrtf, i64, i64)
-
-DEF_HELPER_1(g_to_memory, i64, i64)
-DEF_HELPER_1(memory_to_g, i64, i64)
-DEF_HELPER_2(addg, i64, i64, i64)
-DEF_HELPER_2(subg, i64, i64, i64)
-DEF_HELPER_2(mulg, i64, i64, i64)
-DEF_HELPER_2(divg, i64, i64, i64)
-DEF_HELPER_1(sqrtg, i64, i64)
-
-DEF_HELPER_1(s_to_memory, i32, i64)
-DEF_HELPER_1(memory_to_s, i64, i32)
-DEF_HELPER_2(adds, i64, i64, i64)
-DEF_HELPER_2(subs, i64, i64, i64)
-DEF_HELPER_2(muls, i64, i64, i64)
-DEF_HELPER_2(divs, i64, i64, i64)
-DEF_HELPER_1(sqrts, i64, i64)
-
-DEF_HELPER_2(addt, i64, i64, i64)
-DEF_HELPER_2(subt, i64, i64, i64)
-DEF_HELPER_2(mult, i64, i64, i64)
-DEF_HELPER_2(divt, i64, i64, i64)
-DEF_HELPER_1(sqrtt, i64, i64)
-
-DEF_HELPER_2(cmptun, i64, i64, i64)
-DEF_HELPER_2(cmpteq, i64, i64, i64)
-DEF_HELPER_2(cmptle, i64, i64, i64)
-DEF_HELPER_2(cmptlt, i64, i64, i64)
-DEF_HELPER_2(cmpgeq, i64, i64, i64)
-DEF_HELPER_2(cmpgle, i64, i64, i64)
-DEF_HELPER_2(cmpglt, i64, i64, i64)
-
-DEF_HELPER_2(cpys, i64, i64, i64)
-DEF_HELPER_2(cpysn, i64, i64, i64)
-DEF_HELPER_2(cpyse, i64, i64, i64)
-
-DEF_HELPER_1(cvtts, i64, i64)
-DEF_HELPER_1(cvtst, i64, i64)
-DEF_HELPER_1(cvtqs, i64, i64)
-DEF_HELPER_1(cvtqt, i64, i64)
-DEF_HELPER_1(cvtqf, i64, i64)
-DEF_HELPER_1(cvtgf, i64, i64)
-DEF_HELPER_1(cvtgq, i64, i64)
-DEF_HELPER_1(cvtqg, i64, i64)
-DEF_HELPER_1(cvtlq, i64, i64)
-
-DEF_HELPER_1(cvttq, i64, i64)
-DEF_HELPER_1(cvttq_c, i64, i64)
-DEF_HELPER_1(cvttq_svic, i64, i64)
-
-DEF_HELPER_1(cvtql, i64, i64)
+DEF_HELPER_FLAGS_2(umulh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+
+DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+DEF_HELPER_FLAGS_1(ctlz, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+DEF_HELPER_FLAGS_1(cttz, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+
+DEF_HELPER_FLAGS_2(zap, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(zapnot, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+
+DEF_HELPER_FLAGS_2(cmpbge, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+
+DEF_HELPER_FLAGS_2(minub8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(minsb8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(minuw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(minsw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(maxub8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(maxsb8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(maxuw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(maxsw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(perr, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_1(pklb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+DEF_HELPER_FLAGS_1(pkwb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+DEF_HELPER_FLAGS_1(unpkbl, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+DEF_HELPER_FLAGS_1(unpkbw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+
+DEF_HELPER_FLAGS_0(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64)
+DEF_HELPER_FLAGS_1(store_fpcr, TCG_CALL_CONST, void, i64)
+
+DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
+DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
+DEF_HELPER_FLAGS_2(addf, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(subf, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(mulf, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(divf, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_1(sqrtf, TCG_CALL_CONST, i64, i64)
+
+DEF_HELPER_FLAGS_1(g_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+DEF_HELPER_FLAGS_1(memory_to_g, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+DEF_HELPER_FLAGS_2(addg, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(subg, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(mulg, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(divg, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_1(sqrtg, TCG_CALL_CONST, i64, i64)
+
+DEF_HELPER_FLAGS_1(s_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
+DEF_HELPER_FLAGS_1(memory_to_s, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
+DEF_HELPER_FLAGS_2(adds, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(subs, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(muls, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(divs, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_1(sqrts, TCG_CALL_CONST, i64, i64)
+
+DEF_HELPER_FLAGS_2(addt, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(subt, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(mult, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_2(divt, TCG_CALL_CONST, i64, i64, i64)
+DEF_HELPER_FLAGS_1(sqrtt, TCG_CALL_CONST, i64, i64)
+
+DEF_HELPER_FLAGS_2(cmptun, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(cmpteq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(cmptle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(cmptlt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+
+DEF_HELPER_FLAGS_2(cpys, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(cpysn, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(cpyse, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+
+DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvtqt, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvtqf, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvtgf, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvtgq, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvtqg, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvtlq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
+
+DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_1(cvttq_svic, TCG_CALL_CONST, i64, i64)
+
+DEF_HELPER_FLAGS_1(cvtql, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
DEF_HELPER_1(cvtql_v, i64, i64)
DEF_HELPER_1(cvtql_sv, i64, i64)
-DEF_HELPER_1(setroundmode, void, i32)
-DEF_HELPER_1(setflushzero, void, i32)
-DEF_HELPER_0(fp_exc_clear, void)
-DEF_HELPER_0(fp_exc_get, i32)
+DEF_HELPER_FLAGS_1(setroundmode, TCG_CALL_CONST, void, i32)
+DEF_HELPER_FLAGS_1(setflushzero, TCG_CALL_CONST, void, i32)
+DEF_HELPER_FLAGS_0(fp_exc_clear, TCG_CALL_CONST, void)
+DEF_HELPER_FLAGS_0(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32)
DEF_HELPER_2(fp_exc_raise, void, i32, i32)
DEF_HELPER_2(fp_exc_raise_s, void, i32, i32)
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [Qemu-devel] [PATCH 01/13] target-alpha: Add flags markups to helpers.h.
2010-04-07 22:49 ` [Qemu-devel] [PATCH 01/13] target-alpha: Add flags markups to helpers.h Richard Henderson
@ 2010-04-10 1:05 ` Aurelien Jarno
0 siblings, 0 replies; 32+ messages in thread
From: Aurelien Jarno @ 2010-04-10 1:05 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Fri, Mar 12, 2010 at 10:31:49AM -0800, Richard Henderson wrote:
> Almost all alpha helpers are at least TCG_CALL_CONST
> and a fair few are also TCG_CALL_PURE.
Thanks, applied.
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-alpha/helper.h | 184 ++++++++++++++++++++++++------------------------
> 1 files changed, 92 insertions(+), 92 deletions(-)
>
> diff --git a/target-alpha/helper.h b/target-alpha/helper.h
> index 79cf375..a508077 100644
> --- a/target-alpha/helper.h
> +++ b/target-alpha/helper.h
> @@ -1,9 +1,9 @@
> #include "def-helper.h"
>
> DEF_HELPER_2(excp, void, int, int)
> -DEF_HELPER_0(load_pcc, i64)
> -DEF_HELPER_0(rc, i64)
> -DEF_HELPER_0(rs, i64)
> +DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
> +DEF_HELPER_FLAGS_0(rc, TCG_CALL_CONST, i64)
> +DEF_HELPER_FLAGS_0(rs, TCG_CALL_CONST, i64)
>
> DEF_HELPER_2(addqv, i64, i64, i64)
> DEF_HELPER_2(addlv, i64, i64, i64)
> @@ -11,98 +11,98 @@ DEF_HELPER_2(subqv, i64, i64, i64)
> DEF_HELPER_2(sublv, i64, i64, i64)
> DEF_HELPER_2(mullv, i64, i64, i64)
> DEF_HELPER_2(mulqv, i64, i64, i64)
> -DEF_HELPER_2(umulh, i64, i64, i64)
> -
> -DEF_HELPER_1(ctpop, i64, i64)
> -DEF_HELPER_1(ctlz, i64, i64)
> -DEF_HELPER_1(cttz, i64, i64)
> -
> -DEF_HELPER_2(zap, i64, i64, i64)
> -DEF_HELPER_2(zapnot, i64, i64, i64)
> -
> -DEF_HELPER_2(cmpbge, i64, i64, i64)
> -
> -DEF_HELPER_2(minub8, i64, i64, i64)
> -DEF_HELPER_2(minsb8, i64, i64, i64)
> -DEF_HELPER_2(minuw4, i64, i64, i64)
> -DEF_HELPER_2(minsw4, i64, i64, i64)
> -DEF_HELPER_2(maxub8, i64, i64, i64)
> -DEF_HELPER_2(maxsb8, i64, i64, i64)
> -DEF_HELPER_2(maxuw4, i64, i64, i64)
> -DEF_HELPER_2(maxsw4, i64, i64, i64)
> -DEF_HELPER_2(perr, i64, i64, i64)
> -DEF_HELPER_1(pklb, i64, i64)
> -DEF_HELPER_1(pkwb, i64, i64)
> -DEF_HELPER_1(unpkbl, i64, i64)
> -DEF_HELPER_1(unpkbw, i64, i64)
> -
> -DEF_HELPER_0(load_fpcr, i64)
> -DEF_HELPER_1(store_fpcr, void, i64)
> -
> -DEF_HELPER_1(f_to_memory, i32, i64)
> -DEF_HELPER_1(memory_to_f, i64, i32)
> -DEF_HELPER_2(addf, i64, i64, i64)
> -DEF_HELPER_2(subf, i64, i64, i64)
> -DEF_HELPER_2(mulf, i64, i64, i64)
> -DEF_HELPER_2(divf, i64, i64, i64)
> -DEF_HELPER_1(sqrtf, i64, i64)
> -
> -DEF_HELPER_1(g_to_memory, i64, i64)
> -DEF_HELPER_1(memory_to_g, i64, i64)
> -DEF_HELPER_2(addg, i64, i64, i64)
> -DEF_HELPER_2(subg, i64, i64, i64)
> -DEF_HELPER_2(mulg, i64, i64, i64)
> -DEF_HELPER_2(divg, i64, i64, i64)
> -DEF_HELPER_1(sqrtg, i64, i64)
> -
> -DEF_HELPER_1(s_to_memory, i32, i64)
> -DEF_HELPER_1(memory_to_s, i64, i32)
> -DEF_HELPER_2(adds, i64, i64, i64)
> -DEF_HELPER_2(subs, i64, i64, i64)
> -DEF_HELPER_2(muls, i64, i64, i64)
> -DEF_HELPER_2(divs, i64, i64, i64)
> -DEF_HELPER_1(sqrts, i64, i64)
> -
> -DEF_HELPER_2(addt, i64, i64, i64)
> -DEF_HELPER_2(subt, i64, i64, i64)
> -DEF_HELPER_2(mult, i64, i64, i64)
> -DEF_HELPER_2(divt, i64, i64, i64)
> -DEF_HELPER_1(sqrtt, i64, i64)
> -
> -DEF_HELPER_2(cmptun, i64, i64, i64)
> -DEF_HELPER_2(cmpteq, i64, i64, i64)
> -DEF_HELPER_2(cmptle, i64, i64, i64)
> -DEF_HELPER_2(cmptlt, i64, i64, i64)
> -DEF_HELPER_2(cmpgeq, i64, i64, i64)
> -DEF_HELPER_2(cmpgle, i64, i64, i64)
> -DEF_HELPER_2(cmpglt, i64, i64, i64)
> -
> -DEF_HELPER_2(cpys, i64, i64, i64)
> -DEF_HELPER_2(cpysn, i64, i64, i64)
> -DEF_HELPER_2(cpyse, i64, i64, i64)
> -
> -DEF_HELPER_1(cvtts, i64, i64)
> -DEF_HELPER_1(cvtst, i64, i64)
> -DEF_HELPER_1(cvtqs, i64, i64)
> -DEF_HELPER_1(cvtqt, i64, i64)
> -DEF_HELPER_1(cvtqf, i64, i64)
> -DEF_HELPER_1(cvtgf, i64, i64)
> -DEF_HELPER_1(cvtgq, i64, i64)
> -DEF_HELPER_1(cvtqg, i64, i64)
> -DEF_HELPER_1(cvtlq, i64, i64)
> -
> -DEF_HELPER_1(cvttq, i64, i64)
> -DEF_HELPER_1(cvttq_c, i64, i64)
> -DEF_HELPER_1(cvttq_svic, i64, i64)
> -
> -DEF_HELPER_1(cvtql, i64, i64)
> +DEF_HELPER_FLAGS_2(umulh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +
> +DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +DEF_HELPER_FLAGS_1(ctlz, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +DEF_HELPER_FLAGS_1(cttz, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +
> +DEF_HELPER_FLAGS_2(zap, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(zapnot, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +
> +DEF_HELPER_FLAGS_2(cmpbge, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +
> +DEF_HELPER_FLAGS_2(minub8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(minsb8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(minuw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(minsw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(maxub8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(maxsb8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(maxuw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(maxsw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(perr, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_1(pklb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +DEF_HELPER_FLAGS_1(pkwb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +DEF_HELPER_FLAGS_1(unpkbl, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +DEF_HELPER_FLAGS_1(unpkbw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +
> +DEF_HELPER_FLAGS_0(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64)
> +DEF_HELPER_FLAGS_1(store_fpcr, TCG_CALL_CONST, void, i64)
> +
> +DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
> +DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
> +DEF_HELPER_FLAGS_2(addf, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(subf, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(mulf, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(divf, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_1(sqrtf, TCG_CALL_CONST, i64, i64)
> +
> +DEF_HELPER_FLAGS_1(g_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +DEF_HELPER_FLAGS_1(memory_to_g, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +DEF_HELPER_FLAGS_2(addg, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(subg, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(mulg, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(divg, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_1(sqrtg, TCG_CALL_CONST, i64, i64)
> +
> +DEF_HELPER_FLAGS_1(s_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
> +DEF_HELPER_FLAGS_1(memory_to_s, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
> +DEF_HELPER_FLAGS_2(adds, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(subs, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(muls, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(divs, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_1(sqrts, TCG_CALL_CONST, i64, i64)
> +
> +DEF_HELPER_FLAGS_2(addt, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(subt, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(mult, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(divt, TCG_CALL_CONST, i64, i64, i64)
> +DEF_HELPER_FLAGS_1(sqrtt, TCG_CALL_CONST, i64, i64)
> +
> +DEF_HELPER_FLAGS_2(cmptun, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(cmpteq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(cmptle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(cmptlt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +
> +DEF_HELPER_FLAGS_2(cpys, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(cpysn, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +DEF_HELPER_FLAGS_2(cpyse, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
> +
> +DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvtqt, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvtqf, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvtgf, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvtgq, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvtqg, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvtlq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> +
> +DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
> +DEF_HELPER_FLAGS_1(cvttq_svic, TCG_CALL_CONST, i64, i64)
> +
> +DEF_HELPER_FLAGS_1(cvtql, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
> DEF_HELPER_1(cvtql_v, i64, i64)
> DEF_HELPER_1(cvtql_sv, i64, i64)
>
> -DEF_HELPER_1(setroundmode, void, i32)
> -DEF_HELPER_1(setflushzero, void, i32)
> -DEF_HELPER_0(fp_exc_clear, void)
> -DEF_HELPER_0(fp_exc_get, i32)
> +DEF_HELPER_FLAGS_1(setroundmode, TCG_CALL_CONST, void, i32)
> +DEF_HELPER_FLAGS_1(setflushzero, TCG_CALL_CONST, void, i32)
> +DEF_HELPER_FLAGS_0(fp_exc_clear, TCG_CALL_CONST, void)
> +DEF_HELPER_FLAGS_0(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32)
> DEF_HELPER_2(fp_exc_raise, void, i32, i32)
> DEF_HELPER_2(fp_exc_raise_s, void, i32, i32)
>
> --
> 1.6.6.1
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 07/13] target-alpha: Use non-inverted arguments to gen_{f}cmov.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (9 preceding siblings ...)
2010-04-07 22:49 ` [Qemu-devel] [PATCH 01/13] target-alpha: Add flags markups to helpers.h Richard Henderson
@ 2010-04-07 22:49 ` Richard Henderson
2010-04-10 1:05 ` Aurelien Jarno
2010-04-07 22:49 ` [Qemu-devel] [PATCH 03/13] target-alpha: Implement rs/rc properly Richard Henderson
` (2 subsequent siblings)
13 siblings, 1 reply; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:49 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
The inverted conditions as argument to the function looks wrong
at a glance inside translate_one. Since we have an easy function
to produce the inversion now, use it.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 37 +++++++++++++++++++------------------
1 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index adeff0a..ea651c4 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -394,9 +394,10 @@ static void gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, int32_t disp)
gen_bcond_pcload(ctx, disp, lab_true);
}
-static inline void gen_cmov(TCGCond inv_cond, int ra, int rb, int rc,
- int islit, uint8_t lit, int mask)
+static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
+ int islit, uint8_t lit, int mask)
{
+ TCGCond inv_cond = tcg_invert_cond(cond);
int l1;
if (unlikely(rc == 31))
@@ -426,7 +427,7 @@ static inline void gen_cmov(TCGCond inv_cond, int ra, int rb, int rc,
gen_set_label(l1);
}
-static void gen_fcmov(TCGCond inv_cond, int ra, int rb, int rc)
+static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
{
TCGv va = cpu_fir[ra];
int l1;
@@ -439,7 +440,7 @@ static void gen_fcmov(TCGCond inv_cond, int ra, int rb, int rc)
}
l1 = gen_new_label();
- gen_fbcond_internal(inv_cond, va, l1);
+ gen_fbcond_internal(tcg_invert_cond(cond), va, l1);
if (rb != 31)
tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
@@ -1767,11 +1768,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x14:
/* CMOVLBS */
- gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
+ gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
break;
case 0x16:
/* CMOVLBC */
- gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
+ gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
break;
case 0x20:
/* BIS */
@@ -1791,11 +1792,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x24:
/* CMOVEQ */
- gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
+ gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
break;
case 0x26:
/* CMOVNE */
- gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
+ gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
break;
case 0x28:
/* ORNOT */
@@ -1831,11 +1832,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x44:
/* CMOVLT */
- gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
+ gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
break;
case 0x46:
/* CMOVGE */
- gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
+ gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
break;
case 0x48:
/* EQV */
@@ -1875,11 +1876,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x64:
/* CMOVLE */
- gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
+ gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
break;
case 0x66:
/* CMOVGT */
- gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
+ gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
break;
case 0x6C:
/* IMPLVER */
@@ -2353,27 +2354,27 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x02A:
/* FCMOVEQ */
- gen_fcmov(TCG_COND_NE, ra, rb, rc);
+ gen_fcmov(TCG_COND_EQ, ra, rb, rc);
break;
case 0x02B:
/* FCMOVNE */
- gen_fcmov(TCG_COND_EQ, ra, rb, rc);
+ gen_fcmov(TCG_COND_NE, ra, rb, rc);
break;
case 0x02C:
/* FCMOVLT */
- gen_fcmov(TCG_COND_GE, ra, rb, rc);
+ gen_fcmov(TCG_COND_LT, ra, rb, rc);
break;
case 0x02D:
/* FCMOVGE */
- gen_fcmov(TCG_COND_LT, ra, rb, rc);
+ gen_fcmov(TCG_COND_GE, ra, rb, rc);
break;
case 0x02E:
/* FCMOVLE */
- gen_fcmov(TCG_COND_GT, ra, rb, rc);
+ gen_fcmov(TCG_COND_LE, ra, rb, rc);
break;
case 0x02F:
/* FCMOVGT */
- gen_fcmov(TCG_COND_LE, ra, rb, rc);
+ gen_fcmov(TCG_COND_GT, ra, rb, rc);
break;
case 0x030:
/* CVTQL */
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [Qemu-devel] [PATCH 07/13] target-alpha: Use non-inverted arguments to gen_{f}cmov.
2010-04-07 22:49 ` [Qemu-devel] [PATCH 07/13] target-alpha: Use non-inverted arguments to gen_{f}cmov Richard Henderson
@ 2010-04-10 1:05 ` Aurelien Jarno
0 siblings, 0 replies; 32+ messages in thread
From: Aurelien Jarno @ 2010-04-10 1:05 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Mar 16, 2010 at 02:44:44PM -0700, Richard Henderson wrote:
> The inverted conditions as argument to the function looks wrong
> at a glance inside translate_one. Since we have an easy function
> to produce the inversion now, use it.
Thanks, applied.
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-alpha/translate.c | 37 +++++++++++++++++++------------------
> 1 files changed, 19 insertions(+), 18 deletions(-)
>
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index adeff0a..ea651c4 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -394,9 +394,10 @@ static void gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, int32_t disp)
> gen_bcond_pcload(ctx, disp, lab_true);
> }
>
> -static inline void gen_cmov(TCGCond inv_cond, int ra, int rb, int rc,
> - int islit, uint8_t lit, int mask)
> +static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
> + int islit, uint8_t lit, int mask)
> {
> + TCGCond inv_cond = tcg_invert_cond(cond);
> int l1;
>
> if (unlikely(rc == 31))
> @@ -426,7 +427,7 @@ static inline void gen_cmov(TCGCond inv_cond, int ra, int rb, int rc,
> gen_set_label(l1);
> }
>
> -static void gen_fcmov(TCGCond inv_cond, int ra, int rb, int rc)
> +static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
> {
> TCGv va = cpu_fir[ra];
> int l1;
> @@ -439,7 +440,7 @@ static void gen_fcmov(TCGCond inv_cond, int ra, int rb, int rc)
> }
>
> l1 = gen_new_label();
> - gen_fbcond_internal(inv_cond, va, l1);
> + gen_fbcond_internal(tcg_invert_cond(cond), va, l1);
>
> if (rb != 31)
> tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
> @@ -1767,11 +1768,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
> break;
> case 0x14:
> /* CMOVLBS */
> - gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
> + gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
> break;
> case 0x16:
> /* CMOVLBC */
> - gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
> + gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
> break;
> case 0x20:
> /* BIS */
> @@ -1791,11 +1792,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
> break;
> case 0x24:
> /* CMOVEQ */
> - gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
> + gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
> break;
> case 0x26:
> /* CMOVNE */
> - gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
> + gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
> break;
> case 0x28:
> /* ORNOT */
> @@ -1831,11 +1832,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
> break;
> case 0x44:
> /* CMOVLT */
> - gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
> + gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
> break;
> case 0x46:
> /* CMOVGE */
> - gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
> + gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
> break;
> case 0x48:
> /* EQV */
> @@ -1875,11 +1876,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
> break;
> case 0x64:
> /* CMOVLE */
> - gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
> + gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
> break;
> case 0x66:
> /* CMOVGT */
> - gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
> + gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
> break;
> case 0x6C:
> /* IMPLVER */
> @@ -2353,27 +2354,27 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
> break;
> case 0x02A:
> /* FCMOVEQ */
> - gen_fcmov(TCG_COND_NE, ra, rb, rc);
> + gen_fcmov(TCG_COND_EQ, ra, rb, rc);
> break;
> case 0x02B:
> /* FCMOVNE */
> - gen_fcmov(TCG_COND_EQ, ra, rb, rc);
> + gen_fcmov(TCG_COND_NE, ra, rb, rc);
> break;
> case 0x02C:
> /* FCMOVLT */
> - gen_fcmov(TCG_COND_GE, ra, rb, rc);
> + gen_fcmov(TCG_COND_LT, ra, rb, rc);
> break;
> case 0x02D:
> /* FCMOVGE */
> - gen_fcmov(TCG_COND_LT, ra, rb, rc);
> + gen_fcmov(TCG_COND_GE, ra, rb, rc);
> break;
> case 0x02E:
> /* FCMOVLE */
> - gen_fcmov(TCG_COND_GT, ra, rb, rc);
> + gen_fcmov(TCG_COND_LE, ra, rb, rc);
> break;
> case 0x02F:
> /* FCMOVGT */
> - gen_fcmov(TCG_COND_LE, ra, rb, rc);
> + gen_fcmov(TCG_COND_GT, ra, rb, rc);
> break;
> case 0x030:
> /* CVTQL */
> --
> 1.6.6.1
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 03/13] target-alpha: Implement rs/rc properly.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (10 preceding siblings ...)
2010-04-07 22:49 ` [Qemu-devel] [PATCH 07/13] target-alpha: Use non-inverted arguments to gen_{f}cmov Richard Henderson
@ 2010-04-07 22:49 ` Richard Henderson
2010-04-10 0:44 ` Aurelien Jarno
2010-04-07 22:49 ` [Qemu-devel] [PATCH 08/13] target-alpha: Emit goto_tb opcodes Richard Henderson
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
13 siblings, 1 reply; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:49 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
This is a per-cpu flag; there's no need for a spinlock of any kind.
We were also failing to manipulate the flag with $31 as a target reg
and failing to clear the flag on execution of a return-from-interrupt
instruction.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/main.c | 5 +++++
target-alpha/helper.h | 2 --
target-alpha/op_helper.c | 28 ++--------------------------
target-alpha/translate.c | 19 +++++++++++++++----
4 files changed, 22 insertions(+), 32 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index ca49cc4..5252881 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2357,6 +2357,11 @@ void cpu_loop (CPUState *env)
while (1) {
trapnr = cpu_alpha_exec (env);
+ /* 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");
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 8e11304..c378195 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -2,8 +2,6 @@
DEF_HELPER_2(excp, void, int, int)
DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
-DEF_HELPER_FLAGS_0(rc, TCG_CALL_CONST, i64)
-DEF_HELPER_FLAGS_0(rs, TCG_CALL_CONST, i64)
DEF_HELPER_2(addqv, i64, i64, i64)
DEF_HELPER_2(addlv, i64, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 2419dc4..84867b8 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -47,32 +47,6 @@ void helper_store_fpcr (uint64_t val)
cpu_alpha_store_fpcr (env, val);
}
-static spinlock_t intr_cpu_lock = SPIN_LOCK_UNLOCKED;
-
-uint64_t helper_rs(void)
-{
- uint64_t tmp;
-
- spin_lock(&intr_cpu_lock);
- tmp = env->intr_flag;
- env->intr_flag = 1;
- spin_unlock(&intr_cpu_lock);
-
- return tmp;
-}
-
-uint64_t helper_rc(void)
-{
- uint64_t tmp;
-
- spin_lock(&intr_cpu_lock);
- tmp = env->intr_flag;
- env->intr_flag = 0;
- spin_unlock(&intr_cpu_lock);
-
- return tmp;
-}
-
uint64_t helper_addqv (uint64_t op1, uint64_t op2)
{
uint64_t tmp = op1;
@@ -1211,6 +1185,7 @@ void helper_hw_rei (void)
{
env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
+ env->intr_flag = 0;
/* XXX: re-enable interrupts and memory mapping */
}
@@ -1218,6 +1193,7 @@ void helper_hw_ret (uint64_t a)
{
env->pc = a & ~3;
env->ipr[IPR_EXC_ADDR] = a & 1;
+ env->intr_flag = 0;
/* XXX: re-enable interrupts and memory mapping */
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index b677378..188e76c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1266,6 +1266,19 @@ static inline void gen_cmp(TCGCond cond, int ra, int rb, int rc, int islit,
gen_set_label(l2);
}
+static void gen_rx(int ra, int set)
+{
+ TCGv_i32 tmp;
+
+ if (ra != 31) {
+ tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUState, intr_flag));
+ }
+
+ tmp = tcg_const_i32(set);
+ tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUState, intr_flag));
+ tcg_temp_free_i32(tmp);
+}
+
static inline int translate_one(DisasContext *ctx, uint32_t insn)
{
uint32_t palcode;
@@ -2359,16 +2372,14 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0xE000:
/* RC */
- if (ra != 31)
- gen_helper_rc(cpu_ir[ra]);
+ gen_rx(ra, 0);
break;
case 0xE800:
/* ECB */
break;
case 0xF000:
/* RS */
- if (ra != 31)
- gen_helper_rs(cpu_ir[ra]);
+ gen_rx(ra, 1);
break;
case 0xF800:
/* WH64 */
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [Qemu-devel] [PATCH 03/13] target-alpha: Implement rs/rc properly.
2010-04-07 22:49 ` [Qemu-devel] [PATCH 03/13] target-alpha: Implement rs/rc properly Richard Henderson
@ 2010-04-10 0:44 ` Aurelien Jarno
0 siblings, 0 replies; 32+ messages in thread
From: Aurelien Jarno @ 2010-04-10 0:44 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Mon, Mar 15, 2010 at 07:49:42AM -0700, Richard Henderson wrote:
> This is a per-cpu flag; there's no need for a spinlock of any kind.
>
> We were also failing to manipulate the flag with $31 as a target reg
> and failing to clear the flag on execution of a return-from-interrupt
> instruction.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> linux-user/main.c | 5 +++++
> target-alpha/helper.h | 2 --
> target-alpha/op_helper.c | 28 ++--------------------------
> target-alpha/translate.c | 19 +++++++++++++++----
> 4 files changed, 22 insertions(+), 32 deletions(-)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index ca49cc4..5252881 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -2357,6 +2357,11 @@ void cpu_loop (CPUState *env)
> while (1) {
> trapnr = cpu_alpha_exec (env);
>
> + /* 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;
> +
The indentation here is wrong, you should use spaces instead of tabs.
> switch (trapnr) {
> case EXCP_RESET:
> fprintf(stderr, "Reset requested. Exit\n");
> diff --git a/target-alpha/helper.h b/target-alpha/helper.h
> index 8e11304..c378195 100644
> --- a/target-alpha/helper.h
> +++ b/target-alpha/helper.h
> @@ -2,8 +2,6 @@
>
> DEF_HELPER_2(excp, void, int, int)
> DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
> -DEF_HELPER_FLAGS_0(rc, TCG_CALL_CONST, i64)
> -DEF_HELPER_FLAGS_0(rs, TCG_CALL_CONST, i64)
>
> DEF_HELPER_2(addqv, i64, i64, i64)
> DEF_HELPER_2(addlv, i64, i64, i64)
> diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
> index 2419dc4..84867b8 100644
> --- a/target-alpha/op_helper.c
> +++ b/target-alpha/op_helper.c
> @@ -47,32 +47,6 @@ void helper_store_fpcr (uint64_t val)
> cpu_alpha_store_fpcr (env, val);
> }
>
> -static spinlock_t intr_cpu_lock = SPIN_LOCK_UNLOCKED;
> -
> -uint64_t helper_rs(void)
> -{
> - uint64_t tmp;
> -
> - spin_lock(&intr_cpu_lock);
> - tmp = env->intr_flag;
> - env->intr_flag = 1;
> - spin_unlock(&intr_cpu_lock);
> -
> - return tmp;
> -}
> -
> -uint64_t helper_rc(void)
> -{
> - uint64_t tmp;
> -
> - spin_lock(&intr_cpu_lock);
> - tmp = env->intr_flag;
> - env->intr_flag = 0;
> - spin_unlock(&intr_cpu_lock);
> -
> - return tmp;
> -}
> -
> uint64_t helper_addqv (uint64_t op1, uint64_t op2)
> {
> uint64_t tmp = op1;
> @@ -1211,6 +1185,7 @@ void helper_hw_rei (void)
> {
> env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
> env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
> + env->intr_flag = 0;
> /* XXX: re-enable interrupts and memory mapping */
> }
>
> @@ -1218,6 +1193,7 @@ void helper_hw_ret (uint64_t a)
> {
> env->pc = a & ~3;
> env->ipr[IPR_EXC_ADDR] = a & 1;
> + env->intr_flag = 0;
> /* XXX: re-enable interrupts and memory mapping */
> }
>
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index b677378..188e76c 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -1266,6 +1266,19 @@ static inline void gen_cmp(TCGCond cond, int ra, int rb, int rc, int islit,
> gen_set_label(l2);
> }
>
> +static void gen_rx(int ra, int set)
> +{
> + TCGv_i32 tmp;
> +
> + if (ra != 31) {
> + tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUState, intr_flag));
> + }
> +
> + tmp = tcg_const_i32(set);
> + tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUState, intr_flag));
> + tcg_temp_free_i32(tmp);
> +}
> +
> static inline int translate_one(DisasContext *ctx, uint32_t insn)
> {
> uint32_t palcode;
> @@ -2359,16 +2372,14 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
> break;
> case 0xE000:
> /* RC */
> - if (ra != 31)
> - gen_helper_rc(cpu_ir[ra]);
> + gen_rx(ra, 0);
> break;
> case 0xE800:
> /* ECB */
> break;
> case 0xF000:
> /* RS */
> - if (ra != 31)
> - gen_helper_rs(cpu_ir[ra]);
> + gen_rx(ra, 1);
> break;
> case 0xF800:
> /* WH64 */
> --
> 1.6.6.1
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 08/13] target-alpha: Emit goto_tb opcodes.
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (11 preceding siblings ...)
2010-04-07 22:49 ` [Qemu-devel] [PATCH 03/13] target-alpha: Implement rs/rc properly Richard Henderson
@ 2010-04-07 22:49 ` Richard Henderson
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
13 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:49 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Use an ExitStatus enumeration instead of magic numbers as the return
value from translate_one. Emit goto_tb opcodes when ending a TB via
a direct branch.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 339 ++++++++++++++++++++++++++--------------------
1 files changed, 193 insertions(+), 146 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index ea651c4..dfe55c3 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -43,12 +43,13 @@
typedef struct DisasContext DisasContext;
struct DisasContext {
+ struct TranslationBlock *tb;
+ CPUAlphaState *env;
uint64_t pc;
int mem_idx;
#if !defined (CONFIG_USER_ONLY)
int pal_mode;
#endif
- CPUAlphaState *env;
uint32_t amask;
/* Current rounding mode for this TB. */
@@ -57,6 +58,25 @@ struct DisasContext {
int tb_ftz;
};
+/* Return values from translate_one, indicating the state of the TB.
+ Note that zero indicates that we are not exiting the TB. */
+
+typedef enum {
+ NO_EXIT,
+
+ /* We have emitted one or more goto_tb. No fixup required. */
+ EXIT_GOTO_TB,
+
+ /* We are not using a goto_tb (for whatever reason), but have updated
+ the PC (for whatever reason), so there's no need to do it again on
+ exiting the TB. */
+ EXIT_PC_UPDATED,
+
+ /* We are exiting the TB, but have neither emitted a goto_tb, nor
+ updated the PC for the next instruction to be executed. */
+ EXIT_PC_STALE
+} ExitStatus;
+
/* global register indexes */
static TCGv_ptr cpu_env;
static TCGv cpu_ir[31];
@@ -300,77 +320,126 @@ static inline void gen_store_mem(DisasContext *ctx,
tcg_temp_free(addr);
}
-static void gen_bcond_pcload(DisasContext *ctx, int32_t disp, int lab_true)
+static int use_goto_tb(DisasContext *ctx, uint64_t dest)
{
- int lab_over = gen_new_label();
+ /* Check for the dest on the same page as the start of the TB. We
+ also want to suppress goto_tb in the case of single-steping and IO. */
+ return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
+ && !ctx->env->singlestep_enabled
+ && !(ctx->tb->cflags & CF_LAST_IO));
+}
- tcg_gen_movi_i64(cpu_pc, ctx->pc);
- tcg_gen_br(lab_over);
- gen_set_label(lab_true);
- tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp << 2));
- gen_set_label(lab_over);
+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);
+ }
+
+ /* Notice branch-to-next; used to initialize RA with the PC. */
+ if (disp == 0) {
+ return 0;
+ } else if (use_goto_tb(ctx, dest)) {
+ tcg_gen_goto_tb(0);
+ tcg_gen_movi_i64(cpu_pc, dest);
+ tcg_gen_exit_tb((long)ctx->tb);
+ return EXIT_GOTO_TB;
+ } else {
+ tcg_gen_movi_i64(cpu_pc, dest);
+ return EXIT_PC_UPDATED;
+ }
}
-static void gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
- int32_t disp, int mask)
+static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
+ TCGv cmp, int32_t disp)
{
+ uint64_t dest = ctx->pc + (disp << 2);
int lab_true = gen_new_label();
- if (likely(ra != 31)) {
+ if (use_goto_tb(ctx, dest)) {
+ tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
+
+ tcg_gen_goto_tb(0);
+ tcg_gen_movi_i64(cpu_pc, ctx->pc);
+ tcg_gen_exit_tb((long)ctx->tb);
+
+ gen_set_label(lab_true);
+ tcg_gen_goto_tb(1);
+ tcg_gen_movi_i64(cpu_pc, dest);
+ tcg_gen_exit_tb((long)ctx->tb + 1);
+
+ return EXIT_GOTO_TB;
+ } else {
+ int lab_over = gen_new_label();
+
+ /* ??? Consider using either
+ movi pc, next
+ addi tmp, pc, disp
+ movcond pc, cond, 0, tmp, pc
+ or
+ setcond tmp, cond, 0
+ movi pc, next
+ neg tmp, tmp
+ andi tmp, tmp, disp
+ add pc, pc, tmp
+ The current diamond subgraph surely isn't efficient. */
+
+ tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
+ tcg_gen_movi_i64(cpu_pc, ctx->pc);
+ tcg_gen_br(lab_over);
+ gen_set_label(lab_true);
+ tcg_gen_movi_i64(cpu_pc, dest);
+ gen_set_label(lab_over);
+
+ return EXIT_PC_UPDATED;
+ }
+}
+
+static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
+ int32_t disp, int mask)
+{
+ TCGv cmp_tmp;
+
+ if (unlikely(ra == 31)) {
+ cmp_tmp = tcg_const_i64(0);
+ } else {
+ cmp_tmp = tcg_temp_new();
if (mask) {
- TCGv tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
- tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
- tcg_temp_free(tmp);
+ tcg_gen_andi_i64(cmp_tmp, cpu_ir[ra], 1);
} else {
- tcg_gen_brcondi_i64(cond, cpu_ir[ra], 0, lab_true);
+ tcg_gen_mov_i64(cmp_tmp, cpu_ir[ra]);
}
- } else {
- /* Very uncommon case - Do not bother to optimize. */
- TCGv tmp = tcg_const_i64(0);
- tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
- tcg_temp_free(tmp);
}
- gen_bcond_pcload(ctx, disp, lab_true);
+
+ return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
}
-/* Generate a forward TCG branch to LAB_TRUE if RA cmp 0.0.
- This is complicated by the fact that -0.0 compares the same as +0.0. */
+/* Fold -0.0 for comparison with COND. */
-static void gen_fbcond_internal(TCGCond cond, TCGv src, int lab_true)
+static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
{
- int lab_false = -1;
uint64_t mzero = 1ull << 63;
- TCGv tmp;
switch (cond) {
case TCG_COND_LE:
case TCG_COND_GT:
/* For <= or >, the -0.0 value directly compares the way we want. */
- tcg_gen_brcondi_i64(cond, src, 0, lab_true);
+ tcg_gen_mov_i64(dest, src);
break;
case TCG_COND_EQ:
case TCG_COND_NE:
/* For == or !=, we can simply mask off the sign bit and compare. */
- /* ??? Assume that the temporary is reclaimed at the branch. */
- tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, src, mzero - 1);
- tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
+ tcg_gen_andi_i64(dest, src, mzero - 1);
break;
case TCG_COND_GE:
- /* For >=, emit two branches to the destination. */
- tcg_gen_brcondi_i64(cond, src, 0, lab_true);
- tcg_gen_brcondi_i64(TCG_COND_EQ, src, mzero, lab_true);
- break;
-
case TCG_COND_LT:
- /* For <, first filter out -0.0 to what will be the fallthru. */
- lab_false = gen_new_label();
- tcg_gen_brcondi_i64(TCG_COND_EQ, src, mzero, lab_false);
- tcg_gen_brcondi_i64(cond, src, 0, lab_true);
- gen_set_label(lab_false);
+ /* For >= or <, map -0.0 to +0.0 via comparison and mask. */
+ tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
+ tcg_gen_neg_i64(dest, dest);
+ tcg_gen_and_i64(dest, dest, src);
break;
default:
@@ -378,24 +447,24 @@ static void gen_fbcond_internal(TCGCond cond, TCGv src, int lab_true)
}
}
-static void gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, int32_t disp)
+static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
+ int32_t disp)
{
- int lab_true;
+ TCGv cmp_tmp;
if (unlikely(ra == 31)) {
/* Very uncommon case, but easier to optimize it to an integer
comparison than continuing with the floating point comparison. */
- gen_bcond(ctx, cond, ra, disp, 0);
- return;
+ return gen_bcond(ctx, cond, ra, disp, 0);
}
- lab_true = gen_new_label();
- gen_fbcond_internal(cond, cpu_fir[ra], lab_true);
- gen_bcond_pcload(ctx, disp, lab_true);
+ cmp_tmp = tcg_temp_new();
+ gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
+ return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
}
static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
- int islit, uint8_t lit, int mask)
+ int islit, uint8_t lit, int mask)
{
TCGCond inv_cond = tcg_invert_cond(cond);
int l1;
@@ -429,18 +498,23 @@ static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
{
- TCGv va = cpu_fir[ra];
+ TCGv cmp_tmp;
int l1;
- if (unlikely(rc == 31))
+ if (unlikely(rc == 31)) {
return;
+ }
+
+ cmp_tmp = tcg_temp_new();
if (unlikely(ra == 31)) {
- /* ??? Assume that the temporary is reclaimed at the branch. */
- va = tcg_const_i64(0);
+ tcg_gen_movi_i64(cmp_tmp, 0);
+ } else {
+ gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
}
l1 = gen_new_label();
- gen_fbcond_internal(tcg_invert_cond(cond), va, l1);
+ tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1);
+ tcg_temp_free(cmp_tmp);
if (rb != 31)
tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
@@ -1334,14 +1408,14 @@ static void gen_rx(int ra, int set)
tcg_temp_free_i32(tmp);
}
-static inline int translate_one(DisasContext *ctx, uint32_t insn)
+static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
{
uint32_t palcode;
int32_t disp21, disp16, disp12;
uint16_t fn11, fn16;
uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit, real_islit;
uint8_t lit;
- int ret;
+ ExitStatus ret;
/* Decode all instruction fields */
opc = insn >> 26;
@@ -1364,10 +1438,10 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
fpfn = fn11 & 0x3F;
fn7 = (insn >> 5) & 0x0000007F;
fn2 = (insn >> 5) & 0x00000003;
- ret = 0;
LOG_DISAS("opc %02x ra %2d rb %2d rc %2d disp16 %6d\n",
opc, ra, rb, rc, disp16);
+ ret = NO_EXIT;
switch (opc) {
case 0x00:
/* CALL_PAL */
@@ -1385,7 +1459,8 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
if (palcode >= 0x80 && palcode < 0xC0) {
/* Unprivileged PAL call */
gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
- ret = 3;
+ /* PC updated by gen_excp. */
+ ret = EXIT_PC_UPDATED;
break;
}
#ifndef CONFIG_USER_ONLY
@@ -1394,7 +1469,8 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
if (ctx->mem_idx & 1)
goto invalid_opc;
gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
- ret = 3;
+ /* PC updated by gen_excp. */
+ ret = EXIT_PC_UPDATED;
}
#endif
/* Invalid PAL call */
@@ -2397,13 +2473,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
switch ((uint16_t)disp16) {
case 0x0000:
/* TRAPB */
- /* No-op. Just exit from the current tb */
- ret = 2;
+ /* No-op. */
break;
case 0x0400:
/* EXCB */
- /* No-op. Just exit from the current tb */
- ret = 2;
+ /* No-op. */
break;
case 0x4000:
/* MB */
@@ -2467,21 +2541,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
if (ra != 31)
tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
/* Those four jumps only differ by the branch prediction hint */
- switch (fn2) {
- case 0x0:
- /* JMP */
- break;
- case 0x1:
- /* JSR */
- break;
- case 0x2:
- /* RET */
- break;
- case 0x3:
- /* JSR_COROUTINE */
- break;
- }
- ret = 1;
+ ret = EXIT_PC_UPDATED;
break;
case 0x1B:
/* HW_LD (PALcode) */
@@ -2772,7 +2832,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
tcg_temp_free(tmp2);
}
tcg_temp_free(tmp1);
- ret = 2;
+ ret = EXIT_PC_STALE;
}
break;
#endif
@@ -2797,7 +2857,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
gen_helper_hw_ret(tmp);
tcg_temp_free(tmp);
}
- ret = 2;
+ ret = EXIT_PC_UPDATED;
break;
#endif
case 0x1F:
@@ -2958,85 +3018,66 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x30:
/* BR */
- if (ra != 31)
- tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
- tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp21 << 2));
- ret = 1;
+ ret = gen_bdirect(ctx, ra, disp21);
break;
case 0x31: /* FBEQ */
- gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
break;
case 0x32: /* FBLT */
- gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
break;
case 0x33: /* FBLE */
- gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
break;
case 0x34:
/* BSR */
- if (ra != 31)
- tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
- tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp21 << 2));
- ret = 1;
+ ret = gen_bdirect(ctx, ra, disp21);
break;
case 0x35: /* FBNE */
- gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
break;
case 0x36: /* FBGE */
- gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
break;
case 0x37: /* FBGT */
- gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
break;
case 0x38:
/* BLBC */
- gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
break;
case 0x39:
/* BEQ */
- gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
break;
case 0x3A:
/* BLT */
- gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
break;
case 0x3B:
/* BLE */
- gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
break;
case 0x3C:
/* BLBS */
- gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
break;
case 0x3D:
/* BNE */
- gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
break;
case 0x3E:
/* BGE */
- gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
break;
case 0x3F:
/* BGT */
- gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
break;
invalid_opc:
gen_invalid(ctx);
- ret = 3;
+ /* PC updated by gen_excp. */
+ ret = EXIT_PC_UPDATED;
break;
}
@@ -3053,15 +3094,17 @@ static inline void gen_intermediate_code_internal(CPUState *env,
uint16_t *gen_opc_end;
CPUBreakpoint *bp;
int j, lj = -1;
- int ret;
+ ExitStatus ret;
int num_insns;
int max_insns;
pc_start = tb->pc;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+
+ ctx.tb = tb;
+ ctx.env = env;
ctx.pc = pc_start;
ctx.amask = env->amask;
- ctx.env = env;
#if defined (CONFIG_USER_ONLY)
ctx.mem_idx = 0;
#else
@@ -3085,7 +3128,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
max_insns = CF_COUNT_MASK;
gen_icount_start();
- for (ret = 0; ret == 0;) {
+ do {
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == ctx.pc) {
@@ -3116,36 +3159,39 @@ static inline void gen_intermediate_code_internal(CPUState *env,
ctx.pc += 4;
ret = translate_one(ctxp, insn);
- if (ret != 0)
- break;
- /* if we reach a page boundary or are single stepping, stop
- * generation
- */
- if (env->singlestep_enabled) {
- gen_excp(&ctx, EXCP_DEBUG, 0);
- break;
- }
- if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
- break;
-
- if (gen_opc_ptr >= gen_opc_end)
- break;
-
- if (num_insns >= max_insns)
- break;
-
- if (singlestep) {
- break;
+ if (ret == NO_EXIT) {
+ /* If we reach a page boundary, are single stepping,
+ or exhaust instruction count, stop generation. */
+ if (env->singlestep_enabled) {
+ gen_excp(&ctx, EXCP_DEBUG, 0);
+ ret = EXIT_PC_UPDATED;
+ } else if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
+ || gen_opc_ptr >= gen_opc_end
+ || num_insns >= max_insns
+ || singlestep) {
+ ret = EXIT_PC_STALE;
+ }
}
+ } while (ret == NO_EXIT);
+
+ if (tb->cflags & CF_LAST_IO) {
+ gen_io_end();
}
- if (ret != 1 && ret != 3) {
+
+ switch (ret) {
+ case EXIT_GOTO_TB:
+ break;
+ case EXIT_PC_STALE:
tcg_gen_movi_i64(cpu_pc, ctx.pc);
+ /* FALLTHRU */
+ case EXIT_PC_UPDATED:
+ tcg_gen_exit_tb(0);
+ break;
+ default:
+ abort();
}
- if (tb->cflags & CF_LAST_IO)
- gen_io_end();
- /* Generate the return instruction */
- tcg_gen_exit_tb(0);
+
gen_icount_end(tb, num_insns);
*gen_opc_ptr = INDEX_op_end;
if (search_pc) {
@@ -3157,6 +3203,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
tb->size = ctx.pc - pc_start;
tb->icount = num_insns;
}
+
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("IN: %s\n", lookup_symbol(pc_start));
--
1.6.6.1
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5
2010-04-07 22:43 [Qemu-devel] [PATCH 00/13] target-alpha improvements, version 4 Richard Henderson
` (12 preceding siblings ...)
2010-04-07 22:49 ` [Qemu-devel] [PATCH 08/13] target-alpha: Emit goto_tb opcodes Richard Henderson
@ 2010-04-12 23:23 ` Richard Henderson
2010-03-29 17:48 ` [Qemu-devel] [PATCH 05/10] target-alpha: Update commentary for opcode 0x1A Richard Henderson
` (9 more replies)
13 siblings, 10 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-12 23:23 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Changes from v4->v5:
* Re-base vs master, and accepted patches.
* Address the comments from version 4.
r~
Richard Henderson (10):
target-alpha: Implement cpys{,n,e} inline.
target-alpha: Implement rs/rc properly.
target-alpha: Implement cvtlq inline.
target-alpha: Emit goto_tb opcodes.
target-alpha: Update commentary for opcode 0x1A.
target-alpha: Enable NPTL.
target-alpha: Indicate NORETURN status when raising exception.
target-alpha: Fix load-locked/store-conditional.
target-alpha: Implement RPCC.
Implement cpu_get_real_ticks for Alpha.
configure | 1 +
linux-user/main.c | 62 ++++-
linux-user/syscall.c | 2 +-
qemu-timer.h | 13 +
target-alpha/cpu.h | 36 ++-
target-alpha/helper.c | 7 +-
target-alpha/helper.h | 7 -
target-alpha/op_helper.c | 60 +----
target-alpha/translate.c | 684 ++++++++++++++++++++++++++++++----------------
9 files changed, 555 insertions(+), 317 deletions(-)
^ permalink raw reply [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 05/10] target-alpha: Update commentary for opcode 0x1A.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
@ 2010-03-29 17:48 ` Richard Henderson
2010-04-07 17:17 ` [Qemu-devel] [PATCH 03/10] target-alpha: Implement cvtlq inline Richard Henderson
` (8 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-03-29 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 29152fa..2c29337 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2535,13 +2535,16 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
#endif
case 0x1A:
- if (rb != 31)
+ /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
+ prediction stack action, which of course we don't implement. */
+ if (rb != 31) {
tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
- else
+ } else {
tcg_gen_movi_i64(cpu_pc, 0);
- if (ra != 31)
+ }
+ if (ra != 31) {
tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
- /* Those four jumps only differ by the branch prediction hint */
+ }
ret = EXIT_PC_UPDATED;
break;
case 0x1B:
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 03/10] target-alpha: Implement cvtlq inline.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
2010-03-29 17:48 ` [Qemu-devel] [PATCH 05/10] target-alpha: Update commentary for opcode 0x1A Richard Henderson
@ 2010-04-07 17:17 ` Richard Henderson
2010-04-07 20:32 ` [Qemu-devel] [PATCH 07/10] target-alpha: Indicate NORETURN status when raising exception Richard Henderson
` (7 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 17:17 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
It's a simple shift and mask sequence.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 1 -
target-alpha/op_helper.c | 7 -------
target-alpha/translate.c | 23 ++++++++++++++++++++++-
3 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 10c78d0..ccf6a2a 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -83,7 +83,6 @@ DEF_HELPER_FLAGS_1(cvtqf, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtgf, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtgq, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtqg, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtlq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index f9cd07a..a209130 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1152,13 +1152,6 @@ uint64_t helper_cvtqg (uint64_t a)
return float64_to_g(fr);
}
-uint64_t helper_cvtlq (uint64_t a)
-{
- int32_t lo = a >> 29;
- int32_t hi = a >> 32;
- return (lo & 0x3FFFFFFF) | (hi & 0xc0000000);
-}
-
/* PALcode support special instructions */
#if !defined (CONFIG_USER_ONLY)
void helper_hw_rei (void)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 939496c..00f070d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -598,6 +598,28 @@ static inline void gen_fp_exc_raise(int rc, int fn11)
gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
}
+static void gen_fcvtlq(int rb, int rc)
+{
+ if (unlikely(rc == 31)) {
+ return;
+ }
+ if (unlikely(rb == 31)) {
+ tcg_gen_movi_i64(cpu_fir[rc], 0);
+ } else {
+ TCGv tmp = tcg_temp_new();
+
+ /* The arithmetic right shift here, plus the sign-extended mask below
+ yields a sign-extended result without an explicit ext32s_i64. */
+ tcg_gen_sari_i64(tmp, cpu_fir[rb], 32);
+ tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29);
+ tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
+ tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rc], 0x3fffffff);
+ tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
+
+ tcg_temp_free(tmp);
+ }
+}
+
static void gen_fcvtql(int rb, int rc)
{
if (unlikely(rc == 31)) {
@@ -647,7 +669,6 @@ static inline void glue(gen_f, name)(int rb, int rc) \
tcg_temp_free(tmp); \
} \
}
-FARITH2(cvtlq)
/* ??? VAX instruction qualifiers ignored. */
FARITH2(sqrtf)
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 07/10] target-alpha: Indicate NORETURN status when raising exception.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
2010-03-29 17:48 ` [Qemu-devel] [PATCH 05/10] target-alpha: Update commentary for opcode 0x1A Richard Henderson
2010-04-07 17:17 ` [Qemu-devel] [PATCH 03/10] target-alpha: Implement cvtlq inline Richard Henderson
@ 2010-04-07 20:32 ` Richard Henderson
2010-04-07 22:42 ` [Qemu-devel] [PATCH 08/10] target-alpha: Fix load-locked/store-conditional Richard Henderson
` (6 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 20:32 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
When (indirectly) calling raise_exception, don't emit cleanup
code at the end of the TB, as it is unused.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 27 ++++++++++++++-------------
1 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 2c29337..9ada94e 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -74,7 +74,11 @@ typedef enum {
/* We are exiting the TB, but have neither emitted a goto_tb, nor
updated the PC for the next instruction to be executed. */
- EXIT_PC_STALE
+ EXIT_PC_STALE,
+
+ /* We are ending the TB with a noreturn function call, e.g. longjmp.
+ No following code will be executed. */
+ EXIT_NORETURN,
} ExitStatus;
/* global register indexes */
@@ -134,7 +138,7 @@ static void alpha_translate_init(void)
done_init = 1;
}
-static inline void gen_excp(DisasContext *ctx, int exception, int error_code)
+static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
{
TCGv_i32 tmp1, tmp2;
@@ -144,11 +148,13 @@ static inline void gen_excp(DisasContext *ctx, int exception, int error_code)
gen_helper_excp(tmp1, tmp2);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp1);
+
+ return EXIT_NORETURN;
}
-static inline void gen_invalid(DisasContext *ctx)
+static inline ExitStatus gen_invalid(DisasContext *ctx)
{
- gen_excp(ctx, EXCP_OPCDEC, 0);
+ return gen_excp(ctx, EXCP_OPCDEC, 0);
}
static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
@@ -1459,9 +1465,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
#endif
if (palcode >= 0x80 && palcode < 0xC0) {
/* Unprivileged PAL call */
- gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
- /* PC updated by gen_excp. */
- ret = EXIT_PC_UPDATED;
+ ret = gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
break;
}
#ifndef CONFIG_USER_ONLY
@@ -1469,9 +1473,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* Privileged PAL code */
if (ctx->mem_idx & 1)
goto invalid_opc;
- gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
- /* PC updated by gen_excp. */
- ret = EXIT_PC_UPDATED;
+ ret = gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
}
#endif
/* Invalid PAL call */
@@ -3079,9 +3081,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
break;
invalid_opc:
- gen_invalid(ctx);
- /* PC updated by gen_excp. */
- ret = EXIT_PC_UPDATED;
+ ret = gen_invalid(ctx);
break;
}
@@ -3185,6 +3185,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
switch (ret) {
case EXIT_GOTO_TB:
+ case EXIT_NORETURN:
break;
case EXIT_PC_STALE:
tcg_gen_movi_i64(cpu_pc, ctx.pc);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 08/10] target-alpha: Fix load-locked/store-conditional.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
` (2 preceding siblings ...)
2010-04-07 20:32 ` [Qemu-devel] [PATCH 07/10] target-alpha: Indicate NORETURN status when raising exception Richard Henderson
@ 2010-04-07 22:42 ` Richard Henderson
2010-04-12 23:12 ` [Qemu-devel] [PATCH 01/10] target-alpha: Implement cpys{, n, e} inline Richard Henderson
` (5 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-07 22:42 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Use an exception plus start_exclusive to implement the compare-and-swap.
This follows the example set by the MIPS and PPC ports.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/main.c | 55 +++++++++++++
target-alpha/cpu.h | 6 +-
target-alpha/helper.c | 7 +-
target-alpha/op_helper.c | 2 +
target-alpha/translate.c | 202 ++++++++++++++++++++++++++++-----------------
5 files changed, 193 insertions(+), 79 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index c0cc261..1fdcdc1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2348,6 +2348,51 @@ void cpu_loop(CPUM68KState *env)
#endif /* TARGET_M68K */
#ifdef TARGET_ALPHA
+static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
+{
+ target_ulong addr, val, tmp;
+ target_siginfo_t info;
+ int ret = 0;
+
+ addr = env->lock_addr;
+ tmp = env->lock_st_addr;
+ env->lock_addr = -1;
+ env->lock_st_addr = 0;
+
+ start_exclusive();
+ mmap_lock();
+
+ if (addr == tmp) {
+ if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
+ goto do_sigsegv;
+ }
+
+ if (val == env->lock_value) {
+ tmp = env->ir[reg];
+ if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) {
+ goto do_sigsegv;
+ }
+ ret = 1;
+ }
+ }
+ env->ir[reg] = ret;
+ env->pc += 4;
+
+ mmap_unlock();
+ end_exclusive();
+ return;
+
+ do_sigsegv:
+ mmap_unlock();
+ end_exclusive();
+
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = addr;
+ queue_signal(env, TARGET_SIGSEGV, &info);
+}
+
void cpu_loop (CPUState *env)
{
int trapnr;
@@ -2372,6 +2417,7 @@ void cpu_loop (CPUState *env)
exit(1);
break;
case EXCP_ARITH:
+ env->lock_addr = -1;
info.si_signo = TARGET_SIGFPE;
info.si_errno = 0;
info.si_code = TARGET_FPE_FLTINV;
@@ -2383,6 +2429,7 @@ void cpu_loop (CPUState *env)
exit(1);
break;
case EXCP_DFAULT:
+ env->lock_addr = -1;
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = 0; /* ??? SEGV_MAPERR vs SEGV_ACCERR. */
@@ -2406,6 +2453,7 @@ void cpu_loop (CPUState *env)
exit(1);
break;
case EXCP_UNALIGN:
+ env->lock_addr = -1;
info.si_signo = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
@@ -2414,6 +2462,7 @@ void cpu_loop (CPUState *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;
@@ -2424,6 +2473,7 @@ void cpu_loop (CPUState *env)
/* No-op. Linux simply re-enables the FPU. */
break;
case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
+ env->lock_addr = -1;
switch ((trapnr >> 6) | 0x80) {
case 0x80:
/* BPT */
@@ -2513,11 +2563,16 @@ void cpu_loop (CPUState *env)
case EXCP_DEBUG:
info.si_signo = gdb_handlesig (env, 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, &info);
}
break;
+ case EXCP_STL_C:
+ case EXCP_STQ_C:
+ do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C);
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c397930..817504b 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -355,11 +355,13 @@ struct CPUAlphaState {
uint64_t ir[31];
float64 fir[31];
uint64_t pc;
- uint64_t lock;
uint32_t pcc[2];
uint64_t ipr[IPR_LAST];
uint64_t ps;
uint64_t unique;
+ uint64_t lock_addr;
+ uint64_t lock_st_addr;
+ uint64_t lock_value;
float_status fp_status;
/* The following fields make up the FPCR, but in FP_STATUS format. */
uint8_t fpcr_exc_status;
@@ -440,6 +442,8 @@ enum {
/* Pseudo exception for console */
EXCP_CONSOLE_DISPATCH = 0x4001,
EXCP_CONSOLE_FIXUP = 0x4002,
+ EXCP_STL_C = 0x4003,
+ EXCP_STQ_C = 0x4004,
};
/* Arithmetic exception */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 46335cd..1ed7ea3 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -556,12 +556,15 @@ void cpu_dump_state (CPUState *env, FILE *f,
if ((i % 3) == 2)
cpu_fprintf(f, "\n");
}
- cpu_fprintf(f, "\n");
+
+ cpu_fprintf(f, "lock_a " TARGET_FMT_lx " lock_v " TARGET_FMT_lx "\n",
+ env->lock_addr, env->lock_value);
+
for (i = 0; i < 31; i++) {
cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i,
*((uint64_t *)(&env->fir[i])));
if ((i % 3) == 2)
cpu_fprintf(f, "\n");
}
- cpu_fprintf(f, "\nlock " TARGET_FMT_lx "\n", env->lock);
+ cpu_fprintf(f, "\n");
}
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index a209130..bfc095c 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1159,6 +1159,7 @@ void helper_hw_rei (void)
env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
env->intr_flag = 0;
+ env->lock_addr = -1;
/* XXX: re-enable interrupts and memory mapping */
}
@@ -1167,6 +1168,7 @@ void helper_hw_ret (uint64_t a)
env->pc = a & ~3;
env->ipr[IPR_EXC_ADDR] = a & 1;
env->intr_flag = 0;
+ env->lock_addr = -1;
/* XXX: re-enable interrupts and memory mapping */
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 9ada94e..cbfd2c0 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -86,7 +86,9 @@ static TCGv_ptr cpu_env;
static TCGv cpu_ir[31];
static TCGv cpu_fir[31];
static TCGv cpu_pc;
-static TCGv cpu_lock;
+static TCGv cpu_lock_addr;
+static TCGv cpu_lock_st_addr;
+static TCGv cpu_lock_value;
#ifdef CONFIG_USER_ONLY
static TCGv cpu_uniq;
#endif
@@ -123,8 +125,15 @@ static void alpha_translate_init(void)
cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
offsetof(CPUState, pc), "pc");
- cpu_lock = tcg_global_mem_new_i64(TCG_AREG0,
- offsetof(CPUState, lock), "lock");
+ cpu_lock_addr = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, lock_addr),
+ "lock_addr");
+ cpu_lock_st_addr = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, lock_st_addr),
+ "lock_st_addr");
+ cpu_lock_value = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, lock_value),
+ "lock_value");
#ifdef CONFIG_USER_ONLY
cpu_uniq = tcg_global_mem_new_i64(TCG_AREG0,
@@ -189,14 +198,16 @@ static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
{
- tcg_gen_mov_i64(cpu_lock, t1);
tcg_gen_qemu_ld32s(t0, t1, flags);
+ tcg_gen_mov_i64(cpu_lock_addr, t1);
+ tcg_gen_mov_i64(cpu_lock_value, t0);
}
static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
{
- tcg_gen_mov_i64(cpu_lock, t1);
tcg_gen_qemu_ld64(t0, t1, flags);
+ tcg_gen_mov_i64(cpu_lock_addr, t1);
+ tcg_gen_mov_i64(cpu_lock_value, t0);
}
static inline void gen_load_mem(DisasContext *ctx,
@@ -205,25 +216,31 @@ static inline void gen_load_mem(DisasContext *ctx,
int ra, int rb, int32_t disp16, int fp,
int clear)
{
- TCGv addr;
+ TCGv addr, va;
- if (unlikely(ra == 31))
+ /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
+ prefetches, which we can treat as nops. No worries about
+ missed exceptions here. */
+ if (unlikely(ra == 31)) {
return;
+ }
addr = tcg_temp_new();
if (rb != 31) {
tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
- if (clear)
+ if (clear) {
tcg_gen_andi_i64(addr, addr, ~0x7);
+ }
} else {
- if (clear)
+ if (clear) {
disp16 &= ~0x7;
+ }
tcg_gen_movi_i64(addr, disp16);
}
- if (fp)
- tcg_gen_qemu_load(cpu_fir[ra], addr, ctx->mem_idx);
- else
- tcg_gen_qemu_load(cpu_ir[ra], addr, ctx->mem_idx);
+
+ va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
+ tcg_gen_qemu_load(va, addr, ctx->mem_idx);
+
tcg_temp_free(addr);
}
@@ -257,73 +274,105 @@ static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
tcg_temp_free_i32(tmp32);
}
-static inline void gen_qemu_stl_c(TCGv t0, TCGv t1, int flags)
-{
- int l1, l2;
-
- l1 = gen_new_label();
- l2 = gen_new_label();
- tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
- tcg_gen_qemu_st32(t0, t1, flags);
- tcg_gen_movi_i64(t0, 1);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_movi_i64(t0, 0);
- gen_set_label(l2);
- tcg_gen_movi_i64(cpu_lock, -1);
-}
-
-static inline void gen_qemu_stq_c(TCGv t0, TCGv t1, int flags)
-{
- int l1, l2;
-
- l1 = gen_new_label();
- l2 = gen_new_label();
- tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
- tcg_gen_qemu_st64(t0, t1, flags);
- tcg_gen_movi_i64(t0, 1);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_movi_i64(t0, 0);
- gen_set_label(l2);
- tcg_gen_movi_i64(cpu_lock, -1);
-}
-
static inline void gen_store_mem(DisasContext *ctx,
void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
int flags),
int ra, int rb, int32_t disp16, int fp,
- int clear, int local)
+ int clear)
{
- TCGv addr;
- if (local)
- addr = tcg_temp_local_new();
- else
- addr = tcg_temp_new();
+ TCGv addr, va;
+
+ addr = tcg_temp_new();
if (rb != 31) {
tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
- if (clear)
+ if (clear) {
tcg_gen_andi_i64(addr, addr, ~0x7);
+ }
} else {
- if (clear)
+ if (clear) {
disp16 &= ~0x7;
+ }
tcg_gen_movi_i64(addr, disp16);
}
- if (ra != 31) {
- if (fp)
- tcg_gen_qemu_store(cpu_fir[ra], addr, ctx->mem_idx);
- else
- tcg_gen_qemu_store(cpu_ir[ra], addr, ctx->mem_idx);
+
+ if (ra == 31) {
+ va = tcg_const_i64(0);
} else {
- TCGv zero;
- if (local)
- zero = tcg_const_local_i64(0);
- else
- zero = tcg_const_i64(0);
- tcg_gen_qemu_store(zero, addr, ctx->mem_idx);
- tcg_temp_free(zero);
+ va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
}
+ tcg_gen_qemu_store(va, addr, ctx->mem_idx);
+
tcg_temp_free(addr);
+ if (ra == 31) {
+ tcg_temp_free(va);
+ }
+}
+
+static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
+ int32_t disp16, int quad)
+{
+ TCGv addr;
+
+ if (ra == 31) {
+ /* ??? Don't bother storing anything. The user can't tell
+ the difference, since the zero register always reads zero. */
+ return NO_EXIT;
+ }
+
+#if defined(CONFIG_USER_ONLY)
+ addr = cpu_lock_st_addr;
+#else
+ addr = tcg_local_new();
+#endif
+
+ if (rb != 31) {
+ tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
+ } else {
+ tcg_gen_movi_i64(addr, disp16);
+ }
+
+#if defined(CONFIG_USER_ONLY)
+ /* ??? This is handled via a complicated version of compare-and-swap
+ in the cpu_loop. Hopefully one day we'll have a real CAS opcode
+ in TCG so that this isn't necessary. */
+ return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
+#else
+ /* ??? In system mode we are never multi-threaded, so CAS can be
+ implemented via a non-atomic load-compare-store sequence. */
+ {
+ int lab_fail, lab_done;
+ TCGv val;
+
+ lab_fail = gen_new_label();
+ lab_done = gen_new_label();
+ tcg_gen_brcond(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
+
+ val = tcg_temp_new();
+ if (quad) {
+ tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
+ } else {
+ tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
+ }
+ tcg_gen_brcond(TCG_COND_NE, val, cpu_lock_value, lab_fail);
+
+ if (quad) {
+ tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
+ } else {
+ tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
+ }
+ tcg_gen_movi_i64(cpu_ir[ra], 1);
+ tcg_gen_br(lab_done);
+
+ gen_set_label(lab_fail);
+ tcg_gen_movi_i64(cpu_ir[ra], 0);
+
+ gen_set_label(lab_done);
+ tcg_gen_movi_i64(cpu_lock_addr, -1);
+
+ tcg_temp_free(addr);
+ return NO_EXIT;
+ }
+#endif
}
static int use_goto_tb(DisasContext *ctx, uint64_t dest)
@@ -1535,15 +1584,15 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x0D:
/* STW */
- gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
break;
case 0x0E:
/* STB */
- gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
break;
case 0x0F:
/* STQ_U */
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
break;
case 0x10:
switch (fn7) {
@@ -2976,19 +3025,19 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x24:
/* STF */
- gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0, 0);
+ gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
break;
case 0x25:
/* STG */
- gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0, 0);
+ gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
break;
case 0x26:
/* STS */
- gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0, 0);
+ gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
break;
case 0x27:
/* STT */
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
break;
case 0x28:
/* LDL */
@@ -3008,19 +3057,19 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2C:
/* STL */
- gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
break;
case 0x2D:
/* STQ */
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0, 0);
+ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
break;
case 0x2E:
/* STL_C */
- gen_store_mem(ctx, &gen_qemu_stl_c, ra, rb, disp16, 0, 0, 1);
+ ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
break;
case 0x2F:
/* STQ_C */
- gen_store_mem(ctx, &gen_qemu_stq_c, ra, rb, disp16, 0, 0, 1);
+ ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
break;
case 0x30:
/* BR */
@@ -3286,6 +3335,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
#else
pal_init(env);
#endif
+ env->lock_addr = -1;
/* Initialize IPR */
#if defined (CONFIG_USER_ONLY)
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 01/10] target-alpha: Implement cpys{, n, e} inline.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
` (3 preceding siblings ...)
2010-04-07 22:42 ` [Qemu-devel] [PATCH 08/10] target-alpha: Fix load-locked/store-conditional Richard Henderson
@ 2010-04-12 23:12 ` Richard Henderson
2010-04-12 23:14 ` [Qemu-devel] [PATCH 02/10] target-alpha: Implement rs/rc properly Richard Henderson
` (4 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-12 23:12 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 4 --
target-alpha/op_helper.c | 18 ----------
target-alpha/translate.c | 79 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 75 insertions(+), 26 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 6072a26..73413f2 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -77,10 +77,6 @@ DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cpys, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cpysn, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cpyse, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-
DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index dd1af84..ded71f6 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -921,24 +921,6 @@ uint64_t helper_sqrtt (uint64_t a)
return float64_to_t(fr);
}
-
-/* Sign copy */
-uint64_t helper_cpys(uint64_t a, uint64_t b)
-{
- return (a & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
-}
-
-uint64_t helper_cpysn(uint64_t a, uint64_t b)
-{
- return ((~a) & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
-}
-
-uint64_t helper_cpyse(uint64_t a, uint64_t b)
-{
- return (a & 0xFFF0000000000000ULL) | (b & ~0xFFF0000000000000ULL);
-}
-
-
/* Comparisons */
uint64_t helper_cmptun (uint64_t a, uint64_t b)
{
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index d903800..817194e 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -774,6 +774,81 @@ static inline void glue(gen_f, name)(DisasContext *ctx, \
IEEE_INTCVT(cvtqs)
IEEE_INTCVT(cvtqt)
+static void gen_cpys_internal(int ra, int rb, int rc, int inv_a, uint64_t mask)
+{
+ TCGv va, vb, vmask;
+ int za = 0, zb = 0;
+
+ if (unlikely(rc == 31)) {
+ return;
+ }
+
+ vmask = tcg_const_i64(mask);
+
+ TCGV_UNUSED_I64(va);
+ if (ra == 31) {
+ if (inv_a) {
+ va = vmask;
+ } else {
+ za = 1;
+ }
+ } else {
+ va = tcg_temp_new_i64();
+ tcg_gen_mov_i64(va, cpu_fir[ra]);
+ if (inv_a) {
+ tcg_gen_andc_i64(va, vmask, va);
+ } else {
+ tcg_gen_and_i64(va, va, vmask);
+ }
+ }
+
+ TCGV_UNUSED_I64(vb);
+ if (rb == 31) {
+ zb = 1;
+ } else {
+ vb = tcg_temp_new_i64();
+ tcg_gen_andc_i64(vb, cpu_fir[rb], vmask);
+ }
+
+ switch (za << 1 | zb) {
+ case 0 | 0:
+ tcg_gen_or_i64(cpu_fir[rc], va, vb);
+ break;
+ case 0 | 1:
+ tcg_gen_mov_i64(cpu_fir[rc], va);
+ break;
+ case 2 | 0:
+ tcg_gen_mov_i64(cpu_fir[rc], vb);
+ break;
+ case 2 | 1:
+ tcg_gen_movi_i64(cpu_fir[rc], 0);
+ break;
+ }
+
+ tcg_temp_free(vmask);
+ if (ra != 31) {
+ tcg_temp_free(va);
+ }
+ if (rb != 31) {
+ tcg_temp_free(vb);
+ }
+}
+
+static inline void gen_fcpys(int ra, int rb, int rc)
+{
+ gen_cpys_internal(ra, rb, rc, 0, 0x8000000000000000ULL);
+}
+
+static inline void gen_fcpysn(int ra, int rb, int rc)
+{
+ gen_cpys_internal(ra, rb, rc, 1, 0x8000000000000000ULL);
+}
+
+static inline void gen_fcpyse(int ra, int rb, int rc)
+{
+ gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
+}
+
#define FARITH3(name) \
static inline void glue(gen_f, name)(int ra, int rb, int rc) \
{ \
@@ -802,10 +877,6 @@ static inline void glue(gen_f, name)(int ra, int rb, int rc) \
tcg_temp_free(vb); \
} \
}
-/* ??? Ought to expand these inline; simple masking operations. */
-FARITH3(cpys)
-FARITH3(cpysn)
-FARITH3(cpyse)
/* ??? VAX instruction qualifiers ignored. */
FARITH3(addf)
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 02/10] target-alpha: Implement rs/rc properly.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
` (4 preceding siblings ...)
2010-04-12 23:12 ` [Qemu-devel] [PATCH 01/10] target-alpha: Implement cpys{, n, e} inline Richard Henderson
@ 2010-04-12 23:14 ` Richard Henderson
2010-04-12 23:17 ` [Qemu-devel] [PATCH 06/10] target-alpha: Enable NPTL Richard Henderson
` (3 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-12 23:14 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
This is a per-cpu flag; there's no need for a spinlock of any kind.
We were also failing to manipulate the flag with $31 as a target reg
and failing to clear the flag on execution of a return-from-interrupt
instruction.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/main.c | 7 ++++++-
target-alpha/helper.h | 2 --
target-alpha/op_helper.c | 28 ++--------------------------
target-alpha/translate.c | 19 +++++++++++++++----
4 files changed, 23 insertions(+), 33 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index b394c00..c0cc261 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2357,6 +2357,11 @@ void cpu_loop (CPUState *env)
while (1) {
trapnr = cpu_alpha_exec (env);
+ /* 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");
@@ -2443,7 +2448,7 @@ void cpu_loop (CPUState *env)
env->ir[IR_A0], env->ir[IR_A1],
env->ir[IR_A2], env->ir[IR_A3],
env->ir[IR_A4], env->ir[IR_A5]);
- if (trapnr != TARGET_NR_sigreturn
+ if (trapnr != TARGET_NR_sigreturn
&& trapnr != TARGET_NR_rt_sigreturn) {
env->ir[IR_V0] = (sysret < 0 ? -sysret : sysret);
env->ir[IR_A3] = (sysret < 0);
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 73413f2..10c78d0 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -2,8 +2,6 @@
DEF_HELPER_2(excp, void, int, int)
DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
-DEF_HELPER_FLAGS_0(rc, TCG_CALL_CONST, i64)
-DEF_HELPER_FLAGS_0(rs, TCG_CALL_CONST, i64)
DEF_HELPER_2(addqv, i64, i64, i64)
DEF_HELPER_2(addlv, i64, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index ded71f6..f9cd07a 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -47,32 +47,6 @@ void helper_store_fpcr (uint64_t val)
cpu_alpha_store_fpcr (env, val);
}
-static spinlock_t intr_cpu_lock = SPIN_LOCK_UNLOCKED;
-
-uint64_t helper_rs(void)
-{
- uint64_t tmp;
-
- spin_lock(&intr_cpu_lock);
- tmp = env->intr_flag;
- env->intr_flag = 1;
- spin_unlock(&intr_cpu_lock);
-
- return tmp;
-}
-
-uint64_t helper_rc(void)
-{
- uint64_t tmp;
-
- spin_lock(&intr_cpu_lock);
- tmp = env->intr_flag;
- env->intr_flag = 0;
- spin_unlock(&intr_cpu_lock);
-
- return tmp;
-}
-
uint64_t helper_addqv (uint64_t op1, uint64_t op2)
{
uint64_t tmp = op1;
@@ -1191,6 +1165,7 @@ void helper_hw_rei (void)
{
env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
+ env->intr_flag = 0;
/* XXX: re-enable interrupts and memory mapping */
}
@@ -1198,6 +1173,7 @@ void helper_hw_ret (uint64_t a)
{
env->pc = a & ~3;
env->ipr[IPR_EXC_ADDR] = a & 1;
+ env->intr_flag = 0;
/* XXX: re-enable interrupts and memory mapping */
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 817194e..939496c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1301,6 +1301,19 @@ static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
}
}
+static void gen_rx(int ra, int set)
+{
+ TCGv_i32 tmp;
+
+ if (ra != 31) {
+ tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUState, intr_flag));
+ }
+
+ tmp = tcg_const_i32(set);
+ tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUState, intr_flag));
+ tcg_temp_free_i32(tmp);
+}
+
static inline int translate_one(DisasContext *ctx, uint32_t insn)
{
uint32_t palcode;
@@ -2395,16 +2408,14 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0xE000:
/* RC */
- if (ra != 31)
- gen_helper_rc(cpu_ir[ra]);
+ gen_rx(ra, 0);
break;
case 0xE800:
/* ECB */
break;
case 0xF000:
/* RS */
- if (ra != 31)
- gen_helper_rs(cpu_ir[ra]);
+ gen_rx(ra, 1);
break;
case 0xF800:
/* WH64 */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 06/10] target-alpha: Enable NPTL.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
` (5 preceding siblings ...)
2010-04-12 23:14 ` [Qemu-devel] [PATCH 02/10] target-alpha: Implement rs/rc properly Richard Henderson
@ 2010-04-12 23:17 ` Richard Henderson
2010-04-12 23:18 ` [Qemu-devel] [PATCH 09/10] target-alpha: Implement RPCC Richard Henderson
` (2 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-12 23:17 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
configure | 1 +
linux-user/syscall.c | 2 +-
target-alpha/cpu.h | 29 ++++++++++++++++++-----------
3 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/configure b/configure
index 966cd7d..7c60731 100755
--- a/configure
+++ b/configure
@@ -2433,6 +2433,7 @@ case "$target_arch2" in
;;
alpha)
target_phys_bits=64
+ target_nptl="yes"
;;
arm|armeb)
TARGET_ARCH=arm
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a03e432..050a418 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5768,7 +5768,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(fsync(arg1));
break;
case TARGET_NR_clone:
-#if defined(TARGET_SH4)
+#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
#elif defined(TARGET_CRIS)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 8afe16d..c397930 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -411,15 +411,6 @@ static inline int cpu_mmu_index (CPUState *env)
return (env->ps >> 3) & 3;
}
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
-{
- if (newsp)
- env->ir[30] = newsp;
- /* FIXME: Zero syscall return value. */
-}
-#endif
-
#include "cpu-all.h"
#include "exec-all.h"
@@ -477,7 +468,7 @@ enum {
IR_S4 = 13,
IR_S5 = 14,
IR_S6 = 15,
-#define IR_FP IR_S6
+ IR_FP = IR_S6,
IR_A0 = 16,
IR_A1 = 17,
IR_A2 = 18,
@@ -490,7 +481,7 @@ enum {
IR_T11 = 25,
IR_RA = 26,
IR_T12 = 27,
-#define IR_PV IR_T12
+ IR_PV = IR_T12,
IR_AT = 28,
IR_GP = 29,
IR_SP = 30,
@@ -531,4 +522,20 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
*flags = env->ps;
}
+#if defined(CONFIG_USER_ONLY)
+static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->ir[IR_SP] = newsp;
+ }
+ env->ir[IR_V0] = 0;
+ env->ir[IR_A3] = 0;
+}
+
+static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+{
+ env->unique = newtls;
+}
+#endif
+
#endif /* !defined (__CPU_ALPHA_H__) */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 09/10] target-alpha: Implement RPCC.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
` (6 preceding siblings ...)
2010-04-12 23:17 ` [Qemu-devel] [PATCH 06/10] target-alpha: Enable NPTL Richard Henderson
@ 2010-04-12 23:18 ` Richard Henderson
2010-04-12 23:19 ` [Qemu-devel] [PATCH 10/10] Implement cpu_get_real_ticks for Alpha Richard Henderson
2010-04-12 23:26 ` [Qemu-devel] [PATCH 04/10] target-alpha: Emit goto_tb opcodes Richard Henderson
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-12 23:18 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
A minimal implementation that more or less corresponds to the
user-level version used by target-i386. More hoops will want
to be jumped through when alpha gets system-level emulation.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 1 -
target-alpha/op_helper.c | 5 +++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 817504b..314d6ac 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -355,7 +355,6 @@ struct CPUAlphaState {
uint64_t ir[31];
float64 fir[31];
uint64_t pc;
- uint32_t pcc[2];
uint64_t ipr[IPR_LAST];
uint64_t ps;
uint64_t unique;
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index bfc095c..ff5ae26 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -21,6 +21,7 @@
#include "host-utils.h"
#include "softfloat.h"
#include "helper.h"
+#include "qemu-timer.h"
/*****************************************************************************/
/* Exceptions processing helpers */
@@ -33,8 +34,8 @@ void QEMU_NORETURN helper_excp (int excp, int error)
uint64_t helper_load_pcc (void)
{
- /* XXX: TODO */
- return 0;
+ /* ??? This isn't a timer for which we have any rate info. */
+ return (uint32_t)cpu_get_real_ticks();
}
uint64_t helper_load_fpcr (void)
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 10/10] Implement cpu_get_real_ticks for Alpha.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
` (7 preceding siblings ...)
2010-04-12 23:18 ` [Qemu-devel] [PATCH 09/10] target-alpha: Implement RPCC Richard Henderson
@ 2010-04-12 23:19 ` Richard Henderson
2010-04-12 23:26 ` [Qemu-devel] [PATCH 04/10] target-alpha: Emit goto_tb opcodes Richard Henderson
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-12 23:19 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
qemu-timer.h | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/qemu-timer.h b/qemu-timer.h
index d2e15f4..6e2d2e1 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -209,6 +209,19 @@ static inline int64_t cpu_get_real_ticks(void)
return (int64_t)(count * cyc_per_count);
}
+#elif defined(__alpha__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+ uint64_t cc;
+ uint32_t cur, ofs;
+
+ asm volatile("rpcc %0" : "=r"(cc));
+ cur = cc;
+ ofs = cc >> 32;
+ return cur - ofs;
+}
+
#else
/* The host CPU doesn't have an easily accessible cycle counter.
Just return a monotonically increasing value. This will be
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [Qemu-devel] [PATCH 04/10] target-alpha: Emit goto_tb opcodes.
2010-04-12 23:23 ` [Qemu-devel] [PATCH 00/10] target-alpha improvments, version 5 Richard Henderson
` (8 preceding siblings ...)
2010-04-12 23:19 ` [Qemu-devel] [PATCH 10/10] Implement cpu_get_real_ticks for Alpha Richard Henderson
@ 2010-04-12 23:26 ` Richard Henderson
9 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2010-04-12 23:26 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Use an ExitStatus enumeration instead of magic numbers as the return
value from translate_one. Emit goto_tb opcodes when ending a TB via
a direct branch.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 339 ++++++++++++++++++++++++++--------------------
1 files changed, 193 insertions(+), 146 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 00f070d..29152fa 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -43,12 +43,13 @@
typedef struct DisasContext DisasContext;
struct DisasContext {
+ struct TranslationBlock *tb;
+ CPUAlphaState *env;
uint64_t pc;
int mem_idx;
#if !defined (CONFIG_USER_ONLY)
int pal_mode;
#endif
- CPUAlphaState *env;
uint32_t amask;
/* Current rounding mode for this TB. */
@@ -57,6 +58,25 @@ struct DisasContext {
int tb_ftz;
};
+/* Return values from translate_one, indicating the state of the TB.
+ Note that zero indicates that we are not exiting the TB. */
+
+typedef enum {
+ NO_EXIT,
+
+ /* We have emitted one or more goto_tb. No fixup required. */
+ EXIT_GOTO_TB,
+
+ /* We are not using a goto_tb (for whatever reason), but have updated
+ the PC (for whatever reason), so there's no need to do it again on
+ exiting the TB. */
+ EXIT_PC_UPDATED,
+
+ /* We are exiting the TB, but have neither emitted a goto_tb, nor
+ updated the PC for the next instruction to be executed. */
+ EXIT_PC_STALE
+} ExitStatus;
+
/* global register indexes */
static TCGv_ptr cpu_env;
static TCGv cpu_ir[31];
@@ -300,77 +320,126 @@ static inline void gen_store_mem(DisasContext *ctx,
tcg_temp_free(addr);
}
-static void gen_bcond_pcload(DisasContext *ctx, int32_t disp, int lab_true)
+static int use_goto_tb(DisasContext *ctx, uint64_t dest)
{
- int lab_over = gen_new_label();
+ /* Check for the dest on the same page as the start of the TB. We
+ also want to suppress goto_tb in the case of single-steping and IO. */
+ return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
+ && !ctx->env->singlestep_enabled
+ && !(ctx->tb->cflags & CF_LAST_IO));
+}
- tcg_gen_movi_i64(cpu_pc, ctx->pc);
- tcg_gen_br(lab_over);
- gen_set_label(lab_true);
- tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp << 2));
- gen_set_label(lab_over);
+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);
+ }
+
+ /* Notice branch-to-next; used to initialize RA with the PC. */
+ if (disp == 0) {
+ return 0;
+ } else if (use_goto_tb(ctx, dest)) {
+ tcg_gen_goto_tb(0);
+ tcg_gen_movi_i64(cpu_pc, dest);
+ tcg_gen_exit_tb((long)ctx->tb);
+ return EXIT_GOTO_TB;
+ } else {
+ tcg_gen_movi_i64(cpu_pc, dest);
+ return EXIT_PC_UPDATED;
+ }
}
-static void gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
- int32_t disp, int mask)
+static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
+ TCGv cmp, int32_t disp)
{
+ uint64_t dest = ctx->pc + (disp << 2);
int lab_true = gen_new_label();
- if (likely(ra != 31)) {
+ if (use_goto_tb(ctx, dest)) {
+ tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
+
+ tcg_gen_goto_tb(0);
+ tcg_gen_movi_i64(cpu_pc, ctx->pc);
+ tcg_gen_exit_tb((long)ctx->tb);
+
+ gen_set_label(lab_true);
+ tcg_gen_goto_tb(1);
+ tcg_gen_movi_i64(cpu_pc, dest);
+ tcg_gen_exit_tb((long)ctx->tb + 1);
+
+ return EXIT_GOTO_TB;
+ } else {
+ int lab_over = gen_new_label();
+
+ /* ??? Consider using either
+ movi pc, next
+ addi tmp, pc, disp
+ movcond pc, cond, 0, tmp, pc
+ or
+ setcond tmp, cond, 0
+ movi pc, next
+ neg tmp, tmp
+ andi tmp, tmp, disp
+ add pc, pc, tmp
+ The current diamond subgraph surely isn't efficient. */
+
+ tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
+ tcg_gen_movi_i64(cpu_pc, ctx->pc);
+ tcg_gen_br(lab_over);
+ gen_set_label(lab_true);
+ tcg_gen_movi_i64(cpu_pc, dest);
+ gen_set_label(lab_over);
+
+ return EXIT_PC_UPDATED;
+ }
+}
+
+static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
+ int32_t disp, int mask)
+{
+ TCGv cmp_tmp;
+
+ if (unlikely(ra == 31)) {
+ cmp_tmp = tcg_const_i64(0);
+ } else {
+ cmp_tmp = tcg_temp_new();
if (mask) {
- TCGv tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
- tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
- tcg_temp_free(tmp);
+ tcg_gen_andi_i64(cmp_tmp, cpu_ir[ra], 1);
} else {
- tcg_gen_brcondi_i64(cond, cpu_ir[ra], 0, lab_true);
+ tcg_gen_mov_i64(cmp_tmp, cpu_ir[ra]);
}
- } else {
- /* Very uncommon case - Do not bother to optimize. */
- TCGv tmp = tcg_const_i64(0);
- tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
- tcg_temp_free(tmp);
}
- gen_bcond_pcload(ctx, disp, lab_true);
+
+ return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
}
-/* Generate a forward TCG branch to LAB_TRUE if RA cmp 0.0.
- This is complicated by the fact that -0.0 compares the same as +0.0. */
+/* Fold -0.0 for comparison with COND. */
-static void gen_fbcond_internal(TCGCond cond, TCGv src, int lab_true)
+static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
{
- int lab_false = -1;
uint64_t mzero = 1ull << 63;
- TCGv tmp;
switch (cond) {
case TCG_COND_LE:
case TCG_COND_GT:
/* For <= or >, the -0.0 value directly compares the way we want. */
- tcg_gen_brcondi_i64(cond, src, 0, lab_true);
+ tcg_gen_mov_i64(dest, src);
break;
case TCG_COND_EQ:
case TCG_COND_NE:
/* For == or !=, we can simply mask off the sign bit and compare. */
- /* ??? Assume that the temporary is reclaimed at the branch. */
- tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, src, mzero - 1);
- tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
+ tcg_gen_andi_i64(dest, src, mzero - 1);
break;
case TCG_COND_GE:
- /* For >=, emit two branches to the destination. */
- tcg_gen_brcondi_i64(cond, src, 0, lab_true);
- tcg_gen_brcondi_i64(TCG_COND_EQ, src, mzero, lab_true);
- break;
-
case TCG_COND_LT:
- /* For <, first filter out -0.0 to what will be the fallthru. */
- lab_false = gen_new_label();
- tcg_gen_brcondi_i64(TCG_COND_EQ, src, mzero, lab_false);
- tcg_gen_brcondi_i64(cond, src, 0, lab_true);
- gen_set_label(lab_false);
+ /* For >= or <, map -0.0 to +0.0 via comparison and mask. */
+ tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
+ tcg_gen_neg_i64(dest, dest);
+ tcg_gen_and_i64(dest, dest, src);
break;
default:
@@ -378,24 +447,24 @@ static void gen_fbcond_internal(TCGCond cond, TCGv src, int lab_true)
}
}
-static void gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, int32_t disp)
+static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
+ int32_t disp)
{
- int lab_true;
+ TCGv cmp_tmp;
if (unlikely(ra == 31)) {
/* Very uncommon case, but easier to optimize it to an integer
comparison than continuing with the floating point comparison. */
- gen_bcond(ctx, cond, ra, disp, 0);
- return;
+ return gen_bcond(ctx, cond, ra, disp, 0);
}
- lab_true = gen_new_label();
- gen_fbcond_internal(cond, cpu_fir[ra], lab_true);
- gen_bcond_pcload(ctx, disp, lab_true);
+ cmp_tmp = tcg_temp_new();
+ gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
+ return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
}
static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
- int islit, uint8_t lit, int mask)
+ int islit, uint8_t lit, int mask)
{
TCGCond inv_cond = tcg_invert_cond(cond);
int l1;
@@ -429,18 +498,23 @@ static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
{
- TCGv va = cpu_fir[ra];
+ TCGv cmp_tmp;
int l1;
- if (unlikely(rc == 31))
+ if (unlikely(rc == 31)) {
return;
+ }
+
+ cmp_tmp = tcg_temp_new();
if (unlikely(ra == 31)) {
- /* ??? Assume that the temporary is reclaimed at the branch. */
- va = tcg_const_i64(0);
+ tcg_gen_movi_i64(cmp_tmp, 0);
+ } else {
+ gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
}
l1 = gen_new_label();
- gen_fbcond_internal(tcg_invert_cond(cond), va, l1);
+ tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1);
+ tcg_temp_free(cmp_tmp);
if (rb != 31)
tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
@@ -1335,14 +1409,14 @@ static void gen_rx(int ra, int set)
tcg_temp_free_i32(tmp);
}
-static inline int translate_one(DisasContext *ctx, uint32_t insn)
+static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
{
uint32_t palcode;
int32_t disp21, disp16, disp12;
uint16_t fn11, fn16;
uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit, real_islit;
uint8_t lit;
- int ret;
+ ExitStatus ret;
/* Decode all instruction fields */
opc = insn >> 26;
@@ -1365,10 +1439,10 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
fpfn = fn11 & 0x3F;
fn7 = (insn >> 5) & 0x0000007F;
fn2 = (insn >> 5) & 0x00000003;
- ret = 0;
LOG_DISAS("opc %02x ra %2d rb %2d rc %2d disp16 %6d\n",
opc, ra, rb, rc, disp16);
+ ret = NO_EXIT;
switch (opc) {
case 0x00:
/* CALL_PAL */
@@ -1386,7 +1460,8 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
if (palcode >= 0x80 && palcode < 0xC0) {
/* Unprivileged PAL call */
gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
- ret = 3;
+ /* PC updated by gen_excp. */
+ ret = EXIT_PC_UPDATED;
break;
}
#ifndef CONFIG_USER_ONLY
@@ -1395,7 +1470,8 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
if (ctx->mem_idx & 1)
goto invalid_opc;
gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
- ret = 3;
+ /* PC updated by gen_excp. */
+ ret = EXIT_PC_UPDATED;
}
#endif
/* Invalid PAL call */
@@ -2398,13 +2474,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
switch ((uint16_t)disp16) {
case 0x0000:
/* TRAPB */
- /* No-op. Just exit from the current tb */
- ret = 2;
+ /* No-op. */
break;
case 0x0400:
/* EXCB */
- /* No-op. Just exit from the current tb */
- ret = 2;
+ /* No-op. */
break;
case 0x4000:
/* MB */
@@ -2468,21 +2542,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
if (ra != 31)
tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
/* Those four jumps only differ by the branch prediction hint */
- switch (fn2) {
- case 0x0:
- /* JMP */
- break;
- case 0x1:
- /* JSR */
- break;
- case 0x2:
- /* RET */
- break;
- case 0x3:
- /* JSR_COROUTINE */
- break;
- }
- ret = 1;
+ ret = EXIT_PC_UPDATED;
break;
case 0x1B:
/* HW_LD (PALcode) */
@@ -2773,7 +2833,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
tcg_temp_free(tmp2);
}
tcg_temp_free(tmp1);
- ret = 2;
+ ret = EXIT_PC_STALE;
}
break;
#endif
@@ -2798,7 +2858,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
gen_helper_hw_ret(tmp);
tcg_temp_free(tmp);
}
- ret = 2;
+ ret = EXIT_PC_UPDATED;
break;
#endif
case 0x1F:
@@ -2959,85 +3019,66 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x30:
/* BR */
- if (ra != 31)
- tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
- tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp21 << 2));
- ret = 1;
+ ret = gen_bdirect(ctx, ra, disp21);
break;
case 0x31: /* FBEQ */
- gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
break;
case 0x32: /* FBLT */
- gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
break;
case 0x33: /* FBLE */
- gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
break;
case 0x34:
/* BSR */
- if (ra != 31)
- tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
- tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp21 << 2));
- ret = 1;
+ ret = gen_bdirect(ctx, ra, disp21);
break;
case 0x35: /* FBNE */
- gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
break;
case 0x36: /* FBGE */
- gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
break;
case 0x37: /* FBGT */
- gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
- ret = 1;
+ ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
break;
case 0x38:
/* BLBC */
- gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
break;
case 0x39:
/* BEQ */
- gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
break;
case 0x3A:
/* BLT */
- gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
break;
case 0x3B:
/* BLE */
- gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
break;
case 0x3C:
/* BLBS */
- gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
break;
case 0x3D:
/* BNE */
- gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
break;
case 0x3E:
/* BGE */
- gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
break;
case 0x3F:
/* BGT */
- gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
- ret = 1;
+ ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
break;
invalid_opc:
gen_invalid(ctx);
- ret = 3;
+ /* PC updated by gen_excp. */
+ ret = EXIT_PC_UPDATED;
break;
}
@@ -3054,15 +3095,17 @@ static inline void gen_intermediate_code_internal(CPUState *env,
uint16_t *gen_opc_end;
CPUBreakpoint *bp;
int j, lj = -1;
- int ret;
+ ExitStatus ret;
int num_insns;
int max_insns;
pc_start = tb->pc;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+
+ ctx.tb = tb;
+ ctx.env = env;
ctx.pc = pc_start;
ctx.amask = env->amask;
- ctx.env = env;
#if defined (CONFIG_USER_ONLY)
ctx.mem_idx = 0;
#else
@@ -3086,7 +3129,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
max_insns = CF_COUNT_MASK;
gen_icount_start();
- for (ret = 0; ret == 0;) {
+ do {
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == ctx.pc) {
@@ -3117,36 +3160,39 @@ static inline void gen_intermediate_code_internal(CPUState *env,
ctx.pc += 4;
ret = translate_one(ctxp, insn);
- if (ret != 0)
- break;
- /* if we reach a page boundary or are single stepping, stop
- * generation
- */
- if (env->singlestep_enabled) {
- gen_excp(&ctx, EXCP_DEBUG, 0);
- break;
- }
- if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
- break;
-
- if (gen_opc_ptr >= gen_opc_end)
- break;
-
- if (num_insns >= max_insns)
- break;
-
- if (singlestep) {
- break;
+ if (ret == NO_EXIT) {
+ /* If we reach a page boundary, are single stepping,
+ or exhaust instruction count, stop generation. */
+ if (env->singlestep_enabled) {
+ gen_excp(&ctx, EXCP_DEBUG, 0);
+ ret = EXIT_PC_UPDATED;
+ } else if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
+ || gen_opc_ptr >= gen_opc_end
+ || num_insns >= max_insns
+ || singlestep) {
+ ret = EXIT_PC_STALE;
+ }
}
+ } while (ret == NO_EXIT);
+
+ if (tb->cflags & CF_LAST_IO) {
+ gen_io_end();
}
- if (ret != 1 && ret != 3) {
+
+ switch (ret) {
+ case EXIT_GOTO_TB:
+ break;
+ case EXIT_PC_STALE:
tcg_gen_movi_i64(cpu_pc, ctx.pc);
+ /* FALLTHRU */
+ case EXIT_PC_UPDATED:
+ tcg_gen_exit_tb(0);
+ break;
+ default:
+ abort();
}
- if (tb->cflags & CF_LAST_IO)
- gen_io_end();
- /* Generate the return instruction */
- tcg_gen_exit_tb(0);
+
gen_icount_end(tb, num_insns);
*gen_opc_ptr = INDEX_op_end;
if (search_pc) {
@@ -3158,6 +3204,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
tb->size = ctx.pc - pc_start;
tb->icount = num_insns;
}
+
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("IN: %s\n", lookup_symbol(pc_start));
--
1.6.2.5
^ permalink raw reply related [flat|nested] 32+ messages in thread