Re: [PATCH v2 40/43] contrib/plugins: extend execlog to track register changes

2024-01-11 Thread Frédéric Pétrot

Le 11/01/2024 à 13:24, Alex Bennée a écrit :

Frédéric Pétrot  writes:


Hello Alex,

   just reporting below what might be a riscv only oddity (also applies to
   patch 41 but easier to report here).

Le 03/01/2024 à 18:33, Alex Bennée a écrit :

With the new plugin register API we can now track changes to register
values. Currently the implementation is fairly dumb which will slow
down if a large number of register values are being tracked. This
could be improved by only instrumenting instructions which mention
registers we are interested in tracking.
Example usage:
./qemu-aarch64 -D plugin.log -d plugin \
   -cpu max,sve256=on \
   -plugin contrib/plugins/libexeclog.so,reg=sp,reg=z\* \
   ./tests/tcg/aarch64-linux-user/sha512-sve
will display in the execlog any changes to the stack pointer (sp)
and
the SVE Z registers.
Signed-off-by: Alex Bennée 
Cc: Akihiko Odaki 
Based-On: <20231025093128.33116-19-akihiko.od...@daynix.com>



+static registers_init(int vcpu_index)
+{
+GPtrArray *registers = g_ptr_array_new();
+g_autoptr(GArray) reg_list = qemu_plugin_get_registers(vcpu_index);
+
+if (reg_list && reg_list->len) {
+/*
+ * Go through each register in the complete list and
+ * see if we want to track it.
+ */
+for (int r = 0; r < reg_list->len; r++) {
+qemu_plugin_reg_descriptor *rd = _array_index(
+reg_list, qemu_plugin_reg_descriptor, r);


riscv csrs are not continously numbered and the dynamically generated gdb xml
seems to follow that scheme.
So the calls to Glib string functions output quite a few assertion
warnings because for the non existing csrs rd->name is NULL (and there
are a bit less than 4000 such cases for rv64g).
Checking for NULL and then continue is a simple way to solve the issue, but
I am not sure this is the proper way to proceed, as it might stand in the
generation of the riscv xml description for gdb.


I think in this case it might be easier to not expose it to the plugin
user at all. Is the lack of names an omission? How does gdb see them?


  Well, info all-registers in gdb dumps only the subset of cs registers
  that are defined for the current parameters of the gdbarch.
  Interestingly enough, riscv_print_registers_info, the function that dumps
  register values for riscv in gdb, contains the following comment :
  1385   /* Registers with no name are not valid on this ISA.  */
  and then a check on the "nullness" of the register name to avoid outputting
  something.
  I guess we could follow the same path in QEMU, as having access to the csrs
  in the plugins is really very useful.

  Thanks,
  Frédéric



Re: [PATCH v2 40/43] contrib/plugins: extend execlog to track register changes

2024-01-05 Thread Frédéric Pétrot

Hello Alex,

  just reporting below what might be a riscv only oddity (also applies to
  patch 41 but easier to report here).

Le 03/01/2024 à 18:33, Alex Bennée a écrit :

With the new plugin register API we can now track changes to register
values. Currently the implementation is fairly dumb which will slow
down if a large number of register values are being tracked. This
could be improved by only instrumenting instructions which mention
registers we are interested in tracking.

Example usage:

   ./qemu-aarch64 -D plugin.log -d plugin \
  -cpu max,sve256=on \
  -plugin contrib/plugins/libexeclog.so,reg=sp,reg=z\* \
  ./tests/tcg/aarch64-linux-user/sha512-sve

will display in the execlog any changes to the stack pointer (sp) and
the SVE Z registers.

Signed-off-by: Alex Bennée 
Cc: Akihiko Odaki 
Based-On: <20231025093128.33116-19-akihiko.od...@daynix.com>



+static registers_init(int vcpu_index)
+{
+GPtrArray *registers = g_ptr_array_new();
+g_autoptr(GArray) reg_list = qemu_plugin_get_registers(vcpu_index);
+
+if (reg_list && reg_list->len) {
+/*
+ * Go through each register in the complete list and
+ * see if we want to track it.
+ */
+for (int r = 0; r < reg_list->len; r++) {
+qemu_plugin_reg_descriptor *rd = _array_index(
+reg_list, qemu_plugin_reg_descriptor, r);


riscv csrs are not continously numbered and the dynamically generated gdb xml
seems to follow that scheme.
So the calls to Glib string functions output quite a few assertion
warnings because for the non existing csrs rd->name is NULL (and there
are a bit less than 4000 such cases for rv64g).
Checking for NULL and then continue is a simple way to solve the issue, but
I am not sure this is the proper way to proceed, as it might stand in the
generation of the riscv xml description for gdb.

Cheers,
Frédéric


+for (int p = 0; p < rmatches->len; p++) {
+g_autoptr(GPatternSpec) pat = 
g_pattern_spec_new(rmatches->pdata[p]);
+if (g_pattern_match_string(pat, rd->name)) {
+Register *reg = init_vcpu_register(vcpu_index, rd);
+g_ptr_array_add(registers, reg);
+}
+}
+}
+}
+cpus[num_cpus].registers = registers;
+}





Re: [PATCH 17/29] gdbstub: Simplify XML lookup

2023-11-07 Thread Frédéric Pétrot

Le 07/11/2023 à 11:31, Alex Bennée a écrit :

Frédéric Pétrot  writes:


Hello Alex and Akihiko,

this patch introduces a regression for riscv.
When connecting to gdb, gdb issues the infamous "Architecture rejected
target-supplied description" warning.


I tracked it down to 13/29 when bisecting which I dropped from:

   Message-Id: <20231106185112.2755262-1-alex.ben...@linaro.org>
   Date: Mon,  6 Nov 2023 18:50:50 +
   Subject: [PATCH 00/22] Maintainer updates for 8.2 (gdbstub, tests, plugins) 
pre-PR
   From: =?UTF-8?q?Alex=20Benn=C3=A9e?= 

So if you can check that series doesn't regress RiscV (it passes the
tests) then we can at least get some of the stuff merged during freeze.


  I do confirm that this fixes the issue with gdb, thanks !
--
+-------+
| Frédéric Pétrot,Pr. Grenoble INP-Ensimag/TIMA |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



Re: [PATCH 17/29] gdbstub: Simplify XML lookup

2023-11-07 Thread Frédéric Pétrot
 -223,11 +224,10 @@ static void cpu_common_unrealizefn(DeviceState *dev)
  static void cpu_common_initfn(Object *obj)
  {
  CPUState *cpu = CPU(obj);
-CPUClass *cc = CPU_GET_CLASS(obj);
  
+gdb_init_cpu(cpu);

  cpu->cpu_index = UNASSIGNED_CPU_INDEX;
  cpu->cluster_index = UNASSIGNED_CLUSTER_INDEX;
-cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
  /* user-mode doesn't have configurable SMP topology */
  /* the default value is changed by qemu_init_vcpu() for system-mode */
  cpu->nr_cores = 1;
@@ -247,6 +247,7 @@ static void cpu_common_finalize(Object *obj)
  {
  CPUState *cpu = CPU(obj);
  
+g_array_free(cpu->gdb_regs, TRUE);

  qemu_lockcnt_destroy(>in_ioctl_lock);
  qemu_mutex_destroy(>work_mutex);
  }


--
+---+
| Frédéric Pétrot,Pr. Grenoble INP-Ensimag/TIMA |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



[PATCH] x86_64/atomic128-ldst.h: fix arch include guard

2023-06-20 Thread Frédéric Pétrot
Fix arch name in the define that prevents multiple inclusions.

Signed-off-by: Frédéric Pétrot 
---
 host/include/x86_64/host/atomic128-ldst.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/host/include/x86_64/host/atomic128-ldst.h 
b/host/include/x86_64/host/atomic128-ldst.h
index adc9332f91..d0240d4212 100644
--- a/host/include/x86_64/host/atomic128-ldst.h
+++ b/host/include/x86_64/host/atomic128-ldst.h
@@ -8,8 +8,8 @@
  * atomic primitive is meant to provide.
  */
 
-#ifndef AARCH64_ATOMIC128_LDST_H
-#define AARCH64_ATOMIC128_LDST_H
+#ifndef X86_64_ATOMIC128_LDST_H
+#define X86_64_ATOMIC128_LDST_H
 
 #ifdef CONFIG_INT128_TYPE
 #include "host/cpuinfo.h"
@@ -65,4 +65,4 @@ static inline void atomic16_set(Int128 *ptr, Int128 val)
 #include "host/include/generic/host/atomic128-ldst.h"
 #endif
 
-#endif /* AARCH64_ATOMIC128_LDST_H */
+#endif /* X86_64_ATOMIC128_LDST_H */
-- 
2.30.2




Re: [PATCH] plugin: fix clearing of plugin_mem_cbs before TB exit

2023-02-28 Thread Frédéric Pétrot

Le 22/02/2023 à 05:32, Emilio Cota a écrit :

Currently we are wrongly accessing plugin_tb->mem_helper at
translation time from plugin_gen_disable_mem_helpers, which is
called before generating a TB exit, e.g. with exit_tb.

Recall that it is only during TB finalisation, i.e. when we go over
the TB post-translation to inject or remove plugin instrumentation,
when plugin_tb->mem_helper is set. This means that we never clear
plugin_mem_cbs when calling plugin_gen_disable_mem_helpers since
mem_helper is always false. Therefore a guest instruction that uses
helpers and emits an explicit TB exit results in plugin_mem_cbs being
set upon exiting, which is caught by an assertion as reported in
the reopening of issue #1381 and replicated below.

Fix this by (1) adding an insertion point before exiting a TB
("before_exit"), and (2) deciding whether or not to emit the
clearing of plugin_mem_cbs at this newly-added insertion point
during TB finalisation.

While at it, suffix plugin_gen_disable_mem_helpers with _before_exit
to make its intent more clear.

- Before:
$ ./qemu-system-riscv32 -M spike -nographic -plugin 
contrib/plugins/libexeclog.so -d plugin,in_asm,op
IN:
Priv: 3; Virt: 0
0x1000:  0297  auipc   t0,0
# 0x1000
0x1004:  02828613  addia2,t0,40
0x1008:  f1402573  csrrs   a0,mhartid,zero

OP:
  ld_i32 tmp1,env,$0xfff0
  brcond_i32 tmp1,$0x0,lt,$L0

   1000 
  mov_i64 tmp2,$0x7ff9940152e0
  ld_i32 tmp1,env,$0xef80
  call plugin(0x7ff9edbcb6f0),$0x11,$0,tmp1,tmp2
  mov_i32 x5/t0,$0x1000

   1004 
  mov_i64 tmp2,$0x7ff9940153e0
  ld_i32 tmp1,env,$0xef80
  call plugin(0x7ff9edbcb6f0),$0x11,$0,tmp1,tmp2
  add_i32 x12/a2,x5/t0,$0x28

   1008 f1402573
  mov_i64 tmp2,$0x7ff9940136c0
  st_i64 tmp2,env,$0xef68
  mov_i64 tmp2,$0x7ff994015530
  ld_i32 tmp1,env,$0xef80
  call plugin(0x7ff9edbcb6f0),$0x11,$0,tmp1,tmp2 <-- sets plugin_mem_cbs
  call csrr,$0x0,$1,x10/a0,env,$0xf14  <-- helper that might access memory
  mov_i32 pc,$0x100c
  exit_tb $0x0  <-- exit_tb right after the helper; missing clearing of 
plugin_mem_cbs
  mov_i64 tmp2,$0x0
  st_i64 tmp2,env,$0xef68 <-- after_insn clearing: dead due to 
exit_tb above
  set_label $L0
  exit_tb $0x7ff9a443 <-- again, missing clearing (doesn't matter due to 
$L0 label)

0, 0x1000, 0x297, "0297  auipc   t0,0
# 0x1000"
0, 0x1004, 0x2828613, "02828613  addia2,t0,40"
**
ERROR:../accel/tcg/cpu-exec.c:983:cpu_exec_loop: assertion failed: 
(cpu->plugin_mem_cbs == ((void *)0))
Bail out! ERROR:../accel/tcg/cpu-exec.c:983:cpu_exec_loop: assertion failed: 
(cpu->plugin_mem_cbs == ((void *)0))
Aborted (core dumped)

- After:
$ ./qemu-system-riscv32 -M spike -nographic -plugin 
contrib/plugins/libexeclog.so -d plugin,in_asm,op
(snip)
  call plugin(0x7f19bc9e36f0),$0x11,$0,tmp1,tmp2 <-- sets plugin_mem_cbs
  call csrr,$0x0,$1,x10/a0,env,$0xf14
  mov_i32 pc,$0x100c
  mov_i64 tmp2,$0x0
  st_i64 tmp2,env,$0xef68 <-- before_exit clearing of plugin_mem_cbs
  exit_tb $0x0
  mov_i64 tmp2,$0x0
  st_i64 tmp2,env,$0xef68 <-- after_insn clearing (dead)
  set_label $L0
  mov_i64 tmp2,$0x0
  st_i64 tmp2,env,$0xef68 <-- before_exit clearing (doesn't matter 
due to $L0)
  exit_tb $0x7f38c843
[...]

Fixes: #1381
Signed-off-by: Emilio Cota 
---
  accel/tcg/plugin-gen.c| 44 ---
  include/exec/plugin-gen.h |  4 ++--
  include/qemu/plugin.h |  3 ---
  tcg/tcg-op.c  |  6 +++---
  4 files changed, 28 insertions(+), 29 deletions(-)


   Thanks Emilio for the fix, and Aaron for pointing it out to me.

   Tested-by: Frédéric Pétrot 



[PATCH v2] hw/intc: sifive_plic: Renumber the S irqs for numa support

2022-11-14 Thread Frédéric Pétrot
Commit 40244040a7a changed the way the S irqs are numbered. This breaks when
using numa configuration, e.g.:
./qemu-system-riscv64 -nographic -machine virt,dumpdtb=numa-tree.dtb \
  -m 2G -smp cpus=16 \
  -object memory-backend-ram,id=mem0,size=512M \
  -object memory-backend-ram,id=mem1,size=512M \
  -object memory-backend-ram,id=mem2,size=512M \
  -object memory-backend-ram,id=mem3,size=512M \
  -numa node,cpus=0-3,memdev=mem0,nodeid=0 \
  -numa node,cpus=4-7,memdev=mem1,nodeid=1 \
  -numa node,cpus=8-11,memdev=mem2,nodeid=2 \
  -numa node,cpus=12-15,memdev=mem3,nodeid=3
leads to:
Unexpected error in object_property_find_err() at ../qom/object.c:1304:
qemu-system-riscv64: Property 'riscv.sifive.plic.unnamed-gpio-out[8]' not
found

This patch makes the nubering of the S irqs identical to what it was before.

Reviewed-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Frédéric Pétrot 
---
 hw/intc/sifive_plic.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index c2dfacf028..b4949bef97 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -476,11 +476,11 @@ DeviceState *sifive_plic_create(hwaddr addr, char 
*hart_config,
 CPUState *cpu = qemu_get_cpu(cpu_num);
 
 if (plic->addr_config[i].mode == PLICMode_M) {
-qdev_connect_gpio_out(dev, num_harts - plic->hartid_base + cpu_num,
+qdev_connect_gpio_out(dev, cpu_num - hartid_base + num_harts,
   qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
 }
 if (plic->addr_config[i].mode == PLICMode_S) {
-qdev_connect_gpio_out(dev, cpu_num,
+qdev_connect_gpio_out(dev, cpu_num - hartid_base,
   qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
 }
 }
-- 
2.37.2




Re: [PATCH] hw/intc: sifive_plic: Renumber the S irqs for numa support

2022-11-14 Thread Frédéric Pétrot

Le 14/11/2022 à 09:40, Philippe Mathieu-Daudé a écrit :

On 11/11/22 13:19, Frédéric Pétrot wrote:

Commit 40244040 changed the way the S irqs are numbered. This breaks when


40244040a7 in case?


  Seems reasonnable, indeed, I'll even align with what git blame shows
  (11 chars, so 40244040a7a).


using numa configuration, e.g.:
./qemu-system-riscv64 -nographic -machine virt,dumpdtb=numa-tree.dtb \
   -m 2G -smp cpus=16 \
  -object memory-backend-ram,id=mem0,size=512M \
  -object memory-backend-ram,id=mem1,size=512M \
  -object memory-backend-ram,id=mem2,size=512M \
  -object memory-backend-ram,id=mem3,size=512M \
  -numa node,cpus=0-3,memdev=mem0,nodeid=0 \
  -numa node,cpus=4-7,memdev=mem1,nodeid=1 \
  -numa node,cpus=8-11,memdev=mem2,nodeid=2 \
  -numa node,cpus=12-15,memdev=mem3,nodeid=3
leads to:
Unexpected error in object_property_find_err() at ../qom/object.c:1304:
qemu-system-riscv64: Property 'riscv.sifive.plic.unnamed-gpio-out[8]' not
found

This patch makes the nubering of the S irqs identical to what it was before.

Signed-off-by: Frédéric Pétrot 
---
  hw/intc/sifive_plic.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index c2dfacf028..89d2122742 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -480,7 +480,7 @@ DeviceState *sifive_plic_create(hwaddr addr, char 
*hart_config,

    qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
  }
  if (plic->addr_config[i].mode == PLICMode_S) {
-    qdev_connect_gpio_out(dev, cpu_num,
+    qdev_connect_gpio_out(dev, cpu_num - plic->hartid_base,
    qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
  }
  }


Oops. >
Eventually we could unify the style:

-- >8 --
@@ -476,11 +476,11 @@ DeviceState *sifive_plic_create(hwaddr addr, char 
*hart_config,

  CPUState *cpu = qemu_get_cpu(cpu_num);

  if (plic->addr_config[i].mode == PLICMode_M) {
-    qdev_connect_gpio_out(dev, num_harts - plic->hartid_base + cpu_num,
+    qdev_connect_gpio_out(dev, cpu_num - hartid_base + num_harts,
    qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
  }
  if (plic->addr_config[i].mode == PLICMode_S) {
-    qdev_connect_gpio_out(dev, cpu_num,
+    qdev_connect_gpio_out(dev, cpu_num - hartid_base,hartid_base
    qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
  }
  }
---


  IIUC hartid_base is used to set plic->hartid_base, so agreed, along with the
  style unification.
  I'll send a v2, then.
  Since Alistair already queued the patch, how shall I proceed?


Reviewed-by: Philippe Mathieu-Daudé 



--
+-------+
| Frédéric Pétrot,Pr. Grenoble INP-Ensimag/TIMA |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



[PATCH] hw/intc: sifive_plic: Renumber the S irqs for numa support

2022-11-11 Thread Frédéric Pétrot
Commit 40244040 changed the way the S irqs are numbered. This breaks when
using numa configuration, e.g.:
./qemu-system-riscv64 -nographic -machine virt,dumpdtb=numa-tree.dtb \
  -m 2G -smp cpus=16 \
  -object memory-backend-ram,id=mem0,size=512M \
  -object memory-backend-ram,id=mem1,size=512M \
  -object memory-backend-ram,id=mem2,size=512M \
  -object memory-backend-ram,id=mem3,size=512M \
  -numa node,cpus=0-3,memdev=mem0,nodeid=0 \
  -numa node,cpus=4-7,memdev=mem1,nodeid=1 \
  -numa node,cpus=8-11,memdev=mem2,nodeid=2 \
  -numa node,cpus=12-15,memdev=mem3,nodeid=3
leads to:
Unexpected error in object_property_find_err() at ../qom/object.c:1304:
qemu-system-riscv64: Property 'riscv.sifive.plic.unnamed-gpio-out[8]' not
found

This patch makes the nubering of the S irqs identical to what it was before.

Signed-off-by: Frédéric Pétrot 
---
 hw/intc/sifive_plic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index c2dfacf028..89d2122742 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -480,7 +480,7 @@ DeviceState *sifive_plic_create(hwaddr addr, char 
*hart_config,
   qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
 }
 if (plic->addr_config[i].mode == PLICMode_S) {
-qdev_connect_gpio_out(dev, cpu_num,
+qdev_connect_gpio_out(dev, cpu_num - plic->hartid_base,
   qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
 }
 }
-- 
2.37.2




Re: [PATCH v2] target/riscv: fix shifts shamt value for rv128c

2022-07-11 Thread Frédéric Pétrot

Hi Richard,

Le 11/07/2022 à 06:44, Richard Henderson a écrit :
On Sun, 10 July 2022, 16:36 Frédéric Pétrot, 
<mailto:frederic.pet...@univ-grenoble-alpes.fr>> wrote:


For rv128c shifts, a shamt of 0 is a shamt of 64, while for rv32c/rv64c
it stays 0 and is a hint instruction that does not change processor state.
For rv128c right shifts, the 6-bit shamt is in addition sign extended to
7 bits.


Um, what says that? First, it makes no sense — while some systems define 
negative shifts as opposite direction, riscv is not one of them.


  This is here (I just pulled riscv-isa-manual and recompiled to be right on
  the page): Volume I: RISC-V Unprivileged ISA V20191214-draft (same branch as
  the one you indicate), page 119 & 120.
  This applies *only* to the compressed instructions c.srli and c.srai, not to
  their uncompressed version (the 0 becoming 64 also applies to c.slli).
  "Sign extension" is duplication of the 6th bit on the 7th bit only, and the
  top bits are zeroed, thus leading to shamts of 1-31, 64, 96-127.


Second, the 20220707 draft spec does not agree with you:

   Shifts by an immediate (SLLI/SRLI/SRAI)
   are now encoded using the low 7 bits of
   the I-immediate >
Nothing about that sentence says "signed".


  Agreed, on the non compressed insns, but the compressed ones have a 6-bit
  shamt only as visible on page 18.6 page 125. The explanation for rv128 shifts
  is further detailed in the emphasized paragraph on top of page 120.

  Frédéric



r~


Signed-off-by: Frédéric Pétrot mailto:frederic.pet...@univ-grenoble-alpes.fr>>
---
  target/riscv/insn16.decode |  7 ---
  disas/riscv.c              | 27 +--
  target/riscv/translate.c   | 20 ++--
  3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 02c8f61b48..ccfe59f294 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -31,7 +31,8 @@
  %imm_cb        12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
  %imm_cj        12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1

-%shimm_6bit   12:1 2:5               !function=ex_rvc_shifti
+%shlimm_6bit  12:1 2:5               !function=ex_rvc_shiftli
+%shrimm_6bit  12:1 2:5               !function=ex_rvc_shiftri
  %uimm_6bit_lq 2:4 12:1 6:1           !function=ex_shift_4
  %uimm_6bit_ld 2:3 12:1 5:2           !function=ex_shift_3
  %uimm_6bit_lw 2:2 12:1 4:3           !function=ex_shift_2
@@ -82,9 +83,9 @@
  @c_addi16sp     ... .  . . ..  imm=%imm_addi16sp rs1=2 rd=2

  @c_shift        ... . .. ... . .. \
-                 rd=%rs1_3 rs1=%rs1_3 shamt=%shimm_6bit
+                 rd=%rs1_3 rs1=%rs1_3 shamt=%shrimm_6bit
  @c_shift2       ... . .. ... . .. \
-                 rd=%rd rs1=%rd shamt=%shimm_6bit
+                 rd=%rd rs1=%rd shamt=%shlimm_6bit

  @c_andi         ... . .. ... . ..  imm=%imm_ci rs1=%rs1_3 rd=%rs1_3

diff --git a/disas/riscv.c b/disas/riscv.c
index 7af6afc8fa..489c2ae5e8 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -2402,10 +2402,25 @@ static int32_t operand_sbimm12(rv_inst inst)
          ((inst << 56) >> 63) << 11;
  }

-static uint32_t operand_cimmsh6(rv_inst inst)
+static uint32_t operand_cimmshl6(rv_inst inst, rv_isa isa)
  {
-    return ((inst << 51) >> 63) << 5 |
+    int imm = ((inst << 51) >> 63) << 5 |
          (inst << 57) >> 59;
+    if (isa == rv128) {
+        imm = imm ? imm : 64;
+    }
+    return imm;
+}
+
+static uint32_t operand_cimmshr6(rv_inst inst, rv_isa isa)
+{
+    int imm = ((inst << 51) >> 63) << 5 |
+        (inst << 57) >> 59;
+    if (isa == rv128) {
+        imm = imm | (imm & 32) << 1;
+        imm = imm ? imm : 64;
+    }
+    return imm;
  }

  static int32_t operand_cimmi(rv_inst inst)
@@ -2529,7 +2544,7 @@ static uint32_t operand_rnum(rv_inst inst)

  /* decode operands */

-static void decode_inst_operands(rv_decode *dec)
+static void decode_inst_operands(rv_decode *dec, rv_isa isa)
  {
      rv_inst inst = dec->inst;
      dec->codec = opcode_data[dec->op].codec;
@@ -2652,7 +2667,7 @@ static void decode_inst_operands(rv_decode *dec)
      case rv_codec_cb_sh6:
          dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
          dec->rs2 = rv_ireg_zero;
-        dec->imm = operand_cimmsh6(inst);
+        dec->imm = operand_cimmshr6(inst, isa);
          break;
      case rv_codec_ci:
          dec->rd = dec->rs1 = operand_crs1rd(inst);
@@ -2667,7 +2682,7 @@ static void decode_i

[PATCH v2] target/riscv: fix shifts shamt value for rv128c

2022-07-10 Thread Frédéric Pétrot
For rv128c shifts, a shamt of 0 is a shamt of 64, while for rv32c/rv64c
it stays 0 and is a hint instruction that does not change processor state.
For rv128c right shifts, the 6-bit shamt is in addition sign extended to
7 bits.

Signed-off-by: Frédéric Pétrot 
---
 target/riscv/insn16.decode |  7 ---
 disas/riscv.c  | 27 +--
 target/riscv/translate.c   | 20 ++--
 3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 02c8f61b48..ccfe59f294 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -31,7 +31,8 @@
 %imm_cb12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
 %imm_cj12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
 
-%shimm_6bit   12:1 2:5   !function=ex_rvc_shifti
+%shlimm_6bit  12:1 2:5   !function=ex_rvc_shiftli
+%shrimm_6bit  12:1 2:5   !function=ex_rvc_shiftri
 %uimm_6bit_lq 2:4 12:1 6:1   !function=ex_shift_4
 %uimm_6bit_ld 2:3 12:1 5:2   !function=ex_shift_3
 %uimm_6bit_lw 2:2 12:1 4:3   !function=ex_shift_2
@@ -82,9 +83,9 @@
 @c_addi16sp ... .  . . ..  imm=%imm_addi16sp rs1=2 rd=2
 
 @c_shift... . .. ... . .. \
- rd=%rs1_3 rs1=%rs1_3 shamt=%shimm_6bit
+ rd=%rs1_3 rs1=%rs1_3 shamt=%shrimm_6bit
 @c_shift2   ... . .. ... . .. \
- rd=%rd rs1=%rd shamt=%shimm_6bit
+ rd=%rd rs1=%rd shamt=%shlimm_6bit
 
 @c_andi ... . .. ... . ..  imm=%imm_ci rs1=%rs1_3 rd=%rs1_3
 
diff --git a/disas/riscv.c b/disas/riscv.c
index 7af6afc8fa..489c2ae5e8 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -2402,10 +2402,25 @@ static int32_t operand_sbimm12(rv_inst inst)
 ((inst << 56) >> 63) << 11;
 }
 
-static uint32_t operand_cimmsh6(rv_inst inst)
+static uint32_t operand_cimmshl6(rv_inst inst, rv_isa isa)
 {
-return ((inst << 51) >> 63) << 5 |
+int imm = ((inst << 51) >> 63) << 5 |
 (inst << 57) >> 59;
+if (isa == rv128) {
+imm = imm ? imm : 64;
+}
+return imm;
+}
+
+static uint32_t operand_cimmshr6(rv_inst inst, rv_isa isa)
+{
+int imm = ((inst << 51) >> 63) << 5 |
+(inst << 57) >> 59;
+if (isa == rv128) {
+imm = imm | (imm & 32) << 1;
+imm = imm ? imm : 64;
+}
+return imm;
 }
 
 static int32_t operand_cimmi(rv_inst inst)
@@ -2529,7 +2544,7 @@ static uint32_t operand_rnum(rv_inst inst)
 
 /* decode operands */
 
-static void decode_inst_operands(rv_decode *dec)
+static void decode_inst_operands(rv_decode *dec, rv_isa isa)
 {
 rv_inst inst = dec->inst;
 dec->codec = opcode_data[dec->op].codec;
@@ -2652,7 +2667,7 @@ static void decode_inst_operands(rv_decode *dec)
 case rv_codec_cb_sh6:
 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
 dec->rs2 = rv_ireg_zero;
-dec->imm = operand_cimmsh6(inst);
+dec->imm = operand_cimmshr6(inst, isa);
 break;
 case rv_codec_ci:
 dec->rd = dec->rs1 = operand_crs1rd(inst);
@@ -2667,7 +2682,7 @@ static void decode_inst_operands(rv_decode *dec)
 case rv_codec_ci_sh6:
 dec->rd = dec->rs1 = operand_crs1rd(inst);
 dec->rs2 = rv_ireg_zero;
-dec->imm = operand_cimmsh6(inst);
+dec->imm = operand_cimmshl6(inst, isa);
 break;
 case rv_codec_ci_16sp:
 dec->rd = rv_ireg_sp;
@@ -3193,7 +3208,7 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, 
uint64_t pc, rv_inst inst)
 dec.pc = pc;
 dec.inst = inst;
 decode_inst_opcode(, isa);
-decode_inst_operands();
+decode_inst_operands(, isa);
 decode_inst_decompress(, isa);
 decode_inst_lift_pseudo();
 format_inst(buf, buflen, 16, );
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 63b04e8a94..d7c82a9c81 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -705,10 +705,26 @@ static int ex_rvc_register(DisasContext *ctx, int reg)
 return 8 + reg;
 }
 
-static int ex_rvc_shifti(DisasContext *ctx, int imm)
+static int ex_rvc_shiftli(DisasContext *ctx, int imm)
 {
 /* For RV128 a shamt of 0 means a shift by 64. */
-return imm ? imm : 64;
+if (get_ol(ctx) == MXL_RV128) {
+imm = imm ? imm : 64;
+}
+return imm;
+}
+
+static int ex_rvc_shiftri(DisasContext *ctx, int imm)
+{
+/*
+ * For RV128 a shamt of 0 means a shift by 64, furthermore, for right
+ * shifts, the shamt is sign-extended.
+ */
+if (get_ol(ctx) == MXL_RV128) {
+imm = imm | (imm & 32) << 1;
+imm = imm ? imm : 64;
+}
+return imm;
 }
 
 /* Include the auto-generated decoder for 32 bit insn */
-- 
2.36.1




Re: [PATCH] target/riscv: fix right shifts shamt value for rv128c

2022-07-09 Thread Frédéric Pétrot

Le 09/07/2022 à 10:52, Weiwei Li a écrit :


在 2022/7/8 下午11:00, Frédéric Pétrot 写道:

For rv128c right shifts, the 6-bit shamt is sign extended to 7 bits.

Signed-off-by: Frédéric Pétrot
---
  target/riscv/insn16.decode |  7 ---
  disas/riscv.c  | 27 +--
  target/riscv/translate.c   | 12 +++-
  3 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 02c8f61b48..ea3c5a0411 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -31,7 +31,8 @@
  %imm_cb12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
  %imm_cj12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
  
-%shimm_6bit   12:1 2:5   !function=ex_rvc_shifti

+%shlimm_6bit   12:1 2:5  !function=ex_rvc_shiftli
+%shrimm_6bit   12:1 2:5  !function=ex_rvc_shiftri
  %uimm_6bit_lq 2:4 12:1 6:1   !function=ex_shift_4
  %uimm_6bit_ld 2:3 12:1 5:2   !function=ex_shift_3
  %uimm_6bit_lw 2:2 12:1 4:3   !function=ex_shift_2


It's better to maintain the alignment here.


  Ooups! I'll do that.




@@ -82,9 +83,9 @@
  @c_addi16sp ... .  . . ..  imm=%imm_addi16sp rs1=2 rd=2
  
  @c_shift... . .. ... . .. \

- rd=%rs1_3 rs1=%rs1_3 shamt=%shimm_6bit
+ rd=%rs1_3 rs1=%rs1_3 shamt=%shrimm_6bit
  @c_shift2   ... . .. ... . .. \
- rd=%rd rs1=%rd shamt=%shimm_6bit
+ rd=%rd rs1=%rd shamt=%shlimm_6bit
  
  @c_andi ... . .. ... . ..  imm=%imm_ci rs1=%rs1_3 rd=%rs1_3
  
diff --git a/disas/riscv.c b/disas/riscv.c

index 7af6afc8fa..489c2ae5e8 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -2402,10 +2402,25 @@ static int32_t operand_sbimm12(rv_inst inst)
  ((inst << 56) >> 63) << 11;
  }
  
-static uint32_t operand_cimmsh6(rv_inst inst)

+static uint32_t operand_cimmshl6(rv_inst inst, rv_isa isa)
  {
-return ((inst << 51) >> 63) << 5 |
+int imm = ((inst << 51) >> 63) << 5 |
  (inst << 57) >> 59;
+if (isa == rv128) {
+imm = imm ? imm : 64;
+}
+return imm;
+}
+
+static uint32_t operand_cimmshr6(rv_inst inst, rv_isa isa)
+{
+int imm = ((inst << 51) >> 63) << 5 |
+(inst << 57) >> 59;
+if (isa == rv128) {
+imm = imm | (imm & 32) << 1;
+imm = imm ? imm : 64;
+}
+return imm;
  }
  
  static int32_t operand_cimmi(rv_inst inst)

@@ -2529,7 +2544,7 @@ static uint32_t operand_rnum(rv_inst inst)
  
  /* decode operands */
  
-static void decode_inst_operands(rv_decode *dec)

+static void decode_inst_operands(rv_decode *dec, rv_isa isa)
  {
  rv_inst inst = dec->inst;
  dec->codec = opcode_data[dec->op].codec;
@@ -2652,7 +2667,7 @@ static void decode_inst_operands(rv_decode *dec)
  case rv_codec_cb_sh6:
  dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
  dec->rs2 = rv_ireg_zero;
-dec->imm = operand_cimmsh6(inst);
+dec->imm = operand_cimmshr6(inst, isa);
  break;
  case rv_codec_ci:
  dec->rd = dec->rs1 = operand_crs1rd(inst);
@@ -2667,7 +2682,7 @@ static void decode_inst_operands(rv_decode *dec)
  case rv_codec_ci_sh6:
  dec->rd = dec->rs1 = operand_crs1rd(inst);
  dec->rs2 = rv_ireg_zero;
-dec->imm = operand_cimmsh6(inst);
+dec->imm = operand_cimmshl6(inst, isa);
  break;
  case rv_codec_ci_16sp:
  dec->rd = rv_ireg_sp;
@@ -3193,7 +3208,7 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, 
uint64_t pc, rv_inst inst)
  dec.pc = pc;
  dec.inst = inst;
  decode_inst_opcode(, isa);
-decode_inst_operands();
+decode_inst_operands(, isa);
  decode_inst_decompress(, isa);
  decode_inst_lift_pseudo();
  format_inst(buf, buflen, 16, );
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 63b04e8a94..af3a2cd68c 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -705,12 +705,22 @@ static int ex_rvc_register(DisasContext *ctx, int reg)
  return 8 + reg;
  }
  
-static int ex_rvc_shifti(DisasContext *ctx, int imm)

+static int ex_rvc_shiftli(DisasContext *ctx, int imm)
  {
  /* For RV128 a shamt of 0 means a shift by 64. */
  return imm ? imm : 64;
  }
  
+static int ex_rvc_shiftri(DisasContext *ctx, int imm)

+{
+/*
+ * For RV128 a shamt of 0 means a shift by 64, furthermore, for right
+ * shifts, the shamt is sign-extended.
+ */
+imm = imm | (imm & 32) << 1;
+return imm ? imm : 64;
+}
+


This calculation didn't add limitation for only working in RV128, and may 
trigger fault in RV32/RV64,


such as following check in gen_shift_imm_fn:

if (a->shamt >= max_len) {
return false;
}


  Indeed! Thanks for p

[PATCH] target/riscv: fix right shifts shamt value for rv128c

2022-07-08 Thread Frédéric Pétrot
For rv128c right shifts, the 6-bit shamt is sign extended to 7 bits.

Signed-off-by: Frédéric Pétrot 
---
 target/riscv/insn16.decode |  7 ---
 disas/riscv.c  | 27 +--
 target/riscv/translate.c   | 12 +++-
 3 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 02c8f61b48..ea3c5a0411 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -31,7 +31,8 @@
 %imm_cb12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
 %imm_cj12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
 
-%shimm_6bit   12:1 2:5   !function=ex_rvc_shifti
+%shlimm_6bit   12:1 2:5  !function=ex_rvc_shiftli
+%shrimm_6bit   12:1 2:5  !function=ex_rvc_shiftri
 %uimm_6bit_lq 2:4 12:1 6:1   !function=ex_shift_4
 %uimm_6bit_ld 2:3 12:1 5:2   !function=ex_shift_3
 %uimm_6bit_lw 2:2 12:1 4:3   !function=ex_shift_2
@@ -82,9 +83,9 @@
 @c_addi16sp ... .  . . ..  imm=%imm_addi16sp rs1=2 rd=2
 
 @c_shift... . .. ... . .. \
- rd=%rs1_3 rs1=%rs1_3 shamt=%shimm_6bit
+ rd=%rs1_3 rs1=%rs1_3 shamt=%shrimm_6bit
 @c_shift2   ... . .. ... . .. \
- rd=%rd rs1=%rd shamt=%shimm_6bit
+ rd=%rd rs1=%rd shamt=%shlimm_6bit
 
 @c_andi ... . .. ... . ..  imm=%imm_ci rs1=%rs1_3 rd=%rs1_3
 
diff --git a/disas/riscv.c b/disas/riscv.c
index 7af6afc8fa..489c2ae5e8 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -2402,10 +2402,25 @@ static int32_t operand_sbimm12(rv_inst inst)
 ((inst << 56) >> 63) << 11;
 }
 
-static uint32_t operand_cimmsh6(rv_inst inst)
+static uint32_t operand_cimmshl6(rv_inst inst, rv_isa isa)
 {
-return ((inst << 51) >> 63) << 5 |
+int imm = ((inst << 51) >> 63) << 5 |
 (inst << 57) >> 59;
+if (isa == rv128) {
+imm = imm ? imm : 64;
+}
+return imm;
+}
+
+static uint32_t operand_cimmshr6(rv_inst inst, rv_isa isa)
+{
+int imm = ((inst << 51) >> 63) << 5 |
+(inst << 57) >> 59;
+if (isa == rv128) {
+imm = imm | (imm & 32) << 1;
+imm = imm ? imm : 64;
+}
+return imm;
 }
 
 static int32_t operand_cimmi(rv_inst inst)
@@ -2529,7 +2544,7 @@ static uint32_t operand_rnum(rv_inst inst)
 
 /* decode operands */
 
-static void decode_inst_operands(rv_decode *dec)
+static void decode_inst_operands(rv_decode *dec, rv_isa isa)
 {
 rv_inst inst = dec->inst;
 dec->codec = opcode_data[dec->op].codec;
@@ -2652,7 +2667,7 @@ static void decode_inst_operands(rv_decode *dec)
 case rv_codec_cb_sh6:
 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
 dec->rs2 = rv_ireg_zero;
-dec->imm = operand_cimmsh6(inst);
+dec->imm = operand_cimmshr6(inst, isa);
 break;
 case rv_codec_ci:
 dec->rd = dec->rs1 = operand_crs1rd(inst);
@@ -2667,7 +2682,7 @@ static void decode_inst_operands(rv_decode *dec)
 case rv_codec_ci_sh6:
 dec->rd = dec->rs1 = operand_crs1rd(inst);
 dec->rs2 = rv_ireg_zero;
-dec->imm = operand_cimmsh6(inst);
+dec->imm = operand_cimmshl6(inst, isa);
 break;
 case rv_codec_ci_16sp:
 dec->rd = rv_ireg_sp;
@@ -3193,7 +3208,7 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, 
uint64_t pc, rv_inst inst)
 dec.pc = pc;
 dec.inst = inst;
 decode_inst_opcode(, isa);
-decode_inst_operands();
+decode_inst_operands(, isa);
 decode_inst_decompress(, isa);
 decode_inst_lift_pseudo();
 format_inst(buf, buflen, 16, );
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 63b04e8a94..af3a2cd68c 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -705,12 +705,22 @@ static int ex_rvc_register(DisasContext *ctx, int reg)
 return 8 + reg;
 }
 
-static int ex_rvc_shifti(DisasContext *ctx, int imm)
+static int ex_rvc_shiftli(DisasContext *ctx, int imm)
 {
 /* For RV128 a shamt of 0 means a shift by 64. */
 return imm ? imm : 64;
 }
 
+static int ex_rvc_shiftri(DisasContext *ctx, int imm)
+{
+/*
+ * For RV128 a shamt of 0 means a shift by 64, furthermore, for right
+ * shifts, the shamt is sign-extended.
+ */
+imm = imm | (imm & 32) << 1;
+return imm ? imm : 64;
+}
+
 /* Include the auto-generated decoder for 32 bit insn */
 #include "decode-insn32.c.inc"
 
-- 
2.36.1




[PATCH] target/riscv/debug.c: keep experimental rv128 support working

2022-06-02 Thread Frédéric Pétrot
Add an MXL_RV128 case in two switches so that no error is triggered when
using the -cpu x-rv128 option.

Signed-off-by: Frédéric Pétrot 
---
 target/riscv/debug.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 2f2a51c732..fc6e13222f 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -77,6 +77,7 @@ static inline target_ulong trigger_type(CPURISCVState *env,
 tdata1 = RV32_TYPE(type);
 break;
 case MXL_RV64:
+case MXL_RV128:
 tdata1 = RV64_TYPE(type);
 break;
 default:
@@ -123,6 +124,7 @@ static target_ulong tdata1_validate(CPURISCVState *env, 
target_ulong val,
 tdata1 = RV32_TYPE(t);
 break;
 case MXL_RV64:
+case MXL_RV128:
 type = extract64(val, 60, 4);
 dmode = extract64(val, 59, 1);
 tdata1 = RV64_TYPE(t);
--
2.36.1




Re: [PATCH] target/riscv: replace TARGET_LONG_BITS in gdbstub

2022-04-13 Thread Frédéric Pétrot




Le 09/04/2022 à 17:39, Richard Henderson a écrit :

On 4/9/22 02:46, Frédéric Pétrot wrote:

Now that we have misa xlen, use that in riscv gdbstub.c instead of the
TARGET_LONG_BITS define, and use riscv_cpu_mxl_bits to provide the number of
bits in a consistent way.

Signed-off-by: Frédéric Pétrot 
---
  target/riscv/gdbstub.c | 7 ---
  1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 9ed049c29e..1602f76d2b 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -305,7 +305,7 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)

  CPURISCVState *env = >env;
  GString *s = g_string_new(NULL);
  riscv_csr_predicate_fn predicate;
-    int bitsize = 16 << env->misa_mxl_max;
+    int bitsize = riscv_cpu_mxl_bits(env);


This isn't correct, changing from using max to current mxl.

You might think this is ok, because this will run up in startup, but it really 
runs whenever gdb attaches to the stub.  Which could be anytime.


  I guess it should then be gdb responsibility to check mxl/sxl/uxl and act
  accordingly.
  I'll introduce a new macro then.
  Thanks,
  Frédéric




r~


--
+---+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



[PATCH] target/riscv: use xlen in forging isa string

2022-04-09 Thread Frédéric Pétrot
Since we now have xlen in misa, let's not use TARGET_LONG_BITS while
forging the isa string, and use instead riscv_cpu_mxl_bits.

Signed-off-by: Frédéric Pétrot 
---
 target/riscv/cpu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0c774056c5..0644b3843e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -984,7 +984,8 @@ char *riscv_isa_string(RISCVCPU *cpu)
 int i;
 const size_t maxlen = sizeof("rv128") + sizeof(riscv_single_letter_exts);
 char *isa_str = g_new(char, maxlen);
-char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);
+char *p = isa_str + snprintf(isa_str, maxlen, "rv%lu",
+ riscv_cpu_mxl_bits(>env));
 for (i = 0; i < sizeof(riscv_single_letter_exts) - 1; i++) {
 if (cpu->env.misa_ext & RV(riscv_single_letter_exts[i])) {
 *p++ = qemu_tolower(riscv_single_letter_exts[i]);
-- 
2.35.1




[PATCH] target/riscv: replace TARGET_LONG_BITS in gdbstub

2022-04-09 Thread Frédéric Pétrot
Now that we have misa xlen, use that in riscv gdbstub.c instead of the
TARGET_LONG_BITS define, and use riscv_cpu_mxl_bits to provide the number of
bits in a consistent way.

Signed-off-by: Frédéric Pétrot 
---
 target/riscv/gdbstub.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 9ed049c29e..1602f76d2b 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -305,7 +305,7 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)
 CPURISCVState *env = >env;
 GString *s = g_string_new(NULL);
 riscv_csr_predicate_fn predicate;
-int bitsize = 16 << env->misa_mxl_max;
+int bitsize = riscv_cpu_mxl_bits(env);
 int i;
 
 /* Until gdb knows about 128-bit registers */
@@ -385,10 +385,11 @@ static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int 
base_reg)
 
 for (i = 0; i < 7; i++) {
 g_string_append_printf(s,
-   "",
-   vector_csrs[i], TARGET_LONG_BITS, base_reg++);
+   vector_csrs[i], riscv_cpu_mxl_bits(>env),
+   base_reg++);
 num_regs++;
 }
 
-- 
2.35.1




Re: [PATCH v2 1/1] target/riscv: misa to ISA string conversion fix

2022-03-30 Thread Frédéric Pétrot

Le 30/03/2022 à 04:08, Tsukasa OI a écrit :

On 2022/03/30 1:29, Frédéric Pétrot wrote:

Hello,

Le 28/03/2022 à 15:11, Tsukasa OI a écrit :

Some bits in RISC-V `misa' CSR should not be reflected in the ISA
string.  For instance, `S' and `U' (represents existence of supervisor
and user mode, respectively) in `misa' CSR must not be copied since
neither `S' nor `U' are valid single-letter extensions.

This commit also removes all reserved/dropped single-letter "extensions"
from the list.

-   "B": Not going to be a single-letter extension (misa.B is reserved).
-   "J": Not going to be a single-letter extension (misa.J is reserved).
-   "K": Not going to be a single-letter extension (misa.K is reserved).
-   "L": Dropped.
-   "N": Dropped.
-   "T": Dropped.

It also clarifies that the variable `riscv_single_letter_exts' is a
single-letter extension order list.

Signed-off-by: Tsukasa OI 
---
   target/riscv/cpu.c | 10 +-
   1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ddda4906ff..1f68c696eb 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -34,7 +34,7 @@
     /* RISC-V CPU definitions */
   -static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
+static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
     const char * const riscv_int_regnames[] = {
     "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
@@ -901,12 +901,12 @@ static void riscv_cpu_class_init(ObjectClass *c, void 
*data)
   char *riscv_isa_string(RISCVCPU *cpu)
   {
   int i;
-    const size_t maxlen = sizeof("rv128") + sizeof(riscv_exts) + 1;
+    const size_t maxlen = sizeof("rv128") + sizeof(riscv_single_letter_exts);
   char *isa_str = g_new(char, maxlen);
   char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);


To avoid one dependency on TARGET_LONG_BITS that is not necessary now that we
have mxl, I would suggest to replace the previous line with:
  char *p = isa_str + snprintf(isa_str, maxlen, "rv%d",
   1 << (4 + cpu->env.misa_mxl_max));


LGTM except... that won't be a part of my patch (you are trying to fix
separate issue).  You can submit separate patch for this.


  Sure, I'll do that.


To comment, I like
16 << cpu->env.misa_mxl_max
rather than
1 << (4 + cpu->env.misa_mxl_max)
for consistency with target/riscv/gdbstub.c:
int bitsize = 16 << env->misa_mxl_max;


  Good point.
  However, perhaps I should rather change target/riscv/gdbstub.c, to better fit
  the note page 16 (no pun intended) of the priviledged spec that expresses
  bitsize as $2^{MXL+4}$.

  Frédéric



Tsukasa



Frédéric



--
+---+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



Re: [PATCH v2 1/1] target/riscv: misa to ISA string conversion fix

2022-03-29 Thread Frédéric Pétrot

Hello,

Le 28/03/2022 à 15:11, Tsukasa OI a écrit :

Some bits in RISC-V `misa' CSR should not be reflected in the ISA
string.  For instance, `S' and `U' (represents existence of supervisor
and user mode, respectively) in `misa' CSR must not be copied since
neither `S' nor `U' are valid single-letter extensions.

This commit also removes all reserved/dropped single-letter "extensions"
from the list.

-   "B": Not going to be a single-letter extension (misa.B is reserved).
-   "J": Not going to be a single-letter extension (misa.J is reserved).
-   "K": Not going to be a single-letter extension (misa.K is reserved).
-   "L": Dropped.
-   "N": Dropped.
-   "T": Dropped.

It also clarifies that the variable `riscv_single_letter_exts' is a
single-letter extension order list.

Signed-off-by: Tsukasa OI 
---
  target/riscv/cpu.c | 10 +-
  1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ddda4906ff..1f68c696eb 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -34,7 +34,7 @@
  
  /* RISC-V CPU definitions */
  
-static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";

+static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
  
  const char * const riscv_int_regnames[] = {

"x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
@@ -901,12 +901,12 @@ static void riscv_cpu_class_init(ObjectClass *c, void 
*data)
  char *riscv_isa_string(RISCVCPU *cpu)
  {
  int i;
-const size_t maxlen = sizeof("rv128") + sizeof(riscv_exts) + 1;
+const size_t maxlen = sizeof("rv128") + sizeof(riscv_single_letter_exts);
  char *isa_str = g_new(char, maxlen);
  char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);


To avoid one dependency on TARGET_LONG_BITS that is not necessary now that we
have mxl, I would suggest to replace the previous line with:
 char *p = isa_str + snprintf(isa_str, maxlen, "rv%d",
  1 << (4 + cpu->env.misa_mxl_max));

Frédéric



[PATCH v2] target/riscv: correct "code should not be reached" for x-rv128

2022-01-24 Thread Frédéric Pétrot
The addition of uxl support in gdbstub adds a few checks on the maximum
register length, but omitted MXL_RV128, an experimental feature.
This patch makes rv128 react as rv64, as previously.

Signed-off-by: Frédéric Pétrot 
---
 target/riscv/cpu.c | 3 +--
 target/riscv/gdbstub.c | 3 +++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1cb0436187..5ada71e5bf 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -528,10 +528,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 switch (env->misa_mxl_max) {
 #ifdef TARGET_RISCV64
 case MXL_RV64:
+case MXL_RV128:
 cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
 break;
-case MXL_RV128:
-break;
 #endif
 case MXL_RV32:
 cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index f531a74c2f..9ed049c29e 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -64,6 +64,7 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)
 case MXL_RV32:
 return gdb_get_reg32(mem_buf, tmp);
 case MXL_RV64:
+case MXL_RV128:
 return gdb_get_reg64(mem_buf, tmp);
 default:
 g_assert_not_reached();
@@ -84,6 +85,7 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 length = 4;
 break;
 case MXL_RV64:
+case MXL_RV128:
 if (env->xl < MXL_RV64) {
 tmp = (int32_t)ldq_p(mem_buf);
 } else {
@@ -420,6 +422,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
  1, "riscv-32bit-virtual.xml", 0);
 break;
 case MXL_RV64:
+case MXL_RV128:
 gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
  riscv_gdb_set_virtual,
  1, "riscv-64bit-virtual.xml", 0);
-- 
2.34.1




Re: [PATCH] target/riscv: correct "code should not be reached" for x-rv128

2022-01-24 Thread Frédéric Pétrot

Le 24/01/2022 à 09:47, LIU Zhiwei a écrit :


On 2022/1/24 下午3:49, Frédéric Pétrot wrote:

The addition of uxl support in gdbstub adds a few checks on the maximum
register length, but omitted MXL_RV128, leading to the occurence of
"code should not be reached" in a few places.
This patch makes rv128 react as rv64 for gdb, as previously.


If that is case for rv128, you should also add

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1cb0436187..5ada71e5bf 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -528,9 +528,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
  switch (env->misa_mxl_max) {
  #ifdef TARGET_RISCV64
  case MXL_RV64:
-    cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
-    break;
  case MXL_RV128:
+    cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
  break;


  Thanks Zhiwei for pointing that out, I resend a patch with that too.
  Strangely enough, I didn't bump into that case.


Still I don't know why we should make rv128 react as rv64 for gdb?


  Well, I should surely do what is necessary to have a working 128-bit
  connection to gdb, but it has a bit of influence on other stuff than qemu,
  e.g. when I configure the gdb-xml file with bitsize 128, gdb tests the
  xlens and returns "bfd requires xlen 8, but target has xlen 16", and
  after that no register can be queried.
  Gdb checks what is called "arch features" and knows only about ELFCLASS32
  and ELFCLASS64, so we are stuck for now.

  Thanks,
  Frédéric



Thanks,
Zhiwei



Signed-off-by: Frédéric Pétrot 
---
  target/riscv/gdbstub.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index f531a74c2f..9ed049c29e 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -64,6 +64,7 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)

  case MXL_RV32:
  return gdb_get_reg32(mem_buf, tmp);
  case MXL_RV64:
+    case MXL_RV128:
  return gdb_get_reg64(mem_buf, tmp);
  default:
  g_assert_not_reached();
@@ -84,6 +85,7 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)

  length = 4;
  break;
  case MXL_RV64:
+    case MXL_RV128:
  if (env->xl < MXL_RV64) {
  tmp = (int32_t)ldq_p(mem_buf);
  } else {
@@ -420,6 +422,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
   1, "riscv-32bit-virtual.xml", 0);
  break;
  case MXL_RV64:
+    case MXL_RV128:
  gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
   riscv_gdb_set_virtual,
   1, "riscv-64bit-virtual.xml", 0);


--
+-------+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



[PATCH] target/riscv: correct "code should not be reached" for x-rv128

2022-01-23 Thread Frédéric Pétrot
The addition of uxl support in gdbstub adds a few checks on the maximum
register length, but omitted MXL_RV128, leading to the occurence of
"code should not be reached" in a few places.
This patch makes rv128 react as rv64 for gdb, as previously.

Signed-off-by: Frédéric Pétrot 
---
 target/riscv/gdbstub.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index f531a74c2f..9ed049c29e 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -64,6 +64,7 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)
 case MXL_RV32:
 return gdb_get_reg32(mem_buf, tmp);
 case MXL_RV64:
+case MXL_RV128:
 return gdb_get_reg64(mem_buf, tmp);
 default:
 g_assert_not_reached();
@@ -84,6 +85,7 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 length = 4;
 break;
 case MXL_RV64:
+case MXL_RV128:
 if (env->xl < MXL_RV64) {
 tmp = (int32_t)ldq_p(mem_buf);
 } else {
@@ -420,6 +422,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
  1, "riscv-32bit-virtual.xml", 0);
 break;
 case MXL_RV64:
+case MXL_RV128:
 gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
  riscv_gdb_set_virtual,
  1, "riscv-64bit-virtual.xml", 0);
-- 
2.34.1




Re: [RESEND] target/riscv: fix RV128 lq encoding

2022-01-19 Thread Frédéric Pétrot

Le 18/01/2022 à 17:32, Christoph Muellner a écrit :

If LQ has func3==010 and is located in the MISC-MEM opcodes,
then it conflicts with the CBO opcode space.
However, since LQ is specified as: "LQ is added to the MISC-MEM major
opcode", we have an implementation bug, because 'major opcode'
refers to func3, which must be 111.

This results in the following instruction encodings:

lq  .111 .000
cbo_clean  0001 .010 
cbo_flush  0010 .010 
cbo_inval   .010 
cbo_zero   0100 .010 
  ^^^-func3
   ^^^-opcode


  Hello Christoph,
  I see page table 26.1 of the last riscv-isa-manual.pdf what is called major
  opcodes in my understanding, and MISC-MEM is one of them with value 00_111_11.
  The value for func3 that I chose comes from
  https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
  which admittedly is out-dated, but I don't see any particular value for
  LQ/SQ in the new spec either (I mean, riscv-isa-manual.pdf, any pointer we
  could refer to ?).
  I have nothing against changing the opcode, but then we need to change
  disas/riscv.c which also uses the previous opcode to dump instructions when
  running with -d in_asm.

  Frédéric


Signed-off-by: Christoph Muellner 
---
  target/riscv/insn32.decode | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 5bbedc254c..d3f798ca10 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -168,7 +168,7 @@ sraw 010 .  . 101 . 0111011 @r
  
  # *** RV128I Base Instruction Set (in addition to RV64I) ***

  ldu     . 111 . 011 @i
-lq      . 010 . 000 @i
+lq      . 111 . 000 @i
  sq      . 100 . 0100011 @s
  addid  .  000 . 1011011 @i
  sllid00 ..  . 001 . 1011011 @sh6


--
+---+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



Re: [PATCH v8 07/18] target/riscv: setup everything for rv64 to support rv128 execution

2022-01-07 Thread Frédéric Pétrot

On 07/01/2022 07:47, Alistair Francis wrote:

On Fri, Jan 7, 2022 at 4:23 PM Frédéric Pétrot
 wrote:


On 06/01/2022 22:24, Alistair Francis wrote:

On Fri, Jan 7, 2022 at 7:04 AM Frédéric Pétrot
 wrote:


This patch adds the support of the '-cpu rv128' option to
qemu-system-riscv64 so that we can indicate that we want to run rv128
executables.
Still, there is no support for 128-bit insns at that stage so qemu fails
miserably (as expected) if launched with this option.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
   include/disas/dis-asm.h |  1 +
   target/riscv/cpu.h  |  1 +
   disas/riscv.c   |  5 +
   target/riscv/cpu.c  | 20 
   target/riscv/gdbstub.c  |  5 +
   5 files changed, 32 insertions(+)

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..102a1e7f50 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
   int print_insn_xtensa   (bfd_vma, disassemble_info*);
   int print_insn_riscv32  (bfd_vma, disassemble_info*);
   int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_riscv128 (bfd_vma, disassemble_info*);
   int print_insn_rx(bfd_vma, disassemble_info *);
   int print_insn_hexagon(bfd_vma, disassemble_info *);

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index fa5d238530..efe481f5fb 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -38,6 +38,7 @@
   #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
   #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
   #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
+#define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("rv128")


As this series only adds partial support for 128-bit support, I think
we should probably change this to "x-rv128". That way we indicate to
users that it is experimental. That allows us more flexibility in the
future to have breaking changes and will hopefully avoid confusion
about the current state. What do you think? I can just make the change
when I apply the patches.


Sure, this is clearly experimental (the spec is a draft) and should be
marked so, I totally agree. Please make the change as you suggest,


Great!

Applied to riscv-to-apply.next

If you want to make sure my change didn't break anything you can test
the tree here: https://github.com/alistair23/qemu/tree/riscv-to-apply.next


  Works like a charm !
  Thanks,
  Frédéric



I'll send a PR this weekend or next week.

Alistair



Thanks,
Frédéric



Alistair


--
+-------+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+


--
+-------+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



Re: [PATCH v8 07/18] target/riscv: setup everything for rv64 to support rv128 execution

2022-01-06 Thread Frédéric Pétrot

On 06/01/2022 22:24, Alistair Francis wrote:

On Fri, Jan 7, 2022 at 7:04 AM Frédéric Pétrot
 wrote:


This patch adds the support of the '-cpu rv128' option to
qemu-system-riscv64 so that we can indicate that we want to run rv128
executables.
Still, there is no support for 128-bit insns at that stage so qemu fails
miserably (as expected) if launched with this option.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
  include/disas/dis-asm.h |  1 +
  target/riscv/cpu.h  |  1 +
  disas/riscv.c   |  5 +
  target/riscv/cpu.c  | 20 
  target/riscv/gdbstub.c  |  5 +
  5 files changed, 32 insertions(+)

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..102a1e7f50 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
  int print_insn_xtensa   (bfd_vma, disassemble_info*);
  int print_insn_riscv32  (bfd_vma, disassemble_info*);
  int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_riscv128 (bfd_vma, disassemble_info*);
  int print_insn_rx(bfd_vma, disassemble_info *);
  int print_insn_hexagon(bfd_vma, disassemble_info *);

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index fa5d238530..efe481f5fb 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -38,6 +38,7 @@
  #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
  #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
  #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
+#define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("rv128")


As this series only adds partial support for 128-bit support, I think
we should probably change this to "x-rv128". That way we indicate to
users that it is experimental. That allows us more flexibility in the
future to have breaking changes and will hopefully avoid confusion
about the current state. What do you think? I can just make the change
when I apply the patches.


  Sure, this is clearly experimental (the spec is a draft) and should be
  marked so, I totally agree. Please make the change as you suggest,

  Thanks,
  Frédéric



Alistair


--
+-------+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



[PATCH v8 18/18] target/riscv: actual functions to realize crs 128-bit insns

2022-01-06 Thread Frédéric Pétrot
The csrs are accessed through function pointers: we add 128-bit read
operations in the table for three csrs (writes fallback to the
64-bit version as the upper 64-bit information is handled elsewhere):
- misa, as mxl is needed for proper operation,
- mstatus and sstatus, to return sd
In addition, we also add read and write accesses to the machine and
supervisor scratch registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h  |   7 ++
 target/riscv/cpu_bits.h |   3 +
 target/riscv/csr.c  | 195 +---
 3 files changed, 175 insertions(+), 30 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index edc7de7b17..a19c65bc1d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -505,12 +505,19 @@ RISCVException riscv_csrrw_i128(CPURISCVState *env, int 
csrno,
 Int128 *ret_value,
 Int128 new_value, Int128 write_mask);
 
+typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno,
+   Int128 *ret_value);
+typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int csrno,
+ Int128 new_value);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
 riscv_csr_read_fn read;
 riscv_csr_write_fn write;
 riscv_csr_op_fn op;
+riscv_csr_read128_fn read128;
+riscv_csr_write128_fn write128;
 } riscv_csr_operations;
 
 /* CSR function table constants */
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 1e31f4d35f..5a6d49aa64 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -401,6 +401,7 @@
 
 #define MSTATUS32_SD0x8000
 #define MSTATUS64_SD0x8000ULL
+#define MSTATUSH128_SD  0x8000ULL
 
 #define MISA32_MXL  0xC000
 #define MISA64_MXL  0xC000ULL
@@ -423,6 +424,8 @@ typedef enum {
 #define SSTATUS_SUM 0x0004 /* since: priv-1.10 */
 #define SSTATUS_MXR 0x0008
 
+#define SSTATUS64_UXL   0x0003ULL
+
 #define SSTATUS32_SD0x8000
 #define SSTATUS64_SD0x8000ULL
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 4c6a44c0b8..adb3d4381d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -481,7 +481,7 @@ static const target_ulong vs_delegable_excps = 
DELEGABLE_EXCPS &
   (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)));
 static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
-SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS;
+SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS | (target_ulong)SSTATUS64_UXL;
 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
 static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
@@ -527,6 +527,8 @@ static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
 return status | MSTATUS32_SD;
 case MXL_RV64:
 return status | MSTATUS64_SD;
+case MXL_RV128:
+return MSTATUSH128_SD;
 default:
 g_assert_not_reached();
 }
@@ -576,10 +578,11 @@ static RISCVException write_mstatus(CPURISCVState *env, 
int csrno,
 
 mstatus = (mstatus & ~mask) | (val & mask);
 
-if (riscv_cpu_mxl(env) == MXL_RV64) {
+RISCVMXL xl = riscv_cpu_mxl(env);
+if (xl > MXL_RV32) {
 /* SXL and UXL fields are for now read only */
-mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
-mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
+mstatus = set_field(mstatus, MSTATUS64_SXL, xl);
+mstatus = set_field(mstatus, MSTATUS64_UXL, xl);
 }
 env->mstatus = mstatus;
 
@@ -608,6 +611,20 @@ static RISCVException write_mstatush(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_mstatus_i128(CPURISCVState *env, int csrno,
+Int128 *val)
+{
+*val = int128_make128(env->mstatus, add_status_sd(MXL_RV128, 
env->mstatus));
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_misa_i128(CPURISCVState *env, int csrno,
+ Int128 *val)
+{
+*val = int128_make128(env->misa_ext, (uint64_t)MXL_RV128 << 62);
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException read_misa(CPURISCVState *env, int csrno,
 target_ulong *val)
 {
@@ -765,6 +782,21 @@ static RISCVException write_mcounteren(CPURISCVState *env, 
int csrno,
 }
 
 /* Machine Trap Handling */
+static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno,
+   

[PATCH v8 16/18] target/riscv: helper functions to wrap calls to 128-bit csr insns

2022-01-06 Thread Frédéric Pétrot
Given the side effects they have, the csr instructions are realized as
helpers. We extend this existing infrastructure for 128-bit sized csr.
We return 128-bit values using the same approach as for div/rem.
Theses helpers all call a unique function that is currently a fallback
on the 64-bit version.
The trans_csrxx functions supporting 128-bit are yet to be implemented.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h   |  5 +
 target/riscv/helper.h|  3 +++
 target/riscv/csr.c   | 17 
 target/riscv/op_helper.c | 44 
 4 files changed, 69 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f3a52fef32..edc7de7b17 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -25,6 +25,7 @@
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "qom/object.h"
+#include "qemu/int128.h"
 #include "cpu_bits.h"
 
 #define TCG_GUEST_DEFAULT_MO 0
@@ -500,6 +501,10 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
*env, int csrno,
   target_ulong new_value,
   target_ulong write_mask);
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+Int128 *ret_value,
+Int128 new_value, Int128 write_mask);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index a8ee8a362a..6cf6d6ce98 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -96,6 +96,9 @@ DEF_HELPER_FLAGS_1(fclass_h, TCG_CALL_NO_RWG_SE, tl, i64)
 DEF_HELPER_2(csrr, tl, env, int)
 DEF_HELPER_3(csrw, void, env, int, tl)
 DEF_HELPER_4(csrrw, tl, env, int, tl, tl)
+DEF_HELPER_2(csrr_i128, tl, env, int)
+DEF_HELPER_4(csrw_i128, void, env, int, tl, tl)
+DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_2(sret, tl, env, tl)
 DEF_HELPER_2(mret, tl, env, tl)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 146447eac5..4c6a44c0b8 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1817,6 +1817,23 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
 return RISCV_EXCP_NONE;
 }
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+   Int128 *ret_value,
+   Int128 new_value, Int128 write_mask)
+{
+/* fall back to 64-bit version for now */
+target_ulong ret_64;
+RISCVException ret = riscv_csrrw(env, csrno, _64,
+ int128_getlo(new_value),
+ int128_getlo(write_mask));
+
+if (ret_value) {
+*ret_value = int128_make64(ret_64);
+}
+
+return ret;
+}
+
 /*
  * Debugger support.  If not in user mode, set env->debugger before the
  * riscv_csrrw call and clear it after the call.
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 58d992e98a..6f040f2fb9 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -69,6 +69,50 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
 return val;
 }
 
+target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_zero(),
+  int128_zero());
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
+void helper_csrw_i128(CPURISCVState *env, int csr,
+  target_ulong srcl, target_ulong srch)
+{
+RISCVException ret = riscv_csrrw_i128(env, csr, NULL,
+  int128_make128(srcl, srch),
+  UINT128_MAX);
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+}
+
+target_ulong helper_csrrw_i128(CPURISCVState *env, int csr,
+   target_ulong srcl, target_ulong srch,
+   target_ulong maskl, target_ulong maskh)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_make128(srcl, srch),
+  int128_make128(maskl, maskh));
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
 #ifndef CONFIG_USER_ONLY
 
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
-- 
2.34.1




[PATCH v8 17/18] target/riscv: modification of the trans_csrxx for 128-bit support

2022-01-06 Thread Frédéric Pétrot
As opposed to the gen_arith and gen_shift generation helpers, the csr insns
do not have a common prototype, so the choice to generate 32/64 or 128-bit
helper calls is done in the trans_csrxx functions.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 205 ++--
 1 file changed, 160 insertions(+), 45 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index ca354130ec..3a0ae28fef 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -881,20 +881,78 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, 
TCGv src, TCGv mask)
 return do_csr_post(ctx);
 }
 
+static bool do_csrr_i128(DisasContext *ctx, int rd, int rc)
+{
+TCGv destl = dest_gpr(ctx, rd);
+TCGv desth = dest_gprh(ctx, rd);
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrr_i128(destl, cpu_env, csr);
+tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
+gen_set_gpr128(ctx, rd, destl, desth);
+return do_csr_post(ctx);
+}
+
+static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch)
+{
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrw_i128(cpu_env, csr, srcl, srch);
+return do_csr_post(ctx);
+}
+
+static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc,
+  TCGv srcl, TCGv srch, TCGv maskl, TCGv maskh)
+{
+TCGv destl = dest_gpr(ctx, rd);
+TCGv desth = dest_gprh(ctx, rd);
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrrw_i128(destl, cpu_env, csr, srcl, srch, maskl, maskh);
+tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
+gen_set_gpr128(ctx, rd, destl, desth);
+return do_csr_post(ctx);
+}
+
 static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
 {
-TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
-
-/*
- * If rd == 0, the insn shall not read the csr, nor cause any of the
- * side effects that might occur on a csr read.
- */
-if (a->rd == 0) {
-return do_csrw(ctx, a->csr, src);
+if (get_xl(ctx) < MXL_RV128) {
+TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
+
+/*
+ * If rd == 0, the insn shall not read the csr, nor cause any of the
+ * side effects that might occur on a csr read.
+ */
+if (a->rd == 0) {
+return do_csrw(ctx, a->csr, src);
+}
+
+TCGv mask = tcg_constant_tl(-1);
+return do_csrrw(ctx, a->rd, a->csr, src, mask);
+} else {
+TCGv srcl = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv srch = get_gprh(ctx, a->rs1);
+
+/*
+ * If rd == 0, the insn shall not read the csr, nor cause any of the
+ * side effects that might occur on a csr read.
+ */
+if (a->rd == 0) {
+return do_csrw_i128(ctx, a->csr, srcl, srch);
+}
+
+TCGv mask = tcg_constant_tl(-1);
+return do_csrrw_i128(ctx, a->rd, a->csr, srcl, srch, mask, mask);
 }
-
-TCGv mask = tcg_constant_tl(-1);
-return do_csrrw(ctx, a->rd, a->csr, src, mask);
 }
 
 static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
@@ -906,13 +964,24 @@ static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
  * a zero value, the instruction will still attempt to write the
  * unmodified value back to the csr and will cause side effects.
  */
-if (a->rs1 == 0) {
-return do_csrr(ctx, a->rd, a->csr);
+if (get_xl(ctx) < MXL_RV128) {
+if (a->rs1 == 0) {
+return do_csrr(ctx, a->rd, a->csr);
+}
+
+TCGv ones = tcg_constant_tl(-1);
+TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
+return do_csrrw(ctx, a->rd, a->csr, ones, mask);
+} else {
+if (a->rs1 == 0) {
+return do_csrr_i128(ctx, a->rd, a->csr);
+}
+
+TCGv ones = tcg_constant_tl(-1);
+TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO);
+TCGv maskh = get_gprh(ctx, a->rs1);
+return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, maskl, maskh);
 }
-
-TCGv ones = tcg_constant_tl(-1);
-TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
-return do_csrrw(ctx, a->rd, a->csr, ones, mask);
 }
 
 static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
@@ -924,28 +993,54 @@ static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
  * a zero value, the instruction will still attempt to write the
  * unmodified value back to the csr and wil

[PATCH v8 11/18] target/riscv: support for 128-bit U-type instructions

2022-01-06 Thread Frédéric Pétrot
Adding the 128-bit version of lui and auipc, and introducing to that end
a "set register with immediat" function to handle extension on 128 bits.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c| 21 +
 target/riscv/insn_trans/trans_rvi.c.inc |  8 
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index b43efc9bc3..ba1ad1be5f 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -322,6 +322,27 @@ static void gen_set_gpr(DisasContext *ctx, int reg_num, 
TCGv t)
 }
 }
 
+static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm)
+{
+if (reg_num != 0) {
+switch (get_ol(ctx)) {
+case MXL_RV32:
+tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm);
+break;
+case MXL_RV64:
+case MXL_RV128:
+tcg_gen_movi_tl(cpu_gpr[reg_num], imm);
+break;
+default:
+g_assert_not_reached();
+}
+
+if (get_xl_max(ctx) == MXL_RV128) {
+tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0));
+}
+}
+}
+
 static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh)
 {
 assert(get_ol(ctx) == MXL_RV128);
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index e572976e88..6113acc669 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -26,14 +26,14 @@ static bool trans_illegal(DisasContext *ctx, arg_empty *a)
 
 static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
 {
- REQUIRE_64BIT(ctx);
- return trans_illegal(ctx, a);
+REQUIRE_64_OR_128BIT(ctx);
+return trans_illegal(ctx, a);
 }
 
 static bool trans_lui(DisasContext *ctx, arg_lui *a)
 {
 if (a->rd != 0) {
-tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm);
+gen_set_gpri(ctx, a->rd, a->imm);
 }
 return true;
 }
@@ -41,7 +41,7 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a)
 static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
 {
 if (a->rd != 0) {
-tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm + ctx->base.pc_next);
+gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
 }
 return true;
 }
-- 
2.34.1




[PATCH v8 12/18] target/riscv: support for 128-bit shift instructions

2022-01-06 Thread Frédéric Pétrot
Handling shifts for 32, 64 and 128 operation length for RV128, following the
general framework for handling various olens proposed by Richard.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  10 ++
 target/riscv/translate.c|  58 --
 target/riscv/insn_trans/trans_rvb.c.inc |  22 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 224 ++--
 4 files changed, 270 insertions(+), 44 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index ddbf0da03c..a992c6d369 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -22,6 +22,7 @@
 %rs1   15:5
 %rd7:5
 %sh5   20:5
+%sh6   20:6
 
 %sh720:7
 %csr20:12
@@ -91,6 +92,9 @@
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
+# Formats 128:
+@sh6   .. .. . ... . ...  shamt=%sh6 %rs1 %rd
+
 # *** Privileged Instructions ***
 ecall    0 000 0 1110011
 ebreak  0001 0 000 0 1110011
@@ -166,6 +170,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+sllid00 ..  . 001 . 1011011 @sh6
+srlid00 ..  . 101 . 1011011 @sh6
+sraid01 ..  . 101 . 1011011 @sh6
+slld 000 . .  001 . 011 @r
+srld 000 . .  101 . 011 @r
+srad 010 . .  101 . 011 @r
 
 # *** RV32M Standard Extension ***
 mul  001 .  . 000 . 0110011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index ba1ad1be5f..89220a5fae 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -635,7 +635,8 @@ static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, 
DisasExtend ext,
 }
 
 static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest, src1;
 int max_len = get_olen(ctx);
@@ -647,26 +648,38 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 dest = dest_gpr(ctx, a->rd);
 src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->shamt);
+if (max_len < 128) {
+func(dest, src1, a->shamt);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (f128 == NULL) {
+return false;
+}
+f128(dest, desth, src1, src1h, a->shamt);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
 DisasExtend ext,
 void (*f_tl)(TCGv, TCGv, target_long),
-void (*f_32)(TCGv, TCGv, target_long))
+void (*f_32)(TCGv, TCGv, target_long),
+void (*f_128)(TCGv, TCGv, TCGv, TCGv,
+  target_long))
 {
 int olen = get_olen(ctx);
 if (olen != TARGET_LONG_BITS) {
 if (olen == 32) {
 f_tl = f_32;
-} else {
+} else if (olen != 128) {
 g_assert_not_reached();
 }
 }
-return gen_shift_imm_fn(ctx, a, ext, f_tl);
+return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
 }
 
 static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
@@ -690,34 +703,49 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 }
 
 static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
 {
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 TCGv ext2 = tcg_temp_new();
+int max_len = get_olen(ctx);
 
-tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1);
-func(dest, src1, ext2);
+tcg_gen_andi_tl(ext2, src2, max_len - 1);
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, ext);
+
+if (max_len < 128) {
+func(dest, src1, ext2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh

[PATCH v8 15/18] target/riscv: adding high part of some csrs

2022-01-06 Thread Frédéric Pétrot
Adding the high part of a very minimal set of csr.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h | 4 
 target/riscv/machine.c | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f05f2411ae..f3a52fef32 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -195,6 +195,10 @@ struct CPURISCVState {
 target_ulong hgatp;
 uint64_t htimedelta;
 
+/* Upper 64-bits of 128-bit CSRs */
+uint64_t mscratchh;
+uint64_t sscratchh;
+
 /* Virtual CSRs */
 /*
  * For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 8af9caabf5..13b9ab375b 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -179,6 +179,8 @@ static const VMStateDescription vmstate_rv128 = {
 .needed = rv128_needed,
 .fields = (VMStateField[]) {
 VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_UINT64(env.mscratchh, RISCVCPU),
+VMSTATE_UINT64(env.sscratchh, RISCVCPU),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
2.34.1




[PATCH v8 09/18] target/riscv: accessors to registers upper part and 128-bit load/store

2022-01-06 Thread Frédéric Pétrot
Get function to retrieve the 64 top bits of a register, stored in the gprh
field of the cpu state. Set function that writes the 128-bit value at once.
The access to the gprh field can not be protected at compile time to make
sure it is accessed only in the 128-bit version of the processor because we
have no way to indicate that the misa_mxl_max field is const.

The 128-bit ISA adds ldu, lq and sq. We provide support for these
instructions. Note that (a) we compute only 64-bit addresses to actually
access memory, cowardly utilizing the existing address translation mechanism
of QEMU, and (b) we assume for now little-endian memory accesses.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn16.decode  |  27 ++-
 target/riscv/insn32.decode  |   5 ++
 target/riscv/translate.c|  41 ++
 target/riscv/insn_trans/trans_rvi.c.inc | 100 ++--
 4 files changed, 163 insertions(+), 10 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 2e9212663c..02c8f61b48 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -25,14 +25,17 @@
 # Immediates:
 %imm_ci12:s1 2:5
 %nzuimm_ciw7:4 11:2 5:1 6:1   !function=ex_shift_2
+%uimm_cl_q 10:1 5:2 11:2  !function=ex_shift_4
 %uimm_cl_d 5:2 10:3   !function=ex_shift_3
 %uimm_cl_w 5:1 10:3 6:1   !function=ex_shift_2
 %imm_cb12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
 %imm_cj12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
 
 %shimm_6bit   12:1 2:5   !function=ex_rvc_shifti
+%uimm_6bit_lq 2:4 12:1 6:1   !function=ex_shift_4
 %uimm_6bit_ld 2:3 12:1 5:2   !function=ex_shift_3
 %uimm_6bit_lw 2:2 12:1 4:3   !function=ex_shift_2
+%uimm_6bit_sq 7:4 11:2   !function=ex_shift_4
 %uimm_6bit_sd 7:3 10:3   !function=ex_shift_3
 %uimm_6bit_sw 7:2 9:4!function=ex_shift_2
 
@@ -54,16 +57,20 @@
 # Formats 16:
 @cr  . .  ..   rs2=%rs2_5   rs1=%rd %rd
 @ci... . . .  ..   imm=%imm_ci  rs1=%rd %rd
+@cl_q  ... . .  . ..   imm=%uimm_cl_q   rs1=%rs1_3  rd=%rs2_3
 @cl_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  rd=%rs2_3
 @cl_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  rd=%rs2_3
 @cs_2  ... ... ... .. ... ..   rs2=%rs2_3   rs1=%rs1_3  rd=%rs1_3
+@cs_q  ... ... ... .. ... ..   imm=%uimm_cl_q   rs1=%rs1_3  
rs2=%rs2_3
 @cs_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  
rs2=%rs2_3
 @cs_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  
rs2=%rs2_3
 @cj...... ..   imm=%imm_cj
 @cb_z  ... ... ... .. ... ..   imm=%imm_cb  rs1=%rs1_3  rs2=0
 
+@c_lqsp... . .  . ..   imm=%uimm_6bit_lq rs1=2 %rd
 @c_ldsp... . .  . ..   imm=%uimm_6bit_ld rs1=2 %rd
 @c_lwsp... . .  . ..   imm=%uimm_6bit_lw rs1=2 %rd
+@c_sqsp... . .  . ..   imm=%uimm_6bit_sq rs1=2 rs2=%rs2_5
 @c_sdsp... . .  . ..   imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5
 @c_swsp... . .  . ..   imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5
 @c_li  ... . .  . ..   imm=%imm_ci rs1=0 %rd
@@ -87,9 +94,15 @@
   illegal 000  000 000 00 --- 00
   addi000  ... ... .. ... 00 @c_addi4spn
 }
-fld   001  ... ... .. ... 00 @cl_d
+{
+  lq  001  ... ... .. ... 00 @cl_q
+  fld 001  ... ... .. ... 00 @cl_d
+}
 lw010  ... ... .. ... 00 @cl_w
-fsd   101  ... ... .. ... 00 @cs_d
+{
+  sq  101  ... ... .. ... 00 @cs_q
+  fsd 101  ... ... .. ... 00 @cs_d
+}
 sw110  ... ... .. ... 00 @cs_w
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 0) ***
@@ -132,7 +145,10 @@ addw  100 1 11 ... 01 ... 01 @cs_2
 
 # *** RV32/64C Standard Extension (Quadrant 2) ***
 slli  000 .  .  . 10 @c_shift2
-fld   001 .  .  . 10 @c_ldsp
+{
+  lq  001  ... ... .. ... 10 @c_lqsp
+  fld 001 .  .  . 10 @c_ldsp
+}
 {
   illegal 010 -  0  - 10 # c.lwsp, RES rd=0
   lw  010 .  .  . 10 @c_lwsp
@@ -147,7 +163,10 @@ fld   001 .  .  . 10 @c_ldsp
   jalr100 1  .  0 10 @c_jalr rd=1  # C.JALR
   add 100 1  .  . 10 @cr
 }
-fsd   101   ..  . 10 @c_sdsp
+{
+  sq  101  ... ... .. ... 10 @c_sqsp
+  fsd 101   ..  . 10 @c_sdsp
+}
 sw110 .  .  . 10 @c_swsp
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 2) ***
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 8617307b29..ddbf0da03c 100644

[PATCH v8 13/18] target/riscv: support for 128-bit arithmetic instructions

2022-01-06 Thread Frédéric Pétrot
Addition of 128-bit adds and subs in their various sizes,
"set if less than"s and branches.
Refactored the code to have a comparison function used for both stls and
branches.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn32.decode  |   3 +
 target/riscv/translate.c|  63 --
 target/riscv/insn_trans/trans_rvb.c.inc |  20 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 159 +---
 target/riscv/insn_trans/trans_rvm.c.inc |  26 ++--
 5 files changed, 222 insertions(+), 49 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index a992c6d369..42366d20fb 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -170,9 +170,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+addid  .  000 . 1011011 @i
 sllid00 ..  . 001 . 1011011 @sh6
 srlid00 ..  . 101 . 1011011 @sh6
 sraid01 ..  . 101 . 1011011 @sh6
+addd 000 . .  000 . 011 @r
+subd 010 . .  000 . 011 @r
 slld 000 . .  001 . 011 @r
 srld 000 . .  101 . 011 @r
 srad 010 . .  101 . 011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 89220a5fae..4ae4345691 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -581,57 +581,96 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 }
 
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->imm);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, a->imm);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, a->imm);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, TCGv))
+ void (*func)(TCGv, TCGv, TCGv),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = tcg_constant_tl(a->imm);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = tcg_constant_tl(-(a->imm < 0));
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, ext);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
  void (*f_tl)(TCGv, TCGv, TCGv),
- void (*f_32)(TCGv, TCGv, TCGv))
+ void (*f_32)(TCGv, TCGv, TCGv),
+ void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 int olen = get_olen(ctx);
 
 if (olen != TARGET_LONG_BITS

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

2022-01-06 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 
Reviewed-by: Alistair Francis 
---
 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 efe481f5fb..f05f2411ae 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -143,6 +143,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 c15497e4a1..a8ee8a362a 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1101,3 +1101,9 @@ DEF_HELPER_5(vsext_vf2_d, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(vsext_vf4_w, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(vsext_vf4_d, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(vsext_vf8_d, void, 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 42366d20fb..5bbedc254c 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -197,6 +197,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 <http://www.gnu.org/licenses/>.
+ */
+
+#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

[PATCH v8 05/18] target/riscv: separation of bitwise logic and arithmetic helpers

2022-01-06 Thread Frédéric Pétrot
Introduction of a gen_logic function for bitwise logic to implement
instructions in which no propagation of information occurs between bits and
use of this function on the bitwise instructions.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c| 27 +
 target/riscv/insn_trans/trans_rvb.c.inc |  6 +++---
 target/riscv/insn_trans/trans_rvi.c.inc | 12 +--
 3 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 502bf0d009..c3b4950ad0 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -475,6 +475,33 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm)
 /* Include the auto-generated decoder for 32 bit insn */
 #include "decode-insn32.c.inc"
 
+static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
+ void (*func)(TCGv, TCGv, target_long))
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+
+func(dest, src1, a->imm);
+
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
+static bool gen_logic(DisasContext *ctx, arg_r *a,
+  void (*func)(TCGv, TCGv, TCGv))
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+func(dest, src1, src2);
+
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
  void (*func)(TCGv, TCGv, target_long))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index c8d31907c5..de2cd613b1 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -86,19 +86,19 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
 static bool trans_andn(DisasContext *ctx, arg_andn *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl);
+return gen_logic(ctx, a, tcg_gen_andc_tl);
 }
 
 static bool trans_orn(DisasContext *ctx, arg_orn *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl);
+return gen_logic(ctx, a, tcg_gen_orc_tl);
 }
 
 static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl);
+return gen_logic(ctx, a, tcg_gen_eqv_tl);
 }
 
 static bool trans_min(DisasContext *ctx, arg_min *a)
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 4a2aefe3a5..51607b3d40 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -252,17 +252,17 @@ static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
 
 static bool trans_xori(DisasContext *ctx, arg_xori *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_xori_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_xori_tl);
 }
 
 static bool trans_ori(DisasContext *ctx, arg_ori *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_ori_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_ori_tl);
 }
 
 static bool trans_andi(DisasContext *ctx, arg_andi *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_andi_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_andi_tl);
 }
 
 static bool trans_slli(DisasContext *ctx, arg_slli *a)
@@ -319,7 +319,7 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 
 static bool trans_xor(DisasContext *ctx, arg_xor *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_xor_tl);
+return gen_logic(ctx, a, tcg_gen_xor_tl);
 }
 
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
@@ -334,12 +334,12 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_or_tl);
+return gen_logic(ctx, a, tcg_gen_or_tl);
 }
 
 static bool trans_and(DisasContext *ctx, arg_and *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_and_tl);
+return gen_logic(ctx, a, tcg_gen_and_tl);
 }
 
 static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
-- 
2.34.1




[PATCH v8 10/18] target/riscv: support for 128-bit bitwise instructions

2022-01-06 Thread Frédéric Pétrot
The 128-bit bitwise instructions do not need any function prototype change
as the functions can be applied independently on the lower and upper part of
the registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index d4cf965c9e..b43efc9bc3 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -523,7 +523,15 @@ static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
 
 func(dest, src1, a->imm);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, -(a->imm < 0));
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
@@ -537,7 +545,16 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 
 func(dest, src1, src2);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
-- 
2.34.1




[PATCH v8 06/18] target/riscv: array for the 64 upper bits of 128-bit registers

2022-01-06 Thread Frédéric Pétrot
The upper 64-bit of the 128-bit registers have now a place inside
the cpu state structure, and are created as globals for future use.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h   |  2 ++
 target/riscv/cpu.c   |  9 +
 target/riscv/machine.c   | 20 
 target/riscv/translate.c |  5 -
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index dc10f27093..fa5d238530 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -112,6 +112,7 @@ FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1)
 
 struct CPURISCVState {
 target_ulong gpr[32];
+target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
 uint64_t fpr[32]; /* assume both F and D extensions */
 
 /* vector coprocessor state. */
@@ -344,6 +345,7 @@ static inline bool riscv_feature(CPURISCVState *env, int 
feature)
 #include "cpu_user.h"
 
 extern const char * const riscv_int_regnames[];
+extern const char * const riscv_int_regnamesh[];
 extern const char * const riscv_fpr_regnames[];
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 29749e834f..7b8197db98 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -42,6 +42,15 @@ const char * const riscv_int_regnames[] = {
   "x28/t3",  "x29/t4", "x30/t5", "x31/t6"
 };
 
+const char * const riscv_int_regnamesh[] = {
+  "x0h/zeroh", "x1h/rah",  "x2h/sph",   "x3h/gph",   "x4h/tph",  "x5h/t0h",
+  "x6h/t1h",   "x7h/t2h",  "x8h/s0h",   "x9h/s1h",   "x10h/a0h", "x11h/a1h",
+  "x12h/a2h",  "x13h/a3h", "x14h/a4h",  "x15h/a5h",  "x16h/a6h", "x17h/a7h",
+  "x18h/s2h",  "x19h/s3h", "x20h/s4h",  "x21h/s5h",  "x22h/s6h", "x23h/s7h",
+  "x24h/s8h",  "x25h/s9h", "x26h/s10h", "x27h/s11h", "x28h/t3h", "x29h/t4h",
+  "x30h/t5h",  "x31h/t6h"
+};
+
 const char * const riscv_fpr_regnames[] = {
   "f0/ft0",   "f1/ft1",  "f2/ft2",   "f3/ft3",   "f4/ft4",  "f5/ft5",
   "f6/ft6",   "f7/ft7",  "f8/fs0",   "f9/fs1",   "f10/fa0", "f11/fa1",
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index ad8248ebfd..8af9caabf5 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -164,6 +164,25 @@ static const VMStateDescription vmstate_pointermasking = {
 }
 };
 
+static bool rv128_needed(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+CPURISCVState *env = >env;
+
+return env->misa_mxl_max == MXL_RV128;
+}
+
+static const VMStateDescription vmstate_rv128 = {
+.name = "cpu/rv128",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = rv128_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_END_OF_LIST()
+}
+};
+
 const VMStateDescription vmstate_riscv_cpu = {
 .name = "cpu",
 .version_id = 3,
@@ -218,6 +237,7 @@ const VMStateDescription vmstate_riscv_cpu = {
 _hyper,
 _vector,
 _pointermasking,
+_rv128,
 NULL
 }
 };
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index c3b4950ad0..6c400e8452 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -33,7 +33,7 @@
 #include "internals.h"
 
 /* global register indices */
-static TCGv cpu_gpr[32], cpu_pc, cpu_vl, cpu_vstart;
+static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
 static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
 static TCGv load_res;
 static TCGv load_val;
@@ -858,10 +858,13 @@ void riscv_translate_init(void)
  * unless you specifically block reads/writes to reg 0.
  */
 cpu_gpr[0] = NULL;
+cpu_gprh[0] = NULL;
 
 for (i = 1; i < 32; i++) {
 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
 offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
+cpu_gprh[i] = tcg_global_mem_new(cpu_env,
+offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
 }
 
 for (i = 0; i < 32; i++) {
-- 
2.34.1




[PATCH v8 07/18] target/riscv: setup everything for rv64 to support rv128 execution

2022-01-06 Thread Frédéric Pétrot
This patch adds the support of the '-cpu rv128' option to
qemu-system-riscv64 so that we can indicate that we want to run rv128
executables.
Still, there is no support for 128-bit insns at that stage so qemu fails
miserably (as expected) if launched with this option.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 include/disas/dis-asm.h |  1 +
 target/riscv/cpu.h  |  1 +
 disas/riscv.c   |  5 +
 target/riscv/cpu.c  | 20 
 target/riscv/gdbstub.c  |  5 +
 5 files changed, 32 insertions(+)

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..102a1e7f50 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
 int print_insn_xtensa   (bfd_vma, disassemble_info*);
 int print_insn_riscv32  (bfd_vma, disassemble_info*);
 int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_riscv128 (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
 
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index fa5d238530..efe481f5fb 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -38,6 +38,7 @@
 #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
 #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
 #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
+#define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("rv128")
 #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
 #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c")
 #define TYPE_RISCV_CPU_SIFIVE_E31   RISCV_CPU_TYPE_NAME("sifive-e31")
diff --git a/disas/riscv.c b/disas/riscv.c
index 793ad14c27..03c8dc9961 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -3090,3 +3090,8 @@ int print_insn_riscv64(bfd_vma memaddr, struct 
disassemble_info *info)
 {
 return print_insn_riscv(memaddr, info, rv64);
 }
+
+int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info)
+{
+return print_insn_riscv(memaddr, info, rv128);
+}
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7b8197db98..e3ba53d4d2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -178,6 +178,19 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_priv_version(env, PRIV_VERSION_1_10_0);
 qdev_prop_set_bit(DEVICE(obj), "mmu", false);
 }
+
+static void rv128_base_cpu_init(Object *obj)
+{
+if (qemu_tcg_mttcg_enabled()) {
+/* Missing 128-bit aligned atomics */
+error_report("128-bit RISC-V currently does not work with Multi "
+ "Threaded TCG. Please use: -accel tcg,thread=single");
+exit(EXIT_FAILURE);
+}
+CPURISCVState *env = _CPU(obj)->env;
+/* We set this in the realise function */
+set_misa(env, MXL_RV128, 0);
+}
 #else
 static void rv32_base_cpu_init(Object *obj)
 {
@@ -402,6 +415,9 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 case MXL_RV64:
 info->print_insn = print_insn_riscv64;
 break;
+case MXL_RV128:
+info->print_insn = print_insn_riscv128;
+break;
 default:
 g_assert_not_reached();
 }
@@ -464,6 +480,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 #ifdef TARGET_RISCV64
 case MXL_RV64:
 break;
+case MXL_RV128:
+break;
 #endif
 case MXL_RV32:
 break;
@@ -672,6 +690,7 @@ static gchar *riscv_gdb_arch_name(CPUState *cs)
 case MXL_RV32:
 return g_strdup("riscv:rv32");
 case MXL_RV64:
+case MXL_RV128:
 return g_strdup("riscv:rv64");
 default:
 g_assert_not_reached();
@@ -826,6 +845,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,   rv64_sifive_e_cpu_init),
 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,   rv64_sifive_u_cpu_init),
 DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init),
+DEFINE_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
 #endif
 };
 
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 881ab33392..a5429b92d4 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -280,6 +280,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)
 int bitsize = 16 << env->misa_mxl_max;
 int i;
 
+/* Until gdb knows about 128-bit registers */
+if (bitsize > 64) {
+bitsize = 64;
+}
+
 g_string_printf(s, "");
 g_string_append_printf(s, "");
 g_string_append_printf(s, "");
-- 
2.34.1




[PATCH v8 04/18] target/riscv: additional macros to check instruction support

2022-01-06 Thread Frédéric Pétrot
Given that the 128-bit version of the riscv spec adds new instructions, and
that some instructions that were previously only available in 64-bit mode
are now available for both 64-bit and 128-bit, we added new macros to check
for the processor mode during translation.
Although RV128 is a superset of RV64, we keep for now the RV64 only tests
for extensions other than RVI and RVM.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 5df6c0d800..502bf0d009 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -443,10 +443,22 @@ EX_SH(12)
 }  \
 } while (0)
 
-#define REQUIRE_64BIT(ctx) do {\
-if (get_xl(ctx) < MXL_RV64) {  \
-return false;  \
-}  \
+#define REQUIRE_64BIT(ctx) do { \
+if (get_xl(ctx) != MXL_RV64) {  \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_128BIT(ctx) do {\
+if (get_xl(ctx) != MXL_RV128) { \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_64_OR_128BIT(ctx) do { \
+if (get_xl(ctx) == MXL_RV32) { \
+return false;  \
+}  \
 } while (0)
 
 static int ex_rvc_register(DisasContext *ctx, int reg)
-- 
2.34.1




[PATCH v8 08/18] target/riscv: moving some insns close to similar insns

2022-01-06 Thread Frédéric Pétrot
lwu and ld are functionally close to the other loads, but were after the
stores in the source file.
Similarly, xor was away from or and and by two arithmetic functions, while
the immediate versions were nicely put together.
This patch moves the aforementioned loads after lhu, and xor above or,
where they more logically belong.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 34 -
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 51607b3d40..710f5e6a85 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -176,6 +176,18 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
 return gen_load(ctx, a, MO_TEUW);
 }
 
+static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUL);
+}
+
+static bool trans_ld(DisasContext *ctx, arg_ld *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUQ);
+}
+
 static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
 {
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@@ -207,18 +219,6 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a)
 return gen_store(ctx, a, MO_TESL);
 }
 
-static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUL);
-}
-
-static bool trans_ld(DisasContext *ctx, arg_ld *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUQ);
-}
-
 static bool trans_sd(DisasContext *ctx, arg_sd *a)
 {
 REQUIRE_64BIT(ctx);
@@ -317,11 +317,6 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 return gen_arith(ctx, a, EXT_SIGN, gen_sltu);
 }
 
-static bool trans_xor(DisasContext *ctx, arg_xor *a)
-{
-return gen_logic(ctx, a, tcg_gen_xor_tl);
-}
-
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
 {
 return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
@@ -332,6 +327,11 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
 }
 
+static bool trans_xor(DisasContext *ctx, arg_xor *a)
+{
+return gen_logic(ctx, a, tcg_gen_xor_tl);
+}
+
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
 return gen_logic(ctx, a, tcg_gen_or_tl);
-- 
2.34.1




[PATCH v8 01/18] exec/memop: Adding signedness to quad definitions

2022-01-06 Thread Frédéric Pétrot
Renaming defines for quad in their various forms so that their signedness is
now explicit.
Done using git grep as suggested by Philippe, with a bit of hand edition to
keep assignments aligned.

Signed-off-by: Frédéric Pétrot 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 include/exec/memop.h   |  8 +--
 include/tcg/tcg-op.h   |  4 +-
 target/arm/translate-a32.h |  4 +-
 accel/tcg/cputlb.c | 30 +--
 accel/tcg/user-exec.c  |  8 +--
 target/alpha/translate.c   | 32 ++--
 target/arm/helper-a64.c|  8 +--
 target/arm/translate-a64.c |  8 +--
 target/arm/translate-neon.c|  6 +--
 target/arm/translate-sve.c | 10 ++--
 target/arm/translate-vfp.c |  8 +--
 target/arm/translate.c |  2 +-
 target/cris/translate.c|  2 +-
 target/hppa/translate.c|  4 +-
 target/i386/tcg/mem_helper.c   |  2 +-
 target/i386/tcg/translate.c| 36 +++---
 target/m68k/op_helper.c|  2 +-
 target/mips/tcg/translate.c| 58 +++---
 target/mips/tcg/tx79_translate.c   |  8 +--
 target/ppc/translate.c | 32 ++--
 target/s390x/tcg/mem_helper.c  |  8 +--
 target/s390x/tcg/translate.c   |  8 +--
 target/sh4/translate.c | 12 ++---
 target/sparc/translate.c   | 36 +++---
 target/tricore/translate.c |  4 +-
 target/xtensa/translate.c  |  4 +-
 tcg/tcg.c  |  4 +-
 tcg/tci.c  | 16 +++---
 accel/tcg/ldst_common.c.inc|  8 +--
 target/mips/tcg/micromips_translate.c.inc  | 10 ++--
 target/ppc/translate/fixedpoint-impl.c.inc | 22 
 target/ppc/translate/fp-impl.c.inc |  4 +-
 target/ppc/translate/vsx-impl.c.inc| 42 
 target/riscv/insn_trans/trans_rva.c.inc| 22 
 target/riscv/insn_trans/trans_rvd.c.inc|  4 +-
 target/riscv/insn_trans/trans_rvh.c.inc|  4 +-
 target/riscv/insn_trans/trans_rvi.c.inc|  4 +-
 target/s390x/tcg/translate_vx.c.inc| 18 +++
 tcg/aarch64/tcg-target.c.inc   |  2 +-
 tcg/arm/tcg-target.c.inc   | 10 ++--
 tcg/i386/tcg-target.c.inc  | 12 ++---
 tcg/mips/tcg-target.c.inc  | 12 ++---
 tcg/ppc/tcg-target.c.inc   | 16 +++---
 tcg/riscv/tcg-target.c.inc |  6 +--
 tcg/s390x/tcg-target.c.inc | 18 +++
 tcg/sparc/tcg-target.c.inc | 16 +++---
 target/s390x/tcg/insn-data.def | 28 +--
 47 files changed, 311 insertions(+), 311 deletions(-)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 04264ffd6b..72c2f0ff3d 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -85,29 +85,29 @@ typedef enum MemOp {
 MO_UB= MO_8,
 MO_UW= MO_16,
 MO_UL= MO_32,
+MO_UQ= MO_64,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
-MO_Q = MO_64,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
+MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
-MO_LEQ   = MO_LE | MO_Q,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
+MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
-MO_BEQ   = MO_BE | MO_Q,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
+MO_TEUQ  = MO_TE | MO_UQ,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
-MO_TEQ   = MO_TE | MO_Q,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index 0545a6224c..caa0a63612 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -894,7 +894,7 @@ static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, 
int mem_index)
 
 static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
 {
-tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEQ);
+tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEUQ);
 }
 
 static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
@@ -914,7 +914,7 @@ static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, 
int mem_index)
 
 static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
 {
-tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEQ);
+tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEUQ);
 }
 
 void tcg_gen_atomic_cmpxchg_i32(TCGv_i32, TCGv, TCGv_i32, TCGv_i32,
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
index 17af8dc95a..5be4b9b834 100644

[PATCH v8 03/18] qemu/int128: addition of div/rem 128-bit operations

2022-01-06 Thread Frédéric Pétrot
Addition of div and rem on 128-bit integers, using the 128/64->128 divu and
64x64->128 mulu in host-utils.
These operations will be used within div/rem helpers in the 128-bit riscv
target.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 include/qemu/int128.h |  27 
 util/int128.c | 147 ++
 util/meson.build  |   1 +
 3 files changed, 175 insertions(+)
 create mode 100644 util/int128.c

diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index b6d517aea4..2c4064256c 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -172,6 +172,26 @@ static inline Int128 bswap128(Int128 a)
 #endif
 }
 
+static inline Int128 int128_divu(Int128 a, Int128 b)
+{
+return (__uint128_t)a / (__uint128_t)b;
+}
+
+static inline Int128 int128_remu(Int128 a, Int128 b)
+{
+return (__uint128_t)a % (__uint128_t)b;
+}
+
+static inline Int128 int128_divs(Int128 a, Int128 b)
+{
+return a / b;
+}
+
+static inline Int128 int128_rems(Int128 a, Int128 b)
+{
+return a % b;
+}
+
 #else /* !CONFIG_INT128 */
 
 typedef struct Int128 Int128;
@@ -379,6 +399,11 @@ static inline Int128 bswap128(Int128 a)
 return int128_make128(bswap64(a.hi), bswap64(a.lo));
 }
 
+Int128 int128_divu(Int128, Int128);
+Int128 int128_remu(Int128, Int128);
+Int128 int128_divs(Int128, Int128);
+Int128 int128_rems(Int128, Int128);
+
 #endif /* CONFIG_INT128 */
 
 static inline void bswap128s(Int128 *s)
@@ -386,4 +411,6 @@ static inline void bswap128s(Int128 *s)
 *s = bswap128(*s);
 }
 
+#define UINT128_MAX int128_make128(~0LL, ~0LL)
+
 #endif /* INT128_H */
diff --git a/util/int128.c b/util/int128.c
new file mode 100644
index 00..ed8f25fef1
--- /dev/null
+++ b/util/int128.c
@@ -0,0 +1,147 @@
+/*
+ * 128-bit division and remainder for compilers not supporting __int128
+ *
+ * Copyright (c) 2021 Frédéric Pétrot 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "qemu/int128.h"
+
+#ifndef CONFIG_INT128
+
+/*
+ * Division and remainder algorithms for 128-bit due to Stefan Kanthak,
+ * https://skanthak.homepage.t-online.de/integer.html#udivmodti4
+ * Preconditions:
+ * - function should never be called with v equals to 0, it has to
+ *   be dealt with beforehand
+ * - quotien pointer must be valid
+ */
+static Int128 divrem128(Int128 u, Int128 v, Int128 *q)
+{
+Int128 qq;
+uint64_t hi, lo, tmp;
+int s = clz64(v.hi);
+
+if (s == 64) {
+/* we have uu÷0v => let's use divu128 */
+hi = u.hi;
+lo = u.lo;
+tmp = divu128(, , v.lo);
+*q = int128_make128(lo, hi);
+return int128_make128(tmp, 0);
+} else {
+hi = int128_gethi(int128_lshift(v, s));
+
+if (hi > u.hi) {
+lo = u.lo;
+tmp = u.hi;
+divu128(, , hi);
+lo = int128_gethi(int128_lshift(int128_make128(lo, 0), s));
+} else { /* prevent overflow */
+lo = u.lo;
+tmp = u.hi - hi;
+divu128(, , hi);
+lo = int128_gethi(int128_lshift(int128_make128(lo, 1), s));
+}
+
+qq = int128_make64(lo);
+
+tmp = lo * v.hi;
+mulu64(, , lo, v.lo);
+hi += tmp;
+
+if (hi < tmp /* quotient * divisor >= 2**128 > dividend */
+|| hi > u.hi /* quotient * divisor > dividend */
+|| (hi == u.hi && lo > u.lo)) {
+qq.lo -= 1;
+mulu64(, , qq.lo, v.lo);
+hi += qq.lo * v.hi;
+}
+
+*q = qq;
+u.hi -= hi + (u.lo < lo);
+u.lo -= lo;
+return u;
+}
+}
+
+Int128 int128_divu(Int128 a, Int128 b)
+{
+Int128 q;
+divrem128(a, b, );
+return q;
+}
+
+Int128 int128_remu(Int128 a,

[PATCH v8 02/18] exec/memop: Adding signed quad and octo defines

2022-01-06 Thread Frédéric Pétrot
Adding defines to handle signed 64-bit and unsigned 128-bit quantities in
memory accesses.

Signed-off-by: Frédéric Pétrot 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 include/exec/memop.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 72c2f0ff3d..2a885f3917 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -86,28 +86,35 @@ typedef enum MemOp {
 MO_UW= MO_16,
 MO_UL= MO_32,
 MO_UQ= MO_64,
+MO_UO= MO_128,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
+MO_SQ= MO_SIGN | MO_64,
+MO_SO= MO_SIGN | MO_128,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
 MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
+MO_LESQ  = MO_LE | MO_SQ,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
 MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
+MO_BESQ  = MO_BE | MO_SQ,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
 MO_TEUQ  = MO_TE | MO_UQ,
+MO_TEUO  = MO_TE | MO_UO,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
+MO_TESQ  = MO_TE | MO_SQ,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
-- 
2.34.1




[PATCH v8 00/18] Adding partial support for 128-bit riscv target

2022-01-06 Thread Frédéric Pétrot
This series of patches provides partial 128-bit support for the riscv
target architecture, namely RVI and RVM, with minimal csr support.

Thanks for the reviews and advices.

v8:
- rebase on riscv-to-apply.next

v7:
- code motion following reviews
- correction of a bug preventing riscv{32,64}-linux-user to compile
- sync with master
- Note that 'make check' fails for 5 qemu-iotests cases, namely
  040, 041, 127, 256, and 267, but they also fail with
  qemu-system-riscv{32,64} from current master

v6:
- support for '-cpu rv128' in qemu-system-riscv64 to handle 128-bit
  executables (no more qemu-system-riscv128)
- remove useless (and buggy) big-endian support in lq/sq

v5:
- split the memop define renaming and addition in two patches
- 128-bit div/rem operations using host-utils functions
- removed useless rv128 tests at various places
- refactoring the slt/bxx part so as to share the comparison part
- refactoring the 128-bit csr handling to share code more largely
  Also forwarding writes to the 64-bit version when not 128-bit version
  exists, as a vast majority of the csrs does not use the upper 64-bits

v4: 
- safer and cleaner access to the gpr upper part
- locals for load/store/div/rem helpers
- cleans out the 128-bit div/rem code
- corrects numerous bugs and performs optimizations on shifts and mults
- withdraws the change in page size and the vm schemes we introduced

v3:
- v2 refactored following Richard's xl patch changes

v2:
- load and store making use of new memop.h sizes
- use of the existing Int128 computations in helpers, and addition of
  a few more operations there, in particular division and remainder
- refactoring of the calls to the code generation helpers
- split of the patch in smaller pieces

v1:
- introducing support for rv128 for basic integer and M extension insns


Frédéric Pétrot (18):
  exec/memop: Adding signedness to quad definitions
  exec/memop: Adding signed quad and octo defines
  qemu/int128: addition of div/rem 128-bit operations
  target/riscv: additional macros to check instruction support
  target/riscv: separation of bitwise logic and arithmetic helpers
  target/riscv: array for the 64 upper bits of 128-bit registers
  target/riscv: setup everything for rv64 to support rv128 execution
  target/riscv: moving some insns close to similar insns
  target/riscv: accessors to registers upper part and 128-bit load/store
  target/riscv: support for 128-bit bitwise instructions
  target/riscv: support for 128-bit U-type instructions
  target/riscv: support for 128-bit shift instructions
  target/riscv: support for 128-bit arithmetic instructions
  target/riscv: support for 128-bit M extension
  target/riscv: adding high part of some csrs
  target/riscv: helper functions to wrap calls to 128-bit csr insns
  target/riscv: modification of the trans_csrxx for 128-bit support
  target/riscv: actual functions to realize crs 128-bit insns

 include/disas/dis-asm.h|   1 +
 include/exec/memop.h   |  15 +-
 include/qemu/int128.h  |  27 +
 include/tcg/tcg-op.h   |   4 +-
 target/arm/translate-a32.h |   4 +-
 target/riscv/cpu.h |  22 +
 target/riscv/cpu_bits.h|   3 +
 target/riscv/helper.h  |   9 +
 target/riscv/insn16.decode |  27 +-
 target/riscv/insn32.decode |  25 +
 accel/tcg/cputlb.c |  30 +-
 accel/tcg/user-exec.c  |   8 +-
 disas/riscv.c  |   5 +
 target/alpha/translate.c   |  32 +-
 target/arm/helper-a64.c|   8 +-
 target/arm/translate-a64.c |   8 +-
 target/arm/translate-neon.c|   6 +-
 target/arm/translate-sve.c |  10 +-
 target/arm/translate-vfp.c |   8 +-
 target/arm/translate.c |   2 +-
 target/cris/translate.c|   2 +-
 target/hppa/translate.c|   4 +-
 target/i386/tcg/mem_helper.c   |   2 +-
 target/i386/tcg/translate.c|  36 +-
 target/m68k/op_helper.c|   2 +-
 target/mips/tcg/translate.c|  58 +-
 target/mips/tcg/tx79_translate.c   |   8 +-
 target/ppc/translate.c |  32 +-
 target/riscv/cpu.c |  29 +
 target/riscv/csr.c | 194 +-
 target/riscv/gdbstub.c |   5 +
 target/riscv/m128_helper.c | 109 +++
 target/riscv/machine.c |  22 +
 target/riscv/op_helper.c   |  44 ++
 target/riscv/translate.c   | 252 ++-
 target/s390x/tcg/mem_helper.c  |   8 +-
 target/s390x/tcg/translate.c   |   8 +-
 target/sh4/translate.c |  12 +-
 target/sparc/translate.c   |  36 +-
 target/tricore

Re: [PATCH v7 00/18] Adding partial support for 128-bit riscv target

2022-01-06 Thread Frédéric Pétrot

On 06/01/2022 09:33, Alistair Francis wrote:

On Tue, Dec 14, 2021 at 2:39 AM Frédéric Pétrot
 wrote:


This series of patches provides partial 128-bit support for the riscv
target architecture, namely RVI and RVM, with minimal csr support.

Thanks again for the reviews and advices.


I think this is all reviewed now. I was getting an error when trying
to apply it though, do you mind rebasing on
https://github.com/alistair23/qemu/tree/riscv-to-apply.next ?


  Thanks Alistair,
  I will do that, sure.
  Frédéric


Alistair



v7:
- code motion following reviews
- correction of a bug preventing riscv{32,64}-linux-user to compile
- sync with master
- Note that 'make check' fails for 5 qemu-iotests cases, namely
   040, 041, 127, 256, and 267, but they also fail with
   qemu-system-riscv{32,64} from current master

v6:
- support for '-cpu rv128' in qemu-system-riscv64 to handle 128-bit
   executables (no more qemu-system-riscv128)
- remove useless (and buggy) big-endian support in lq/sq

v5:
- split the memop define renaming and addition in two patches
- 128-bit div/rem operations using host-utils functions
- removed useless rv128 tests at various places
- refactoring the slt/bxx part so as to share the comparison part
- refactoring the 128-bit csr handling to share code more largely
   Also forwarding writes to the 64-bit version when not 128-bit version
   exists, as a vast majority of the csrs does not use the upper 64-bits

v4:
- safer and cleaner access to the gpr upper part
- locals for load/store/div/rem helpers
- cleans out the 128-bit div/rem code
- corrects numerous bugs and performs optimizations on shifts and mults
- withdraws the change in page size and the vm schemes we introduced

v3:
- v2 refactored following Richard's xl patch changes

v2:
- load and store making use of new memop.h sizes
- use of the existing Int128 computations in helpers, and addition of
   a few more operations there, in particular division and remainder
- refactoring of the calls to the code generation helpers
- split of the patch in smaller pieces

v1:
- introducing support for rv128 for basic integer and M extension insns

Frédéric Pétrot (18):
   exec/memop: Adding signedness to quad definitions
   exec/memop: Adding signed quad and octo defines
   qemu/int128: addition of div/rem 128-bit operations
   target/riscv: additional macros to check instruction support
   target/riscv: separation of bitwise logic and arithmetic helpers
   target/riscv: array for the 64 upper bits of 128-bit registers
   target/riscv: setup everything for rv64 to support rv128 execution
   target/riscv: moving some insns close to similar insns
   target/riscv: accessors to registers upper part and 128-bit load/store
   target/riscv: support for 128-bit bitwise instructions
   target/riscv: support for 128-bit U-type instructions
   target/riscv: support for 128-bit shift instructions
   target/riscv: support for 128-bit arithmetic instructions
   target/riscv: support for 128-bit M extension
   target/riscv: adding high part of some csrs
   target/riscv: helper functions to wrap calls to 128-bit csr insns
   target/riscv: modification of the trans_csrxx for 128-bit support
   target/riscv: actual functions to realize crs 128-bit insns

  include/disas/dis-asm.h|   1 +
  include/exec/memop.h   |  15 +-
  include/qemu/int128.h  |  27 +
  include/tcg/tcg-op.h   |   4 +-
  target/arm/translate-a32.h |   4 +-
  target/riscv/cpu.h |  22 +
  target/riscv/cpu_bits.h|   3 +
  target/riscv/helper.h  |   9 +
  target/riscv/insn16.decode |  27 +-
  target/riscv/insn32.decode |  25 +
  accel/tcg/cputlb.c |  30 +-
  accel/tcg/user-exec.c  |   8 +-
  disas/riscv.c  |   5 +
  target/alpha/translate.c   |  32 +-
  target/arm/helper-a64.c|   8 +-
  target/arm/translate-a64.c |   8 +-
  target/arm/translate-neon.c|   6 +-
  target/arm/translate-sve.c |  10 +-
  target/arm/translate-vfp.c |   8 +-
  target/arm/translate.c |   2 +-
  target/cris/translate.c|   2 +-
  target/hppa/translate.c|   4 +-
  target/i386/tcg/mem_helper.c   |   2 +-
  target/i386/tcg/translate.c|  36 +-
  target/m68k/op_helper.c|   2 +-
  target/mips/tcg/translate.c|  58 +-
  target/mips/tcg/tx79_translate.c   |   8 +-
  target/ppc/translate.c |  32 +-
  target/riscv/cpu.c |  29 +
  target/riscv/csr.c | 194 +-
  target/riscv/gdbstub.c |   5 +
  target/riscv/m128_helper.c | 109 +++
  target/riscv

[PATCH v7 18/18] target/riscv: actual functions to realize crs 128-bit insns

2021-12-13 Thread Frédéric Pétrot
The csrs are accessed through function pointers: we add 128-bit read
operations in the table for three csrs (writes fallback to the
64-bit version as the upper 64-bit information is handled elsewhere):
- misa, as mxl is needed for proper operation,
- mstatus and sstatus, to return sd
In addition, we also add read and write accesses to the machine and
supervisor scratch registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/cpu.h  |   7 ++
 target/riscv/cpu_bits.h |   3 +
 target/riscv/csr.c  | 195 +---
 3 files changed, 175 insertions(+), 30 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 00e5081598..3e770e3d03 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -486,12 +486,19 @@ RISCVException riscv_csrrw_i128(CPURISCVState *env, int 
csrno,
 Int128 *ret_value,
 Int128 new_value, Int128 write_mask);
 
+typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno,
+   Int128 *ret_value);
+typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int csrno,
+ Int128 new_value);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
 riscv_csr_read_fn read;
 riscv_csr_write_fn write;
 riscv_csr_op_fn op;
+riscv_csr_read128_fn read128;
+riscv_csr_write128_fn write128;
 } riscv_csr_operations;
 
 /* CSR function table constants */
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 9913fa9f77..390ba0a52f 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -392,6 +392,7 @@
 
 #define MSTATUS32_SD0x8000
 #define MSTATUS64_SD0x8000ULL
+#define MSTATUSH128_SD  0x8000ULL
 
 #define MISA32_MXL  0xC000
 #define MISA64_MXL  0xC000ULL
@@ -413,6 +414,8 @@ typedef enum {
 #define SSTATUS_SUM 0x0004 /* since: priv-1.10 */
 #define SSTATUS_MXR 0x0008
 
+#define SSTATUS64_UXL   0x0003ULL
+
 #define SSTATUS32_SD0x8000
 #define SSTATUS64_SD0x8000ULL
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index dca9e19a64..404aa2f31d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -453,7 +453,7 @@ static const target_ulong vs_delegable_excps = 
DELEGABLE_EXCPS &
   (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)));
 static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
-SSTATUS_SUM | SSTATUS_MXR;
+SSTATUS_SUM | SSTATUS_MXR | (target_ulong)SSTATUS64_UXL;
 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
 static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
@@ -498,6 +498,8 @@ static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
 return status | MSTATUS32_SD;
 case MXL_RV64:
 return status | MSTATUS64_SD;
+case MXL_RV128:
+return MSTATUSH128_SD;
 default:
 g_assert_not_reached();
 }
@@ -547,10 +549,11 @@ static RISCVException write_mstatus(CPURISCVState *env, 
int csrno,
 
 mstatus = (mstatus & ~mask) | (val & mask);
 
-if (riscv_cpu_mxl(env) == MXL_RV64) {
+RISCVMXL xl = riscv_cpu_mxl(env);
+if (xl > MXL_RV32) {
 /* SXL and UXL fields are for now read only */
-mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
-mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
+mstatus = set_field(mstatus, MSTATUS64_SXL, xl);
+mstatus = set_field(mstatus, MSTATUS64_UXL, xl);
 }
 env->mstatus = mstatus;
 
@@ -579,6 +582,20 @@ static RISCVException write_mstatush(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_mstatus_i128(CPURISCVState *env, int csrno,
+Int128 *val)
+{
+*val = int128_make128(env->mstatus, add_status_sd(MXL_RV128, 
env->mstatus));
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_misa_i128(CPURISCVState *env, int csrno,
+ Int128 *val)
+{
+*val = int128_make128(env->misa_ext, (uint64_t)MXL_RV128 << 62);
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException read_misa(CPURISCVState *env, int csrno,
 target_ulong *val)
 {
@@ -736,6 +753,21 @@ static RISCVException write_mcounteren(CPURISCVState *env, 
int csrno,
 }
 
 /* Machine Trap Handling */
+static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno,
+ Int128 *val)
+{
+*val = int128_make128(env-

[PATCH v7 15/18] target/riscv: adding high part of some csrs

2021-12-13 Thread Frédéric Pétrot
Adding the high part of a very minimal set of csr.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h | 4 
 target/riscv/machine.c | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 603ae04837..a7c2e5c93e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -193,6 +193,10 @@ struct CPURISCVState {
 target_ulong hgatp;
 uint64_t htimedelta;
 
+/* Upper 64-bits of 128-bit CSRs */
+uint64_t mscratchh;
+uint64_t sscratchh;
+
 /* Virtual CSRs */
 /*
  * For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 8af9caabf5..13b9ab375b 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -179,6 +179,8 @@ static const VMStateDescription vmstate_rv128 = {
 .needed = rv128_needed,
 .fields = (VMStateField[]) {
 VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_UINT64(env.mscratchh, RISCVCPU),
+VMSTATE_UINT64(env.sscratchh, RISCVCPU),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
2.34.1




[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 <http://www.gnu.org/licenses/>.
+ */
+
+#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

[PATCH v7 12/18] target/riscv: support for 128-bit shift instructions

2021-12-13 Thread Frédéric Pétrot
Handling shifts for 32, 64 and 128 operation length for RV128, following the
general framework for handling various olens proposed by Richard.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/insn32.decode  |  10 ++
 target/riscv/translate.c|  58 --
 target/riscv/insn_trans/trans_rvb.c.inc |  22 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 224 ++--
 4 files changed, 270 insertions(+), 44 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 02889c6082..e338a803a0 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -22,6 +22,7 @@
 %rs1   15:5
 %rd7:5
 %sh5   20:5
+%sh6   20:6
 
 %sh720:7
 %csr20:12
@@ -92,6 +93,9 @@
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
+# Formats 128:
+@sh6   .. .. . ... . ...  shamt=%sh6 %rs1 %rd
+
 # *** Privileged Instructions ***
 ecall    0 000 0 1110011
 ebreak  0001 0 000 0 1110011
@@ -167,6 +171,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+sllid00 ..  . 001 . 1011011 @sh6
+srlid00 ..  . 101 . 1011011 @sh6
+sraid01 ..  . 101 . 1011011 @sh6
+slld 000 . .  001 . 011 @r
+srld 000 . .  101 . 011 @r
+srad 010 . .  101 . 011 @r
 
 # *** RV32M Standard Extension ***
 mul  001 .  . 000 . 0110011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0b87312dda..15e628308d 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -560,7 +560,8 @@ static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, 
DisasExtend ext,
 }
 
 static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest, src1;
 int max_len = get_olen(ctx);
@@ -572,26 +573,38 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 dest = dest_gpr(ctx, a->rd);
 src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->shamt);
+if (max_len < 128) {
+func(dest, src1, a->shamt);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (f128 == NULL) {
+return false;
+}
+f128(dest, desth, src1, src1h, a->shamt);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
 DisasExtend ext,
 void (*f_tl)(TCGv, TCGv, target_long),
-void (*f_32)(TCGv, TCGv, target_long))
+void (*f_32)(TCGv, TCGv, target_long),
+void (*f_128)(TCGv, TCGv, TCGv, TCGv,
+  target_long))
 {
 int olen = get_olen(ctx);
 if (olen != TARGET_LONG_BITS) {
 if (olen == 32) {
 f_tl = f_32;
-} else {
+} else if (olen != 128) {
 g_assert_not_reached();
 }
 }
-return gen_shift_imm_fn(ctx, a, ext, f_tl);
+return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
 }
 
 static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
@@ -615,34 +628,49 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 }
 
 static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
 {
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 TCGv ext2 = tcg_temp_new();
+int max_len = get_olen(ctx);
 
-tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1);
-func(dest, src1, ext2);
+tcg_gen_andi_tl(ext2, src2, max_len - 1);
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, ext);
+
+if (max_len < 128) {
+func(dest, src1, ext2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCG

[PATCH v7 07/18] target/riscv: setup everything for rv64 to support rv128 execution

2021-12-13 Thread Frédéric Pétrot
This patch adds the support of the '-cpu rv128' option to
qemu-system-riscv64 so that we can indicate that we want to run rv128
executables.
Still, there is no support for 128-bit insns at that stage so qemu fails
miserably (as expected) if launched with this option.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 include/disas/dis-asm.h |  1 +
 target/riscv/cpu.h  |  1 +
 disas/riscv.c   |  5 +
 target/riscv/cpu.c  | 20 
 target/riscv/gdbstub.c  |  5 +
 5 files changed, 32 insertions(+)

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..102a1e7f50 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
 int print_insn_xtensa   (bfd_vma, disassemble_info*);
 int print_insn_riscv32  (bfd_vma, disassemble_info*);
 int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_riscv128 (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
 
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 53a295efb7..cbd4daa6d9 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -38,6 +38,7 @@
 #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
 #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
 #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
+#define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("rv128")
 #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
 #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c")
 #define TYPE_RISCV_CPU_SIFIVE_E31   RISCV_CPU_TYPE_NAME("sifive-e31")
diff --git a/disas/riscv.c b/disas/riscv.c
index 793ad14c27..03c8dc9961 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -3090,3 +3090,8 @@ int print_insn_riscv64(bfd_vma memaddr, struct 
disassemble_info *info)
 {
 return print_insn_riscv(memaddr, info, rv64);
 }
+
+int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info)
+{
+return print_insn_riscv(memaddr, info, rv128);
+}
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 364140f5ff..7f5370f2b2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -178,6 +178,19 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_priv_version(env, PRIV_VERSION_1_10_0);
 qdev_prop_set_bit(DEVICE(obj), "mmu", false);
 }
+
+static void rv128_base_cpu_init(Object *obj)
+{
+if (qemu_tcg_mttcg_enabled()) {
+/* Missing 128-bit aligned atomics */
+error_report("128-bit RISC-V currently does not work with Multi "
+ "Threaded TCG. Please use: -accel tcg,thread=single");
+exit(EXIT_FAILURE);
+}
+CPURISCVState *env = _CPU(obj)->env;
+/* We set this in the realise function */
+set_misa(env, MXL_RV128, 0);
+}
 #else
 static void rv32_base_cpu_init(Object *obj)
 {
@@ -402,6 +415,9 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 case MXL_RV64:
 info->print_insn = print_insn_riscv64;
 break;
+case MXL_RV128:
+info->print_insn = print_insn_riscv128;
+break;
 default:
 g_assert_not_reached();
 }
@@ -464,6 +480,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 #ifdef TARGET_RISCV64
 case MXL_RV64:
 break;
+case MXL_RV128:
+break;
 #endif
 case MXL_RV32:
 break;
@@ -670,6 +688,7 @@ static gchar *riscv_gdb_arch_name(CPUState *cs)
 case MXL_RV32:
 return g_strdup("riscv:rv32");
 case MXL_RV64:
+case MXL_RV128:
 return g_strdup("riscv:rv64");
 default:
 g_assert_not_reached();
@@ -822,6 +841,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,   rv64_sifive_e_cpu_init),
 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,   rv64_sifive_u_cpu_init),
 DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init),
+DEFINE_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
 #endif
 };
 
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 23429179e2..2fbdcc5879 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -164,6 +164,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)
 int bitsize = 16 << env->misa_mxl_max;
 int i;
 
+/* Until gdb knows about 128-bit registers */
+if (bitsize > 64) {
+bitsize = 64;
+}
+
 g_string_printf(s, "");
 g_string_append_printf(s, "");
 g_string_append_printf(s, "");
-- 
2.34.1




[PATCH v7 17/18] target/riscv: modification of the trans_csrxx for 128-bit support

2021-12-13 Thread Frédéric Pétrot
As opposed to the gen_arith and gen_shift generation helpers, the csr insns
do not have a common prototype, so the choice to generate 32/64 or 128-bit
helper calls is done in the trans_csrxx functions.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 205 ++--
 1 file changed, 160 insertions(+), 45 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index ca354130ec..3a0ae28fef 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -881,20 +881,78 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, 
TCGv src, TCGv mask)
 return do_csr_post(ctx);
 }
 
+static bool do_csrr_i128(DisasContext *ctx, int rd, int rc)
+{
+TCGv destl = dest_gpr(ctx, rd);
+TCGv desth = dest_gprh(ctx, rd);
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrr_i128(destl, cpu_env, csr);
+tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
+gen_set_gpr128(ctx, rd, destl, desth);
+return do_csr_post(ctx);
+}
+
+static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch)
+{
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrw_i128(cpu_env, csr, srcl, srch);
+return do_csr_post(ctx);
+}
+
+static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc,
+  TCGv srcl, TCGv srch, TCGv maskl, TCGv maskh)
+{
+TCGv destl = dest_gpr(ctx, rd);
+TCGv desth = dest_gprh(ctx, rd);
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrrw_i128(destl, cpu_env, csr, srcl, srch, maskl, maskh);
+tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
+gen_set_gpr128(ctx, rd, destl, desth);
+return do_csr_post(ctx);
+}
+
 static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
 {
-TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
-
-/*
- * If rd == 0, the insn shall not read the csr, nor cause any of the
- * side effects that might occur on a csr read.
- */
-if (a->rd == 0) {
-return do_csrw(ctx, a->csr, src);
+if (get_xl(ctx) < MXL_RV128) {
+TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
+
+/*
+ * If rd == 0, the insn shall not read the csr, nor cause any of the
+ * side effects that might occur on a csr read.
+ */
+if (a->rd == 0) {
+return do_csrw(ctx, a->csr, src);
+}
+
+TCGv mask = tcg_constant_tl(-1);
+return do_csrrw(ctx, a->rd, a->csr, src, mask);
+} else {
+TCGv srcl = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv srch = get_gprh(ctx, a->rs1);
+
+/*
+ * If rd == 0, the insn shall not read the csr, nor cause any of the
+ * side effects that might occur on a csr read.
+ */
+if (a->rd == 0) {
+return do_csrw_i128(ctx, a->csr, srcl, srch);
+}
+
+TCGv mask = tcg_constant_tl(-1);
+return do_csrrw_i128(ctx, a->rd, a->csr, srcl, srch, mask, mask);
 }
-
-TCGv mask = tcg_constant_tl(-1);
-return do_csrrw(ctx, a->rd, a->csr, src, mask);
 }
 
 static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
@@ -906,13 +964,24 @@ static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
  * a zero value, the instruction will still attempt to write the
  * unmodified value back to the csr and will cause side effects.
  */
-if (a->rs1 == 0) {
-return do_csrr(ctx, a->rd, a->csr);
+if (get_xl(ctx) < MXL_RV128) {
+if (a->rs1 == 0) {
+return do_csrr(ctx, a->rd, a->csr);
+}
+
+TCGv ones = tcg_constant_tl(-1);
+TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
+return do_csrrw(ctx, a->rd, a->csr, ones, mask);
+} else {
+if (a->rs1 == 0) {
+return do_csrr_i128(ctx, a->rd, a->csr);
+}
+
+TCGv ones = tcg_constant_tl(-1);
+TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO);
+TCGv maskh = get_gprh(ctx, a->rs1);
+return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, maskl, maskh);
 }
-
-TCGv ones = tcg_constant_tl(-1);
-TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
-return do_csrrw(ctx, a->rd, a->csr, ones, mask);
 }
 
 static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
@@ -924,28 +993,54 @@ static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
  * a zero value, the instruction will still attempt to write the
  * unmodified value back to the csr and will cause side effects.
  

[PATCH v7 06/18] target/riscv: array for the 64 upper bits of 128-bit registers

2021-12-13 Thread Frédéric Pétrot
The upper 64-bit of the 128-bit registers have now a place inside
the cpu state structure, and are created as globals for future use.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h   |  2 ++
 target/riscv/cpu.c   |  9 +
 target/riscv/machine.c   | 20 
 target/riscv/translate.c |  5 -
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0760c0af93..53a295efb7 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -110,6 +110,7 @@ FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1)
 
 struct CPURISCVState {
 target_ulong gpr[32];
+target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
 uint64_t fpr[32]; /* assume both F and D extensions */
 
 /* vector coprocessor state. */
@@ -339,6 +340,7 @@ static inline bool riscv_feature(CPURISCVState *env, int 
feature)
 #include "cpu_user.h"
 
 extern const char * const riscv_int_regnames[];
+extern const char * const riscv_int_regnamesh[];
 extern const char * const riscv_fpr_regnames[];
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f812998123..364140f5ff 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -42,6 +42,15 @@ const char * const riscv_int_regnames[] = {
   "x28/t3",  "x29/t4", "x30/t5", "x31/t6"
 };
 
+const char * const riscv_int_regnamesh[] = {
+  "x0h/zeroh", "x1h/rah",  "x2h/sph",   "x3h/gph",   "x4h/tph",  "x5h/t0h",
+  "x6h/t1h",   "x7h/t2h",  "x8h/s0h",   "x9h/s1h",   "x10h/a0h", "x11h/a1h",
+  "x12h/a2h",  "x13h/a3h", "x14h/a4h",  "x15h/a5h",  "x16h/a6h", "x17h/a7h",
+  "x18h/s2h",  "x19h/s3h", "x20h/s4h",  "x21h/s5h",  "x22h/s6h", "x23h/s7h",
+  "x24h/s8h",  "x25h/s9h", "x26h/s10h", "x27h/s11h", "x28h/t3h", "x29h/t4h",
+  "x30h/t5h",  "x31h/t6h"
+};
+
 const char * const riscv_fpr_regnames[] = {
   "f0/ft0",   "f1/ft1",  "f2/ft2",   "f3/ft3",   "f4/ft4",  "f5/ft5",
   "f6/ft6",   "f7/ft7",  "f8/fs0",   "f9/fs1",   "f10/fa0", "f11/fa1",
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index ad8248ebfd..8af9caabf5 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -164,6 +164,25 @@ static const VMStateDescription vmstate_pointermasking = {
 }
 };
 
+static bool rv128_needed(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+CPURISCVState *env = >env;
+
+return env->misa_mxl_max == MXL_RV128;
+}
+
+static const VMStateDescription vmstate_rv128 = {
+.name = "cpu/rv128",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = rv128_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_END_OF_LIST()
+}
+};
+
 const VMStateDescription vmstate_riscv_cpu = {
 .name = "cpu",
 .version_id = 3,
@@ -218,6 +237,7 @@ const VMStateDescription vmstate_riscv_cpu = {
 _hyper,
 _vector,
 _pointermasking,
+_rv128,
 NULL
 }
 };
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 9d102f21ee..f969885eed 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -32,7 +32,7 @@
 #include "instmap.h"
 
 /* global register indices */
-static TCGv cpu_gpr[32], cpu_pc, cpu_vl;
+static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl;
 static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
 static TCGv load_res;
 static TCGv load_val;
@@ -777,10 +777,13 @@ void riscv_translate_init(void)
  * unless you specifically block reads/writes to reg 0.
  */
 cpu_gpr[0] = NULL;
+cpu_gprh[0] = NULL;
 
 for (i = 1; i < 32; i++) {
 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
 offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
+cpu_gprh[i] = tcg_global_mem_new(cpu_env,
+offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
 }
 
 for (i = 0; i < 32; i++) {
-- 
2.34.1




[PATCH v7 16/18] target/riscv: helper functions to wrap calls to 128-bit csr insns

2021-12-13 Thread Frédéric Pétrot
Given the side effects they have, the csr instructions are realized as
helpers. We extend this existing infrastructure for 128-bit sized csr.
We return 128-bit values using the same approach as for div/rem.
Theses helpers all call a unique function that is currently a fallback
on the 64-bit version.
The trans_csrxx functions supporting 128-bit are yet to be implemented.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.h   |  5 +
 target/riscv/helper.h|  3 +++
 target/riscv/csr.c   | 17 
 target/riscv/op_helper.c | 44 
 4 files changed, 69 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a7c2e5c93e..00e5081598 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -25,6 +25,7 @@
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "qom/object.h"
+#include "qemu/int128.h"
 #include "cpu_bits.h"
 
 #define TCG_GUEST_DEFAULT_MO 0
@@ -481,6 +482,10 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
*env, int csrno,
   target_ulong new_value,
   target_ulong write_mask);
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+Int128 *ret_value,
+Int128 new_value, Int128 write_mask);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index c036825723..bf2b338bfd 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -66,6 +66,9 @@ DEF_HELPER_FLAGS_2(clmulr, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_2(csrr, tl, env, int)
 DEF_HELPER_3(csrw, void, env, int, tl)
 DEF_HELPER_4(csrrw, tl, env, int, tl, tl)
+DEF_HELPER_2(csrr_i128, tl, env, int)
+DEF_HELPER_4(csrw_i128, void, env, int, tl, tl)
+DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_2(sret, tl, env, tl)
 DEF_HELPER_2(mret, tl, env, tl)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 9f41954894..dca9e19a64 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1788,6 +1788,23 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
 return RISCV_EXCP_NONE;
 }
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+   Int128 *ret_value,
+   Int128 new_value, Int128 write_mask)
+{
+/* fall back to 64-bit version for now */
+target_ulong ret_64;
+RISCVException ret = riscv_csrrw(env, csrno, _64,
+ int128_getlo(new_value),
+ int128_getlo(write_mask));
+
+if (ret_value) {
+*ret_value = int128_make64(ret_64);
+}
+
+return ret;
+}
+
 /*
  * Debugger support.  If not in user mode, set env->debugger before the
  * riscv_csrrw call and clear it after the call.
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index ee7c24efe7..f4cf9c4698 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -69,6 +69,50 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
 return val;
 }
 
+target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_zero(),
+  int128_zero());
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
+void helper_csrw_i128(CPURISCVState *env, int csr,
+  target_ulong srcl, target_ulong srch)
+{
+RISCVException ret = riscv_csrrw_i128(env, csr, NULL,
+  int128_make128(srcl, srch),
+  UINT128_MAX);
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+}
+
+target_ulong helper_csrrw_i128(CPURISCVState *env, int csr,
+   target_ulong srcl, target_ulong srch,
+   target_ulong maskl, target_ulong maskh)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_make128(srcl, srch),
+  int128_make128(maskl, maskh));
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
 #ifndef CONFIG_USER_ONLY
 
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
-- 
2.34.1




[PATCH v7 09/18] target/riscv: accessors to registers upper part and 128-bit load/store

2021-12-13 Thread Frédéric Pétrot
Get function to retrieve the 64 top bits of a register, stored in the gprh
field of the cpu state. Set function that writes the 128-bit value at once.
The access to the gprh field can not be protected at compile time to make
sure it is accessed only in the 128-bit version of the processor because we
have no way to indicate that the misa_mxl_max field is const.

The 128-bit ISA adds ldu, lq and sq. We provide support for these
instructions. Note that (a) we compute only 64-bit addresses to actually
access memory, cowardly utilizing the existing address translation mechanism
of QEMU, and (b) we assume for now little-endian memory accesses.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn16.decode  |  27 ++-
 target/riscv/insn32.decode  |   5 ++
 target/riscv/translate.c|  41 ++
 target/riscv/insn_trans/trans_rvi.c.inc | 100 ++--
 4 files changed, 163 insertions(+), 10 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 2e9212663c..02c8f61b48 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -25,14 +25,17 @@
 # Immediates:
 %imm_ci12:s1 2:5
 %nzuimm_ciw7:4 11:2 5:1 6:1   !function=ex_shift_2
+%uimm_cl_q 10:1 5:2 11:2  !function=ex_shift_4
 %uimm_cl_d 5:2 10:3   !function=ex_shift_3
 %uimm_cl_w 5:1 10:3 6:1   !function=ex_shift_2
 %imm_cb12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
 %imm_cj12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
 
 %shimm_6bit   12:1 2:5   !function=ex_rvc_shifti
+%uimm_6bit_lq 2:4 12:1 6:1   !function=ex_shift_4
 %uimm_6bit_ld 2:3 12:1 5:2   !function=ex_shift_3
 %uimm_6bit_lw 2:2 12:1 4:3   !function=ex_shift_2
+%uimm_6bit_sq 7:4 11:2   !function=ex_shift_4
 %uimm_6bit_sd 7:3 10:3   !function=ex_shift_3
 %uimm_6bit_sw 7:2 9:4!function=ex_shift_2
 
@@ -54,16 +57,20 @@
 # Formats 16:
 @cr  . .  ..   rs2=%rs2_5   rs1=%rd %rd
 @ci... . . .  ..   imm=%imm_ci  rs1=%rd %rd
+@cl_q  ... . .  . ..   imm=%uimm_cl_q   rs1=%rs1_3  rd=%rs2_3
 @cl_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  rd=%rs2_3
 @cl_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  rd=%rs2_3
 @cs_2  ... ... ... .. ... ..   rs2=%rs2_3   rs1=%rs1_3  rd=%rs1_3
+@cs_q  ... ... ... .. ... ..   imm=%uimm_cl_q   rs1=%rs1_3  
rs2=%rs2_3
 @cs_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  
rs2=%rs2_3
 @cs_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  
rs2=%rs2_3
 @cj...... ..   imm=%imm_cj
 @cb_z  ... ... ... .. ... ..   imm=%imm_cb  rs1=%rs1_3  rs2=0
 
+@c_lqsp... . .  . ..   imm=%uimm_6bit_lq rs1=2 %rd
 @c_ldsp... . .  . ..   imm=%uimm_6bit_ld rs1=2 %rd
 @c_lwsp... . .  . ..   imm=%uimm_6bit_lw rs1=2 %rd
+@c_sqsp... . .  . ..   imm=%uimm_6bit_sq rs1=2 rs2=%rs2_5
 @c_sdsp... . .  . ..   imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5
 @c_swsp... . .  . ..   imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5
 @c_li  ... . .  . ..   imm=%imm_ci rs1=0 %rd
@@ -87,9 +94,15 @@
   illegal 000  000 000 00 --- 00
   addi000  ... ... .. ... 00 @c_addi4spn
 }
-fld   001  ... ... .. ... 00 @cl_d
+{
+  lq  001  ... ... .. ... 00 @cl_q
+  fld 001  ... ... .. ... 00 @cl_d
+}
 lw010  ... ... .. ... 00 @cl_w
-fsd   101  ... ... .. ... 00 @cs_d
+{
+  sq  101  ... ... .. ... 00 @cs_q
+  fsd 101  ... ... .. ... 00 @cs_d
+}
 sw110  ... ... .. ... 00 @cs_w
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 0) ***
@@ -132,7 +145,10 @@ addw  100 1 11 ... 01 ... 01 @cs_2
 
 # *** RV32/64C Standard Extension (Quadrant 2) ***
 slli  000 .  .  . 10 @c_shift2
-fld   001 .  .  . 10 @c_ldsp
+{
+  lq  001  ... ... .. ... 10 @c_lqsp
+  fld 001 .  .  . 10 @c_ldsp
+}
 {
   illegal 010 -  0  - 10 # c.lwsp, RES rd=0
   lw  010 .  .  . 10 @c_lwsp
@@ -147,7 +163,10 @@ fld   001 .  .  . 10 @c_ldsp
   jalr100 1  .  0 10 @c_jalr rd=1  # C.JALR
   add 100 1  .  . 10 @cr
 }
-fsd   101   ..  . 10 @c_sdsp
+{
+  sq  101  ... ... .. ... 10 @c_sqsp
+  fsd 101   ..  . 10 @c_sdsp
+}
 sw110 .  .  . 10 @c_swsp
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 2) ***
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 2f251dac1b..02889c6082 100644

[PATCH v7 05/18] target/riscv: separation of bitwise logic and arithmetic helpers

2021-12-13 Thread Frédéric Pétrot
Introduction of a gen_logic function for bitwise logic to implement
instructions in which no propagation of information occurs between bits and
use of this function on the bitwise instructions.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c| 27 +
 target/riscv/insn_trans/trans_rvb.c.inc |  6 +++---
 target/riscv/insn_trans/trans_rvi.c.inc | 12 +--
 3 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 2718ff15a1..9d102f21ee 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -400,6 +400,33 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm)
 /* Include the auto-generated decoder for 32 bit insn */
 #include "decode-insn32.c.inc"
 
+static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
+ void (*func)(TCGv, TCGv, target_long))
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+
+func(dest, src1, a->imm);
+
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
+static bool gen_logic(DisasContext *ctx, arg_r *a,
+  void (*func)(TCGv, TCGv, TCGv))
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+func(dest, src1, src2);
+
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
  void (*func)(TCGv, TCGv, target_long))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index c8d31907c5..de2cd613b1 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -86,19 +86,19 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
 static bool trans_andn(DisasContext *ctx, arg_andn *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl);
+return gen_logic(ctx, a, tcg_gen_andc_tl);
 }
 
 static bool trans_orn(DisasContext *ctx, arg_orn *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl);
+return gen_logic(ctx, a, tcg_gen_orc_tl);
 }
 
 static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl);
+return gen_logic(ctx, a, tcg_gen_eqv_tl);
 }
 
 static bool trans_min(DisasContext *ctx, arg_min *a)
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 4a2aefe3a5..51607b3d40 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -252,17 +252,17 @@ static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
 
 static bool trans_xori(DisasContext *ctx, arg_xori *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_xori_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_xori_tl);
 }
 
 static bool trans_ori(DisasContext *ctx, arg_ori *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_ori_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_ori_tl);
 }
 
 static bool trans_andi(DisasContext *ctx, arg_andi *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_andi_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_andi_tl);
 }
 
 static bool trans_slli(DisasContext *ctx, arg_slli *a)
@@ -319,7 +319,7 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 
 static bool trans_xor(DisasContext *ctx, arg_xor *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_xor_tl);
+return gen_logic(ctx, a, tcg_gen_xor_tl);
 }
 
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
@@ -334,12 +334,12 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_or_tl);
+return gen_logic(ctx, a, tcg_gen_or_tl);
 }
 
 static bool trans_and(DisasContext *ctx, arg_and *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_and_tl);
+return gen_logic(ctx, a, tcg_gen_and_tl);
 }
 
 static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
-- 
2.34.1




[PATCH v7 13/18] target/riscv: support for 128-bit arithmetic instructions

2021-12-13 Thread Frédéric Pétrot
Addition of 128-bit adds and subs in their various sizes,
"set if less than"s and branches.
Refactored the code to have a comparison function used for both stls and
branches.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/insn32.decode  |   3 +
 target/riscv/translate.c|  63 --
 target/riscv/insn_trans/trans_rvb.c.inc |  20 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 159 +---
 target/riscv/insn_trans/trans_rvm.c.inc |  26 ++--
 5 files changed, 222 insertions(+), 49 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index e338a803a0..afaf243b4e 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -171,9 +171,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+addid  .  000 . 1011011 @i
 sllid00 ..  . 001 . 1011011 @sh6
 srlid00 ..  . 101 . 1011011 @sh6
 sraid01 ..  . 101 . 1011011 @sh6
+addd 000 . .  000 . 011 @r
+subd 010 . .  000 . 011 @r
 slld 000 . .  001 . 011 @r
 srld 000 . .  101 . 011 @r
 srad 010 . .  101 . 011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 15e628308d..02176ec1a9 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -506,57 +506,96 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 }
 
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->imm);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, a->imm);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, a->imm);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, TCGv))
+ void (*func)(TCGv, TCGv, TCGv),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = tcg_constant_tl(a->imm);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = tcg_constant_tl(-(a->imm < 0));
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, ext);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
  void (*f_tl)(TCGv, TCGv, TCGv),
- void (*f_32)(TCGv, TCGv, TCGv))
+ void (*f_32)(TCGv, TCGv, TCGv),
+ void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 int olen = get_olen(ctx);
 
 if (olen != TARGET_LONG_BITS) {
 if (olen == 32) {
  

[PATCH v7 10/18] target/riscv: support for 128-bit bitwise instructions

2021-12-13 Thread Frédéric Pétrot
The 128-bit bitwise instructions do not need any function prototype change
as the functions can be applied independently on the lower and upper part of
the registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index b6127783b3..4790dc0cb4 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -448,7 +448,15 @@ static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
 
 func(dest, src1, a->imm);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, -(a->imm < 0));
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
@@ -462,7 +470,16 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 
 func(dest, src1, src2);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
-- 
2.34.1




[PATCH v7 02/18] exec/memop: Adding signed quad and octo defines

2021-12-13 Thread Frédéric Pétrot
Adding defines to handle signed 64-bit and unsigned 128-bit quantities in
memory accesses.

Signed-off-by: Frédéric Pétrot 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 include/exec/memop.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 72c2f0ff3d..2a885f3917 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -86,28 +86,35 @@ typedef enum MemOp {
 MO_UW= MO_16,
 MO_UL= MO_32,
 MO_UQ= MO_64,
+MO_UO= MO_128,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
+MO_SQ= MO_SIGN | MO_64,
+MO_SO= MO_SIGN | MO_128,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
 MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
+MO_LESQ  = MO_LE | MO_SQ,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
 MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
+MO_BESQ  = MO_BE | MO_SQ,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
 MO_TEUQ  = MO_TE | MO_UQ,
+MO_TEUO  = MO_TE | MO_UO,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
+MO_TESQ  = MO_TE | MO_SQ,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
-- 
2.34.1




[PATCH v7 11/18] target/riscv: support for 128-bit U-type instructions

2021-12-13 Thread Frédéric Pétrot
Adding the 128-bit version of lui and auipc, and introducing to that end
a "set register with immediat" function to handle extension on 128 bits.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c| 21 +
 target/riscv/insn_trans/trans_rvi.c.inc |  8 
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 4790dc0cb4..0b87312dda 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -289,6 +289,27 @@ static void gen_set_gpr(DisasContext *ctx, int reg_num, 
TCGv t)
 }
 }
 
+static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm)
+{
+if (reg_num != 0) {
+switch (get_ol(ctx)) {
+case MXL_RV32:
+tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm);
+break;
+case MXL_RV64:
+case MXL_RV128:
+tcg_gen_movi_tl(cpu_gpr[reg_num], imm);
+break;
+default:
+g_assert_not_reached();
+}
+
+if (get_xl_max(ctx) == MXL_RV128) {
+tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0));
+}
+}
+}
+
 static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh)
 {
 assert(get_ol(ctx) == MXL_RV128);
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index e572976e88..6113acc669 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -26,14 +26,14 @@ static bool trans_illegal(DisasContext *ctx, arg_empty *a)
 
 static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
 {
- REQUIRE_64BIT(ctx);
- return trans_illegal(ctx, a);
+REQUIRE_64_OR_128BIT(ctx);
+return trans_illegal(ctx, a);
 }
 
 static bool trans_lui(DisasContext *ctx, arg_lui *a)
 {
 if (a->rd != 0) {
-tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm);
+gen_set_gpri(ctx, a->rd, a->imm);
 }
 return true;
 }
@@ -41,7 +41,7 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a)
 static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
 {
 if (a->rd != 0) {
-tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm + ctx->base.pc_next);
+gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
 }
 return true;
 }
-- 
2.34.1




[PATCH v7 03/18] qemu/int128: addition of div/rem 128-bit operations

2021-12-13 Thread Frédéric Pétrot
Addition of div and rem on 128-bit integers, using the 128/64->128 divu and
64x64->128 mulu in host-utils.
These operations will be used within div/rem helpers in the 128-bit riscv
target.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 include/qemu/int128.h |  27 
 util/int128.c | 147 ++
 util/meson.build  |   1 +
 3 files changed, 175 insertions(+)
 create mode 100644 util/int128.c

diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index b6d517aea4..2c4064256c 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -172,6 +172,26 @@ static inline Int128 bswap128(Int128 a)
 #endif
 }
 
+static inline Int128 int128_divu(Int128 a, Int128 b)
+{
+return (__uint128_t)a / (__uint128_t)b;
+}
+
+static inline Int128 int128_remu(Int128 a, Int128 b)
+{
+return (__uint128_t)a % (__uint128_t)b;
+}
+
+static inline Int128 int128_divs(Int128 a, Int128 b)
+{
+return a / b;
+}
+
+static inline Int128 int128_rems(Int128 a, Int128 b)
+{
+return a % b;
+}
+
 #else /* !CONFIG_INT128 */
 
 typedef struct Int128 Int128;
@@ -379,6 +399,11 @@ static inline Int128 bswap128(Int128 a)
 return int128_make128(bswap64(a.hi), bswap64(a.lo));
 }
 
+Int128 int128_divu(Int128, Int128);
+Int128 int128_remu(Int128, Int128);
+Int128 int128_divs(Int128, Int128);
+Int128 int128_rems(Int128, Int128);
+
 #endif /* CONFIG_INT128 */
 
 static inline void bswap128s(Int128 *s)
@@ -386,4 +411,6 @@ static inline void bswap128s(Int128 *s)
 *s = bswap128(*s);
 }
 
+#define UINT128_MAX int128_make128(~0LL, ~0LL)
+
 #endif /* INT128_H */
diff --git a/util/int128.c b/util/int128.c
new file mode 100644
index 00..ed8f25fef1
--- /dev/null
+++ b/util/int128.c
@@ -0,0 +1,147 @@
+/*
+ * 128-bit division and remainder for compilers not supporting __int128
+ *
+ * Copyright (c) 2021 Frédéric Pétrot 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "qemu/int128.h"
+
+#ifndef CONFIG_INT128
+
+/*
+ * Division and remainder algorithms for 128-bit due to Stefan Kanthak,
+ * https://skanthak.homepage.t-online.de/integer.html#udivmodti4
+ * Preconditions:
+ * - function should never be called with v equals to 0, it has to
+ *   be dealt with beforehand
+ * - quotien pointer must be valid
+ */
+static Int128 divrem128(Int128 u, Int128 v, Int128 *q)
+{
+Int128 qq;
+uint64_t hi, lo, tmp;
+int s = clz64(v.hi);
+
+if (s == 64) {
+/* we have uu÷0v => let's use divu128 */
+hi = u.hi;
+lo = u.lo;
+tmp = divu128(, , v.lo);
+*q = int128_make128(lo, hi);
+return int128_make128(tmp, 0);
+} else {
+hi = int128_gethi(int128_lshift(v, s));
+
+if (hi > u.hi) {
+lo = u.lo;
+tmp = u.hi;
+divu128(, , hi);
+lo = int128_gethi(int128_lshift(int128_make128(lo, 0), s));
+} else { /* prevent overflow */
+lo = u.lo;
+tmp = u.hi - hi;
+divu128(, , hi);
+lo = int128_gethi(int128_lshift(int128_make128(lo, 1), s));
+}
+
+qq = int128_make64(lo);
+
+tmp = lo * v.hi;
+mulu64(, , lo, v.lo);
+hi += tmp;
+
+if (hi < tmp /* quotient * divisor >= 2**128 > dividend */
+|| hi > u.hi /* quotient * divisor > dividend */
+|| (hi == u.hi && lo > u.lo)) {
+qq.lo -= 1;
+mulu64(, , qq.lo, v.lo);
+hi += qq.lo * v.hi;
+}
+
+*q = qq;
+u.hi -= hi + (u.lo < lo);
+u.lo -= lo;
+return u;
+}
+}
+
+Int128 int128_divu(Int128 a, Int128 b)
+{
+Int128 q;
+divrem128(a, b, );
+return q;
+}
+
+Int128 int128_remu(Int128 a,

[PATCH v7 08/18] target/riscv: moving some insns close to similar insns

2021-12-13 Thread Frédéric Pétrot
lwu and ld are functionally close to the other loads, but were after the
stores in the source file.
Similarly, xor was away from or and and by two arithmetic functions, while
the immediate versions were nicely put together.
This patch moves the aforementioned loads after lhu, and xor above or,
where they more logically belong.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 34 -
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 51607b3d40..710f5e6a85 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -176,6 +176,18 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
 return gen_load(ctx, a, MO_TEUW);
 }
 
+static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUL);
+}
+
+static bool trans_ld(DisasContext *ctx, arg_ld *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUQ);
+}
+
 static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
 {
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@@ -207,18 +219,6 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a)
 return gen_store(ctx, a, MO_TESL);
 }
 
-static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUL);
-}
-
-static bool trans_ld(DisasContext *ctx, arg_ld *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUQ);
-}
-
 static bool trans_sd(DisasContext *ctx, arg_sd *a)
 {
 REQUIRE_64BIT(ctx);
@@ -317,11 +317,6 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 return gen_arith(ctx, a, EXT_SIGN, gen_sltu);
 }
 
-static bool trans_xor(DisasContext *ctx, arg_xor *a)
-{
-return gen_logic(ctx, a, tcg_gen_xor_tl);
-}
-
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
 {
 return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
@@ -332,6 +327,11 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
 }
 
+static bool trans_xor(DisasContext *ctx, arg_xor *a)
+{
+return gen_logic(ctx, a, tcg_gen_xor_tl);
+}
+
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
 return gen_logic(ctx, a, tcg_gen_or_tl);
-- 
2.34.1




[PATCH v7 00/18] Adding partial support for 128-bit riscv target

2021-12-13 Thread Frédéric Pétrot
This series of patches provides partial 128-bit support for the riscv
target architecture, namely RVI and RVM, with minimal csr support.

Thanks again for the reviews and advices.

v7:
- code motion following reviews
- correction of a bug preventing riscv{32,64}-linux-user to compile
- sync with master
- Note that 'make check' fails for 5 qemu-iotests cases, namely
  040, 041, 127, 256, and 267, but they also fail with
  qemu-system-riscv{32,64} from current master

v6:
- support for '-cpu rv128' in qemu-system-riscv64 to handle 128-bit
  executables (no more qemu-system-riscv128)
- remove useless (and buggy) big-endian support in lq/sq

v5:
- split the memop define renaming and addition in two patches
- 128-bit div/rem operations using host-utils functions
- removed useless rv128 tests at various places
- refactoring the slt/bxx part so as to share the comparison part
- refactoring the 128-bit csr handling to share code more largely
  Also forwarding writes to the 64-bit version when not 128-bit version
  exists, as a vast majority of the csrs does not use the upper 64-bits

v4: 
- safer and cleaner access to the gpr upper part
- locals for load/store/div/rem helpers
- cleans out the 128-bit div/rem code
- corrects numerous bugs and performs optimizations on shifts and mults
- withdraws the change in page size and the vm schemes we introduced

v3:
- v2 refactored following Richard's xl patch changes

v2:
- load and store making use of new memop.h sizes
- use of the existing Int128 computations in helpers, and addition of
  a few more operations there, in particular division and remainder
- refactoring of the calls to the code generation helpers
- split of the patch in smaller pieces

v1:
- introducing support for rv128 for basic integer and M extension insns

Frédéric Pétrot (18):
  exec/memop: Adding signedness to quad definitions
  exec/memop: Adding signed quad and octo defines
  qemu/int128: addition of div/rem 128-bit operations
  target/riscv: additional macros to check instruction support
  target/riscv: separation of bitwise logic and arithmetic helpers
  target/riscv: array for the 64 upper bits of 128-bit registers
  target/riscv: setup everything for rv64 to support rv128 execution
  target/riscv: moving some insns close to similar insns
  target/riscv: accessors to registers upper part and 128-bit load/store
  target/riscv: support for 128-bit bitwise instructions
  target/riscv: support for 128-bit U-type instructions
  target/riscv: support for 128-bit shift instructions
  target/riscv: support for 128-bit arithmetic instructions
  target/riscv: support for 128-bit M extension
  target/riscv: adding high part of some csrs
  target/riscv: helper functions to wrap calls to 128-bit csr insns
  target/riscv: modification of the trans_csrxx for 128-bit support
  target/riscv: actual functions to realize crs 128-bit insns

 include/disas/dis-asm.h|   1 +
 include/exec/memop.h   |  15 +-
 include/qemu/int128.h  |  27 +
 include/tcg/tcg-op.h   |   4 +-
 target/arm/translate-a32.h |   4 +-
 target/riscv/cpu.h |  22 +
 target/riscv/cpu_bits.h|   3 +
 target/riscv/helper.h  |   9 +
 target/riscv/insn16.decode |  27 +-
 target/riscv/insn32.decode |  25 +
 accel/tcg/cputlb.c |  30 +-
 accel/tcg/user-exec.c  |   8 +-
 disas/riscv.c  |   5 +
 target/alpha/translate.c   |  32 +-
 target/arm/helper-a64.c|   8 +-
 target/arm/translate-a64.c |   8 +-
 target/arm/translate-neon.c|   6 +-
 target/arm/translate-sve.c |  10 +-
 target/arm/translate-vfp.c |   8 +-
 target/arm/translate.c |   2 +-
 target/cris/translate.c|   2 +-
 target/hppa/translate.c|   4 +-
 target/i386/tcg/mem_helper.c   |   2 +-
 target/i386/tcg/translate.c|  36 +-
 target/m68k/op_helper.c|   2 +-
 target/mips/tcg/translate.c|  58 +-
 target/mips/tcg/tx79_translate.c   |   8 +-
 target/ppc/translate.c |  32 +-
 target/riscv/cpu.c |  29 +
 target/riscv/csr.c | 194 +-
 target/riscv/gdbstub.c |   5 +
 target/riscv/m128_helper.c | 109 +++
 target/riscv/machine.c |  22 +
 target/riscv/op_helper.c   |  44 ++
 target/riscv/translate.c   | 252 ++-
 target/s390x/tcg/mem_helper.c  |   8 +-
 target/s390x/tcg/translate.c   |   8 +-
 target/sh4/translate.c |  12 +-
 target/sparc/translate.c   |  36 +-
 target/tricore/translate.c

[PATCH v7 04/18] target/riscv: additional macros to check instruction support

2021-12-13 Thread Frédéric Pétrot
Given that the 128-bit version of the riscv spec adds new instructions, and
that some instructions that were previously only available in 64-bit mode
are now available for both 64-bit and 128-bit, we added new macros to check
for the processor mode during translation.
Although RV128 is a superset of RV64, we keep for now the RV64 only tests
for extensions other than RVI and RVM.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 1d57bc97b5..2718ff15a1 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -368,10 +368,22 @@ EX_SH(12)
 }  \
 } while (0)
 
-#define REQUIRE_64BIT(ctx) do {\
-if (get_xl(ctx) < MXL_RV64) {  \
-return false;  \
-}  \
+#define REQUIRE_64BIT(ctx) do { \
+if (get_xl(ctx) != MXL_RV64) {  \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_128BIT(ctx) do {\
+if (get_xl(ctx) != MXL_RV128) { \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_64_OR_128BIT(ctx) do { \
+if (get_xl(ctx) == MXL_RV32) { \
+return false;  \
+}  \
 } while (0)
 
 static int ex_rvc_register(DisasContext *ctx, int reg)
-- 
2.34.1




[PATCH v7 01/18] exec/memop: Adding signedness to quad definitions

2021-12-13 Thread Frédéric Pétrot
Renaming defines for quad in their various forms so that their signedness is
now explicit.
Done using git grep as suggested by Philippe, with a bit of hand edition to
keep assignments aligned.

Signed-off-by: Frédéric Pétrot 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 include/exec/memop.h   |  8 +--
 include/tcg/tcg-op.h   |  4 +-
 target/arm/translate-a32.h |  4 +-
 accel/tcg/cputlb.c | 30 +--
 accel/tcg/user-exec.c  |  8 +--
 target/alpha/translate.c   | 32 ++--
 target/arm/helper-a64.c|  8 +--
 target/arm/translate-a64.c |  8 +--
 target/arm/translate-neon.c|  6 +--
 target/arm/translate-sve.c | 10 ++--
 target/arm/translate-vfp.c |  8 +--
 target/arm/translate.c |  2 +-
 target/cris/translate.c|  2 +-
 target/hppa/translate.c|  4 +-
 target/i386/tcg/mem_helper.c   |  2 +-
 target/i386/tcg/translate.c| 36 +++---
 target/m68k/op_helper.c|  2 +-
 target/mips/tcg/translate.c| 58 +++---
 target/mips/tcg/tx79_translate.c   |  8 +--
 target/ppc/translate.c | 32 ++--
 target/s390x/tcg/mem_helper.c  |  8 +--
 target/s390x/tcg/translate.c   |  8 +--
 target/sh4/translate.c | 12 ++---
 target/sparc/translate.c   | 36 +++---
 target/tricore/translate.c |  4 +-
 target/xtensa/translate.c  |  4 +-
 tcg/tcg.c  |  4 +-
 tcg/tci.c  | 16 +++---
 accel/tcg/ldst_common.c.inc|  8 +--
 target/mips/tcg/micromips_translate.c.inc  | 10 ++--
 target/ppc/translate/fixedpoint-impl.c.inc | 22 
 target/ppc/translate/fp-impl.c.inc |  4 +-
 target/ppc/translate/vsx-impl.c.inc| 42 
 target/riscv/insn_trans/trans_rva.c.inc| 22 
 target/riscv/insn_trans/trans_rvd.c.inc|  4 +-
 target/riscv/insn_trans/trans_rvh.c.inc|  4 +-
 target/riscv/insn_trans/trans_rvi.c.inc|  4 +-
 target/s390x/tcg/translate_vx.c.inc| 18 +++
 tcg/aarch64/tcg-target.c.inc   |  2 +-
 tcg/arm/tcg-target.c.inc   | 10 ++--
 tcg/i386/tcg-target.c.inc  | 12 ++---
 tcg/mips/tcg-target.c.inc  | 12 ++---
 tcg/ppc/tcg-target.c.inc   | 16 +++---
 tcg/riscv/tcg-target.c.inc |  6 +--
 tcg/s390x/tcg-target.c.inc | 18 +++
 tcg/sparc/tcg-target.c.inc | 16 +++---
 target/s390x/tcg/insn-data.def | 28 +--
 47 files changed, 311 insertions(+), 311 deletions(-)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 04264ffd6b..72c2f0ff3d 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -85,29 +85,29 @@ typedef enum MemOp {
 MO_UB= MO_8,
 MO_UW= MO_16,
 MO_UL= MO_32,
+MO_UQ= MO_64,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
-MO_Q = MO_64,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
+MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
-MO_LEQ   = MO_LE | MO_Q,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
+MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
-MO_BEQ   = MO_BE | MO_Q,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
+MO_TEUQ  = MO_TE | MO_UQ,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
-MO_TEQ   = MO_TE | MO_Q,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index 0545a6224c..caa0a63612 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -894,7 +894,7 @@ static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, 
int mem_index)
 
 static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
 {
-tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEQ);
+tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEUQ);
 }
 
 static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
@@ -914,7 +914,7 @@ static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, 
int mem_index)
 
 static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
 {
-tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEQ);
+tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEUQ);
 }
 
 void tcg_gen_atomic_cmpxchg_i32(TCGv_i32, TCGv, TCGv_i32, TCGv_i32,
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
index 17af8dc95a..5be4b9b834 100644

Re: [PATCH v6 00/18] Adding partial support for 128-bit riscv target

2021-12-06 Thread Frédéric Pétrot

Hi Richard,

On 29/11/2021 13:13, Richard Henderson wrote:

On 11/28/21 2:57 PM, Frédéric Pétrot wrote:

This series of patches provides partial 128-bit support for the riscv
target architecture, namely RVI and RVM, with minimal csr support.

Thanks again for the reviews and suggestions.

v6:
- support for '-cpu rv128' in qemu-system-riscv64 to handle 128-bit
   executables (no more qemu-system-riscv128)
- remove useless (and buggy) big-endian support in lq/sq


This also fails make check.  With

   ../qemu/configure --enable-debug 
--target-list=riscv64-linux-user,riscv64-softmmu,riscv32-softmmu,riscv32-linux-user


watch qemu-iotest 040 fail.


  I'm afraid this test and a few others (5 in total) fail on current master,
  too, with this 'configure' command line.
  I just did a fresh install to make sure I did not kill something in the rv128
  patches.

  Note that if I add x86_64-softmmu to target-list, it runs like a charm, as
  it takes it as default choice.
  I did try to go back in time to find a working 040 with qemu-system-riscv32
  (the default choice of check when qemu-system-x86_64 does not exist) or
  qemu-system-riscv64, but I could not find one I could compile with my current
  system.
  So I suspect this is the syndrome of something that is (1) not of my doing
  (although it could have, for sure), and (2) above my understanding.

  Sorry for not being more helpful,
  Frédéric



r~


--
+---+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



Re: [PATCH v6 03/18] qemu/int128: addition of div/rem 128-bit operations

2021-11-29 Thread Frédéric Pétrot

On 29/11/2021 11:07, Richard Henderson wrote:

On 11/28/21 2:57 PM, Frédéric Pétrot wrote:

--- /dev/null
+++ b/util/int128.c
@@ -0,0 +1,145 @@
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "qemu/int128.h"


Missing file header and copyright boilerplate.


+#ifdef CONFIG_INT128
+
+Int128 int128_divu(Int128 a, Int128 b)
+{
+    return (__uint128_t)a / (__uint128_t)b;
+}
+
+Int128 int128_remu(Int128 a, Int128 b)
+{
+    return (__uint128_t)a % (__uint128_t)b;
+}
+
+Int128 int128_divs(Int128 a, Int128 b)
+{
+    return a / b;
+}
+
+Int128 int128_rems(Int128 a, Int128 b)
+{
+    return a % b;
+}


I think we should simply expose these inline, and let the compiler call its 
runtime function directly.


  Thanks.
  Ok, I'll drop that and handle the CONFIG_INT128 directly in the rv128
  div/rem helpers then.
  Frédéric



r~


--
+-------+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



Re: [PATCH v6 00/18] Adding partial support for 128-bit riscv target

2021-11-29 Thread Frédéric Pétrot

On 29/11/2021 13:13, Richard Henderson wrote:

On 11/28/21 2:57 PM, Frédéric Pétrot wrote:

This series of patches provides partial 128-bit support for the riscv
target architecture, namely RVI and RVM, with minimal csr support.

Thanks again for the reviews and suggestions.

v6:
- support for '-cpu rv128' in qemu-system-riscv64 to handle 128-bit
   executables (no more qemu-system-riscv128)
- remove useless (and buggy) big-endian support in lq/sq


This also fails make check.  With

   ../qemu/configure --enable-debug 
--target-list=riscv64-linux-user,riscv64-softmmu,riscv32-softmmu,riscv32-linux-user


  Ah! Indeed, sorry for the mess, I indeed forgot about linux-user.
  Frédéric



watch qemu-iotest 040 fail.


r~


--
+---+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



[PATCH v6 13/18] target/riscv: support for 128-bit arithmetic instructions

2021-11-28 Thread Frédéric Pétrot
Addition of 128-bit adds and subs in their various sizes,
"set if less than"s and branches.
Refactored the code to have a comparison function used for both stls and
branches.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/insn32.decode  |   3 +
 target/riscv/translate.c|  63 --
 target/riscv/insn_trans/trans_rvb.c.inc |  20 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 159 +---
 target/riscv/insn_trans/trans_rvm.c.inc |  26 ++--
 5 files changed, 222 insertions(+), 49 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index e338a803a0..afaf243b4e 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -171,9 +171,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+addid  .  000 . 1011011 @i
 sllid00 ..  . 001 . 1011011 @sh6
 srlid00 ..  . 101 . 1011011 @sh6
 sraid01 ..  . 101 . 1011011 @sh6
+addd 000 . .  000 . 011 @r
+subd 010 . .  000 . 011 @r
 slld 000 . .  001 . 011 @r
 srld 000 . .  101 . 011 @r
 srad 010 . .  101 . 011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 15e628308d..02176ec1a9 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -506,57 +506,96 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 }
 
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->imm);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, a->imm);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, a->imm);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, TCGv))
+ void (*func)(TCGv, TCGv, TCGv),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = tcg_constant_tl(a->imm);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = tcg_constant_tl(-(a->imm < 0));
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, ext);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
  void (*f_tl)(TCGv, TCGv, TCGv),
- void (*f_32)(TCGv, TCGv, TCGv))
+ void (*f_32)(TCGv, TCGv, TCGv),
+ void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 int olen = get_olen(ctx);
 
 if (olen != TARGET_LONG_BITS) {
 if (olen == 32) {
  

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

2021-11-28 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 <http://www.gnu.org/licenses/>.
+ */
+
+#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

[PATCH v6 11/18] target/riscv: support for 128-bit U-type instructions

2021-11-28 Thread Frédéric Pétrot
Adding the 128-bit version of lui and auipc, and introducing to that end
a "set register with immediat" function to handle extension on 128 bits.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c| 21 +
 target/riscv/insn_trans/trans_rvi.c.inc |  8 
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 4790dc0cb4..0b87312dda 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -289,6 +289,27 @@ static void gen_set_gpr(DisasContext *ctx, int reg_num, 
TCGv t)
 }
 }
 
+static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm)
+{
+if (reg_num != 0) {
+switch (get_ol(ctx)) {
+case MXL_RV32:
+tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm);
+break;
+case MXL_RV64:
+case MXL_RV128:
+tcg_gen_movi_tl(cpu_gpr[reg_num], imm);
+break;
+default:
+g_assert_not_reached();
+}
+
+if (get_xl_max(ctx) == MXL_RV128) {
+tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0));
+}
+}
+}
+
 static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh)
 {
 assert(get_ol(ctx) == MXL_RV128);
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index e572976e88..6113acc669 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -26,14 +26,14 @@ static bool trans_illegal(DisasContext *ctx, arg_empty *a)
 
 static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
 {
- REQUIRE_64BIT(ctx);
- return trans_illegal(ctx, a);
+REQUIRE_64_OR_128BIT(ctx);
+return trans_illegal(ctx, a);
 }
 
 static bool trans_lui(DisasContext *ctx, arg_lui *a)
 {
 if (a->rd != 0) {
-tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm);
+gen_set_gpri(ctx, a->rd, a->imm);
 }
 return true;
 }
@@ -41,7 +41,7 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a)
 static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
 {
 if (a->rd != 0) {
-tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm + ctx->base.pc_next);
+gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
 }
 return true;
 }
-- 
2.34.0




[PATCH v6 16/18] target/riscv: helper functions to wrap calls to 128-bit csr insns

2021-11-28 Thread Frédéric Pétrot
Given the side effects they have, the csr instructions are realized as
helpers. We extend this existing infrastructure for 128-bit sized csr.
We return 128-bit values using the same approach as for div/rem.
Theses helpers all call a unique function that is currently a fallback
on the 64-bit version.
The trans_csrxx functions supporting 128-bit are yet to be implemented.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.h   |  4 
 target/riscv/helper.h|  3 +++
 target/riscv/csr.c   | 17 
 target/riscv/op_helper.c | 44 
 4 files changed, 68 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a7c2e5c93e..a9717a63af 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -481,6 +481,10 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
*env, int csrno,
   target_ulong new_value,
   target_ulong write_mask);
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+Int128 *ret_value,
+Int128 new_value, Int128 write_mask);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index c036825723..bf2b338bfd 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -66,6 +66,9 @@ DEF_HELPER_FLAGS_2(clmulr, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_2(csrr, tl, env, int)
 DEF_HELPER_3(csrw, void, env, int, tl)
 DEF_HELPER_4(csrrw, tl, env, int, tl, tl)
+DEF_HELPER_2(csrr_i128, tl, env, int)
+DEF_HELPER_4(csrw_i128, void, env, int, tl, tl)
+DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_2(sret, tl, env, tl)
 DEF_HELPER_2(mret, tl, env, tl)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 9f41954894..dca9e19a64 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1788,6 +1788,23 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
 return RISCV_EXCP_NONE;
 }
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+   Int128 *ret_value,
+   Int128 new_value, Int128 write_mask)
+{
+/* fall back to 64-bit version for now */
+target_ulong ret_64;
+RISCVException ret = riscv_csrrw(env, csrno, _64,
+ int128_getlo(new_value),
+ int128_getlo(write_mask));
+
+if (ret_value) {
+*ret_value = int128_make64(ret_64);
+}
+
+return ret;
+}
+
 /*
  * Debugger support.  If not in user mode, set env->debugger before the
  * riscv_csrrw call and clear it after the call.
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index ee7c24efe7..f4cf9c4698 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -69,6 +69,50 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
 return val;
 }
 
+target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_zero(),
+  int128_zero());
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
+void helper_csrw_i128(CPURISCVState *env, int csr,
+  target_ulong srcl, target_ulong srch)
+{
+RISCVException ret = riscv_csrrw_i128(env, csr, NULL,
+  int128_make128(srcl, srch),
+  UINT128_MAX);
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+}
+
+target_ulong helper_csrrw_i128(CPURISCVState *env, int csr,
+   target_ulong srcl, target_ulong srch,
+   target_ulong maskl, target_ulong maskh)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_make128(srcl, srch),
+  int128_make128(maskl, maskh));
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
 #ifndef CONFIG_USER_ONLY
 
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
-- 
2.34.0




[PATCH v6 10/18] target/riscv: support for 128-bit bitwise instructions

2021-11-28 Thread Frédéric Pétrot
The 128-bit bitwise instructions do not need any function prototype change
as the functions can be applied independently on the lower and upper part of
the registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index b6127783b3..4790dc0cb4 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -448,7 +448,15 @@ static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
 
 func(dest, src1, a->imm);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, -(a->imm < 0));
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
@@ -462,7 +470,16 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 
 func(dest, src1, src2);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
-- 
2.34.0




[PATCH v6 18/18] target/riscv: actual functions to realize crs 128-bit insns

2021-11-28 Thread Frédéric Pétrot
The csrs are accessed through function pointers: we add 128-bit read
operations in the table for three csrs (writes fallback to the
64-bit version as the upper 64-bit information is handled elsewhere):
- misa, as mxl is needed for proper operation,
- mstatus and sstatus, to return sd
In addition, we also add read and write accesses to the machine and
supervisor scratch registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/cpu.h  |   7 ++
 target/riscv/cpu_bits.h |   3 +
 target/riscv/csr.c  | 195 +---
 3 files changed, 175 insertions(+), 30 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a9717a63af..a410f91e99 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -485,12 +485,19 @@ RISCVException riscv_csrrw_i128(CPURISCVState *env, int 
csrno,
 Int128 *ret_value,
 Int128 new_value, Int128 write_mask);
 
+typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno,
+   Int128 *ret_value);
+typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int csrno,
+ Int128 new_value);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
 riscv_csr_read_fn read;
 riscv_csr_write_fn write;
 riscv_csr_op_fn op;
+riscv_csr_read128_fn read128;
+riscv_csr_write128_fn write128;
 } riscv_csr_operations;
 
 /* CSR function table constants */
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 9913fa9f77..390ba0a52f 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -392,6 +392,7 @@
 
 #define MSTATUS32_SD0x8000
 #define MSTATUS64_SD0x8000ULL
+#define MSTATUSH128_SD  0x8000ULL
 
 #define MISA32_MXL  0xC000
 #define MISA64_MXL  0xC000ULL
@@ -413,6 +414,8 @@ typedef enum {
 #define SSTATUS_SUM 0x0004 /* since: priv-1.10 */
 #define SSTATUS_MXR 0x0008
 
+#define SSTATUS64_UXL   0x0003ULL
+
 #define SSTATUS32_SD0x8000
 #define SSTATUS64_SD0x8000ULL
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index dca9e19a64..ef4db1bb3a 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -453,7 +453,7 @@ static const target_ulong vs_delegable_excps = 
DELEGABLE_EXCPS &
   (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)));
 static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
-SSTATUS_SUM | SSTATUS_MXR;
+SSTATUS_SUM | SSTATUS_MXR | (target_ulong)SSTATUS64_UXL;
 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
 static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
@@ -498,6 +498,8 @@ static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
 return status | MSTATUS32_SD;
 case MXL_RV64:
 return status | MSTATUS64_SD;
+case MXL_RV128:
+return MSTATUSH128_SD;
 default:
 g_assert_not_reached();
 }
@@ -547,10 +549,11 @@ static RISCVException write_mstatus(CPURISCVState *env, 
int csrno,
 
 mstatus = (mstatus & ~mask) | (val & mask);
 
-if (riscv_cpu_mxl(env) == MXL_RV64) {
+RISCVMXL xl = riscv_cpu_mxl(env);
+if (xl > MXL_RV32) {
 /* SXL and UXL fields are for now read only */
-mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
-mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
+mstatus = set_field(mstatus, MSTATUS64_SXL, xl);
+mstatus = set_field(mstatus, MSTATUS64_UXL, xl);
 }
 env->mstatus = mstatus;
 
@@ -579,6 +582,20 @@ static RISCVException write_mstatush(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_mstatus_i128(CPURISCVState *env, int csrno,
+Int128 *val)
+{
+*val = int128_make128(env->mstatus, add_status_sd(MXL_RV128, 
env->mstatus));
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_misa_i128(CPURISCVState *env, int csrno,
+ Int128 *val)
+{
+*val = int128_make128(env->misa_ext, (uint64_t)MXL_RV128 << 62);
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException read_misa(CPURISCVState *env, int csrno,
 target_ulong *val)
 {
@@ -736,6 +753,21 @@ static RISCVException write_mcounteren(CPURISCVState *env, 
int csrno,
 }
 
 /* Machine Trap Handling */
+static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno,
+ Int128 *val)
+{
+*val = int128_make128(env-

[PATCH v6 17/18] target/riscv: modification of the trans_csrxx for 128-bit support

2021-11-28 Thread Frédéric Pétrot
As opposed to the gen_arith and gen_shift generation helpers, the csr insns
do not have a common prototype, so the choice to generate 32/64 or 128-bit
helper calls is done in the trans_csrxx functions.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 205 ++--
 1 file changed, 160 insertions(+), 45 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index ca354130ec..3a0ae28fef 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -881,20 +881,78 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, 
TCGv src, TCGv mask)
 return do_csr_post(ctx);
 }
 
+static bool do_csrr_i128(DisasContext *ctx, int rd, int rc)
+{
+TCGv destl = dest_gpr(ctx, rd);
+TCGv desth = dest_gprh(ctx, rd);
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrr_i128(destl, cpu_env, csr);
+tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
+gen_set_gpr128(ctx, rd, destl, desth);
+return do_csr_post(ctx);
+}
+
+static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch)
+{
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrw_i128(cpu_env, csr, srcl, srch);
+return do_csr_post(ctx);
+}
+
+static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc,
+  TCGv srcl, TCGv srch, TCGv maskl, TCGv maskh)
+{
+TCGv destl = dest_gpr(ctx, rd);
+TCGv desth = dest_gprh(ctx, rd);
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrrw_i128(destl, cpu_env, csr, srcl, srch, maskl, maskh);
+tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
+gen_set_gpr128(ctx, rd, destl, desth);
+return do_csr_post(ctx);
+}
+
 static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
 {
-TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
-
-/*
- * If rd == 0, the insn shall not read the csr, nor cause any of the
- * side effects that might occur on a csr read.
- */
-if (a->rd == 0) {
-return do_csrw(ctx, a->csr, src);
+if (get_xl(ctx) < MXL_RV128) {
+TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
+
+/*
+ * If rd == 0, the insn shall not read the csr, nor cause any of the
+ * side effects that might occur on a csr read.
+ */
+if (a->rd == 0) {
+return do_csrw(ctx, a->csr, src);
+}
+
+TCGv mask = tcg_constant_tl(-1);
+return do_csrrw(ctx, a->rd, a->csr, src, mask);
+} else {
+TCGv srcl = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv srch = get_gprh(ctx, a->rs1);
+
+/*
+ * If rd == 0, the insn shall not read the csr, nor cause any of the
+ * side effects that might occur on a csr read.
+ */
+if (a->rd == 0) {
+return do_csrw_i128(ctx, a->csr, srcl, srch);
+}
+
+TCGv mask = tcg_constant_tl(-1);
+return do_csrrw_i128(ctx, a->rd, a->csr, srcl, srch, mask, mask);
 }
-
-TCGv mask = tcg_constant_tl(-1);
-return do_csrrw(ctx, a->rd, a->csr, src, mask);
 }
 
 static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
@@ -906,13 +964,24 @@ static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
  * a zero value, the instruction will still attempt to write the
  * unmodified value back to the csr and will cause side effects.
  */
-if (a->rs1 == 0) {
-return do_csrr(ctx, a->rd, a->csr);
+if (get_xl(ctx) < MXL_RV128) {
+if (a->rs1 == 0) {
+return do_csrr(ctx, a->rd, a->csr);
+}
+
+TCGv ones = tcg_constant_tl(-1);
+TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
+return do_csrrw(ctx, a->rd, a->csr, ones, mask);
+} else {
+if (a->rs1 == 0) {
+return do_csrr_i128(ctx, a->rd, a->csr);
+}
+
+TCGv ones = tcg_constant_tl(-1);
+TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO);
+TCGv maskh = get_gprh(ctx, a->rs1);
+return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, maskl, maskh);
 }
-
-TCGv ones = tcg_constant_tl(-1);
-TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
-return do_csrrw(ctx, a->rd, a->csr, ones, mask);
 }
 
 static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
@@ -924,28 +993,54 @@ static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
  * a zero value, the instruction will still attempt to write the
  * unmodified value back to the csr and will cause side effects.
  

[PATCH v6 04/18] target/riscv: additional macros to check instruction support

2021-11-28 Thread Frédéric Pétrot
Given that the 128-bit version of the riscv spec adds new instructions, and
that some instructions that were previously only available in 64-bit mode
are now available for both 64-bit and 128-bit, we added new macros to check
for the processor mode during translation.
Although RV128 is a superset of RV64, we keep for now the RV64 only tests
for extensions other than RVI and RVM.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 1d57bc97b5..2718ff15a1 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -368,10 +368,22 @@ EX_SH(12)
 }  \
 } while (0)
 
-#define REQUIRE_64BIT(ctx) do {\
-if (get_xl(ctx) < MXL_RV64) {  \
-return false;  \
-}  \
+#define REQUIRE_64BIT(ctx) do { \
+if (get_xl(ctx) != MXL_RV64) {  \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_128BIT(ctx) do {\
+if (get_xl(ctx) != MXL_RV128) { \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_64_OR_128BIT(ctx) do { \
+if (get_xl(ctx) == MXL_RV32) { \
+return false;  \
+}  \
 } while (0)
 
 static int ex_rvc_register(DisasContext *ctx, int reg)
-- 
2.34.0




[PATCH v6 00/18] Adding partial support for 128-bit riscv target

2021-11-28 Thread Frédéric Pétrot
This series of patches provides partial 128-bit support for the riscv
target architecture, namely RVI and RVM, with minimal csr support.

Thanks again for the reviews and suggestions.

v6:
- support for '-cpu rv128' in qemu-system-riscv64 to handle 128-bit
  executables (no more qemu-system-riscv128)
- remove useless (and buggy) big-endian support in lq/sq

v5:
- split the memop define renaming and addition in two patches
- 128-bit div/rem operations using host-utils functions
- removed useless rv128 tests at various places
- refactoring the slt/bxx part so as to share the comparison part
- refactoring the 128-bit csr handling to share code more largely
  Also forwarding writes to the 64-bit version when not 128-bit version
  exists, as a vast majority of the csrs does not use the upper 64-bits

v4: 
- safer and cleaner access to the gpr upper part
- locals for load/store/div/rem helpers
- cleans out the 128-bit div/rem code
- corrects numerous bugs and performs optimizations on shifts and mults
- withdraws the change in page size and the vm schemes we introduced

v3:
- v2 refactored following Richard's xl patch changes

v2:
- load and store making use of new memop.h sizes
- use of the existing Int128 computations in helpers, and addition of
  a few more operations there, in particular division and remainder
- refactoring of the calls to the code generation helpers
- split of the patch in smaller pieces

v1:
- introducing support for rv128 for basic integer and M extension insns

Frédéric Pétrot (18):
  exec/memop: Adding signedness to quad definitions
  exec/memop: Adding signed quad and octo defines
  qemu/int128: addition of div/rem 128-bit operations
  target/riscv: additional macros to check instruction support
  target/riscv: separation of bitwise logic and arithmetic helpers
  target/riscv: array for the 64 upper bits of 128-bit registers
  target/riscv: setup everything for rv64 to support rv128 execution
  target/riscv: moving some insns close to similar insns
  target/riscv: accessors to registers upper part and 128-bit load/store
  target/riscv: support for 128-bit bitwise instructions
  target/riscv: support for 128-bit U-type instructions
  target/riscv: support for 128-bit shift instructions
  target/riscv: support for 128-bit arithmetic instructions
  target/riscv: support for 128-bit M extension
  target/riscv: adding high part of some csrs
  target/riscv: helper functions to wrap calls to 128-bit csr insns
  target/riscv: modification of the trans_csrxx for 128-bit support
  target/riscv: actual functions to realize crs 128-bit insns

 include/disas/dis-asm.h|   1 +
 include/exec/memop.h   |  15 +-
 include/qemu/int128.h  |   6 +
 include/tcg/tcg-op.h   |   4 +-
 target/arm/translate-a32.h |   4 +-
 target/riscv/cpu.h |  21 +
 target/riscv/cpu_bits.h|   3 +
 target/riscv/helper.h  |   9 +
 target/riscv/insn16.decode |  27 +-
 target/riscv/insn32.decode |  25 +
 accel/tcg/cputlb.c |  30 +-
 accel/tcg/user-exec.c  |   8 +-
 disas/riscv.c  |   5 +
 target/alpha/translate.c   |  32 +-
 target/arm/helper-a64.c|   8 +-
 target/arm/translate-a64.c |   8 +-
 target/arm/translate-neon.c|   6 +-
 target/arm/translate-sve.c |  10 +-
 target/arm/translate-vfp.c |   8 +-
 target/arm/translate.c |   2 +-
 target/cris/translate.c|   2 +-
 target/hppa/translate.c|   4 +-
 target/i386/tcg/mem_helper.c   |   2 +-
 target/i386/tcg/translate.c|  36 +-
 target/m68k/op_helper.c|   2 +-
 target/mips/tcg/translate.c|  58 +-
 target/mips/tcg/tx79_translate.c   |   8 +-
 target/ppc/translate.c |  32 +-
 target/riscv/cpu.c |  29 +
 target/riscv/csr.c | 194 +-
 target/riscv/gdbstub.c |   5 +
 target/riscv/m128_helper.c | 109 +++
 target/riscv/machine.c |  22 +
 target/riscv/op_helper.c   |  44 ++
 target/riscv/translate.c   | 252 ++-
 target/s390x/tcg/mem_helper.c  |   8 +-
 target/s390x/tcg/translate.c   |   8 +-
 target/sh4/translate.c |  12 +-
 target/sparc/translate.c   |  36 +-
 target/tricore/translate.c |   4 +-
 target/xtensa/translate.c  |   4 +-
 tcg/tcg.c  |   4 +-
 tcg/tci.c  |  16 +-
 util/int128.c  | 145 
 accel/tcg/ldst_common.c.inc|   8 +-
 target/mips

[PATCH v6 12/18] target/riscv: support for 128-bit shift instructions

2021-11-28 Thread Frédéric Pétrot
Handling shifts for 32, 64 and 128 operation length for RV128, following the
general framework for handling various olens proposed by Richard.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/insn32.decode  |  10 ++
 target/riscv/translate.c|  58 --
 target/riscv/insn_trans/trans_rvb.c.inc |  22 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 224 ++--
 4 files changed, 270 insertions(+), 44 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 02889c6082..e338a803a0 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -22,6 +22,7 @@
 %rs1   15:5
 %rd7:5
 %sh5   20:5
+%sh6   20:6
 
 %sh720:7
 %csr20:12
@@ -92,6 +93,9 @@
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
+# Formats 128:
+@sh6   .. .. . ... . ...  shamt=%sh6 %rs1 %rd
+
 # *** Privileged Instructions ***
 ecall    0 000 0 1110011
 ebreak  0001 0 000 0 1110011
@@ -167,6 +171,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+sllid00 ..  . 001 . 1011011 @sh6
+srlid00 ..  . 101 . 1011011 @sh6
+sraid01 ..  . 101 . 1011011 @sh6
+slld 000 . .  001 . 011 @r
+srld 000 . .  101 . 011 @r
+srad 010 . .  101 . 011 @r
 
 # *** RV32M Standard Extension ***
 mul  001 .  . 000 . 0110011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0b87312dda..15e628308d 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -560,7 +560,8 @@ static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, 
DisasExtend ext,
 }
 
 static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest, src1;
 int max_len = get_olen(ctx);
@@ -572,26 +573,38 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 dest = dest_gpr(ctx, a->rd);
 src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->shamt);
+if (max_len < 128) {
+func(dest, src1, a->shamt);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (f128 == NULL) {
+return false;
+}
+f128(dest, desth, src1, src1h, a->shamt);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
 DisasExtend ext,
 void (*f_tl)(TCGv, TCGv, target_long),
-void (*f_32)(TCGv, TCGv, target_long))
+void (*f_32)(TCGv, TCGv, target_long),
+void (*f_128)(TCGv, TCGv, TCGv, TCGv,
+  target_long))
 {
 int olen = get_olen(ctx);
 if (olen != TARGET_LONG_BITS) {
 if (olen == 32) {
 f_tl = f_32;
-} else {
+} else if (olen != 128) {
 g_assert_not_reached();
 }
 }
-return gen_shift_imm_fn(ctx, a, ext, f_tl);
+return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
 }
 
 static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
@@ -615,34 +628,49 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 }
 
 static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
 {
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 TCGv ext2 = tcg_temp_new();
+int max_len = get_olen(ctx);
 
-tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1);
-func(dest, src1, ext2);
+tcg_gen_andi_tl(ext2, src2, max_len - 1);
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, ext);
+
+if (max_len < 128) {
+func(dest, src1, ext2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCG

[PATCH v6 06/18] target/riscv: array for the 64 upper bits of 128-bit registers

2021-11-28 Thread Frédéric Pétrot
The upper 64-bit of the 128-bit registers have now a place inside
the cpu state structure, and are created as globals for future use.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h   |  2 ++
 target/riscv/cpu.c   |  9 +
 target/riscv/machine.c   | 20 
 target/riscv/translate.c |  5 -
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0760c0af93..53a295efb7 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -110,6 +110,7 @@ FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1)
 
 struct CPURISCVState {
 target_ulong gpr[32];
+target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
 uint64_t fpr[32]; /* assume both F and D extensions */
 
 /* vector coprocessor state. */
@@ -339,6 +340,7 @@ static inline bool riscv_feature(CPURISCVState *env, int 
feature)
 #include "cpu_user.h"
 
 extern const char * const riscv_int_regnames[];
+extern const char * const riscv_int_regnamesh[];
 extern const char * const riscv_fpr_regnames[];
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f812998123..364140f5ff 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -42,6 +42,15 @@ const char * const riscv_int_regnames[] = {
   "x28/t3",  "x29/t4", "x30/t5", "x31/t6"
 };
 
+const char * const riscv_int_regnamesh[] = {
+  "x0h/zeroh", "x1h/rah",  "x2h/sph",   "x3h/gph",   "x4h/tph",  "x5h/t0h",
+  "x6h/t1h",   "x7h/t2h",  "x8h/s0h",   "x9h/s1h",   "x10h/a0h", "x11h/a1h",
+  "x12h/a2h",  "x13h/a3h", "x14h/a4h",  "x15h/a5h",  "x16h/a6h", "x17h/a7h",
+  "x18h/s2h",  "x19h/s3h", "x20h/s4h",  "x21h/s5h",  "x22h/s6h", "x23h/s7h",
+  "x24h/s8h",  "x25h/s9h", "x26h/s10h", "x27h/s11h", "x28h/t3h", "x29h/t4h",
+  "x30h/t5h",  "x31h/t6h"
+};
+
 const char * const riscv_fpr_regnames[] = {
   "f0/ft0",   "f1/ft1",  "f2/ft2",   "f3/ft3",   "f4/ft4",  "f5/ft5",
   "f6/ft6",   "f7/ft7",  "f8/fs0",   "f9/fs1",   "f10/fa0", "f11/fa1",
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index ad8248ebfd..8af9caabf5 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -164,6 +164,25 @@ static const VMStateDescription vmstate_pointermasking = {
 }
 };
 
+static bool rv128_needed(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+CPURISCVState *env = >env;
+
+return env->misa_mxl_max == MXL_RV128;
+}
+
+static const VMStateDescription vmstate_rv128 = {
+.name = "cpu/rv128",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = rv128_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_END_OF_LIST()
+}
+};
+
 const VMStateDescription vmstate_riscv_cpu = {
 .name = "cpu",
 .version_id = 3,
@@ -218,6 +237,7 @@ const VMStateDescription vmstate_riscv_cpu = {
 _hyper,
 _vector,
 _pointermasking,
+_rv128,
 NULL
 }
 };
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 9d102f21ee..f969885eed 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -32,7 +32,7 @@
 #include "instmap.h"
 
 /* global register indices */
-static TCGv cpu_gpr[32], cpu_pc, cpu_vl;
+static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl;
 static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
 static TCGv load_res;
 static TCGv load_val;
@@ -777,10 +777,13 @@ void riscv_translate_init(void)
  * unless you specifically block reads/writes to reg 0.
  */
 cpu_gpr[0] = NULL;
+cpu_gprh[0] = NULL;
 
 for (i = 1; i < 32; i++) {
 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
 offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
+cpu_gprh[i] = tcg_global_mem_new(cpu_env,
+offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
 }
 
 for (i = 0; i < 32; i++) {
-- 
2.34.0




[PATCH v6 07/18] target/riscv: setup everything for rv64 to support rv128 execution

2021-11-28 Thread Frédéric Pétrot
This patch adds the support of the '-cpu rv128' option to
qemu-system-riscv64 so that we can indicate that we want to run rv128
executables.
Still, there is no support for 128-bit insns at that stage so qemu fails
miserably (as expected) if launched with this option.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 include/disas/dis-asm.h |  1 +
 target/riscv/cpu.h  |  1 +
 disas/riscv.c   |  5 +
 target/riscv/cpu.c  | 20 
 target/riscv/gdbstub.c  |  5 +
 5 files changed, 32 insertions(+)

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..102a1e7f50 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
 int print_insn_xtensa   (bfd_vma, disassemble_info*);
 int print_insn_riscv32  (bfd_vma, disassemble_info*);
 int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_riscv128 (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
 
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 53a295efb7..cbd4daa6d9 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -38,6 +38,7 @@
 #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
 #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
 #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
+#define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("rv128")
 #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
 #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c")
 #define TYPE_RISCV_CPU_SIFIVE_E31   RISCV_CPU_TYPE_NAME("sifive-e31")
diff --git a/disas/riscv.c b/disas/riscv.c
index 793ad14c27..03c8dc9961 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -3090,3 +3090,8 @@ int print_insn_riscv64(bfd_vma memaddr, struct 
disassemble_info *info)
 {
 return print_insn_riscv(memaddr, info, rv64);
 }
+
+int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info)
+{
+return print_insn_riscv(memaddr, info, rv128);
+}
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 364140f5ff..7f5370f2b2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -178,6 +178,19 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_priv_version(env, PRIV_VERSION_1_10_0);
 qdev_prop_set_bit(DEVICE(obj), "mmu", false);
 }
+
+static void rv128_base_cpu_init(Object *obj)
+{
+if (qemu_tcg_mttcg_enabled()) {
+/* Missing 128-bit aligned atomics */
+error_report("128-bit RISC-V currently does not work with Multi "
+ "Threaded TCG. Please use: -accel tcg,thread=single");
+exit(EXIT_FAILURE);
+}
+CPURISCVState *env = _CPU(obj)->env;
+/* We set this in the realise function */
+set_misa(env, MXL_RV128, 0);
+}
 #else
 static void rv32_base_cpu_init(Object *obj)
 {
@@ -402,6 +415,9 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 case MXL_RV64:
 info->print_insn = print_insn_riscv64;
 break;
+case MXL_RV128:
+info->print_insn = print_insn_riscv128;
+break;
 default:
 g_assert_not_reached();
 }
@@ -464,6 +480,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 #ifdef TARGET_RISCV64
 case MXL_RV64:
 break;
+case MXL_RV128:
+break;
 #endif
 case MXL_RV32:
 break;
@@ -670,6 +688,7 @@ static gchar *riscv_gdb_arch_name(CPUState *cs)
 case MXL_RV32:
 return g_strdup("riscv:rv32");
 case MXL_RV64:
+case MXL_RV128:
 return g_strdup("riscv:rv64");
 default:
 g_assert_not_reached();
@@ -822,6 +841,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,   rv64_sifive_e_cpu_init),
 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,   rv64_sifive_u_cpu_init),
 DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init),
+DEFINE_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
 #endif
 };
 
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 23429179e2..2fbdcc5879 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -164,6 +164,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)
 int bitsize = 16 << env->misa_mxl_max;
 int i;
 
+/* Until gdb knows about 128-bit registers */
+if (bitsize > 64) {
+bitsize = 64;
+}
+
 g_string_printf(s, "");
 g_string_append_printf(s, "");
 g_string_append_printf(s, "");
-- 
2.34.0




[PATCH v6 05/18] target/riscv: separation of bitwise logic and arithmetic helpers

2021-11-28 Thread Frédéric Pétrot
Introduction of a gen_logic function for bitwise logic to implement
instructions in which no propagation of information occurs between bits and
use of this function on the bitwise instructions.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c| 27 +
 target/riscv/insn_trans/trans_rvb.c.inc |  6 +++---
 target/riscv/insn_trans/trans_rvi.c.inc | 12 +--
 3 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 2718ff15a1..9d102f21ee 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -400,6 +400,33 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm)
 /* Include the auto-generated decoder for 32 bit insn */
 #include "decode-insn32.c.inc"
 
+static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
+ void (*func)(TCGv, TCGv, target_long))
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+
+func(dest, src1, a->imm);
+
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
+static bool gen_logic(DisasContext *ctx, arg_r *a,
+  void (*func)(TCGv, TCGv, TCGv))
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+func(dest, src1, src2);
+
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
  void (*func)(TCGv, TCGv, target_long))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index c8d31907c5..de2cd613b1 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -86,19 +86,19 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
 static bool trans_andn(DisasContext *ctx, arg_andn *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl);
+return gen_logic(ctx, a, tcg_gen_andc_tl);
 }
 
 static bool trans_orn(DisasContext *ctx, arg_orn *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl);
+return gen_logic(ctx, a, tcg_gen_orc_tl);
 }
 
 static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl);
+return gen_logic(ctx, a, tcg_gen_eqv_tl);
 }
 
 static bool trans_min(DisasContext *ctx, arg_min *a)
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 4a2aefe3a5..51607b3d40 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -252,17 +252,17 @@ static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
 
 static bool trans_xori(DisasContext *ctx, arg_xori *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_xori_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_xori_tl);
 }
 
 static bool trans_ori(DisasContext *ctx, arg_ori *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_ori_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_ori_tl);
 }
 
 static bool trans_andi(DisasContext *ctx, arg_andi *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_andi_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_andi_tl);
 }
 
 static bool trans_slli(DisasContext *ctx, arg_slli *a)
@@ -319,7 +319,7 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 
 static bool trans_xor(DisasContext *ctx, arg_xor *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_xor_tl);
+return gen_logic(ctx, a, tcg_gen_xor_tl);
 }
 
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
@@ -334,12 +334,12 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_or_tl);
+return gen_logic(ctx, a, tcg_gen_or_tl);
 }
 
 static bool trans_and(DisasContext *ctx, arg_and *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_and_tl);
+return gen_logic(ctx, a, tcg_gen_and_tl);
 }
 
 static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
-- 
2.34.0




[PATCH v6 15/18] target/riscv: adding high part of some csrs

2021-11-28 Thread Frédéric Pétrot
Adding the high part of a very minimal set of csr.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h | 4 
 target/riscv/machine.c | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 603ae04837..a7c2e5c93e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -193,6 +193,10 @@ struct CPURISCVState {
 target_ulong hgatp;
 uint64_t htimedelta;
 
+/* Upper 64-bits of 128-bit CSRs */
+uint64_t mscratchh;
+uint64_t sscratchh;
+
 /* Virtual CSRs */
 /*
  * For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 8af9caabf5..13b9ab375b 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -179,6 +179,8 @@ static const VMStateDescription vmstate_rv128 = {
 .needed = rv128_needed,
 .fields = (VMStateField[]) {
 VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_UINT64(env.mscratchh, RISCVCPU),
+VMSTATE_UINT64(env.sscratchh, RISCVCPU),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
2.34.0




[PATCH v6 09/18] target/riscv: accessors to registers upper part and 128-bit load/store

2021-11-28 Thread Frédéric Pétrot
Get function to retrieve the 64 top bits of a register, stored in the gprh
field of the cpu state. Set function that writes the 128-bit value at once.
The access to the gprh field can not be protected at compile time to make
sure it is accessed only in the 128-bit version of the processor because we
have no way to indicate that the misa_mxl_max field is const.

The 128-bit ISA adds ldu, lq and sq. We provide support for these
instructions. Note that (a) we compute only 64-bit addresses to actually
access memory, cowardly utilizing the existing address translation mechanism
of QEMU, and (b) we assume for now little-endian memory accesses.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/insn16.decode  |  27 ++-
 target/riscv/insn32.decode  |   5 ++
 target/riscv/translate.c|  41 ++
 target/riscv/insn_trans/trans_rvi.c.inc | 100 ++--
 4 files changed, 163 insertions(+), 10 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 2e9212663c..02c8f61b48 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -25,14 +25,17 @@
 # Immediates:
 %imm_ci12:s1 2:5
 %nzuimm_ciw7:4 11:2 5:1 6:1   !function=ex_shift_2
+%uimm_cl_q 10:1 5:2 11:2  !function=ex_shift_4
 %uimm_cl_d 5:2 10:3   !function=ex_shift_3
 %uimm_cl_w 5:1 10:3 6:1   !function=ex_shift_2
 %imm_cb12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
 %imm_cj12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
 
 %shimm_6bit   12:1 2:5   !function=ex_rvc_shifti
+%uimm_6bit_lq 2:4 12:1 6:1   !function=ex_shift_4
 %uimm_6bit_ld 2:3 12:1 5:2   !function=ex_shift_3
 %uimm_6bit_lw 2:2 12:1 4:3   !function=ex_shift_2
+%uimm_6bit_sq 7:4 11:2   !function=ex_shift_4
 %uimm_6bit_sd 7:3 10:3   !function=ex_shift_3
 %uimm_6bit_sw 7:2 9:4!function=ex_shift_2
 
@@ -54,16 +57,20 @@
 # Formats 16:
 @cr  . .  ..   rs2=%rs2_5   rs1=%rd %rd
 @ci... . . .  ..   imm=%imm_ci  rs1=%rd %rd
+@cl_q  ... . .  . ..   imm=%uimm_cl_q   rs1=%rs1_3  rd=%rs2_3
 @cl_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  rd=%rs2_3
 @cl_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  rd=%rs2_3
 @cs_2  ... ... ... .. ... ..   rs2=%rs2_3   rs1=%rs1_3  rd=%rs1_3
+@cs_q  ... ... ... .. ... ..   imm=%uimm_cl_q   rs1=%rs1_3  
rs2=%rs2_3
 @cs_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  
rs2=%rs2_3
 @cs_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  
rs2=%rs2_3
 @cj...... ..   imm=%imm_cj
 @cb_z  ... ... ... .. ... ..   imm=%imm_cb  rs1=%rs1_3  rs2=0
 
+@c_lqsp... . .  . ..   imm=%uimm_6bit_lq rs1=2 %rd
 @c_ldsp... . .  . ..   imm=%uimm_6bit_ld rs1=2 %rd
 @c_lwsp... . .  . ..   imm=%uimm_6bit_lw rs1=2 %rd
+@c_sqsp... . .  . ..   imm=%uimm_6bit_sq rs1=2 rs2=%rs2_5
 @c_sdsp... . .  . ..   imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5
 @c_swsp... . .  . ..   imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5
 @c_li  ... . .  . ..   imm=%imm_ci rs1=0 %rd
@@ -87,9 +94,15 @@
   illegal 000  000 000 00 --- 00
   addi000  ... ... .. ... 00 @c_addi4spn
 }
-fld   001  ... ... .. ... 00 @cl_d
+{
+  lq  001  ... ... .. ... 00 @cl_q
+  fld 001  ... ... .. ... 00 @cl_d
+}
 lw010  ... ... .. ... 00 @cl_w
-fsd   101  ... ... .. ... 00 @cs_d
+{
+  sq  101  ... ... .. ... 00 @cs_q
+  fsd 101  ... ... .. ... 00 @cs_d
+}
 sw110  ... ... .. ... 00 @cs_w
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 0) ***
@@ -132,7 +145,10 @@ addw  100 1 11 ... 01 ... 01 @cs_2
 
 # *** RV32/64C Standard Extension (Quadrant 2) ***
 slli  000 .  .  . 10 @c_shift2
-fld   001 .  .  . 10 @c_ldsp
+{
+  lq  001  ... ... .. ... 10 @c_lqsp
+  fld 001 .  .  . 10 @c_ldsp
+}
 {
   illegal 010 -  0  - 10 # c.lwsp, RES rd=0
   lw  010 .  .  . 10 @c_lwsp
@@ -147,7 +163,10 @@ fld   001 .  .  . 10 @c_ldsp
   jalr100 1  .  0 10 @c_jalr rd=1  # C.JALR
   add 100 1  .  . 10 @cr
 }
-fsd   101   ..  . 10 @c_sdsp
+{
+  sq  101  ... ... .. ... 10 @c_sqsp
+  fsd 101   ..  . 10 @c_sdsp
+}
 sw110 .  .  . 10 @c_swsp
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 2) ***
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 2f251dac1b..02889c6082 100644
--- a/target/riscv/insn32.decode

[PATCH v6 08/18] target/riscv: moving some insns close to similar insns

2021-11-28 Thread Frédéric Pétrot
lwu and ld are functionally close to the other loads, but were after the
stores in the source file.
Similarly, xor was away from or and and by two arithmetic functions, while
the immediate versions were nicely put together.
This patch moves the aforementioned loads after lhu, and xor above or,
where they more logically belong.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 34 -
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 51607b3d40..710f5e6a85 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -176,6 +176,18 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
 return gen_load(ctx, a, MO_TEUW);
 }
 
+static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUL);
+}
+
+static bool trans_ld(DisasContext *ctx, arg_ld *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUQ);
+}
+
 static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
 {
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@@ -207,18 +219,6 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a)
 return gen_store(ctx, a, MO_TESL);
 }
 
-static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUL);
-}
-
-static bool trans_ld(DisasContext *ctx, arg_ld *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUQ);
-}
-
 static bool trans_sd(DisasContext *ctx, arg_sd *a)
 {
 REQUIRE_64BIT(ctx);
@@ -317,11 +317,6 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 return gen_arith(ctx, a, EXT_SIGN, gen_sltu);
 }
 
-static bool trans_xor(DisasContext *ctx, arg_xor *a)
-{
-return gen_logic(ctx, a, tcg_gen_xor_tl);
-}
-
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
 {
 return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
@@ -332,6 +327,11 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
 }
 
+static bool trans_xor(DisasContext *ctx, arg_xor *a)
+{
+return gen_logic(ctx, a, tcg_gen_xor_tl);
+}
+
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
 return gen_logic(ctx, a, tcg_gen_or_tl);
-- 
2.34.0




[PATCH v6 03/18] qemu/int128: addition of div/rem 128-bit operations

2021-11-28 Thread Frédéric Pétrot
Addition of div and rem on 128-bit integers, using the 128/64->128 divu and
64x64->128 mulu in host-utils.
These operations will be used within div/rem helpers in the 128-bit riscv
target.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
---
 include/qemu/int128.h |   6 ++
 util/int128.c | 145 ++
 util/meson.build  |   1 +
 3 files changed, 152 insertions(+)
 create mode 100644 util/int128.c

diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index b6d517aea4..ef41892dac 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -386,4 +386,10 @@ static inline void bswap128s(Int128 *s)
 *s = bswap128(*s);
 }
 
+#define UINT128_MAX int128_make128(~0LL, ~0LL)
+Int128 int128_divu(Int128, Int128);
+Int128 int128_remu(Int128, Int128);
+Int128 int128_divs(Int128, Int128);
+Int128 int128_rems(Int128, Int128);
+
 #endif /* INT128_H */
diff --git a/util/int128.c b/util/int128.c
new file mode 100644
index 00..62c56c8b7c
--- /dev/null
+++ b/util/int128.c
@@ -0,0 +1,145 @@
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "qemu/int128.h"
+
+#ifdef CONFIG_INT128
+
+Int128 int128_divu(Int128 a, Int128 b)
+{
+return (__uint128_t)a / (__uint128_t)b;
+}
+
+Int128 int128_remu(Int128 a, Int128 b)
+{
+return (__uint128_t)a % (__uint128_t)b;
+}
+
+Int128 int128_divs(Int128 a, Int128 b)
+{
+return a / b;
+}
+
+Int128 int128_rems(Int128 a, Int128 b)
+{
+return a % b;
+}
+
+#else
+
+/*
+ * Division and remainder algorithms for 128-bit due to Stefan Kanthak,
+ * https://skanthak.homepage.t-online.de/integer.html#udivmodti4
+ * Preconditions:
+ * - function should never be called with v equals to 0, it has to
+ *   be dealt with beforehand
+ * - quotien pointer must be valid
+ */
+static Int128 divrem128(Int128 u, Int128 v, Int128 *q)
+{
+Int128 qq;
+uint64_t hi, lo, tmp;
+int s = clz64(v.hi);
+
+if (s == 64) {
+/* we have uu÷0v => let's use divu128 */
+hi = u.hi;
+lo = u.lo;
+tmp = divu128(, , v.lo);
+*q = int128_make128(lo, hi);
+return int128_make128(tmp, 0);
+} else {
+hi = int128_gethi(int128_lshift(v, s));
+
+if (hi > u.hi) {
+lo = u.lo;
+tmp = u.hi;
+divu128(, , hi);
+lo = int128_gethi(int128_lshift(int128_make128(lo, 0), s));
+} else { /* prevent overflow */
+lo = u.lo;
+tmp = u.hi - hi;
+divu128(, , hi);
+lo = int128_gethi(int128_lshift(int128_make128(lo, 1), s));
+}
+
+qq = int128_make64(lo);
+
+tmp = lo * v.hi;
+mulu64(, , lo, v.lo);
+hi += tmp;
+
+if (hi < tmp /* quotient * divisor >= 2**128 > dividend */
+|| hi > u.hi /* quotient * divisor > dividend */
+|| (hi == u.hi && lo > u.lo)) {
+qq.lo -= 1;
+mulu64(, , qq.lo, v.lo);
+hi += qq.lo * v.hi;
+}
+
+*q = qq;
+u.hi -= hi + (u.lo < lo);
+u.lo -= lo;
+return u;
+}
+}
+
+Int128 int128_divu(Int128 a, Int128 b)
+{
+Int128 q;
+divrem128(a, b, );
+return q;
+}
+
+Int128 int128_remu(Int128 a, Int128 b)
+{
+Int128 q;
+return divrem128(a, b, );
+}
+
+Int128 int128_divs(Int128 a, Int128 b)
+{
+Int128 q;
+bool sgna = !int128_nonneg(a);
+bool sgnb = !int128_nonneg(b);
+
+if (sgna) {
+a = int128_neg(a);
+}
+
+if (sgnb) {
+b = int128_neg(b);
+}
+
+divrem128(a, b, );
+
+if (sgna != sgnb) {
+q = int128_neg(q);
+}
+
+return q;
+}
+
+Int128 int128_rems(Int128 a, Int128 b)
+{
+Int128 q, r;
+bool sgna = !int128_nonneg(a);
+bool sgnb = !int128_nonneg(b);
+
+if (sgna) {
+a = int128_neg(a);
+}
+
+if (sgnb) {
+b = int128_neg(b);
+}
+
+r = divrem128(a, b, );
+
+if (sgna) {
+r = int128_neg(r);
+}
+
+return r;
+}
+
+#endif
diff --git a/util/meson.build b/util/meson.build
index 05b593055a..e676b2f6c6 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -48,6 +48,7 @@ util_ss.add(files('transactions.c'))
 util_ss.add(when: 'CONFIG_POSIX', if_true: files('drm.c'))
 util_ss.add(files('guest-random.c'))
 util_ss.add(files('yank.c'))
+util_ss.add(files('int128.c'))
 
 if have_user
   util_ss.add(files('selfmap.c'))
-- 
2.34.0




[PATCH v6 01/18] exec/memop: Adding signedness to quad definitions

2021-11-28 Thread Frédéric Pétrot
Renaming defines for quad in their various forms so that their signedness is
now explicit.
Done using git grep as suggested by Philippe, with a bit of hand edition to
keep assignments aligned.

Signed-off-by: Frédéric Pétrot 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
---
 include/exec/memop.h   |  8 +--
 include/tcg/tcg-op.h   |  4 +-
 target/arm/translate-a32.h |  4 +-
 accel/tcg/cputlb.c | 30 +--
 accel/tcg/user-exec.c  |  8 +--
 target/alpha/translate.c   | 32 ++--
 target/arm/helper-a64.c|  8 +--
 target/arm/translate-a64.c |  8 +--
 target/arm/translate-neon.c|  6 +--
 target/arm/translate-sve.c | 10 ++--
 target/arm/translate-vfp.c |  8 +--
 target/arm/translate.c |  2 +-
 target/cris/translate.c|  2 +-
 target/hppa/translate.c|  4 +-
 target/i386/tcg/mem_helper.c   |  2 +-
 target/i386/tcg/translate.c| 36 +++---
 target/m68k/op_helper.c|  2 +-
 target/mips/tcg/translate.c| 58 +++---
 target/mips/tcg/tx79_translate.c   |  8 +--
 target/ppc/translate.c | 32 ++--
 target/s390x/tcg/mem_helper.c  |  8 +--
 target/s390x/tcg/translate.c   |  8 +--
 target/sh4/translate.c | 12 ++---
 target/sparc/translate.c   | 36 +++---
 target/tricore/translate.c |  4 +-
 target/xtensa/translate.c  |  4 +-
 tcg/tcg.c  |  4 +-
 tcg/tci.c  | 16 +++---
 accel/tcg/ldst_common.c.inc|  8 +--
 target/mips/tcg/micromips_translate.c.inc  | 10 ++--
 target/ppc/translate/fixedpoint-impl.c.inc | 22 
 target/ppc/translate/fp-impl.c.inc |  4 +-
 target/ppc/translate/vsx-impl.c.inc| 42 
 target/riscv/insn_trans/trans_rva.c.inc| 22 
 target/riscv/insn_trans/trans_rvd.c.inc|  4 +-
 target/riscv/insn_trans/trans_rvh.c.inc|  4 +-
 target/riscv/insn_trans/trans_rvi.c.inc|  4 +-
 target/s390x/tcg/translate_vx.c.inc| 18 +++
 tcg/aarch64/tcg-target.c.inc   |  2 +-
 tcg/arm/tcg-target.c.inc   | 10 ++--
 tcg/i386/tcg-target.c.inc  | 12 ++---
 tcg/mips/tcg-target.c.inc  | 12 ++---
 tcg/ppc/tcg-target.c.inc   | 16 +++---
 tcg/riscv/tcg-target.c.inc |  6 +--
 tcg/s390x/tcg-target.c.inc | 18 +++
 tcg/sparc/tcg-target.c.inc | 16 +++---
 target/s390x/tcg/insn-data.def | 28 +--
 47 files changed, 311 insertions(+), 311 deletions(-)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 04264ffd6b..72c2f0ff3d 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -85,29 +85,29 @@ typedef enum MemOp {
 MO_UB= MO_8,
 MO_UW= MO_16,
 MO_UL= MO_32,
+MO_UQ= MO_64,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
-MO_Q = MO_64,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
+MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
-MO_LEQ   = MO_LE | MO_Q,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
+MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
-MO_BEQ   = MO_BE | MO_Q,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
+MO_TEUQ  = MO_TE | MO_UQ,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
-MO_TEQ   = MO_TE | MO_Q,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index 0545a6224c..caa0a63612 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -894,7 +894,7 @@ static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, 
int mem_index)
 
 static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
 {
-tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEQ);
+tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEUQ);
 }
 
 static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
@@ -914,7 +914,7 @@ static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, 
int mem_index)
 
 static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
 {
-tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEQ);
+tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEUQ);
 }
 
 void tcg_gen_atomic_cmpxchg_i32(TCGv_i32, TCGv, TCGv_i32, TCGv_i32,
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
index 17af8dc95a..5be4b9b834 100644
--- a/target/arm/translate-a32.h

[PATCH v6 02/18] exec/memop: Adding signed quad and octo defines

2021-11-28 Thread Frédéric Pétrot
Adding defines to handle signed 64-bit and unsigned 128-bit quantities in
memory accesses.

Signed-off-by: Frédéric Pétrot 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 include/exec/memop.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 72c2f0ff3d..2a885f3917 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -86,28 +86,35 @@ typedef enum MemOp {
 MO_UW= MO_16,
 MO_UL= MO_32,
 MO_UQ= MO_64,
+MO_UO= MO_128,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
+MO_SQ= MO_SIGN | MO_64,
+MO_SO= MO_SIGN | MO_128,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
 MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
+MO_LESQ  = MO_LE | MO_SQ,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
 MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
+MO_BESQ  = MO_BE | MO_SQ,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
 MO_TEUQ  = MO_TE | MO_UQ,
+MO_TEUO  = MO_TE | MO_UO,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
+MO_TESQ  = MO_TE | MO_SQ,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
-- 
2.34.0




Re: [PATCH v5 07/18] target/riscv: setup everything so that riscv128-softmmu compiles

2021-11-25 Thread Frédéric Pétrot

On 25/11/2021 12:47, Alistair Francis wrote:

On Wed, Nov 24, 2021 at 5:33 PM Philippe Mathieu-Daudé  wrote:


Hi Frédéric,

On 11/24/21 07:55, Frédéric Pétrot wrote:

On 24/11/2021 07:12, Alistair Francis wrote:

On Sat, Nov 13, 2021 at 1:16 AM Frédéric Pétrot
 wrote:


This patch is kind of a mess because several files have to be slightly
modified to allow for a new target. In the current status, we have done
our best to have RV64 and RV128 under the same RV64 umbrella, but there
is still work to do to have a single executable for both.
In particular, we have no atomic accesses for aligned 128-bit addresses.

Once this patch applied, adding risc128-sofmmu to --target-list produces
a (no so useful yet) executable.


I can't remember if we discussed this before, but do we need the
riscv128-sofmmu executable? Can we instead just use a riscv64-sofmmu
executable?


   Hello Alistair,
   Richard was also advocating for a single executable, but pointed out that
   we need to disable mttcg because there is a need for specific tcg
support for
   128-bit aligned atomics.
   Given my understanding of that part of QEMU, I choose the easy way to
disable
   it once and for all at compile time until we have that.



In rv128_base_cpu_init():

   if (qemu_tcg_mttcg_enabled) {
   /* Missing 128-bit aligned atomics */
   error_report("128-bit RISC-V currently does not work"
" with Multi Threaded TCG. Please use:"
" -accel tcg,thread=single");
   exit(EXIT_FAILURE);
   }


That seems like a good option! I think we could add this to the CPU
realise function.

The problem with a riscv128-sofmmu executable is that it's hard to get
rid of in the future. We are very slowly moving towards a single
executable and adding a new one means we are stuck with it for a
while.

Alistair


  Ooups, I replied yesterday to Philippe that I would work that out, but I
  missed the reply all button, sorry.

  Frédéric




Regards,

Phil.


--
+-------+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



Re: [PATCH v5 07/18] target/riscv: setup everything so that riscv128-softmmu compiles

2021-11-23 Thread Frédéric Pétrot

On 24/11/2021 07:12, Alistair Francis wrote:

On Sat, Nov 13, 2021 at 1:16 AM Frédéric Pétrot
 wrote:


This patch is kind of a mess because several files have to be slightly
modified to allow for a new target. In the current status, we have done
our best to have RV64 and RV128 under the same RV64 umbrella, but there
is still work to do to have a single executable for both.
In particular, we have no atomic accesses for aligned 128-bit addresses.

Once this patch applied, adding risc128-sofmmu to --target-list produces
a (no so useful yet) executable.


I can't remember if we discussed this before, but do we need the
riscv128-sofmmu executable? Can we instead just use a riscv64-sofmmu
executable?


  Hello Alistair,
  Richard was also advocating for a single executable, but pointed out that
  we need to disable mttcg because there is a need for specific tcg support for
  128-bit aligned atomics.
  Given my understanding of that part of QEMU, I choose the easy way to disable
  it once and for all at compile time until we have that.

  Frédéric



Alistair



Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
  configs/devices/riscv128-softmmu/default.mak | 17 +++
  configs/targets/riscv128-softmmu.mak |  6 ++
  include/disas/dis-asm.h  |  1 +
  include/hw/riscv/sifive_cpu.h|  3 +++
  target/riscv/cpu-param.h |  5 +
  target/riscv/cpu.h   |  3 +++
  disas/riscv.c|  5 +
  target/riscv/cpu.c   | 22 ++--
  target/riscv/gdbstub.c   |  8 +++
  target/riscv/insn_trans/trans_rvd.c.inc  | 12 +--
  target/riscv/insn_trans/trans_rvf.c.inc  |  6 +++---
  target/riscv/Kconfig |  3 +++
  12 files changed, 80 insertions(+), 11 deletions(-)
  create mode 100644 configs/devices/riscv128-softmmu/default.mak
  create mode 100644 configs/targets/riscv128-softmmu.mak

diff --git a/configs/devices/riscv128-softmmu/default.mak 
b/configs/devices/riscv128-softmmu/default.mak
new file mode 100644
index 00..e838f35785
--- /dev/null
+++ b/configs/devices/riscv128-softmmu/default.mak
@@ -0,0 +1,17 @@
+# Default configuration for riscv128-softmmu
+
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_PCI_DEVICES=n
+# No does not seem to be an option for these two parameters
+CONFIG_SEMIHOSTING=y
+CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
+
+# Boards:
+#
+CONFIG_SPIKE=n
+CONFIG_SIFIVE_E=n
+CONFIG_SIFIVE_U=n
+CONFIG_RISCV_VIRT=y
+CONFIG_MICROCHIP_PFSOC=n
+CONFIG_SHAKTI_C=n
diff --git a/configs/targets/riscv128-softmmu.mak 
b/configs/targets/riscv128-softmmu.mak
new file mode 100644
index 00..d812cc1c80
--- /dev/null
+++ b/configs/targets/riscv128-softmmu.mak
@@ -0,0 +1,6 @@
+TARGET_ARCH=riscv128
+TARGET_BASE_ARCH=riscv
+# As long as we have no atomic accesses for aligned 128-bit addresses
+TARGET_SUPPORTS_MTTCG=n
+TARGET_XML_FILES=gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+TARGET_NEED_FDT=y
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..102a1e7f50 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
  int print_insn_xtensa   (bfd_vma, disassemble_info*);
  int print_insn_riscv32  (bfd_vma, disassemble_info*);
  int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_riscv128 (bfd_vma, disassemble_info*);
  int print_insn_rx(bfd_vma, disassemble_info *);
  int print_insn_hexagon(bfd_vma, disassemble_info *);

diff --git a/include/hw/riscv/sifive_cpu.h b/include/hw/riscv/sifive_cpu.h
index 136799633a..64078feba8 100644
--- a/include/hw/riscv/sifive_cpu.h
+++ b/include/hw/riscv/sifive_cpu.h
@@ -26,6 +26,9 @@
  #elif defined(TARGET_RISCV64)
  #define SIFIVE_E_CPU TYPE_RISCV_CPU_SIFIVE_E51
  #define SIFIVE_U_CPU TYPE_RISCV_CPU_SIFIVE_U54
+#else
+#define SIFIVE_E_CPU TYPE_RISCV_CPU_SIFIVE_E51
+#define SIFIVE_U_CPU TYPE_RISCV_CPU_SIFIVE_U54
  #endif

  #endif /* HW_SIFIVE_CPU_H */
diff --git a/target/riscv/cpu-param.h b/target/riscv/cpu-param.h
index 80eb615f93..c10459b56f 100644
--- a/target/riscv/cpu-param.h
+++ b/target/riscv/cpu-param.h
@@ -16,6 +16,11 @@
  # define TARGET_LONG_BITS 32
  # define TARGET_PHYS_ADDR_SPACE_BITS 34 /* 22-bit PPN */
  # define TARGET_VIRT_ADDR_SPACE_BITS 32 /* sv32 */
+#else
+/* 64-bit target, since QEMU isn't built to have TARGET_LONG_BITS over 64 */
+# define TARGET_LONG_BITS 64
+# define TARGET_PHYS_ADDR_SPACE_BITS 56 /* 44-bit PPN */
+# define TARGET_VIRT_ADDR_SPACE_BITS 48 /* sv48 */
  #endif
  #define TARGET_PAGE_BITS 12 /* 4 KiB Pages */
  /*
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 53a295efb7..8ff5b08d15 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv

Re: [PATCH v5 06/18] target/riscv: array for the 64 upper bits of 128-bit registers

2021-11-23 Thread Frédéric Pétrot

On 23/11/2021 07:09, Alistair Francis wrote:

On Sat, Nov 13, 2021 at 1:07 AM Frédéric Pétrot
 wrote:

+static bool rv128_needed(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+CPURISCVState *env = >env;
+
+return env->misa_mxl_max == MXL_RV128;
+}


I think it would just be better to use riscv_cpu_mxl() directly
instead of adding a new function here.


  Ok, thanks.
  I was doing that because as Zhiwei is progressing on the dynamic handling
  of xlen, in the end the "current" mxl could be different from mxl_max, and
  some state to be saved might live in the registers upper 64-bit.
  But you are quite right that we are not there yet, so I'll do that.

  Frédéric
--
+-------+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



Re: [PATCH v5 09/18] target/riscv: accessors to registers upper part and 128-bit load/store

2021-11-16 Thread Frédéric Pétrot

On 15/11/2021 09:29, Richard Henderson wrote:

On 11/12/21 3:58 PM, Frédéric Pétrot wrote:

+    tcg_gen_qemu_ld_tl(memop & MO_BSWAP ? desth : destl, addrl,
+   ctx->mem_idx, MO_TEUQ);


This isn't correct.  MO_BSWAP is related to the host, not the guest.


  Argh! Thx for pointing out my misunderstanding.

You want

 (memop & MO_BSWAP) == MO_LE ? destl : desth

Are there any big-endian RISC-V though?


  Not that I know of, but the spec defines it since V2.0 (bitfields MBE/SBE/UBE
  in mstatus), gcc supports it, and there is a check for it in get_dump_info
  for the riscv, so I opted for adding that (wrong) line.
  Since we can expect in the future endianness to be dynamic, you are probably
  right that we should assume litte-endian accesses for now, as handling both
  will anyway require many other changes.

  Frédéric
--
+---+
| Frédéric Pétrot, Pr. Grenoble INP-Ensimag/TIMA,   Ensimag deputy director |
| Mob/Pho: +33 6 74 57 99 65/+33 4 76 57 48 70  Ad augusta  per angusta |
| http://tima.univ-grenoble-alpes.fr frederic.pet...@univ-grenoble-alpes.fr |
+---+



[PATCH v5 10/18] target/riscv: support for 128-bit bitwise instructions

2021-11-12 Thread Frédéric Pétrot
The 128-bit bitwise instructions do not need any function prototype change
as the functions can be applied independently on the lower and upper part of
the registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/translate.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 554cf05084..508ae87985 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -448,7 +448,15 @@ static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
 
 func(dest, src1, a->imm);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, -(a->imm < 0));
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
@@ -462,7 +470,16 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 
 func(dest, src1, src2);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
-- 
2.33.1




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

2021-11-12 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 | 183 ++--
 target/riscv/meson.build|   1 +
 6 files changed, 296 insertions(+), 13 deletions(-)
 create mode 100644 target/riscv/m128_helper.c

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 8ff5b08d15..ae1f9cb876 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -143,6 +143,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 <http://www.gnu.org/licenses/>.
+ */
+
+#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

[PATCH v5 15/18] target/riscv: adding high part of some csrs

2021-11-12 Thread Frédéric Pétrot
Adding the high part of a very minimal set of csr.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.h | 4 
 target/riscv/machine.c | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index ae1f9cb876..15609a5533 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -195,6 +195,10 @@ struct CPURISCVState {
 target_ulong hgatp;
 uint64_t htimedelta;
 
+/* Upper 64-bits of 128-bit CSRs */
+uint64_t mscratchh;
+uint64_t sscratchh;
+
 /* Virtual CSRs */
 /*
  * For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 7e2d02457e..6f0eabf66a 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -179,6 +179,8 @@ static const VMStateDescription vmstate_rv128 = {
 .needed = rv128_needed,
 .fields = (VMStateField[]) {
 VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_UINT64(env.mscratchh, RISCVCPU),
+VMSTATE_UINT64(env.sscratchh, RISCVCPU),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
2.33.1




[PATCH v5 08/18] target/riscv: moving some insns close to similar insns

2021-11-12 Thread Frédéric Pétrot
lwu and ld are functionally close to the other loads, but were after the
stores in the source file.
Similarly, xor was away from or and and by two arithmetic functions, while
the immediate versions were nicely put together.
This patch moves the aforementioned loads after lhu, and xor above or,
where they more logically belong.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 34 -
 meson   |  2 +-
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 51607b3d40..710f5e6a85 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -176,6 +176,18 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
 return gen_load(ctx, a, MO_TEUW);
 }
 
+static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUL);
+}
+
+static bool trans_ld(DisasContext *ctx, arg_ld *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUQ);
+}
+
 static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
 {
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@@ -207,18 +219,6 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a)
 return gen_store(ctx, a, MO_TESL);
 }
 
-static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUL);
-}
-
-static bool trans_ld(DisasContext *ctx, arg_ld *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUQ);
-}
-
 static bool trans_sd(DisasContext *ctx, arg_sd *a)
 {
 REQUIRE_64BIT(ctx);
@@ -317,11 +317,6 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 return gen_arith(ctx, a, EXT_SIGN, gen_sltu);
 }
 
-static bool trans_xor(DisasContext *ctx, arg_xor *a)
-{
-return gen_logic(ctx, a, tcg_gen_xor_tl);
-}
-
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
 {
 return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
@@ -332,6 +327,11 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
 }
 
+static bool trans_xor(DisasContext *ctx, arg_xor *a)
+{
+return gen_logic(ctx, a, tcg_gen_xor_tl);
+}
+
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
 return gen_logic(ctx, a, tcg_gen_or_tl);
diff --git a/meson b/meson
index 12f9f04ba0..b25d94e7c7 16
--- a/meson
+++ b/meson
@@ -1 +1 @@
-Subproject commit 12f9f04ba0decfda425dbbf9a501084c153a2d18
+Subproject commit b25d94e7c77fda05a7fdfe8afe562cf9760d69da
-- 
2.33.1




[PATCH v5 16/18] target/riscv: helper functions to wrap calls to 128-bit csr insns

2021-11-12 Thread Frédéric Pétrot
Given the side effects they have, the csr instructions are realized as
helpers. We extend this existing infrastructure for 128-bit sized csr.
We return 128-bit values using the same approach as for div/rem.
Theses helpers all call a unique function that is currently a fallback
on the 64-bit version.
The trans_csrxx functions supporting 128-bit are yet to be implemented.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.h   |  4 
 target/riscv/helper.h|  3 +++
 target/riscv/csr.c   | 17 
 target/riscv/op_helper.c | 44 
 4 files changed, 68 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 15609a5533..6828c136ad 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -483,6 +483,10 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
*env, int csrno,
   target_ulong new_value,
   target_ulong write_mask);
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+Int128 *ret_value,
+Int128 new_value, Int128 write_mask);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index c036825723..bf2b338bfd 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -66,6 +66,9 @@ DEF_HELPER_FLAGS_2(clmulr, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_2(csrr, tl, env, int)
 DEF_HELPER_3(csrw, void, env, int, tl)
 DEF_HELPER_4(csrrw, tl, env, int, tl, tl)
+DEF_HELPER_2(csrr_i128, tl, env, int)
+DEF_HELPER_4(csrw_i128, void, env, int, tl, tl)
+DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_2(sret, tl, env, tl)
 DEF_HELPER_2(mret, tl, env, tl)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 9f41954894..dca9e19a64 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1788,6 +1788,23 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
 return RISCV_EXCP_NONE;
 }
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+   Int128 *ret_value,
+   Int128 new_value, Int128 write_mask)
+{
+/* fall back to 64-bit version for now */
+target_ulong ret_64;
+RISCVException ret = riscv_csrrw(env, csrno, _64,
+ int128_getlo(new_value),
+ int128_getlo(write_mask));
+
+if (ret_value) {
+*ret_value = int128_make64(ret_64);
+}
+
+return ret;
+}
+
 /*
  * Debugger support.  If not in user mode, set env->debugger before the
  * riscv_csrrw call and clear it after the call.
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index ee7c24efe7..f4cf9c4698 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -69,6 +69,50 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
 return val;
 }
 
+target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_zero(),
+  int128_zero());
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
+void helper_csrw_i128(CPURISCVState *env, int csr,
+  target_ulong srcl, target_ulong srch)
+{
+RISCVException ret = riscv_csrrw_i128(env, csr, NULL,
+  int128_make128(srcl, srch),
+  UINT128_MAX);
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+}
+
+target_ulong helper_csrrw_i128(CPURISCVState *env, int csr,
+   target_ulong srcl, target_ulong srch,
+   target_ulong maskl, target_ulong maskh)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_make128(srcl, srch),
+  int128_make128(maskl, maskh));
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
 #ifndef CONFIG_USER_ONLY
 
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
-- 
2.33.1




[PATCH v5 07/18] target/riscv: setup everything so that riscv128-softmmu compiles

2021-11-12 Thread Frédéric Pétrot
This patch is kind of a mess because several files have to be slightly
modified to allow for a new target. In the current status, we have done
our best to have RV64 and RV128 under the same RV64 umbrella, but there
is still work to do to have a single executable for both.
In particular, we have no atomic accesses for aligned 128-bit addresses.

Once this patch applied, adding risc128-sofmmu to --target-list produces
a (no so useful yet) executable.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 configs/devices/riscv128-softmmu/default.mak | 17 +++
 configs/targets/riscv128-softmmu.mak |  6 ++
 include/disas/dis-asm.h  |  1 +
 include/hw/riscv/sifive_cpu.h|  3 +++
 target/riscv/cpu-param.h |  5 +
 target/riscv/cpu.h   |  3 +++
 disas/riscv.c|  5 +
 target/riscv/cpu.c   | 22 ++--
 target/riscv/gdbstub.c   |  8 +++
 target/riscv/insn_trans/trans_rvd.c.inc  | 12 +--
 target/riscv/insn_trans/trans_rvf.c.inc  |  6 +++---
 target/riscv/Kconfig |  3 +++
 12 files changed, 80 insertions(+), 11 deletions(-)
 create mode 100644 configs/devices/riscv128-softmmu/default.mak
 create mode 100644 configs/targets/riscv128-softmmu.mak

diff --git a/configs/devices/riscv128-softmmu/default.mak 
b/configs/devices/riscv128-softmmu/default.mak
new file mode 100644
index 00..e838f35785
--- /dev/null
+++ b/configs/devices/riscv128-softmmu/default.mak
@@ -0,0 +1,17 @@
+# Default configuration for riscv128-softmmu
+
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_PCI_DEVICES=n
+# No does not seem to be an option for these two parameters
+CONFIG_SEMIHOSTING=y
+CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
+
+# Boards:
+#
+CONFIG_SPIKE=n
+CONFIG_SIFIVE_E=n
+CONFIG_SIFIVE_U=n
+CONFIG_RISCV_VIRT=y
+CONFIG_MICROCHIP_PFSOC=n
+CONFIG_SHAKTI_C=n
diff --git a/configs/targets/riscv128-softmmu.mak 
b/configs/targets/riscv128-softmmu.mak
new file mode 100644
index 00..d812cc1c80
--- /dev/null
+++ b/configs/targets/riscv128-softmmu.mak
@@ -0,0 +1,6 @@
+TARGET_ARCH=riscv128
+TARGET_BASE_ARCH=riscv
+# As long as we have no atomic accesses for aligned 128-bit addresses
+TARGET_SUPPORTS_MTTCG=n
+TARGET_XML_FILES=gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+TARGET_NEED_FDT=y
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..102a1e7f50 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
 int print_insn_xtensa   (bfd_vma, disassemble_info*);
 int print_insn_riscv32  (bfd_vma, disassemble_info*);
 int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_riscv128 (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
 
diff --git a/include/hw/riscv/sifive_cpu.h b/include/hw/riscv/sifive_cpu.h
index 136799633a..64078feba8 100644
--- a/include/hw/riscv/sifive_cpu.h
+++ b/include/hw/riscv/sifive_cpu.h
@@ -26,6 +26,9 @@
 #elif defined(TARGET_RISCV64)
 #define SIFIVE_E_CPU TYPE_RISCV_CPU_SIFIVE_E51
 #define SIFIVE_U_CPU TYPE_RISCV_CPU_SIFIVE_U54
+#else
+#define SIFIVE_E_CPU TYPE_RISCV_CPU_SIFIVE_E51
+#define SIFIVE_U_CPU TYPE_RISCV_CPU_SIFIVE_U54
 #endif
 
 #endif /* HW_SIFIVE_CPU_H */
diff --git a/target/riscv/cpu-param.h b/target/riscv/cpu-param.h
index 80eb615f93..c10459b56f 100644
--- a/target/riscv/cpu-param.h
+++ b/target/riscv/cpu-param.h
@@ -16,6 +16,11 @@
 # define TARGET_LONG_BITS 32
 # define TARGET_PHYS_ADDR_SPACE_BITS 34 /* 22-bit PPN */
 # define TARGET_VIRT_ADDR_SPACE_BITS 32 /* sv32 */
+#else
+/* 64-bit target, since QEMU isn't built to have TARGET_LONG_BITS over 64 */
+# define TARGET_LONG_BITS 64
+# define TARGET_PHYS_ADDR_SPACE_BITS 56 /* 44-bit PPN */
+# define TARGET_VIRT_ADDR_SPACE_BITS 48 /* sv48 */
 #endif
 #define TARGET_PAGE_BITS 12 /* 4 KiB Pages */
 /*
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 53a295efb7..8ff5b08d15 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -38,6 +38,7 @@
 #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
 #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
 #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
+#define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("rv128")
 #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
 #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c")
 #define TYPE_RISCV_CPU_SIFIVE_E31   RISCV_CPU_TYPE_NAME("sifive-e31")
@@ -50,6 +51,8 @@
 # define TYPE_RISCV_CPU_BASE

[PATCH v5 09/18] target/riscv: accessors to registers upper part and 128-bit load/store

2021-11-12 Thread Frédéric Pétrot
Get function to retrieve the 64 top bits of a register, stored in the gprh
field of the cpu state. Set function that writes the 128-bit value at once.
The access to the gprh field can not be protected at compile time to make
sure it is accessed only in the 128-bit version of the processor because we
have no way to indicate that the misa_mxl_max field is const.

The 128-bit ISA adds ldu, lq and sq. We provide support for these
instructions. Note that we compute only 64-bit addresses to actually access
memory, cowardly utilizing the existing address translation mechanism of
QEMU.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/insn16.decode  |  27 ++-
 target/riscv/insn32.decode  |   5 ++
 target/riscv/translate.c|  41 ++
 target/riscv/insn_trans/trans_rvi.c.inc | 102 ++--
 4 files changed, 165 insertions(+), 10 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 2e9212663c..02c8f61b48 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -25,14 +25,17 @@
 # Immediates:
 %imm_ci12:s1 2:5
 %nzuimm_ciw7:4 11:2 5:1 6:1   !function=ex_shift_2
+%uimm_cl_q 10:1 5:2 11:2  !function=ex_shift_4
 %uimm_cl_d 5:2 10:3   !function=ex_shift_3
 %uimm_cl_w 5:1 10:3 6:1   !function=ex_shift_2
 %imm_cb12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
 %imm_cj12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
 
 %shimm_6bit   12:1 2:5   !function=ex_rvc_shifti
+%uimm_6bit_lq 2:4 12:1 6:1   !function=ex_shift_4
 %uimm_6bit_ld 2:3 12:1 5:2   !function=ex_shift_3
 %uimm_6bit_lw 2:2 12:1 4:3   !function=ex_shift_2
+%uimm_6bit_sq 7:4 11:2   !function=ex_shift_4
 %uimm_6bit_sd 7:3 10:3   !function=ex_shift_3
 %uimm_6bit_sw 7:2 9:4!function=ex_shift_2
 
@@ -54,16 +57,20 @@
 # Formats 16:
 @cr  . .  ..   rs2=%rs2_5   rs1=%rd %rd
 @ci... . . .  ..   imm=%imm_ci  rs1=%rd %rd
+@cl_q  ... . .  . ..   imm=%uimm_cl_q   rs1=%rs1_3  rd=%rs2_3
 @cl_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  rd=%rs2_3
 @cl_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  rd=%rs2_3
 @cs_2  ... ... ... .. ... ..   rs2=%rs2_3   rs1=%rs1_3  rd=%rs1_3
+@cs_q  ... ... ... .. ... ..   imm=%uimm_cl_q   rs1=%rs1_3  
rs2=%rs2_3
 @cs_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  
rs2=%rs2_3
 @cs_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  
rs2=%rs2_3
 @cj...... ..   imm=%imm_cj
 @cb_z  ... ... ... .. ... ..   imm=%imm_cb  rs1=%rs1_3  rs2=0
 
+@c_lqsp... . .  . ..   imm=%uimm_6bit_lq rs1=2 %rd
 @c_ldsp... . .  . ..   imm=%uimm_6bit_ld rs1=2 %rd
 @c_lwsp... . .  . ..   imm=%uimm_6bit_lw rs1=2 %rd
+@c_sqsp... . .  . ..   imm=%uimm_6bit_sq rs1=2 rs2=%rs2_5
 @c_sdsp... . .  . ..   imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5
 @c_swsp... . .  . ..   imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5
 @c_li  ... . .  . ..   imm=%imm_ci rs1=0 %rd
@@ -87,9 +94,15 @@
   illegal 000  000 000 00 --- 00
   addi000  ... ... .. ... 00 @c_addi4spn
 }
-fld   001  ... ... .. ... 00 @cl_d
+{
+  lq  001  ... ... .. ... 00 @cl_q
+  fld 001  ... ... .. ... 00 @cl_d
+}
 lw010  ... ... .. ... 00 @cl_w
-fsd   101  ... ... .. ... 00 @cs_d
+{
+  sq  101  ... ... .. ... 00 @cs_q
+  fsd 101  ... ... .. ... 00 @cs_d
+}
 sw110  ... ... .. ... 00 @cs_w
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 0) ***
@@ -132,7 +145,10 @@ addw  100 1 11 ... 01 ... 01 @cs_2
 
 # *** RV32/64C Standard Extension (Quadrant 2) ***
 slli  000 .  .  . 10 @c_shift2
-fld   001 .  .  . 10 @c_ldsp
+{
+  lq  001  ... ... .. ... 10 @c_lqsp
+  fld 001 .  .  . 10 @c_ldsp
+}
 {
   illegal 010 -  0  - 10 # c.lwsp, RES rd=0
   lw  010 .  .  . 10 @c_lwsp
@@ -147,7 +163,10 @@ fld   001 .  .  . 10 @c_ldsp
   jalr100 1  .  0 10 @c_jalr rd=1  # C.JALR
   add 100 1  .  . 10 @cr
 }
-fsd   101   ..  . 10 @c_sdsp
+{
+  sq  101  ... ... .. ... 10 @c_sqsp
+  fsd 101   ..  . 10 @c_sdsp
+}
 sw110 .  .  . 10 @c_swsp
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 2) ***
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 2f251dac1b..02889c6082 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -163,6 +163,11 @@ sllw

[PATCH v5 12/18] target/riscv: support for 128-bit shift instructions

2021-11-12 Thread Frédéric Pétrot
Handling shifts for 32, 64 and 128 operation length for RV128, following the
general framework for handling various olens proposed by Richard.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/insn32.decode  |  10 ++
 target/riscv/translate.c|  58 --
 target/riscv/insn_trans/trans_rvb.c.inc |  22 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 224 ++--
 4 files changed, 270 insertions(+), 44 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 02889c6082..e338a803a0 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -22,6 +22,7 @@
 %rs1   15:5
 %rd7:5
 %sh5   20:5
+%sh6   20:6
 
 %sh720:7
 %csr20:12
@@ -92,6 +93,9 @@
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
+# Formats 128:
+@sh6   .. .. . ... . ...  shamt=%sh6 %rs1 %rd
+
 # *** Privileged Instructions ***
 ecall    0 000 0 1110011
 ebreak  0001 0 000 0 1110011
@@ -167,6 +171,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+sllid00 ..  . 001 . 1011011 @sh6
+srlid00 ..  . 101 . 1011011 @sh6
+sraid01 ..  . 101 . 1011011 @sh6
+slld 000 . .  001 . 011 @r
+srld 000 . .  101 . 011 @r
+srad 010 . .  101 . 011 @r
 
 # *** RV32M Standard Extension ***
 mul  001 .  . 000 . 0110011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index d2a2f1021d..504fbfc26a 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -560,7 +560,8 @@ static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, 
DisasExtend ext,
 }
 
 static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest, src1;
 int max_len = get_olen(ctx);
@@ -572,26 +573,38 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 dest = dest_gpr(ctx, a->rd);
 src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->shamt);
+if (max_len < 128) {
+func(dest, src1, a->shamt);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (f128 == NULL) {
+return false;
+}
+f128(dest, desth, src1, src1h, a->shamt);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
 DisasExtend ext,
 void (*f_tl)(TCGv, TCGv, target_long),
-void (*f_32)(TCGv, TCGv, target_long))
+void (*f_32)(TCGv, TCGv, target_long),
+void (*f_128)(TCGv, TCGv, TCGv, TCGv,
+  target_long))
 {
 int olen = get_olen(ctx);
 if (olen != TARGET_LONG_BITS) {
 if (olen == 32) {
 f_tl = f_32;
-} else {
+} else if (olen != 128) {
 g_assert_not_reached();
 }
 }
-return gen_shift_imm_fn(ctx, a, ext, f_tl);
+return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
 }
 
 static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
@@ -615,34 +628,49 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 }
 
 static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
 {
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 TCGv ext2 = tcg_temp_new();
+int max_len = get_olen(ctx);
 
-tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1);
-func(dest, src1, ext2);
+tcg_gen_andi_tl(ext2, src2, max_len - 1);
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, ext);
+
+if (max_len < 128) {
+func(dest, src1, ext2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCG

[PATCH v5 13/18] target/riscv: support for 128-bit arithmetic instructions

2021-11-12 Thread Frédéric Pétrot
Addition of 128-bit adds and subs in their various sizes,
"set if less than"s and branches.
Refactored the code to have a comparison function used for both stls and
branches.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
---
 target/riscv/insn32.decode  |   3 +
 target/riscv/translate.c|  63 --
 target/riscv/insn_trans/trans_rvb.c.inc |  20 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 159 +---
 target/riscv/insn_trans/trans_rvm.c.inc |  26 ++--
 5 files changed, 222 insertions(+), 49 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index e338a803a0..afaf243b4e 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -171,9 +171,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+addid  .  000 . 1011011 @i
 sllid00 ..  . 001 . 1011011 @sh6
 srlid00 ..  . 101 . 1011011 @sh6
 sraid01 ..  . 101 . 1011011 @sh6
+addd 000 . .  000 . 011 @r
+subd 010 . .  000 . 011 @r
 slld 000 . .  001 . 011 @r
 srld 000 . .  101 . 011 @r
 srad 010 . .  101 . 011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 504fbfc26a..a5554275e2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -506,57 +506,96 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 }
 
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->imm);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, a->imm);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, a->imm);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, TCGv))
+ void (*func)(TCGv, TCGv, TCGv),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = tcg_constant_tl(a->imm);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = tcg_constant_tl(-(a->imm < 0));
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, ext);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
  void (*f_tl)(TCGv, TCGv, TCGv),
- void (*f_32)(TCGv, TCGv, TCGv))
+ void (*f_32)(TCGv, TCGv, TCGv),
+ void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 int olen = get_olen(ctx);
 
 if (olen != TARGET_LONG_BITS) {
 if (olen == 32) {
  

[PATCH v5 02/18] exec/memop: Adding signed quad and octo defines

2021-11-12 Thread Frédéric Pétrot
Adding defines to handle signed 64-bit and unsigned 128-bit quantities in
memory accesses.

Signed-off-by: Frédéric Pétrot 
---
 include/exec/memop.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 72c2f0ff3d..2a885f3917 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -86,28 +86,35 @@ typedef enum MemOp {
 MO_UW= MO_16,
 MO_UL= MO_32,
 MO_UQ= MO_64,
+MO_UO= MO_128,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
+MO_SQ= MO_SIGN | MO_64,
+MO_SO= MO_SIGN | MO_128,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
 MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
+MO_LESQ  = MO_LE | MO_SQ,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
 MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
+MO_BESQ  = MO_BE | MO_SQ,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
 MO_TEUQ  = MO_TE | MO_UQ,
+MO_TEUO  = MO_TE | MO_UO,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
+MO_TESQ  = MO_TE | MO_SQ,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
-- 
2.33.1




  1   2   3   >