qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2] s390x: Add laa and laag instructions


From: Alexander Graf
Subject: [Qemu-devel] [PATCH v2] s390x: Add laa and laag instructions
Date: Tue, 12 May 2015 22:20:31 +0200

We're currently missing the laa and laag instructions in our emulation.
In fact, we're missing the complete "interlocked-access facility 1" which
is part of zEC12. However, I really only needed the laa instruction for now.

Signed-off-by: Alexander Graf <address@hidden>

---

This really should implement all the other atomic load&modify instructions,
but I'd like to make sure we have a smart scheme to implement them first.

v1 -> v2:

  - move atomic specific bits into load/store helpers, leave actual op
    as normal op we can reuse
---
 target-s390x/insn-data.def |  3 +++
 target-s390x/translate.c   | 48 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 48e979e..cd95035 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -359,6 +359,9 @@
     C(0xe371, LAY,     RXY_a, LD,  0, a2, 0, r1, mov2, 0)
 /* LOAD ADDRESS RELATIVE LONG */
     C(0xc000, LARL,    RIL_b, Z,   0, ri2, 0, r1, mov2, 0)
+/* LOAD AND ADD */
+    C(0xebf8, LAA,     RSY_a, ILA, r3_32s, m2_32s_atomic, new, 
m2_32_r1_atomic, add, adds32)
+    C(0xebe8, LAAG,    RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, 
add, adds64)
 /* LOAD AND TEST */
     C(0x1200, LTR,     RR_a,  Z,   0, r2_o, 0, cond_r1r2_32, mov2, s32)
     C(0xb902, LTGR,    RRE,   Z,   0, r2_o, 0, r1, mov2, s64)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index fa3e334..73f2de3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1118,6 +1118,7 @@ typedef enum DisasFacility {
     FAC_PC,                 /* population count */
     FAC_SCF,                /* store clock fast */
     FAC_SFLE,               /* store facility list extended */
+    FAC_ILA,                /* interlocked access facility 1 */
 } DisasFacility;
 
 struct DisasInsn {
@@ -1297,6 +1298,12 @@ static ExitStatus help_branch(DisasContext *s, 
DisasCompare *c,
     return ret;
 }
 
+static TCGv_i64 get_a2(DisasContext *s, DisasFields *f)
+{
+    int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
+    return get_address(s, x2, get_field(f, b2), get_field(f, d2));
+}
+
 /* ====================================================================== */
 /* The operations.  These perform the bulk of the work for any insn,
    usually after the operands have been loaded and output initialized.  */
@@ -4065,6 +4072,30 @@ static void wout_m2_32(DisasContext *s, DisasFields *f, 
DisasOps *o)
 }
 #define SPEC_wout_m2_32 0
 
+static void wout_m2_32_r1_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    TCGv_i64 a2 = get_a2(s, f);
+
+    /* XXX release reservation */
+    tcg_gen_qemu_st32(o->out, a2, get_mem_index(s));
+    store_reg32_i64(get_field(f, r1), o->in2);
+
+    tcg_temp_free_i64(a2);
+}
+#define SPEC_wout_m2_32_r1_atomic 0
+
+static void wout_m2_64_r1_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    TCGv_i64 a2 = get_a2(s, f);
+
+    /* XXX release reservation */
+    tcg_gen_qemu_st64(o->out, a2, get_mem_index(s));
+    store_reg(get_field(f, r1), o->in2);
+
+    tcg_temp_free_i64(a2);
+}
+#define SPEC_wout_m2_64_r1_atomic 0
+
 /* ====================================================================== */
 /* The "INput 1" generators.  These load the first operand to an insn.  */
 
@@ -4393,8 +4424,7 @@ static void in2_ra2(DisasContext *s, DisasFields *f, 
DisasOps *o)
 
 static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
-    o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
+    o->in2 = get_a2(s, f);
 }
 #define SPEC_in2_a2 0
 
@@ -4486,6 +4516,20 @@ static void in2_mri2_64(DisasContext *s, DisasFields *f, 
DisasOps *o)
 }
 #define SPEC_in2_mri2_64 0
 
+static void in2_m2_32s_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* XXX should reserve the address */
+    in2_m2_32s(s, f, o);
+}
+#define SPEC_in2_m2_32s_atomic 0
+
+static void in2_m2_64_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* XXX should reserve the address */
+    in2_m2_64(s, f, o);
+}
+#define SPEC_in2_m2_64_atomic 0
+
 static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_const_i64(get_field(f, i2));
-- 
1.7.12.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]