From c095ed731ce4fecf166e4ac02ddc606b408f5e1f Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 15 Apr 2015 03:45:41 +0200 Subject: [PATCH 1/3] s390x: Fix stoc direction The store conditional instruction wants to store when the condition is fulfilled, so we should branch out when it's not true. The code today branches out when the condition is true, clearly reversing the logic. Fix it up by negating the condition. Signed-off-by: Alexander Graf Reviewed-by: Richard Henderson --- target-s390x/translate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 8784112f4e..fa3e334e4f 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -3082,6 +3082,10 @@ static ExitStatus op_soc(DisasContext *s, DisasOps *o) disas_jcc(s, &c, get_field(s->fields, m3)); + /* We want to store when the condition is fulfilled, so branch + out when it's not */ + c.cond = tcg_invert_cond(c.cond); + lab = gen_new_label(); if (c.is_64) { tcg_gen_brcond_i64(c.cond, c.u.s64.a, c.u.s64.b, lab); From 13f67dd5825a7dfd7a4904a5fb0cf0a3f95d2d45 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 8 May 2015 03:06:41 +0200 Subject: [PATCH 2/3] s390x: Add some documentation in opcode list I find it really hard to grasp what each field in the opcode list means. Slowly walking through its semantics myself, I figured I'd write a small summary at the top of the file to make life easier for me and whoever looks at the file next. Signed-off-by: Alexander Graf Reviewed-by: Richard Henderson --- target-s390x/insn-data.def | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def index 8d8e47e0bf..48e979e881 100644 --- a/target-s390x/insn-data.def +++ b/target-s390x/insn-data.def @@ -1,3 +1,24 @@ +/* + * Arguments to the opcode prototypes + * + * C(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC) + * D(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC, DATA) + * + * OPC = (op << 8) | op2 where op is the major, op2 the minor opcode + * NAME = name of the opcode, used internally + * FMT = format of the opcode (defined in insn-format.def) + * FAC = facility the opcode is available in (defined in DisasFacility) + * I1 = func in1_xx fills o->in1 + * I2 = func in2_xx fills o->in2 + * P = func prep_xx initializes o->*out* + * W = func wout_xx writes o->*out* somewhere + * OP = func op_xx does the bulk of the operation + * CC = func cout_xx defines how cc should get set + * DATA = immediate argument to op_xx function + * + * The helpers get called in order: I1, I2, P, OP, W, CC + */ + /* ADD */ C(0x1a00, AR, RR_a, Z, r1, r2, new, r1_32, add, adds32) C(0xb9f8, ARK, RRF_a, DO, r2, r3, new, r1_32, add, adds32) From 57af7289f276ce70b65f2fbb4981833f04264aac Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 8 May 2015 03:07:53 +0200 Subject: [PATCH 3/3] s390x: Add interlocked access facility 1 instructions We're currently missing all instructions defined by the "interlocked-access facility 1" which is part of zEC12. This patch implements all of them except for LPD and LPDG. Signed-off-by: Alexander Graf Reviewed-by: Richard Henderson --- target-s390x/insn-data.def | 16 ++++++++++++++++ target-s390x/translate.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def index 48e979e881..72c3a2edda 100644 --- a/target-s390x/insn-data.def +++ b/target-s390x/insn-data.def @@ -359,6 +359,21 @@ 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 ADD LOGICAL */ + C(0xebfa, LAAL, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, add, addu32) + C(0xebea, LAALG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, add, addu64) +/* LOAD AND AND */ + C(0xebf4, LAN, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, and, nz32) + C(0xebe4, LANG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, and, nz64) +/* LOAD AND EXCLUSIVE OR */ + C(0xebf7, LAX, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, xor, nz32) + C(0xebe7, LAXG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, xor, nz64) +/* LOAD AND OR */ + C(0xebf6, LAO, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, or, nz32) + C(0xebe6, LAOG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, or, nz64) /* 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) @@ -438,6 +453,7 @@ C(0xb9e2, LOCGR, RRF_c, LOC, r1, r2, r1, 0, loc, 0) C(0xebf2, LOC, RSY_b, LOC, r1, m2_32u, new, r1_32, loc, 0) C(0xebe2, LOCG, RSY_b, LOC, r1, m2_64, r1, 0, loc, 0) +/* LOAD PAIR DISJOINT TODO */ /* LOAD POSITIVE */ C(0x1000, LPR, RR_a, Z, 0, r2_32s, new, r1_32, abs, abs32) C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index fa3e334e4f..80e3a545e4 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 { @@ -4065,6 +4066,22 @@ 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) +{ + /* XXX release reservation */ + tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s)); + store_reg32_i64(get_field(f, r1), o->in2); +} +#define SPEC_wout_m2_32_r1_atomic 0 + +static void wout_m2_64_r1_atomic(DisasContext *s, DisasFields *f, DisasOps *o) +{ + /* XXX release reservation */ + tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s)); + store_reg(get_field(f, r1), o->in2); +} +#define SPEC_wout_m2_64_r1_atomic 0 + /* ====================================================================== */ /* The "INput 1" generators. These load the first operand to an insn. */ @@ -4486,6 +4503,24 @@ 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 */ + in1_la2(s, f, o); + o->in2 = tcg_temp_new_i64(); + tcg_gen_qemu_ld32s(o->in2, o->addr1, get_mem_index(s)); +} +#define SPEC_in2_m2_32s_atomic 0 + +static void in2_m2_64_atomic(DisasContext *s, DisasFields *f, DisasOps *o) +{ + /* XXX should reserve the address */ + in1_la2(s, f, o); + o->in2 = tcg_temp_new_i64(); + tcg_gen_qemu_ld64(o->in2, o->addr1, get_mem_index(s)); +} +#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));