qemu-s390x
[Top][All Lists]
Advanced

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

Re: patch s390x/tcg: Implement Miscellaneous-Instruction-Extensions Faci


From: Christian Borntraeger
Subject: Re: patch s390x/tcg: Implement Miscellaneous-Instruction-Extensions Facility 3 for the s390x
Date: Wed, 9 Feb 2022 10:02:44 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0

CCing TCG/s390x maintainers.


Am 08.02.22 um 23:52 schrieb David Miller:
 From c21eaa57a40ed22f10087a1019dd456d99e3fb03 Mon Sep 17 00:00:00 2001
From: David Miller <dmiller423@gmail.com>
Date: Tue, 8 Feb 2022 22:33:48 -0500
Subject: [PATCH] s390x/tcg: Implement Miscellaneous-Instruction-Extensions
  Facility 3 for the s390x

Signed-off-by: David Miller <dmiller423@gmail.com>
---
  target/s390x/helper.h           |  1 +
  target/s390x/tcg/insn-data.def  | 26 +++++++++++++++++
  target/s390x/tcg/mem_helper.c   | 42 ++++++++++++++++++++++++++
  target/s390x/tcg/translate.c    | 49 +++++++++++++++++++++++++++++++
  tests/tcg/s390x/Makefile.target |  2 +-
  tests/tcg/s390x/mie3-compl.c    | 52 +++++++++++++++++++++++++++++++++
  tests/tcg/s390x/mie3-mvcrl.c    | 31 ++++++++++++++++++++
  tests/tcg/s390x/mie3-sel.c      | 42 ++++++++++++++++++++++++++
  8 files changed, 244 insertions(+), 1 deletion(-)
  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/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 1c3e115712..5678c94b09 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 */
@@ -725,6 +730,21 @@
      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)
+
+/* 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)

  /* PACK */
      /* Really format SS_b, but we pack both lengths into one argument
@@ -765,6 +785,12 @@
  /* SEARCH STRING UNICODE */
      C(0xb9be, SRSTU,   RRE,   ETF3, 0, 0, 0, 0, srstu, 0)

+/* SELECT */
+    C(0xb9f0, SELR,    RRF_a, MIE3, r2, r3, new, r1_32, sel, 0)
+    C(0xb9e3, SELGR,   RRF_a, MIE3, r2, r3, r1, 0, sel, 0)
+/* SELECT HIGH */
+    C(0xb9c0, SELFHR,  RRF_a, MIE3, r2, r3, new, r1_32h, sel, 0)
+
  /* SET ACCESS */
      C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
  /* SET ADDRESSING MODE */


I quickly verified that the mnemonics and binary instructions match.

One thing that might be missing:
I could not find the POPCOUNT changes mentioned in SA22-7832-12

--snip--
In addition, POPULATION COUNT includes a control
in an M 3 field for counting the number of one bits in
each byte or the entire 64-bit register.
--snip--

Can you have a look?


diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index 406578d105..9275f1349f 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -546,6 +546,48 @@ 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 */
+static uint32_t do_helper_mvcrl(CPUS390XState *env, uint64_t l, uint64_t dest,
+                                uint64_t src, uintptr_t ra)
+{
+    const int mmu_idx = cpu_mmu_index(env, false);
+    S390Access srca, desta;
+    uint32_t i;
+
+    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
+               __func__, l, dest, src);
+
+    /* 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);
+
+    /*
+     * "When the operands overlap, the result is obtained as if the operands
+     * were processed one byte at a time". Only non-destructive overlaps
+     * behave like memmove().
+     */
+    if (dest == src + l - 1) {
+        access_memset(env, &desta, access_get_byte(env, &srca, 0, ra), ra);
+    } else if (!is_destructive_overlap(env, dest, src, l)) {
+        access_memmove(env, &desta, &srca, ra);
+    } else {
+        for (i = 0; i < l; i++) {
+            uint32_t ti = l - i - 1;
+            uint8_t byte = access_get_byte(env, &srca, ti, ra);
+            access_set_byte(env, &desta, ti, byte, ra);
+        }
+    }
+
+    return env->cc_op;
+}
+
+void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t dest, uint64_t src)
+{
+    do_helper_mvcrl(env, l, dest, src, GETPC());
+}
+
  /* 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 46dea73357..c0a89e2787 100644
--- a/target/s390x/tcg/translate.c
+++ b/target/s390x/tcg/translate.c
@@ -1498,6 +1498,48 @@ 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_xor_i64(o->out, o->in1, o->in2);
+    tcg_gen_not_i64(o->out, o->out);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_sel(DisasContext *s, DisasOps *o)
+{
+    DisasCompare c;
+    disas_jcc(s, &c, get_field(s, m4));
+    tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
+                        o->in1, o->in2);
+    free_compare(&c);
+    return DISAS_NEXT;
+}
+
+
  static DisasJumpType op_ni(DisasContext *s, DisasOps *o)
  {
      o->in1 = tcg_temp_new_i64();
@@ -3358,6 +3400,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));
@@ -6170,6 +6218,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"
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
index 1a7238b4eb..16b9d45307 100644
--- a/tests/tcg/s390x/Makefile.target
+++ b/tests/tcg/s390x/Makefile.target
@@ -1,6 +1,6 @@
  S390X_SRC=$(SRC_PATH)/tests/tcg/s390x
  VPATH+=$(S390X_SRC)
-CFLAGS+=-march=zEC12 -m64
+CFLAGS+=-march=z15 -m64
  TESTS+=hello-s390x
  TESTS+=csst
  TESTS+=ipm
diff --git a/tests/tcg/s390x/mie3-compl.c b/tests/tcg/s390x/mie3-compl.c
new file mode 100644
index 0000000000..c03c2b6b7f
--- /dev/null
+++ b/tests/tcg/s390x/mie3-compl.c
@@ -0,0 +1,52 @@
+#include <stdint.h>
+
+
+#define F_EPI "stg %%r0, %[res] ": [res] "+m" (res) : : "r0", "r2", "r3"
+
+#define F_PRO    asm ( \
+    "llihf %%r0,801\n" \
+    "lg %%r2, %[a] \n" \
+    "lg %%r3, %[b] "   \
+    : : [a] "m" (a),   \
+        [b] "m" (b)    \
+    : "r2", "r3" )
+
+#define FbinOp(S, ASM) uint64_t S(uint64_t a, uint64_t b) \
+{ uint64_t res = 0; F_PRO; ASM; return res; }
+
+
+FbinOp(_ncrk,  asm("ncrk  %%r0, %%r3, %%r2 \n" F_EPI)) // AND WITH COMPLEMENT
+FbinOp(_ncgrk, asm("ncgrk %%r0, %%r3, %%r2 \n" F_EPI))
+
+FbinOp(_nnrk,  asm("nnrk  %%r0, %%r3, %%r2 \n" F_EPI)) // NAND
+FbinOp(_nngrk, asm("nngrk %%r0, %%r3, %%r2 \n" F_EPI))
+
+FbinOp(_nxrk,  asm("nxrk  %%r0, %%r3, %%r2 \n" F_EPI)) // NOT XOR
+FbinOp(_nxgrk, asm("nxgrk %%r0, %%r3, %%r2 \n" F_EPI))
+
+FbinOp(_nork,  asm("nork  %%r0, %%r3, %%r2 \n" F_EPI)) // NOR
+FbinOp(_nogrk, asm("nogrk %%r0, %%r3, %%r2 \n" F_EPI))
+
+FbinOp(_ocrk,  asm("ocrk  %%r0, %%r3, %%r2 \n" F_EPI)) // OR WITH COMPLEMENT
+FbinOp(_ocgrk, asm("ocgrk %%r0, %%r3, %%r2 \n" F_EPI))
+
+
+
+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..00f9c150a1
--- /dev/null
+++ b/tests/tcg/s390x/mie3-mvcrl.c
@@ -0,0 +1,31 @@
+#include <stdint.h>
+#include <string.h>
+
+
+static inline void mvcrl_8(const char *dst, const char *src)
+{
+    asm volatile (
+    "llill %%r0, 8 \n"
+    "mvcrl 0(%[dst]), 0(%[src]) \n"
+    : : [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..e771b1e413
--- /dev/null
+++ b/tests/tcg/s390x/mie3-sel.c
@@ -0,0 +1,42 @@
+#include <stdint.h>
+
+
+#define F_EPI "stg %%r0, %[res] ": [res] "+m" (res) : : "r0", "r2", "r3"
+
+#define F_PRO    asm (  \
+    "lg %%r2, %[a]  \n" \
+    "lg %%r3, %[b]  \n" \
+    "lg %%r0, %[c]  \n" \
+    "ltgr %%r0, %%r0"   \
+    : : [a] "m" (a),    \
+        [b] "m" (b),    \
+        [c] "m" (c)     \
+    : "r0", "r2", "r3", "r4")
+
+
+
+#define Fi3(S, ASM) uint64_t S(uint64_t a, uint64_t b, uint64_t c) \
+{ uint64_t res=0; F_PRO ; ASM ; return res; }
+
+
+Fi3 (_selre,     asm("selre    %%r0, %%r3, %%r2 \n" F_EPI))
+Fi3 (_selgrz,    asm("selgrz   %%r0, %%r3, %%r2 \n" F_EPI))
+Fi3 (_selfhrnz,  asm("selfhrnz %%r0, %%r3, %%r2 \n" F_EPI))
+
+
+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(0x004400000044ull, 0x000400000004ull,c);
+
+    if( (0xFFFFFFFF00000066ull != a) ||
+        (0x0000F00D00000005ull != b) ||
+        (0x00000004FFFFFFFFull != c) )
+    {
+        return 1;
+    }
+    return 0;
+}
+



reply via email to

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