Re: [PATCH v7 14/18] target/riscv: support for 128-bit M extension

2022-01-05 Thread Alistair Francis
On Tue, Dec 14, 2021 at 2:55 AM Frédéric Pétrot
 wrote:
>
> Mult are generated inline (using a cool trick pointed out by Richard), but
> for div and rem, given the complexity of the implementation of these
> instructions, we call helpers to produce their behavior. From an
> implementation standpoint, the helpers return the low part of the results,
> while the high part is temporarily stored in a dedicated field of cpu_env
> that is used to update the architectural register in the generation wrapper.
>
> Signed-off-by: Frédéric Pétrot 
> Co-authored-by: Fabien Portas 
> Reviewed-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.h  |   3 +
>  target/riscv/helper.h   |   6 +
>  target/riscv/insn32.decode  |   7 +
>  target/riscv/m128_helper.c  | 109 ++
>  target/riscv/insn_trans/trans_rvm.c.inc | 182 ++--
>  target/riscv/meson.build|   1 +
>  6 files changed, 295 insertions(+), 13 deletions(-)
>  create mode 100644 target/riscv/m128_helper.c
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index cbd4daa6d9..603ae04837 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -141,6 +141,9 @@ struct CPURISCVState {
>  uint32_t misa_ext;  /* current extensions */
>  uint32_t misa_ext_mask; /* max ext for this cpu */
>
> +/* 128-bit helpers upper part return value */
> +target_ulong retxh;
> +
>  uint32_t features;
>
>  #ifdef CONFIG_USER_ONLY
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index c7a5376227..c036825723 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -1147,3 +1147,9 @@ DEF_HELPER_6(vcompress_vm_b, void, ptr, ptr, ptr, ptr, 
> env, i32)
>  DEF_HELPER_6(vcompress_vm_h, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vcompress_vm_w, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vcompress_vm_d, void, ptr, ptr, ptr, ptr, env, i32)
> +
> +/* 128-bit integer multiplication and division */
> +DEF_HELPER_5(divu_i128, tl, env, tl, tl, tl, tl)
> +DEF_HELPER_5(divs_i128, tl, env, tl, tl, tl, tl)
> +DEF_HELPER_5(remu_i128, tl, env, tl, tl, tl, tl)
> +DEF_HELPER_5(rems_i128, tl, env, tl, tl, tl, tl)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index afaf243b4e..16d40362e6 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -198,6 +198,13 @@ divuw001 .  . 101 . 0111011 @r
>  remw 001 .  . 110 . 0111011 @r
>  remuw001 .  . 111 . 0111011 @r
>
> +# *** RV128M Standard Extension (in addition to RV64M) ***
> +muld 001 .  . 000 . 011 @r
> +divd 001 .  . 100 . 011 @r
> +divud001 .  . 101 . 011 @r
> +remd 001 .  . 110 . 011 @r
> +remud001 .  . 111 . 011 @r
> +
>  # *** RV32A Standard Extension ***
>  lr_w   00010 . . 0 . 010 . 010 @atom_ld
>  sc_w   00011 . . . . 010 . 010 @atom_st
> diff --git a/target/riscv/m128_helper.c b/target/riscv/m128_helper.c
> new file mode 100644
> index 00..7bf115b85e
> --- /dev/null
> +++ b/target/riscv/m128_helper.c
> @@ -0,0 +1,109 @@
> +/*
> + * RISC-V Emulation Helpers for QEMU.
> + *
> + * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
> + * Copyright (c) 2017-2018 SiFive, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along 
> with
> + * this program.  If not, see .
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "qemu/main-loop.h"
> +#include "exec/exec-all.h"
> +#include "exec/helper-proto.h"
> +
> +target_ulong HELPER(divu_i128)(CPURISCVState *env,
> +   target_ulong ul, target_ulong uh,
> +   target_ulong vl, target_ulong vh)
> +{
> +target_ulong ql, qh;
> +Int128 q;
> +
> +if (vl == 0 && vh == 0) { /* Handle special behavior on div by zero */
> +ql = ~0x0;
> +qh = ~0x0;
> +} else {
> +q = int128_divu(int128_make128(ul, uh), int128_make128(vl, vh));
> +ql = int128_getlo(q);
> +qh = int128_gethi(q);
> +}
> +
> +env->retxh = qh;
> +return ql;
> +}
> +
> +target_ulong HELPER(remu_i128)(CPURISCVState *env,
> +   target_ulong ul, target_ulong uh,
> + 

[PATCH v7 14/18] target/riscv: support for 128-bit M extension

2021-12-13 Thread Frédéric Pétrot
Mult are generated inline (using a cool trick pointed out by Richard), but
for div and rem, given the complexity of the implementation of these
instructions, we call helpers to produce their behavior. From an
implementation standpoint, the helpers return the low part of the results,
while the high part is temporarily stored in a dedicated field of cpu_env
that is used to update the architectural register in the generation wrapper.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.h  |   3 +
 target/riscv/helper.h   |   6 +
 target/riscv/insn32.decode  |   7 +
 target/riscv/m128_helper.c  | 109 ++
 target/riscv/insn_trans/trans_rvm.c.inc | 182 ++--
 target/riscv/meson.build|   1 +
 6 files changed, 295 insertions(+), 13 deletions(-)
 create mode 100644 target/riscv/m128_helper.c

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index cbd4daa6d9..603ae04837 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -141,6 +141,9 @@ struct CPURISCVState {
 uint32_t misa_ext;  /* current extensions */
 uint32_t misa_ext_mask; /* max ext for this cpu */
 
+/* 128-bit helpers upper part return value */
+target_ulong retxh;
+
 uint32_t features;
 
 #ifdef CONFIG_USER_ONLY
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index c7a5376227..c036825723 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1147,3 +1147,9 @@ DEF_HELPER_6(vcompress_vm_b, void, ptr, ptr, ptr, ptr, 
env, i32)
 DEF_HELPER_6(vcompress_vm_h, void, ptr, ptr, ptr, ptr, env, i32)
 DEF_HELPER_6(vcompress_vm_w, void, ptr, ptr, ptr, ptr, env, i32)
 DEF_HELPER_6(vcompress_vm_d, void, ptr, ptr, ptr, ptr, env, i32)
+
+/* 128-bit integer multiplication and division */
+DEF_HELPER_5(divu_i128, tl, env, tl, tl, tl, tl)
+DEF_HELPER_5(divs_i128, tl, env, tl, tl, tl, tl)
+DEF_HELPER_5(remu_i128, tl, env, tl, tl, tl, tl)
+DEF_HELPER_5(rems_i128, tl, env, tl, tl, tl, tl)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index afaf243b4e..16d40362e6 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -198,6 +198,13 @@ divuw001 .  . 101 . 0111011 @r
 remw 001 .  . 110 . 0111011 @r
 remuw001 .  . 111 . 0111011 @r
 
+# *** RV128M Standard Extension (in addition to RV64M) ***
+muld 001 .  . 000 . 011 @r
+divd 001 .  . 100 . 011 @r
+divud001 .  . 101 . 011 @r
+remd 001 .  . 110 . 011 @r
+remud001 .  . 111 . 011 @r
+
 # *** RV32A Standard Extension ***
 lr_w   00010 . . 0 . 010 . 010 @atom_ld
 sc_w   00011 . . . . 010 . 010 @atom_st
diff --git a/target/riscv/m128_helper.c b/target/riscv/m128_helper.c
new file mode 100644
index 00..7bf115b85e
--- /dev/null
+++ b/target/riscv/m128_helper.c
@@ -0,0 +1,109 @@
+/*
+ * RISC-V Emulation Helpers for QEMU.
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "qemu/main-loop.h"
+#include "exec/exec-all.h"
+#include "exec/helper-proto.h"
+
+target_ulong HELPER(divu_i128)(CPURISCVState *env,
+   target_ulong ul, target_ulong uh,
+   target_ulong vl, target_ulong vh)
+{
+target_ulong ql, qh;
+Int128 q;
+
+if (vl == 0 && vh == 0) { /* Handle special behavior on div by zero */
+ql = ~0x0;
+qh = ~0x0;
+} else {
+q = int128_divu(int128_make128(ul, uh), int128_make128(vl, vh));
+ql = int128_getlo(q);
+qh = int128_gethi(q);
+}
+
+env->retxh = qh;
+return ql;
+}
+
+target_ulong HELPER(remu_i128)(CPURISCVState *env,
+   target_ulong ul, target_ulong uh,
+   target_ulong vl, target_ulong vh)
+{
+target_ulong rl, rh;
+Int128 r;
+
+if (vl == 0 && vh == 0) {
+rl = ul;
+rh = uh;
+} else {
+r = int128_remu(int128_make128(ul, uh), int128_make128(vl, vh));
+rl = int128_getlo(r);
+rh = int128_gethi(r);
+}
+
+env->retxh =