[PATCH 1/2] util/log: Add vu to dump content of vector unit

2022-07-08 Thread Kito Cheng
Add new option for -d vu to dump the content of vector unit, many target
has vector register, but there is no easy way to dump the content, we
use this on downstream for a while to help debug, and I feel that's
really useful, so I think it would be great to upstream that to save debug time
for other people :)

Signed-off-by: Kito Cheng 
---
 accel/tcg/cpu-exec.c  | 3 +++
 include/hw/core/cpu.h | 2 ++
 include/qemu/log.h| 1 +
 util/log.c| 2 ++
 4 files changed, 8 insertions(+)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index a565a3f8ec..2cbec0a6ed 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -221,6 +221,9 @@ static inline void log_cpu_exec(target_ulong pc, CPUState 
*cpu,
 if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
 flags |= CPU_DUMP_FPU;
 }
+if (qemu_loglevel_mask(CPU_LOG_TB_VU)) {
+flags |= CPU_DUMP_VU;
+}
 #if defined(TARGET_I386)
 flags |= CPU_DUMP_CCOP;
 #endif
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 996f94059f..7a767e17cd 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -535,11 +535,13 @@ GuestPanicInformation *cpu_get_crash_info(CPUState *cpu);
  * @CPU_DUMP_CODE:
  * @CPU_DUMP_FPU: dump FPU register state, not just integer
  * @CPU_DUMP_CCOP: dump info about TCG QEMU's condition code optimization state
+ * @CPU_DUMP_VU: dump vector register state
  */
 enum CPUDumpFlags {
 CPU_DUMP_CODE = 0x0001,
 CPU_DUMP_FPU  = 0x0002,
 CPU_DUMP_CCOP = 0x0004,
+CPU_DUMP_VU   = 0x0008,
 };
 
 /**
diff --git a/include/qemu/log.h b/include/qemu/log.h
index c5643d8dd5..49bd0b0fbc 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -35,6 +35,7 @@ bool qemu_log_separate(void);
 /* LOG_STRACE is used for user-mode strace logging. */
 #define LOG_STRACE (1 << 19)
 #define LOG_PER_THREAD (1 << 20)
+#define CPU_LOG_TB_VU  (1 << 21)
 
 /* Lock/unlock output. */
 
diff --git a/util/log.c b/util/log.c
index d6eb0378c3..775d122c2e 100644
--- a/util/log.c
+++ b/util/log.c
@@ -441,6 +441,8 @@ const QEMULogItem qemu_log_items[] = {
 #ifdef CONFIG_PLUGIN
 { CPU_LOG_PLUGIN, "plugin", "output from TCG plugins\n"},
 #endif
+{ CPU_LOG_TB_VU, "vu",
+  "include vector unit registers in the 'cpu' logging" },
 { LOG_STRACE, "strace",
   "log every user-mode syscall, its input, and its result" },
 { LOG_PER_THREAD, "tid",
-- 
2.34.0




[PATCH 2/2] target/riscv: Implement dump content of vector register

2022-07-08 Thread Kito Cheng
Implement -d cpu,vu to dump content of vector register.

Signed-off-by: Kito Cheng 
---
 target/riscv/cpu.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c1b96da7da..97b289d277 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -72,6 +72,15 @@ const char * const riscv_fpr_regnames[] = {
   "f30/ft10", "f31/ft11"
 };
 
+const char * const riscv_vr_regnames[] = {
+  "v0",  "v1",  "v2",  "v3",  "v4",  "v5",
+  "v6",  "v7",  "v8",  "v9",  "v10", "v11",
+  "v12", "v13", "v14", "v15", "v16", "v17",
+  "v18", "v19", "v20", "v21", "v22", "v23",
+  "v24", "v25", "v26", "v27", "v28", "v29",
+  "v30", "v31"
+};
+
 static const char * const riscv_excp_names[] = {
 "misaligned_fetch",
 "fault_fetch",
@@ -375,6 +384,28 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 }
 }
 }
+if (flags & CPU_DUMP_VU) {
+int vlen = cpu->cfg.vlen;
+int n_chunk = vlen / 64;
+if (vlen == 32) {
+for (i = 0; i < 32; i++) {
+qemu_fprintf(f, "0x%08" PRIx64 "\n", env->vreg[i]);
+}
+} else {
+for (i = 0; i < 32; i++) {
+qemu_fprintf(f, " %-8s ",
+ riscv_vr_regnames[i]);
+
+int vec_reg_offset = i * vlen / 64;
+qemu_fprintf(f, "0x");
+for (int j = n_chunk - 1; j >= 0; --j) {
+qemu_fprintf(f, "%016" PRIx64,
+ env->vreg[vec_reg_offset + j]);
+}
+qemu_fprintf(f, "\n");
+}
+}
+}
 }
 
 static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
-- 
2.34.0




[PATCH 2/2] target/riscv: Auto set elen from vector extension by default

2022-07-08 Thread Kito Cheng
Default ELEN is setting to 64 for now, which is incorrect setting for
Zve32*, and spec has mention minimum VLEN and supported EEW in chapter
"Zve*: Vector Extensions for Embedded Processors" is 32 for Zve32.

ELEN actaully could be derived from which extensions are enabled,
so this patch set elen to 0 as auto detect, and keep the capability to
let user could configure that.

Signed-off-by: Kito Cheng 
---
 target/riscv/cpu.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 487d0faa63..c1b96da7da 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -751,13 +751,22 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 "Vector extension ELEN must be power of 2");
 return;
 }
-if (cpu->cfg.elen > 64 || cpu->cfg.vlen < 8) {
+if (cpu->cfg.elen == 0) {
+  if (cpu->cfg.ext_zve32f) {
+cpu->cfg.elen = 32;
+  }
+  if (cpu->cfg.ext_zve64f || cpu->cfg.ext_v) {
+cpu->cfg.elen = 64;
+  }
+}
+if (cpu->cfg.elen != 0 && (cpu->cfg.elen > 64 ||
+   cpu->cfg.elen < 8)) {
 error_setg(errp,
 "Vector extension implementation only supports ELEN "
 "in the range [8, 64]");
 return;
 }
-if (cpu->cfg.vlen < cpu->cfg.elen) {
+if (cpu->cfg.elen != 0 && cpu->cfg.vlen < cpu->cfg.elen) {
 error_setg(errp,
 "Vector extension VLEN must be greater than or equal "
 "to ELEN");
@@ -901,7 +910,8 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
 DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
 DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
-DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
+/* elen = 0 means set from v or zve* extension */
+DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 0),
 
 DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
 DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
-- 
2.34.0




[PATCH 1/2] target/riscv: Lower bound of VLEN is 32, and check VLEN >= ELEN

2022-07-08 Thread Kito Cheng
According RVV spec 1.0, the minmal requirement of VLEN is great than or
equal to ELEN, and minmal possible ELEN is 32, and also spec has mention
`Minimum VLEN` for zve32* is 32, so the lower bound of VLEN is 32 I
think.

[1] 
https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#2-implementation-defined-constant-parameters
[2] 
https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#182-zve-vector-extensions-for-embedded-processors

Signed-off-by: Kito Cheng 
---
 target/riscv/cpu.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1bb3973806..487d0faa63 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -740,10 +740,10 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 "Vector extension VLEN must be power of 2");
 return;
 }
-if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 128) {
+if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 32) {
 error_setg(errp,
 "Vector extension implementation only supports VLEN "
-"in the range [128, %d]", RV_VLEN_MAX);
+"in the range [32, %d]", RV_VLEN_MAX);
 return;
 }
 if (!is_power_of_2(cpu->cfg.elen)) {
@@ -757,6 +757,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 "in the range [8, 64]");
 return;
 }
+if (cpu->cfg.vlen < cpu->cfg.elen) {
+error_setg(errp,
+"Vector extension VLEN must be greater than or equal "
+"to ELEN");
+return;
+}
 if (cpu->cfg.vext_spec) {
 if (!g_strcmp0(cpu->cfg.vext_spec, "v1.0")) {
 vext_version = VEXT_VERSION_1_00_0;
-- 
2.34.0




[PATCH v3] linux-user/elfload: Implement ELF_HWCAP for RISC-V

2021-07-05 Thread Kito Cheng
Set I, M, A, F, D and C bit for hwcap if misa is set.

V3 Changes:
- Simplify logic of getting hwcap.

V2 Changes:
- Only set imafdc bits, sync with upstream linux kernel.

Signed-off-by: Kito Cheng 
---
 linux-user/elfload.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 598ab8aa13..42ef2a1148 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1434,6 +1434,19 @@ static void elf_core_copy_regs(target_elf_gregset_t 
*regs,
 #define ELF_CLASS ELFCLASS64
 #endif
 
+#define ELF_HWCAP get_elf_hwcap()
+
+static uint32_t get_elf_hwcap(void)
+{
+#define MISA_BIT(EXT) (1 << (EXT - 'A'))
+RISCVCPU *cpu = RISCV_CPU(thread_cpu);
+uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A')
+| MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C');
+
+return cpu->env.misa & mask;
+#undef MISA_BIT
+}
+
 static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
 {
-- 
2.31.1




[PATCH v2] linux-user/elfload: Implement ELF_HWCAP for RISC-V

2021-07-05 Thread Kito Cheng
Set I, M, A, F, D and C bit for hwcap if misa is set.

V2 Changes:
- Only set imafdc bits, sync with upstream linux kernel.

Signed-off-by: Kito Cheng 
---
 linux-user/elfload.c | 30 +-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 598ab8aa13..3cdc7d06e1 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1426,7 +1426,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
 #ifdef TARGET_RISCV
 
 #define ELF_START_MMAP 0x8000
-#define ELF_ARCH  EM_RISCV
+#define ELF_ARCH EM_RISCV
 
 #ifdef TARGET_RISCV32
 #define ELF_CLASS ELFCLASS32
@@ -1434,6 +1434,34 @@ static void elf_core_copy_regs(target_elf_gregset_t 
*regs,
 #define ELF_CLASS ELFCLASS64
 #endif
 
+#define ELF_HWCAP get_elf_hwcap()
+
+static uint32_t get_elf_hwcap(void)
+{
+RISCVCPU *cpu = RISCV_CPU(thread_cpu);
+uint32_t hwcap = 0;
+
+#define MISA_BIT(EXT) (1 << (EXT - 'A'))
+#define GET_EXT(EXT)   \
+do {   \
+if (cpu->env.misa & MISA_BIT(EXT)) {   \
+hwcap |= MISA_BIT(EXT);\
+}  \
+} while (0)
+
+GET_EXT('I');
+GET_EXT('M');
+GET_EXT('A');
+GET_EXT('F');
+GET_EXT('D');
+GET_EXT('C');
+
+#undef MISA_BIT
+#undef GET_EXT
+
+return hwcap;
+}
+
 static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
 {
-- 
2.31.1




[PATCH] linux-user/elfload: Implement ELF_HWCAP for RISC-V

2021-06-04 Thread Kito Cheng
RISC-V define the hwcap as same as content of misa, but it only take lower
26-bits.

Signed-off-by: Kito Cheng 
---
 linux-user/elfload.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 17ab06f612..41b9ef72ea 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1433,6 +1433,17 @@ static void elf_core_copy_regs(target_elf_gregset_t 
*regs,
 #define ELF_CLASS ELFCLASS64
 #endif
 
+#define ELF_HWCAP get_elf_hwcap()
+
+static uint32_t get_elf_hwcap(void)
+{
+RISCVCPU *cpu = RISCV_CPU(thread_cpu);
+/* Take lower 26 bits from misa.  */
+uint32_t hwcap = cpu->env.misa & 0x3ff;
+
+return hwcap;
+}
+
 static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
 {
-- 
2.31.1




[PATCH] linux-user: Add strace support for printing arguments of llseek

2021-05-12 Thread Kito Cheng
Some target are using llseek instead of _llseek like riscv,
nios2, hexagon, and openrisc.

Signed-off-by: Kito Cheng 
---
 linux-user/strace.c| 3 ++-
 linux-user/strace.list | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index e969121b6c..4ebf85b063 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -2335,7 +2335,7 @@ print_linkat(void *cpu_env, const struct syscallname 
*name,
 }
 #endif
 
-#ifdef TARGET_NR__llseek
+#if defined(TARGET_NR__llseek) || defined(TARGET_NR_llseek)
 static void
 print__llseek(void *cpu_env, const struct syscallname *name,
   abi_long arg0, abi_long arg1, abi_long arg2,
@@ -2355,6 +2355,7 @@ print__llseek(void *cpu_env, const struct syscallname 
*name,
 qemu_log("%s", whence);
 print_syscall_epilogue(name);
 }
+#define print_llseek print__llseek
 #endif
 
 #ifdef TARGET_NR_lseek
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 084048ab96..46e1410836 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -511,6 +511,9 @@
 #ifdef TARGET_NR__llseek
 { TARGET_NR__llseek, "_llseek" , NULL, print__llseek, NULL },
 #endif
+#ifdef TARGET_NR_llseek
+{ TARGET_NR_llseek, "llseek" , NULL, print_llseek, NULL },
+#endif
 #ifdef TARGET_NR_lock
 { TARGET_NR_lock, "lock" , NULL, NULL, NULL },
 #endif
-- 
2.31.1




Re: [Bug 1923629] [NEW] RISC-V Vector Instruction vssub.vv not saturating

2021-04-14 Thread Kito Cheng
Add Frank, he is the SiFive's qemu maintainer.

On Thu, Apr 15, 2021 at 11:57 AM Alistair Francis  wrote:
>
> + LIU Zhiwei and Kito Cheng
>
> Alistair
>
> On Wed, Apr 14, 2021 at 1:31 AM Tony Cole <1923...@bugs.launchpad.net> wrote:
> >
> > Public bug reported:
> >
> > I noticed doing a negate ( 0 – 0x8000 ) using vssub.vv produces an
> > incorrect result of 0x8000 (should saturate to 0x7FFF).
> >
> > Here is the bit of the code:
> >
> > vmv.v.i v16, 0
> > …
> > 8f040457vssub.vvv8,v16,v8
> >
> > I believe the instruction encoding is correct (vssub.vv with vd = v8,
> > vs2 = v16, rs1 = v8), but the result does not saturate in QEMU.
> >
> > I’ve just tested with what I think is the latest branch (
> > https://github.com/sifive/qemu/tree/rvv-1.0-upstream-v7 commit 26 Feb
> > 2021: 1151361fa7d45cc90d69086ccf1a4d8397931811 ) and the problem still
> > exists.
> >
> > ** Affects: qemu
> >  Importance: Undecided
> >  Status: New
> >
> >
> > ** Tags: riscv vector
> >
> > --
> > You received this bug notification because you are a member of qemu-
> > devel-ml, which is subscribed to QEMU.
> > https://bugs.launchpad.net/bugs/1923629
> >
> > Title:
> >   RISC-V Vector Instruction vssub.vv not saturating
> >
> > Status in QEMU:
> >   New
> >
> > Bug description:
> >   I noticed doing a negate ( 0 – 0x8000 ) using vssub.vv produces an
> >   incorrect result of 0x8000 (should saturate to 0x7FFF).
> >
> >   Here is the bit of the code:
> >
> > vmv.v.i v16, 0
> > …
> >   8f040457  vssub.vvv8,v16,v8
> >
> >   I believe the instruction encoding is correct (vssub.vv with vd = v8,
> >   vs2 = v16, rs1 = v8), but the result does not saturate in QEMU.
> >
> >   I’ve just tested with what I think is the latest branch (
> >   https://github.com/sifive/qemu/tree/rvv-1.0-upstream-v7 commit 26 Feb
> >   2021: 1151361fa7d45cc90d69086ccf1a4d8397931811 ) and the problem still
> >   exists.
> >
> > To manage notifications about this bug go to:
> > https://bugs.launchpad.net/qemu/+bug/1923629/+subscriptions
> >



Re: [RFC v2 15/15] target/riscv: rvb: support and turn on B-extension from command line

2020-12-16 Thread Kito Cheng
Hi Alistair, Frank:

Should we add the bext_spec option like Vector-ext? I would suggest
adding one to align the behavior between V and B.
But I have no strong opinion for this.

>DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),



Re: [PATCH 5/8] riscv: Add semihosting support [v13]

2020-12-09 Thread Kito Cheng
Hi Keith:

Thanks for your reply, but it seems like we need some more modification in
 linux-user/riscv/cpu_loop.c to enable that, I guess I should post that in mail
rather than attachment :)

Patch here:

>From 2f1eb5825a6dda177d3289106970eab05cb08445 Mon Sep 17 00:00:00 2001
From: Kito Cheng 
Date: Wed, 9 Dec 2020 14:24:51 +0800
Subject: [PATCH] riscv: Add semihosting support for user mode

This could make testing easier and ARM/AArch64 has support on
their linux user mode too, so I think it should be reasonable.

Verified GCC testsuite with newlib/semihosting.

Signed-off-by: Kito Cheng 
---
 linux-user/riscv/cpu_loop.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c
index aa9e437875..9665dabb09 100644
--- a/linux-user/riscv/cpu_loop.c
+++ b/linux-user/riscv/cpu_loop.c
@@ -23,6 +23,7 @@
 #include "qemu.h"
 #include "cpu_loop-common.h"
 #include "elf.h"
+#include "hw/semihosting/common-semi.h"

 void cpu_loop(CPURISCVState *env)
 {
@@ -91,6 +92,10 @@ void cpu_loop(CPURISCVState *env)
 sigcode = TARGET_SEGV_MAPERR;
 sigaddr = env->badaddr;
 break;
+case RISCV_EXCP_SEMIHOST:
+env->gpr[xA0] = do_common_semihosting(cs);
+env->pc += 4;
+break;
 case EXCP_DEBUG:
 gdbstep:
 signum = TARGET_SIGTRAP;
-- 
2.29.2

On Thu, Dec 10, 2020 at 12:30 AM Keith Packard via
 wrote:
>
> Kito Cheng  writes:
>
> > Hi Keith:
> >
> > Thanks for the patch, I've verified with newlib semihosting support
> > which is contributed by Craig Blackmore from embecosm,
> > and I would like to add semihosting to user mode, do you mind add this
> > patch into this patch series?
>
> I tried to add that already, but I admit that I haven't tested it in a
> while. You should find that there are patches to linux-user/semihost.c
> and linux-user/qemu.h to enable it.
>
> --
> -keith



Re: [PATCH 5/8] riscv: Add semihosting support [v13]

2020-12-08 Thread Kito Cheng
RT_INSTRUCTION_FAULT0x16
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index a2787b1d48..e730fd1fe9 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -24,6 +24,7 @@
>  #include "exec/exec-all.h"
>  #include "tcg/tcg-op.h"
>  #include "trace.h"
> +#include "hw/semihosting/common-semi.h"
>
>  int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>  {
> @@ -844,6 +845,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>  target_ulong htval = 0;
>  target_ulong mtval2 = 0;
>
> +if  (cause == RISCV_EXCP_SEMIHOST) {
> +if (env->priv >= PRV_S) {
> +env->gpr[xA0] = do_common_semihosting(cs);
> +env->pc += 4;
> +return;
> +}
> +cause = RISCV_EXCP_BREAKPOINT;
> +}
> +
>  if (!async) {
>  /* set tval to badaddr for traps with address information */
>  switch (cause) {
> diff --git a/target/riscv/insn_trans/trans_privileged.c.inc 
> b/target/riscv/insn_trans/trans_privileged.c.inc
> index 2a61a853bf..32312be202 100644
> --- a/target/riscv/insn_trans/trans_privileged.c.inc
> +++ b/target/riscv/insn_trans/trans_privileged.c.inc
> @@ -29,7 +29,42 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
>
>  static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
>  {
> -generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
> +target_ulongebreak_addr = ctx->base.pc_next;
> +target_ulongpre_addr = ebreak_addr - 4;
> +target_ulongpost_addr = ebreak_addr + 4;
> +uint32_t pre= 0;
> +uint32_t ebreak = 0;
> +uint32_t post   = 0;
> +
> +/*
> + * The RISC-V semihosting spec specifies the following
> + * three-instruction sequence to flag a semihosting call:
> + *
> + *  slli zero, zero, 0x1f   0x01f01013
> + *  ebreak  0x00100073
> + *  srai zero, zero, 0x70x40705013
> + *
> + * The two shift operations on the zero register are no-ops, used
> + * here to signify a semihosting exception, rather than a breakpoint.
> + *
> + * Uncompressed instructions are required so that the sequence is easy
> + * to validate.
> + *
> + * The three instructions are required to lie in the same page so
> + * that no exception will be raised when fetching them.
> + */
> +
> +if ((pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
> +pre= opcode_at(>base, pre_addr);
> +ebreak = opcode_at(>base, ebreak_addr);
> +post   = opcode_at(>base, post_addr);
> +}
> +
> +if  (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
> +generate_exception(ctx, RISCV_EXCP_SEMIHOST);
> +} else {
> +generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
> +}
>  exit_tb(ctx); /* no chaining */
>  ctx->base.is_jmp = DISAS_NORETURN;
>  return true;
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 554d52a4be..0f28b5f41e 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -64,6 +64,7 @@ typedef struct DisasContext {
>  uint16_t vlen;
>  uint16_t mlen;
>  bool vl_eq_vlmax;
> +CPUState *cs;
>  } DisasContext;
>
>  #ifdef TARGET_RISCV64
> @@ -747,6 +748,15 @@ static bool gen_shift(DisasContext *ctx, arg_r *a,
>  return true;
>  }
>
> +static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
> +{
> +DisasContext *ctx = container_of(dcbase, DisasContext, base);
> +CPUState *cpu = ctx->cs;
> +CPURISCVState *env = cpu->env_ptr;
> +
> +return cpu_ldl_code(env, pc);
> +}
> +
>  /* Include insn module translation function */
>  #include "insn_trans/trans_rvi.c.inc"
>  #include "insn_trans/trans_rvm.c.inc"
> @@ -814,6 +824,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
> *dcbase, CPUState *cs)
>  ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
>  ctx->mlen = 1 << (ctx->sew  + 3 - ctx->lmul);
>  ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
> +ctx->cs = cs;
>  }
>
>  static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
> --
> 2.29.2
>
>
From 2f1eb5825a6dda177d3289106970eab05cb08445 Mon Sep 17 00:00:00 2001
From: Kito Cheng 
Date: Wed, 9 Dec 2020 14:24:51 +0800
Subject: [PATCH] riscv: Add semihosting support for user mode

This could made testing more easier and ARM/AArch64 has supported on
their linux user mode too, so I think it should be reasonable.

Verified GCC testsuite with newlib/semihosting.

Signed-off-by: Kito Cheng 
---
 linux-user/riscv/cpu_loop.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c
index aa9e437875..9665dabb09 100644
--- a/linux-user/riscv/cpu_loop.c
+++ b/linux-user/riscv/cpu_loop.c
@@ -23,6 +23,7 @@
 #include "qemu.h"
 #include "cpu_loop-common.h"
 #include "elf.h"
+#include "hw/semihosting/common-semi.h"
 
 void cpu_loop(CPURISCVState *env)
 {
@@ -91,6 +92,10 @@ void cpu_loop(CPURISCVState *env)
 sigcode = TARGET_SEGV_MAPERR;
 sigaddr = env->badaddr;
 break;
+case RISCV_EXCP_SEMIHOST:
+env->gpr[xA0] = do_common_semihosting(cs);
+env->pc += 4;
+break;
 case EXCP_DEBUG:
 gdbstep:
 signum = TARGET_SIGTRAP;
-- 
2.29.2



Re: [RFC 15/15] target/riscv: rvb: support and turn on B-extension from command line

2020-11-19 Thread Kito Cheng
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 0bbfd7f4574..bc29e118c6d 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -438,6 +438,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> **errp)
>  if (cpu->cfg.ext_h) {
>  target_misa |= RVH;
>  }
> +if (cpu->cfg.ext_b) {
> +target_misa |= RVB;
> +}
>  if (cpu->cfg.ext_v) {
>  target_misa |= RVV;
>  if (!is_power_of_2(cpu->cfg.vlen)) {
> @@ -515,6 +518,7 @@ static Property riscv_cpu_properties[] = {
>  DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
>  DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
>  /* This is experimental so mark with 'x-' */
> +DEFINE_PROP_BOOL("x-b", RISCVCPU, cfg.ext_b, true),

I think the default value should be false?

>  DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
>  DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false),
>  DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),



Re: [PATCH v6 04/61] target/riscv: add vector configure instruction

2020-03-23 Thread Kito Cheng
Hi Zhiwei:

vsetvl and vsetvli seems like missing ISA checking before translate,
this cause those 2 instructions can be executed even RVV not enable.
My testing env is qemu riscv64-linux-user mode.

> diff --git a/target/riscv/insn_trans/trans_rvv.inc.c 
> b/target/riscv/insn_trans/trans_rvv.inc.c
> new file mode 100644
> index 00..7381c24295
> --- /dev/null
> +++ b/target/riscv/insn_trans/trans_rvv.inc.c
> @@ -0,0 +1,69 @@
> +/*
> + * RISC-V translation routines for the RVV Standard Extension.
> + *
> + * Copyright (c) 2020 C-SKY Limited. All rights reserved.
> + *
> + * 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 .
> + */
> +
> +static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl * a)
> +{

Missing vext_check_isa_ill(s) check?

> +TCGv s1, s2, dst;
> +s2 = tcg_temp_new();
> +dst = tcg_temp_new();
> +
> +/* Using x0 as the rs1 register specifier, encodes an infinite AVL */
> +if (a->rs1 == 0) {
> +/* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */
> +s1 = tcg_const_tl(RV_VLEN_MAX);
> +} else {
> +s1 = tcg_temp_new();
> +gen_get_gpr(s1, a->rs1);
> +}
> +gen_get_gpr(s2, a->rs2);
> +gen_helper_vsetvl(dst, cpu_env, s1, s2);
> +gen_set_gpr(a->rd, dst);
> +tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
> +lookup_and_goto_ptr(ctx);
> +ctx->base.is_jmp = DISAS_NORETURN;
> +
> +tcg_temp_free(s1);
> +tcg_temp_free(s2);
> +tcg_temp_free(dst);
> +return true;
> +}
> +
> +static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli * a)
> +{
Missing vext_check_isa_ill(s) check?


> +TCGv s1, s2, dst;
> +s2 = tcg_const_tl(a->zimm);
> +dst = tcg_temp_new();
> +
> +/* Using x0 as the rs1 register specifier, encodes an infinite AVL */
> +if (a->rs1 == 0) {
> +/* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */
> +s1 = tcg_const_tl(RV_VLEN_MAX);
> +} else {
> +s1 = tcg_temp_new();
> +gen_get_gpr(s1, a->rs1);
> +}
> +gen_helper_vsetvl(dst, cpu_env, s1, s2);
> +gen_set_gpr(a->rd, dst);
> +gen_goto_tb(ctx, 0, ctx->pc_succ_insn);
> +ctx->base.is_jmp = DISAS_NORETURN;
> +
> +tcg_temp_free(s1);
> +tcg_temp_free(s2);
> +tcg_temp_free(dst);
> +return true;
> +}



[Qemu-devel] [PATCH] target/riscv: Fix wrong expanding for c.fswsp

2019-03-26 Thread Kito Cheng
From: Kito Cheng 

base register is no rs1 not rs2 for fsw.

Signed-off-by: Kito Cheng 
---
 target/riscv/insn_trans/trans_rvc.inc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/insn_trans/trans_rvc.inc.c 
b/target/riscv/insn_trans/trans_rvc.inc.c
index 5819f53..ebcd977 100644
--- a/target/riscv/insn_trans/trans_rvc.inc.c
+++ b/target/riscv/insn_trans/trans_rvc.inc.c
@@ -337,7 +337,7 @@ static bool trans_c_fswsp_sdsp(DisasContext *ctx, 
arg_c_fswsp_sdsp *a)
 {
 #ifdef TARGET_RISCV32
 /* C.FSWSP */
-arg_fsw a_fsw = { .rs1 = a->rs2, .rs2 = 2, .imm = a->uimm_fswsp };
+arg_fsw a_fsw = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm_fswsp };
 return trans_fsw(ctx, _fsw);
 #else
 /* C.SDSP */
-- 
1.8.3.1




[Qemu-devel] [PATCH] hardfloat: fix float32/64 fused multiply-add

2019-03-22 Thread Kito Cheng
hardfloat fused multiply-add might fallback to softfloat mode in some
situation, but it might already changed the value of input operands,
so we must restore those value before fallback.

This bug is catched by running gcc testsuite on RISC-V qemu.

Signed-off-by: Kito Cheng 
---
 fpu/softfloat.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 4610738..f53f391 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1596,6 +1596,7 @@ float32_muladd(float32 xa, float32 xb, float32
xc, int flags, float_status *s)
 }
 ur.h = up.h + uc.h;
 } else {
+union_float32 ux = ua, uy = uc;
 if (flags & float_muladd_negate_product) {
 ua.h = -ua.h;
 }
@@ -1608,6 +1609,8 @@ float32_muladd(float32 xa, float32 xb, float32
xc, int flags, float_status *s)
 if (unlikely(f32_is_inf(ur))) {
 s->float_exception_flags |= float_flag_overflow;
 } else if (unlikely(fabsf(ur.h) <= FLT_MIN)) {
+ua.h = ux.h;
+uc.h = uy.h;
 goto soft;
 }
 }
@@ -1662,6 +1665,8 @@ float64_muladd(float64 xa, float64 xb, float64
xc, int flags, float_status *s)
 }
 ur.h = up.h + uc.h;
 } else {
+union_float64 ux = ua, uy = uc;
+
 if (flags & float_muladd_negate_product) {
 ua.h = -ua.h;
 }
@@ -1674,6 +1679,8 @@ float64_muladd(float64 xa, float64 xb, float64
xc, int flags, float_status *s)
 if (unlikely(f64_is_inf(ur))) {
 s->float_exception_flags |= float_flag_overflow;
 } else if (unlikely(fabs(ur.h) <= FLT_MIN)) {
+ua.h = ux.h;
+uc.h = uy.h;
 goto soft;
 }
 }



Re: [Qemu-devel] [PATCH] target/riscv: Zero extend the inputs of divuw and remuw

2019-03-21 Thread Kito Cheng
Verified with gcc testsuite on rv64gc, no new regression introduced, and
get less fails.

Palmer Dabbelt 於 2019年3月21日 週四,22:59寫道:

> While running the GCC test suite against 4.0.0-rc0, Kito found a
> regression introduced by the decodetree conversion that caused divuw and
> remuw to sign-extend their inputs.  The ISA manual says they are
> supposed to be zero extended:
>
> DIVW and DIVUW instructions are only valid for RV64, and divide the
> lower 32 bits of rs1 by the lower 32 bits of rs2, treating them as
> signed and unsigned integers respectively, placing the 32-bit
> quotient in rd, sign-extended to 64 bits. REMW and REMUW
> instructions are only valid for RV64, and provide the corresponding
> signed and unsigned remainder operations respectively.  Both REMW
> and REMUW always sign-extend the 32-bit result to 64 bits, including
> on a divide by zero.
>
> Here's Kito's reduced test case from the GCC test suite
>
> unsigned calc_mp(unsigned mod)
> {
>  unsigned a,b,c;
>  c=-1;
>  a=c/mod;
>  b=0-a*mod;
>  if (b > mod) { a += 1; b-=mod; }
>  return b;
> }
>
> int main(int argc, char *argv[])
> {
>  unsigned x = 1234;
>  unsigned y = calc_mp(x);
>
>  if ((sizeof (y) == 4 && y != 680)
>   || (sizeof (y) == 2 && y != 134))
> abort ();
>  exit (0);
> }
>
> I haven't done any other testing on this, but it does fix the test case.
>
> Signed-off-by: Palmer Dabbelt 
> ---
>  target/riscv/insn_trans/trans_rvm.inc.c |  4 ++--
>  target/riscv/translate.c| 21 +
>  2 files changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvm.inc.c
> b/target/riscv/insn_trans/trans_rvm.inc.c
> index 204af225f8f3..47cd6edc72a1 100644
> --- a/target/riscv/insn_trans/trans_rvm.inc.c
> +++ b/target/riscv/insn_trans/trans_rvm.inc.c
> @@ -103,7 +103,7 @@ static bool trans_divw(DisasContext *ctx, arg_divw *a)
>  static bool trans_divuw(DisasContext *ctx, arg_divuw *a)
>  {
>  REQUIRE_EXT(ctx, RVM);
> -return gen_arith_div_w(ctx, a, _divu);
> +return gen_arith_div_uw(ctx, a, _divu);
>  }
>
>  static bool trans_remw(DisasContext *ctx, arg_remw *a)
> @@ -115,6 +115,6 @@ static bool trans_remw(DisasContext *ctx, arg_remw *a)
>  static bool trans_remuw(DisasContext *ctx, arg_remuw *a)
>  {
>  REQUIRE_EXT(ctx, RVM);
> -return gen_arith_div_w(ctx, a, _remu);
> +return gen_arith_div_uw(ctx, a, _remu);
>  }
>  #endif
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 049fa65c6611..dd763647ea55 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -600,6 +600,27 @@ static bool gen_arith_div_w(DisasContext *ctx, arg_r
> *a,
>  return true;
>  }
>
> +static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a,
> +void(*func)(TCGv, TCGv, TCGv))
> +{
> +TCGv source1, source2;
> +source1 = tcg_temp_new();
> +source2 = tcg_temp_new();
> +
> +gen_get_gpr(source1, a->rs1);
> +gen_get_gpr(source2, a->rs2);
> +tcg_gen_ext32u_tl(source1, source1);
> +tcg_gen_ext32u_tl(source2, source2);
> +
> +(*func)(source1, source1, source2);
> +
> +tcg_gen_ext32s_tl(source1, source1);
> +gen_set_gpr(a->rd, source1);
> +tcg_temp_free(source1);
> +tcg_temp_free(source2);
> +return true;
> +}
> +
>  #endif
>
>  static bool gen_arith(DisasContext *ctx, arg_r *a,
> --
> 2.19.2
>
>