All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 01/10] target-alpha: Add flags markups to helpers.h.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
@ 2010-03-12 18:31 ` Richard Henderson
  2010-03-12 19:22 ` [Qemu-devel] [PATCH 02/10] target-alpha: Implement cpys{, n, e} inline Richard Henderson
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-12 18:31 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] 24+ messages in thread

* [Qemu-devel] [PATCH 02/10] target-alpha: Implement cpys{, n, e} inline.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
  2010-03-12 18:31 ` [Qemu-devel] [PATCH 01/10] target-alpha: Add flags markups to helpers.h Richard Henderson
@ 2010-03-12 19:22 ` Richard Henderson
  2010-03-15 14:49 ` [Qemu-devel] [PATCH 03/10] target-alpha: Implement rs/rc properly Richard Henderson
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-12 19:22 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] 24+ messages in thread

* [Qemu-devel] [PATCH 03/10] target-alpha: Implement rs/rc properly.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
  2010-03-12 18:31 ` [Qemu-devel] [PATCH 01/10] target-alpha: Add flags markups to helpers.h Richard Henderson
  2010-03-12 19:22 ` [Qemu-devel] [PATCH 02/10] target-alpha: Implement cpys{, n, e} inline Richard Henderson
@ 2010-03-15 14:49 ` Richard Henderson
  2010-03-15 15:38 ` [Qemu-devel] [PATCH 05/10] target-alpha: Implement cvtlq inline Richard Henderson
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-15 14: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 4614e3c..d4a29cb 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2356,6 +2356,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] 24+ messages in thread

* [Qemu-devel] [PATCH 05/10] target-alpha: Implement cvtlq inline.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
                   ` (2 preceding siblings ...)
  2010-03-15 14:49 ` [Qemu-devel] [PATCH 03/10] target-alpha: Implement rs/rc properly Richard Henderson
@ 2010-03-15 15:38 ` Richard Henderson
  2010-03-16 20:04 ` [Qemu-devel] [PATCH 06/10] target-alpha: Use setcond for int comparisons Richard Henderson
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-15 15:38 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 |   21 ++++++++++++++++++++-
 3 files changed, 20 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..90a14f5 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -597,6 +597,26 @@ 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();
+
+        tcg_gen_shri_i64(tmp, cpu_fir[rb], 32);
+        tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29);
+        tcg_gen_andi_i64(tmp, tmp, 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 +666,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] 24+ messages in thread

* [Qemu-devel] [PATCH 06/10] target-alpha: Use setcond for int comparisons.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
                   ` (3 preceding siblings ...)
  2010-03-15 15:38 ` [Qemu-devel] [PATCH 05/10] target-alpha: Implement cvtlq inline Richard Henderson
@ 2010-03-16 20:04 ` Richard Henderson
  2010-03-16 21:44 ` [Qemu-devel] [PATCH 07/10] target-alpha: Use non-inverted arguments to gen_{f}cmov Richard Henderson
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-16 20:04 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 90a14f5..80b5f52 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1288,33 +1288,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] 24+ messages in thread

* [Qemu-devel] [PATCH 07/10] target-alpha: Use non-inverted arguments to gen_{f}cmov.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
                   ` (4 preceding siblings ...)
  2010-03-16 20:04 ` [Qemu-devel] [PATCH 06/10] target-alpha: Use setcond for int comparisons Richard Henderson
@ 2010-03-16 21:44 ` Richard Henderson
  2010-03-16 22:10 ` [Qemu-devel] [PATCH 08/10] target-alpha: Emit goto_tb opcodes Richard Henderson
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-16 21:44 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 80b5f52..8e98b15 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]);
@@ -1765,11 +1766,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 */
@@ -1789,11 +1790,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 */
@@ -1829,11 +1830,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 */
@@ -1873,11 +1874,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 */
@@ -2351,27 +2352,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] 24+ messages in thread

* [Qemu-devel] [PATCH 08/10] target-alpha: Emit goto_tb opcodes.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
                   ` (5 preceding siblings ...)
  2010-03-16 21:44 ` [Qemu-devel] [PATCH 07/10] target-alpha: Use non-inverted arguments to gen_{f}cmov Richard Henderson
@ 2010-03-16 22:10 ` Richard Henderson
  2010-03-19 22:55 ` [Qemu-devel] [PATCH 04/10] target-alpha: Implement cvtql inline Richard Henderson
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-16 22:10 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 8e98b15..fe693b3 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]);
@@ -1332,14 +1406,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;
@@ -1362,10 +1436,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 */
@@ -1383,7 +1457,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
@@ -1392,7 +1467,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 */
@@ -2395,13 +2471,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 */
@@ -2465,21 +2539,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) */
@@ -2770,7 +2830,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
@@ -2795,7 +2855,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:
@@ -2956,85 +3016,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;
     }
 
@@ -3051,15 +3092,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
@@ -3083,7 +3126,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) {
@@ -3114,36 +3157,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) {
@@ -3155,6 +3201,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] 24+ messages in thread

* [Qemu-devel] [PATCH 04/10] target-alpha: Implement cvtql inline.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
                   ` (6 preceding siblings ...)
  2010-03-16 22:10 ` [Qemu-devel] [PATCH 08/10] target-alpha: Emit goto_tb opcodes Richard Henderson
@ 2010-03-19 22:55 ` Richard Henderson
  2010-03-25  0:11 ` [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly Richard Henderson
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-19 22:55 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] 24+ messages in thread

* [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
                   ` (7 preceding siblings ...)
  2010-03-19 22:55 ` [Qemu-devel] [PATCH 04/10] target-alpha: Implement cvtql inline Richard Henderson
@ 2010-03-25  0:11 ` Richard Henderson
  2010-03-25 13:39   ` Nathan Froyd
  2010-03-25  0:13 ` [Qemu-devel] [PATCH 10/10] target-alpha: Enable NPTL Richard Henderson
  2010-03-26  1:52 ` [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Jamie Lokier
  10 siblings, 1 reply; 24+ messages in thread
From: Richard Henderson @ 2010-03-25  0:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Use __sync_bool_compare_and_swap to yield correctly atomic results.
As yet, this assumes running on an strict-memory-ordering host (i.e. x86),
since we're still "implementing" the memory-barrier instructions as nops.

Rename the "lock" cpu field to "lock_addr" and add a "lock_value" field
to be used as the "old" value for the compare-and-swap.  Use -1 in the
lock_addr field to indicate no lock held.  Break the lock when processing
any sort of exception.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/main.c        |   11 ++++
 target-alpha/cpu.h       |    3 +-
 target-alpha/helper.c    |    6 +-
 target-alpha/helper.h    |    3 +
 target-alpha/op_helper.c |   70 ++++++++++++++++++++++
 target-alpha/translate.c |  146 ++++++++++++++++++++++++---------------------
 6 files changed, 168 insertions(+), 71 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index d4a29cb..cbff027 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2361,6 +2361,14 @@ void cpu_loop (CPUState *env)
 	   that the intr_flag should be cleared.  */
 	env->intr_flag = 0;
 
+        /* Similarly with the lock_flag, where "clear" is -1 here.
+           ??? Note that it's not possible to single-step through
+           a ldl_l/stl_c sequence on real hardware, but let's see
+           if we can do better than that in the emulator.  */
+        if (trapnr != EXCP_DEBUG) {
+            env->lock_addr = -1;
+        }
+
         switch (trapnr) {
         case EXCP_RESET:
             fprintf(stderr, "Reset requested. Exit\n");
@@ -2512,6 +2520,9 @@ void cpu_loop (CPUState *env)
         case EXCP_DEBUG:
             info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
             if (info.si_signo) {
+                /* ??? See above re single-stepping and ldl_l.  If we're
+                   actually going to deliver a signal, break the lock.  */
+                env->lock_addr = -1;
                 info.si_errno = 0;
                 info.si_code = TARGET_TRAP_BRKPT;
                 queue_signal(env, info.si_signo, &info);
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 8afe16d..cf2b587 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -355,11 +355,12 @@ 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_value;
     float_status fp_status;
     /* The following fields make up the FPCR, but in FP_STATUS format.  */
     uint8_t fpcr_exc_status;
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 46335cd..e4dd124 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -556,12 +556,14 @@ 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);
 }
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index ccf6a2a..a540eeb 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -99,6 +99,9 @@ DEF_HELPER_1(ieee_input, i64, i64)
 DEF_HELPER_1(ieee_input_cmp, i64, i64)
 DEF_HELPER_1(ieee_input_s, i64, i64)
 
+DEF_HELPER_2(stl_c, i64, i64, i64)
+DEF_HELPER_2(stq_c, i64, i64, i64)
+
 #if !defined (CONFIG_USER_ONLY)
 DEF_HELPER_0(hw_rei, void)
 DEF_HELPER_1(hw_ret, void, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index a209130..ea68222 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1152,6 +1152,74 @@ uint64_t helper_cvtqg (uint64_t a)
     return float64_to_g(fr);
 }
 
+uint64_t helper_stl_c (uint64_t addr, uint64_t val)
+{
+    uint64_t ret = 0;
+
+    /* The resultant virtual and physical address must specify a location
+       within the same natually aligned 16-byte block as the preceeding
+       load instruction.  Note that (1) we're only checking the physical
+       address here, since ADDR has already been through virt_to_phys,
+       and (2) LOCK_ADDR has already been masked with -16.  We do this
+       ahead of time so that we can assign LOCK_ADDR = -1 to force a 
+       failure here.  */
+    /* ??? The "16" in the spec is no doubt the minimum architectural
+       cacheline size.  If we are attempting to model the real hardware
+       implementation, we should probably expand this to the real cache
+       line size.  But this is certainly good enough for now.  */
+    if ((addr & -16) == env->lock_addr) {
+        int32_t *host_addr;
+
+#if defined(CONFIG_USER_ONLY)
+        host_addr = (int32_t *)addr;
+#else
+        /* FIXME */
+        cpu_abort();
+#endif
+
+        /* Emulate the ldl_l/stl_c pair with a compare-and-swap.  */
+        ret = __sync_bool_compare_and_swap(host_addr,
+                                           (int32_t)env->lock_value,
+                                           (int32_t)val);
+    }
+
+    env->lock_addr = -1;
+    return ret;
+}
+
+uint64_t helper_stq_c (uint64_t addr, uint64_t val)
+{
+    uint64_t ret = 0;
+
+    /* The resultant virtual and physical address must specify a location
+       within the same natually aligned 16-byte block as the preceeding
+       load instruction.  Note that (1) we're only checking the physical
+       address here, since ADDR has already been through virt_to_phys,
+       and (2) LOCK_ADDR has already been masked with -16.  We do this
+       ahead of time so that we can assign LOCK_ADDR = -1 to force a 
+       failure here.  */
+    /* ??? The "16" in the spec is no doubt the minimum architectural
+       cacheline size.  If we are attempting to model the real hardware
+       implementation, we should probably expand this to the real cache
+       line size.  But this is certainly good enough for now.  */
+    if ((addr & -16) == env->lock_addr) {
+        uint64_t *host_addr;
+
+#if defined(CONFIG_USER_ONLY)
+        host_addr = (uint64_t *)addr;
+#else
+        /* FIXME */
+        cpu_abort();
+#endif
+
+        /* Emulate the ldq_l/stq_c pair with a compare-and-swap.  */
+        ret = __sync_bool_compare_and_swap(host_addr, env->lock_value, val);
+    }
+
+    env->lock_addr = -1;
+    return ret;
+}
+
 /* PALcode support special instructions */
 #if !defined (CONFIG_USER_ONLY)
 void helper_hw_rei (void)
@@ -1159,6 +1227,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 +1236,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 fe693b3..7a67ff8 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -82,7 +82,8 @@ 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_value;
 #ifdef CONFIG_USER_ONLY
 static TCGv cpu_uniq;
 #endif
@@ -119,8 +120,12 @@ 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_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,
@@ -181,16 +186,33 @@ static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
     tcg_temp_free(tmp);
 }
 
+static void gen_virt_to_phys(TCGv out, TCGv in, int store)
+{
+#if defined(CONFIG_USER_ONLY)
+    tcg_gen_addi_i64(out, in, GUEST_BASE);
+#else
+    if (store) {
+        gen_helper_st_virt_to_phys(out, in);
+    } else {
+        gen_helper_ld_virt_to_phys(out, in);
+    }
+#endif
+}
+
 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);
+    gen_virt_to_phys(cpu_lock_addr, t1, 0);
+    tcg_gen_andi_i64(cpu_lock_addr, cpu_lock_addr, -16);
+    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);
+    gen_virt_to_phys(cpu_lock_addr, t1, 0);
+    tcg_gen_andi_i64(cpu_lock_addr, cpu_lock_addr, -16);
+    tcg_gen_mov_i64(cpu_lock_value, t0);
 }
 
 static inline void gen_load_mem(DisasContext *ctx,
@@ -199,25 +221,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);
 }
 
@@ -253,71 +281,52 @@ static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
 
 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);
+    TCGv va = tcg_temp_new();
+    gen_virt_to_phys(va, t1, 1);
+    gen_helper_stl_c(t0, va, t0);
+    tcg_temp_free(va);
 }
 
 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);
+    TCGv va = tcg_temp_new();
+    gen_virt_to_phys(va, t1, 1);
+    gen_helper_stq_c(t0, va, t0);
+    tcg_temp_free(va);
 }
 
 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 int use_goto_tb(DisasContext *ctx, uint64_t dest)
@@ -1530,15 +1539,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) {
@@ -2968,19 +2977,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 */
@@ -3000,19 +3009,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);
+        gen_store_mem(ctx, &gen_qemu_stl_c, ra, rb, disp16, 0, 0);
         break;
     case 0x2F:
         /* STQ_C */
-        gen_store_mem(ctx, &gen_qemu_stq_c, ra, rb, disp16, 0, 0, 1);
+        gen_store_mem(ctx, &gen_qemu_stq_c, ra, rb, disp16, 0, 0);
         break;
     case 0x30:
         /* BR */
@@ -3279,6 +3288,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] 24+ messages in thread

* [Qemu-devel] [PATCH 10/10] target-alpha: Enable NPTL.
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
                   ` (8 preceding siblings ...)
  2010-03-25  0:11 ` [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly Richard Henderson
@ 2010-03-25  0:13 ` Richard Henderson
  2010-03-26  1:52 ` [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Jamie Lokier
  10 siblings, 0 replies; 24+ 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 6bc40a3..6b50b6a 100755
--- a/configure
+++ b/configure
@@ -2368,6 +2368,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 80d8633..b921076 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5755,7 +5755,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 cf2b587..bbc5ac2 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -412,15 +412,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"
 
@@ -478,7 +469,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,
@@ -491,7 +482,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,
@@ -532,4 +523,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] 24+ messages in thread

* [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements
@ 2010-03-25  0:24 Richard Henderson
  2010-03-12 18:31 ` [Qemu-devel] [PATCH 01/10] target-alpha: Add flags markups to helpers.h Richard Henderson
                   ` (10 more replies)
  0 siblings, 11 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-25  0:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Changes from v1->v2:
  * Use setcond and goto_tb.

Changes from v2->v3:
  * Enable NPTL.

I don't see how any sort of emulation of cmpxchg/load-locked is working
for any currently enabled nptl target.  I think how I've approached
handling load-locked for alpha is probably the easiest way.  Slightly
better would be if TCG had a (set of) cmpxchg opcodes, which would have
the benefit of getting the virt->phys->host address (and segfault handling)
more correct.  I've sort of totally ignored the faulting for now.

This is just good enough to not immediately fail the glibc testsuite for
alpha, as the default glibc test skeleton uses clone.  I'm concurrently
debuging the glibc-alpha port and the qemu-alpha syscall emulation, so
it's not always clear which is at fault.  


r~


Richard Henderson (10):
  target-alpha: Add flags markups to helpers.h.
  target-alpha: Implement cpys{,n,e} inline.
  target-alpha: Implement rs/rc properly.
  target-alpha: Implement cvtql inline.
  target-alpha: Implement cvtlq inline.
  target-alpha: Use setcond for int comparisons.
  target-alpha: Use non-inverted arguments to gen_{f}cmov.
  target-alpha: Emit goto_tb opcodes.
  target-alpha: Implement load-locked/store-conditional properly.
  target-alpha: Enable NPTL.

 configure                |    1 +
 linux-user/main.c        |   16 +
 linux-user/syscall.c     |    2 +-
 target-alpha/cpu.h       |   31 ++-
 target-alpha/helper.c    |    6 +-
 target-alpha/helper.h    |  182 ++++++------
 target-alpha/op_helper.c |  131 +++++----
 target-alpha/translate.c |  722 +++++++++++++++++++++++++++++-----------------
 8 files changed, 651 insertions(+), 440 deletions(-)

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25  0:11 ` [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly Richard Henderson
@ 2010-03-25 13:39   ` Nathan Froyd
  2010-03-25 15:46     ` Richard Henderson
  0 siblings, 1 reply; 24+ messages in thread
From: Nathan Froyd @ 2010-03-25 13:39 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, aurelien

On Wed, Mar 24, 2010 at 05:11:43PM -0700, Richard Henderson wrote:
> Use __sync_bool_compare_and_swap to yield correctly atomic results.
> As yet, this assumes running on an strict-memory-ordering host (i.e. x86),
> since we're still "implementing" the memory-barrier instructions as nops.

Did the approach taken by other targets (arm/mips/ppc) not work on
Alpha?

-Nathan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 13:39   ` Nathan Froyd
@ 2010-03-25 15:46     ` Richard Henderson
  2010-03-25 16:06       ` Nathan Froyd
                         ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-25 15:46 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: qemu-devel, aurelien

On 03/25/2010 06:39 AM, Nathan Froyd wrote:
> On Wed, Mar 24, 2010 at 05:11:43PM -0700, Richard Henderson wrote:
>> Use __sync_bool_compare_and_swap to yield correctly atomic results.
>> As yet, this assumes running on an strict-memory-ordering host (i.e. x86),
>> since we're still "implementing" the memory-barrier instructions as nops.
> 
> Did the approach taken by other targets (arm/mips/ppc) not work on
> Alpha?

Mips doesn't even pretend to be atomic.

Powerpc and Arm -- if I've got this straight -- use some sort of stop-the-world
mutex+condition and then perform the compare-and-exchange by hand.  I can't
see how that's better than using an actual compare-and-exchange provided by
the host cpu.  In fact, I'm mildly horrified by the prospect.

Honestly.  Even ARM and HPPA which doesn't (always) natively have cmpxchg, have
an easy to use kernel trap to perform the operation.  I suppose real 80386 and
sparc-pre-v9 don't have anything particularly useful, but frankly it wouldn't
bother me to deprecate them as hosts since the modern editions all do work.


r~

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 15:46     ` Richard Henderson
@ 2010-03-25 16:06       ` Nathan Froyd
  2010-03-25 16:29         ` Richard Henderson
  2010-03-25 17:40       ` Blue Swirl
  2010-03-26  2:01       ` Jamie Lokier
  2 siblings, 1 reply; 24+ messages in thread
From: Nathan Froyd @ 2010-03-25 16:06 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, aurelien

On Thu, Mar 25, 2010 at 08:46:06AM -0700, Richard Henderson wrote:
> On 03/25/2010 06:39 AM, Nathan Froyd wrote:
> > On Wed, Mar 24, 2010 at 05:11:43PM -0700, Richard Henderson wrote:
> >> Use __sync_bool_compare_and_swap to yield correctly atomic results.
> >> As yet, this assumes running on an strict-memory-ordering host (i.e. x86),
> >> since we're still "implementing" the memory-barrier instructions as nops.
> > 
> > Did the approach taken by other targets (arm/mips/ppc) not work on
> > Alpha?
> 
> Mips doesn't even pretend to be atomic.

It pretends just as much as ppc and arm.  See translate.c:OP_ST_ATOMIC.

> Powerpc and Arm -- if I've got this straight -- use some sort of stop-the-world
> mutex+condition and then perform the compare-and-exchange by hand.  I can't
> see how that's better than using an actual compare-and-exchange provided by
> the host cpu.  In fact, I'm mildly horrified by the prospect.

Oh, I didn't say it was pretty.  But it does work fairly well in
practice--enough to pass most of glibc's NPTL testsuite, for instance.
(The remaining cases are tricky things, like cross-process locks.)  I
think--though Paul would remember better than I--that the stop-the-world
approach might have been taken due to a desire to continue compiling
with gcc < 4.1.  I don't know how much of a desdirata that still is.

(stop-the-world is also somewhat less complex than the previous
implementation, which involved page protection games.)

Certainly using actual compare-and-exchange would be much faster.

-Nathan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 16:06       ` Nathan Froyd
@ 2010-03-25 16:29         ` Richard Henderson
  2010-03-25 16:42           ` Nathan Froyd
  0 siblings, 1 reply; 24+ messages in thread
From: Richard Henderson @ 2010-03-25 16:29 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: qemu-devel, aurelien

On 03/25/2010 09:06 AM, Nathan Froyd wrote:
>> Mips doesn't even pretend to be atomic.
> 
> It pretends just as much as ppc and arm.  See translate.c:OP_ST_ATOMIC.

No it doesn't.  Look at HELPER_ST_ATOMIC:

        tmp = do_##ld_insn(arg2, mem_idx);                                    \
        if (tmp == env->llval) {                                              \
            do_##st_insn(arg2, arg1, mem_idx);                                \
            return 1;                                                         \

> (The remaining cases are tricky things, like cross-process locks.)  I
> think--though Paul would remember better than I--that the stop-the-world
> approach might have been taken due to a desire to continue compiling
> with gcc < 4.1.  I don't know how much of a desdirata that still is.

Even that wouldn't be an issue if we move the cmpxchg into TCG.

I'll put this at the end of the enhancement queue...


r~

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 16:29         ` Richard Henderson
@ 2010-03-25 16:42           ` Nathan Froyd
  2010-03-25 16:50             ` Richard Henderson
  0 siblings, 1 reply; 24+ messages in thread
From: Nathan Froyd @ 2010-03-25 16:42 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, aurelien

On Thu, Mar 25, 2010 at 09:29:18AM -0700, Richard Henderson wrote:
> On 03/25/2010 09:06 AM, Nathan Froyd wrote:
> > It pretends just as much as ppc and arm.  See translate.c:OP_ST_ATOMIC.
> 
> No it doesn't.  Look at HELPER_ST_ATOMIC:
> 
>         tmp = do_##ld_insn(arg2, mem_idx);                                    \
>         if (tmp == env->llval) {                                              \
>             do_##st_insn(arg2, arg1, mem_idx);                                \
>             return 1;                                                         \

Ah, OK.  Those helpers are never called for user-mode emulation,
though.  They're only called for system emulation and...well, everybody
lies about being atomic in system mode. :)

-Nathan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 16:42           ` Nathan Froyd
@ 2010-03-25 16:50             ` Richard Henderson
  0 siblings, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-25 16:50 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: qemu-devel, aurelien

On 03/25/2010 09:42 AM, Nathan Froyd wrote:
> Ah, OK.  Those helpers are never called for user-mode emulation,
> though.  They're only called for system emulation and...well, everybody
> lies about being atomic in system mode. :)

Ah, right.  I missed the user/system variations of OP_ST_ATOMIC.


r~

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 15:46     ` Richard Henderson
  2010-03-25 16:06       ` Nathan Froyd
@ 2010-03-25 17:40       ` Blue Swirl
  2010-03-25 18:19         ` Richard Henderson
  2010-03-26  2:01       ` Jamie Lokier
  2 siblings, 1 reply; 24+ messages in thread
From: Blue Swirl @ 2010-03-25 17:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: aurelien, qemu-devel, Nathan Froyd

On 3/25/10, Richard Henderson <rth@twiddle.net> wrote:
> On 03/25/2010 06:39 AM, Nathan Froyd wrote:
>  > On Wed, Mar 24, 2010 at 05:11:43PM -0700, Richard Henderson wrote:
>  >> Use __sync_bool_compare_and_swap to yield correctly atomic results.
>  >> As yet, this assumes running on an strict-memory-ordering host (i.e. x86),
>  >> since we're still "implementing" the memory-barrier instructions as nops.
>  >
>  > Did the approach taken by other targets (arm/mips/ppc) not work on
>  > Alpha?
>
>
> Mips doesn't even pretend to be atomic.
>
>  Powerpc and Arm -- if I've got this straight -- use some sort of stop-the-world
>  mutex+condition and then perform the compare-and-exchange by hand.  I can't
>  see how that's better than using an actual compare-and-exchange provided by
>  the host cpu.  In fact, I'm mildly horrified by the prospect.
>
>  Honestly.  Even ARM and HPPA which doesn't (always) natively have cmpxchg, have
>  an easy to use kernel trap to perform the operation.  I suppose real 80386 and
>  sparc-pre-v9 don't have anything particularly useful, but frankly it wouldn't
>  bother me to deprecate them as hosts since the modern editions all do work.

Sparc V8 has two atomic instructions, ldstub and swap.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 17:40       ` Blue Swirl
@ 2010-03-25 18:19         ` Richard Henderson
  2010-03-26  1:55           ` Jamie Lokier
  0 siblings, 1 reply; 24+ messages in thread
From: Richard Henderson @ 2010-03-25 18:19 UTC (permalink / raw)
  To: Blue Swirl; +Cc: aurelien, qemu-devel, Nathan Froyd

On 03/25/2010 10:40 AM, Blue Swirl wrote:
> Sparc V8 has two atomic instructions, ldstub and swap.

I know -- but not the CAS operation being discussed here.

As I think about this more and more, the Real Problem is
not with the CAS, but with the memory ordering requirements
of the guest vs the memory ordering of the host.  It's easy
to implement things on x86, because of the host's strict
memory ordering.  It would be much more difficult to properly
emulate x86 on a relaxed memory ordering host.  We'd need to
insert barriers between pairs of qemu_{ld,st} operations.

I may give this some proper thinking this weekend.


r~

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements
  2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
                   ` (9 preceding siblings ...)
  2010-03-25  0:13 ` [Qemu-devel] [PATCH 10/10] target-alpha: Enable NPTL Richard Henderson
@ 2010-03-26  1:52 ` Jamie Lokier
  2010-03-26 13:37   ` Richard Henderson
  2010-04-01 13:44   ` Paul Brook
  10 siblings, 2 replies; 24+ messages in thread
From: Jamie Lokier @ 2010-03-26  1:52 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, aurelien

Richard Henderson wrote:
> I don't see how any sort of emulation of cmpxchg/load-locked is working
> for any currently enabled nptl target.  I think how I've approached
> handling load-locked for alpha is probably the easiest way.  Slightly
> better would be if TCG had a (set of) cmpxchg opcodes, which would have
> the benefit of getting the virt->phys->host address (and segfault handling)
> more correct.  I've sort of totally ignored the faulting for now.

I guess you are thinking to save the value loaded by load-locked, and
use it as the "old" for host cmpxchg at target's store-conditional?

I'm not sure if that will have the correct behaviour for all target
architectures, where _any_ value written by another CPU during an
ll/sc sequence will prevent the sequence from proceeding, including

   CPU #0                CPU #1

   x <- load-locked(A)
   y <- load(B)
                         x+1 -> store(A)
                         y+1 -> store(B)
                         x   -> store(A)
   f(x,y) -> store-cond(A)

Unless I made a mistake, the above cannot store f(x,y+1) into A, for
any interleaving (assume strongly ordered memory or barriers), on
machines where any store by another CPU breaks the condition.  But on
machines which implement store-cond by atomic-cmpxchg using the
load-locked value, f(x,y+1) can be stored.

It'll be fine when ll/sc are only used to provide single-word atomic
calculations, but I'm not sure those are the only uses to which they
are put by any code anywhere.  E.g. if I remember rightly, there was
some discussion of a planned unusual ll/sc use on the linux-arm list,
which involved a second word, but the idea wasn't ever implemented.

-- Jamie

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 18:19         ` Richard Henderson
@ 2010-03-26  1:55           ` Jamie Lokier
  0 siblings, 0 replies; 24+ messages in thread
From: Jamie Lokier @ 2010-03-26  1:55 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Blue Swirl, Nathan Froyd, qemu-devel, aurelien

Richard Henderson wrote:
> On 03/25/2010 10:40 AM, Blue Swirl wrote:
> > Sparc V8 has two atomic instructions, ldstub and swap.
> 
> I know -- but not the CAS operation being discussed here.
> 
> As I think about this more and more, the Real Problem is
> not with the CAS, but with the memory ordering requirements
> of the guest vs the memory ordering of the host.  It's easy
> to implement things on x86, because of the host's strict
> memory ordering.  It would be much more difficult to properly
> emulate x86 on a relaxed memory ordering host.  We'd need to
> insert barriers between pairs of qemu_{ld,st} operations.
> 
> I may give this some proper thinking this weekend.

Some host architectures have a strongly ordered mode, which might
help, and be faster than putting barriers everywhere.

-- Jamie

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly.
  2010-03-25 15:46     ` Richard Henderson
  2010-03-25 16:06       ` Nathan Froyd
  2010-03-25 17:40       ` Blue Swirl
@ 2010-03-26  2:01       ` Jamie Lokier
  2 siblings, 0 replies; 24+ messages in thread
From: Jamie Lokier @ 2010-03-26  2:01 UTC (permalink / raw)
  To: Richard Henderson; +Cc: aurelien, qemu-devel, Nathan Froyd

Richard Henderson wrote:
> On 03/25/2010 06:39 AM, Nathan Froyd wrote:
> > On Wed, Mar 24, 2010 at 05:11:43PM -0700, Richard Henderson wrote:
> >> Use __sync_bool_compare_and_swap to yield correctly atomic results.
> >> As yet, this assumes running on an strict-memory-ordering host (i.e. x86),
> >> since we're still "implementing" the memory-barrier instructions as nops.
> > 
> > Did the approach taken by other targets (arm/mips/ppc) not work on
> > Alpha?
> 
> Mips doesn't even pretend to be atomic.
> 
> Powerpc and Arm -- if I've got this straight -- use some sort of stop-the-world
> mutex+condition and then perform the compare-and-exchange by hand.  I can't
> see how that's better than using an actual compare-and-exchange provided by
> the host cpu.  In fact, I'm mildly horrified by the prospect.

As I've just written with an example elsewhere on this thread,
compare-and-exchange is insufficient to properly emulate ll/sc on some
targets archs, when used with certain algorithms.  I believe ARM is
one such; I don't know about any of the others.

But in nearly all cases, if not all the ones actually seen, it should
be trivial to scan the guest instruction sequence between load-locked
and store-conditional, and confirm that there's no funny business
(non-register operations) in between that would prevent
compare-exchange from emulating it correctly.

So stop-the-world ought to remain in, but only as a last resort to be
used when the ll/sc sequence doesn't pass the no-funny-business test.

The example I gave might even be usable to test it.

-- Jamie

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements
  2010-03-26  1:52 ` [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Jamie Lokier
@ 2010-03-26 13:37   ` Richard Henderson
  2010-04-01 13:44   ` Paul Brook
  1 sibling, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2010-03-26 13:37 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: qemu-devel, aurelien

On 03/25/2010 06:52 PM, Jamie Lokier wrote:
> I guess you are thinking to save the value loaded by load-locked,
> and use it as the "old" for host cmpxchg at target's
> store-conditional?

Yes.

> It'll be fine when ll/sc are only used to provide single-word atomic
> calculations, but I'm not sure those are the only uses to which they
> are put by any code anywhere.  E.g. if I remember rightly, there was
> some discussion of a planned unusual ll/sc use on the linux-arm
> list, which involved a second word, but the idea wasn't ever
> implemented.

"It is UNPREDICTABLE whether a processor's lock_flag is cleared by
that processor executing a normal load or store instruction."

So at least on Alpha your double-word update isn't supposed to work.

Now, what the cmpxchg *doesn't* handle is when the store isn't to
exactly the same address as the load.  The Alpha spec does allow the
store to be anywhere within the same 16-byte aligned block, and we
can't handle that.  That said, I'm pretty sure such a non-matching
store is never used on Linux.

> So stop-the-world ought to remain in, but only as a last resort to
> be used when the ll/sc sequence doesn't pass the no-funny-business
> test.

The existing stop-the-world implementation is *exactly* cmpxchg.

It doesn't do what you want: stop the world at the ll, resume the
world at the sc (or other suitable subsequent condition e.g. taken
branch or N executed instructions).


r~

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements
  2010-03-26  1:52 ` [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Jamie Lokier
  2010-03-26 13:37   ` Richard Henderson
@ 2010-04-01 13:44   ` Paul Brook
  1 sibling, 0 replies; 24+ messages in thread
From: Paul Brook @ 2010-04-01 13:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, Richard Henderson

>    CPU #0                CPU #1
> 
>    x <- load-locked(A)
>    y <- load(B)
>                          x+1 -> store(A)
>                          y+1 -> store(B)
>                          x   -> store(A)
>    f(x,y) -> store-cond(A)
> 
> Unless I made a mistake, the above cannot store f(x,y+1) into A, for
> any interleaving (assume strongly ordered memory or barriers), on
> machines where any store by another CPU breaks the condition.  But on
> machines which implement store-cond by atomic-cmpxchg using the
> load-locked value, f(x,y+1) can be stored.

I investigated this fairly closely for the initial implementation.
Your key assumption is that you have strict ordering between CPUs.
While it is possible to construct theoretical failure cases there this is 
observable. In practice you end up falling fall foul of architectural 
limitations on the use of ll/sc. Your example fails to describe how x and y 
are transferred from CPU0 to CPU1.

I'd regard any code that has a barrier between a load-locked and store-
conditional with extreme suspicion.  For example PPC states that barrier 
instructions cause a CPU to loose the lock[1].

Paul

[1] We currently get this wrong in QEMU.

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2010-04-01 13:44 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-25  0:24 [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Richard Henderson
2010-03-12 18:31 ` [Qemu-devel] [PATCH 01/10] target-alpha: Add flags markups to helpers.h Richard Henderson
2010-03-12 19:22 ` [Qemu-devel] [PATCH 02/10] target-alpha: Implement cpys{, n, e} inline Richard Henderson
2010-03-15 14:49 ` [Qemu-devel] [PATCH 03/10] target-alpha: Implement rs/rc properly Richard Henderson
2010-03-15 15:38 ` [Qemu-devel] [PATCH 05/10] target-alpha: Implement cvtlq inline Richard Henderson
2010-03-16 20:04 ` [Qemu-devel] [PATCH 06/10] target-alpha: Use setcond for int comparisons Richard Henderson
2010-03-16 21:44 ` [Qemu-devel] [PATCH 07/10] target-alpha: Use non-inverted arguments to gen_{f}cmov Richard Henderson
2010-03-16 22:10 ` [Qemu-devel] [PATCH 08/10] target-alpha: Emit goto_tb opcodes Richard Henderson
2010-03-19 22:55 ` [Qemu-devel] [PATCH 04/10] target-alpha: Implement cvtql inline Richard Henderson
2010-03-25  0:11 ` [Qemu-devel] [PATCH 09/10] target-alpha: Implement load-locked/store-conditional properly Richard Henderson
2010-03-25 13:39   ` Nathan Froyd
2010-03-25 15:46     ` Richard Henderson
2010-03-25 16:06       ` Nathan Froyd
2010-03-25 16:29         ` Richard Henderson
2010-03-25 16:42           ` Nathan Froyd
2010-03-25 16:50             ` Richard Henderson
2010-03-25 17:40       ` Blue Swirl
2010-03-25 18:19         ` Richard Henderson
2010-03-26  1:55           ` Jamie Lokier
2010-03-26  2:01       ` Jamie Lokier
2010-03-25  0:13 ` [Qemu-devel] [PATCH 10/10] target-alpha: Enable NPTL Richard Henderson
2010-03-26  1:52 ` [Qemu-devel] [PATCH 00/10, v3] target-alpha improvements Jamie Lokier
2010-03-26 13:37   ` Richard Henderson
2010-04-01 13:44   ` Paul Brook

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.