qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions
@ 2023-05-03  8:56 Richard Henderson
  2023-05-03  8:56 ` [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez} Richard Henderson
                   ` (11 more replies)
  0 siblings, 12 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Based-on: 20230503070656.1746170-1-richard.henderson@linaro.org
("[PATCH v4 00/57] tcg: Improve atomicity support")

I've been vaguely following the __hw_probe syscall progress
in the upstream kernel.  The initial version only handled
bog standard F+D and C extensions, which everything expects
to be present anyway, which was disappointing.  But at least
the basis is there for proper extensions.

In the meantime, probe via sigill.  Tested with qemu-on-qemu.
I understand the Ventana core has all of these, if you'd be
so kind as to test.


r~


Richard Henderson (11):
  disas/riscv: Decode czero.{eqz,nez}
  tcg/riscv: Probe for Zba, Zbb, Zicond extensions
  tcg/riscv: Support ANDN, ORN, XNOR from Zbb
  tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb
  tcg/riscv: Use ADD.UW for guest address generation
  tcg/riscv: Support rotates from Zbb
  tcg/riscv: Support REV8 from Zbb
  tcg/riscv: Support CPOP from Zbb
  tcg/riscv: Improve setcond expansion
  tcg/riscv: Implement movcond
  tcg/riscv: Support CTZ, CLZ from Zbb

 tcg/riscv/tcg-target-con-set.h |   3 +
 tcg/riscv/tcg-target-con-str.h |   1 +
 tcg/riscv/tcg-target.h         |  48 +--
 disas/riscv.c                  |   8 +-
 tcg/riscv/tcg-target.c.inc     | 612 +++++++++++++++++++++++++++++----
 5 files changed, 587 insertions(+), 85 deletions(-)

-- 
2.34.1



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

* [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez}
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:37   ` Daniel Henrique Barboza
  2023-05-16 23:33   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 02/11] tcg/riscv: Probe for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (10 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 disas/riscv.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/disas/riscv.c b/disas/riscv.c
index d6b0fbe5e8..c0a8b1006a 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -935,6 +935,8 @@ typedef enum {
     rv_op_vsetvli = 766,
     rv_op_vsetivli = 767,
     rv_op_vsetvl = 768,
+    rv_op_czero_eqz = 769,
+    rv_op_czero_nez = 770,
 } rv_op;
 
 /* structures */
@@ -2066,7 +2068,9 @@ const rv_opcode_data opcode_data[] = {
     { "vsext.vf8", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, rv_op_vsext_vf8, rv_op_vsext_vf8, 0 },
     { "vsetvli", rv_codec_vsetvli, rv_fmt_vsetvli, NULL, rv_op_vsetvli, rv_op_vsetvli, 0 },
     { "vsetivli", rv_codec_vsetivli, rv_fmt_vsetivli, NULL, rv_op_vsetivli, rv_op_vsetivli, 0 },
-    { "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 }
+    { "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 },
+    { "czero.eqz", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+    { "czero.nez", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2792,6 +2796,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
             case 45: op = rv_op_minu; break;
             case 46: op = rv_op_max; break;
             case 47: op = rv_op_maxu; break;
+            case 075: op = rv_op_czero_eqz; break;
+            case 077: op = rv_op_czero_nez; break;
             case 130: op = rv_op_sh1add; break;
             case 132: op = rv_op_sh2add; break;
             case 134: op = rv_op_sh3add; break;
-- 
2.34.1



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

* [PATCH 02/11] tcg/riscv: Probe for Zba, Zbb, Zicond extensions
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
  2023-05-03  8:56 ` [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez} Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:37   ` Daniel Henrique Barboza
  2023-05-16 23:35   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 03/11] tcg/riscv: Support ANDN, ORN, XNOR from Zbb Richard Henderson
                   ` (9 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Define a useful subset of the extensions.  Probe for them
via compiler pre-processor feature macros and SIGILL.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target.h     |  6 +++
 tcg/riscv/tcg-target.c.inc | 96 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+)

diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index 494c986b49..863ac8ba2f 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -90,6 +90,12 @@ typedef enum {
 #define TCG_TARGET_CALL_ARG_I128        TCG_CALL_ARG_NORMAL
 #define TCG_TARGET_CALL_RET_I128        TCG_CALL_RET_NORMAL
 
+#if defined(__riscv_arch_test) && defined(__riscv_zbb)
+# define have_zbb true
+#else
+extern bool have_zbb;
+#endif
+
 /* optional instructions */
 #define TCG_TARGET_HAS_movcond_i32      0
 #define TCG_TARGET_HAS_div_i32          1
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 4dd33c73e8..49ff9c8b9d 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -113,6 +113,20 @@ static const int tcg_target_call_iarg_regs[] = {
     TCG_REG_A7,
 };
 
+#ifndef have_zbb
+bool have_zbb;
+#endif
+#if defined(__riscv_arch_test) && defined(__riscv_zba)
+# define have_zba true
+#else
+static bool have_zba;
+#endif
+#if defined(__riscv_arch_test) && defined(__riscv_zicond)
+# define have_zicond true
+#else
+static bool have_zicond;
+#endif
+
 static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
 {
     tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
@@ -234,6 +248,34 @@ typedef enum {
 
     OPC_FENCE = 0x0000000f,
     OPC_NOP   = OPC_ADDI,   /* nop = addi r0,r0,0 */
+
+    /* Zba: Bit manipulation extension, address generation */
+    OPC_ADD_UW = 0x0800003b,
+
+    /* Zbb: Bit manipulation extension, basic bit manipulaton */
+    OPC_ANDN   = 0x40007033,
+    OPC_CLZ    = 0x60001013,
+    OPC_CLZW   = 0x6000101b,
+    OPC_CPOP   = 0x60201013,
+    OPC_CPOPW  = 0x6020101b,
+    OPC_CTZ    = 0x60101013,
+    OPC_CTZW   = 0x6010101b,
+    OPC_ORN    = 0x40006033,
+    OPC_REV8   = 0x6b805013,
+    OPC_ROL    = 0x60001033,
+    OPC_ROLW   = 0x6000103b,
+    OPC_ROR    = 0x60005033,
+    OPC_RORW   = 0x6000503b,
+    OPC_RORI   = 0x60005013,
+    OPC_RORIW  = 0x6000501b,
+    OPC_SEXT_B = 0x60401013,
+    OPC_SEXT_H = 0x60501013,
+    OPC_XNOR   = 0x40004033,
+    OPC_ZEXT_H = 0x0800403b,
+
+    /* Zicond: integer conditional operations */
+    OPC_CZERO_EQZ = 0x0e005033,
+    OPC_CZERO_NEZ = 0x0e007033,
 } RISCVInsn;
 
 /*
@@ -1612,8 +1654,62 @@ static void tcg_target_qemu_prologue(TCGContext *s)
     tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
 }
 
+static volatile sig_atomic_t got_sigill;
+
+static void sigill_handler(int signo, siginfo_t *si, void *data)
+{
+    /* Skip the faulty instruction */
+    ucontext_t *uc = (ucontext_t *)data;
+    uc->uc_mcontext.__gregs[REG_PC] += 4;
+
+    got_sigill = 1;
+}
+
+static void tcg_target_detect_isa(void)
+{
+#if !defined(have_zba) || !defined(have_zbb) || !defined(have_zicond)
+    /*
+     * TODO: It is expected that this will be determinable via
+     * linux riscv_hwprobe syscall, not yet merged.
+     * In the meantime, test via sigill.
+     */
+
+    struct sigaction sa_old, sa_new;
+
+    memset(&sa_new, 0, sizeof(sa_new));
+    sa_new.sa_flags = SA_SIGINFO;
+    sa_new.sa_sigaction = sigill_handler;
+    sigaction(SIGILL, &sa_new, &sa_old);
+
+#ifndef have_zba
+    /* Probe for Zba: add.uw zero,zero,zero. */
+    got_sigill = 0;
+    asm volatile(".insn %0" : : "i"(OPC_ADD_UW) : "memory");
+    have_zba = !got_sigill;
+#endif
+
+#ifndef have_zbb
+    /* Probe for Zba: andn zero,zero,zero. */
+    got_sigill = 0;
+    asm volatile(".insn %0" : : "i"(OPC_ANDN) : "memory");
+    have_zbb = !got_sigill;
+#endif
+
+#ifndef have_zicond
+    /* Probe for Zicond: czero.eqz zero,zero,zero. */
+    got_sigill = 0;
+    asm volatile(".insn %0" : : "i"(OPC_CZERO_EQZ) : "memory");
+    have_zicond = !got_sigill;
+#endif
+
+    sigaction(SIGILL, &sa_old, NULL);
+#endif
+}
+
 static void tcg_target_init(TCGContext *s)
 {
+    tcg_target_detect_isa();
+
     tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
     tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
 
-- 
2.34.1



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

* [PATCH 03/11] tcg/riscv: Support ANDN, ORN, XNOR from Zbb
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
  2023-05-03  8:56 ` [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez} Richard Henderson
  2023-05-03  8:56 ` [PATCH 02/11] tcg/riscv: Probe for Zba, Zbb, Zicond extensions Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:37   ` Daniel Henrique Barboza
  2023-05-16 23:38   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 04/11] tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb Richard Henderson
                   ` (8 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target-con-set.h |  1 +
 tcg/riscv/tcg-target-con-str.h |  1 +
 tcg/riscv/tcg-target.h         | 12 +++++-----
 tcg/riscv/tcg-target.c.inc     | 41 ++++++++++++++++++++++++++++++++++
 4 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
index d88888d3ac..1a33ece98f 100644
--- a/tcg/riscv/tcg-target-con-set.h
+++ b/tcg/riscv/tcg-target-con-set.h
@@ -15,6 +15,7 @@ C_O0_I2(rZ, rZ)
 C_O1_I1(r, r)
 C_O1_I2(r, r, ri)
 C_O1_I2(r, r, rI)
+C_O1_I2(r, r, rJ)
 C_O1_I2(r, rZ, rN)
 C_O1_I2(r, rZ, rZ)
 C_O2_I4(r, r, rZ, rZ, rM, rM)
diff --git a/tcg/riscv/tcg-target-con-str.h b/tcg/riscv/tcg-target-con-str.h
index 6f1cfb976c..d5c419dff1 100644
--- a/tcg/riscv/tcg-target-con-str.h
+++ b/tcg/riscv/tcg-target-con-str.h
@@ -15,6 +15,7 @@ REGS('r', ALL_GENERAL_REGS)
  * CONST(letter, TCG_CT_CONST_* bit set)
  */
 CONST('I', TCG_CT_CONST_S12)
+CONST('J', TCG_CT_CONST_J12)
 CONST('N', TCG_CT_CONST_N12)
 CONST('M', TCG_CT_CONST_M12)
 CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index 863ac8ba2f..9f58d46208 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -120,9 +120,9 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_bswap32_i32      0
 #define TCG_TARGET_HAS_not_i32          1
 #define TCG_TARGET_HAS_neg_i32          1
-#define TCG_TARGET_HAS_andc_i32         0
-#define TCG_TARGET_HAS_orc_i32          0
-#define TCG_TARGET_HAS_eqv_i32          0
+#define TCG_TARGET_HAS_andc_i32         have_zbb
+#define TCG_TARGET_HAS_orc_i32          have_zbb
+#define TCG_TARGET_HAS_eqv_i32          have_zbb
 #define TCG_TARGET_HAS_nand_i32         0
 #define TCG_TARGET_HAS_nor_i32          0
 #define TCG_TARGET_HAS_clz_i32          0
@@ -154,9 +154,9 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_bswap64_i64      0
 #define TCG_TARGET_HAS_not_i64          1
 #define TCG_TARGET_HAS_neg_i64          1
-#define TCG_TARGET_HAS_andc_i64         0
-#define TCG_TARGET_HAS_orc_i64          0
-#define TCG_TARGET_HAS_eqv_i64          0
+#define TCG_TARGET_HAS_andc_i64         have_zbb
+#define TCG_TARGET_HAS_orc_i64          have_zbb
+#define TCG_TARGET_HAS_eqv_i64          have_zbb
 #define TCG_TARGET_HAS_nand_i64         0
 #define TCG_TARGET_HAS_nor_i64          0
 #define TCG_TARGET_HAS_clz_i64          0
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 49ff9c8b9d..c5b060023f 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -138,6 +138,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
 #define TCG_CT_CONST_S12   0x200
 #define TCG_CT_CONST_N12   0x400
 #define TCG_CT_CONST_M12   0x800
+#define TCG_CT_CONST_J12  0x1000
 
 #define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
 
@@ -174,6 +175,13 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
     if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
         return 1;
     }
+    /*
+     * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff].
+     * Used to map ANDN back to ANDI, etc.
+     */
+    if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) {
+        return 1;
+    }
     return 0;
 }
 
@@ -1306,6 +1314,31 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
         }
         break;
 
+    case INDEX_op_andc_i32:
+    case INDEX_op_andc_i64:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2);
+        } else {
+            tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2);
+        }
+        break;
+    case INDEX_op_orc_i32:
+    case INDEX_op_orc_i64:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2);
+        } else {
+            tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2);
+        }
+        break;
+    case INDEX_op_eqv_i32:
+    case INDEX_op_eqv_i64:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2);
+        } else {
+            tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2);
+        }
+        break;
+
     case INDEX_op_not_i32:
     case INDEX_op_not_i64:
         tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
@@ -1536,6 +1569,14 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_xor_i64:
         return C_O1_I2(r, r, rI);
 
+    case INDEX_op_andc_i32:
+    case INDEX_op_andc_i64:
+    case INDEX_op_orc_i32:
+    case INDEX_op_orc_i64:
+    case INDEX_op_eqv_i32:
+    case INDEX_op_eqv_i64:
+        return C_O1_I2(r, r, rJ);
+
     case INDEX_op_sub_i32:
     case INDEX_op_sub_i64:
         return C_O1_I2(r, rZ, rN);
-- 
2.34.1



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

* [PATCH 04/11] tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (2 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 03/11] tcg/riscv: Support ANDN, ORN, XNOR from Zbb Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:39   ` Daniel Henrique Barboza
  2023-05-16 23:40   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 05/11] tcg/riscv: Use ADD.UW for guest address generation Richard Henderson
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target.c.inc | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index c5b060023f..53a7f97b29 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -593,26 +593,42 @@ static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
 
 static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
 {
-    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
-    tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
+    if (have_zbb) {
+        tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO);
+    } else {
+        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
+        tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
+    }
 }
 
 static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
 {
-    tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
-    tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
+    if (have_zba) {
+        tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO);
+    } else {
+        tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
+        tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
+    }
 }
 
 static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
-    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
-    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
+    if (have_zbb) {
+        tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0);
+    } else {
+        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
+        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
+    }
 }
 
 static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
-    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
-    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
+    if (have_zbb) {
+        tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0);
+    } else {
+        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
+        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
+    }
 }
 
 static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
-- 
2.34.1



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

* [PATCH 05/11] tcg/riscv: Use ADD.UW for guest address generation
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (3 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 04/11] tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:43   ` Daniel Henrique Barboza
  2023-05-16 23:43   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 06/11] tcg/riscv: Support rotates from Zbb Richard Henderson
                   ` (6 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

The instruction is a combined zero-extend and add.
Use it for exactly that.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target.c.inc | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 53a7f97b29..f64eaa8515 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -1039,14 +1039,18 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
     tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
 
     /* TLB Hit - translate address using addend.  */
-    addr_adj = addr_reg;
-    if (TARGET_LONG_BITS == 32) {
-        addr_adj = TCG_REG_TMP0;
-        tcg_out_ext32u(s, addr_adj, addr_reg);
+    if (TARGET_LONG_BITS == 64) {
+        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
+    } else if (have_zba) {
+        tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
+    } else {
+        tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
+        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, TCG_REG_TMP2);
     }
-    tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP2, addr_adj);
     *pbase = TCG_REG_TMP0;
 #else
+    TCGReg base;
+
     if (a_mask) {
         ldst = new_ldst_label(s);
         ldst->is_ld = is_ld;
@@ -1061,14 +1065,21 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
         tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
     }
 
-    TCGReg base = addr_reg;
-    if (TARGET_LONG_BITS == 32) {
-        tcg_out_ext32u(s, TCG_REG_TMP0, base);
-        base = TCG_REG_TMP0;
-    }
     if (guest_base != 0) {
-        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_GUEST_BASE_REG, base);
         base = TCG_REG_TMP0;
+        if (TARGET_LONG_BITS == 64) {
+            tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, TCG_GUEST_BASE_REG);
+        } else if (have_zba) {
+            tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, TCG_GUEST_BASE_REG);
+        } else {
+            tcg_out_ext32u(s, base, addr_reg);
+            tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
+        }
+    } else if (TARGET_LONG_BITS == 64) {
+        base = addr_reg;
+    } else {
+        base = TCG_REG_TMP0;
+        tcg_out_ext32u(s, base, addr_reg);
     }
     *pbase = base;
 #endif
-- 
2.34.1



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

* [PATCH 06/11] tcg/riscv: Support rotates from Zbb
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (4 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 05/11] tcg/riscv: Use ADD.UW for guest address generation Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:44   ` Daniel Henrique Barboza
  2023-05-16 23:48   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 07/11] tcg/riscv: Support REV8 " Richard Henderson
                   ` (5 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target.h     |  4 ++--
 tcg/riscv/tcg-target.c.inc | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index 9f58d46208..317d385924 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -101,7 +101,7 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_div_i32          1
 #define TCG_TARGET_HAS_rem_i32          1
 #define TCG_TARGET_HAS_div2_i32         0
-#define TCG_TARGET_HAS_rot_i32          0
+#define TCG_TARGET_HAS_rot_i32          have_zbb
 #define TCG_TARGET_HAS_deposit_i32      0
 #define TCG_TARGET_HAS_extract_i32      0
 #define TCG_TARGET_HAS_sextract_i32     0
@@ -136,7 +136,7 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_div_i64          1
 #define TCG_TARGET_HAS_rem_i64          1
 #define TCG_TARGET_HAS_div2_i64         0
-#define TCG_TARGET_HAS_rot_i64          0
+#define TCG_TARGET_HAS_rot_i64          have_zbb
 #define TCG_TARGET_HAS_deposit_i64      0
 #define TCG_TARGET_HAS_extract_i64      0
 #define TCG_TARGET_HAS_sextract_i64     0
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index f64eaa8515..58f969b4fe 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -1458,6 +1458,36 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
         }
         break;
 
+    case INDEX_op_rotl_i32:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f);
+        } else {
+            tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2);
+        }
+        break;
+    case INDEX_op_rotl_i64:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f);
+        } else {
+            tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2);
+        }
+        break;
+
+    case INDEX_op_rotr_i32:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f);
+        } else {
+            tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2);
+        }
+        break;
+    case INDEX_op_rotr_i64:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f);
+        } else {
+            tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2);
+        }
+        break;
+
     case INDEX_op_add2_i32:
         tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
                         const_args[4], const_args[5], false, true);
@@ -1629,9 +1659,13 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_shl_i32:
     case INDEX_op_shr_i32:
     case INDEX_op_sar_i32:
+    case INDEX_op_rotl_i32:
+    case INDEX_op_rotr_i32:
     case INDEX_op_shl_i64:
     case INDEX_op_shr_i64:
     case INDEX_op_sar_i64:
+    case INDEX_op_rotl_i64:
+    case INDEX_op_rotr_i64:
         return C_O1_I2(r, r, ri);
 
     case INDEX_op_brcond_i32:
-- 
2.34.1



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

* [PATCH 07/11] tcg/riscv: Support REV8 from Zbb
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (5 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 06/11] tcg/riscv: Support rotates from Zbb Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:45   ` Daniel Henrique Barboza
  2023-05-16 23:50   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 08/11] tcg/riscv: Support CPOP " Richard Henderson
                   ` (4 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target.h     | 10 +++++-----
 tcg/riscv/tcg-target.c.inc | 29 +++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index 317d385924..8e327afc3a 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -116,8 +116,8 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_ext16s_i32       1
 #define TCG_TARGET_HAS_ext8u_i32        1
 #define TCG_TARGET_HAS_ext16u_i32       1
-#define TCG_TARGET_HAS_bswap16_i32      0
-#define TCG_TARGET_HAS_bswap32_i32      0
+#define TCG_TARGET_HAS_bswap16_i32      have_zbb
+#define TCG_TARGET_HAS_bswap32_i32      have_zbb
 #define TCG_TARGET_HAS_not_i32          1
 #define TCG_TARGET_HAS_neg_i32          1
 #define TCG_TARGET_HAS_andc_i32         have_zbb
@@ -149,9 +149,9 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_ext8u_i64        1
 #define TCG_TARGET_HAS_ext16u_i64       1
 #define TCG_TARGET_HAS_ext32u_i64       1
-#define TCG_TARGET_HAS_bswap16_i64      0
-#define TCG_TARGET_HAS_bswap32_i64      0
-#define TCG_TARGET_HAS_bswap64_i64      0
+#define TCG_TARGET_HAS_bswap16_i64      have_zbb
+#define TCG_TARGET_HAS_bswap32_i64      have_zbb
+#define TCG_TARGET_HAS_bswap64_i64      have_zbb
 #define TCG_TARGET_HAS_not_i64          1
 #define TCG_TARGET_HAS_neg_i64          1
 #define TCG_TARGET_HAS_andc_i64         have_zbb
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 58f969b4fe..9cbefb2833 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -1488,6 +1488,30 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
         }
         break;
 
+    case INDEX_op_bswap64_i64:
+        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
+        break;
+    case INDEX_op_bswap32_i32:
+        a2 = 0;
+        /* fall through */
+    case INDEX_op_bswap32_i64:
+        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
+        if (a2 & TCG_BSWAP_OZ) {
+            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32);
+        } else {
+            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32);
+        }
+        break;
+    case INDEX_op_bswap16_i64:
+    case INDEX_op_bswap16_i32:
+        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
+        if (a2 & TCG_BSWAP_OZ) {
+            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48);
+        } else {
+            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48);
+        }
+        break;
+
     case INDEX_op_add2_i32:
         tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
                         const_args[4], const_args[5], false, true);
@@ -1605,6 +1629,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_extrl_i64_i32:
     case INDEX_op_extrh_i64_i32:
     case INDEX_op_ext_i32_i64:
+    case INDEX_op_bswap16_i32:
+    case INDEX_op_bswap32_i32:
+    case INDEX_op_bswap16_i64:
+    case INDEX_op_bswap32_i64:
+    case INDEX_op_bswap64_i64:
         return C_O1_I1(r, r);
 
     case INDEX_op_st8_i32:
-- 
2.34.1



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

* [PATCH 08/11] tcg/riscv: Support CPOP from Zbb
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (6 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 07/11] tcg/riscv: Support REV8 " Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:45   ` Daniel Henrique Barboza
  2023-05-16 23:50   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 09/11] tcg/riscv: Improve setcond expansion Richard Henderson
                   ` (3 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target.h     | 4 ++--
 tcg/riscv/tcg-target.c.inc | 9 +++++++++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index 8e327afc3a..e0b23006c4 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -127,7 +127,7 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_nor_i32          0
 #define TCG_TARGET_HAS_clz_i32          0
 #define TCG_TARGET_HAS_ctz_i32          0
-#define TCG_TARGET_HAS_ctpop_i32        0
+#define TCG_TARGET_HAS_ctpop_i32        have_zbb
 #define TCG_TARGET_HAS_brcond2          1
 #define TCG_TARGET_HAS_setcond2         1
 #define TCG_TARGET_HAS_qemu_st8_i32     0
@@ -161,7 +161,7 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_nor_i64          0
 #define TCG_TARGET_HAS_clz_i64          0
 #define TCG_TARGET_HAS_ctz_i64          0
-#define TCG_TARGET_HAS_ctpop_i64        0
+#define TCG_TARGET_HAS_ctpop_i64        have_zbb
 #define TCG_TARGET_HAS_add2_i64         1
 #define TCG_TARGET_HAS_sub2_i64         1
 #define TCG_TARGET_HAS_mulu2_i64        0
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 9cbefb2833..044ddfb160 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -1512,6 +1512,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
         }
         break;
 
+    case INDEX_op_ctpop_i32:
+        tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0);
+        break;
+    case INDEX_op_ctpop_i64:
+        tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
+        break;
+
     case INDEX_op_add2_i32:
         tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
                         const_args[4], const_args[5], false, true);
@@ -1634,6 +1641,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_bswap16_i64:
     case INDEX_op_bswap32_i64:
     case INDEX_op_bswap64_i64:
+    case INDEX_op_ctpop_i32:
+    case INDEX_op_ctpop_i64:
         return C_O1_I1(r, r);
 
     case INDEX_op_st8_i32:
-- 
2.34.1



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

* [PATCH 09/11] tcg/riscv: Improve setcond expansion
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (7 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 08/11] tcg/riscv: Support CPOP " Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:46   ` Daniel Henrique Barboza
  2023-05-17  0:16   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 10/11] tcg/riscv: Implement movcond Richard Henderson
                   ` (2 subsequent siblings)
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Split out a helper function, tcg_out_setcond_int, which does not
always produce the complete boolean result, but returns a set of
flags to do so.

Based on 21af16198425, the same improvement for loongarch64.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target.c.inc | 164 +++++++++++++++++++++++++++----------
 1 file changed, 121 insertions(+), 43 deletions(-)

diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 044ddfb160..84b646105c 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -812,50 +812,128 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
     tcg_out_opc_branch(s, op, arg1, arg2, 0);
 }
 
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
-                            TCGReg arg1, TCGReg arg2)
+#define SETCOND_INV    TCG_TARGET_NB_REGS
+#define SETCOND_NEZ    (SETCOND_INV << 1)
+#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
+
+static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
+                               TCGReg arg1, tcg_target_long arg2, bool c2)
 {
+    int flags = 0;
+
     switch (cond) {
-    case TCG_COND_EQ:
-        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
-        tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
-        break;
-    case TCG_COND_NE:
-        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
-        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
-        break;
-    case TCG_COND_LT:
-        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
-        break;
-    case TCG_COND_GE:
-        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
-        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
-        break;
-    case TCG_COND_LE:
-        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
-        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
-        break;
-    case TCG_COND_GT:
-        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
-        break;
-    case TCG_COND_LTU:
-        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
-        break;
-    case TCG_COND_GEU:
-        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
-        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
-        break;
-    case TCG_COND_LEU:
-        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
-        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
-        break;
-    case TCG_COND_GTU:
-        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
+    case TCG_COND_EQ:    /* -> NE  */
+    case TCG_COND_GE:    /* -> LT  */
+    case TCG_COND_GEU:   /* -> LTU */
+    case TCG_COND_GT:    /* -> LE  */
+    case TCG_COND_GTU:   /* -> LEU */
+        cond = tcg_invert_cond(cond);
+        flags ^= SETCOND_INV;
         break;
     default:
-         g_assert_not_reached();
-         break;
-     }
+        break;
+    }
+
+    switch (cond) {
+    case TCG_COND_LE:
+    case TCG_COND_LEU:
+        /*
+         * If we have a constant input, the most efficient way to implement
+         * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
+         * We don't need to care for this for LE because the constant input
+         * is constrained to signed 12-bit, and 0x800 is representable in the
+         * temporary register.
+         */
+        if (c2) {
+            if (cond == TCG_COND_LEU) {
+                /* unsigned <= -1 is true */
+                if (arg2 == -1) {
+                    tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
+                    return ret;
+                }
+                cond = TCG_COND_LTU;
+            } else {
+                cond = TCG_COND_LT;
+            }
+            tcg_debug_assert(arg2 <= 0x7ff);
+            if (++arg2 == 0x800) {
+                tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
+                arg2 = TCG_REG_TMP0;
+                c2 = false;
+            }
+        } else {
+            TCGReg tmp = arg2;
+            arg2 = arg1;
+            arg1 = tmp;
+            cond = tcg_swap_cond(cond);    /* LE -> GE */
+            cond = tcg_invert_cond(cond);  /* GE -> LT */
+            flags ^= SETCOND_INV;
+        }
+        break;
+    default:
+        break;
+    }
+
+    switch (cond) {
+    case TCG_COND_NE:
+        flags |= SETCOND_NEZ;
+        if (!c2) {
+            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
+        } else if (arg2 == 0) {
+            ret = arg1;
+        } else {
+            tcg_out_opc_reg(s, OPC_XORI, ret, arg1, arg2);
+        }
+        break;
+
+    case TCG_COND_LT:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
+        } else {
+            tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
+        }
+        break;
+
+    case TCG_COND_LTU:
+        if (c2) {
+            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2);
+        } else {
+            tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
+        }
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
+
+    return ret | flags;
+}
+
+static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
+                            TCGReg arg1, tcg_target_long arg2, bool c2)
+{
+    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
+
+    if (tmpflags != ret) {
+        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
+
+        switch (tmpflags & SETCOND_FLAGS) {
+        case SETCOND_INV:
+            /* Intermediate result is boolean: simply invert. */
+            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
+            break;
+        case SETCOND_NEZ:
+            /* Intermediate result is zero/non-zero: test != 0. */
+            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
+            break;
+        case SETCOND_NEZ | SETCOND_INV:
+            /* Intermediate result is zero/non-zero: test == 0. */
+            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
+            break;
+        default:
+            g_assert_not_reached();
+        }
+    }
 }
 
 static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
@@ -1543,7 +1621,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 
     case INDEX_op_setcond_i32:
     case INDEX_op_setcond_i64:
-        tcg_out_setcond(s, args[3], a0, a1, a2);
+        tcg_out_setcond(s, args[3], a0, a1, a2, c2);
         break;
 
     case INDEX_op_qemu_ld_i32:
@@ -1662,6 +1740,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_and_i64:
     case INDEX_op_or_i64:
     case INDEX_op_xor_i64:
+    case INDEX_op_setcond_i32:
+    case INDEX_op_setcond_i64:
         return C_O1_I2(r, r, rI);
 
     case INDEX_op_andc_i32:
@@ -1683,7 +1763,6 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_divu_i32:
     case INDEX_op_rem_i32:
     case INDEX_op_remu_i32:
-    case INDEX_op_setcond_i32:
     case INDEX_op_mul_i64:
     case INDEX_op_mulsh_i64:
     case INDEX_op_muluh_i64:
@@ -1691,7 +1770,6 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_divu_i64:
     case INDEX_op_rem_i64:
     case INDEX_op_remu_i64:
-    case INDEX_op_setcond_i64:
         return C_O1_I2(r, rZ, rZ);
 
     case INDEX_op_shl_i32:
-- 
2.34.1



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

* [PATCH 10/11] tcg/riscv: Implement movcond
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (8 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 09/11] tcg/riscv: Improve setcond expansion Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:47   ` Daniel Henrique Barboza
  2023-05-17  0:19   ` Alistair Francis
  2023-05-03  8:56 ` [PATCH 11/11] tcg/riscv: Support CTZ, CLZ from Zbb Richard Henderson
  2023-05-08 12:53 ` [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Daniel Henrique Barboza
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Implement with and without Zicond.  Without Zicond, we were letting
the middle-end expand to a 5 insn sequence; better to use a branch
over a single insn.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target-con-set.h |   1 +
 tcg/riscv/tcg-target.h         |   4 +-
 tcg/riscv/tcg-target.c.inc     | 139 ++++++++++++++++++++++++++++++++-
 3 files changed, 141 insertions(+), 3 deletions(-)

diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
index 1a33ece98f..a5cadd303f 100644
--- a/tcg/riscv/tcg-target-con-set.h
+++ b/tcg/riscv/tcg-target-con-set.h
@@ -18,4 +18,5 @@ C_O1_I2(r, r, rI)
 C_O1_I2(r, r, rJ)
 C_O1_I2(r, rZ, rN)
 C_O1_I2(r, rZ, rZ)
+C_O1_I4(r, r, rI, rM, rM)
 C_O2_I4(r, r, rZ, rZ, rM, rM)
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index e0b23006c4..e9e84be9a5 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -97,7 +97,7 @@ extern bool have_zbb;
 #endif
 
 /* optional instructions */
-#define TCG_TARGET_HAS_movcond_i32      0
+#define TCG_TARGET_HAS_movcond_i32      1
 #define TCG_TARGET_HAS_div_i32          1
 #define TCG_TARGET_HAS_rem_i32          1
 #define TCG_TARGET_HAS_div2_i32         0
@@ -132,7 +132,7 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_setcond2         1
 #define TCG_TARGET_HAS_qemu_st8_i32     0
 
-#define TCG_TARGET_HAS_movcond_i64      0
+#define TCG_TARGET_HAS_movcond_i64      1
 #define TCG_TARGET_HAS_div_i64          1
 #define TCG_TARGET_HAS_rem_i64          1
 #define TCG_TARGET_HAS_div2_i64         0
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 84b646105c..1c57b64182 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -169,7 +169,7 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
     }
     /*
      * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff].
-     * Used by addsub2, which may need the negative operation,
+     * Used by addsub2 and movcond, which may need the negative value,
      * and requires the modified constant to be representable.
      */
     if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
@@ -936,6 +936,133 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
     }
 }
 
+static void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
+                                   int val1, bool c_val1,
+                                   int val2, bool c_val2)
+{
+    if (val1 == 0) {
+        if (c_val2) {
+            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2);
+            val2 = TCG_REG_TMP1;
+        }
+        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne);
+        return;
+    }
+
+    if (val2 == 0) {
+        if (c_val1) {
+            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1);
+            val1 = TCG_REG_TMP1;
+        }
+        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne);
+        return;
+    }
+
+    if (c_val2) {
+        if (c_val1) {
+            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2);
+        } else {
+            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2);
+        }
+        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne);
+        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2);
+        return;
+    }
+
+    if (c_val1) {
+        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1);
+        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne);
+        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1);
+        return;
+    }
+
+    tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne);
+    tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne);
+    tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1);
+}
+
+static void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret,
+                                TCGReg cmp1, TCGReg cmp2,
+                                int val, bool c_val)
+{
+    RISCVInsn op;
+    int disp = 8;
+
+    tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv));
+    op = tcg_brcond_to_riscv[cond].op;
+    tcg_debug_assert(op != 0);
+
+    if (tcg_brcond_to_riscv[cond].swap) {
+        tcg_out_opc_branch(s, op, cmp2, cmp1, disp);
+    } else {
+        tcg_out_opc_branch(s, op, cmp1, cmp2, disp);
+    }
+    if (c_val) {
+        tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val);
+    } else {
+        tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0);
+    }
+}
+
+static void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret,
+                                TCGReg cmp1, TCGReg cmp2,
+                                int val1, bool c_val1,
+                                int val2, bool c_val2)
+{
+    TCGReg tmp;
+
+    /* TCG optimizer reorders to prefer ret matching val2. */
+    if (!c_val2 && ret == val2) {
+        cond = tcg_invert_cond(cond);
+        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1);
+        return;
+    }
+
+    if (!c_val1 && ret == val1) {
+        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2);
+        return;
+    }
+
+    tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret);
+    if (c_val1) {
+        tcg_out_movi(s, TCG_TYPE_REG, tmp, val1);
+    } else {
+        tcg_out_mov(s, TCG_TYPE_REG, tmp, val1);
+    }
+    tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2);
+    tcg_out_mov(s, TCG_TYPE_REG, ret, tmp);
+}
+
+static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
+                            TCGReg cmp1, int cmp2, bool c_cmp2,
+                            TCGReg val1, bool c_val1,
+                            TCGReg val2, bool c_val2)
+{
+    int tmpflags;
+    TCGReg t;
+
+    if (!have_zicond && (!c_cmp2 || cmp2 == 0)) {
+        tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
+                            val1, c_val1, val2, c_val2);
+        return;
+    }
+
+    tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2);
+    t = tmpflags & ~SETCOND_FLAGS;
+
+    if (have_zicond) {
+        if (tmpflags & SETCOND_INV) {
+            tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1);
+        } else {
+            tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2);
+        }
+    } else {
+        cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE;
+        tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO,
+                            val1, c_val1, val2, c_val2);
+    }
+}
+
 static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
 {
     TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
@@ -1624,6 +1751,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_setcond(s, args[3], a0, a1, a2, c2);
         break;
 
+    case INDEX_op_movcond_i32:
+    case INDEX_op_movcond_i64:
+        tcg_out_movcond(s, args[5], a0, a1, a2, c2,
+                        args[3], const_args[3], args[4], const_args[4]);
+        break;
+
     case INDEX_op_qemu_ld_i32:
         tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
         break;
@@ -1788,6 +1921,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_brcond_i64:
         return C_O0_I2(rZ, rZ);
 
+    case INDEX_op_movcond_i32:
+    case INDEX_op_movcond_i64:
+        return C_O1_I4(r, r, rI, rM, rM);
+
     case INDEX_op_add2_i32:
     case INDEX_op_add2_i64:
     case INDEX_op_sub2_i32:
-- 
2.34.1



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

* [PATCH 11/11] tcg/riscv: Support CTZ, CLZ from Zbb
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (9 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 10/11] tcg/riscv: Implement movcond Richard Henderson
@ 2023-05-03  8:56 ` Richard Henderson
  2023-05-08 12:47   ` Daniel Henrique Barboza
  2023-05-17  1:47   ` Alistair Francis
  2023-05-08 12:53 ` [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Daniel Henrique Barboza
  11 siblings, 2 replies; 35+ messages in thread
From: Richard Henderson @ 2023-05-03  8:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: dbarboza

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target-con-set.h |  1 +
 tcg/riscv/tcg-target.h         |  8 ++++----
 tcg/riscv/tcg-target.c.inc     | 35 ++++++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
index a5cadd303f..aac5ceee2b 100644
--- a/tcg/riscv/tcg-target-con-set.h
+++ b/tcg/riscv/tcg-target-con-set.h
@@ -18,5 +18,6 @@ C_O1_I2(r, r, rI)
 C_O1_I2(r, r, rJ)
 C_O1_I2(r, rZ, rN)
 C_O1_I2(r, rZ, rZ)
+C_N1_I2(r, r, rM)
 C_O1_I4(r, r, rI, rM, rM)
 C_O2_I4(r, r, rZ, rZ, rM, rM)
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index e9e84be9a5..cff5de5c9e 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -125,8 +125,8 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_eqv_i32          have_zbb
 #define TCG_TARGET_HAS_nand_i32         0
 #define TCG_TARGET_HAS_nor_i32          0
-#define TCG_TARGET_HAS_clz_i32          0
-#define TCG_TARGET_HAS_ctz_i32          0
+#define TCG_TARGET_HAS_clz_i32          1
+#define TCG_TARGET_HAS_ctz_i32          1
 #define TCG_TARGET_HAS_ctpop_i32        have_zbb
 #define TCG_TARGET_HAS_brcond2          1
 #define TCG_TARGET_HAS_setcond2         1
@@ -159,8 +159,8 @@ extern bool have_zbb;
 #define TCG_TARGET_HAS_eqv_i64          have_zbb
 #define TCG_TARGET_HAS_nand_i64         0
 #define TCG_TARGET_HAS_nor_i64          0
-#define TCG_TARGET_HAS_clz_i64          0
-#define TCG_TARGET_HAS_ctz_i64          0
+#define TCG_TARGET_HAS_clz_i64          1
+#define TCG_TARGET_HAS_ctz_i64          1
 #define TCG_TARGET_HAS_ctpop_i64        have_zbb
 #define TCG_TARGET_HAS_add2_i64         1
 #define TCG_TARGET_HAS_sub2_i64         1
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 1c57b64182..a1c92b0603 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -1063,6 +1063,22 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
     }
 }
 
+static void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn,
+                         TCGReg ret, TCGReg src1, int src2, bool c_src2)
+{
+    tcg_out_opc_imm(s, insn, ret, src1, 0);
+
+    if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) {
+        /*
+         * The requested zero result does not match the insn, so adjust.
+         * Note that constraints put 'ret' in a new register, so the
+         * computation above did not clobber either 'src1' or 'src2'.
+         */
+        tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true,
+                        src2, c_src2, ret, false);
+    }
+}
+
 static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
 {
     TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
@@ -1724,6 +1740,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
         break;
 
+    case INDEX_op_clz_i32:
+        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2);
+        break;
+    case INDEX_op_clz_i64:
+        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2);
+        break;
+    case INDEX_op_ctz_i32:
+        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2);
+        break;
+    case INDEX_op_ctz_i64:
+        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2);
+        break;
+
     case INDEX_op_add2_i32:
         tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
                         const_args[4], const_args[5], false, true);
@@ -1917,6 +1946,12 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_rotr_i64:
         return C_O1_I2(r, r, ri);
 
+    case INDEX_op_clz_i32:
+    case INDEX_op_clz_i64:
+    case INDEX_op_ctz_i32:
+    case INDEX_op_ctz_i64:
+        return C_N1_I2(r, r, rM);
+
     case INDEX_op_brcond_i32:
     case INDEX_op_brcond_i64:
         return C_O0_I2(rZ, rZ);
-- 
2.34.1



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

* Re: [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez}
  2023-05-03  8:56 ` [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez} Richard Henderson
@ 2023-05-08 12:37   ` Daniel Henrique Barboza
  2023-05-16 23:33   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:37 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   disas/riscv.c | 8 +++++++-
>   1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/disas/riscv.c b/disas/riscv.c
> index d6b0fbe5e8..c0a8b1006a 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -935,6 +935,8 @@ typedef enum {
>       rv_op_vsetvli = 766,
>       rv_op_vsetivli = 767,
>       rv_op_vsetvl = 768,
> +    rv_op_czero_eqz = 769,
> +    rv_op_czero_nez = 770,
>   } rv_op;
>   
>   /* structures */
> @@ -2066,7 +2068,9 @@ const rv_opcode_data opcode_data[] = {
>       { "vsext.vf8", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, rv_op_vsext_vf8, rv_op_vsext_vf8, 0 },
>       { "vsetvli", rv_codec_vsetvli, rv_fmt_vsetvli, NULL, rv_op_vsetvli, rv_op_vsetvli, 0 },
>       { "vsetivli", rv_codec_vsetivli, rv_fmt_vsetivli, NULL, rv_op_vsetivli, rv_op_vsetivli, 0 },
> -    { "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 }
> +    { "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 },
> +    { "czero.eqz", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
> +    { "czero.nez", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
>   };
>   
>   /* CSR names */
> @@ -2792,6 +2796,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
>               case 45: op = rv_op_minu; break;
>               case 46: op = rv_op_max; break;
>               case 47: op = rv_op_maxu; break;
> +            case 075: op = rv_op_czero_eqz; break;
> +            case 077: op = rv_op_czero_nez; break;
>               case 130: op = rv_op_sh1add; break;
>               case 132: op = rv_op_sh2add; break;
>               case 134: op = rv_op_sh3add; break;


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

* Re: [PATCH 02/11] tcg/riscv: Probe for Zba, Zbb, Zicond extensions
  2023-05-03  8:56 ` [PATCH 02/11] tcg/riscv: Probe for Zba, Zbb, Zicond extensions Richard Henderson
@ 2023-05-08 12:37   ` Daniel Henrique Barboza
  2023-05-16 23:35   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:37 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Define a useful subset of the extensions.  Probe for them
> via compiler pre-processor feature macros and SIGILL.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target.h     |  6 +++
>   tcg/riscv/tcg-target.c.inc | 96 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 102 insertions(+)
> 
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 494c986b49..863ac8ba2f 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -90,6 +90,12 @@ typedef enum {
>   #define TCG_TARGET_CALL_ARG_I128        TCG_CALL_ARG_NORMAL
>   #define TCG_TARGET_CALL_RET_I128        TCG_CALL_RET_NORMAL
>   
> +#if defined(__riscv_arch_test) && defined(__riscv_zbb)
> +# define have_zbb true
> +#else
> +extern bool have_zbb;
> +#endif
> +
>   /* optional instructions */
>   #define TCG_TARGET_HAS_movcond_i32      0
>   #define TCG_TARGET_HAS_div_i32          1
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 4dd33c73e8..49ff9c8b9d 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -113,6 +113,20 @@ static const int tcg_target_call_iarg_regs[] = {
>       TCG_REG_A7,
>   };
>   
> +#ifndef have_zbb
> +bool have_zbb;
> +#endif
> +#if defined(__riscv_arch_test) && defined(__riscv_zba)
> +# define have_zba true
> +#else
> +static bool have_zba;
> +#endif
> +#if defined(__riscv_arch_test) && defined(__riscv_zicond)
> +# define have_zicond true
> +#else
> +static bool have_zicond;
> +#endif
> +
>   static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
>   {
>       tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
> @@ -234,6 +248,34 @@ typedef enum {
>   
>       OPC_FENCE = 0x0000000f,
>       OPC_NOP   = OPC_ADDI,   /* nop = addi r0,r0,0 */
> +
> +    /* Zba: Bit manipulation extension, address generation */
> +    OPC_ADD_UW = 0x0800003b,
> +
> +    /* Zbb: Bit manipulation extension, basic bit manipulaton */
> +    OPC_ANDN   = 0x40007033,
> +    OPC_CLZ    = 0x60001013,
> +    OPC_CLZW   = 0x6000101b,
> +    OPC_CPOP   = 0x60201013,
> +    OPC_CPOPW  = 0x6020101b,
> +    OPC_CTZ    = 0x60101013,
> +    OPC_CTZW   = 0x6010101b,
> +    OPC_ORN    = 0x40006033,
> +    OPC_REV8   = 0x6b805013,
> +    OPC_ROL    = 0x60001033,
> +    OPC_ROLW   = 0x6000103b,
> +    OPC_ROR    = 0x60005033,
> +    OPC_RORW   = 0x6000503b,
> +    OPC_RORI   = 0x60005013,
> +    OPC_RORIW  = 0x6000501b,
> +    OPC_SEXT_B = 0x60401013,
> +    OPC_SEXT_H = 0x60501013,
> +    OPC_XNOR   = 0x40004033,
> +    OPC_ZEXT_H = 0x0800403b,
> +
> +    /* Zicond: integer conditional operations */
> +    OPC_CZERO_EQZ = 0x0e005033,
> +    OPC_CZERO_NEZ = 0x0e007033,
>   } RISCVInsn;
>   
>   /*
> @@ -1612,8 +1654,62 @@ static void tcg_target_qemu_prologue(TCGContext *s)
>       tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
>   }
>   
> +static volatile sig_atomic_t got_sigill;
> +
> +static void sigill_handler(int signo, siginfo_t *si, void *data)
> +{
> +    /* Skip the faulty instruction */
> +    ucontext_t *uc = (ucontext_t *)data;
> +    uc->uc_mcontext.__gregs[REG_PC] += 4;
> +
> +    got_sigill = 1;
> +}
> +
> +static void tcg_target_detect_isa(void)
> +{
> +#if !defined(have_zba) || !defined(have_zbb) || !defined(have_zicond)
> +    /*
> +     * TODO: It is expected that this will be determinable via
> +     * linux riscv_hwprobe syscall, not yet merged.
> +     * In the meantime, test via sigill.
> +     */
> +
> +    struct sigaction sa_old, sa_new;
> +
> +    memset(&sa_new, 0, sizeof(sa_new));
> +    sa_new.sa_flags = SA_SIGINFO;
> +    sa_new.sa_sigaction = sigill_handler;
> +    sigaction(SIGILL, &sa_new, &sa_old);
> +
> +#ifndef have_zba
> +    /* Probe for Zba: add.uw zero,zero,zero. */
> +    got_sigill = 0;
> +    asm volatile(".insn %0" : : "i"(OPC_ADD_UW) : "memory");
> +    have_zba = !got_sigill;
> +#endif
> +
> +#ifndef have_zbb
> +    /* Probe for Zba: andn zero,zero,zero. */
> +    got_sigill = 0;
> +    asm volatile(".insn %0" : : "i"(OPC_ANDN) : "memory");
> +    have_zbb = !got_sigill;
> +#endif
> +
> +#ifndef have_zicond
> +    /* Probe for Zicond: czero.eqz zero,zero,zero. */
> +    got_sigill = 0;
> +    asm volatile(".insn %0" : : "i"(OPC_CZERO_EQZ) : "memory");
> +    have_zicond = !got_sigill;
> +#endif
> +
> +    sigaction(SIGILL, &sa_old, NULL);
> +#endif
> +}
> +
>   static void tcg_target_init(TCGContext *s)
>   {
> +    tcg_target_detect_isa();
> +
>       tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
>       tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
>   


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

* Re: [PATCH 03/11] tcg/riscv: Support ANDN, ORN, XNOR from Zbb
  2023-05-03  8:56 ` [PATCH 03/11] tcg/riscv: Support ANDN, ORN, XNOR from Zbb Richard Henderson
@ 2023-05-08 12:37   ` Daniel Henrique Barboza
  2023-05-16 23:38   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:37 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target-con-set.h |  1 +
>   tcg/riscv/tcg-target-con-str.h |  1 +
>   tcg/riscv/tcg-target.h         | 12 +++++-----
>   tcg/riscv/tcg-target.c.inc     | 41 ++++++++++++++++++++++++++++++++++
>   4 files changed, 49 insertions(+), 6 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
> index d88888d3ac..1a33ece98f 100644
> --- a/tcg/riscv/tcg-target-con-set.h
> +++ b/tcg/riscv/tcg-target-con-set.h
> @@ -15,6 +15,7 @@ C_O0_I2(rZ, rZ)
>   C_O1_I1(r, r)
>   C_O1_I2(r, r, ri)
>   C_O1_I2(r, r, rI)
> +C_O1_I2(r, r, rJ)
>   C_O1_I2(r, rZ, rN)
>   C_O1_I2(r, rZ, rZ)
>   C_O2_I4(r, r, rZ, rZ, rM, rM)
> diff --git a/tcg/riscv/tcg-target-con-str.h b/tcg/riscv/tcg-target-con-str.h
> index 6f1cfb976c..d5c419dff1 100644
> --- a/tcg/riscv/tcg-target-con-str.h
> +++ b/tcg/riscv/tcg-target-con-str.h
> @@ -15,6 +15,7 @@ REGS('r', ALL_GENERAL_REGS)
>    * CONST(letter, TCG_CT_CONST_* bit set)
>    */
>   CONST('I', TCG_CT_CONST_S12)
> +CONST('J', TCG_CT_CONST_J12)
>   CONST('N', TCG_CT_CONST_N12)
>   CONST('M', TCG_CT_CONST_M12)
>   CONST('Z', TCG_CT_CONST_ZERO)
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 863ac8ba2f..9f58d46208 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -120,9 +120,9 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_bswap32_i32      0
>   #define TCG_TARGET_HAS_not_i32          1
>   #define TCG_TARGET_HAS_neg_i32          1
> -#define TCG_TARGET_HAS_andc_i32         0
> -#define TCG_TARGET_HAS_orc_i32          0
> -#define TCG_TARGET_HAS_eqv_i32          0
> +#define TCG_TARGET_HAS_andc_i32         have_zbb
> +#define TCG_TARGET_HAS_orc_i32          have_zbb
> +#define TCG_TARGET_HAS_eqv_i32          have_zbb
>   #define TCG_TARGET_HAS_nand_i32         0
>   #define TCG_TARGET_HAS_nor_i32          0
>   #define TCG_TARGET_HAS_clz_i32          0
> @@ -154,9 +154,9 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_bswap64_i64      0
>   #define TCG_TARGET_HAS_not_i64          1
>   #define TCG_TARGET_HAS_neg_i64          1
> -#define TCG_TARGET_HAS_andc_i64         0
> -#define TCG_TARGET_HAS_orc_i64          0
> -#define TCG_TARGET_HAS_eqv_i64          0
> +#define TCG_TARGET_HAS_andc_i64         have_zbb
> +#define TCG_TARGET_HAS_orc_i64          have_zbb
> +#define TCG_TARGET_HAS_eqv_i64          have_zbb
>   #define TCG_TARGET_HAS_nand_i64         0
>   #define TCG_TARGET_HAS_nor_i64          0
>   #define TCG_TARGET_HAS_clz_i64          0
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 49ff9c8b9d..c5b060023f 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -138,6 +138,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
>   #define TCG_CT_CONST_S12   0x200
>   #define TCG_CT_CONST_N12   0x400
>   #define TCG_CT_CONST_M12   0x800
> +#define TCG_CT_CONST_J12  0x1000
>   
>   #define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
>   
> @@ -174,6 +175,13 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
>       if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
>           return 1;
>       }
> +    /*
> +     * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff].
> +     * Used to map ANDN back to ANDI, etc.
> +     */
> +    if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) {
> +        return 1;
> +    }
>       return 0;
>   }
>   
> @@ -1306,6 +1314,31 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>           }
>           break;
>   
> +    case INDEX_op_andc_i32:
> +    case INDEX_op_andc_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2);
> +        }
> +        break;
> +    case INDEX_op_orc_i32:
> +    case INDEX_op_orc_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2);
> +        }
> +        break;
> +    case INDEX_op_eqv_i32:
> +    case INDEX_op_eqv_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2);
> +        }
> +        break;
> +
>       case INDEX_op_not_i32:
>       case INDEX_op_not_i64:
>           tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
> @@ -1536,6 +1569,14 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_xor_i64:
>           return C_O1_I2(r, r, rI);
>   
> +    case INDEX_op_andc_i32:
> +    case INDEX_op_andc_i64:
> +    case INDEX_op_orc_i32:
> +    case INDEX_op_orc_i64:
> +    case INDEX_op_eqv_i32:
> +    case INDEX_op_eqv_i64:
> +        return C_O1_I2(r, r, rJ);
> +
>       case INDEX_op_sub_i32:
>       case INDEX_op_sub_i64:
>           return C_O1_I2(r, rZ, rN);


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

* Re: [PATCH 04/11] tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb
  2023-05-03  8:56 ` [PATCH 04/11] tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb Richard Henderson
@ 2023-05-08 12:39   ` Daniel Henrique Barboza
  2023-05-16 23:40   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:39 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---


Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target.c.inc | 32 ++++++++++++++++++++++++--------
>   1 file changed, 24 insertions(+), 8 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index c5b060023f..53a7f97b29 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -593,26 +593,42 @@ static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
>   
>   static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
>   {
> -    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
> -    tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
> +    if (have_zbb) {
> +        tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
> +        tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
> +    }
>   }
>   
>   static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
>   {
> -    tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
> -    tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
> +    if (have_zba) {
> +        tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
> +        tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
> +    }
>   }
>   
>   static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
>   {
> -    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
> -    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
> +    if (have_zbb) {
> +        tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
> +        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
> +    }
>   }
>   
>   static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
>   {
> -    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
> -    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
> +    if (have_zbb) {
> +        tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
> +        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
> +    }
>   }
>   
>   static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)


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

* Re: [PATCH 05/11] tcg/riscv: Use ADD.UW for guest address generation
  2023-05-03  8:56 ` [PATCH 05/11] tcg/riscv: Use ADD.UW for guest address generation Richard Henderson
@ 2023-05-08 12:43   ` Daniel Henrique Barboza
  2023-05-16 23:43   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:43 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> The instruction is a combined zero-extend and add.
> Use it for exactly that.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   tcg/riscv/tcg-target.c.inc | 33 ++++++++++++++++++++++-----------
>   1 file changed, 22 insertions(+), 11 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 53a7f97b29..f64eaa8515 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1039,14 +1039,18 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
>       tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
>   
>       /* TLB Hit - translate address using addend.  */
> -    addr_adj = addr_reg;
> -    if (TARGET_LONG_BITS == 32) {
> -        addr_adj = TCG_REG_TMP0;
> -        tcg_out_ext32u(s, addr_adj, addr_reg);
> +    if (TARGET_LONG_BITS == 64) {
> +        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
> +    } else if (have_zba) {
> +        tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
> +    } else {
> +        tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
> +        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, TCG_REG_TMP2);
>       }
> -    tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP2, addr_adj);
>       *pbase = TCG_REG_TMP0;
>   #else
> +    TCGReg base;
> +
>       if (a_mask) {
>           ldst = new_ldst_label(s);
>           ldst->is_ld = is_ld;
> @@ -1061,14 +1065,21 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
>           tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
>       }
>   
> -    TCGReg base = addr_reg;
> -    if (TARGET_LONG_BITS == 32) {
> -        tcg_out_ext32u(s, TCG_REG_TMP0, base);
> -        base = TCG_REG_TMP0;
> -    }
>       if (guest_base != 0) {
> -        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_GUEST_BASE_REG, base);
>           base = TCG_REG_TMP0;
> +        if (TARGET_LONG_BITS == 64) {
> +            tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, TCG_GUEST_BASE_REG);
> +        } else if (have_zba) {
> +            tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, TCG_GUEST_BASE_REG);
> +        } else {
> +            tcg_out_ext32u(s, base, addr_reg);
> +            tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
> +        }
> +    } else if (TARGET_LONG_BITS == 64) {
> +        base = addr_reg;
> +    } else {
> +        base = TCG_REG_TMP0;
> +        tcg_out_ext32u(s, base, addr_reg);

I tried to find a way to remove some of these IFs but all my alternatives weren't
much better.


Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>


>       }
>       *pbase = base;
>   #endif


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

* Re: [PATCH 06/11] tcg/riscv: Support rotates from Zbb
  2023-05-03  8:56 ` [PATCH 06/11] tcg/riscv: Support rotates from Zbb Richard Henderson
@ 2023-05-08 12:44   ` Daniel Henrique Barboza
  2023-05-16 23:48   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:44 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target.h     |  4 ++--
>   tcg/riscv/tcg-target.c.inc | 34 ++++++++++++++++++++++++++++++++++
>   2 files changed, 36 insertions(+), 2 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 9f58d46208..317d385924 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -101,7 +101,7 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_div_i32          1
>   #define TCG_TARGET_HAS_rem_i32          1
>   #define TCG_TARGET_HAS_div2_i32         0
> -#define TCG_TARGET_HAS_rot_i32          0
> +#define TCG_TARGET_HAS_rot_i32          have_zbb
>   #define TCG_TARGET_HAS_deposit_i32      0
>   #define TCG_TARGET_HAS_extract_i32      0
>   #define TCG_TARGET_HAS_sextract_i32     0
> @@ -136,7 +136,7 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_div_i64          1
>   #define TCG_TARGET_HAS_rem_i64          1
>   #define TCG_TARGET_HAS_div2_i64         0
> -#define TCG_TARGET_HAS_rot_i64          0
> +#define TCG_TARGET_HAS_rot_i64          have_zbb
>   #define TCG_TARGET_HAS_deposit_i64      0
>   #define TCG_TARGET_HAS_extract_i64      0
>   #define TCG_TARGET_HAS_sextract_i64     0
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index f64eaa8515..58f969b4fe 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1458,6 +1458,36 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>           }
>           break;
>   
> +    case INDEX_op_rotl_i32:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2);
> +        }
> +        break;
> +    case INDEX_op_rotl_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2);
> +        }
> +        break;
> +
> +    case INDEX_op_rotr_i32:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2);
> +        }
> +        break;
> +    case INDEX_op_rotr_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2);
> +        }
> +        break;
> +
>       case INDEX_op_add2_i32:
>           tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
>                           const_args[4], const_args[5], false, true);
> @@ -1629,9 +1659,13 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_shl_i32:
>       case INDEX_op_shr_i32:
>       case INDEX_op_sar_i32:
> +    case INDEX_op_rotl_i32:
> +    case INDEX_op_rotr_i32:
>       case INDEX_op_shl_i64:
>       case INDEX_op_shr_i64:
>       case INDEX_op_sar_i64:
> +    case INDEX_op_rotl_i64:
> +    case INDEX_op_rotr_i64:
>           return C_O1_I2(r, r, ri);
>   
>       case INDEX_op_brcond_i32:


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

* Re: [PATCH 07/11] tcg/riscv: Support REV8 from Zbb
  2023-05-03  8:56 ` [PATCH 07/11] tcg/riscv: Support REV8 " Richard Henderson
@ 2023-05-08 12:45   ` Daniel Henrique Barboza
  2023-05-16 23:50   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:45 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target.h     | 10 +++++-----
>   tcg/riscv/tcg-target.c.inc | 29 +++++++++++++++++++++++++++++
>   2 files changed, 34 insertions(+), 5 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 317d385924..8e327afc3a 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -116,8 +116,8 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_ext16s_i32       1
>   #define TCG_TARGET_HAS_ext8u_i32        1
>   #define TCG_TARGET_HAS_ext16u_i32       1
> -#define TCG_TARGET_HAS_bswap16_i32      0
> -#define TCG_TARGET_HAS_bswap32_i32      0
> +#define TCG_TARGET_HAS_bswap16_i32      have_zbb
> +#define TCG_TARGET_HAS_bswap32_i32      have_zbb
>   #define TCG_TARGET_HAS_not_i32          1
>   #define TCG_TARGET_HAS_neg_i32          1
>   #define TCG_TARGET_HAS_andc_i32         have_zbb
> @@ -149,9 +149,9 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_ext8u_i64        1
>   #define TCG_TARGET_HAS_ext16u_i64       1
>   #define TCG_TARGET_HAS_ext32u_i64       1
> -#define TCG_TARGET_HAS_bswap16_i64      0
> -#define TCG_TARGET_HAS_bswap32_i64      0
> -#define TCG_TARGET_HAS_bswap64_i64      0
> +#define TCG_TARGET_HAS_bswap16_i64      have_zbb
> +#define TCG_TARGET_HAS_bswap32_i64      have_zbb
> +#define TCG_TARGET_HAS_bswap64_i64      have_zbb
>   #define TCG_TARGET_HAS_not_i64          1
>   #define TCG_TARGET_HAS_neg_i64          1
>   #define TCG_TARGET_HAS_andc_i64         have_zbb
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 58f969b4fe..9cbefb2833 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1488,6 +1488,30 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>           }
>           break;
>   
> +    case INDEX_op_bswap64_i64:
> +        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
> +        break;
> +    case INDEX_op_bswap32_i32:
> +        a2 = 0;
> +        /* fall through */
> +    case INDEX_op_bswap32_i64:
> +        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
> +        if (a2 & TCG_BSWAP_OZ) {
> +            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32);
> +        } else {
> +            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32);
> +        }
> +        break;
> +    case INDEX_op_bswap16_i64:
> +    case INDEX_op_bswap16_i32:
> +        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
> +        if (a2 & TCG_BSWAP_OZ) {
> +            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48);
> +        } else {
> +            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48);
> +        }
> +        break;
> +
>       case INDEX_op_add2_i32:
>           tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
>                           const_args[4], const_args[5], false, true);
> @@ -1605,6 +1629,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_extrl_i64_i32:
>       case INDEX_op_extrh_i64_i32:
>       case INDEX_op_ext_i32_i64:
> +    case INDEX_op_bswap16_i32:
> +    case INDEX_op_bswap32_i32:
> +    case INDEX_op_bswap16_i64:
> +    case INDEX_op_bswap32_i64:
> +    case INDEX_op_bswap64_i64:
>           return C_O1_I1(r, r);
>   
>       case INDEX_op_st8_i32:


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

* Re: [PATCH 08/11] tcg/riscv: Support CPOP from Zbb
  2023-05-03  8:56 ` [PATCH 08/11] tcg/riscv: Support CPOP " Richard Henderson
@ 2023-05-08 12:45   ` Daniel Henrique Barboza
  2023-05-16 23:50   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:45 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---


Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target.h     | 4 ++--
>   tcg/riscv/tcg-target.c.inc | 9 +++++++++
>   2 files changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 8e327afc3a..e0b23006c4 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -127,7 +127,7 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_nor_i32          0
>   #define TCG_TARGET_HAS_clz_i32          0
>   #define TCG_TARGET_HAS_ctz_i32          0
> -#define TCG_TARGET_HAS_ctpop_i32        0
> +#define TCG_TARGET_HAS_ctpop_i32        have_zbb
>   #define TCG_TARGET_HAS_brcond2          1
>   #define TCG_TARGET_HAS_setcond2         1
>   #define TCG_TARGET_HAS_qemu_st8_i32     0
> @@ -161,7 +161,7 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_nor_i64          0
>   #define TCG_TARGET_HAS_clz_i64          0
>   #define TCG_TARGET_HAS_ctz_i64          0
> -#define TCG_TARGET_HAS_ctpop_i64        0
> +#define TCG_TARGET_HAS_ctpop_i64        have_zbb
>   #define TCG_TARGET_HAS_add2_i64         1
>   #define TCG_TARGET_HAS_sub2_i64         1
>   #define TCG_TARGET_HAS_mulu2_i64        0
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 9cbefb2833..044ddfb160 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1512,6 +1512,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>           }
>           break;
>   
> +    case INDEX_op_ctpop_i32:
> +        tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0);
> +        break;
> +    case INDEX_op_ctpop_i64:
> +        tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
> +        break;
> +
>       case INDEX_op_add2_i32:
>           tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
>                           const_args[4], const_args[5], false, true);
> @@ -1634,6 +1641,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_bswap16_i64:
>       case INDEX_op_bswap32_i64:
>       case INDEX_op_bswap64_i64:
> +    case INDEX_op_ctpop_i32:
> +    case INDEX_op_ctpop_i64:
>           return C_O1_I1(r, r);
>   
>       case INDEX_op_st8_i32:


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

* Re: [PATCH 09/11] tcg/riscv: Improve setcond expansion
  2023-05-03  8:56 ` [PATCH 09/11] tcg/riscv: Improve setcond expansion Richard Henderson
@ 2023-05-08 12:46   ` Daniel Henrique Barboza
  2023-05-17  0:16   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:46 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Split out a helper function, tcg_out_setcond_int, which does not
> always produce the complete boolean result, but returns a set of
> flags to do so.
> 
> Based on 21af16198425, the same improvement for loongarch64.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target.c.inc | 164 +++++++++++++++++++++++++++----------
>   1 file changed, 121 insertions(+), 43 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 044ddfb160..84b646105c 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -812,50 +812,128 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
>       tcg_out_opc_branch(s, op, arg1, arg2, 0);
>   }
>   
> -static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
> -                            TCGReg arg1, TCGReg arg2)
> +#define SETCOND_INV    TCG_TARGET_NB_REGS
> +#define SETCOND_NEZ    (SETCOND_INV << 1)
> +#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
> +
> +static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
> +                               TCGReg arg1, tcg_target_long arg2, bool c2)
>   {
> +    int flags = 0;
> +
>       switch (cond) {
> -    case TCG_COND_EQ:
> -        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
> -        tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
> -        break;
> -    case TCG_COND_NE:
> -        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
> -        break;
> -    case TCG_COND_LT:
> -        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
> -        break;
> -    case TCG_COND_GE:
> -        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
> -        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
> -        break;
> -    case TCG_COND_LE:
> -        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
> -        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
> -        break;
> -    case TCG_COND_GT:
> -        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
> -        break;
> -    case TCG_COND_LTU:
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
> -        break;
> -    case TCG_COND_GEU:
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
> -        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
> -        break;
> -    case TCG_COND_LEU:
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
> -        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
> -        break;
> -    case TCG_COND_GTU:
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
> +    case TCG_COND_EQ:    /* -> NE  */
> +    case TCG_COND_GE:    /* -> LT  */
> +    case TCG_COND_GEU:   /* -> LTU */
> +    case TCG_COND_GT:    /* -> LE  */
> +    case TCG_COND_GTU:   /* -> LEU */
> +        cond = tcg_invert_cond(cond);
> +        flags ^= SETCOND_INV;
>           break;
>       default:
> -         g_assert_not_reached();
> -         break;
> -     }
> +        break;
> +    }
> +
> +    switch (cond) {
> +    case TCG_COND_LE:
> +    case TCG_COND_LEU:
> +        /*
> +         * If we have a constant input, the most efficient way to implement
> +         * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
> +         * We don't need to care for this for LE because the constant input
> +         * is constrained to signed 12-bit, and 0x800 is representable in the
> +         * temporary register.
> +         */
> +        if (c2) {
> +            if (cond == TCG_COND_LEU) {
> +                /* unsigned <= -1 is true */
> +                if (arg2 == -1) {
> +                    tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
> +                    return ret;
> +                }
> +                cond = TCG_COND_LTU;
> +            } else {
> +                cond = TCG_COND_LT;
> +            }
> +            tcg_debug_assert(arg2 <= 0x7ff);
> +            if (++arg2 == 0x800) {
> +                tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
> +                arg2 = TCG_REG_TMP0;
> +                c2 = false;
> +            }
> +        } else {
> +            TCGReg tmp = arg2;
> +            arg2 = arg1;
> +            arg1 = tmp;
> +            cond = tcg_swap_cond(cond);    /* LE -> GE */
> +            cond = tcg_invert_cond(cond);  /* GE -> LT */
> +            flags ^= SETCOND_INV;
> +        }
> +        break;
> +    default:
> +        break;
> +    }
> +
> +    switch (cond) {
> +    case TCG_COND_NE:
> +        flags |= SETCOND_NEZ;
> +        if (!c2) {
> +            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
> +        } else if (arg2 == 0) {
> +            ret = arg1;
> +        } else {
> +            tcg_out_opc_reg(s, OPC_XORI, ret, arg1, arg2);
> +        }
> +        break;
> +
> +    case TCG_COND_LT:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
> +        }
> +        break;
> +
> +    case TCG_COND_LTU:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
> +        }
> +        break;
> +
> +    default:
> +        g_assert_not_reached();
> +    }
> +
> +    return ret | flags;
> +}
> +
> +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
> +                            TCGReg arg1, tcg_target_long arg2, bool c2)
> +{
> +    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
> +
> +    if (tmpflags != ret) {
> +        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
> +
> +        switch (tmpflags & SETCOND_FLAGS) {
> +        case SETCOND_INV:
> +            /* Intermediate result is boolean: simply invert. */
> +            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
> +            break;
> +        case SETCOND_NEZ:
> +            /* Intermediate result is zero/non-zero: test != 0. */
> +            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
> +            break;
> +        case SETCOND_NEZ | SETCOND_INV:
> +            /* Intermediate result is zero/non-zero: test == 0. */
> +            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
> +            break;
> +        default:
> +            g_assert_not_reached();
> +        }
> +    }
>   }
>   
>   static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
> @@ -1543,7 +1621,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>   
>       case INDEX_op_setcond_i32:
>       case INDEX_op_setcond_i64:
> -        tcg_out_setcond(s, args[3], a0, a1, a2);
> +        tcg_out_setcond(s, args[3], a0, a1, a2, c2);
>           break;
>   
>       case INDEX_op_qemu_ld_i32:
> @@ -1662,6 +1740,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_and_i64:
>       case INDEX_op_or_i64:
>       case INDEX_op_xor_i64:
> +    case INDEX_op_setcond_i32:
> +    case INDEX_op_setcond_i64:
>           return C_O1_I2(r, r, rI);
>   
>       case INDEX_op_andc_i32:
> @@ -1683,7 +1763,6 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_divu_i32:
>       case INDEX_op_rem_i32:
>       case INDEX_op_remu_i32:
> -    case INDEX_op_setcond_i32:
>       case INDEX_op_mul_i64:
>       case INDEX_op_mulsh_i64:
>       case INDEX_op_muluh_i64:
> @@ -1691,7 +1770,6 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_divu_i64:
>       case INDEX_op_rem_i64:
>       case INDEX_op_remu_i64:
> -    case INDEX_op_setcond_i64:
>           return C_O1_I2(r, rZ, rZ);
>   
>       case INDEX_op_shl_i32:


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

* Re: [PATCH 10/11] tcg/riscv: Implement movcond
  2023-05-03  8:56 ` [PATCH 10/11] tcg/riscv: Implement movcond Richard Henderson
@ 2023-05-08 12:47   ` Daniel Henrique Barboza
  2023-05-17  0:19   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:47 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Implement with and without Zicond.  Without Zicond, we were letting
> the middle-end expand to a 5 insn sequence; better to use a branch
> over a single insn.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target-con-set.h |   1 +
>   tcg/riscv/tcg-target.h         |   4 +-
>   tcg/riscv/tcg-target.c.inc     | 139 ++++++++++++++++++++++++++++++++-
>   3 files changed, 141 insertions(+), 3 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
> index 1a33ece98f..a5cadd303f 100644
> --- a/tcg/riscv/tcg-target-con-set.h
> +++ b/tcg/riscv/tcg-target-con-set.h
> @@ -18,4 +18,5 @@ C_O1_I2(r, r, rI)
>   C_O1_I2(r, r, rJ)
>   C_O1_I2(r, rZ, rN)
>   C_O1_I2(r, rZ, rZ)
> +C_O1_I4(r, r, rI, rM, rM)
>   C_O2_I4(r, r, rZ, rZ, rM, rM)
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index e0b23006c4..e9e84be9a5 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -97,7 +97,7 @@ extern bool have_zbb;
>   #endif
>   
>   /* optional instructions */
> -#define TCG_TARGET_HAS_movcond_i32      0
> +#define TCG_TARGET_HAS_movcond_i32      1
>   #define TCG_TARGET_HAS_div_i32          1
>   #define TCG_TARGET_HAS_rem_i32          1
>   #define TCG_TARGET_HAS_div2_i32         0
> @@ -132,7 +132,7 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_setcond2         1
>   #define TCG_TARGET_HAS_qemu_st8_i32     0
>   
> -#define TCG_TARGET_HAS_movcond_i64      0
> +#define TCG_TARGET_HAS_movcond_i64      1
>   #define TCG_TARGET_HAS_div_i64          1
>   #define TCG_TARGET_HAS_rem_i64          1
>   #define TCG_TARGET_HAS_div2_i64         0
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 84b646105c..1c57b64182 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -169,7 +169,7 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
>       }
>       /*
>        * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff].
> -     * Used by addsub2, which may need the negative operation,
> +     * Used by addsub2 and movcond, which may need the negative value,
>        * and requires the modified constant to be representable.
>        */
>       if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
> @@ -936,6 +936,133 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
>       }
>   }
>   
> +static void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
> +                                   int val1, bool c_val1,
> +                                   int val2, bool c_val2)
> +{
> +    if (val1 == 0) {
> +        if (c_val2) {
> +            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2);
> +            val2 = TCG_REG_TMP1;
> +        }
> +        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne);
> +        return;
> +    }
> +
> +    if (val2 == 0) {
> +        if (c_val1) {
> +            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1);
> +            val1 = TCG_REG_TMP1;
> +        }
> +        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne);
> +        return;
> +    }
> +
> +    if (c_val2) {
> +        if (c_val1) {
> +            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2);
> +        } else {
> +            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2);
> +        }
> +        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne);
> +        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2);
> +        return;
> +    }
> +
> +    if (c_val1) {
> +        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1);
> +        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne);
> +        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1);
> +        return;
> +    }
> +
> +    tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne);
> +    tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne);
> +    tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1);
> +}
> +
> +static void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret,
> +                                TCGReg cmp1, TCGReg cmp2,
> +                                int val, bool c_val)
> +{
> +    RISCVInsn op;
> +    int disp = 8;
> +
> +    tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv));
> +    op = tcg_brcond_to_riscv[cond].op;
> +    tcg_debug_assert(op != 0);
> +
> +    if (tcg_brcond_to_riscv[cond].swap) {
> +        tcg_out_opc_branch(s, op, cmp2, cmp1, disp);
> +    } else {
> +        tcg_out_opc_branch(s, op, cmp1, cmp2, disp);
> +    }
> +    if (c_val) {
> +        tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0);
> +    }
> +}
> +
> +static void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret,
> +                                TCGReg cmp1, TCGReg cmp2,
> +                                int val1, bool c_val1,
> +                                int val2, bool c_val2)
> +{
> +    TCGReg tmp;
> +
> +    /* TCG optimizer reorders to prefer ret matching val2. */
> +    if (!c_val2 && ret == val2) {
> +        cond = tcg_invert_cond(cond);
> +        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1);
> +        return;
> +    }
> +
> +    if (!c_val1 && ret == val1) {
> +        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2);
> +        return;
> +    }
> +
> +    tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret);
> +    if (c_val1) {
> +        tcg_out_movi(s, TCG_TYPE_REG, tmp, val1);
> +    } else {
> +        tcg_out_mov(s, TCG_TYPE_REG, tmp, val1);
> +    }
> +    tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2);
> +    tcg_out_mov(s, TCG_TYPE_REG, ret, tmp);
> +}
> +
> +static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
> +                            TCGReg cmp1, int cmp2, bool c_cmp2,
> +                            TCGReg val1, bool c_val1,
> +                            TCGReg val2, bool c_val2)
> +{
> +    int tmpflags;
> +    TCGReg t;
> +
> +    if (!have_zicond && (!c_cmp2 || cmp2 == 0)) {
> +        tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
> +                            val1, c_val1, val2, c_val2);
> +        return;
> +    }
> +
> +    tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2);
> +    t = tmpflags & ~SETCOND_FLAGS;
> +
> +    if (have_zicond) {
> +        if (tmpflags & SETCOND_INV) {
> +            tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1);
> +        } else {
> +            tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2);
> +        }
> +    } else {
> +        cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE;
> +        tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO,
> +                            val1, c_val1, val2, c_val2);
> +    }
> +}
> +
>   static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
>   {
>       TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
> @@ -1624,6 +1751,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>           tcg_out_setcond(s, args[3], a0, a1, a2, c2);
>           break;
>   
> +    case INDEX_op_movcond_i32:
> +    case INDEX_op_movcond_i64:
> +        tcg_out_movcond(s, args[5], a0, a1, a2, c2,
> +                        args[3], const_args[3], args[4], const_args[4]);
> +        break;
> +
>       case INDEX_op_qemu_ld_i32:
>           tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
>           break;
> @@ -1788,6 +1921,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_brcond_i64:
>           return C_O0_I2(rZ, rZ);
>   
> +    case INDEX_op_movcond_i32:
> +    case INDEX_op_movcond_i64:
> +        return C_O1_I4(r, r, rI, rM, rM);
> +
>       case INDEX_op_add2_i32:
>       case INDEX_op_add2_i64:
>       case INDEX_op_sub2_i32:


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

* Re: [PATCH 11/11] tcg/riscv: Support CTZ, CLZ from Zbb
  2023-05-03  8:56 ` [PATCH 11/11] tcg/riscv: Support CTZ, CLZ from Zbb Richard Henderson
@ 2023-05-08 12:47   ` Daniel Henrique Barboza
  2023-05-17  1:47   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:47 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   tcg/riscv/tcg-target-con-set.h |  1 +
>   tcg/riscv/tcg-target.h         |  8 ++++----
>   tcg/riscv/tcg-target.c.inc     | 35 ++++++++++++++++++++++++++++++++++
>   3 files changed, 40 insertions(+), 4 deletions(-)
> 
> diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
> index a5cadd303f..aac5ceee2b 100644
> --- a/tcg/riscv/tcg-target-con-set.h
> +++ b/tcg/riscv/tcg-target-con-set.h
> @@ -18,5 +18,6 @@ C_O1_I2(r, r, rI)
>   C_O1_I2(r, r, rJ)
>   C_O1_I2(r, rZ, rN)
>   C_O1_I2(r, rZ, rZ)
> +C_N1_I2(r, r, rM)
>   C_O1_I4(r, r, rI, rM, rM)
>   C_O2_I4(r, r, rZ, rZ, rM, rM)
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index e9e84be9a5..cff5de5c9e 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -125,8 +125,8 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_eqv_i32          have_zbb
>   #define TCG_TARGET_HAS_nand_i32         0
>   #define TCG_TARGET_HAS_nor_i32          0
> -#define TCG_TARGET_HAS_clz_i32          0
> -#define TCG_TARGET_HAS_ctz_i32          0
> +#define TCG_TARGET_HAS_clz_i32          1
> +#define TCG_TARGET_HAS_ctz_i32          1
>   #define TCG_TARGET_HAS_ctpop_i32        have_zbb
>   #define TCG_TARGET_HAS_brcond2          1
>   #define TCG_TARGET_HAS_setcond2         1
> @@ -159,8 +159,8 @@ extern bool have_zbb;
>   #define TCG_TARGET_HAS_eqv_i64          have_zbb
>   #define TCG_TARGET_HAS_nand_i64         0
>   #define TCG_TARGET_HAS_nor_i64          0
> -#define TCG_TARGET_HAS_clz_i64          0
> -#define TCG_TARGET_HAS_ctz_i64          0
> +#define TCG_TARGET_HAS_clz_i64          1
> +#define TCG_TARGET_HAS_ctz_i64          1
>   #define TCG_TARGET_HAS_ctpop_i64        have_zbb
>   #define TCG_TARGET_HAS_add2_i64         1
>   #define TCG_TARGET_HAS_sub2_i64         1
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 1c57b64182..a1c92b0603 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1063,6 +1063,22 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
>       }
>   }
>   
> +static void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn,
> +                         TCGReg ret, TCGReg src1, int src2, bool c_src2)
> +{
> +    tcg_out_opc_imm(s, insn, ret, src1, 0);
> +
> +    if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) {
> +        /*
> +         * The requested zero result does not match the insn, so adjust.
> +         * Note that constraints put 'ret' in a new register, so the
> +         * computation above did not clobber either 'src1' or 'src2'.
> +         */
> +        tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true,
> +                        src2, c_src2, ret, false);
> +    }
> +}
> +
>   static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
>   {
>       TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
> @@ -1724,6 +1740,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>           tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
>           break;
>   
> +    case INDEX_op_clz_i32:
> +        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2);
> +        break;
> +    case INDEX_op_clz_i64:
> +        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2);
> +        break;
> +    case INDEX_op_ctz_i32:
> +        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2);
> +        break;
> +    case INDEX_op_ctz_i64:
> +        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2);
> +        break;
> +
>       case INDEX_op_add2_i32:
>           tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
>                           const_args[4], const_args[5], false, true);
> @@ -1917,6 +1946,12 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>       case INDEX_op_rotr_i64:
>           return C_O1_I2(r, r, ri);
>   
> +    case INDEX_op_clz_i32:
> +    case INDEX_op_clz_i64:
> +    case INDEX_op_ctz_i32:
> +    case INDEX_op_ctz_i64:
> +        return C_N1_I2(r, r, rM);
> +
>       case INDEX_op_brcond_i32:
>       case INDEX_op_brcond_i64:
>           return C_O0_I2(rZ, rZ);


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

* Re: [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions
  2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
                   ` (10 preceding siblings ...)
  2023-05-03  8:56 ` [PATCH 11/11] tcg/riscv: Support CTZ, CLZ from Zbb Richard Henderson
@ 2023-05-08 12:53 ` Daniel Henrique Barboza
  11 siblings, 0 replies; 35+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-08 12:53 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel



On 5/3/23 05:56, Richard Henderson wrote:
> Based-on: 20230503070656.1746170-1-richard.henderson@linaro.org
> ("[PATCH v4 00/57] tcg: Improve atomicity support")
> 
> I've been vaguely following the __hw_probe syscall progress
> in the upstream kernel.  The initial version only handled
> bog standard F+D and C extensions, which everything expects
> to be present anyway, which was disappointing.  But at least
> the basis is there for proper extensions.
> 
> In the meantime, probe via sigill.  Tested with qemu-on-qemu.
> I understand the Ventana core has all of these, if you'd be
> so kind as to test.

I'll run this series with upstream kernel on a real HW as soon as able.
(hopefully this month).

I think this is good to go regardless of HW testing though.


Daniel

> 
> 
> r~
> 
> 
> Richard Henderson (11):
>    disas/riscv: Decode czero.{eqz,nez}
>    tcg/riscv: Probe for Zba, Zbb, Zicond extensions
>    tcg/riscv: Support ANDN, ORN, XNOR from Zbb
>    tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb
>    tcg/riscv: Use ADD.UW for guest address generation
>    tcg/riscv: Support rotates from Zbb
>    tcg/riscv: Support REV8 from Zbb
>    tcg/riscv: Support CPOP from Zbb
>    tcg/riscv: Improve setcond expansion
>    tcg/riscv: Implement movcond
>    tcg/riscv: Support CTZ, CLZ from Zbb
> 
>   tcg/riscv/tcg-target-con-set.h |   3 +
>   tcg/riscv/tcg-target-con-str.h |   1 +
>   tcg/riscv/tcg-target.h         |  48 +--
>   disas/riscv.c                  |   8 +-
>   tcg/riscv/tcg-target.c.inc     | 612 +++++++++++++++++++++++++++++----
>   5 files changed, 587 insertions(+), 85 deletions(-)
> 


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

* Re: [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez}
  2023-05-03  8:56 ` [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez} Richard Henderson
  2023-05-08 12:37   ` Daniel Henrique Barboza
@ 2023-05-16 23:33   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-16 23:33 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:59 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  disas/riscv.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/disas/riscv.c b/disas/riscv.c
> index d6b0fbe5e8..c0a8b1006a 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -935,6 +935,8 @@ typedef enum {
>      rv_op_vsetvli = 766,
>      rv_op_vsetivli = 767,
>      rv_op_vsetvl = 768,
> +    rv_op_czero_eqz = 769,
> +    rv_op_czero_nez = 770,
>  } rv_op;
>
>  /* structures */
> @@ -2066,7 +2068,9 @@ const rv_opcode_data opcode_data[] = {
>      { "vsext.vf8", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, rv_op_vsext_vf8, rv_op_vsext_vf8, 0 },
>      { "vsetvli", rv_codec_vsetvli, rv_fmt_vsetvli, NULL, rv_op_vsetvli, rv_op_vsetvli, 0 },
>      { "vsetivli", rv_codec_vsetivli, rv_fmt_vsetivli, NULL, rv_op_vsetivli, rv_op_vsetivli, 0 },
> -    { "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 }
> +    { "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 },
> +    { "czero.eqz", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
> +    { "czero.nez", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
>  };
>
>  /* CSR names */
> @@ -2792,6 +2796,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
>              case 45: op = rv_op_minu; break;
>              case 46: op = rv_op_max; break;
>              case 47: op = rv_op_maxu; break;
> +            case 075: op = rv_op_czero_eqz; break;
> +            case 077: op = rv_op_czero_nez; break;
>              case 130: op = rv_op_sh1add; break;
>              case 132: op = rv_op_sh2add; break;
>              case 134: op = rv_op_sh3add; break;
> --
> 2.34.1
>
>


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

* Re: [PATCH 02/11] tcg/riscv: Probe for Zba, Zbb, Zicond extensions
  2023-05-03  8:56 ` [PATCH 02/11] tcg/riscv: Probe for Zba, Zbb, Zicond extensions Richard Henderson
  2023-05-08 12:37   ` Daniel Henrique Barboza
@ 2023-05-16 23:35   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-16 23:35 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:59 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Define a useful subset of the extensions.  Probe for them
> via compiler pre-processor feature macros and SIGILL.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target.h     |  6 +++
>  tcg/riscv/tcg-target.c.inc | 96 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 102 insertions(+)
>
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 494c986b49..863ac8ba2f 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -90,6 +90,12 @@ typedef enum {
>  #define TCG_TARGET_CALL_ARG_I128        TCG_CALL_ARG_NORMAL
>  #define TCG_TARGET_CALL_RET_I128        TCG_CALL_RET_NORMAL
>
> +#if defined(__riscv_arch_test) && defined(__riscv_zbb)
> +# define have_zbb true
> +#else
> +extern bool have_zbb;
> +#endif
> +
>  /* optional instructions */
>  #define TCG_TARGET_HAS_movcond_i32      0
>  #define TCG_TARGET_HAS_div_i32          1
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 4dd33c73e8..49ff9c8b9d 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -113,6 +113,20 @@ static const int tcg_target_call_iarg_regs[] = {
>      TCG_REG_A7,
>  };
>
> +#ifndef have_zbb
> +bool have_zbb;
> +#endif
> +#if defined(__riscv_arch_test) && defined(__riscv_zba)
> +# define have_zba true
> +#else
> +static bool have_zba;
> +#endif
> +#if defined(__riscv_arch_test) && defined(__riscv_zicond)
> +# define have_zicond true
> +#else
> +static bool have_zicond;
> +#endif
> +
>  static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
>  {
>      tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
> @@ -234,6 +248,34 @@ typedef enum {
>
>      OPC_FENCE = 0x0000000f,
>      OPC_NOP   = OPC_ADDI,   /* nop = addi r0,r0,0 */
> +
> +    /* Zba: Bit manipulation extension, address generation */
> +    OPC_ADD_UW = 0x0800003b,
> +
> +    /* Zbb: Bit manipulation extension, basic bit manipulaton */
> +    OPC_ANDN   = 0x40007033,
> +    OPC_CLZ    = 0x60001013,
> +    OPC_CLZW   = 0x6000101b,
> +    OPC_CPOP   = 0x60201013,
> +    OPC_CPOPW  = 0x6020101b,
> +    OPC_CTZ    = 0x60101013,
> +    OPC_CTZW   = 0x6010101b,
> +    OPC_ORN    = 0x40006033,
> +    OPC_REV8   = 0x6b805013,
> +    OPC_ROL    = 0x60001033,
> +    OPC_ROLW   = 0x6000103b,
> +    OPC_ROR    = 0x60005033,
> +    OPC_RORW   = 0x6000503b,
> +    OPC_RORI   = 0x60005013,
> +    OPC_RORIW  = 0x6000501b,
> +    OPC_SEXT_B = 0x60401013,
> +    OPC_SEXT_H = 0x60501013,
> +    OPC_XNOR   = 0x40004033,
> +    OPC_ZEXT_H = 0x0800403b,
> +
> +    /* Zicond: integer conditional operations */
> +    OPC_CZERO_EQZ = 0x0e005033,
> +    OPC_CZERO_NEZ = 0x0e007033,
>  } RISCVInsn;
>
>  /*
> @@ -1612,8 +1654,62 @@ static void tcg_target_qemu_prologue(TCGContext *s)
>      tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
>  }
>
> +static volatile sig_atomic_t got_sigill;
> +
> +static void sigill_handler(int signo, siginfo_t *si, void *data)
> +{
> +    /* Skip the faulty instruction */
> +    ucontext_t *uc = (ucontext_t *)data;
> +    uc->uc_mcontext.__gregs[REG_PC] += 4;
> +
> +    got_sigill = 1;
> +}
> +
> +static void tcg_target_detect_isa(void)
> +{
> +#if !defined(have_zba) || !defined(have_zbb) || !defined(have_zicond)
> +    /*
> +     * TODO: It is expected that this will be determinable via
> +     * linux riscv_hwprobe syscall, not yet merged.
> +     * In the meantime, test via sigill.
> +     */
> +
> +    struct sigaction sa_old, sa_new;
> +
> +    memset(&sa_new, 0, sizeof(sa_new));
> +    sa_new.sa_flags = SA_SIGINFO;
> +    sa_new.sa_sigaction = sigill_handler;
> +    sigaction(SIGILL, &sa_new, &sa_old);
> +
> +#ifndef have_zba
> +    /* Probe for Zba: add.uw zero,zero,zero. */
> +    got_sigill = 0;
> +    asm volatile(".insn %0" : : "i"(OPC_ADD_UW) : "memory");
> +    have_zba = !got_sigill;
> +#endif
> +
> +#ifndef have_zbb
> +    /* Probe for Zba: andn zero,zero,zero. */
> +    got_sigill = 0;
> +    asm volatile(".insn %0" : : "i"(OPC_ANDN) : "memory");
> +    have_zbb = !got_sigill;
> +#endif
> +
> +#ifndef have_zicond
> +    /* Probe for Zicond: czero.eqz zero,zero,zero. */
> +    got_sigill = 0;
> +    asm volatile(".insn %0" : : "i"(OPC_CZERO_EQZ) : "memory");
> +    have_zicond = !got_sigill;
> +#endif
> +
> +    sigaction(SIGILL, &sa_old, NULL);
> +#endif
> +}
> +
>  static void tcg_target_init(TCGContext *s)
>  {
> +    tcg_target_detect_isa();
> +
>      tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
>      tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
>
> --
> 2.34.1
>
>


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

* Re: [PATCH 03/11] tcg/riscv: Support ANDN, ORN, XNOR from Zbb
  2023-05-03  8:56 ` [PATCH 03/11] tcg/riscv: Support ANDN, ORN, XNOR from Zbb Richard Henderson
  2023-05-08 12:37   ` Daniel Henrique Barboza
@ 2023-05-16 23:38   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-16 23:38 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:58 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target-con-set.h |  1 +
>  tcg/riscv/tcg-target-con-str.h |  1 +
>  tcg/riscv/tcg-target.h         | 12 +++++-----
>  tcg/riscv/tcg-target.c.inc     | 41 ++++++++++++++++++++++++++++++++++
>  4 files changed, 49 insertions(+), 6 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
> index d88888d3ac..1a33ece98f 100644
> --- a/tcg/riscv/tcg-target-con-set.h
> +++ b/tcg/riscv/tcg-target-con-set.h
> @@ -15,6 +15,7 @@ C_O0_I2(rZ, rZ)
>  C_O1_I1(r, r)
>  C_O1_I2(r, r, ri)
>  C_O1_I2(r, r, rI)
> +C_O1_I2(r, r, rJ)
>  C_O1_I2(r, rZ, rN)
>  C_O1_I2(r, rZ, rZ)
>  C_O2_I4(r, r, rZ, rZ, rM, rM)
> diff --git a/tcg/riscv/tcg-target-con-str.h b/tcg/riscv/tcg-target-con-str.h
> index 6f1cfb976c..d5c419dff1 100644
> --- a/tcg/riscv/tcg-target-con-str.h
> +++ b/tcg/riscv/tcg-target-con-str.h
> @@ -15,6 +15,7 @@ REGS('r', ALL_GENERAL_REGS)
>   * CONST(letter, TCG_CT_CONST_* bit set)
>   */
>  CONST('I', TCG_CT_CONST_S12)
> +CONST('J', TCG_CT_CONST_J12)
>  CONST('N', TCG_CT_CONST_N12)
>  CONST('M', TCG_CT_CONST_M12)
>  CONST('Z', TCG_CT_CONST_ZERO)
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 863ac8ba2f..9f58d46208 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -120,9 +120,9 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_bswap32_i32      0
>  #define TCG_TARGET_HAS_not_i32          1
>  #define TCG_TARGET_HAS_neg_i32          1
> -#define TCG_TARGET_HAS_andc_i32         0
> -#define TCG_TARGET_HAS_orc_i32          0
> -#define TCG_TARGET_HAS_eqv_i32          0
> +#define TCG_TARGET_HAS_andc_i32         have_zbb
> +#define TCG_TARGET_HAS_orc_i32          have_zbb
> +#define TCG_TARGET_HAS_eqv_i32          have_zbb
>  #define TCG_TARGET_HAS_nand_i32         0
>  #define TCG_TARGET_HAS_nor_i32          0
>  #define TCG_TARGET_HAS_clz_i32          0
> @@ -154,9 +154,9 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_bswap64_i64      0
>  #define TCG_TARGET_HAS_not_i64          1
>  #define TCG_TARGET_HAS_neg_i64          1
> -#define TCG_TARGET_HAS_andc_i64         0
> -#define TCG_TARGET_HAS_orc_i64          0
> -#define TCG_TARGET_HAS_eqv_i64          0
> +#define TCG_TARGET_HAS_andc_i64         have_zbb
> +#define TCG_TARGET_HAS_orc_i64          have_zbb
> +#define TCG_TARGET_HAS_eqv_i64          have_zbb
>  #define TCG_TARGET_HAS_nand_i64         0
>  #define TCG_TARGET_HAS_nor_i64          0
>  #define TCG_TARGET_HAS_clz_i64          0
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 49ff9c8b9d..c5b060023f 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -138,6 +138,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
>  #define TCG_CT_CONST_S12   0x200
>  #define TCG_CT_CONST_N12   0x400
>  #define TCG_CT_CONST_M12   0x800
> +#define TCG_CT_CONST_J12  0x1000
>
>  #define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
>
> @@ -174,6 +175,13 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
>      if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
>          return 1;
>      }
> +    /*
> +     * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff].
> +     * Used to map ANDN back to ANDI, etc.
> +     */
> +    if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) {
> +        return 1;
> +    }
>      return 0;
>  }
>
> @@ -1306,6 +1314,31 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>          }
>          break;
>
> +    case INDEX_op_andc_i32:
> +    case INDEX_op_andc_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2);
> +        }
> +        break;
> +    case INDEX_op_orc_i32:
> +    case INDEX_op_orc_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2);
> +        }
> +        break;
> +    case INDEX_op_eqv_i32:
> +    case INDEX_op_eqv_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2);
> +        }
> +        break;
> +
>      case INDEX_op_not_i32:
>      case INDEX_op_not_i64:
>          tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
> @@ -1536,6 +1569,14 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_xor_i64:
>          return C_O1_I2(r, r, rI);
>
> +    case INDEX_op_andc_i32:
> +    case INDEX_op_andc_i64:
> +    case INDEX_op_orc_i32:
> +    case INDEX_op_orc_i64:
> +    case INDEX_op_eqv_i32:
> +    case INDEX_op_eqv_i64:
> +        return C_O1_I2(r, r, rJ);
> +
>      case INDEX_op_sub_i32:
>      case INDEX_op_sub_i64:
>          return C_O1_I2(r, rZ, rN);
> --
> 2.34.1
>
>


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

* Re: [PATCH 04/11] tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb
  2023-05-03  8:56 ` [PATCH 04/11] tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb Richard Henderson
  2023-05-08 12:39   ` Daniel Henrique Barboza
@ 2023-05-16 23:40   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-16 23:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:59 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target.c.inc | 32 ++++++++++++++++++++++++--------
>  1 file changed, 24 insertions(+), 8 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index c5b060023f..53a7f97b29 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -593,26 +593,42 @@ static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
>
>  static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
>  {
> -    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
> -    tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
> +    if (have_zbb) {
> +        tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
> +        tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
> +    }
>  }
>
>  static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
>  {
> -    tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
> -    tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
> +    if (have_zba) {
> +        tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
> +        tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
> +    }
>  }
>
>  static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
>  {
> -    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
> -    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
> +    if (have_zbb) {
> +        tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
> +        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
> +    }
>  }
>
>  static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
>  {
> -    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
> -    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
> +    if (have_zbb) {
> +        tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
> +        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
> +    }
>  }
>
>  static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
> --
> 2.34.1
>
>


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

* Re: [PATCH 05/11] tcg/riscv: Use ADD.UW for guest address generation
  2023-05-03  8:56 ` [PATCH 05/11] tcg/riscv: Use ADD.UW for guest address generation Richard Henderson
  2023-05-08 12:43   ` Daniel Henrique Barboza
@ 2023-05-16 23:43   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-16 23:43 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:58 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> The instruction is a combined zero-extend and add.
> Use it for exactly that.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target.c.inc | 33 ++++++++++++++++++++++-----------
>  1 file changed, 22 insertions(+), 11 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 53a7f97b29..f64eaa8515 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1039,14 +1039,18 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
>      tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
>
>      /* TLB Hit - translate address using addend.  */
> -    addr_adj = addr_reg;
> -    if (TARGET_LONG_BITS == 32) {
> -        addr_adj = TCG_REG_TMP0;
> -        tcg_out_ext32u(s, addr_adj, addr_reg);
> +    if (TARGET_LONG_BITS == 64) {
> +        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
> +    } else if (have_zba) {
> +        tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
> +    } else {
> +        tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
> +        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, TCG_REG_TMP2);
>      }
> -    tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP2, addr_adj);
>      *pbase = TCG_REG_TMP0;
>  #else
> +    TCGReg base;
> +
>      if (a_mask) {
>          ldst = new_ldst_label(s);
>          ldst->is_ld = is_ld;
> @@ -1061,14 +1065,21 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
>          tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
>      }
>
> -    TCGReg base = addr_reg;
> -    if (TARGET_LONG_BITS == 32) {
> -        tcg_out_ext32u(s, TCG_REG_TMP0, base);
> -        base = TCG_REG_TMP0;
> -    }
>      if (guest_base != 0) {
> -        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_GUEST_BASE_REG, base);
>          base = TCG_REG_TMP0;
> +        if (TARGET_LONG_BITS == 64) {
> +            tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, TCG_GUEST_BASE_REG);
> +        } else if (have_zba) {
> +            tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, TCG_GUEST_BASE_REG);
> +        } else {
> +            tcg_out_ext32u(s, base, addr_reg);
> +            tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
> +        }
> +    } else if (TARGET_LONG_BITS == 64) {
> +        base = addr_reg;
> +    } else {
> +        base = TCG_REG_TMP0;
> +        tcg_out_ext32u(s, base, addr_reg);
>      }
>      *pbase = base;
>  #endif
> --
> 2.34.1
>
>


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

* Re: [PATCH 06/11] tcg/riscv: Support rotates from Zbb
  2023-05-03  8:56 ` [PATCH 06/11] tcg/riscv: Support rotates from Zbb Richard Henderson
  2023-05-08 12:44   ` Daniel Henrique Barboza
@ 2023-05-16 23:48   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-16 23:48 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:57 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target.h     |  4 ++--
>  tcg/riscv/tcg-target.c.inc | 34 ++++++++++++++++++++++++++++++++++
>  2 files changed, 36 insertions(+), 2 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 9f58d46208..317d385924 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -101,7 +101,7 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_div_i32          1
>  #define TCG_TARGET_HAS_rem_i32          1
>  #define TCG_TARGET_HAS_div2_i32         0
> -#define TCG_TARGET_HAS_rot_i32          0
> +#define TCG_TARGET_HAS_rot_i32          have_zbb
>  #define TCG_TARGET_HAS_deposit_i32      0
>  #define TCG_TARGET_HAS_extract_i32      0
>  #define TCG_TARGET_HAS_sextract_i32     0
> @@ -136,7 +136,7 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_div_i64          1
>  #define TCG_TARGET_HAS_rem_i64          1
>  #define TCG_TARGET_HAS_div2_i64         0
> -#define TCG_TARGET_HAS_rot_i64          0
> +#define TCG_TARGET_HAS_rot_i64          have_zbb
>  #define TCG_TARGET_HAS_deposit_i64      0
>  #define TCG_TARGET_HAS_extract_i64      0
>  #define TCG_TARGET_HAS_sextract_i64     0
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index f64eaa8515..58f969b4fe 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1458,6 +1458,36 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>          }
>          break;
>
> +    case INDEX_op_rotl_i32:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2);
> +        }
> +        break;
> +    case INDEX_op_rotl_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2);
> +        }
> +        break;
> +
> +    case INDEX_op_rotr_i32:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2);
> +        }
> +        break;
> +    case INDEX_op_rotr_i64:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2);
> +        }
> +        break;
> +
>      case INDEX_op_add2_i32:
>          tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
>                          const_args[4], const_args[5], false, true);
> @@ -1629,9 +1659,13 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_shl_i32:
>      case INDEX_op_shr_i32:
>      case INDEX_op_sar_i32:
> +    case INDEX_op_rotl_i32:
> +    case INDEX_op_rotr_i32:
>      case INDEX_op_shl_i64:
>      case INDEX_op_shr_i64:
>      case INDEX_op_sar_i64:
> +    case INDEX_op_rotl_i64:
> +    case INDEX_op_rotr_i64:
>          return C_O1_I2(r, r, ri);
>
>      case INDEX_op_brcond_i32:
> --
> 2.34.1
>
>


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

* Re: [PATCH 07/11] tcg/riscv: Support REV8 from Zbb
  2023-05-03  8:56 ` [PATCH 07/11] tcg/riscv: Support REV8 " Richard Henderson
  2023-05-08 12:45   ` Daniel Henrique Barboza
@ 2023-05-16 23:50   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-16 23:50 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:59 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target.h     | 10 +++++-----
>  tcg/riscv/tcg-target.c.inc | 29 +++++++++++++++++++++++++++++
>  2 files changed, 34 insertions(+), 5 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 317d385924..8e327afc3a 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -116,8 +116,8 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_ext16s_i32       1
>  #define TCG_TARGET_HAS_ext8u_i32        1
>  #define TCG_TARGET_HAS_ext16u_i32       1
> -#define TCG_TARGET_HAS_bswap16_i32      0
> -#define TCG_TARGET_HAS_bswap32_i32      0
> +#define TCG_TARGET_HAS_bswap16_i32      have_zbb
> +#define TCG_TARGET_HAS_bswap32_i32      have_zbb
>  #define TCG_TARGET_HAS_not_i32          1
>  #define TCG_TARGET_HAS_neg_i32          1
>  #define TCG_TARGET_HAS_andc_i32         have_zbb
> @@ -149,9 +149,9 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_ext8u_i64        1
>  #define TCG_TARGET_HAS_ext16u_i64       1
>  #define TCG_TARGET_HAS_ext32u_i64       1
> -#define TCG_TARGET_HAS_bswap16_i64      0
> -#define TCG_TARGET_HAS_bswap32_i64      0
> -#define TCG_TARGET_HAS_bswap64_i64      0
> +#define TCG_TARGET_HAS_bswap16_i64      have_zbb
> +#define TCG_TARGET_HAS_bswap32_i64      have_zbb
> +#define TCG_TARGET_HAS_bswap64_i64      have_zbb
>  #define TCG_TARGET_HAS_not_i64          1
>  #define TCG_TARGET_HAS_neg_i64          1
>  #define TCG_TARGET_HAS_andc_i64         have_zbb
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 58f969b4fe..9cbefb2833 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1488,6 +1488,30 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>          }
>          break;
>
> +    case INDEX_op_bswap64_i64:
> +        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
> +        break;
> +    case INDEX_op_bswap32_i32:
> +        a2 = 0;
> +        /* fall through */
> +    case INDEX_op_bswap32_i64:
> +        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
> +        if (a2 & TCG_BSWAP_OZ) {
> +            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32);
> +        } else {
> +            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32);
> +        }
> +        break;
> +    case INDEX_op_bswap16_i64:
> +    case INDEX_op_bswap16_i32:
> +        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
> +        if (a2 & TCG_BSWAP_OZ) {
> +            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48);
> +        } else {
> +            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48);
> +        }
> +        break;
> +
>      case INDEX_op_add2_i32:
>          tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
>                          const_args[4], const_args[5], false, true);
> @@ -1605,6 +1629,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_extrl_i64_i32:
>      case INDEX_op_extrh_i64_i32:
>      case INDEX_op_ext_i32_i64:
> +    case INDEX_op_bswap16_i32:
> +    case INDEX_op_bswap32_i32:
> +    case INDEX_op_bswap16_i64:
> +    case INDEX_op_bswap32_i64:
> +    case INDEX_op_bswap64_i64:
>          return C_O1_I1(r, r);
>
>      case INDEX_op_st8_i32:
> --
> 2.34.1
>
>


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

* Re: [PATCH 08/11] tcg/riscv: Support CPOP from Zbb
  2023-05-03  8:56 ` [PATCH 08/11] tcg/riscv: Support CPOP " Richard Henderson
  2023-05-08 12:45   ` Daniel Henrique Barboza
@ 2023-05-16 23:50   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-16 23:50 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:58 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target.h     | 4 ++--
>  tcg/riscv/tcg-target.c.inc | 9 +++++++++
>  2 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 8e327afc3a..e0b23006c4 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -127,7 +127,7 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_nor_i32          0
>  #define TCG_TARGET_HAS_clz_i32          0
>  #define TCG_TARGET_HAS_ctz_i32          0
> -#define TCG_TARGET_HAS_ctpop_i32        0
> +#define TCG_TARGET_HAS_ctpop_i32        have_zbb
>  #define TCG_TARGET_HAS_brcond2          1
>  #define TCG_TARGET_HAS_setcond2         1
>  #define TCG_TARGET_HAS_qemu_st8_i32     0
> @@ -161,7 +161,7 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_nor_i64          0
>  #define TCG_TARGET_HAS_clz_i64          0
>  #define TCG_TARGET_HAS_ctz_i64          0
> -#define TCG_TARGET_HAS_ctpop_i64        0
> +#define TCG_TARGET_HAS_ctpop_i64        have_zbb
>  #define TCG_TARGET_HAS_add2_i64         1
>  #define TCG_TARGET_HAS_sub2_i64         1
>  #define TCG_TARGET_HAS_mulu2_i64        0
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 9cbefb2833..044ddfb160 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1512,6 +1512,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>          }
>          break;
>
> +    case INDEX_op_ctpop_i32:
> +        tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0);
> +        break;
> +    case INDEX_op_ctpop_i64:
> +        tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
> +        break;
> +
>      case INDEX_op_add2_i32:
>          tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
>                          const_args[4], const_args[5], false, true);
> @@ -1634,6 +1641,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_bswap16_i64:
>      case INDEX_op_bswap32_i64:
>      case INDEX_op_bswap64_i64:
> +    case INDEX_op_ctpop_i32:
> +    case INDEX_op_ctpop_i64:
>          return C_O1_I1(r, r);
>
>      case INDEX_op_st8_i32:
> --
> 2.34.1
>
>


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

* Re: [PATCH 09/11] tcg/riscv: Improve setcond expansion
  2023-05-03  8:56 ` [PATCH 09/11] tcg/riscv: Improve setcond expansion Richard Henderson
  2023-05-08 12:46   ` Daniel Henrique Barboza
@ 2023-05-17  0:16   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-17  0:16 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:59 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Split out a helper function, tcg_out_setcond_int, which does not
> always produce the complete boolean result, but returns a set of
> flags to do so.
>
> Based on 21af16198425, the same improvement for loongarch64.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target.c.inc | 164 +++++++++++++++++++++++++++----------
>  1 file changed, 121 insertions(+), 43 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 044ddfb160..84b646105c 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -812,50 +812,128 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
>      tcg_out_opc_branch(s, op, arg1, arg2, 0);
>  }
>
> -static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
> -                            TCGReg arg1, TCGReg arg2)
> +#define SETCOND_INV    TCG_TARGET_NB_REGS
> +#define SETCOND_NEZ    (SETCOND_INV << 1)
> +#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
> +
> +static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
> +                               TCGReg arg1, tcg_target_long arg2, bool c2)
>  {
> +    int flags = 0;
> +
>      switch (cond) {
> -    case TCG_COND_EQ:
> -        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
> -        tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
> -        break;
> -    case TCG_COND_NE:
> -        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
> -        break;
> -    case TCG_COND_LT:
> -        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
> -        break;
> -    case TCG_COND_GE:
> -        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
> -        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
> -        break;
> -    case TCG_COND_LE:
> -        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
> -        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
> -        break;
> -    case TCG_COND_GT:
> -        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
> -        break;
> -    case TCG_COND_LTU:
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
> -        break;
> -    case TCG_COND_GEU:
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
> -        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
> -        break;
> -    case TCG_COND_LEU:
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
> -        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
> -        break;
> -    case TCG_COND_GTU:
> -        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
> +    case TCG_COND_EQ:    /* -> NE  */
> +    case TCG_COND_GE:    /* -> LT  */
> +    case TCG_COND_GEU:   /* -> LTU */
> +    case TCG_COND_GT:    /* -> LE  */
> +    case TCG_COND_GTU:   /* -> LEU */
> +        cond = tcg_invert_cond(cond);
> +        flags ^= SETCOND_INV;
>          break;
>      default:
> -         g_assert_not_reached();
> -         break;
> -     }
> +        break;
> +    }
> +
> +    switch (cond) {
> +    case TCG_COND_LE:
> +    case TCG_COND_LEU:
> +        /*
> +         * If we have a constant input, the most efficient way to implement
> +         * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
> +         * We don't need to care for this for LE because the constant input
> +         * is constrained to signed 12-bit, and 0x800 is representable in the
> +         * temporary register.
> +         */
> +        if (c2) {
> +            if (cond == TCG_COND_LEU) {
> +                /* unsigned <= -1 is true */
> +                if (arg2 == -1) {
> +                    tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
> +                    return ret;
> +                }
> +                cond = TCG_COND_LTU;
> +            } else {
> +                cond = TCG_COND_LT;
> +            }
> +            tcg_debug_assert(arg2 <= 0x7ff);
> +            if (++arg2 == 0x800) {
> +                tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
> +                arg2 = TCG_REG_TMP0;
> +                c2 = false;
> +            }
> +        } else {
> +            TCGReg tmp = arg2;
> +            arg2 = arg1;
> +            arg1 = tmp;
> +            cond = tcg_swap_cond(cond);    /* LE -> GE */
> +            cond = tcg_invert_cond(cond);  /* GE -> LT */
> +            flags ^= SETCOND_INV;
> +        }
> +        break;
> +    default:
> +        break;
> +    }
> +
> +    switch (cond) {
> +    case TCG_COND_NE:
> +        flags |= SETCOND_NEZ;
> +        if (!c2) {
> +            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
> +        } else if (arg2 == 0) {
> +            ret = arg1;
> +        } else {
> +            tcg_out_opc_reg(s, OPC_XORI, ret, arg1, arg2);
> +        }
> +        break;
> +
> +    case TCG_COND_LT:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
> +        }
> +        break;
> +
> +    case TCG_COND_LTU:
> +        if (c2) {
> +            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2);
> +        } else {
> +            tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
> +        }
> +        break;
> +
> +    default:
> +        g_assert_not_reached();
> +    }
> +
> +    return ret | flags;
> +}
> +
> +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
> +                            TCGReg arg1, tcg_target_long arg2, bool c2)
> +{
> +    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
> +
> +    if (tmpflags != ret) {
> +        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
> +
> +        switch (tmpflags & SETCOND_FLAGS) {
> +        case SETCOND_INV:
> +            /* Intermediate result is boolean: simply invert. */
> +            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
> +            break;
> +        case SETCOND_NEZ:
> +            /* Intermediate result is zero/non-zero: test != 0. */
> +            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
> +            break;
> +        case SETCOND_NEZ | SETCOND_INV:
> +            /* Intermediate result is zero/non-zero: test == 0. */
> +            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
> +            break;
> +        default:
> +            g_assert_not_reached();
> +        }
> +    }
>  }
>
>  static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
> @@ -1543,7 +1621,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>
>      case INDEX_op_setcond_i32:
>      case INDEX_op_setcond_i64:
> -        tcg_out_setcond(s, args[3], a0, a1, a2);
> +        tcg_out_setcond(s, args[3], a0, a1, a2, c2);
>          break;
>
>      case INDEX_op_qemu_ld_i32:
> @@ -1662,6 +1740,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_and_i64:
>      case INDEX_op_or_i64:
>      case INDEX_op_xor_i64:
> +    case INDEX_op_setcond_i32:
> +    case INDEX_op_setcond_i64:
>          return C_O1_I2(r, r, rI);
>
>      case INDEX_op_andc_i32:
> @@ -1683,7 +1763,6 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_divu_i32:
>      case INDEX_op_rem_i32:
>      case INDEX_op_remu_i32:
> -    case INDEX_op_setcond_i32:
>      case INDEX_op_mul_i64:
>      case INDEX_op_mulsh_i64:
>      case INDEX_op_muluh_i64:
> @@ -1691,7 +1770,6 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_divu_i64:
>      case INDEX_op_rem_i64:
>      case INDEX_op_remu_i64:
> -    case INDEX_op_setcond_i64:
>          return C_O1_I2(r, rZ, rZ);
>
>      case INDEX_op_shl_i32:
> --
> 2.34.1
>
>


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

* Re: [PATCH 10/11] tcg/riscv: Implement movcond
  2023-05-03  8:56 ` [PATCH 10/11] tcg/riscv: Implement movcond Richard Henderson
  2023-05-08 12:47   ` Daniel Henrique Barboza
@ 2023-05-17  0:19   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-17  0:19 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:59 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Implement with and without Zicond.  Without Zicond, we were letting
> the middle-end expand to a 5 insn sequence; better to use a branch
> over a single insn.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target-con-set.h |   1 +
>  tcg/riscv/tcg-target.h         |   4 +-
>  tcg/riscv/tcg-target.c.inc     | 139 ++++++++++++++++++++++++++++++++-
>  3 files changed, 141 insertions(+), 3 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
> index 1a33ece98f..a5cadd303f 100644
> --- a/tcg/riscv/tcg-target-con-set.h
> +++ b/tcg/riscv/tcg-target-con-set.h
> @@ -18,4 +18,5 @@ C_O1_I2(r, r, rI)
>  C_O1_I2(r, r, rJ)
>  C_O1_I2(r, rZ, rN)
>  C_O1_I2(r, rZ, rZ)
> +C_O1_I4(r, r, rI, rM, rM)
>  C_O2_I4(r, r, rZ, rZ, rM, rM)
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index e0b23006c4..e9e84be9a5 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -97,7 +97,7 @@ extern bool have_zbb;
>  #endif
>
>  /* optional instructions */
> -#define TCG_TARGET_HAS_movcond_i32      0
> +#define TCG_TARGET_HAS_movcond_i32      1
>  #define TCG_TARGET_HAS_div_i32          1
>  #define TCG_TARGET_HAS_rem_i32          1
>  #define TCG_TARGET_HAS_div2_i32         0
> @@ -132,7 +132,7 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_setcond2         1
>  #define TCG_TARGET_HAS_qemu_st8_i32     0
>
> -#define TCG_TARGET_HAS_movcond_i64      0
> +#define TCG_TARGET_HAS_movcond_i64      1
>  #define TCG_TARGET_HAS_div_i64          1
>  #define TCG_TARGET_HAS_rem_i64          1
>  #define TCG_TARGET_HAS_div2_i64         0
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 84b646105c..1c57b64182 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -169,7 +169,7 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
>      }
>      /*
>       * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff].
> -     * Used by addsub2, which may need the negative operation,
> +     * Used by addsub2 and movcond, which may need the negative value,
>       * and requires the modified constant to be representable.
>       */
>      if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
> @@ -936,6 +936,133 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
>      }
>  }
>
> +static void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
> +                                   int val1, bool c_val1,
> +                                   int val2, bool c_val2)
> +{
> +    if (val1 == 0) {
> +        if (c_val2) {
> +            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2);
> +            val2 = TCG_REG_TMP1;
> +        }
> +        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne);
> +        return;
> +    }
> +
> +    if (val2 == 0) {
> +        if (c_val1) {
> +            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1);
> +            val1 = TCG_REG_TMP1;
> +        }
> +        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne);
> +        return;
> +    }
> +
> +    if (c_val2) {
> +        if (c_val1) {
> +            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2);
> +        } else {
> +            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2);
> +        }
> +        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne);
> +        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2);
> +        return;
> +    }
> +
> +    if (c_val1) {
> +        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1);
> +        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne);
> +        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1);
> +        return;
> +    }
> +
> +    tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne);
> +    tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne);
> +    tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1);
> +}
> +
> +static void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret,
> +                                TCGReg cmp1, TCGReg cmp2,
> +                                int val, bool c_val)
> +{
> +    RISCVInsn op;
> +    int disp = 8;
> +
> +    tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv));
> +    op = tcg_brcond_to_riscv[cond].op;
> +    tcg_debug_assert(op != 0);
> +
> +    if (tcg_brcond_to_riscv[cond].swap) {
> +        tcg_out_opc_branch(s, op, cmp2, cmp1, disp);
> +    } else {
> +        tcg_out_opc_branch(s, op, cmp1, cmp2, disp);
> +    }
> +    if (c_val) {
> +        tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val);
> +    } else {
> +        tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0);
> +    }
> +}
> +
> +static void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret,
> +                                TCGReg cmp1, TCGReg cmp2,
> +                                int val1, bool c_val1,
> +                                int val2, bool c_val2)
> +{
> +    TCGReg tmp;
> +
> +    /* TCG optimizer reorders to prefer ret matching val2. */
> +    if (!c_val2 && ret == val2) {
> +        cond = tcg_invert_cond(cond);
> +        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1);
> +        return;
> +    }
> +
> +    if (!c_val1 && ret == val1) {
> +        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2);
> +        return;
> +    }
> +
> +    tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret);
> +    if (c_val1) {
> +        tcg_out_movi(s, TCG_TYPE_REG, tmp, val1);
> +    } else {
> +        tcg_out_mov(s, TCG_TYPE_REG, tmp, val1);
> +    }
> +    tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2);
> +    tcg_out_mov(s, TCG_TYPE_REG, ret, tmp);
> +}
> +
> +static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
> +                            TCGReg cmp1, int cmp2, bool c_cmp2,
> +                            TCGReg val1, bool c_val1,
> +                            TCGReg val2, bool c_val2)
> +{
> +    int tmpflags;
> +    TCGReg t;
> +
> +    if (!have_zicond && (!c_cmp2 || cmp2 == 0)) {
> +        tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
> +                            val1, c_val1, val2, c_val2);
> +        return;
> +    }
> +
> +    tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2);
> +    t = tmpflags & ~SETCOND_FLAGS;
> +
> +    if (have_zicond) {
> +        if (tmpflags & SETCOND_INV) {
> +            tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1);
> +        } else {
> +            tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2);
> +        }
> +    } else {
> +        cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE;
> +        tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO,
> +                            val1, c_val1, val2, c_val2);
> +    }
> +}
> +
>  static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
>  {
>      TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
> @@ -1624,6 +1751,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>          tcg_out_setcond(s, args[3], a0, a1, a2, c2);
>          break;
>
> +    case INDEX_op_movcond_i32:
> +    case INDEX_op_movcond_i64:
> +        tcg_out_movcond(s, args[5], a0, a1, a2, c2,
> +                        args[3], const_args[3], args[4], const_args[4]);
> +        break;
> +
>      case INDEX_op_qemu_ld_i32:
>          tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
>          break;
> @@ -1788,6 +1921,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_brcond_i64:
>          return C_O0_I2(rZ, rZ);
>
> +    case INDEX_op_movcond_i32:
> +    case INDEX_op_movcond_i64:
> +        return C_O1_I4(r, r, rI, rM, rM);
> +
>      case INDEX_op_add2_i32:
>      case INDEX_op_add2_i64:
>      case INDEX_op_sub2_i32:
> --
> 2.34.1
>
>


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

* Re: [PATCH 11/11] tcg/riscv: Support CTZ, CLZ from Zbb
  2023-05-03  8:56 ` [PATCH 11/11] tcg/riscv: Support CTZ, CLZ from Zbb Richard Henderson
  2023-05-08 12:47   ` Daniel Henrique Barboza
@ 2023-05-17  1:47   ` Alistair Francis
  1 sibling, 0 replies; 35+ messages in thread
From: Alistair Francis @ 2023-05-17  1:47 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, dbarboza

On Wed, May 3, 2023 at 6:57 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  tcg/riscv/tcg-target-con-set.h |  1 +
>  tcg/riscv/tcg-target.h         |  8 ++++----
>  tcg/riscv/tcg-target.c.inc     | 35 ++++++++++++++++++++++++++++++++++
>  3 files changed, 40 insertions(+), 4 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
> index a5cadd303f..aac5ceee2b 100644
> --- a/tcg/riscv/tcg-target-con-set.h
> +++ b/tcg/riscv/tcg-target-con-set.h
> @@ -18,5 +18,6 @@ C_O1_I2(r, r, rI)
>  C_O1_I2(r, r, rJ)
>  C_O1_I2(r, rZ, rN)
>  C_O1_I2(r, rZ, rZ)
> +C_N1_I2(r, r, rM)
>  C_O1_I4(r, r, rI, rM, rM)
>  C_O2_I4(r, r, rZ, rZ, rM, rM)
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index e9e84be9a5..cff5de5c9e 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -125,8 +125,8 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_eqv_i32          have_zbb
>  #define TCG_TARGET_HAS_nand_i32         0
>  #define TCG_TARGET_HAS_nor_i32          0
> -#define TCG_TARGET_HAS_clz_i32          0
> -#define TCG_TARGET_HAS_ctz_i32          0
> +#define TCG_TARGET_HAS_clz_i32          1
> +#define TCG_TARGET_HAS_ctz_i32          1
>  #define TCG_TARGET_HAS_ctpop_i32        have_zbb
>  #define TCG_TARGET_HAS_brcond2          1
>  #define TCG_TARGET_HAS_setcond2         1
> @@ -159,8 +159,8 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_eqv_i64          have_zbb
>  #define TCG_TARGET_HAS_nand_i64         0
>  #define TCG_TARGET_HAS_nor_i64          0
> -#define TCG_TARGET_HAS_clz_i64          0
> -#define TCG_TARGET_HAS_ctz_i64          0
> +#define TCG_TARGET_HAS_clz_i64          1
> +#define TCG_TARGET_HAS_ctz_i64          1
>  #define TCG_TARGET_HAS_ctpop_i64        have_zbb
>  #define TCG_TARGET_HAS_add2_i64         1
>  #define TCG_TARGET_HAS_sub2_i64         1
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 1c57b64182..a1c92b0603 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -1063,6 +1063,22 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
>      }
>  }
>
> +static void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn,
> +                         TCGReg ret, TCGReg src1, int src2, bool c_src2)
> +{
> +    tcg_out_opc_imm(s, insn, ret, src1, 0);
> +
> +    if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) {
> +        /*
> +         * The requested zero result does not match the insn, so adjust.
> +         * Note that constraints put 'ret' in a new register, so the
> +         * computation above did not clobber either 'src1' or 'src2'.
> +         */
> +        tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true,
> +                        src2, c_src2, ret, false);
> +    }
> +}
> +
>  static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
>  {
>      TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
> @@ -1724,6 +1740,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
>          tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
>          break;
>
> +    case INDEX_op_clz_i32:
> +        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2);
> +        break;
> +    case INDEX_op_clz_i64:
> +        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2);
> +        break;
> +    case INDEX_op_ctz_i32:
> +        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2);
> +        break;
> +    case INDEX_op_ctz_i64:
> +        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2);
> +        break;
> +
>      case INDEX_op_add2_i32:
>          tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
>                          const_args[4], const_args[5], false, true);
> @@ -1917,6 +1946,12 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
>      case INDEX_op_rotr_i64:
>          return C_O1_I2(r, r, ri);
>
> +    case INDEX_op_clz_i32:
> +    case INDEX_op_clz_i64:
> +    case INDEX_op_ctz_i32:
> +    case INDEX_op_ctz_i64:
> +        return C_N1_I2(r, r, rM);
> +
>      case INDEX_op_brcond_i32:
>      case INDEX_op_brcond_i64:
>          return C_O0_I2(rZ, rZ);
> --
> 2.34.1
>
>


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

end of thread, other threads:[~2023-05-17  1:49 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-03  8:56 [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Richard Henderson
2023-05-03  8:56 ` [PATCH 01/11] disas/riscv: Decode czero.{eqz,nez} Richard Henderson
2023-05-08 12:37   ` Daniel Henrique Barboza
2023-05-16 23:33   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 02/11] tcg/riscv: Probe for Zba, Zbb, Zicond extensions Richard Henderson
2023-05-08 12:37   ` Daniel Henrique Barboza
2023-05-16 23:35   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 03/11] tcg/riscv: Support ANDN, ORN, XNOR from Zbb Richard Henderson
2023-05-08 12:37   ` Daniel Henrique Barboza
2023-05-16 23:38   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 04/11] tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb Richard Henderson
2023-05-08 12:39   ` Daniel Henrique Barboza
2023-05-16 23:40   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 05/11] tcg/riscv: Use ADD.UW for guest address generation Richard Henderson
2023-05-08 12:43   ` Daniel Henrique Barboza
2023-05-16 23:43   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 06/11] tcg/riscv: Support rotates from Zbb Richard Henderson
2023-05-08 12:44   ` Daniel Henrique Barboza
2023-05-16 23:48   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 07/11] tcg/riscv: Support REV8 " Richard Henderson
2023-05-08 12:45   ` Daniel Henrique Barboza
2023-05-16 23:50   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 08/11] tcg/riscv: Support CPOP " Richard Henderson
2023-05-08 12:45   ` Daniel Henrique Barboza
2023-05-16 23:50   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 09/11] tcg/riscv: Improve setcond expansion Richard Henderson
2023-05-08 12:46   ` Daniel Henrique Barboza
2023-05-17  0:16   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 10/11] tcg/riscv: Implement movcond Richard Henderson
2023-05-08 12:47   ` Daniel Henrique Barboza
2023-05-17  0:19   ` Alistair Francis
2023-05-03  8:56 ` [PATCH 11/11] tcg/riscv: Support CTZ, CLZ from Zbb Richard Henderson
2023-05-08 12:47   ` Daniel Henrique Barboza
2023-05-17  1:47   ` Alistair Francis
2023-05-08 12:53 ` [PATCH 00/11] tcg/riscv: Support for Zba, Zbb, Zicond extensions Daniel Henrique Barboza

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).