* [PULL 4/6] s390x/tcg: Implement Miscellaneous-Instruction-Extensions Facility 3 for the s390x
2022-02-28 13:29 [PULL 0/6] s390x patches Thomas Huth
` (2 preceding siblings ...)
2022-02-28 13:29 ` [PULL 3/6] travis.yml: Update the s390x jobs to Ubuntu Focal Thomas Huth
@ 2022-02-28 13:29 ` Thomas Huth
2022-02-28 13:29 ` [PULL 5/6] s390x/cpumodel: Bump up QEMU model to a stripped-down IBM z15 GA1 Thomas Huth
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Thomas Huth @ 2022-02-28 13:29 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, qemu-s390x, David Hildenbrand, Richard Henderson,
David Miller
From: David Miller <dmiller423@gmail.com>
implements:
AND WITH COMPLEMENT (NCRK, NCGRK)
NAND (NNRK, NNGRK)
NOT EXCLUSIVE OR (NXRK, NXGRK)
NOR (NORK, NOGRK)
OR WITH COMPLEMENT (OCRK, OCGRK)
SELECT (SELR, SELGR)
SELECT HIGH (SELFHR)
MOVE RIGHT TO LEFT (MVCRL)
POPULATION COUNT (POPCNT)
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/737
Signed-off-by: David Miller <dmiller423@gmail.com>
Message-Id: <20220223223117.66660-2-dmiller423@gmail.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
target/s390x/gen-features.c | 1 +
target/s390x/helper.h | 1 +
target/s390x/tcg/insn-data.def | 30 +++++++++++++++--
target/s390x/tcg/mem_helper.c | 20 ++++++++++++
target/s390x/tcg/translate.c | 60 ++++++++++++++++++++++++++++++++--
5 files changed, 107 insertions(+), 5 deletions(-)
diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c
index 7cb1a6ec10..a3f30f69d9 100644
--- a/target/s390x/gen-features.c
+++ b/target/s390x/gen-features.c
@@ -740,6 +740,7 @@ static uint16_t qemu_LATEST[] = {
/* add all new definitions before this point */
static uint16_t qemu_MAX[] = {
+ S390_FEAT_MISC_INSTRUCTION_EXT3,
/* generates a dependency warning, leave it out for now */
S390_FEAT_MSA_EXT_5,
};
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 271b081e8c..69f69cf718 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -4,6 +4,7 @@ DEF_HELPER_FLAGS_4(nc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(mvc, TCG_CALL_NO_WG, void, env, i32, i64, i64)
+DEF_HELPER_FLAGS_4(mvcrl, TCG_CALL_NO_WG, void, env, i64, i64, i64)
DEF_HELPER_FLAGS_4(mvcin, TCG_CALL_NO_WG, void, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_3(mvcl, i32, env, i32, i32)
diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def
index 4911952080..6c8a8b229f 100644
--- a/target/s390x/tcg/insn-data.def
+++ b/target/s390x/tcg/insn-data.def
@@ -105,6 +105,9 @@
D(0xa507, NILL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
D(0x9400, NI, SI, Z, la1, i2_8u, new, 0, ni, nz64, MO_UB)
D(0xeb54, NIY, SIY, LD, la1, i2_8u, new, 0, ni, nz64, MO_UB)
+/* AND WITH COMPLEMENT */
+ C(0xb9f5, NCRK, RRF_a, MIE3, r2, r3, new, r1_32, andc, nz32)
+ C(0xb9e5, NCGRK, RRF_a, MIE3, r2, r3, r1, 0, andc, nz64)
/* BRANCH AND LINK */
C(0x0500, BALR, RR_a, Z, 0, r2_nz, r1, 0, bal, 0)
@@ -640,6 +643,8 @@
C(0xeb8e, MVCLU, RSY_a, E2, 0, a2, 0, 0, mvclu, 0)
/* MOVE NUMERICS */
C(0xd100, MVN, SS_a, Z, la1, a2, 0, 0, mvn, 0)
+/* MOVE RIGHT TO LEFT */
+ C(0xe50a, MVCRL, SSE, MIE3, la1, a2, 0, 0, mvcrl, 0)
/* MOVE PAGE */
C(0xb254, MVPG, RRE, Z, 0, 0, 0, 0, mvpg, 0)
/* MOVE STRING */
@@ -707,6 +712,16 @@
F(0xed0f, MSEB, RXF, Z, e1, m2_32u, new, e1, mseb, 0, IF_BFP)
F(0xed1f, MSDB, RXF, Z, f1, m2_64, new, f1, msdb, 0, IF_BFP)
+/* NAND */
+ C(0xb974, NNRK, RRF_a, MIE3, r2, r3, new, r1_32, nand, nz32)
+ C(0xb964, NNGRK, RRF_a, MIE3, r2, r3, r1, 0, nand, nz64)
+/* NOR */
+ C(0xb976, NORK, RRF_a, MIE3, r2, r3, new, r1_32, nor, nz32)
+ C(0xb966, NOGRK, RRF_a, MIE3, r2, r3, r1, 0, nor, nz64)
+/* NOT EXCLUSIVE OR */
+ C(0xb977, NXRK, RRF_a, MIE3, r2, r3, new, r1_32, nxor, nz32)
+ C(0xb967, NXGRK, RRF_a, MIE3, r2, r3, r1, 0, nxor, nz64)
+
/* OR */
C(0x1600, OR, RR_a, Z, r1, r2, new, r1_32, or, nz32)
C(0xb9f6, ORK, RRF_a, DO, r2, r3, new, r1_32, or, nz32)
@@ -725,6 +740,9 @@
D(0xa50b, OILL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
D(0x9600, OI, SI, Z, la1, i2_8u, new, 0, oi, nz64, MO_UB)
D(0xeb56, OIY, SIY, LD, la1, i2_8u, new, 0, oi, nz64, MO_UB)
+/* OR WITH COMPLEMENT */
+ C(0xb975, OCRK, RRF_a, MIE3, r2, r3, new, r1_32, orc, nz32)
+ C(0xb965, OCGRK, RRF_a, MIE3, r2, r3, r1, 0, orc, nz64)
/* PACK */
/* Really format SS_b, but we pack both lengths into one argument
@@ -735,6 +753,9 @@
/* PACK UNICODE */
C(0xe100, PKU, SS_f, E2, la1, a2, 0, 0, pku, 0)
+/* POPULATION COUNT */
+ C(0xb9e1, POPCNT, RRF_c, PC, 0, r2_o, r1, 0, popcnt, nz64)
+
/* PREFETCH */
/* Implemented as nops of course. */
C(0xe336, PFD, RXY_b, GIE, 0, 0, 0, 0, 0, 0)
@@ -743,9 +764,6 @@
/* Implemented as nop of course. */
C(0xb2e8, PPA, RRF_c, PPA, 0, 0, 0, 0, 0, 0)
-/* POPULATION COUNT */
- C(0xb9e1, POPCNT, RRE, PC, 0, r2_o, r1, 0, popcnt, nz64)
-
/* ROTATE LEFT SINGLE LOGICAL */
C(0xeb1d, RLL, RSY_a, Z, r3_o, sh, new, r1_32, rll32, 0)
C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh, r1, 0, rll64, 0)
@@ -765,6 +783,12 @@
/* SEARCH STRING UNICODE */
C(0xb9be, SRSTU, RRE, ETF3, 0, 0, 0, 0, srstu, 0)
+/* SELECT */
+ C(0xb9f0, SELR, RRF_a, MIE3, r3, r2, new, r1_32, loc, 0)
+ C(0xb9e3, SELGR, RRF_a, MIE3, r3, r2, r1, 0, loc, 0)
+/* SELECT HIGH */
+ C(0xb9c0, SELFHR, RRF_a, MIE3, r3_sr32, r2_sr32, new, r1_32h, loc, 0)
+
/* SET ACCESS */
C(0xb24e, SAR, RRE, Z, 0, r2_o, 0, 0, sar, 0)
/* SET ADDRESSING MODE */
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index b5523ef3c7..fc52aa128b 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -547,6 +547,26 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
do_helper_mvc(env, l, dest, src, GETPC());
}
+/* move right to left */
+void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t dest, uint64_t src)
+{
+ const int mmu_idx = cpu_mmu_index(env, false);
+ const uint64_t ra = GETPC();
+ S390Access srca, desta;
+ int32_t i;
+
+ /* MVCRL always copies one more byte than specified - maximum is 256 */
+ l++;
+
+ srca = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
+ desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
+
+ for (i = l - 1; i >= 0; i--) {
+ uint8_t byte = access_get_byte(env, &srca, i, ra);
+ access_set_byte(env, &desta, i, byte, ra);
+ }
+}
+
/* move inverse */
void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
{
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
index e21da539e5..904b51542f 100644
--- a/target/s390x/tcg/translate.c
+++ b/target/s390x/tcg/translate.c
@@ -1498,6 +1498,36 @@ static DisasJumpType op_andi(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
+static DisasJumpType op_andc(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_andc_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
+static DisasJumpType op_orc(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_orc_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
+static DisasJumpType op_nand(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_nand_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
+static DisasJumpType op_nor(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_nor_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
+static DisasJumpType op_nxor(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_eqv_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
static DisasJumpType op_ni(DisasContext *s, DisasOps *o)
{
o->in1 = tcg_temp_new_i64();
@@ -2958,7 +2988,13 @@ static DisasJumpType op_loc(DisasContext *s, DisasOps *o)
{
DisasCompare c;
- disas_jcc(s, &c, get_field(s, m3));
+ if (have_field(s, m3)) {
+ /* LOAD * ON CONDITION */
+ disas_jcc(s, &c, get_field(s, m3));
+ } else {
+ /* SELECT */
+ disas_jcc(s, &c, get_field(s, m4));
+ }
if (c.is_64) {
tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
@@ -3358,6 +3394,12 @@ static DisasJumpType op_mvc(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
+static DisasJumpType op_mvcrl(DisasContext *s, DisasOps *o)
+{
+ gen_helper_mvcrl(cpu_env, regs[0], o->addr1, o->in2);
+ return DISAS_NEXT;
+}
+
static DisasJumpType op_mvcin(DisasContext *s, DisasOps *o)
{
TCGv_i32 l = tcg_const_i32(get_field(s, l1));
@@ -3744,7 +3786,13 @@ static DisasJumpType op_pku(DisasContext *s, DisasOps *o)
static DisasJumpType op_popcnt(DisasContext *s, DisasOps *o)
{
- gen_helper_popcnt(o->out, o->in2);
+ const uint8_t m3 = get_field(s, m3);
+
+ if ((m3 & 8) && s390_has_feat(S390_FEAT_MISC_INSTRUCTION_EXT3)) {
+ tcg_gen_ctpop_i64(o->out, o->in2);
+ } else {
+ gen_helper_popcnt(o->out, o->in2);
+ }
return DISAS_NEXT;
}
@@ -5667,6 +5715,13 @@ static void in1_r3_D32(DisasContext *s, DisasOps *o)
}
#define SPEC_in1_r3_D32 SPEC_r3_even
+static void in1_r3_sr32(DisasContext *s, DisasOps *o)
+{
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_shri_i64(o->in1, regs[get_field(s, r3)], 32);
+}
+#define SPEC_in1_r3_sr32 0
+
static void in1_e1(DisasContext *s, DisasOps *o)
{
o->in1 = load_freg32_i64(get_field(s, r1));
@@ -6169,6 +6224,7 @@ enum DisasInsnEnum {
#define FAC_V S390_FEAT_VECTOR /* vector facility */
#define FAC_VE S390_FEAT_VECTOR_ENH /* vector enhancements facility 1 */
#define FAC_MIE2 S390_FEAT_MISC_INSTRUCTION_EXT2 /* miscellaneous-instruction-extensions facility 2 */
+#define FAC_MIE3 S390_FEAT_MISC_INSTRUCTION_EXT3 /* miscellaneous-instruction-extensions facility 3 */
static const DisasInsn insn_info[] = {
#include "insn-data.def"
--
2.27.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PULL 6/6] tests/tcg/s390x: Tests for Miscellaneous-Instruction-Extensions Facility 3
2022-02-28 13:29 [PULL 0/6] s390x patches Thomas Huth
` (4 preceding siblings ...)
2022-02-28 13:29 ` [PULL 5/6] s390x/cpumodel: Bump up QEMU model to a stripped-down IBM z15 GA1 Thomas Huth
@ 2022-02-28 13:29 ` Thomas Huth
2022-03-01 15:55 ` [PULL 0/6] s390x patches Peter Maydell
6 siblings, 0 replies; 8+ messages in thread
From: Thomas Huth @ 2022-02-28 13:29 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, qemu-s390x, David Miller
From: David Miller <dmiller423@gmail.com>
tests/tcg/s390x/mie3-compl.c: [N]*K instructions
tests/tcg/s390x/mie3-mvcrl.c: MVCRL instruction
tests/tcg/s390x/mie3-sel.c: SELECT instruction
Signed-off-by: David Miller <dmiller423@gmail.com>
Message-Id: <20220223223117.66660-4-dmiller423@gmail.com>
[thuth: Squash mnemonic -> .insn patch, white space cleanup, improve asm usage]
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
tests/tcg/s390x/Makefile.target | 3 +++
tests/tcg/s390x/mie3-compl.c | 48 +++++++++++++++++++++++++++++++++
tests/tcg/s390x/mie3-mvcrl.c | 27 +++++++++++++++++++
tests/tcg/s390x/mie3-sel.c | 38 ++++++++++++++++++++++++++
4 files changed, 116 insertions(+)
create mode 100644 tests/tcg/s390x/mie3-compl.c
create mode 100644 tests/tcg/s390x/mie3-mvcrl.c
create mode 100644 tests/tcg/s390x/mie3-sel.c
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
index 1a7238b4eb..8c9b6a13ce 100644
--- a/tests/tcg/s390x/Makefile.target
+++ b/tests/tcg/s390x/Makefile.target
@@ -7,6 +7,9 @@ TESTS+=ipm
TESTS+=exrl-trt
TESTS+=exrl-trtr
TESTS+=pack
+TESTS+=mie3-compl
+TESTS+=mie3-mvcrl
+TESTS+=mie3-sel
TESTS+=mvo
TESTS+=mvc
TESTS+=shift
diff --git a/tests/tcg/s390x/mie3-compl.c b/tests/tcg/s390x/mie3-compl.c
new file mode 100644
index 0000000000..35649f3b02
--- /dev/null
+++ b/tests/tcg/s390x/mie3-compl.c
@@ -0,0 +1,48 @@
+#include <stdint.h>
+
+#define FbinOp(S, ASM) uint64_t S(uint64_t a, uint64_t b) \
+{ \
+ uint64_t res = 0; \
+ asm ("llihf %[res],801\n" ASM \
+ : [res]"=&r"(res) : [a]"r"(a), [b]"r"(b) : "cc"); \
+ return res; \
+}
+
+/* AND WITH COMPLEMENT */
+FbinOp(_ncrk, ".insn rrf, 0xB9F50000, %[res], %[b], %[a], 0\n")
+FbinOp(_ncgrk, ".insn rrf, 0xB9E50000, %[res], %[b], %[a], 0\n")
+
+/* NAND */
+FbinOp(_nnrk, ".insn rrf, 0xB9740000, %[res], %[b], %[a], 0\n")
+FbinOp(_nngrk, ".insn rrf, 0xB9640000, %[res], %[b], %[a], 0\n")
+
+/* NOT XOR */
+FbinOp(_nxrk, ".insn rrf, 0xB9770000, %[res], %[b], %[a], 0\n")
+FbinOp(_nxgrk, ".insn rrf, 0xB9670000, %[res], %[b], %[a], 0\n")
+
+/* NOR */
+FbinOp(_nork, ".insn rrf, 0xB9760000, %[res], %[b], %[a], 0\n")
+FbinOp(_nogrk, ".insn rrf, 0xB9660000, %[res], %[b], %[a], 0\n")
+
+/* OR WITH COMPLEMENT */
+FbinOp(_ocrk, ".insn rrf, 0xB9750000, %[res], %[b], %[a], 0\n")
+FbinOp(_ocgrk, ".insn rrf, 0xB9650000, %[res], %[b], %[a], 0\n")
+
+int main(int argc, char *argv[])
+{
+ if (_ncrk(0xFF88, 0xAA11) != 0x0000032100000011ull ||
+ _nnrk(0xFF88, 0xAA11) != 0x00000321FFFF55FFull ||
+ _nork(0xFF88, 0xAA11) != 0x00000321FFFF0066ull ||
+ _nxrk(0xFF88, 0xAA11) != 0x00000321FFFFAA66ull ||
+ _ocrk(0xFF88, 0xAA11) != 0x00000321FFFFAA77ull ||
+ _ncgrk(0xFF88, 0xAA11) != 0x0000000000000011ull ||
+ _nngrk(0xFF88, 0xAA11) != 0xFFFFFFFFFFFF55FFull ||
+ _nogrk(0xFF88, 0xAA11) != 0xFFFFFFFFFFFF0066ull ||
+ _nxgrk(0xFF88, 0xAA11) != 0xFFFFFFFFFFFFAA66ull ||
+ _ocgrk(0xFF88, 0xAA11) != 0xFFFFFFFFFFFFAA77ull)
+ {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/tests/tcg/s390x/mie3-mvcrl.c b/tests/tcg/s390x/mie3-mvcrl.c
new file mode 100644
index 0000000000..57b08e48d0
--- /dev/null
+++ b/tests/tcg/s390x/mie3-mvcrl.c
@@ -0,0 +1,27 @@
+#include <stdint.h>
+#include <string.h>
+
+static inline void mvcrl_8(const char *dst, const char *src)
+{
+ asm volatile (
+ "llill %%r0, 8\n"
+ ".insn sse, 0xE50A00000000, 0(%[dst]), 0(%[src])"
+ : : [dst] "d" (dst), [src] "d" (src)
+ : "memory");
+}
+
+int main(int argc, char *argv[])
+{
+ const char *alpha = "abcdefghijklmnop";
+
+ /* array missing 'i' */
+ char tstr[17] = "abcdefghjklmnop\0" ;
+
+ /* mvcrl reference use: 'open a hole in an array' */
+ mvcrl_8(tstr + 9, tstr + 8);
+
+ /* place missing 'i' */
+ tstr[8] = 'i';
+
+ return strncmp(alpha, tstr, 16ul);
+}
diff --git a/tests/tcg/s390x/mie3-sel.c b/tests/tcg/s390x/mie3-sel.c
new file mode 100644
index 0000000000..b0c5c9857d
--- /dev/null
+++ b/tests/tcg/s390x/mie3-sel.c
@@ -0,0 +1,38 @@
+#include <stdint.h>
+
+#define Fi3(S, ASM) uint64_t S(uint64_t a, uint64_t b, uint64_t c) \
+{ \
+ uint64_t res = 0; \
+ asm ( \
+ "lg %%r2, %[a]\n" \
+ "lg %%r3, %[b]\n" \
+ "lg %%r0, %[c]\n" \
+ "ltgr %%r0, %%r0\n" \
+ ASM \
+ "stg %%r0, %[res] " \
+ : [res] "=m" (res) \
+ : [a] "m" (a), \
+ [b] "m" (b), \
+ [c] "m" (c) \
+ : "r0", "r2", \
+ "r3", "r4" \
+ ); \
+ return res; \
+}
+
+Fi3 (_selre, ".insn rrf, 0xB9F00000, %%r0, %%r3, %%r2, 8\n")
+Fi3 (_selgrz, ".insn rrf, 0xB9E30000, %%r0, %%r3, %%r2, 8\n")
+Fi3 (_selfhrnz, ".insn rrf, 0xB9C00000, %%r0, %%r3, %%r2, 7\n")
+
+int main(int argc, char *argv[])
+{
+ uint64_t a = ~0, b = ~0, c = ~0;
+ a = _selre(0x066600000066ull, 0x066600000006ull, a);
+ b = _selgrz(0xF00D00000005ull, 0xF00D00000055ull, b);
+ c = _selfhrnz(0x043200000044ull, 0x065400000004ull, c);
+
+ return (int) (
+ (0xFFFFFFFF00000066ull != a) ||
+ (0x0000F00D00000005ull != b) ||
+ (0x00000654FFFFFFFFull != c));
+}
--
2.27.0
^ permalink raw reply related [flat|nested] 8+ messages in thread