All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v14 00/26] Add LoongArch linux-user emulation support
@ 2022-01-06  9:41 Song Gao
  2022-01-06  9:41 ` [PATCH v14 01/26] target/loongarch: Add README Song Gao
                   ` (26 more replies)
  0 siblings, 27 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel

Based-on: <20220106074740.1754661-1-gaosong@loongson.cn>

Hi all,

This series only support linux-user emulation.
More about LoongArch at: https://github.com/loongson/

The latest kernel:
  * https://github.com/loongson/linux/tree/loongarch-next

Patches need review:
  * 0018-linux-user-Add-LoongArch-specific-structures.patch
  * 0019-linux-user-Add-LoongArch-signal-support.patch

Changes for v14:
  * Rebase;
  * Update README, use new clfs-system/cross-tools test.

V13:
https://patchew.org/QEMU/1638610165-15036-1-git-send-email-gaosong@loongson.cn/

Please review! Thanks.

Song Gao (26):
  target/loongarch: Add README
  target/loongarch: Add core definition
  target/loongarch: Add main translation routines
  target/loongarch: Add fixed point arithmetic instruction translation
  target/loongarch: Add fixed point shift instruction translation
  target/loongarch: Add fixed point bit instruction translation
  target/loongarch: Add fixed point load/store instruction translation
  target/loongarch: Add fixed point atomic instruction translation
  target/loongarch: Add fixed point extra instruction translation
  target/loongarch: Add floating point arithmetic instruction
    translation
  target/loongarch: Add floating point comparison instruction
    translation
  target/loongarch: Add floating point conversion instruction
    translation
  target/loongarch: Add floating point move instruction translation
  target/loongarch: Add floating point load/store instruction
    translation
  target/loongarch: Add branch instruction translation
  target/loongarch: Add disassembler
  linux-user: Add LoongArch generic header files
  linux-user: Add LoongArch specific structures
  linux-user: Add LoongArch signal support
  linux-user: Add LoongArch elf support
  linux-user: Add LoongArch syscall support
  linux-user: Add LoongArch cpu_loop support
  default-configs: Add loongarch linux-user support
  target/loongarch: Add target build suport
  target/loongarch: 'make check-tcg' support
  scripts: add loongarch64 binfmt config

 MAINTAINERS                                   |   5 +
 configs/targets/loongarch64-linux-user.mak    |   3 +
 configure                                     |   3 +
 include/disas/dis-asm.h                       |   2 +
 linux-user/elfload.c                          |  53 ++
 linux-user/loongarch64/cpu_loop.c             |  94 ++
 linux-user/loongarch64/signal.c               | 198 ++++
 linux-user/loongarch64/sockbits.h             |  11 +
 linux-user/loongarch64/syscall_nr.h           | 313 +++++++
 linux-user/loongarch64/target_cpu.h           |  34 +
 linux-user/loongarch64/target_elf.h           |  12 +
 linux-user/loongarch64/target_errno_defs.h    |  12 +
 linux-user/loongarch64/target_fcntl.h         |  11 +
 linux-user/loongarch64/target_signal.h        |  13 +
 linux-user/loongarch64/target_structs.h       |  47 +
 linux-user/loongarch64/target_syscall.h       |  48 +
 linux-user/loongarch64/termbits.h             |  11 +
 linux-user/syscall_defs.h                     |  10 +-
 meson.build                                   |   1 +
 scripts/gensyscalls.sh                        |   1 +
 scripts/qemu-binfmt-conf.sh                   |   6 +-
 target/loongarch/README                       |  77 ++
 target/loongarch/cpu-param.h                  |  18 +
 target/loongarch/cpu.c                        | 315 +++++++
 target/loongarch/cpu.h                        | 252 +++++
 target/loongarch/disas.c                      | 612 +++++++++++++
 target/loongarch/fpu_helper.c                 | 862 ++++++++++++++++++
 target/loongarch/helper.h                     |  94 ++
 target/loongarch/insn_trans/trans_arith.c.inc | 304 ++++++
 .../loongarch/insn_trans/trans_atomic.c.inc   | 114 +++
 target/loongarch/insn_trans/trans_bit.c.inc   | 212 +++++
 .../loongarch/insn_trans/trans_branch.c.inc   |  83 ++
 target/loongarch/insn_trans/trans_extra.c.inc |  86 ++
 .../loongarch/insn_trans/trans_farith.c.inc   | 105 +++
 target/loongarch/insn_trans/trans_fcmp.c.inc  |  56 ++
 target/loongarch/insn_trans/trans_fcnv.c.inc  |  33 +
 .../loongarch/insn_trans/trans_fmemory.c.inc  | 153 ++++
 target/loongarch/insn_trans/trans_fmov.c.inc  | 157 ++++
 .../loongarch/insn_trans/trans_memory.c.inc   | 229 +++++
 target/loongarch/insn_trans/trans_shift.c.inc | 106 +++
 target/loongarch/insns.decode                 | 442 +++++++++
 target/loongarch/internals.h                  |  28 +
 target/loongarch/meson.build                  |  19 +
 target/loongarch/op_helper.c                  |  85 ++
 target/loongarch/translate.c                  | 268 ++++++
 target/loongarch/translate.h                  |  45 +
 target/meson.build                            |   1 +
 tests/tcg/configure.sh                        |   1 +
 48 files changed, 5640 insertions(+), 5 deletions(-)
 create mode 100644 configs/targets/loongarch64-linux-user.mak
 create mode 100644 linux-user/loongarch64/cpu_loop.c
 create mode 100644 linux-user/loongarch64/signal.c
 create mode 100644 linux-user/loongarch64/sockbits.h
 create mode 100644 linux-user/loongarch64/syscall_nr.h
 create mode 100644 linux-user/loongarch64/target_cpu.h
 create mode 100644 linux-user/loongarch64/target_elf.h
 create mode 100644 linux-user/loongarch64/target_errno_defs.h
 create mode 100644 linux-user/loongarch64/target_fcntl.h
 create mode 100644 linux-user/loongarch64/target_signal.h
 create mode 100644 linux-user/loongarch64/target_structs.h
 create mode 100644 linux-user/loongarch64/target_syscall.h
 create mode 100644 linux-user/loongarch64/termbits.h
 create mode 100644 target/loongarch/README
 create mode 100644 target/loongarch/cpu-param.h
 create mode 100644 target/loongarch/cpu.c
 create mode 100644 target/loongarch/cpu.h
 create mode 100644 target/loongarch/disas.c
 create mode 100644 target/loongarch/fpu_helper.c
 create mode 100644 target/loongarch/helper.h
 create mode 100644 target/loongarch/insn_trans/trans_arith.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_atomic.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_bit.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_branch.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_extra.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_farith.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_fcmp.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_fcnv.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_fmemory.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_fmov.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_memory.c.inc
 create mode 100644 target/loongarch/insn_trans/trans_shift.c.inc
 create mode 100644 target/loongarch/insns.decode
 create mode 100644 target/loongarch/internals.h
 create mode 100644 target/loongarch/meson.build
 create mode 100644 target/loongarch/op_helper.c
 create mode 100644 target/loongarch/translate.c
 create mode 100644 target/loongarch/translate.h

-- 
2.27.0



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

* [PATCH v14 01/26] target/loongarch: Add README
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:24   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 02/26] target/loongarch: Add core definition Song Gao
                   ` (25 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This patch gives an introduction to the LoongArch target.

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 MAINTAINERS             |  5 +++
 target/loongarch/README | 77 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)
 create mode 100644 target/loongarch/README

diff --git a/MAINTAINERS b/MAINTAINERS
index f871d759fd..2df0d4a7c2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -213,6 +213,11 @@ S: Maintained
 F: target/hppa/
 F: disas/hppa.c
 
+LoongArch TCG CPUS
+M: Song Gao <gaosong@loongson.cn>
+S: Maintained
+F: target/loongarch/
+
 M68K TCG CPUs
 M: Laurent Vivier <laurent@vivier.eu>
 S: Maintained
diff --git a/target/loongarch/README b/target/loongarch/README
new file mode 100644
index 0000000000..d5780c5918
--- /dev/null
+++ b/target/loongarch/README
@@ -0,0 +1,77 @@
+- Introduction
+
+  LoongArch is the general processor architecture of Loongson.
+
+  The following versions of the LoongArch core are supported
+    core: 3A5000
+    https://github.com/loongson/LoongArch-Documentation/releases/download/2021.08.17/LoongArch-Vol1-v1.00-EN.pdf
+
+  We can get the latest loongarch documents at https://github.com/loongson/LoongArch-Documentation/tags.
+
+
+- Linux-user emulation
+
+  We already support Linux user emulation. We can use LoongArch cross-tools to build LoongArch executables on X86 machines,
+  and We can also use qemu-loongarch64 to run LoongArch executables.
+
+  1. Install LoongArch cross-tools on X86 machines.
+
+    Download cross-tools.
+
+      wget https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20211202-cross-tools.tar.xz
+
+      tar -vxf loongarch64-clfs-20211202-cross-tools.tar.xz -C /opt
+
+    Config cross-tools env.
+
+      . setenv.sh
+
+      setenv.sh:
+
+          #!/bin/sh
+          set -x
+          CC_PREFIX=/opt/cross-tools
+
+          export PATH=$CC_PREFIX/bin:$PATH
+          export LD_LIBRARY_PATH=$CC_PREFIX/lib:$LD_LIBRARY_PATH
+          export LD_LIBRARY_PATH=$CC_PREFIX/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH
+          set +x
+
+  2. Test tests/tcg/multiarch.
+
+    ./configure --disable-rdma --disable-pvrdma --prefix=/usr  \
+            --target-list="loongarch64-linux-user"  \
+            --disable-libiscsi --disable-libnfs --disable-libpmem \
+            --disable-glusterfs --enable-libusb --enable-usb-redir \
+            --disable-opengl --disable-xen --enable-spice --disable-werror \
+            --enable-debug --disable-capstone --disable-kvm --enable-profiler
+
+    cd  build/
+
+    make && make check-tcg
+
+  3. Run LoongArch system basic command with loongarch-clfs-system.
+
+    Download clfs-system.
+
+      wget https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-system-2021-12-02.tar.bz2
+
+      tar -vxf loongarch64-clfs-system-2021-12-02.tar.bz2 -C /opt/clfs
+      ln -s /opt/clfs/  /opt/clfs/tls
+
+    Config env.
+
+      cp /opt/clfs/lib64/ld-linux-loongarch64.so.1   /lib64
+
+      export LD_LIBRARY_PATH="/opt/clfs/lib64"
+
+    Run LoongArch system basic command.
+
+      ./qemu-loongarch64  /opt/clfs/usr/bin/bash
+      ./qemu-loongarch64  /opt/clfs/usr/bin/ls
+      ./qemu-loongarch64  /opt/clfs/usr/bin/pwd
+      ...
+
+
+- Note.
+  We can get the latest LoongArch documents or LoongArch tools at https://github.com/loongson/
-- 
2.27.0



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

* [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
  2022-01-06  9:41 ` [PATCH v14 01/26] target/loongarch: Add README Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 03/26] target/loongarch: Add main translation routines Song Gao
                   ` (24 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé

This patch adds target state header, target definitions
and initialization routines.

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 target/loongarch/cpu-param.h |  18 ++
 target/loongarch/cpu.c       | 314 +++++++++++++++++++++++++++++++++++
 target/loongarch/cpu.h       | 252 ++++++++++++++++++++++++++++
 target/loongarch/internals.h |  21 +++
 4 files changed, 605 insertions(+)
 create mode 100644 target/loongarch/cpu-param.h
 create mode 100644 target/loongarch/cpu.c
 create mode 100644 target/loongarch/cpu.h
 create mode 100644 target/loongarch/internals.h

diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h
new file mode 100644
index 0000000000..9a769b67e0
--- /dev/null
+++ b/target/loongarch/cpu-param.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch CPU parameters for QEMU.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_PARAM_H
+#define LOONGARCH_CPU_PARAM_H
+
+#define TARGET_LONG_BITS 64
+#define TARGET_PHYS_ADDR_SPACE_BITS 48
+#define TARGET_VIRT_ADDR_SPACE_BITS 48
+
+#define TARGET_PAGE_BITS 14
+#define NB_MMU_MODES 4
+
+#endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
new file mode 100644
index 0000000000..76b89d1606
--- /dev/null
+++ b/target/loongarch/cpu.c
@@ -0,0 +1,314 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/qemu-print.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "sysemu/qtest.h"
+#include "exec/exec-all.h"
+#include "qapi/qapi-commands-machine-target.h"
+#include "cpu.h"
+#include "internals.h"
+#include "fpu/softfloat-helpers.h"
+
+const char * const regnames[32] = {
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+};
+
+const char * const fregnames[32] = {
+    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+    "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+    "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+    "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+};
+
+static const char * const excp_names[EXCP_LAST + 1] = {
+    [EXCP_SYSCALL] = "Syscall",
+    [EXCP_BREAK] = "Break",
+    [EXCP_INE] = "Instruction Non-existent",
+    [EXCP_FPE] = "Floating Point Exception",
+};
+
+const char *loongarch_exception_name(int32_t exception)
+{
+    assert(excp_names[exception]);
+    return excp_names[exception];
+}
+
+void QEMU_NORETURN do_raise_exception(CPULoongArchState *env,
+                                      uint32_t exception,
+                                      uintptr_t pc)
+{
+    CPUState *cs = env_cpu(env);
+
+    qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n",
+                  __func__,
+                  exception,
+                  loongarch_exception_name(exception));
+    cs->exception_index = exception;
+
+    cpu_loop_exit_restore(cs, pc);
+}
+
+static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    CPULoongArchState *env = &cpu->env;
+
+    env->pc = value;
+}
+
+#ifdef CONFIG_TCG
+static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
+                                              const TranslationBlock *tb)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    CPULoongArchState *env = &cpu->env;
+
+    env->pc = tb->pc;
+}
+#endif /* CONFIG_TCG */
+
+static bool loongarch_cpu_has_work(CPUState *cs)
+{
+    return true;
+}
+
+static void loongarch_3a5000_initfn(Object *obj)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+    CPULoongArchState *env = &cpu->env;
+    int i;
+
+    for (i = 0; i < 21; i++) {
+        env->cpucfg[i] = 0x0;
+    }
+
+    env->cpucfg[0] = 0x14c010;  /* PRID */
+
+    uint32_t data = 0;
+    data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
+    data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
+    data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
+    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
+    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
+    data = FIELD_DP32(data, CPUCFG1, UAL, 1);
+    data = FIELD_DP32(data, CPUCFG1, RI, 1);
+    data = FIELD_DP32(data, CPUCFG1, EP, 1);
+    data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
+    data = FIELD_DP32(data, CPUCFG1, HP, 1);
+    data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
+    env->cpucfg[1] = data;
+
+    data = 0;
+    data = FIELD_DP32(data, CPUCFG2, FP, 1);
+    data = FIELD_DP32(data, CPUCFG2, FP_SP, 1);
+    data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
+    data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
+    data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
+    data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
+    data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
+    data = FIELD_DP32(data, CPUCFG2, LAM, 1);
+    env->cpucfg[2] = data;
+
+    env->cpucfg[4] = 100 * 1000 * 1000; /* Crystal frequency */
+
+    data = 0;
+    data = FIELD_DP32(data, CPUCFG5, CC_MUL, 1);
+    data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1);
+    env->cpucfg[5] = data;
+
+    data = 0;
+    data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1);
+    data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
+    data = FIELD_DP32(data, CPUCFG16, L2_IUPRE, 1);
+    data = FIELD_DP32(data, CPUCFG16, L2_IUUNIFY, 1);
+    data = FIELD_DP32(data, CPUCFG16, L2_IUPRIV, 1);
+    data = FIELD_DP32(data, CPUCFG16, L3_IUPRE, 1);
+    data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
+    data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
+    env->cpucfg[16] = data;
+
+    data = 0;
+    data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 0x8003);
+    data = FIELD_DP32(data, CPUCFG17, L1IU_SETS, 0x60);
+    env->cpucfg[17] =  data;
+
+    data = 0;
+    data = FIELD_DP32(data, CPUCFG18, L1D_WAYS, 0x8003);
+    data = FIELD_DP32(data, CPUCFG18, L1D_SETS, 0x60);
+    env->cpucfg[18] = data;
+
+    data = 0;
+    data = FIELD_DP32(data, CPUCFG19, L2IU_WAYS, 0x800f);
+    data = FIELD_DP32(data, CPUCFG19, L2IU_SETS, 0x60);
+    env->cpucfg[19] = data;
+
+    data = 0;
+    data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 0xf00f);
+    data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 0x60);
+    env->cpucfg[20] = data;
+}
+
+static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    const char *typename = object_class_get_name(OBJECT_CLASS(data));
+
+    qemu_printf("%s\n", typename);
+}
+
+void loongarch_cpu_list(void)
+{
+    GSList *list;
+    list = object_class_get_list_sorted(TYPE_LOONGARCH_CPU, false);
+    g_slist_foreach(list, loongarch_cpu_list_entry, NULL);
+    g_slist_free(list);
+}
+
+static void loongarch_cpu_reset(DeviceState *dev)
+{
+    CPUState *cs = CPU(dev);
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(cpu);
+    CPULoongArchState *env = &cpu->env;
+
+    lacc->parent_reset(dev);
+
+    env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
+    env->fcsr0 = 0x0;
+
+    cs->exception_index = EXCP_NONE;
+}
+
+static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info)
+{
+    info->print_insn = print_insn_loongarch;
+}
+
+static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+    CPUState *cs = CPU(dev);
+    LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
+    Error *local_err = NULL;
+
+    cpu_exec_realizefn(cs, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    cpu_reset(cs);
+    qemu_init_vcpu(cs);
+
+    lacc->parent_realize(dev, errp);
+}
+
+static void loongarch_cpu_initfn(Object *obj)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+
+    cpu_set_cpustate_pointers(cpu);
+}
+
+static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
+{
+    ObjectClass *oc;
+    char *typename;
+
+    typename = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model);
+    oc = object_class_by_name(typename);
+    g_free(typename);
+    return oc;
+}
+
+void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    CPULoongArchState *env = &cpu->env;
+    int i;
+
+    qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
+    qemu_fprintf(f, " FCSR0 0x%08x  fp_status 0x%02x\n", env->fcsr0,
+                 get_float_exception_flags(&env->fp_status));
+
+    /* gpr */
+    for (i = 0; i < 32; i++) {
+        if ((i & 3) == 0) {
+            qemu_fprintf(f, " GPR%02d:", i);
+        }
+        qemu_fprintf(f, " %s %016" PRIx64, regnames[i], env->gpr[i]);
+        if ((i & 3) == 3) {
+            qemu_fprintf(f, "\n");
+        }
+    }
+
+    /* fpr */
+    if (flags & CPU_DUMP_FPU) {
+        for (i = 0; i < 32; i++) {
+            qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i]);
+            if ((i & 3) == 3) {
+                qemu_fprintf(f, "\n");
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps loongarch_tcg_ops = {
+    .initialize = loongarch_translate_init,
+    .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
+};
+#endif /* CONFIG_TCG */
+
+static void loongarch_cpu_class_init(ObjectClass *c, void *data)
+{
+    LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
+    CPUClass *cc = CPU_CLASS(c);
+    DeviceClass *dc = DEVICE_CLASS(c);
+
+    device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
+                                    &lacc->parent_realize);
+    device_class_set_parent_reset(dc, loongarch_cpu_reset, &lacc->parent_reset);
+
+    cc->class_by_name = loongarch_cpu_class_by_name;
+    cc->has_work = loongarch_cpu_has_work;
+    cc->dump_state = loongarch_cpu_dump_state;
+    cc->set_pc = loongarch_cpu_set_pc;
+    cc->disas_set_info = loongarch_cpu_disas_set_info;
+#ifdef CONFIG_TCG
+    cc->tcg_ops = &loongarch_tcg_ops;
+#endif
+}
+
+#define DEFINE_LOONGARCH_CPU_TYPE(model, initfn) \
+    { \
+        .parent = TYPE_LOONGARCH_CPU, \
+        .instance_init = initfn, \
+        .name = LOONGARCH_CPU_TYPE_NAME(model), \
+    }
+
+static const TypeInfo loongarch_cpu_type_infos[] = {
+    {
+        .name = TYPE_LOONGARCH_CPU,
+        .parent = TYPE_CPU,
+        .instance_size = sizeof(LoongArchCPU),
+        .instance_init = loongarch_cpu_initfn,
+
+        .abstract = true,
+        .class_size = sizeof(LoongArchCPUClass),
+        .class_init = loongarch_cpu_class_init,
+    },
+    DEFINE_LOONGARCH_CPU_TYPE("Loongson-3A5000", loongarch_3a5000_initfn),
+};
+
+DEFINE_TYPES(loongarch_cpu_type_infos)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
new file mode 100644
index 0000000000..b036cdee5f
--- /dev/null
+++ b/target/loongarch/cpu.h
@@ -0,0 +1,252 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_H
+#define LOONGARCH_CPU_H
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat-types.h"
+#include "hw/registerfields.h"
+
+#define TCG_GUEST_DEFAULT_MO (0)
+
+#define FCSR0_M1    0x1f         /* FCSR1 mask, Enables */
+#define FCSR0_M2    0x1f1f0000   /* FCSR2 mask, Cause and Flags */
+#define FCSR0_M3    0x300        /* FCSR3 mask, Round Mode */
+#define FCSR0_RM    8            /* Round Mode bit num on fcsr0 */
+
+FIELD(FCSR0, ENABLES, 0, 5)
+FIELD(FCSR0, RM, 8, 2)
+FIELD(FCSR0, FLAGS, 16, 5)
+FIELD(FCSR0, CAUSE, 24, 5)
+
+#define GET_FP_CAUSE(REG)      FIELD_EX32(REG, FCSR0, CAUSE)
+#define SET_FP_CAUSE(REG, V)   FIELD_DP32(REG, FCSR0, CAUSE, V)
+#define GET_FP_ENABLES(REG)    FIELD_EX32(REG, FCSR0, ENABLES)
+#define SET_FP_ENABLES(REG, V) FIELD_DP32(REG, FCSR0, ENABLES, V)
+#define GET_FP_FLAGS(REG)      FIELD_EX32(REG, FCSR0, FLAGS)
+#define SET_FP_FLAGS(REG, V)   FIELD_DP32(REG, FCSR0, FLAGS, V)
+#define UPDATE_FP_FLAGS(REG, V) \
+    do { \
+        (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \
+    } while (0)
+
+#define FP_INEXACT        1
+#define FP_UNDERFLOW      2
+#define FP_OVERFLOW       4
+#define FP_DIV0           8
+#define FP_INVALID        16
+
+/* cpucfg[0] bits */
+FIELD(CPUCFG0, PRID, 0, 32)
+
+/* cpucfg[1] bits */
+FIELD(CPUCFG1, ARCH, 0, 2)
+FIELD(CPUCFG1, PGMMU, 2, 1)
+FIELD(CPUCFG1, IOCSR, 3, 1)
+FIELD(CPUCFG1, PALEN, 4, 8)
+FIELD(CPUCFG1, VALEN, 12, 8)
+FIELD(CPUCFG1, UAL, 20, 1)
+FIELD(CPUCFG1, RI, 21, 1)
+FIELD(CPUCFG1, EP, 22, 1)
+FIELD(CPUCFG1, RPLV, 23, 1)
+FIELD(CPUCFG1, HP, 24, 1)
+FIELD(CPUCFG1, IOCSR_BRD, 25, 1)
+FIELD(CPUCFG1, MSG_INT, 26, 1)
+
+/* cpucfg[2] bits */
+FIELD(CPUCFG2, FP, 0, 1)
+FIELD(CPUCFG2, FP_SP, 1, 1)
+FIELD(CPUCFG2, FP_DP, 2, 1)
+FIELD(CPUCFG2, FP_VER, 3, 3)
+FIELD(CPUCFG2, LSX, 6, 1)
+FIELD(CPUCFG2, LASX, 7, 1)
+FIELD(CPUCFG2, COMPLEX, 8, 1)
+FIELD(CPUCFG2, CRYPTO, 9, 1)
+FIELD(CPUCFG2, LVZ, 10, 1)
+FIELD(CPUCFG2, LVZ_VER, 11, 3)
+FIELD(CPUCFG2, LLFTP, 14, 1)
+FIELD(CPUCFG2, LLFTP_VER, 15, 3)
+FIELD(CPUCFG2, LBT_X86, 18, 1)
+FIELD(CPUCFG2, LBT_ARM, 19, 1)
+FIELD(CPUCFG2, LBT_MIPS, 20, 1)
+FIELD(CPUCFG2, LSPW, 21, 1)
+FIELD(CPUCFG2, LAM, 22, 1)
+
+/* cpucfg[3] bits */
+FIELD(CPUCFG3, CCDMA, 0, 1)
+FIELD(CPUCFG3, SFB, 1, 1)
+FIELD(CPUCFG3, UCACC, 2, 1)
+FIELD(CPUCFG3, LLEXC, 3, 1)
+FIELD(CPUCFG3, SCDLY, 4, 1)
+FIELD(CPUCFG3, LLDBAR, 5, 1)
+FIELD(CPUCFG3, ITLBHMC, 6, 1)
+FIELD(CPUCFG3, ICHMC, 7, 1)
+FIELD(CPUCFG3, SPW_LVL, 8, 3)
+FIELD(CPUCFG3, SPW_HP_HF, 11, 1)
+FIELD(CPUCFG3, RVA, 12, 1)
+FIELD(CPUCFG3, RVAMAX, 13, 4)
+
+/* cpucfg[4] bits */
+FIELD(CPUCFG4, CC_FREQ, 0, 32)
+
+/* cpucfg[5] bits */
+FIELD(CPUCFG5, CC_MUL, 0, 16)
+FIELD(CPUCFG5, CC_DIV, 16, 16)
+
+/* cpucfg[6] bits */
+FIELD(CPUCFG6, PMP, 0, 1)
+FIELD(CPUCFG6, PMVER, 1, 3)
+FIELD(CPUCFG6, PMNUM, 4, 4)
+FIELD(CPUCFG6, PMBITS, 8, 6)
+FIELD(CPUCFG6, UPM, 14, 1)
+
+/* cpucfg[16] bits */
+FIELD(CPUCFG16, L1_IUPRE, 0, 1)
+FIELD(CPUCFG16, L1_IUUNIFY, 1, 1)
+FIELD(CPUCFG16, L1_DPRE, 2, 1)
+FIELD(CPUCFG16, L2_IUPRE, 3, 1)
+FIELD(CPUCFG16, L2_IUUNIFY, 4, 1)
+FIELD(CPUCFG16, L2_IUPRIV, 5, 1)
+FIELD(CPUCFG16, L2_IUINCL, 6, 1)
+FIELD(CPUCFG16, L2_DPRE, 7, 1)
+FIELD(CPUCFG16, L2_DPRIV, 8, 1)
+FIELD(CPUCFG16, L2_DINCL, 9, 1)
+FIELD(CPUCFG16, L3_IUPRE, 10, 1)
+FIELD(CPUCFG16, L3_IUUNIFY, 11, 1)
+FIELD(CPUCFG16, L3_IUPRIV, 12, 1)
+FIELD(CPUCFG16, L3_IUINCL, 13, 1)
+FIELD(CPUCFG16, L3_DPRE, 14, 1)
+FIELD(CPUCFG16, L3_DPRIV, 15, 1)
+FIELD(CPUCFG16, L3_DINCL, 16, 1)
+
+/* cpucfg[17] bits */
+FIELD(CPUCFG17, L1IU_WAYS, 0, 16)
+FIELD(CPUCFG17, L1IU_SETS, 16, 8)
+FIELD(CPUCFG17, L1IU_SIZE, 24, 7)
+
+/* cpucfg[18] bits */
+FIELD(CPUCFG18, L1D_WAYS, 0, 16)
+FIELD(CPUCFG18, L1D_SETS, 16, 8)
+FIELD(CPUCFG18, L1D_SIZE, 24, 7)
+
+/* cpucfg[19] bits */
+FIELD(CPUCFG19, L2IU_WAYS, 0, 16)
+FIELD(CPUCFG19, L2IU_SETS, 16, 8)
+FIELD(CPUCFG19, L2IU_SIZE, 24, 7)
+
+/* cpucfg[20] bits */
+FIELD(CPUCFG20, L3IU_WAYS, 0, 16)
+FIELD(CPUCFG20, L3IU_SETS, 16, 8)
+FIELD(CPUCFG20, L3IU_SIZE, 24, 7)
+
+extern const char * const regnames[32];
+extern const char * const fregnames[32];
+
+typedef struct CPULoongArchState CPULoongArchState;
+struct CPULoongArchState {
+    uint64_t gpr[32];
+    uint64_t pc;
+
+    uint64_t fpr[32];
+    float_status fp_status;
+    bool cf[8];
+
+    /*
+     * fcsr0
+     * 31:29 |28:24 |23:21 |20:16 |15:10 |9:8 |7:5 |4:0
+     *        Cause         Flags         RM        Enables
+     */
+    uint32_t fcsr0;
+    uint32_t fcsr0_mask;
+
+    uint32_t cpucfg[21];
+
+    uint64_t lladdr; /* LL virtual address compared against SC */
+    uint64_t llval;
+
+    uint64_t badaddr;
+};
+
+/**
+ * LoongArchCPU:
+ * @env: #CPULoongArchState
+ *
+ * A LoongArch CPU.
+ */
+struct LoongArchCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUNegativeOffsetState neg;
+    CPULoongArchState env;
+};
+
+#define TYPE_LOONGARCH_CPU "loongarch-cpu"
+
+OBJECT_DECLARE_TYPE(LoongArchCPU, LoongArchCPUClass,
+                    LOONGARCH_CPU)
+
+/**
+ * LoongArchCPUClass:
+ * @parent_realize: The parent class' realize handler.
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A LoongArch CPU model.
+ */
+struct LoongArchCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    DeviceRealize parent_realize;
+    DeviceReset parent_reset;
+};
+
+#define MMU_USER_IDX 3
+
+static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
+{
+    return MMU_USER_IDX;
+}
+
+static inline void cpu_get_tb_cpu_state(CPULoongArchState *env,
+                                        target_ulong *pc,
+                                        target_ulong *cs_base,
+                                        uint32_t *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = cpu_mmu_index(env, false);
+}
+
+void loongarch_cpu_list(void);
+
+#define cpu_list loongarch_cpu_list
+
+typedef CPULoongArchState CPUArchState;
+typedef LoongArchCPU ArchCPU;
+
+#include "exec/cpu-all.h"
+
+/* Exceptions */
+enum {
+    EXCP_NONE          = -1,
+    EXCP_SYSCALL       = 0,
+    EXCP_BREAK,
+    EXCP_INE,
+    EXCP_FPE,
+
+    EXCP_LAST = EXCP_FPE,
+};
+
+#define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU
+#define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX
+#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
+
+#endif /* LOONGARCH_CPU_H */
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
new file mode 100644
index 0000000000..1e69e7d9d9
--- /dev/null
+++ b/target/loongarch/internals.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU -- internal functions and types
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_INTERNALS_H
+#define LOONGARCH_INTERNALS_H
+
+void loongarch_translate_init(void);
+
+void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
+
+void QEMU_NORETURN do_raise_exception(CPULoongArchState *env,
+                                      uint32_t exception,
+                                      uintptr_t pc);
+
+const char *loongarch_exception_name(int32_t exception);
+
+#endif
-- 
2.27.0



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

* [PATCH v14 03/26] target/loongarch: Add main translation routines
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
  2022-01-06  9:41 ` [PATCH v14 01/26] target/loongarch: Add README Song Gao
  2022-01-06  9:41 ` [PATCH v14 02/26] target/loongarch: Add core definition Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 04/26] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
                   ` (23 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This patch adds main translation routines and
basic functions for translation.

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/helper.h    |   6 ++
 target/loongarch/op_helper.c |  21 +++++
 target/loongarch/translate.c | 159 +++++++++++++++++++++++++++++++++++
 target/loongarch/translate.h |  26 ++++++
 4 files changed, 212 insertions(+)
 create mode 100644 target/loongarch/helper.h
 create mode 100644 target/loongarch/op_helper.c
 create mode 100644 target/loongarch/translate.c
 create mode 100644 target/loongarch/translate.h

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
new file mode 100644
index 0000000000..eb771c0628
--- /dev/null
+++ b/target/loongarch/helper.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+DEF_HELPER_2(raise_exception, noreturn, env, i32)
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
new file mode 100644
index 0000000000..903810951e
--- /dev/null
+++ b/target/loongarch/op_helper.c
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation helpers for QEMU.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "internals.h"
+
+/* Exceptions helpers */
+void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
+{
+    do_raise_exception(env, exception, GETPC());
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
new file mode 100644
index 0000000000..048c8953b6
--- /dev/null
+++ b/target/loongarch/translate.c
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation for QEMU - main translation routines.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "tcg/tcg-op.h"
+#include "exec/translator.h"
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+
+#include "exec/translator.h"
+#include "exec/log.h"
+#include "qemu/qemu-print.h"
+#include "translate.h"
+#include "internals.h"
+
+/* Global register indices */
+TCGv cpu_gpr[32], cpu_pc;
+static TCGv cpu_lladdr, cpu_llval;
+TCGv_i32 cpu_fcsr0;
+TCGv_i64 cpu_fpr[32];
+
+#define DISAS_STOP       DISAS_TARGET_0
+
+void generate_exception(DisasContext *ctx, int excp)
+{
+    tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+    gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
+    ctx->base.is_jmp = DISAS_NORETURN;
+}
+
+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+{
+    if (translator_use_goto_tb(&ctx->base, dest)) {
+        tcg_gen_goto_tb(n);
+        tcg_gen_movi_tl(cpu_pc, dest);
+        tcg_gen_exit_tb(ctx->base.tb, n);
+    } else {
+        tcg_gen_movi_tl(cpu_pc, dest);
+        tcg_gen_lookup_and_goto_ptr();
+    }
+}
+
+static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
+                                            CPUState *cs)
+{
+    int64_t bound;
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+    ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
+    ctx->mem_idx = ctx->base.tb->flags;
+
+    /* Bound the number of insns to execute to those left on the page.  */
+    bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
+    ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
+}
+
+static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
+{
+}
+
+static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+    tcg_gen_insn_start(ctx->base.pc_next);
+}
+
+static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
+{
+    CPULoongArchState *env = cs->env_ptr;
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+    ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
+
+    if (!decode(ctx, ctx->opcode)) {
+        qemu_log_mask(LOG_UNIMP, "Error: unkown opcode. 0x%lx: 0x%x\n",
+                      ctx->base.pc_next, ctx->opcode);
+        generate_exception(ctx, EXCP_INE);
+    }
+
+    ctx->base.pc_next += 4;
+}
+
+static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+    switch (ctx->base.is_jmp) {
+    case DISAS_STOP:
+        tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+        tcg_gen_lookup_and_goto_ptr();
+        break;
+    case DISAS_TOO_MANY:
+        gen_goto_tb(ctx, 0, ctx->base.pc_next);
+        break;
+    case DISAS_NORETURN:
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static void loongarch_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
+{
+    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
+    log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
+}
+
+static const TranslatorOps loongarch_tr_ops = {
+    .init_disas_context = loongarch_tr_init_disas_context,
+    .tb_start           = loongarch_tr_tb_start,
+    .insn_start         = loongarch_tr_insn_start,
+    .translate_insn     = loongarch_tr_translate_insn,
+    .tb_stop            = loongarch_tr_tb_stop,
+    .disas_log          = loongarch_tr_disas_log,
+};
+
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
+{
+    DisasContext ctx;
+
+    translator_loop(&loongarch_tr_ops, &ctx.base, cs, tb, max_insns);
+}
+
+void loongarch_translate_init(void)
+{
+    int i;
+
+    cpu_gpr[0] = NULL;
+    for (i = 1; i < 32; i++) {
+        cpu_gpr[i] = tcg_global_mem_new(cpu_env,
+                                        offsetof(CPULoongArchState, gpr[i]),
+                                        regnames[i]);
+    }
+
+    for (i = 0; i < 32; i++) {
+        int off = offsetof(CPULoongArchState, fpr[i]);
+        cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
+    }
+
+    cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPULoongArchState, pc), "pc");
+    cpu_fcsr0 = tcg_global_mem_new_i32(cpu_env,
+                    offsetof(CPULoongArchState, fcsr0), "fcsr0");
+    cpu_lladdr = tcg_global_mem_new(cpu_env,
+                    offsetof(CPULoongArchState, lladdr), "lladdr");
+    cpu_llval = tcg_global_mem_new(cpu_env,
+                    offsetof(CPULoongArchState, llval), "llval");
+}
+
+void restore_state_to_opc(CPULoongArchState *env, TranslationBlock *tb,
+                          target_ulong *data)
+{
+    env->pc = data[0];
+}
diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
new file mode 100644
index 0000000000..6cc7f1a7cd
--- /dev/null
+++ b/target/loongarch/translate.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch translation routines.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef TARGET_LOONGARCH_TRANSLATE_H
+#define TARGET_LOONGARCH_TRANSLATE_H
+
+#include "exec/translator.h"
+
+typedef struct DisasContext {
+    DisasContextBase base;
+    target_ulong page_start;
+    uint32_t opcode;
+    int mem_idx;
+} DisasContext;
+
+void generate_exception(DisasContext *ctx, int excp);
+
+extern TCGv cpu_gpr[32], cpu_pc;
+extern TCGv_i32 cpu_fscr0;
+extern TCGv_i64 cpu_fpr[32];
+
+#endif
-- 
2.27.0



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

* [PATCH v14 04/26] target/loongarch: Add fixed point arithmetic instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (2 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 03/26] target/loongarch: Add main translation routines Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 05/26] target/loongarch: Add fixed point shift " Song Gao
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- ADD.{W/D}, SUB.{W/D}
- ADDI.{W/D}, ADDU16ID
- ALSL.{W[U]/D}
- LU12I.W, LU32I.D LU52I.D
- SLT[U], SLT[U]I
- PCADDI, PCADDU12I, PCADDU18I, PCALAU12I
- AND, OR, NOR, XOR, ANDN, ORN
- MUL.{W/D}, MULH.{W[U]/D[U]}
- MULW.D.W[U]
- DIV.{W[U]/D[U]}, MOD.{W[U]/D[U]}
- ANDI, ORI, XORI

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/insn_trans/trans_arith.c.inc | 304 ++++++++++++++++++
 target/loongarch/insns.decode                 |  79 +++++
 target/loongarch/translate.c                  |  83 +++++
 target/loongarch/translate.h                  |  19 ++
 4 files changed, 485 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_arith.c.inc
 create mode 100644 target/loongarch/insns.decode

diff --git a/target/loongarch/insn_trans/trans_arith.c.inc b/target/loongarch/insn_trans/trans_arith.c.inc
new file mode 100644
index 0000000000..8e45eadbc8
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_arith.c.inc
@@ -0,0 +1,304 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_rrr(DisasContext *ctx, arg_rrr *a,
+                    DisasExtend src1_ext, DisasExtend src2_ext,
+                    DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+    TCGv src1 = gpr_src(ctx, a->rj, src1_ext);
+    TCGv src2 = gpr_src(ctx, a->rk, src2_ext);
+
+    func(dest, src1, src2);
+    gen_set_gpr(a->rd, dest, dst_ext);
+
+    return true;
+}
+
+static bool gen_rri_v(DisasContext *ctx, arg_rr_i *a,
+                      DisasExtend src_ext, DisasExtend dst_ext,
+                      void (*func)(TCGv, TCGv, TCGv))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+    TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+    TCGv src2 = tcg_constant_tl(a->imm);
+
+    func(dest, src1, src2);
+    gen_set_gpr(a->rd, dest, dst_ext);
+
+    return true;
+}
+
+static bool gen_rri_c(DisasContext *ctx, arg_rr_i *a,
+                      DisasExtend src_ext, DisasExtend dst_ext,
+                      void (*func)(TCGv, TCGv, target_long))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+    TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+    func(dest, src1, a->imm);
+    gen_set_gpr(a->rd, dest, dst_ext);
+
+    return true;
+}
+
+static bool gen_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
+                       DisasExtend src_ext, DisasExtend dst_ext,
+                       void (*func)(TCGv, TCGv, TCGv, target_long))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+    TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+    TCGv src2 = gpr_src(ctx, a->rk, src_ext);
+
+    func(dest, src1, src2, a->sa);
+    gen_set_gpr(a->rd, dest, dst_ext);
+
+    return true;
+}
+
+static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+    tcg_gen_movi_tl(dest, a->imm << 12);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+static bool gen_pc(DisasContext *ctx, arg_r_i *a,
+                   target_ulong (*func)(target_ulong, int))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    target_ulong addr = func(ctx->base.pc_next, a->imm);
+
+    tcg_gen_movi_tl(dest, addr);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+static void gen_slt(TCGv dest, TCGv src1, TCGv src2)
+{
+    tcg_gen_setcond_tl(TCG_COND_LT, dest, src1, src2);
+}
+
+static void gen_sltu(TCGv dest, TCGv src1, TCGv src2)
+{
+    tcg_gen_setcond_tl(TCG_COND_LTU, dest, src1, src2);
+}
+
+static void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2)
+{
+    tcg_gen_mul_i64(dest, src1, src2);
+    tcg_gen_sari_i64(dest, dest, 32);
+}
+
+static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv discard = tcg_temp_new();
+    tcg_gen_muls2_tl(discard, dest, src1, src2);
+    tcg_temp_free(discard);
+}
+
+static void gen_mulh_du(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv discard = tcg_temp_new();
+    tcg_gen_mulu2_tl(discard, dest, src1, src2);
+    tcg_temp_free(discard);
+}
+
+static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+    TCGv zero = tcg_constant_tl(0);
+
+    /*
+     * If min / -1, set the divisor to 1.
+     * This avoids potential host overflow trap and produces min.
+     * If x / 0, set the divisor to 1.
+     * This avoids potential host overflow trap;
+     * the required result is undefined.
+     */
+    tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, INT64_MIN);
+    tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1);
+    tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0);
+    tcg_gen_and_tl(ret, ret, t0);
+    tcg_gen_or_tl(ret, ret, t1);
+    tcg_gen_movcond_tl(TCG_COND_NE, ret, ret, zero, ret, src2);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+static void prep_divisor_du(TCGv ret, TCGv src2)
+{
+    TCGv zero = tcg_constant_tl(0);
+    TCGv one = tcg_constant_tl(1);
+
+    /*
+     * If x / 0, set the divisor to 1.
+     * This avoids potential host overflow trap;
+     * the required result is undefined.
+     */
+    tcg_gen_movcond_tl(TCG_COND_EQ, ret, src2, zero, one, src2);
+}
+
+static void gen_div_d(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    prep_divisor_d(t0, src1, src2);
+    tcg_gen_div_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_rem_d(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    prep_divisor_d(t0, src1, src2);
+    tcg_gen_rem_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_div_du(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    prep_divisor_du(t0, src2);
+    tcg_gen_divu_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_rem_du(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    prep_divisor_du(t0, src2);
+    tcg_gen_remu_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_div_w(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    /* We need not check for integer overflow for div_w. */
+    prep_divisor_du(t0, src2);
+    tcg_gen_div_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_rem_w(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    /* We need not check for integer overflow for rem_w. */
+    prep_divisor_du(t0, src2);
+    tcg_gen_rem_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_alsl(TCGv dest, TCGv src1, TCGv src2, target_long sa)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_shli_tl(t0, src1, sa);
+    tcg_gen_add_tl(dest, t0, src2);
+    tcg_temp_free(t0);
+}
+
+static bool trans_lu32i_d(DisasContext *ctx, arg_lu32i_d *a)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE);
+    TCGv src2 = tcg_constant_tl(a->imm);
+
+    tcg_gen_deposit_tl(dest, src1, src2, 32, 32);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+static bool trans_lu52i_d(DisasContext *ctx, arg_lu52i_d *a)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = tcg_constant_tl(a->imm);
+
+    tcg_gen_deposit_tl(dest, src1, src2, 52, 12);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+static target_ulong gen_pcaddi(target_ulong pc, int imm)
+{
+    return pc + (imm << 2);
+}
+
+static target_ulong gen_pcalau12i(target_ulong pc, int imm)
+{
+    return (pc + (imm << 12)) & ~0xfff;
+}
+
+static target_ulong gen_pcaddu12i(target_ulong pc, int imm)
+{
+    return pc + (imm << 12);
+}
+
+static target_ulong gen_pcaddu18i(target_ulong pc, int imm)
+{
+    return pc + ((target_ulong)(imm) << 18);
+}
+
+static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+    tcg_gen_addi_tl(dest, src1, a->imm << 16);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+TRANS(add_w, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_add_tl)
+TRANS(add_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_add_tl)
+TRANS(sub_w, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_sub_tl)
+TRANS(sub_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_sub_tl)
+TRANS(and, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_and_tl)
+TRANS(or, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_or_tl)
+TRANS(xor, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_xor_tl)
+TRANS(nor, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_nor_tl)
+TRANS(andn, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_andc_tl)
+TRANS(orn, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_orc_tl)
+TRANS(slt, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_slt)
+TRANS(sltu, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sltu)
+TRANS(mul_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, tcg_gen_mul_tl)
+TRANS(mul_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_mul_tl)
+TRANS(mulh_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w)
+TRANS(mulh_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_w)
+TRANS(mulh_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d)
+TRANS(mulh_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du)
+TRANS(mulw_d_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl)
+TRANS(mulw_d_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, tcg_gen_mul_tl)
+TRANS(div_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_div_w)
+TRANS(mod_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_rem_w)
+TRANS(div_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
+TRANS(mod_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_rem_du)
+TRANS(div_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_d)
+TRANS(mod_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_d)
+TRANS(div_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_du)
+TRANS(mod_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_du)
+TRANS(slti, gen_rri_v, EXT_NONE, EXT_NONE, gen_slt)
+TRANS(sltui, gen_rri_v, EXT_NONE, EXT_NONE, gen_sltu)
+TRANS(addi_w, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_addi_tl)
+TRANS(addi_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_addi_tl)
+TRANS(alsl_w, gen_rrr_sa, EXT_NONE, EXT_SIGN, gen_alsl)
+TRANS(alsl_wu, gen_rrr_sa, EXT_NONE, EXT_ZERO, gen_alsl)
+TRANS(alsl_d, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_alsl)
+TRANS(pcaddi, gen_pc, gen_pcaddi)
+TRANS(pcalau12i, gen_pc, gen_pcalau12i)
+TRANS(pcaddu12i, gen_pc, gen_pcaddu12i)
+TRANS(pcaddu18i, gen_pc, gen_pcaddu18i)
+TRANS(andi, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_andi_tl)
+TRANS(ori, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_ori_tl)
+TRANS(xori, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_xori_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
new file mode 100644
index 0000000000..8579c11984
--- /dev/null
+++ b/target/loongarch/insns.decode
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# LoongArch instruction decode definitions.
+#
+# Copyright (c) 2021 Loongson Technology Corporation Limited
+#
+
+#
+# Fields
+#
+%sa2p1     15:2         !function=plus_1
+
+#
+# Argument sets
+#
+&r_i          rd imm
+&rrr          rd rj rk
+&rr_i         rd rj imm
+&rrr_sa       rd rj rk sa
+
+#
+# Formats
+#
+@rrr               .... ........ ..... rk:5 rj:5 rd:5    &rrr
+@r_i20                          .... ... imm:s20 rd:5    &r_i
+@rr_i12                 .... ...... imm:s12 rj:5 rd:5    &rr_i
+@rr_ui12                 .... ...... imm:12 rj:5 rd:5    &rr_i
+@rr_i16                     .... .. imm:s16 rj:5 rd:5    &rr_i
+@rrr_sa2p1        .... ........ ... .. rk:5 rj:5 rd:5    &rrr_sa  sa=%sa2p1
+
+#
+# Fixed point arithmetic operation instruction
+#
+add_w           0000 00000001 00000 ..... ..... .....    @rrr
+add_d           0000 00000001 00001 ..... ..... .....    @rrr
+sub_w           0000 00000001 00010 ..... ..... .....    @rrr
+sub_d           0000 00000001 00011 ..... ..... .....    @rrr
+slt             0000 00000001 00100 ..... ..... .....    @rrr
+sltu            0000 00000001 00101 ..... ..... .....    @rrr
+slti            0000 001000 ............ ..... .....     @rr_i12
+sltui           0000 001001 ............ ..... .....     @rr_i12
+nor             0000 00000001 01000 ..... ..... .....    @rrr
+and             0000 00000001 01001 ..... ..... .....    @rrr
+or              0000 00000001 01010 ..... ..... .....    @rrr
+xor             0000 00000001 01011 ..... ..... .....    @rrr
+orn             0000 00000001 01100 ..... ..... .....    @rrr
+andn            0000 00000001 01101 ..... ..... .....    @rrr
+mul_w           0000 00000001 11000 ..... ..... .....    @rrr
+mulh_w          0000 00000001 11001 ..... ..... .....    @rrr
+mulh_wu         0000 00000001 11010 ..... ..... .....    @rrr
+mul_d           0000 00000001 11011 ..... ..... .....    @rrr
+mulh_d          0000 00000001 11100 ..... ..... .....    @rrr
+mulh_du         0000 00000001 11101 ..... ..... .....    @rrr
+mulw_d_w        0000 00000001 11110 ..... ..... .....    @rrr
+mulw_d_wu       0000 00000001 11111 ..... ..... .....    @rrr
+div_w           0000 00000010 00000 ..... ..... .....    @rrr
+mod_w           0000 00000010 00001 ..... ..... .....    @rrr
+div_wu          0000 00000010 00010 ..... ..... .....    @rrr
+mod_wu          0000 00000010 00011 ..... ..... .....    @rrr
+div_d           0000 00000010 00100 ..... ..... .....    @rrr
+mod_d           0000 00000010 00101 ..... ..... .....    @rrr
+div_du          0000 00000010 00110 ..... ..... .....    @rrr
+mod_du          0000 00000010 00111 ..... ..... .....    @rrr
+alsl_w          0000 00000000 010 .. ..... ..... .....   @rrr_sa2p1
+alsl_wu         0000 00000000 011 .. ..... ..... .....   @rrr_sa2p1
+alsl_d          0000 00000010 110 .. ..... ..... .....   @rrr_sa2p1
+lu12i_w         0001 010 .................... .....      @r_i20
+lu32i_d         0001 011 .................... .....      @r_i20
+lu52i_d         0000 001100 ............ ..... .....     @rr_i12
+pcaddi          0001 100 .................... .....      @r_i20
+pcalau12i       0001 101 .................... .....      @r_i20
+pcaddu12i       0001 110 .................... .....      @r_i20
+pcaddu18i       0001 111 .................... .....      @r_i20
+addi_w          0000 001010 ............ ..... .....     @rr_i12
+addi_d          0000 001011 ............ ..... .....     @rr_i12
+addu16i_d       0001 00 ................ ..... .....     @rr_i16
+andi            0000 001101 ............ ..... .....     @rr_ui12
+ori             0000 001110 ............ ..... .....     @rr_ui12
+xori            0000 001111 ............ ..... .....     @rr_ui12
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 048c8953b6..3de18efbf2 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -26,6 +26,11 @@ TCGv_i64 cpu_fpr[32];
 
 #define DISAS_STOP       DISAS_TARGET_0
 
+static inline int plus_1(DisasContext *ctx, int x)
+{
+    return x + 1;
+}
+
 void generate_exception(DisasContext *ctx, int excp)
 {
     tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
@@ -57,6 +62,11 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
     /* Bound the number of insns to execute to those left on the page.  */
     bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
     ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
+
+    ctx->ntemp = 0;
+    memset(ctx->temp, 0, sizeof(ctx->temp));
+
+    ctx->zero = tcg_constant_tl(0);
 }
 
 static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
@@ -70,6 +80,73 @@ static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
     tcg_gen_insn_start(ctx->base.pc_next);
 }
 
+/*
+ * Wrappers for getting reg values.
+ *
+ * The $zero register does not have cpu_gpr[0] allocated -- we supply the
+ * constant zero as a source, and an uninitialized sink as destination.
+ *
+ * Further, we may provide an extension for word operations.
+ */
+static TCGv temp_new(DisasContext *ctx)
+{
+    assert(ctx->ntemp < ARRAY_SIZE(ctx->temp));
+    return ctx->temp[ctx->ntemp++] = tcg_temp_new();
+}
+
+static TCGv gpr_src(DisasContext *ctx, int reg_num, DisasExtend src_ext)
+{
+    TCGv t;
+
+    if (reg_num == 0) {
+        return ctx->zero;
+    }
+
+    switch (src_ext) {
+    case EXT_NONE:
+        return cpu_gpr[reg_num];
+    case EXT_SIGN:
+        t = temp_new(ctx);
+        tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
+        return t;
+    case EXT_ZERO:
+        t = temp_new(ctx);
+        tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
+        return t;
+    }
+    g_assert_not_reached();
+}
+
+static TCGv gpr_dst(DisasContext *ctx, int reg_num, DisasExtend dst_ext)
+{
+    if (reg_num == 0 || dst_ext) {
+        return temp_new(ctx);
+    }
+    return cpu_gpr[reg_num];
+}
+
+static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
+{
+    if (reg_num != 0) {
+        switch (dst_ext) {
+        case EXT_NONE:
+            tcg_gen_mov_tl(cpu_gpr[reg_num], t);
+            break;
+        case EXT_SIGN:
+            tcg_gen_ext32s_tl(cpu_gpr[reg_num], t);
+            break;
+        case EXT_ZERO:
+            tcg_gen_ext32u_tl(cpu_gpr[reg_num], t);
+            break;
+        default:
+            g_assert_not_reached();
+        }
+    }
+}
+
+#include "decode-insns.c.inc"
+#include "insn_trans/trans_arith.c.inc"
+
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
     CPULoongArchState *env = cs->env_ptr;
@@ -83,6 +160,12 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
         generate_exception(ctx, EXCP_INE);
     }
 
+    for (int i = ctx->ntemp - 1; i >= 0; --i) {
+        tcg_temp_free(ctx->temp[i]);
+        ctx->temp[i] = NULL;
+    }
+    ctx->ntemp = 0;
+
     ctx->base.pc_next += 4;
 }
 
diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
index 6cc7f1a7cd..9cc12512d1 100644
--- a/target/loongarch/translate.h
+++ b/target/loongarch/translate.h
@@ -10,11 +10,30 @@
 
 #include "exec/translator.h"
 
+#define TRANS(NAME, FUNC, ...) \
+    static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+    { return FUNC(ctx, a, __VA_ARGS__); }
+
+/*
+ * If an operation is being performed on less than TARGET_LONG_BITS,
+ * it may require the inputs to be sign- or zero-extended; which will
+ * depend on the exact operation being performed.
+ */
+typedef enum {
+    EXT_NONE,
+    EXT_SIGN,
+    EXT_ZERO,
+} DisasExtend;
+
 typedef struct DisasContext {
     DisasContextBase base;
     target_ulong page_start;
     uint32_t opcode;
     int mem_idx;
+    TCGv zero;
+    /* Space for 3 operands plus 1 extra for address computation. */
+    TCGv temp[4];
+    uint8_t ntemp;
 } DisasContext;
 
 void generate_exception(DisasContext *ctx, int excp);
-- 
2.27.0



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

* [PATCH v14 05/26] target/loongarch: Add fixed point shift instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (3 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 04/26] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 06/26] target/loongarch: Add fixed point bit " Song Gao
                   ` (21 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- SLL.W, SRL.W, SRA.W, ROTR.W
- SLLI.W, SRLI.W, SRAI.W, ROTRI.W
- SLL.D, SRL.D, SRA.D, ROTR.D
- SLLI.D, SRLI.D, SRAI.D, ROTRI.D

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/insn_trans/trans_shift.c.inc | 106 ++++++++++++++++++
 target/loongarch/insns.decode                 |  22 ++++
 target/loongarch/translate.c                  |   1 +
 3 files changed, 129 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_shift.c.inc

diff --git a/target/loongarch/insn_trans/trans_shift.c.inc b/target/loongarch/insn_trans/trans_shift.c.inc
new file mode 100644
index 0000000000..5260af2337
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_shift.c.inc
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static void gen_sll_w(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_andi_tl(t0, src2, 0x1f);
+    tcg_gen_shl_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_srl_w(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_andi_tl(t0, src2, 0x1f);
+    tcg_gen_shr_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_sra_w(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_andi_tl(t0, src2, 0x1f);
+    tcg_gen_sar_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_sll_d(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_andi_tl(t0, src2, 0x3f);
+    tcg_gen_shl_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_srl_d(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_andi_tl(t0, src2, 0x3f);
+    tcg_gen_shr_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_sra_d(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_andi_tl(t0, src2, 0x3f);
+    tcg_gen_sar_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static void gen_rotr_w(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv_i32 t1 = tcg_temp_new_i32();
+    TCGv_i32 t2 = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_andi_tl(t0, src2, 0x1f);
+
+    tcg_gen_trunc_tl_i32(t1, src1);
+    tcg_gen_trunc_tl_i32(t2, t0);
+
+    tcg_gen_rotr_i32(t1, t1, t2);
+    tcg_gen_ext_i32_tl(dest, t1);
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free(t0);
+}
+
+static void gen_rotr_d(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_andi_tl(t0, src2, 0x3f);
+    tcg_gen_rotr_tl(dest, src1, t0);
+    tcg_temp_free(t0);
+}
+
+static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
+
+    tcg_gen_sextract_tl(dest, src1, a->imm, 32 - a->imm);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+TRANS(sll_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sll_w)
+TRANS(srl_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_srl_w)
+TRANS(sra_w, gen_rrr, EXT_SIGN, EXT_NONE, EXT_SIGN, gen_sra_w)
+TRANS(sll_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d)
+TRANS(srl_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d)
+TRANS(sra_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d)
+TRANS(rotr_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w)
+TRANS(rotr_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d)
+TRANS(slli_w, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_shli_tl)
+TRANS(slli_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shli_tl)
+TRANS(srli_w, gen_rri_c, EXT_ZERO, EXT_SIGN, tcg_gen_shri_tl)
+TRANS(srli_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shri_tl)
+TRANS(srai_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_sari_tl)
+TRANS(rotri_w, gen_rri_v, EXT_NONE, EXT_NONE, gen_rotr_w)
+TRANS(rotri_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_rotri_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8579c11984..673aee4be5 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -23,6 +23,8 @@
 #
 @rrr               .... ........ ..... rk:5 rj:5 rd:5    &rrr
 @r_i20                          .... ... imm:s20 rd:5    &r_i
+@rr_ui5           .... ........ ..... imm:5 rj:5 rd:5    &rr_i
+@rr_ui6            .... ........ .... imm:6 rj:5 rd:5    &rr_i
 @rr_i12                 .... ...... imm:s12 rj:5 rd:5    &rr_i
 @rr_ui12                 .... ...... imm:12 rj:5 rd:5    &rr_i
 @rr_i16                     .... .. imm:s16 rj:5 rd:5    &rr_i
@@ -77,3 +79,23 @@ addu16i_d       0001 00 ................ ..... .....     @rr_i16
 andi            0000 001101 ............ ..... .....     @rr_ui12
 ori             0000 001110 ............ ..... .....     @rr_ui12
 xori            0000 001111 ............ ..... .....     @rr_ui12
+
+#
+# Fixed point shift operation instruction
+#
+sll_w           0000 00000001 01110 ..... ..... .....    @rrr
+srl_w           0000 00000001 01111 ..... ..... .....    @rrr
+sra_w           0000 00000001 10000 ..... ..... .....    @rrr
+sll_d           0000 00000001 10001 ..... ..... .....    @rrr
+srl_d           0000 00000001 10010 ..... ..... .....    @rrr
+sra_d           0000 00000001 10011 ..... ..... .....    @rrr
+rotr_w          0000 00000001 10110 ..... ..... .....    @rrr
+rotr_d          0000 00000001 10111 ..... ..... .....    @rrr
+slli_w          0000 00000100 00001 ..... ..... .....    @rr_ui5
+slli_d          0000 00000100 0001 ...... ..... .....    @rr_ui6
+srli_w          0000 00000100 01001 ..... ..... .....    @rr_ui5
+srli_d          0000 00000100 0101 ...... ..... .....    @rr_ui6
+srai_w          0000 00000100 10001 ..... ..... .....    @rr_ui5
+srai_d          0000 00000100 1001 ...... ..... .....    @rr_ui6
+rotri_w         0000 00000100 11001 ..... ..... .....    @rr_ui5
+rotri_d         0000 00000100 1101 ...... ..... .....    @rr_ui6
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 3de18efbf2..f90b63ad83 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -146,6 +146,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 
 #include "decode-insns.c.inc"
 #include "insn_trans/trans_arith.c.inc"
+#include "insn_trans/trans_shift.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 06/26] target/loongarch: Add fixed point bit instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (4 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 05/26] target/loongarch: Add fixed point shift " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 07/26] target/loongarch: Add fixed point load/store " Song Gao
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- EXT.W.{B/H}
- CL{O/Z}.{W/D}, CT{O/Z}.{W/D}
- BYTEPICK.{W/D}
- REVB.{2H/4H/2W/D}
- REVH.{2W/D}
- BITREV.{4B/8B}, BITREV.{W/D}
- BSTRINS.{W/D}, BSTRPICK.{W/D}
- MASKEQZ, MASKNEZ

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/helper.h                   |   4 +
 target/loongarch/insn_trans/trans_bit.c.inc | 212 ++++++++++++++++++++
 target/loongarch/insns.decode               |  39 ++++
 target/loongarch/op_helper.c                |  21 ++
 target/loongarch/translate.c                |   1 +
 5 files changed, 277 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_bit.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index eb771c0628..04e0245d5e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -4,3 +4,7 @@
  */
 
 DEF_HELPER_2(raise_exception, noreturn, env, i32)
+
+DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target/loongarch/insn_trans/trans_bit.c.inc b/target/loongarch/insn_trans/trans_bit.c.inc
new file mode 100644
index 0000000000..9337714ec4
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_bit.c.inc
@@ -0,0 +1,212 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_rr(DisasContext *ctx, arg_rr *a,
+                   DisasExtend src_ext, DisasExtend dst_ext,
+                   void (*func)(TCGv, TCGv))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+    TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+    func(dest, src1);
+    gen_set_gpr(a->rd, dest, dst_ext);
+
+    return true;
+}
+
+static void gen_bytepick_w(TCGv dest, TCGv src1, TCGv src2, target_long sa)
+{
+    tcg_gen_concat_tl_i64(dest, src1, src2);
+    tcg_gen_sextract_i64(dest, dest, (32 - sa * 8), 32);
+}
+
+static void gen_bytepick_d(TCGv dest, TCGv src1, TCGv src2, target_long sa)
+{
+    tcg_gen_extract2_i64(dest, src1, src2, (64 - sa * 8));
+}
+
+static void gen_bstrins(TCGv dest, TCGv src1,
+                        unsigned int ls, unsigned int len)
+{
+    tcg_gen_deposit_tl(dest, dest, src1, ls, len);
+}
+
+static bool gen_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
+                         DisasExtend src_ext, DisasExtend dst_ext,
+                         void (*func)(TCGv, TCGv, unsigned int, unsigned int))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+    TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+    if (a->ls > a->ms) {
+        return false;
+    }
+
+    func(dest, src1, a->ls, a->ms - a->ls + 1);
+    gen_set_gpr(a->rd, dest, dst_ext);
+
+    return true;
+}
+
+static void gen_clz_w(TCGv dest, TCGv src1)
+{
+    tcg_gen_clzi_tl(dest, src1, TARGET_LONG_BITS);
+    tcg_gen_subi_tl(dest, dest, TARGET_LONG_BITS - 32);
+}
+
+static void gen_clo_w(TCGv dest, TCGv src1)
+{
+    tcg_gen_not_tl(dest, src1);
+    tcg_gen_ext32u_tl(dest, dest);
+    gen_clz_w(dest, dest);
+}
+
+static void gen_ctz_w(TCGv dest, TCGv src1)
+{
+    tcg_gen_ori_tl(dest, src1, (target_ulong)MAKE_64BIT_MASK(32, 32));
+    tcg_gen_ctzi_tl(dest, dest, TARGET_LONG_BITS);
+}
+
+static void gen_cto_w(TCGv dest, TCGv src1)
+{
+    tcg_gen_not_tl(dest, src1);
+    gen_ctz_w(dest, dest);
+}
+
+static void gen_clz_d(TCGv dest, TCGv src1)
+{
+    tcg_gen_clzi_i64(dest, src1, TARGET_LONG_BITS);
+}
+
+static void gen_clo_d(TCGv dest, TCGv src1)
+{
+    tcg_gen_not_tl(dest, src1);
+    gen_clz_d(dest, dest);
+}
+
+static void gen_ctz_d(TCGv dest, TCGv src1)
+{
+    tcg_gen_ctzi_tl(dest, src1, TARGET_LONG_BITS);
+}
+
+static void gen_cto_d(TCGv dest, TCGv src1)
+{
+    tcg_gen_not_tl(dest, src1);
+    gen_ctz_d(dest, dest);
+}
+
+static void gen_revb_2w(TCGv dest, TCGv src1)
+{
+    tcg_gen_bswap64_i64(dest, src1);
+    tcg_gen_rotri_i64(dest, dest, 32);
+}
+
+static void gen_revb_2h(TCGv dest, TCGv src1)
+{
+    TCGv mask = tcg_constant_tl(0x00FF00FF);
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+
+    tcg_gen_shri_tl(t0, src1, 8);
+    tcg_gen_and_tl(t0, t0, mask);
+    tcg_gen_and_tl(t1, src1, mask);
+    tcg_gen_shli_tl(t1, t1, 8);
+    tcg_gen_or_tl(dest, t0, t1);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+static void gen_revb_4h(TCGv dest, TCGv src1)
+{
+    TCGv mask = tcg_constant_tl(0x00FF00FF00FF00FFULL);
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+
+    tcg_gen_shri_tl(t0, src1, 8);
+    tcg_gen_and_tl(t0, t0, mask);
+    tcg_gen_and_tl(t1, src1, mask);
+    tcg_gen_shli_tl(t1, t1, 8);
+    tcg_gen_or_tl(dest, t0, t1);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+static void gen_revh_2w(TCGv dest, TCGv src1)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 mask = tcg_constant_i64(0x0000ffff0000ffffull);
+
+    tcg_gen_shri_i64(t0, src1, 16);
+    tcg_gen_and_i64(t1, src1, mask);
+    tcg_gen_and_i64(t0, t0, mask);
+    tcg_gen_shli_i64(t1, t1, 16);
+    tcg_gen_or_i64(dest, t1, t0);
+
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
+}
+
+static void gen_revh_d(TCGv dest, TCGv src1)
+{
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+    TCGv mask = tcg_constant_tl(0x0000FFFF0000FFFFULL);
+
+    tcg_gen_shri_tl(t1, src1, 16);
+    tcg_gen_and_tl(t1, t1, mask);
+    tcg_gen_and_tl(t0, src1, mask);
+    tcg_gen_shli_tl(t0, t0, 16);
+    tcg_gen_or_tl(t0, t0, t1);
+    tcg_gen_rotri_tl(dest, t0, 32);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+static void gen_maskeqz(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv zero = tcg_constant_tl(0);
+
+    tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, zero, zero, src1);
+}
+
+static void gen_masknez(TCGv dest, TCGv src1, TCGv src2)
+{
+    TCGv zero = tcg_constant_tl(0);
+
+    tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, zero, zero, src1);
+}
+
+TRANS(ext_w_h, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext16s_tl)
+TRANS(ext_w_b, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext8s_tl)
+TRANS(clo_w, gen_rr, EXT_NONE, EXT_NONE, gen_clo_w)
+TRANS(clz_w, gen_rr, EXT_ZERO, EXT_NONE, gen_clz_w)
+TRANS(cto_w, gen_rr, EXT_NONE, EXT_NONE, gen_cto_w)
+TRANS(ctz_w, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_w)
+TRANS(clo_d, gen_rr, EXT_NONE, EXT_NONE, gen_clo_d)
+TRANS(clz_d, gen_rr, EXT_NONE, EXT_NONE, gen_clz_d)
+TRANS(cto_d, gen_rr, EXT_NONE, EXT_NONE, gen_cto_d)
+TRANS(ctz_d, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_d)
+TRANS(revb_2h, gen_rr, EXT_NONE, EXT_SIGN, gen_revb_2h)
+TRANS(revb_4h, gen_rr, EXT_NONE, EXT_NONE, gen_revb_4h)
+TRANS(revb_2w, gen_rr, EXT_NONE, EXT_NONE, gen_revb_2w)
+TRANS(revb_d, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_bswap64_i64)
+TRANS(revh_2w, gen_rr, EXT_NONE, EXT_NONE, gen_revh_2w)
+TRANS(revh_d, gen_rr, EXT_NONE, EXT_NONE, gen_revh_d)
+TRANS(bitrev_4b, gen_rr, EXT_ZERO, EXT_SIGN, gen_helper_bitswap)
+TRANS(bitrev_8b, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitswap)
+TRANS(bitrev_w, gen_rr, EXT_NONE, EXT_SIGN, gen_helper_bitrev_w)
+TRANS(bitrev_d, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitrev_d)
+TRANS(maskeqz, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_maskeqz)
+TRANS(masknez, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_masknez)
+TRANS(bytepick_w, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_w)
+TRANS(bytepick_d, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_d)
+TRANS(bstrins_w, gen_rr_ms_ls, EXT_NONE, EXT_NONE, gen_bstrins)
+TRANS(bstrins_d, gen_rr_ms_ls, EXT_NONE, EXT_NONE, gen_bstrins)
+TRANS(bstrpick_w, gen_rr_ms_ls, EXT_NONE, EXT_SIGN, tcg_gen_extract_tl)
+TRANS(bstrpick_d, gen_rr_ms_ls, EXT_NONE, EXT_NONE, tcg_gen_extract_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 673aee4be5..b0bed5531b 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -14,13 +14,16 @@
 # Argument sets
 #
 &r_i          rd imm
+&rr           rd rj
 &rrr          rd rj rk
 &rr_i         rd rj imm
 &rrr_sa       rd rj rk sa
+&rr_ms_ls     rd rj ms ls
 
 #
 # Formats
 #
+@rr               .... ........ ..... ..... rj:5 rd:5    &rr
 @rrr               .... ........ ..... rk:5 rj:5 rd:5    &rrr
 @r_i20                          .... ... imm:s20 rd:5    &r_i
 @rr_ui5           .... ........ ..... imm:5 rj:5 rd:5    &rr_i
@@ -29,6 +32,10 @@
 @rr_ui12                 .... ...... imm:12 rj:5 rd:5    &rr_i
 @rr_i16                     .... .. imm:s16 rj:5 rd:5    &rr_i
 @rrr_sa2p1        .... ........ ... .. rk:5 rj:5 rd:5    &rrr_sa  sa=%sa2p1
+@rrr_sa2        .... ........ ... sa:2 rk:5 rj:5 rd:5    &rrr_sa
+@rrr_sa3         .... ........ .. sa:3 rk:5 rj:5 rd:5    &rrr_sa
+@rr_2bw            .... ....... ms:5 . ls:5 rj:5 rd:5    &rr_ms_ls
+@rr_2bd               .... ...... ms:6 ls:6 rj:5 rd:5    &rr_ms_ls
 
 #
 # Fixed point arithmetic operation instruction
@@ -99,3 +106,35 @@ srai_w          0000 00000100 10001 ..... ..... .....    @rr_ui5
 srai_d          0000 00000100 1001 ...... ..... .....    @rr_ui6
 rotri_w         0000 00000100 11001 ..... ..... .....    @rr_ui5
 rotri_d         0000 00000100 1101 ...... ..... .....    @rr_ui6
+
+#
+# Fixed point bit operation instruction
+#
+ext_w_h         0000 00000000 00000 10110 ..... .....    @rr
+ext_w_b         0000 00000000 00000 10111 ..... .....    @rr
+clo_w           0000 00000000 00000 00100 ..... .....    @rr
+clz_w           0000 00000000 00000 00101 ..... .....    @rr
+cto_w           0000 00000000 00000 00110 ..... .....    @rr
+ctz_w           0000 00000000 00000 00111 ..... .....    @rr
+clo_d           0000 00000000 00000 01000 ..... .....    @rr
+clz_d           0000 00000000 00000 01001 ..... .....    @rr
+cto_d           0000 00000000 00000 01010 ..... .....    @rr
+ctz_d           0000 00000000 00000 01011 ..... .....    @rr
+revb_2h         0000 00000000 00000 01100 ..... .....    @rr
+revb_4h         0000 00000000 00000 01101 ..... .....    @rr
+revb_2w         0000 00000000 00000 01110 ..... .....    @rr
+revb_d          0000 00000000 00000 01111 ..... .....    @rr
+revh_2w         0000 00000000 00000 10000 ..... .....    @rr
+revh_d          0000 00000000 00000 10001 ..... .....    @rr
+bitrev_4b       0000 00000000 00000 10010 ..... .....    @rr
+bitrev_8b       0000 00000000 00000 10011 ..... .....    @rr
+bitrev_w        0000 00000000 00000 10100 ..... .....    @rr
+bitrev_d        0000 00000000 00000 10101 ..... .....    @rr
+bytepick_w      0000 00000000 100 .. ..... ..... .....   @rrr_sa2
+bytepick_d      0000 00000000 11 ... ..... ..... .....   @rrr_sa3
+maskeqz         0000 00000001 00110 ..... ..... .....    @rrr
+masknez         0000 00000001 00111 ..... ..... .....    @rrr
+bstrins_w       0000 0000011 ..... 0 ..... ..... .....   @rr_2bw
+bstrpick_w      0000 0000011 ..... 1 ..... ..... .....   @rr_2bw
+bstrins_d       0000 000010 ...... ...... ..... .....    @rr_2bd
+bstrpick_d      0000 000011 ...... ...... ..... .....    @rr_2bd
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 903810951e..f4b22c70a0 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -19,3 +19,24 @@ void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
 {
     do_raise_exception(env, exception, GETPC());
 }
+
+target_ulong helper_bitrev_w(target_ulong rj)
+{
+    return (int32_t)revbit32(rj);
+}
+
+target_ulong helper_bitrev_d(target_ulong rj)
+{
+    return revbit64(rj);
+}
+
+target_ulong helper_bitswap(target_ulong v)
+{
+    v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) |
+        ((v & (target_ulong)0x5555555555555555ULL) << 1);
+    v = ((v >> 2) & (target_ulong)0x3333333333333333ULL) |
+        ((v & (target_ulong)0x3333333333333333ULL) << 2);
+    v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0FULL) |
+        ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4);
+    return v;
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index f90b63ad83..c0875db255 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -147,6 +147,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "decode-insns.c.inc"
 #include "insn_trans/trans_arith.c.inc"
 #include "insn_trans/trans_shift.c.inc"
+#include "insn_trans/trans_bit.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 07/26] target/loongarch: Add fixed point load/store instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (5 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 06/26] target/loongarch: Add fixed point bit " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 08/26] target/loongarch: Add fixed point atomic " Song Gao
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- LD.{B[U]/H[U]/W[U]/D}, ST.{B/H/W/D}
- LDX.{B[U]/H[U]/W[U]/D}, STX.{B/H/W/D}
- LDPTR.{W/D}, STPTR.{W/D}
- PRELD
- LD{GT/LE}.{B/H/W/D}, ST{GT/LE}.{B/H/W/D}
- DBAR, IBAR

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/helper.h                     |   3 +
 .../loongarch/insn_trans/trans_memory.c.inc   | 229 ++++++++++++++++++
 target/loongarch/insns.decode                 |  55 +++++
 target/loongarch/op_helper.c                  |  15 ++
 target/loongarch/translate.c                  |   6 +
 5 files changed, 308 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_memory.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 04e0245d5e..100622bfc2 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -8,3 +8,6 @@ DEF_HELPER_2(raise_exception, noreturn, env, i32)
 DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
+
+DEF_HELPER_FLAGS_3(asrtle_d, TCG_CALL_NO_WG, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
diff --git a/target/loongarch/insn_trans/trans_memory.c.inc b/target/loongarch/insn_trans/trans_memory.c.inc
new file mode 100644
index 0000000000..9003d9af9a
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_memory.c.inc
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_load(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv temp = NULL;
+
+    if (a->imm) {
+        temp = tcg_temp_new();
+        tcg_gen_addi_tl(temp, addr, a->imm);
+        addr = temp;
+    }
+
+    tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    if (temp) {
+        tcg_temp_free(temp);
+    }
+
+    return true;
+}
+
+static bool gen_store(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+    TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv temp = NULL;
+
+    if (a->imm) {
+        temp = tcg_temp_new();
+        tcg_gen_addi_tl(temp, addr, a->imm);
+        addr = temp;
+    }
+
+    tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
+
+    if (temp) {
+        tcg_temp_free(temp);
+    }
+
+    return true;
+}
+
+static bool gen_loadx(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+    TCGv addr = tcg_temp_new();
+
+    tcg_gen_add_tl(addr, src1, src2);
+    tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+    tcg_temp_free(addr);
+
+    return true;
+}
+
+static bool gen_storex(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+    TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+    TCGv addr = tcg_temp_new();
+
+    tcg_gen_add_tl(addr, src1, src2);
+    tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
+    tcg_temp_free(addr);
+
+    return true;
+}
+
+static bool gen_load_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+    gen_helper_asrtgt_d(cpu_env, src1, src2);
+    tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+static bool gen_load_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+    gen_helper_asrtle_d(cpu_env, src1, src2);
+    tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+static bool gen_store_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+    TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+    gen_helper_asrtgt_d(cpu_env, src1, src2);
+    tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
+
+    return true;
+}
+
+static bool gen_store_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+    TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+    gen_helper_asrtle_d(cpu_env, src1, src2);
+    tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
+
+    return true;
+}
+
+static bool trans_preld(DisasContext *ctx, arg_preld *a)
+{
+    return true;
+}
+
+static bool trans_dbar(DisasContext *ctx, arg_dbar * a)
+{
+    tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
+    return true;
+}
+
+static bool trans_ibar(DisasContext *ctx, arg_ibar *a)
+{
+    ctx->base.is_jmp = DISAS_STOP;
+    return true;
+}
+
+static bool gen_ldptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv temp = NULL;
+
+    if (a->imm) {
+        temp = tcg_temp_new();
+        tcg_gen_addi_tl(temp, addr, a->imm);
+        addr = temp;
+    }
+
+    tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    if (temp) {
+        tcg_temp_free(temp);
+    }
+
+    return true;
+}
+
+static bool gen_stptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+    TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv temp = NULL;
+
+    if (a->imm) {
+        temp = tcg_temp_new();
+        tcg_gen_addi_tl(temp, addr, a->im);
+        addr = temp;
+    }
+
+    tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
+
+    if (temp) {
+        tcg_temp_free(temp);
+    }
+
+    return true;
+}
+
+TRANS(ld_b, gen_load, MO_SB)
+TRANS(ld_h, gen_load, MO_TESW)
+TRANS(ld_w, gen_load, MO_TESL)
+TRANS(ld_d, gen_load, MO_TEQ)
+TRANS(st_b, gen_store, MO_SB)
+TRANS(st_h, gen_store, MO_TESW)
+TRANS(st_w, gen_store, MO_TESL)
+TRANS(st_d, gen_store, MO_TEQ)
+TRANS(ld_bu, gen_load, MO_UB)
+TRANS(ld_hu, gen_load, MO_TEUW)
+TRANS(ld_wu, gen_load, MO_TEUL)
+TRANS(ldx_b, gen_loadx, MO_SB)
+TRANS(ldx_h, gen_loadx, MO_TESW)
+TRANS(ldx_w, gen_loadx, MO_TESL)
+TRANS(ldx_d, gen_loadx, MO_TEQ)
+TRANS(stx_b, gen_storex, MO_SB)
+TRANS(stx_h, gen_storex, MO_TESW)
+TRANS(stx_w, gen_storex, MO_TESL)
+TRANS(stx_d, gen_storex, MO_TEQ)
+TRANS(ldx_bu, gen_loadx, MO_UB)
+TRANS(ldx_hu, gen_loadx, MO_TEUW)
+TRANS(ldx_wu, gen_loadx, MO_TEUL)
+TRANS(ldptr_w, gen_ldptr, MO_TESL)
+TRANS(stptr_w, gen_stptr, MO_TESL)
+TRANS(ldptr_d, gen_ldptr, MO_TEQ)
+TRANS(stptr_d, gen_stptr, MO_TEQ)
+TRANS(ldgt_b, gen_load_gt, MO_SB)
+TRANS(ldgt_h, gen_load_gt, MO_TESW)
+TRANS(ldgt_w, gen_load_gt, MO_TESL)
+TRANS(ldgt_d, gen_load_gt, MO_TEQ)
+TRANS(ldle_b, gen_load_le, MO_SB)
+TRANS(ldle_h, gen_load_le, MO_TESW)
+TRANS(ldle_w, gen_load_le, MO_TESL)
+TRANS(ldle_d, gen_load_le, MO_TEQ)
+TRANS(stgt_b, gen_store_gt, MO_SB)
+TRANS(stgt_h, gen_store_gt, MO_TESW)
+TRANS(stgt_w, gen_store_gt, MO_TESL)
+TRANS(stgt_d, gen_store_gt, MO_TEQ)
+TRANS(stle_b, gen_store_le, MO_SB)
+TRANS(stle_h, gen_store_le, MO_TESW)
+TRANS(stle_w, gen_store_le, MO_TESL)
+TRANS(stle_d, gen_store_le, MO_TEQ)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index b0bed5531b..1156e6965c 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -8,21 +8,25 @@
 #
 # Fields
 #
+%i14s2     10:s14       !function=shl_2
 %sa2p1     15:2         !function=plus_1
 
 #
 # Argument sets
 #
+&i            imm
 &r_i          rd imm
 &rr           rd rj
 &rrr          rd rj rk
 &rr_i         rd rj imm
+&hint_r_i     hint rj imm
 &rrr_sa       rd rj rk sa
 &rr_ms_ls     rd rj ms ls
 
 #
 # Formats
 #
+@i15                       .... ........ ..... imm:15    &i
 @rr               .... ........ ..... ..... rj:5 rd:5    &rr
 @rrr               .... ........ ..... rk:5 rj:5 rd:5    &rrr
 @r_i20                          .... ... imm:s20 rd:5    &r_i
@@ -30,7 +34,9 @@
 @rr_ui6            .... ........ .... imm:6 rj:5 rd:5    &rr_i
 @rr_i12                 .... ...... imm:s12 rj:5 rd:5    &rr_i
 @rr_ui12                 .... ...... imm:12 rj:5 rd:5    &rr_i
+@rr_i14s2         .... ....  .............. rj:5 rd:5    &rr_i imm=%i14s2
 @rr_i16                     .... .. imm:s16 rj:5 rd:5    &rr_i
+@hint_r_i12           .... ...... imm:s12 rj:5 hint:5    &hint_r_i
 @rrr_sa2p1        .... ........ ... .. rk:5 rj:5 rd:5    &rrr_sa  sa=%sa2p1
 @rrr_sa2        .... ........ ... sa:2 rk:5 rj:5 rd:5    &rrr_sa
 @rrr_sa3         .... ........ .. sa:3 rk:5 rj:5 rd:5    &rrr_sa
@@ -138,3 +144,52 @@ bstrins_w       0000 0000011 ..... 0 ..... ..... .....   @rr_2bw
 bstrpick_w      0000 0000011 ..... 1 ..... ..... .....   @rr_2bw
 bstrins_d       0000 000010 ...... ...... ..... .....    @rr_2bd
 bstrpick_d      0000 000011 ...... ...... ..... .....    @rr_2bd
+
+#
+# Fixed point load/store instruction
+#
+ld_b            0010 100000 ............ ..... .....     @rr_i12
+ld_h            0010 100001 ............ ..... .....     @rr_i12
+ld_w            0010 100010 ............ ..... .....     @rr_i12
+ld_d            0010 100011 ............ ..... .....     @rr_i12
+st_b            0010 100100 ............ ..... .....     @rr_i12
+st_h            0010 100101 ............ ..... .....     @rr_i12
+st_w            0010 100110 ............ ..... .....     @rr_i12
+st_d            0010 100111 ............ ..... .....     @rr_i12
+ld_bu           0010 101000 ............ ..... .....     @rr_i12
+ld_hu           0010 101001 ............ ..... .....     @rr_i12
+ld_wu           0010 101010 ............ ..... .....     @rr_i12
+ldx_b           0011 10000000 00000 ..... ..... .....    @rrr
+ldx_h           0011 10000000 01000 ..... ..... .....    @rrr
+ldx_w           0011 10000000 10000 ..... ..... .....    @rrr
+ldx_d           0011 10000000 11000 ..... ..... .....    @rrr
+stx_b           0011 10000001 00000 ..... ..... .....    @rrr
+stx_h           0011 10000001 01000 ..... ..... .....    @rrr
+stx_w           0011 10000001 10000 ..... ..... .....    @rrr
+stx_d           0011 10000001 11000 ..... ..... .....    @rrr
+ldx_bu          0011 10000010 00000 ..... ..... .....    @rrr
+ldx_hu          0011 10000010 01000 ..... ..... .....    @rrr
+ldx_wu          0011 10000010 10000 ..... ..... .....    @rrr
+preld           0010 101011 ............ ..... .....     @hint_r_i12
+dbar            0011 10000111 00100 ...............      @i15
+ibar            0011 10000111 00101 ...............      @i15
+ldptr_w         0010 0100 .............. ..... .....     @rr_i14s2
+stptr_w         0010 0101 .............. ..... .....     @rr_i14s2
+ldptr_d         0010 0110 .............. ..... .....     @rr_i14s2
+stptr_d         0010 0111 .............. ..... .....     @rr_i14s2
+ldgt_b          0011 10000111 10000 ..... ..... .....    @rrr
+ldgt_h          0011 10000111 10001 ..... ..... .....    @rrr
+ldgt_w          0011 10000111 10010 ..... ..... .....    @rrr
+ldgt_d          0011 10000111 10011 ..... ..... .....    @rrr
+ldle_b          0011 10000111 10100 ..... ..... .....    @rrr
+ldle_h          0011 10000111 10101 ..... ..... .....    @rrr
+ldle_w          0011 10000111 10110 ..... ..... .....    @rrr
+ldle_d          0011 10000111 10111 ..... ..... .....    @rrr
+stgt_b          0011 10000111 11000 ..... ..... .....    @rrr
+stgt_h          0011 10000111 11001 ..... ..... .....    @rrr
+stgt_w          0011 10000111 11010 ..... ..... .....    @rrr
+stgt_d          0011 10000111 11011 ..... ..... .....    @rrr
+stle_b          0011 10000111 11100 ..... ..... .....    @rrr
+stle_h          0011 10000111 11101 ..... ..... .....    @rrr
+stle_w          0011 10000111 11110 ..... ..... .....    @rrr
+stle_d          0011 10000111 11111 ..... ..... .....    @rrr
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index f4b22c70a0..e6410f67f9 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -40,3 +40,18 @@ target_ulong helper_bitswap(target_ulong v)
         ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4);
     return v;
 }
+
+/* loongarch assert op */
+void helper_asrtle_d(CPULoongArchState *env, target_ulong rj, target_ulong rk)
+{
+    if (rj > rk) {
+        do_raise_exception(env, EXCP_ADE, GETPC());
+    }
+}
+
+void helper_asrtgt_d(CPULoongArchState *env, target_ulong rj, target_ulong rk)
+{
+    if (rj <= rk) {
+        do_raise_exception(env, EXCP_ADE, GETPC());
+    }
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index c0875db255..4ce452a959 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -31,6 +31,11 @@ static inline int plus_1(DisasContext *ctx, int x)
     return x + 1;
 }
 
+static inline int shl_2(DisasContext *ctx, int x)
+{
+    return x * 4;
+}
+
 void generate_exception(DisasContext *ctx, int excp)
 {
     tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
@@ -148,6 +153,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_arith.c.inc"
 #include "insn_trans/trans_shift.c.inc"
 #include "insn_trans/trans_bit.c.inc"
+#include "insn_trans/trans_memory.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 08/26] target/loongarch: Add fixed point atomic instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (6 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 07/26] target/loongarch: Add fixed point load/store " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 09/26] target/loongarch: Add fixed point extra " Song Gao
                   ` (18 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- LL.{W/D}, SC.{W/D}
- AM{SWAP/ADD/AND/OR/XOR/MAX/MIN}[_DB].{W/D}
- AM{MAX/MIN}[_DB].{WU/DU}

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 .../loongarch/insn_trans/trans_atomic.c.inc   | 114 ++++++++++++++++++
 .../loongarch/insn_trans/trans_memory.c.inc   |   2 +-
 target/loongarch/insns.decode                 |  44 +++++++
 target/loongarch/translate.c                  |   1 +
 4 files changed, 160 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/insn_trans/trans_atomic.c.inc

diff --git a/target/loongarch/insn_trans/trans_atomic.c.inc b/target/loongarch/insn_trans/trans_atomic.c.inc
new file mode 100644
index 0000000000..f89b9a58e9
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_atomic.c.inc
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_ll(DisasContext *ctx, arg_rr_i *a,
+                   void (*func)(TCGv, TCGv, int))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_addi_tl(t0, src1, a->imm);
+    func(dest, t0, ctx->mem_idx);
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPULoongArchState, lladdr));
+    tcg_gen_st_tl(dest, cpu_env, offsetof(CPULoongArchState, llval));
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+    tcg_temp_free(t0);
+
+    return true;
+}
+
+static bool gen_sc(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE);
+    TCGv t0 = tcg_temp_new();
+    TCGv val = tcg_temp_new();
+
+    TCGLabel *l1 = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_addi_tl(t0, src1, a->imm);
+    tcg_gen_brcond_tl(TCG_COND_EQ, t0, cpu_lladdr, l1);
+    tcg_gen_movi_tl(dest, 0);
+    tcg_gen_br(done);
+
+    gen_set_label(l1);
+    tcg_gen_mov_tl(val, src2);
+    /* generate cmpxchg */
+    tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval,
+                              val, ctx->mem_idx, mop);
+    tcg_gen_setcond_tl(TCG_COND_EQ, dest, t0, cpu_llval);
+    gen_set_label(done);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+    tcg_temp_free(t0);
+    tcg_temp_free(val);
+
+    return true;
+}
+
+static bool gen_am(DisasContext *ctx, arg_rrr *a,
+                   void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+                   MemOp mop)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv val = gpr_src(ctx, a->rk, EXT_NONE);
+
+    if (a->rd != 0 && (a->rj == a->rd || a->rk == a->rd)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "Warning: source register overlaps destination register"
+                      "in atomic insn at pc=0x" TARGET_FMT_lx "\n",
+                      ctx->base.pc_next - 4);
+        return false;
+    }
+
+    func(dest, addr, val, ctx->mem_idx, mop);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+TRANS(ll_w, gen_ll, tcg_gen_qemu_ld32s)
+TRANS(sc_w, gen_sc, MO_TESL)
+TRANS(ll_d, gen_ll, tcg_gen_qemu_ld64)
+TRANS(sc_d, gen_sc, MO_TEQ)
+TRANS(amswap_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEQ)
+TRANS(amadd_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEQ)
+TRANS(amand_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEQ)
+TRANS(amor_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEQ)
+TRANS(amxor_w, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
+TRANS(amxor_d, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEQ)
+TRANS(ammax_w, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
+TRANS(ammax_d, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEQ)
+TRANS(ammin_w, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
+TRANS(ammin_d, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEQ)
+TRANS(ammax_wu, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
+TRANS(ammax_du, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEQ)
+TRANS(ammin_wu, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
+TRANS(ammin_du, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEQ)
+TRANS(amswap_db_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_db_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEQ)
+TRANS(amadd_db_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_db_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEQ)
+TRANS(amand_db_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_db_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEQ)
+TRANS(amor_db_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_db_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEQ)
+TRANS(amxor_db_w, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
+TRANS(amxor_db_d, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEQ)
+TRANS(ammax_db_w, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
+TRANS(ammax_db_d, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEQ)
+TRANS(ammin_db_w, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
+TRANS(ammin_db_d, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEQ)
+TRANS(ammax_db_wu, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
+TRANS(ammax_db_du, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEQ)
+TRANS(ammin_db_wu, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
+TRANS(ammin_db_du, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEQ)
diff --git a/target/loongarch/insn_trans/trans_memory.c.inc b/target/loongarch/insn_trans/trans_memory.c.inc
index 9003d9af9a..8c9925e4e5 100644
--- a/target/loongarch/insn_trans/trans_memory.c.inc
+++ b/target/loongarch/insn_trans/trans_memory.c.inc
@@ -172,7 +172,7 @@ static bool gen_stptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
 
     if (a->imm) {
         temp = tcg_temp_new();
-        tcg_gen_addi_tl(temp, addr, a->im);
+        tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
 
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 1156e6965c..8d247aa68c 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -193,3 +193,47 @@ stle_b          0011 10000111 11100 ..... ..... .....    @rrr
 stle_h          0011 10000111 11101 ..... ..... .....    @rrr
 stle_w          0011 10000111 11110 ..... ..... .....    @rrr
 stle_d          0011 10000111 11111 ..... ..... .....    @rrr
+
+#
+# Fixed point atomic instruction
+#
+ll_w            0010 0000 .............. ..... .....     @rr_i14s2
+sc_w            0010 0001 .............. ..... .....     @rr_i14s2
+ll_d            0010 0010 .............. ..... .....     @rr_i14s2
+sc_d            0010 0011 .............. ..... .....     @rr_i14s2
+amswap_w        0011 10000110 00000 ..... ..... .....    @rrr
+amswap_d        0011 10000110 00001 ..... ..... .....    @rrr
+amadd_w         0011 10000110 00010 ..... ..... .....    @rrr
+amadd_d         0011 10000110 00011 ..... ..... .....    @rrr
+amand_w         0011 10000110 00100 ..... ..... .....    @rrr
+amand_d         0011 10000110 00101 ..... ..... .....    @rrr
+amor_w          0011 10000110 00110 ..... ..... .....    @rrr
+amor_d          0011 10000110 00111 ..... ..... .....    @rrr
+amxor_w         0011 10000110 01000 ..... ..... .....    @rrr
+amxor_d         0011 10000110 01001 ..... ..... .....    @rrr
+ammax_w         0011 10000110 01010 ..... ..... .....    @rrr
+ammax_d         0011 10000110 01011 ..... ..... .....    @rrr
+ammin_w         0011 10000110 01100 ..... ..... .....    @rrr
+ammin_d         0011 10000110 01101 ..... ..... .....    @rrr
+ammax_wu        0011 10000110 01110 ..... ..... .....    @rrr
+ammax_du        0011 10000110 01111 ..... ..... .....    @rrr
+ammin_wu        0011 10000110 10000 ..... ..... .....    @rrr
+ammin_du        0011 10000110 10001 ..... ..... .....    @rrr
+amswap_db_w     0011 10000110 10010 ..... ..... .....    @rrr
+amswap_db_d     0011 10000110 10011 ..... ..... .....    @rrr
+amadd_db_w      0011 10000110 10100 ..... ..... .....    @rrr
+amadd_db_d      0011 10000110 10101 ..... ..... .....    @rrr
+amand_db_w      0011 10000110 10110 ..... ..... .....    @rrr
+amand_db_d      0011 10000110 10111 ..... ..... .....    @rrr
+amor_db_w       0011 10000110 11000 ..... ..... .....    @rrr
+amor_db_d       0011 10000110 11001 ..... ..... .....    @rrr
+amxor_db_w      0011 10000110 11010 ..... ..... .....    @rrr
+amxor_db_d      0011 10000110 11011 ..... ..... .....    @rrr
+ammax_db_w      0011 10000110 11100 ..... ..... .....    @rrr
+ammax_db_d      0011 10000110 11101 ..... ..... .....    @rrr
+ammin_db_w      0011 10000110 11110 ..... ..... .....    @rrr
+ammin_db_d      0011 10000110 11111 ..... ..... .....    @rrr
+ammax_db_wu     0011 10000111 00000 ..... ..... .....    @rrr
+ammax_db_du     0011 10000111 00001 ..... ..... .....    @rrr
+ammin_db_wu     0011 10000111 00010 ..... ..... .....    @rrr
+ammin_db_du     0011 10000111 00011 ..... ..... .....    @rrr
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 4ce452a959..5bb0d82bad 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -154,6 +154,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_shift.c.inc"
 #include "insn_trans/trans_bit.c.inc"
 #include "insn_trans/trans_memory.c.inc"
+#include "insn_trans/trans_atomic.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 09/26] target/loongarch: Add fixed point extra instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (7 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 08/26] target/loongarch: Add fixed point atomic " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 10/26] target/loongarch: Add floating point arithmetic " Song Gao
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- CRC[C].W.{B/H/W/D}.W
- SYSCALL
- BREAK
- ASRT{LE/GT}.D
- RDTIME{L/H}.W, RDTIME.D
- CPUCFG

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/helper.h                     |  4 +
 target/loongarch/insn_trans/trans_extra.c.inc | 86 +++++++++++++++++++
 target/loongarch/insns.decode                 | 22 +++++
 target/loongarch/op_helper.c                  | 32 ++++++-
 target/loongarch/translate.c                  |  1 +
 5 files changed, 143 insertions(+), 2 deletions(-)
 create mode 100644 target/loongarch/insn_trans/trans_extra.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 100622bfc2..638c2efc51 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -11,3 +11,7 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
 
 DEF_HELPER_FLAGS_3(asrtle_d, TCG_CALL_NO_WG, void, env, tl, tl)
 DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
+
+DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
+DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cpucfg, TCG_CALL_NO_RWG_SE, tl, env, tl)
diff --git a/target/loongarch/insn_trans/trans_extra.c.inc b/target/loongarch/insn_trans/trans_extra.c.inc
new file mode 100644
index 0000000000..bc622ced23
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_extra.c.inc
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool trans_break(DisasContext *ctx, arg_break *a)
+{
+    generate_exception(ctx, EXCP_BREAK);
+    return true;
+}
+
+static bool trans_syscall(DisasContext *ctx, arg_syscall *a)
+{
+    generate_exception(ctx, EXCP_SYSCALL);
+    return true;
+}
+
+static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+    gen_helper_asrtle_d(cpu_env, src1, src2);
+    return true;
+}
+
+static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+    gen_helper_asrtgt_d(cpu_env, src1, src2);
+    return true;
+}
+
+static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
+{
+    tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
+    return true;
+}
+
+static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a)
+{
+    tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
+    return true;
+}
+
+static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
+{
+    tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
+    return true;
+}
+
+static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+    gen_helper_cpucfg(dest, cpu_env, src1);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+static bool gen_crc(DisasContext *ctx, arg_rrr *a,
+                    void (*func)(TCGv, TCGv, TCGv, TCGv),
+                    TCGv tsz)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+    func(dest, src2, src1, tsz);
+    gen_set_gpr(a->rd, dest, EXT_SIGN);
+
+    return true;
+}
+
+TRANS(crc_w_b_w, gen_crc, gen_helper_crc32, tcg_constant_tl(1))
+TRANS(crc_w_h_w, gen_crc, gen_helper_crc32, tcg_constant_tl(2))
+TRANS(crc_w_w_w, gen_crc, gen_helper_crc32, tcg_constant_tl(4))
+TRANS(crc_w_d_w, gen_crc, gen_helper_crc32, tcg_constant_tl(8))
+TRANS(crcc_w_b_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(1))
+TRANS(crcc_w_h_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(2))
+TRANS(crcc_w_w_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(4))
+TRANS(crcc_w_d_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(8))
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8d247aa68c..d07b3c3b4a 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -17,6 +17,7 @@
 &i            imm
 &r_i          rd imm
 &rr           rd rj
+&rr_jk        rj rk
 &rrr          rd rj rk
 &rr_i         rd rj imm
 &hint_r_i     hint rj imm
@@ -28,6 +29,7 @@
 #
 @i15                       .... ........ ..... imm:15    &i
 @rr               .... ........ ..... ..... rj:5 rd:5    &rr
+@rr_jk            .... ........ ..... rk:5 rj:5 .....    &rr_jk
 @rrr               .... ........ ..... rk:5 rj:5 rd:5    &rrr
 @r_i20                          .... ... imm:s20 rd:5    &r_i
 @rr_ui5           .... ........ ..... imm:5 rj:5 rd:5    &rr_i
@@ -237,3 +239,23 @@ ammax_db_wu     0011 10000111 00000 ..... ..... .....    @rrr
 ammax_db_du     0011 10000111 00001 ..... ..... .....    @rrr
 ammin_db_wu     0011 10000111 00010 ..... ..... .....    @rrr
 ammin_db_du     0011 10000111 00011 ..... ..... .....    @rrr
+
+#
+# Fixed point extra instruction
+#
+crc_w_b_w       0000 00000010 01000 ..... ..... .....    @rrr
+crc_w_h_w       0000 00000010 01001 ..... ..... .....    @rrr
+crc_w_w_w       0000 00000010 01010 ..... ..... .....    @rrr
+crc_w_d_w       0000 00000010 01011 ..... ..... .....    @rrr
+crcc_w_b_w      0000 00000010 01100 ..... ..... .....    @rrr
+crcc_w_h_w      0000 00000010 01101 ..... ..... .....    @rrr
+crcc_w_w_w      0000 00000010 01110 ..... ..... .....    @rrr
+crcc_w_d_w      0000 00000010 01111 ..... ..... .....    @rrr
+break           0000 00000010 10100 ...............      @i15
+syscall         0000 00000010 10110 ...............      @i15
+asrtle_d        0000 00000000 00010 ..... ..... 00000    @rr_jk
+asrtgt_d        0000 00000000 00011 ..... ..... 00000    @rr_jk
+rdtimel_w       0000 00000000 00000 11000 ..... .....    @rr
+rdtimeh_w       0000 00000000 00000 11001 ..... .....    @rr
+rdtime_d        0000 00000000 00000 11010 ..... .....    @rr
+cpucfg          0000 00000000 00000 11011 ..... .....    @rr
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index e6410f67f9..1083e39b7f 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -13,6 +13,8 @@
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
 #include "internals.h"
+#include "qemu/crc32c.h"
+#include <zlib.h>
 
 /* Exceptions helpers */
 void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
@@ -45,13 +47,39 @@ target_ulong helper_bitswap(target_ulong v)
 void helper_asrtle_d(CPULoongArchState *env, target_ulong rj, target_ulong rk)
 {
     if (rj > rk) {
-        do_raise_exception(env, EXCP_ADE, GETPC());
+        cpu_loop_exit_sigsegv(env_cpu(env), GETPC(),
+                              MMU_DATA_LOAD, true, GETPC());
     }
 }
 
 void helper_asrtgt_d(CPULoongArchState *env, target_ulong rj, target_ulong rk)
 {
     if (rj <= rk) {
-        do_raise_exception(env, EXCP_ADE, GETPC());
+        cpu_loop_exit_sigsegv(env_cpu(env), GETPC(),
+                              MMU_DATA_LOAD, true, GETPC());
     }
 }
+
+target_ulong helper_crc32(target_ulong val, target_ulong m, uint64_t sz)
+{
+    uint8_t buf[8];
+    target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1);
+
+    m &= mask;
+    stq_le_p(buf, m);
+    return (int32_t) (crc32(val ^ 0xffffffff, buf, sz) ^ 0xffffffff);
+}
+
+target_ulong helper_crc32c(target_ulong val, target_ulong m, uint64_t sz)
+{
+    uint8_t buf[8];
+    target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1);
+    m &= mask;
+    stq_le_p(buf, m);
+    return (int32_t) (crc32c(val, buf, sz) ^ 0xffffffff);
+}
+
+target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj)
+{
+    return rj > 21 ? 0 : env->cpucfg[rj];
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 5bb0d82bad..6cebad7aa5 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -155,6 +155,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_bit.c.inc"
 #include "insn_trans/trans_memory.c.inc"
 #include "insn_trans/trans_atomic.c.inc"
+#include "insn_trans/trans_extra.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 10/26] target/loongarch: Add floating point arithmetic instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (8 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 09/26] target/loongarch: Add fixed point extra " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 11/26] target/loongarch: Add floating point comparison " Song Gao
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- F{ADD/SUB/MUL/DIV}.{S/D}
- F{MADD/MSUB/NMADD/NMSUB}.{S/D}
- F{MAX/MIN}.{S/D}
- F{MAXA/MINA}.{S/D}
- F{ABS/NEG}.{S/D}
- F{SQRT/RECIP/RSQRT}.{S/D}
- F{SCALEB/LOGB/COPYSIGN}.{S/D}
- FCLASS.{S/D}

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/cpu.c                        |   1 +
 target/loongarch/fpu_helper.c                 | 403 ++++++++++++++++++
 target/loongarch/helper.h                     |  37 ++
 .../loongarch/insn_trans/trans_farith.c.inc   | 105 +++++
 target/loongarch/insns.decode                 |  52 +++
 target/loongarch/internals.h                  |   2 +
 target/loongarch/translate.c                  |  11 +
 7 files changed, 611 insertions(+)
 create mode 100644 target/loongarch/fpu_helper.c
 create mode 100644 target/loongarch/insn_trans/trans_farith.c.inc

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 76b89d1606..883c6c623f 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -185,6 +185,7 @@ static void loongarch_cpu_reset(DeviceState *dev)
     env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
     env->fcsr0 = 0x0;
 
+    restore_fp_status(env);
     cs->exception_index = EXCP_NONE;
 }
 
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
new file mode 100644
index 0000000000..c4e35f8d2b
--- /dev/null
+++ b/target/loongarch/fpu_helper.c
@@ -0,0 +1,403 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch float point emulation helpers for QEMU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "fpu/softfloat.h"
+#include "internals.h"
+
+#define FLOAT_TO_INT32_OVERFLOW 0x7fffffff
+#define FLOAT_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
+
+static inline uint64_t nanbox_s(float32 fp)
+{
+    return fp | MAKE_64BIT_MASK(32, 32);
+}
+
+/* Convert loongarch rounding mode in fcsr0 to IEEE library */
+static const FloatRoundMode ieee_rm[4] = {
+    float_round_nearest_even,
+    float_round_to_zero,
+    float_round_up,
+    float_round_down
+};
+
+void restore_fp_status(CPULoongArchState *env)
+{
+    set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
+                            &env->fp_status);
+    set_flush_to_zero(0, &env->fp_status);
+}
+
+static int ieee_ex_to_loongarch(int xcpt)
+{
+    int ret = 0;
+    if (xcpt & float_flag_invalid) {
+        ret |= FP_INVALID;
+    }
+    if (xcpt & float_flag_overflow) {
+        ret |= FP_OVERFLOW;
+    }
+    if (xcpt & float_flag_underflow) {
+        ret |= FP_UNDERFLOW;
+    }
+    if (xcpt & float_flag_divbyzero) {
+        ret |= FP_DIV0;
+    }
+    if (xcpt & float_flag_inexact) {
+        ret |= FP_INEXACT;
+    }
+    return ret;
+}
+
+static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask)
+{
+    int flags = get_float_exception_flags(&env->fp_status);
+
+    set_float_exception_flags(0, &env->fp_status);
+
+    flags &= ~mask;
+
+    if (!flags) {
+        SET_FP_CAUSE(env->fcsr0, flags);
+        return;
+    } else {
+        flags = ieee_ex_to_loongarch(flags);
+        SET_FP_CAUSE(env->fcsr0, flags);
+    }
+
+    if (GET_FP_ENABLES(env->fcsr0) & flags) {
+        do_raise_exception(env, EXCP_FPE, pc);
+    } else {
+        UPDATE_FP_FLAGS(env->fcsr0, flags);
+    }
+}
+
+static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
+{
+    update_fcsr0_mask(env, pc, 0);
+}
+
+uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = float64_add(fj, fk, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = float64_sub(fj, fk, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = float64_mul(fj, fk, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = float64_div(fj, fk, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmax_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_maxnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmax_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = float64_maxnum(fj, fk, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmin_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_minnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmin_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = float64_minnum(fj, fk, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_maxnummag((uint32_t)fj,
+                                    (uint32_t)fk, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = float64_maxnummag(fj, fk, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_minnummag((uint32_t)fj,
+                                    (uint32_t)fk, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+
+    fd = float64_minnummag(fj, fk, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+    int32_t n = (int32_t)fk;
+
+    fd = nanbox_s(float32_scalbn((uint32_t)fj,
+                                 n >  0x200 ?  0x200 :
+                                 n < -0x200 ? -0x200 : n,
+                                 &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+    uint64_t fd;
+    int64_t n = (int64_t)fk;
+
+    fd = float64_scalbn(fj,
+                        n >  0x1000 ?  0x1000 :
+                        n < -0x1000 ? -0x1000 : n,
+                        &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = float64_sqrt(fj, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = float64_div(float64_one, fj, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    uint32_t fp;
+
+    fp = float32_sqrt((uint32_t)fj, &env->fp_status);
+    fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fp, fd;
+
+    fp = float64_sqrt(fj, &env->fp_status);
+    fd = float64_div(float64_one, fp, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    uint32_t fp;
+    float_status *status = &env->fp_status;
+    FloatRoundMode old_mode = get_float_rounding_mode(status);
+
+    set_float_rounding_mode(float_round_down, status);
+    fp = float32_log2((uint32_t)fj, status);
+    fd = nanbox_s(float32_round_to_int(fp, status));
+    set_float_rounding_mode(old_mode, status);
+    update_fcsr0_mask(env, GETPC(), float_flag_inexact);
+    return fd;
+}
+
+uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    float_status *status = &env->fp_status;
+    FloatRoundMode old_mode = get_float_rounding_mode(status);
+
+    set_float_rounding_mode(float_round_down, status);
+    fd = float64_log2(fj, status);
+    fd = float64_round_to_int(fd, status);
+    set_float_rounding_mode(old_mode, status);
+    update_fcsr0_mask(env, GETPC(), float_flag_inexact);
+    return fd;
+}
+
+uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
+{
+    float32 f = fj;
+    bool sign = float32_is_neg(f);
+
+    if (float32_is_infinity(f)) {
+        return sign ? 1 << 0 : 1 << 7;
+    } else if (float32_is_zero(f)) {
+        return sign ? 1 << 3 : 1 << 4;
+    } else if (float32_is_zero_or_denormal(f)) {
+        return sign ? 1 << 2 : 1 << 5;
+    } else if (float32_is_any_nan(f)) {
+        float_status s = { }; /* for snan_bit_is_one */
+        return float32_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8;
+    } else {
+        return sign ? 1 << 1 : 1 << 6;
+    }
+}
+
+uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
+{
+    float64 f = fj;
+    bool sign = float64_is_neg(f);
+
+    if (float64_is_infinity(f)) {
+        return sign ? 1 << 0 : 1 << 7;
+    } else if (float64_is_zero(f)) {
+        return sign ? 1 << 3 : 1 << 4;
+    } else if (float64_is_zero_or_denormal(f)) {
+        return sign ? 1 << 2 : 1 << 5;
+    } else if (float64_is_any_nan(f)) {
+        float_status s = { }; /* for snan_bit_is_one */
+        return float64_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8;
+    } else {
+        return sign ? 1 << 1 : 1 << 6;
+    }
+}
+
+uint64_t helper_fmuladd_s(CPULoongArchState *env, uint64_t fj,
+                          uint64_t fk, uint64_t fa, uint32_t flag)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float32_muladd((uint32_t)fj, (uint32_t)fk,
+                                 (uint32_t)fa, flag, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj,
+                          uint64_t fk, uint64_t fa, uint32_t flag)
+{
+    uint64_t fd;
+
+    fd = float64_muladd(fj, fk, fa, flag, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 638c2efc51..840bad9b2f 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -15,3 +15,40 @@ DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
 DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
 DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
 DEF_HELPER_FLAGS_2(cpucfg, TCG_CALL_NO_RWG_SE, tl, env, tl)
+
+/* Floating-point helper */
+DEF_HELPER_FLAGS_3(fadd_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fadd_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fsub_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fsub_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmul_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmul_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fdiv_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fdiv_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmax_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmax_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmin_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmin_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmaxa_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmaxa_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmina_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmina_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+
+DEF_HELPER_FLAGS_5(fmuladd_s, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i32)
+DEF_HELPER_FLAGS_5(fmuladd_d, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i32)
+
+DEF_HELPER_FLAGS_3(fscaleb_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fscaleb_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+
+DEF_HELPER_FLAGS_2(flogb_s, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(flogb_d, TCG_CALL_NO_WG, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(fsqrt_s, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fsqrt_d, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(frsqrt_s, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(frsqrt_d, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(frecip_s, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(frecip_d, TCG_CALL_NO_WG, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64)
+DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64)
diff --git a/target/loongarch/insn_trans/trans_farith.c.inc b/target/loongarch/insn_trans/trans_farith.c.inc
new file mode 100644
index 0000000000..65ad2ffab8
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_farith.c.inc
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_fff(DisasContext *ctx, arg_fff *a,
+                    void (*func)(TCGv, TCGv_env, TCGv, TCGv))
+{
+    func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk]);
+    return true;
+}
+
+static bool gen_ff(DisasContext *ctx, arg_ff *a,
+                   void (*func)(TCGv, TCGv_env, TCGv))
+{
+    func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj]);
+    return true;
+}
+
+static bool gen_muladd(DisasContext *ctx, arg_ffff *a,
+                       void (*func)(TCGv, TCGv_env, TCGv, TCGv, TCGv, TCGv_i32),
+                       int flag)
+{
+    TCGv_i32 tflag = tcg_constant_i32(flag);
+    func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj],
+         cpu_fpr[a->fk], cpu_fpr[a->fa], tflag);
+    return true;
+}
+
+static bool trans_fcopysign_s(DisasContext *ctx, arg_fcopysign_s *a)
+{
+    tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 31);
+    return true;
+}
+
+static bool trans_fcopysign_d(DisasContext *ctx, arg_fcopysign_d *a)
+{
+    tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 63);
+    return true;
+}
+
+static bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a)
+{
+    tcg_gen_andi_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], MAKE_64BIT_MASK(0, 31));
+    gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+    return true;
+}
+
+static bool trans_fabs_d(DisasContext *ctx, arg_fabs_d *a)
+{
+    tcg_gen_andi_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], MAKE_64BIT_MASK(0, 63));
+    return true;
+}
+
+static bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a)
+{
+    tcg_gen_xori_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], 0x80000000);
+    gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+    return true;
+}
+
+static bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a)
+{
+    tcg_gen_xori_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], 0x8000000000000000LL);
+    return true;
+}
+
+TRANS(fadd_s, gen_fff, gen_helper_fadd_s)
+TRANS(fadd_d, gen_fff, gen_helper_fadd_d)
+TRANS(fsub_s, gen_fff, gen_helper_fsub_s)
+TRANS(fsub_d, gen_fff, gen_helper_fsub_d)
+TRANS(fmul_s, gen_fff, gen_helper_fmul_s)
+TRANS(fmul_d, gen_fff, gen_helper_fmul_d)
+TRANS(fdiv_s, gen_fff, gen_helper_fdiv_s)
+TRANS(fdiv_d, gen_fff, gen_helper_fdiv_d)
+TRANS(fmax_s, gen_fff, gen_helper_fmax_s)
+TRANS(fmax_d, gen_fff, gen_helper_fmax_d)
+TRANS(fmin_s, gen_fff, gen_helper_fmin_s)
+TRANS(fmin_d, gen_fff, gen_helper_fmin_d)
+TRANS(fmaxa_s, gen_fff, gen_helper_fmaxa_s)
+TRANS(fmaxa_d, gen_fff, gen_helper_fmaxa_d)
+TRANS(fmina_s, gen_fff, gen_helper_fmina_s)
+TRANS(fmina_d, gen_fff, gen_helper_fmina_d)
+TRANS(fscaleb_s, gen_fff, gen_helper_fscaleb_s)
+TRANS(fscaleb_d, gen_fff, gen_helper_fscaleb_d)
+TRANS(fsqrt_s, gen_ff, gen_helper_fsqrt_s)
+TRANS(fsqrt_d, gen_ff, gen_helper_fsqrt_d)
+TRANS(frecip_s, gen_ff, gen_helper_frecip_s)
+TRANS(frecip_d, gen_ff, gen_helper_frecip_d)
+TRANS(frsqrt_s, gen_ff, gen_helper_frsqrt_s)
+TRANS(frsqrt_d, gen_ff, gen_helper_frsqrt_d)
+TRANS(flogb_s, gen_ff, gen_helper_flogb_s)
+TRANS(flogb_d, gen_ff, gen_helper_flogb_d)
+TRANS(fclass_s, gen_ff, gen_helper_fclass_s)
+TRANS(fclass_d, gen_ff, gen_helper_fclass_d)
+TRANS(fmadd_s, gen_muladd, gen_helper_fmuladd_s, 0)
+TRANS(fmadd_d, gen_muladd, gen_helper_fmuladd_d, 0)
+TRANS(fmsub_s, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_c)
+TRANS(fmsub_d, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_c)
+TRANS(fnmadd_s, gen_muladd, gen_helper_fmuladd_s,
+      float_muladd_negate_product | float_muladd_negate_c)
+TRANS(fnmadd_d, gen_muladd, gen_helper_fmuladd_d,
+      float_muladd_negate_product | float_muladd_negate_c)
+TRANS(fnmsub_s, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_product)
+TRANS(fnmsub_d, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_product)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index d07b3c3b4a..b67562dc00 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -23,6 +23,9 @@
 &hint_r_i     hint rj imm
 &rrr_sa       rd rj rk sa
 &rr_ms_ls     rd rj ms ls
+&ff           fd fj
+&fff          fd fj fk
+&ffff         fd fj fk fa
 
 #
 # Formats
@@ -44,6 +47,9 @@
 @rrr_sa3         .... ........ .. sa:3 rk:5 rj:5 rd:5    &rrr_sa
 @rr_2bw            .... ....... ms:5 . ls:5 rj:5 rd:5    &rr_ms_ls
 @rr_2bd               .... ...... ms:6 ls:6 rj:5 rd:5    &rr_ms_ls
+@ff               .... ........ ..... ..... fj:5 fd:5    &ff
+@fff               .... ........ ..... fk:5 fj:5 fd:5    &fff
+@ffff               .... ........ fa:5 fk:5 fj:5 fd:5    &ffff
 
 #
 # Fixed point arithmetic operation instruction
@@ -259,3 +265,49 @@ rdtimel_w       0000 00000000 00000 11000 ..... .....    @rr
 rdtimeh_w       0000 00000000 00000 11001 ..... .....    @rr
 rdtime_d        0000 00000000 00000 11010 ..... .....    @rr
 cpucfg          0000 00000000 00000 11011 ..... .....    @rr
+
+#
+# Floating point arithmetic operation instruction
+#
+fadd_s          0000 00010000 00001 ..... ..... .....    @fff
+fadd_d          0000 00010000 00010 ..... ..... .....    @fff
+fsub_s          0000 00010000 00101 ..... ..... .....    @fff
+fsub_d          0000 00010000 00110 ..... ..... .....    @fff
+fmul_s          0000 00010000 01001 ..... ..... .....    @fff
+fmul_d          0000 00010000 01010 ..... ..... .....    @fff
+fdiv_s          0000 00010000 01101 ..... ..... .....    @fff
+fdiv_d          0000 00010000 01110 ..... ..... .....    @fff
+fmadd_s         0000 10000001 ..... ..... ..... .....    @ffff
+fmadd_d         0000 10000010 ..... ..... ..... .....    @ffff
+fmsub_s         0000 10000101 ..... ..... ..... .....    @ffff
+fmsub_d         0000 10000110 ..... ..... ..... .....    @ffff
+fnmadd_s        0000 10001001 ..... ..... ..... .....    @ffff
+fnmadd_d        0000 10001010 ..... ..... ..... .....    @ffff
+fnmsub_s        0000 10001101 ..... ..... ..... .....    @ffff
+fnmsub_d        0000 10001110 ..... ..... ..... .....    @ffff
+fmax_s          0000 00010000 10001 ..... ..... .....    @fff
+fmax_d          0000 00010000 10010 ..... ..... .....    @fff
+fmin_s          0000 00010000 10101 ..... ..... .....    @fff
+fmin_d          0000 00010000 10110 ..... ..... .....    @fff
+fmaxa_s         0000 00010000 11001 ..... ..... .....    @fff
+fmaxa_d         0000 00010000 11010 ..... ..... .....    @fff
+fmina_s         0000 00010000 11101 ..... ..... .....    @fff
+fmina_d         0000 00010000 11110 ..... ..... .....    @fff
+fabs_s          0000 00010001 01000 00001 ..... .....    @ff
+fabs_d          0000 00010001 01000 00010 ..... .....    @ff
+fneg_s          0000 00010001 01000 00101 ..... .....    @ff
+fneg_d          0000 00010001 01000 00110 ..... .....    @ff
+fsqrt_s         0000 00010001 01000 10001 ..... .....    @ff
+fsqrt_d         0000 00010001 01000 10010 ..... .....    @ff
+frecip_s        0000 00010001 01000 10101 ..... .....    @ff
+frecip_d        0000 00010001 01000 10110 ..... .....    @ff
+frsqrt_s        0000 00010001 01000 11001 ..... .....    @ff
+frsqrt_d        0000 00010001 01000 11010 ..... .....    @ff
+fscaleb_s       0000 00010001 00001 ..... ..... .....    @fff
+fscaleb_d       0000 00010001 00010 ..... ..... .....    @fff
+flogb_s         0000 00010001 01000 01001 ..... .....    @ff
+flogb_d         0000 00010001 01000 01010 ..... .....    @ff
+fcopysign_s     0000 00010001 00101 ..... ..... .....    @fff
+fcopysign_d     0000 00010001 00110 ..... ..... .....    @fff
+fclass_s        0000 00010001 01000 01101 ..... .....    @ff
+fclass_d        0000 00010001 01000 01110 ..... .....    @ff
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 1e69e7d9d9..17219d4070 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -18,4 +18,6 @@ void QEMU_NORETURN do_raise_exception(CPULoongArchState *env,
 
 const char *loongarch_exception_name(int32_t exception);
 
+void restore_fp_status(CPULoongArchState *env);
+
 #endif
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 6cebad7aa5..9ed3907e08 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -15,6 +15,7 @@
 #include "exec/translator.h"
 #include "exec/log.h"
 #include "qemu/qemu-print.h"
+#include "fpu/softfloat.h"
 #include "translate.h"
 #include "internals.h"
 
@@ -36,6 +37,15 @@ static inline int shl_2(DisasContext *ctx, int x)
     return x * 4;
 }
 
+/*
+ * LoongArch the upper 32 bits are undefined ("can be any value").
+ * QEMU chooses to nanbox, because it is most likely to show guest bugs early.
+ */
+static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
+{
+    tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32));
+}
+
 void generate_exception(DisasContext *ctx, int excp)
 {
     tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
@@ -156,6 +166,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_memory.c.inc"
 #include "insn_trans/trans_atomic.c.inc"
 #include "insn_trans/trans_extra.c.inc"
+#include "insn_trans/trans_farith.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 11/26] target/loongarch: Add floating point comparison instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (9 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 10/26] target/loongarch: Add floating point arithmetic " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 12/26] target/loongarch: Add floating point conversion " Song Gao
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- FCMP.cond.{S/D}

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/fpu_helper.c                | 60 ++++++++++++++++++++
 target/loongarch/helper.h                    |  9 +++
 target/loongarch/insn_trans/trans_fcmp.c.inc | 56 ++++++++++++++++++
 target/loongarch/insns.decode                |  8 +++
 target/loongarch/internals.h                 |  5 ++
 target/loongarch/translate.c                 |  1 +
 6 files changed, 139 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fcmp.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index c4e35f8d2b..089a5be199 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -401,3 +401,63 @@ uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj,
     update_fcsr0(env, GETPC());
     return fd;
 }
+
+static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp,
+                            uint32_t flags)
+{
+    bool ret;
+
+    switch (cmp) {
+    case float_relation_less:
+        ret = (flags & FCMP_LT);
+        break;
+    case float_relation_equal:
+        ret = (flags & FCMP_EQ);
+        break;
+    case float_relation_greater:
+        ret = (flags & FCMP_GT);
+        break;
+    case float_relation_unordered:
+        ret = (flags & FCMP_UN);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    update_fcsr0(env, GETPC());
+
+    return ret;
+}
+
+/* fcmp_cXXX_s */
+uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
+                         uint64_t fk, uint32_t flags)
+{
+    FloatRelation cmp = float32_compare_quiet((uint32_t)fj,
+                                              (uint32_t)fk, &env->fp_status);
+    return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_sXXX_s */
+uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj,
+                         uint64_t fk, uint32_t flags)
+{
+    FloatRelation cmp = float32_compare((uint32_t)fj,
+                                        (uint32_t)fk, &env->fp_status);
+    return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_cXXX_d */
+uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj,
+                         uint64_t fk, uint32_t flags)
+{
+    FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status);
+    return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_sXXX_d */
+uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
+                         uint64_t fk, uint32_t flags)
+{
+    FloatRelation cmp = float64_compare(fj, fk, &env->fp_status);
+    return fcmp_common(env, cmp, flags);
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 840bad9b2f..25a891bf8b 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -52,3 +52,12 @@ DEF_HELPER_FLAGS_2(frecip_d, TCG_CALL_NO_WG, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64)
 DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64)
+
+/* fcmp.cXXX.s */
+DEF_HELPER_4(fcmp_c_s, i64, env, i64, i64, i32)
+/* fcmp.sXXX.s */
+DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32)
+/* fcmp.cXXX.d */
+DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32)
+/* fcmp.sXXX.d */
+DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_fcmp.c.inc b/target/loongarch/insn_trans/trans_fcmp.c.inc
new file mode 100644
index 0000000000..93a6a2230f
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fcmp.c.inc
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+/* bit0(signaling/quiet) bit1(lt) bit2(eq) bit3(un) bit4(neq) */
+static uint32_t get_fcmp_flags(int cond)
+{
+    uint32_t flags = 0;
+
+    if (cond & 0x1) {
+        flags |= FCMP_LT;
+    }
+    if (cond & 0x2) {
+        flags |= FCMP_EQ;
+    }
+    if (cond & 0x4) {
+        flags |= FCMP_UN;
+    }
+    if (cond & 0x8) {
+        flags |= FCMP_GT | FCMP_LT;
+    }
+    return flags;
+}
+
+static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
+{
+    TCGv var = tcg_temp_new();
+    uint32_t flags;
+    void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
+
+    fn = (a->fcond & 1 ? gen_helper_fcmp_s_s : gen_helper_fcmp_c_s);
+    flags = get_fcmp_flags(a->fcond >> 1);
+
+    fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], tcg_constant_i32(flags));
+
+    tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd]));
+    tcg_temp_free(var);
+    return true;
+}
+
+static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a)
+{
+    TCGv var = tcg_temp_new();
+    uint32_t flags;
+    void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
+    fn = (a->fcond & 1 ? gen_helper_fcmp_s_d : gen_helper_fcmp_c_d);
+    flags = get_fcmp_flags(a->fcond >> 1);
+
+    fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], tcg_constant_i32(flags));
+
+    tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd]));
+
+    tcg_temp_free(var);
+    return true;
+}
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index b67562dc00..33d3e13760 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -26,6 +26,7 @@
 &ff           fd fj
 &fff          fd fj fk
 &ffff         fd fj fk fa
+&cff_fcond    cd fj fk fcond
 
 #
 # Formats
@@ -50,6 +51,7 @@
 @ff               .... ........ ..... ..... fj:5 fd:5    &ff
 @fff               .... ........ ..... fk:5 fj:5 fd:5    &fff
 @ffff               .... ........ fa:5 fk:5 fj:5 fd:5    &ffff
+@cff_fcond    .... ........ fcond:5 fk:5 fj:5 .. cd:3    &cff_fcond
 
 #
 # Fixed point arithmetic operation instruction
@@ -311,3 +313,9 @@ fcopysign_s     0000 00010001 00101 ..... ..... .....    @fff
 fcopysign_d     0000 00010001 00110 ..... ..... .....    @fff
 fclass_s        0000 00010001 01000 01101 ..... .....    @ff
 fclass_d        0000 00010001 01000 01110 ..... .....    @ff
+
+#
+# Floating point compare instruction
+#
+fcmp_cond_s     0000 11000001 ..... ..... ..... 00 ...   @cff_fcond
+fcmp_cond_d     0000 11000010 ..... ..... ..... 00 ...   @cff_fcond
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 17219d4070..774a87ec80 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -8,6 +8,11 @@
 #ifndef LOONGARCH_INTERNALS_H
 #define LOONGARCH_INTERNALS_H
 
+#define FCMP_LT   0b0001  /* fp0 < fp1 */
+#define FCMP_EQ   0b0010  /* fp0 = fp1 */
+#define FCMP_UN   0b0100  /* unordered */
+#define FCMP_GT   0b1000  /* fp0 > fp1 */
+
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 9ed3907e08..43c7f71645 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -167,6 +167,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_atomic.c.inc"
 #include "insn_trans/trans_extra.c.inc"
 #include "insn_trans/trans_farith.c.inc"
+#include "insn_trans/trans_fcmp.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 12/26] target/loongarch: Add floating point conversion instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (10 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 11/26] target/loongarch: Add floating point comparison " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 13/26] target/loongarch: Add floating point move " Song Gao
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- FCVT.S.D, FCVT.D.S
- FFINT.{S/D}.{W/L}, FTINT.{W/L}.{S/D}
- FTINT{RM/RP/RZ/RNE}.{W/L}.{S/D}
- FRINT.{S/D}

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/fpu_helper.c                | 393 +++++++++++++++++++
 target/loongarch/helper.h                    |  29 ++
 target/loongarch/insn_trans/trans_fcnv.c.inc |  33 ++
 target/loongarch/insns.decode                |  32 ++
 target/loongarch/translate.c                 |   1 +
 5 files changed, 488 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fcnv.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index 089a5be199..deae76c766 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -461,3 +461,396 @@ uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
     FloatRelation cmp = float64_compare(fj, fk, &env->fp_status);
     return fcmp_common(env, cmp, flags);
 }
+
+/* floating point conversion */
+uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(float64_to_float32(fj, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = float32_to_float64((uint32_t)fj, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = nanbox_s(int64_to_float32(fj, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = int32_to_float64((int32_t)fj, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = int64_to_float64(fj, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status));
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = float64_round_to_int(fj, &env->fp_status);
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_down, &env->fp_status);
+    fd = float64_to_int64(fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_down, &env->fp_status);
+    fd = float32_to_int64((uint32_t)fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_down, &env->fp_status);
+    fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_down, &env->fp_status);
+    fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_up, &env->fp_status);
+    fd = float64_to_int64(fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrp_l_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_up, &env->fp_status);
+    fd = float32_to_int64((uint32_t)fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrp_w_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_up, &env->fp_status);
+    fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrp_w_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_up, &env->fp_status);
+    fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrz_l_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    fd = float64_to_int64_round_to_zero(fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrz_l_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    fd = float32_to_int64_round_to_zero((uint32_t)fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrz_w_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    fd = (uint64_t)float64_to_int32_round_to_zero(fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrz_w_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint32_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    fd = float32_to_int32_round_to_zero((uint32_t)fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return (uint64_t)fd;
+}
+
+uint64_t helper_ftintrne_l_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+    fd = float64_to_int64(fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrne_l_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+    fd = float32_to_int64((uint32_t)fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrne_w_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+    fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftintrne_w_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint32_t fd;
+    FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
+
+    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+    fd = float32_to_int32((uint32_t)fj, &env->fp_status);
+    set_float_rounding_mode(old_mode, &env->fp_status);
+
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return (uint64_t)fd;
+}
+
+uint64_t helper_ftint_l_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = float64_to_int64(fj, &env->fp_status);
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftint_l_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = float32_to_int64((uint32_t)fj, &env->fp_status);
+    if (get_float_exception_flags(&env->fp_status) &
+        (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT64_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftint_w_s(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
+    if (get_float_exception_flags(&env->fp_status)
+        & (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj)
+{
+    uint64_t fd;
+
+    fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
+    if (get_float_exception_flags(&env->fp_status)
+        & (float_flag_invalid | float_flag_overflow)) {
+        fd = FLOAT_TO_INT32_OVERFLOW;
+    }
+    update_fcsr0(env, GETPC());
+    return fd;
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 25a891bf8b..1e8749433a 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -61,3 +61,32 @@ DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32)
 DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32)
 /* fcmp.sXXX.d */
 DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32)
+
+DEF_HELPER_2(fcvt_d_s, i64, env, i64)
+DEF_HELPER_2(fcvt_s_d, i64, env, i64)
+DEF_HELPER_2(ffint_d_w, i64, env, i64)
+DEF_HELPER_2(ffint_d_l, i64, env, i64)
+DEF_HELPER_2(ffint_s_w, i64, env, i64)
+DEF_HELPER_2(ffint_s_l, i64, env, i64)
+DEF_HELPER_2(ftintrm_l_s, i64, env, i64)
+DEF_HELPER_2(ftintrm_l_d, i64, env, i64)
+DEF_HELPER_2(ftintrm_w_s, i64, env, i64)
+DEF_HELPER_2(ftintrm_w_d, i64, env, i64)
+DEF_HELPER_2(ftintrp_l_s, i64, env, i64)
+DEF_HELPER_2(ftintrp_l_d, i64, env, i64)
+DEF_HELPER_2(ftintrp_w_s, i64, env, i64)
+DEF_HELPER_2(ftintrp_w_d, i64, env, i64)
+DEF_HELPER_2(ftintrz_l_s, i64, env, i64)
+DEF_HELPER_2(ftintrz_l_d, i64, env, i64)
+DEF_HELPER_2(ftintrz_w_s, i64, env, i64)
+DEF_HELPER_2(ftintrz_w_d, i64, env, i64)
+DEF_HELPER_2(ftintrne_l_s, i64, env, i64)
+DEF_HELPER_2(ftintrne_l_d, i64, env, i64)
+DEF_HELPER_2(ftintrne_w_s, i64, env, i64)
+DEF_HELPER_2(ftintrne_w_d, i64, env, i64)
+DEF_HELPER_2(ftint_l_s, i64, env, i64)
+DEF_HELPER_2(ftint_l_d, i64, env, i64)
+DEF_HELPER_2(ftint_w_s, i64, env, i64)
+DEF_HELPER_2(ftint_w_d, i64, env, i64)
+DEF_HELPER_2(frint_s, i64, env, i64)
+DEF_HELPER_2(frint_d, i64, env, i64)
diff --git a/target/loongarch/insn_trans/trans_fcnv.c.inc b/target/loongarch/insn_trans/trans_fcnv.c.inc
new file mode 100644
index 0000000000..c1c6918ad1
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fcnv.c.inc
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+TRANS(fcvt_s_d, gen_ff, gen_helper_fcvt_s_d)
+TRANS(fcvt_d_s, gen_ff, gen_helper_fcvt_d_s)
+TRANS(ftintrm_w_s, gen_ff, gen_helper_ftintrm_w_s)
+TRANS(ftintrm_w_d, gen_ff, gen_helper_ftintrm_w_d)
+TRANS(ftintrm_l_s, gen_ff, gen_helper_ftintrm_l_s)
+TRANS(ftintrm_l_d, gen_ff, gen_helper_ftintrm_l_d)
+TRANS(ftintrp_w_s, gen_ff, gen_helper_ftintrp_w_s)
+TRANS(ftintrp_w_d, gen_ff, gen_helper_ftintrp_w_d)
+TRANS(ftintrp_l_s, gen_ff, gen_helper_ftintrp_l_s)
+TRANS(ftintrp_l_d, gen_ff, gen_helper_ftintrp_l_d)
+TRANS(ftintrz_w_s, gen_ff, gen_helper_ftintrz_w_s)
+TRANS(ftintrz_w_d, gen_ff, gen_helper_ftintrz_w_d)
+TRANS(ftintrz_l_s, gen_ff, gen_helper_ftintrz_l_s)
+TRANS(ftintrz_l_d, gen_ff, gen_helper_ftintrz_l_d)
+TRANS(ftintrne_w_s, gen_ff, gen_helper_ftintrne_w_s)
+TRANS(ftintrne_w_d, gen_ff, gen_helper_ftintrne_w_d)
+TRANS(ftintrne_l_s, gen_ff, gen_helper_ftintrne_l_s)
+TRANS(ftintrne_l_d, gen_ff, gen_helper_ftintrne_l_d)
+TRANS(ftint_w_s, gen_ff, gen_helper_ftint_w_s)
+TRANS(ftint_w_d, gen_ff, gen_helper_ftint_w_d)
+TRANS(ftint_l_s, gen_ff, gen_helper_ftint_l_s)
+TRANS(ftint_l_d, gen_ff, gen_helper_ftint_l_d)
+TRANS(ffint_s_w, gen_ff, gen_helper_ffint_s_w)
+TRANS(ffint_s_l, gen_ff, gen_helper_ffint_s_l)
+TRANS(ffint_d_w, gen_ff, gen_helper_ffint_d_w)
+TRANS(ffint_d_l, gen_ff, gen_helper_ffint_d_l)
+TRANS(frint_s, gen_ff, gen_helper_frint_s)
+TRANS(frint_d, gen_ff, gen_helper_frint_d)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 33d3e13760..3e745115d3 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -319,3 +319,35 @@ fclass_d        0000 00010001 01000 01110 ..... .....    @ff
 #
 fcmp_cond_s     0000 11000001 ..... ..... ..... 00 ...   @cff_fcond
 fcmp_cond_d     0000 11000010 ..... ..... ..... 00 ...   @cff_fcond
+
+#
+# Floating point conversion instruction
+#
+fcvt_s_d        0000 00010001 10010 00110 ..... .....    @ff
+fcvt_d_s        0000 00010001 10010 01001 ..... .....    @ff
+ftintrm_w_s     0000 00010001 10100 00001 ..... .....    @ff
+ftintrm_w_d     0000 00010001 10100 00010 ..... .....    @ff
+ftintrm_l_s     0000 00010001 10100 01001 ..... .....    @ff
+ftintrm_l_d     0000 00010001 10100 01010 ..... .....    @ff
+ftintrp_w_s     0000 00010001 10100 10001 ..... .....    @ff
+ftintrp_w_d     0000 00010001 10100 10010 ..... .....    @ff
+ftintrp_l_s     0000 00010001 10100 11001 ..... .....    @ff
+ftintrp_l_d     0000 00010001 10100 11010 ..... .....    @ff
+ftintrz_w_s     0000 00010001 10101 00001 ..... .....    @ff
+ftintrz_w_d     0000 00010001 10101 00010 ..... .....    @ff
+ftintrz_l_s     0000 00010001 10101 01001 ..... .....    @ff
+ftintrz_l_d     0000 00010001 10101 01010 ..... .....    @ff
+ftintrne_w_s    0000 00010001 10101 10001 ..... .....    @ff
+ftintrne_w_d    0000 00010001 10101 10010 ..... .....    @ff
+ftintrne_l_s    0000 00010001 10101 11001 ..... .....    @ff
+ftintrne_l_d    0000 00010001 10101 11010 ..... .....    @ff
+ftint_w_s       0000 00010001 10110 00001 ..... .....    @ff
+ftint_w_d       0000 00010001 10110 00010 ..... .....    @ff
+ftint_l_s       0000 00010001 10110 01001 ..... .....    @ff
+ftint_l_d       0000 00010001 10110 01010 ..... .....    @ff
+ffint_s_w       0000 00010001 11010 00100 ..... .....    @ff
+ffint_s_l       0000 00010001 11010 00110 ..... .....    @ff
+ffint_d_w       0000 00010001 11010 01000 ..... .....    @ff
+ffint_d_l       0000 00010001 11010 01010 ..... .....    @ff
+frint_s         0000 00010001 11100 10001 ..... .....    @ff
+frint_d         0000 00010001 11100 10010 ..... .....    @ff
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 43c7f71645..d865f9e6b0 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -168,6 +168,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_extra.c.inc"
 #include "insn_trans/trans_farith.c.inc"
 #include "insn_trans/trans_fcmp.c.inc"
+#include "insn_trans/trans_fcnv.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 13/26] target/loongarch: Add floating point move instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (11 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 12/26] target/loongarch: Add floating point conversion " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 14/26] target/loongarch: Add floating point load/store " Song Gao
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- FMOV.{S/D}
- FSEL
- MOVGR2FR.{W/D}, MOVGR2FRH.W
- MOVFR2GR.{S/D}, MOVFRH2GR.S
- MOVGR2FCSR, MOVFCSR2GR
- MOVFR2CF, MOVCF2FR
- MOVGR2CF, MOVCF2GR

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/loongarch/fpu_helper.c                |   6 +
 target/loongarch/helper.h                    |   2 +
 target/loongarch/insn_trans/trans_fmov.c.inc | 157 +++++++++++++++++++
 target/loongarch/insns.decode                |  37 +++++
 target/loongarch/translate.c                 |   1 +
 5 files changed, 203 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fmov.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index deae76c766..9f5235c4f8 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -854,3 +854,9 @@ uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj)
     update_fcsr0(env, GETPC());
     return fd;
 }
+
+void helper_set_rounding_mode(CPULoongArchState *env, uint32_t fcsr0)
+{
+    set_float_rounding_mode(ieee_rm[(fcsr0 >> FCSR0_RM) & 0x3],
+                            &env->fp_status);
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 1e8749433a..da1a2bced7 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -90,3 +90,5 @@ DEF_HELPER_2(ftint_w_s, i64, env, i64)
 DEF_HELPER_2(ftint_w_d, i64, env, i64)
 DEF_HELPER_2(frint_s, i64, env, i64)
 DEF_HELPER_2(frint_d, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
diff --git a/target/loongarch/insn_trans/trans_fmov.c.inc b/target/loongarch/insn_trans/trans_fmov.c.inc
new file mode 100644
index 0000000000..24753d4568
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmov.c.inc
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static const uint32_t fcsr_mask[4] = {
+    UINT32_MAX, FCSR0_M1, FCSR0_M2, FCSR0_M3
+};
+
+static bool trans_fsel(DisasContext *ctx, arg_fsel *a)
+{
+    TCGv zero = tcg_constant_tl(0);
+    TCGv cond = tcg_temp_new();
+
+    tcg_gen_ld8u_tl(cond, cpu_env, offsetof(CPULoongArchState, cf[a->ca]));
+    tcg_gen_movcond_tl(TCG_COND_EQ, cpu_fpr[a->fd], cond, zero,
+                       cpu_fpr[a->fj], cpu_fpr[a->fk]);
+    tcg_temp_free(cond);
+
+    return true;
+}
+
+static bool gen_f2f(DisasContext *ctx, arg_ff *a,
+                    void (*func)(TCGv, TCGv), bool nanbox)
+{
+    TCGv dest = cpu_fpr[a->fd];
+    TCGv src = cpu_fpr[a->fj];
+
+    func(dest, src);
+    if (nanbox) {
+        gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+    }
+
+    return true;
+}
+
+static bool gen_r2f(DisasContext *ctx, arg_fr *a,
+                    void (*func)(TCGv, TCGv))
+{
+    TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
+
+    func(cpu_fpr[a->fd], src);
+    return true;
+}
+
+static bool gen_f2r(DisasContext *ctx, arg_rf *a,
+                    void (*func)(TCGv, TCGv))
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+    func(dest, cpu_fpr[a->fj]);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+
+    return true;
+}
+
+static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a)
+{
+    uint32_t mask = fcsr_mask[a->fcsrd];
+    TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE);
+
+    if (mask == UINT32_MAX) {
+        tcg_gen_extrl_i64_i32(cpu_fcsr0, Rj);
+    } else {
+        TCGv_i32 temp = tcg_temp_new_i32();
+
+        tcg_gen_extrl_i64_i32(temp, Rj);
+        tcg_gen_andi_i32(temp, temp, mask);
+        tcg_gen_andi_i32(cpu_fcsr0, cpu_fcsr0, ~mask);
+        tcg_gen_or_i32(cpu_fcsr0, cpu_fcsr0, temp);
+        tcg_temp_free_i32(temp);
+
+        /*
+         * Install the new rounding mode to fpu_status, if changed.
+         * Note that FCSR3 is exactly the rounding mode field.
+         */
+        if (mask != FCSR0_M3) {
+            return true;
+        }
+    }
+    gen_helper_set_rounding_mode(cpu_env, cpu_fcsr0);
+
+    return true;
+}
+
+static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a)
+{
+    TCGv_i32 temp = tcg_temp_new_i32();
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+    tcg_gen_andi_i32(temp, cpu_fcsr0, fcsr_mask[a->fcsrs]);
+    tcg_gen_ext_i32_i64(dest, temp);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+    tcg_temp_free_i32(temp);
+
+    return true;
+}
+
+static void gen_movgr2fr_w(TCGv dest, TCGv src)
+{
+    tcg_gen_deposit_i64(dest, dest, src, 0, 32);
+}
+
+static void gen_movgr2frh_w(TCGv dest, TCGv src)
+{
+    tcg_gen_deposit_i64(dest, dest, src, 32, 32);
+}
+
+static void gen_movfrh2gr_s(TCGv dest, TCGv src)
+{
+    tcg_gen_sextract_tl(dest, src, 32, 32);
+}
+
+static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a)
+{
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_andi_tl(t0, cpu_fpr[a->fj], 0x1);
+    tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7]));
+    tcg_temp_free(t0);
+
+    return true;
+}
+
+static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a)
+{
+    tcg_gen_ld8u_tl(cpu_fpr[a->fd], cpu_env,
+                    offsetof(CPULoongArchState, cf[a->cj & 0x7]));
+    return true;
+}
+
+static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a)
+{
+    TCGv t0 = tcg_temp_new();
+
+    tcg_gen_andi_tl(t0, gpr_src(ctx, a->rj, EXT_NONE), 0x1);
+    tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7]));
+    tcg_temp_free(t0);
+
+    return true;
+}
+
+static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a)
+{
+    tcg_gen_ld8u_tl(gpr_dst(ctx, a->rd, EXT_NONE), cpu_env,
+                    offsetof(CPULoongArchState, cf[a->cj & 0x7]));
+    return true;
+}
+
+TRANS(fmov_s, gen_f2f, tcg_gen_mov_tl, true)
+TRANS(fmov_d, gen_f2f, tcg_gen_mov_tl, false)
+TRANS(movgr2fr_w, gen_r2f, gen_movgr2fr_w)
+TRANS(movgr2fr_d, gen_r2f, tcg_gen_mov_tl)
+TRANS(movgr2frh_w, gen_r2f, gen_movgr2frh_w)
+TRANS(movfr2gr_s, gen_f2r, tcg_gen_ext32s_tl)
+TRANS(movfr2gr_d, gen_f2r, tcg_gen_mov_tl)
+TRANS(movfrh2gr_s, gen_f2r, gen_movfrh2gr_s)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 3e745115d3..e9d9a74c47 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -27,6 +27,15 @@
 &fff          fd fj fk
 &ffff         fd fj fk fa
 &cff_fcond    cd fj fk fcond
+&fffc         fd fj fk ca
+&fr           fd rj
+&rf           rd fj
+&fcsrd_r      fcsrd rj
+&r_fcsrs      rd fcsrs
+&cf           cd fj
+&fc           fd cj
+&cr           cd rj
+&rc           rd cj
 
 #
 # Formats
@@ -52,6 +61,15 @@
 @fff               .... ........ ..... fk:5 fj:5 fd:5    &fff
 @ffff               .... ........ fa:5 fk:5 fj:5 fd:5    &ffff
 @cff_fcond    .... ........ fcond:5 fk:5 fj:5 .. cd:3    &cff_fcond
+@fffc            .... ........ .. ca:3 fk:5 fj:5 fd:5    &fffc
+@fr               .... ........ ..... ..... rj:5 fd:5    &fr
+@rf               .... ........ ..... ..... fj:5 rd:5    &rf
+@fcsrd_r       .... ........ ..... ..... rj:5 fcsrd:5    &fcsrd_r
+@r_fcsrs       .... ........ ..... ..... fcsrs:5 rd:5    &r_fcsrs
+@cf            .... ........ ..... ..... fj:5 .. cd:3    &cf
+@fc            .... ........ ..... ..... .. cj:3 fd:5    &fc
+@cr            .... ........ ..... ..... rj:5 .. cd:3    &cr
+@rc            .... ........ ..... ..... .. cj:3 rd:5    &rc
 
 #
 # Fixed point arithmetic operation instruction
@@ -351,3 +369,22 @@ ffint_d_w       0000 00010001 11010 01000 ..... .....    @ff
 ffint_d_l       0000 00010001 11010 01010 ..... .....    @ff
 frint_s         0000 00010001 11100 10001 ..... .....    @ff
 frint_d         0000 00010001 11100 10010 ..... .....    @ff
+
+#
+# Floating point move instruction
+#
+fmov_s          0000 00010001 01001 00101 ..... .....    @ff
+fmov_d          0000 00010001 01001 00110 ..... .....    @ff
+fsel            0000 11010000 00 ... ..... ..... .....   @fffc
+movgr2fr_w      0000 00010001 01001 01001 ..... .....    @fr
+movgr2fr_d      0000 00010001 01001 01010 ..... .....    @fr
+movgr2frh_w     0000 00010001 01001 01011 ..... .....    @fr
+movfr2gr_s      0000 00010001 01001 01101 ..... .....    @rf
+movfr2gr_d      0000 00010001 01001 01110 ..... .....    @rf
+movfrh2gr_s     0000 00010001 01001 01111 ..... .....    @rf
+movgr2fcsr      0000 00010001 01001 10000 ..... .....    @fcsrd_r
+movfcsr2gr      0000 00010001 01001 10010 ..... .....    @r_fcsrs
+movfr2cf        0000 00010001 01001 10100 ..... 00 ...   @cf
+movcf2fr        0000 00010001 01001 10101 00 ... .....   @fc
+movgr2cf        0000 00010001 01001 10110 ..... 00 ...   @cr
+movcf2gr        0000 00010001 01001 10111 00 ... .....   @rc
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index d865f9e6b0..b9cfce5303 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -169,6 +169,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_farith.c.inc"
 #include "insn_trans/trans_fcmp.c.inc"
 #include "insn_trans/trans_fcnv.c.inc"
+#include "insn_trans/trans_fmov.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 14/26] target/loongarch: Add floating point load/store instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (12 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 13/26] target/loongarch: Add floating point move " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 15/26] target/loongarch: Add branch " Song Gao
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- FLD.{S/D}, FST.{S/D}
- FLDX.{S/D}, FSTX.{S/D}
- FLD{GT/LE}.{S/D}, FST{GT/LE}.{S/D}

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 .../loongarch/insn_trans/trans_fmemory.c.inc  | 153 ++++++++++++++++++
 target/loongarch/insns.decode                 |  24 +++
 target/loongarch/translate.c                  |   1 +
 3 files changed, 178 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fmemory.c.inc

diff --git a/target/loongarch/insn_trans/trans_fmemory.c.inc b/target/loongarch/insn_trans/trans_fmemory.c.inc
new file mode 100644
index 0000000000..c9b7c04fc0
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmemory.c.inc
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static void maybe_nanbox_load(TCGv freg, MemOp mop)
+{
+    if ((mop & MO_SIZE) == MO_32) {
+        gen_nanbox_s(freg, freg);
+    }
+}
+
+static bool gen_fload_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
+{
+    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv temp = NULL;
+
+    if (a->imm) {
+        temp = tcg_temp_new();
+        tcg_gen_addi_tl(temp, addr, a->imm);
+        addr = temp;
+    }
+
+    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+    maybe_nanbox_load(cpu_fpr[a->fd], mop);
+
+    if (temp) {
+        tcg_temp_free(temp);
+    }
+
+    return true;
+}
+
+static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
+{
+    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv temp = NULL;
+
+    if (a->imm) {
+        temp = tcg_temp_new();
+        tcg_gen_addi_tl(temp, addr, a->imm);
+        addr = temp;
+    }
+
+    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+    if (temp) {
+        tcg_temp_free(temp);
+    }
+    return true;
+}
+
+static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+    TCGv addr = tcg_temp_new();
+
+    tcg_gen_add_tl(addr, src1, src2);
+    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+    maybe_nanbox_load(cpu_fpr[a->fd], mop);
+    tcg_temp_free(addr);
+
+    return true;
+}
+
+static bool gen_fstorex(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+    TCGv addr = tcg_temp_new();
+
+    tcg_gen_add_tl(addr, src1, src2);
+    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+    tcg_temp_free(addr);
+
+    return true;
+}
+
+static bool gen_fload_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+    TCGv addr = tcg_temp_new();
+
+    gen_helper_asrtgt_d(cpu_env, src1, src2);
+    tcg_gen_add_tl(addr, src1, src2);
+    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+    maybe_nanbox_load(cpu_fpr[a->fd], mop);
+    tcg_temp_free(addr);
+
+    return true;
+}
+
+static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+    TCGv addr = tcg_temp_new();
+
+    gen_helper_asrtgt_d(cpu_env, src1, src2);
+    tcg_gen_add_tl(addr, src1, src2);
+    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+    tcg_temp_free(addr);
+
+    return true;
+}
+
+static bool gen_fload_le(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+    TCGv addr = tcg_temp_new();
+
+    gen_helper_asrtle_d(cpu_env, src1, src2);
+    tcg_gen_add_tl(addr, src1, src2);
+    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+    maybe_nanbox_load(cpu_fpr[a->fd], mop);
+    tcg_temp_free(addr);
+
+    return true;
+}
+
+static bool gen_fstore_le(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+    TCGv addr = tcg_temp_new();
+
+    gen_helper_asrtle_d(cpu_env, src1, src2);
+    tcg_gen_add_tl(addr, src1, src2);
+    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+    tcg_temp_free(addr);
+
+    return true;
+}
+
+TRANS(fld_s, gen_fload_i, MO_TEUL)
+TRANS(fst_s, gen_fstore_i, MO_TEUL)
+TRANS(fld_d, gen_fload_i, MO_TEQ)
+TRANS(fst_d, gen_fstore_i, MO_TEQ)
+TRANS(fldx_s, gen_floadx, MO_TEUL)
+TRANS(fldx_d, gen_floadx, MO_TEQ)
+TRANS(fstx_s, gen_fstorex, MO_TEUL)
+TRANS(fstx_d, gen_fstorex, MO_TEQ)
+TRANS(fldgt_s, gen_fload_gt, MO_TEUL)
+TRANS(fldgt_d, gen_fload_gt, MO_TEQ)
+TRANS(fldle_s, gen_fload_le, MO_TEUL)
+TRANS(fldle_d, gen_fload_le, MO_TEQ)
+TRANS(fstgt_s, gen_fstore_gt, MO_TEUL)
+TRANS(fstgt_d, gen_fstore_gt, MO_TEQ)
+TRANS(fstle_s, gen_fstore_le, MO_TEUL)
+TRANS(fstle_d, gen_fstore_le, MO_TEQ)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index e9d9a74c47..c9daa55574 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -36,6 +36,8 @@
 &fc           fd cj
 &cr           cd rj
 &rc           rd cj
+&frr          fd rj rk
+&fr_i         fd rj imm
 
 #
 # Formats
@@ -70,6 +72,8 @@
 @fc            .... ........ ..... ..... .. cj:3 fd:5    &fc
 @cr            .... ........ ..... ..... rj:5 .. cd:3    &cr
 @rc            .... ........ ..... ..... .. cj:3 rd:5    &rc
+@frr               .... ........ ..... rk:5 rj:5 fd:5    &frr
+@fr_i12                 .... ...... imm:s12 rj:5 fd:5    &fr_i
 
 #
 # Fixed point arithmetic operation instruction
@@ -388,3 +392,23 @@ movfr2cf        0000 00010001 01001 10100 ..... 00 ...   @cf
 movcf2fr        0000 00010001 01001 10101 00 ... .....   @fc
 movgr2cf        0000 00010001 01001 10110 ..... 00 ...   @cr
 movcf2gr        0000 00010001 01001 10111 00 ... .....   @rc
+
+#
+# Floating point load/store instruction
+#
+fld_s           0010 101100 ............ ..... .....     @fr_i12
+fst_s           0010 101101 ............ ..... .....     @fr_i12
+fld_d           0010 101110 ............ ..... .....     @fr_i12
+fst_d           0010 101111 ............ ..... .....     @fr_i12
+fldx_s          0011 10000011 00000 ..... ..... .....    @frr
+fldx_d          0011 10000011 01000 ..... ..... .....    @frr
+fstx_s          0011 10000011 10000 ..... ..... .....    @frr
+fstx_d          0011 10000011 11000 ..... ..... .....    @frr
+fldgt_s         0011 10000111 01000 ..... ..... .....    @frr
+fldgt_d         0011 10000111 01001 ..... ..... .....    @frr
+fldle_s         0011 10000111 01010 ..... ..... .....    @frr
+fldle_d         0011 10000111 01011 ..... ..... .....    @frr
+fstgt_s         0011 10000111 01100 ..... ..... .....    @frr
+fstgt_d         0011 10000111 01101 ..... ..... .....    @frr
+fstle_s         0011 10000111 01110 ..... ..... .....    @frr
+fstle_d         0011 10000111 01111 ..... ..... .....    @frr
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index b9cfce5303..7b5d1a9eab 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -170,6 +170,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_fcmp.c.inc"
 #include "insn_trans/trans_fcnv.c.inc"
 #include "insn_trans/trans_fmov.c.inc"
+#include "insn_trans/trans_fmemory.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 15/26] target/loongarch: Add branch instruction translation
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (13 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 14/26] target/loongarch: Add floating point load/store " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 16/26] target/loongarch: Add disassembler Song Gao
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This includes:
- BEQ, BNE, BLT[U], BGE[U]
- BEQZ, BNEZ
- B
- BL
- JIRL
- BCEQZ, BCNEZ

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 .../loongarch/insn_trans/trans_branch.c.inc   | 83 +++++++++++++++++++
 target/loongarch/insns.decode                 | 28 +++++++
 target/loongarch/translate.c                  |  1 +
 3 files changed, 112 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_branch.c.inc

diff --git a/target/loongarch/insn_trans/trans_branch.c.inc b/target/loongarch/insn_trans/trans_branch.c.inc
new file mode 100644
index 0000000000..65dbdff41e
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_branch.c.inc
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool trans_b(DisasContext *ctx, arg_b *a)
+{
+    gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
+    ctx->base.is_jmp = DISAS_NORETURN;
+    return true;
+}
+
+static bool trans_bl(DisasContext *ctx, arg_bl *a)
+{
+    tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4);
+    gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
+    ctx->base.is_jmp = DISAS_NORETURN;
+    return true;
+}
+
+static bool trans_jirl(DisasContext *ctx, arg_jirl *a)
+{
+    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+    tcg_gen_addi_tl(cpu_pc, src1, a->offs);
+    tcg_gen_movi_tl(dest, ctx->base.pc_next + 4);
+    gen_set_gpr(a->rd, dest, EXT_NONE);
+    tcg_gen_lookup_and_goto_ptr();
+    ctx->base.is_jmp = DISAS_NORETURN;
+    return true;
+}
+
+static void gen_bc(DisasContext *ctx, TCGv src1, TCGv src2,
+                   target_long offs, TCGCond cond)
+{
+    TCGLabel *l = gen_new_label();
+    tcg_gen_brcond_tl(cond, src1, src2, l);
+    gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
+    gen_set_label(l);
+    gen_goto_tb(ctx, 0, ctx->base.pc_next + offs);
+    ctx->base.is_jmp = DISAS_NORETURN;
+}
+
+static bool gen_rr_bc(DisasContext *ctx, arg_rr_offs *a, TCGCond cond)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE);
+
+    gen_bc(ctx, src1, src2, a->offs, cond);
+    return true;
+}
+
+static bool gen_rz_bc(DisasContext *ctx, arg_r_offs *a, TCGCond cond)
+{
+    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+    TCGv src2 = tcg_constant_tl(0);
+
+    gen_bc(ctx, src1, src2, a->offs, cond);
+    return true;
+}
+
+static bool gen_cz_bc(DisasContext *ctx, arg_c_offs *a, TCGCond cond)
+{
+    TCGv src1 = tcg_temp_new();
+    TCGv src2 = tcg_constant_tl(0);
+
+    tcg_gen_ld8u_tl(src1, cpu_env,
+                    offsetof(CPULoongArchState, cf[a->cj]));
+    gen_bc(ctx, src1, src2, a->offs, cond);
+    return true;
+}
+
+TRANS(beq, gen_rr_bc, TCG_COND_EQ)
+TRANS(bne, gen_rr_bc, TCG_COND_NE)
+TRANS(blt, gen_rr_bc, TCG_COND_LT)
+TRANS(bge, gen_rr_bc, TCG_COND_GE)
+TRANS(bltu, gen_rr_bc, TCG_COND_LTU)
+TRANS(bgeu, gen_rr_bc, TCG_COND_GEU)
+TRANS(beqz, gen_rz_bc, TCG_COND_EQ)
+TRANS(bnez, gen_rz_bc, TCG_COND_NE)
+TRANS(bceqz, gen_cz_bc, TCG_COND_EQ)
+TRANS(bcnez, gen_cz_bc, TCG_COND_NE)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index c9daa55574..3379d22979 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -10,6 +10,9 @@
 #
 %i14s2     10:s14       !function=shl_2
 %sa2p1     15:2         !function=plus_1
+%offs21    0:s5 10:16   !function=shl_2
+%offs16    10:s16       !function=shl_2
+%offs26    0:s10 10:16  !function=shl_2
 
 #
 # Argument sets
@@ -38,6 +41,10 @@
 &rc           rd cj
 &frr          fd rj rk
 &fr_i         fd rj imm
+&r_offs       rj offs
+&c_offs       cj offs
+&offs         offs
+&rr_offs      rj rd offs
 
 #
 # Formats
@@ -74,6 +81,10 @@
 @rc            .... ........ ..... ..... .. cj:3 rd:5    &rc
 @frr               .... ........ ..... rk:5 rj:5 fd:5    &frr
 @fr_i12                 .... ...... imm:s12 rj:5 fd:5    &fr_i
+@r_offs21         .... .. ................ rj:5 .....    &r_offs      offs=%offs21
+@c_offs21      .... .. ................ .. cj:3 .....    &c_offs      offs=%offs21
+@offs26            .... .. ..........................    &offs        offs=%offs26
+@rr_offs16         .... .. ................ rj:5 rd:5    &rr_offs     offs=%offs16
 
 #
 # Fixed point arithmetic operation instruction
@@ -412,3 +423,20 @@ fstgt_s         0011 10000111 01100 ..... ..... .....    @frr
 fstgt_d         0011 10000111 01101 ..... ..... .....    @frr
 fstle_s         0011 10000111 01110 ..... ..... .....    @frr
 fstle_d         0011 10000111 01111 ..... ..... .....    @frr
+
+#
+# Branch instructions
+#
+beqz            0100 00 ................ ..... .....     @r_offs21
+bnez            0100 01 ................ ..... .....     @r_offs21
+bceqz           0100 10 ................ 00 ... .....    @c_offs21
+bcnez           0100 10 ................ 01 ... .....    @c_offs21
+jirl            0100 11 ................ ..... .....     @rr_offs16
+b               0101 00 ..........................       @offs26
+bl              0101 01 ..........................       @offs26
+beq             0101 10 ................ ..... .....     @rr_offs16
+bne             0101 11 ................ ..... .....     @rr_offs16
+blt             0110 00 ................ ..... .....     @rr_offs16
+bge             0110 01 ................ ..... .....     @rr_offs16
+bltu            0110 10 ................ ..... .....     @rr_offs16
+bgeu            0110 11 ................ ..... .....     @rr_offs16
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 7b5d1a9eab..2710764653 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -171,6 +171,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
 #include "insn_trans/trans_fcnv.c.inc"
 #include "insn_trans/trans_fmov.c.inc"
 #include "insn_trans/trans_fmemory.c.inc"
+#include "insn_trans/trans_branch.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.27.0



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

* [PATCH v14 16/26] target/loongarch: Add disassembler
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (14 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 15/26] target/loongarch: Add branch " Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 17/26] linux-user: Add LoongArch generic header files Song Gao
                   ` (10 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This patch adds support for disassembling via option '-d in_asm'.

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/disas/dis-asm.h  |   2 +
 meson.build              |   1 +
 target/loongarch/disas.c | 612 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 615 insertions(+)
 create mode 100644 target/loongarch/disas.c

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..aeab30f19c 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -253,6 +253,7 @@ enum bfd_architecture
 #define bfd_mach_rx            0x75
 #define bfd_mach_rx_v2         0x76
 #define bfd_mach_rx_v3         0x77
+  bfd_arch_loongarch,
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -461,6 +462,7 @@ int print_insn_riscv32          (bfd_vma, disassemble_info*);
 int print_insn_riscv64          (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
+int print_insn_loongarch(bfd_vma, disassemble_info *);
 
 #ifdef CONFIG_CAPSTONE
 bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
diff --git a/meson.build b/meson.build
index 53065e96ec..fa4c6dd241 100644
--- a/meson.build
+++ b/meson.build
@@ -1848,6 +1848,7 @@ disassemblers = {
   'sh4' : ['CONFIG_SH4_DIS'],
   'sparc' : ['CONFIG_SPARC_DIS'],
   'xtensa' : ['CONFIG_XTENSA_DIS'],
+  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
 }
 if link_language == 'cpp'
   disassemblers += {
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
new file mode 100644
index 0000000000..45be34de27
--- /dev/null
+++ b/target/loongarch/disas.c
@@ -0,0 +1,612 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch Disassembler
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited.
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+#include "qemu/bitops.h"
+
+typedef struct {
+    disassemble_info *info;
+    uint64_t pc;
+    uint32_t insn;
+} DisasContext;
+
+static inline int plus_1(DisasContext *ctx, int x)
+{
+    return x + 1;
+}
+
+static inline int shl_2(DisasContext *ctx, int x)
+{
+    return x * 4;
+}
+
+#define output(C, INSN, FMT, ...)                                   \
+{                                                                   \
+    (C)->info->fprintf_func((C)->info->stream, "%08x   %-9s\t" FMT, \
+                            (C)->insn, INSN, ##__VA_ARGS__);        \
+}
+
+#include "decode-insns.c.inc"
+
+int print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
+{
+    bfd_byte buffer[4];
+    uint32_t insn;
+    int status;
+
+    status = (*info->read_memory_func)(memaddr, buffer, 4, info);
+    if (status != 0) {
+        (*info->memory_error_func)(status, memaddr, info);
+        return -1;
+    }
+    insn = bfd_getl32(buffer);
+    DisasContext ctx = {
+        .info = info,
+        .pc = memaddr,
+        .insn = insn
+    };
+
+    if (!decode(&ctx, insn)) {
+        output(&ctx, "illegal", "");
+    }
+    return 4;
+}
+
+static void output_r_i(DisasContext *ctx, arg_r_i *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, %d", a->rd, a->imm);
+}
+
+static void output_rrr(DisasContext *ctx, arg_rrr *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, r%d, r%d", a->rd, a->rj, a->rk);
+}
+
+static void output_rr_i(DisasContext *ctx, arg_rr_i *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, r%d, %d", a->rd, a->rj, a->imm);
+}
+
+static void output_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
+                          const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, r%d, r%d, %d", a->rd, a->rj, a->rk, a->sa);
+}
+
+static void output_rr(DisasContext *ctx, arg_rr *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, r%d", a->rd, a->rj);
+}
+
+static void output_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
+                          const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, r%d, %d, %d", a->rd, a->rj, a->ms, a->ls);
+}
+
+static void output_hint_r_i(DisasContext *ctx, arg_hint_r_i *a,
+                            const char *mnemonic)
+{
+    output(ctx, mnemonic, "%d, r%d, %d", a->hint, a->rj, a->imm);
+}
+
+static void output_i(DisasContext *ctx, arg_i *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "%d", a->imm);
+}
+
+static void output_rr_jk(DisasContext *ctx, arg_rr_jk *a,
+                         const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, r%d", a->rj, a->rk);
+}
+
+static void output_ff(DisasContext *ctx, arg_ff *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "f%d, f%d", a->fd, a->fj);
+}
+
+static void output_fff(DisasContext *ctx, arg_fff *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "f%d, f%d, f%d", a->fd, a->fj, a->fk);
+}
+
+static void output_ffff(DisasContext *ctx, arg_ffff *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "f%d, f%d, f%d, f%d", a->fd, a->fj, a->fk, a->fa);
+}
+
+static void output_fffc(DisasContext *ctx, arg_fffc *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "f%d, f%d, f%d, %d", a->fd, a->fj, a->fk, a->ca);
+}
+
+static void output_fr(DisasContext *ctx, arg_fr *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "f%d, r%d", a->fd, a->rj);
+}
+
+static void output_rf(DisasContext *ctx, arg_rf *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, f%d", a->rd, a->fj);
+}
+
+static void output_fcsrd_r(DisasContext *ctx, arg_fcsrd_r *a,
+                           const char *mnemonic)
+{
+    output(ctx, mnemonic, "fcsr%d, r%d", a->fcsrd, a->rj);
+}
+
+static void output_r_fcsrs(DisasContext *ctx, arg_r_fcsrs *a,
+                           const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, fcsr%d", a->rd, a->fcsrs);
+}
+
+static void output_cf(DisasContext *ctx, arg_cf *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "fcc%d, f%d", a->cd, a->fj);
+}
+
+static void output_fc(DisasContext *ctx, arg_fc *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "f%d, fcc%d", a->fd, a->cj);
+}
+
+static void output_cr(DisasContext *ctx, arg_cr *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "fcc%d, r%d", a->cd, a->rj);
+}
+
+static void output_rc(DisasContext *ctx, arg_rc *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, fcc%d", a->rd, a->cj);
+}
+
+static void output_frr(DisasContext *ctx, arg_frr *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "f%d, r%d, r%d", a->fd, a->rj, a->rk);
+}
+
+static void output_fr_i(DisasContext *ctx, arg_fr_i *a, const char *mnemonic)
+{
+    output(ctx, mnemonic, "f%d, r%d, %d", a->fd, a->rj, a->imm);
+}
+
+static void output_r_offs(DisasContext *ctx, arg_r_offs *a,
+                          const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, %d # 0x%" PRIx64, a->rj, a->offs,
+           ctx->pc + a->offs);
+}
+
+static void output_c_offs(DisasContext *ctx, arg_c_offs *a,
+                          const char *mnemonic)
+{
+    output(ctx, mnemonic, "fcc%d, %d # 0x%" PRIx64, a->cj, a->offs,
+           ctx->pc + a->offs);
+}
+
+static void output_offs(DisasContext *ctx, arg_offs *a,
+                        const char *mnemonic)
+{
+    output(ctx, mnemonic, "%d # 0x%" PRIx64, a->offs, ctx->pc + a->offs);
+}
+
+static void output_rr_offs(DisasContext *ctx, arg_rr_offs *a,
+                           const char *mnemonic)
+{
+    output(ctx, mnemonic, "r%d, r%d, %d", a->rj, a->rd, a->offs);
+}
+
+#define INSN(insn, type)                                    \
+static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
+{                                                           \
+    output_##type(ctx, a, #insn);                           \
+    return true;                                            \
+}
+
+INSN(clo_w,        rr)
+INSN(clz_w,        rr)
+INSN(cto_w,        rr)
+INSN(ctz_w,        rr)
+INSN(clo_d,        rr)
+INSN(clz_d,        rr)
+INSN(cto_d,        rr)
+INSN(ctz_d,        rr)
+INSN(revb_2h,      rr)
+INSN(revb_4h,      rr)
+INSN(revb_2w,      rr)
+INSN(revb_d,       rr)
+INSN(revh_2w,      rr)
+INSN(revh_d,       rr)
+INSN(bitrev_4b,    rr)
+INSN(bitrev_8b,    rr)
+INSN(bitrev_w,     rr)
+INSN(bitrev_d,     rr)
+INSN(ext_w_h,      rr)
+INSN(ext_w_b,      rr)
+INSN(rdtime_d,     rr)
+INSN(cpucfg,       rr)
+INSN(asrtle_d,     rr_jk)
+INSN(asrtgt_d,     rr_jk)
+INSN(alsl_w,       rrr_sa)
+INSN(alsl_wu,      rrr_sa)
+INSN(bytepick_w,   rrr_sa)
+INSN(bytepick_d,   rrr_sa)
+INSN(add_w,        rrr)
+INSN(add_d,        rrr)
+INSN(sub_w,        rrr)
+INSN(sub_d,        rrr)
+INSN(slt,          rrr)
+INSN(sltu,         rrr)
+INSN(maskeqz,      rrr)
+INSN(masknez,      rrr)
+INSN(nor,          rrr)
+INSN(and,          rrr)
+INSN(or,           rrr)
+INSN(xor,          rrr)
+INSN(orn,          rrr)
+INSN(andn,         rrr)
+INSN(sll_w,        rrr)
+INSN(srl_w,        rrr)
+INSN(sra_w,        rrr)
+INSN(sll_d,        rrr)
+INSN(srl_d,        rrr)
+INSN(sra_d,        rrr)
+INSN(rotr_w,       rrr)
+INSN(rotr_d,       rrr)
+INSN(mul_w,        rrr)
+INSN(mulh_w,       rrr)
+INSN(mulh_wu,      rrr)
+INSN(mul_d,        rrr)
+INSN(mulh_d,       rrr)
+INSN(mulh_du,      rrr)
+INSN(mulw_d_w,     rrr)
+INSN(mulw_d_wu,    rrr)
+INSN(div_w,        rrr)
+INSN(mod_w,        rrr)
+INSN(div_wu,       rrr)
+INSN(mod_wu,       rrr)
+INSN(div_d,        rrr)
+INSN(mod_d,        rrr)
+INSN(div_du,       rrr)
+INSN(mod_du,       rrr)
+INSN(crc_w_b_w,    rrr)
+INSN(crc_w_h_w,    rrr)
+INSN(crc_w_w_w,    rrr)
+INSN(crc_w_d_w,    rrr)
+INSN(crcc_w_b_w,   rrr)
+INSN(crcc_w_h_w,   rrr)
+INSN(crcc_w_w_w,   rrr)
+INSN(crcc_w_d_w,   rrr)
+INSN(break,        i)
+INSN(syscall,      i)
+INSN(alsl_d,       rrr_sa)
+INSN(slli_w,       rr_i)
+INSN(slli_d,       rr_i)
+INSN(srli_w,       rr_i)
+INSN(srli_d,       rr_i)
+INSN(srai_w,       rr_i)
+INSN(srai_d,       rr_i)
+INSN(rotri_w,      rr_i)
+INSN(rotri_d,      rr_i)
+INSN(bstrins_w,    rr_ms_ls)
+INSN(bstrpick_w,   rr_ms_ls)
+INSN(bstrins_d,    rr_ms_ls)
+INSN(bstrpick_d,   rr_ms_ls)
+INSN(fadd_s,       fff)
+INSN(fadd_d,       fff)
+INSN(fsub_s,       fff)
+INSN(fsub_d,       fff)
+INSN(fmul_s,       fff)
+INSN(fmul_d,       fff)
+INSN(fdiv_s,       fff)
+INSN(fdiv_d,       fff)
+INSN(fmax_s,       fff)
+INSN(fmax_d,       fff)
+INSN(fmin_s,       fff)
+INSN(fmin_d,       fff)
+INSN(fmaxa_s,      fff)
+INSN(fmaxa_d,      fff)
+INSN(fmina_s,      fff)
+INSN(fmina_d,      fff)
+INSN(fscaleb_s,    fff)
+INSN(fscaleb_d,    fff)
+INSN(fcopysign_s,  fff)
+INSN(fcopysign_d,  fff)
+INSN(fabs_s,       ff)
+INSN(fabs_d,       ff)
+INSN(fneg_s,       ff)
+INSN(fneg_d,       ff)
+INSN(flogb_s,      ff)
+INSN(flogb_d,      ff)
+INSN(fclass_s,     ff)
+INSN(fclass_d,     ff)
+INSN(fsqrt_s,      ff)
+INSN(fsqrt_d,      ff)
+INSN(frecip_s,     ff)
+INSN(frecip_d,     ff)
+INSN(frsqrt_s,     ff)
+INSN(frsqrt_d,     ff)
+INSN(fmov_s,       ff)
+INSN(fmov_d,       ff)
+INSN(movgr2fr_w,   fr)
+INSN(movgr2fr_d,   fr)
+INSN(movgr2frh_w,  fr)
+INSN(movfr2gr_s,   rf)
+INSN(movfr2gr_d,   rf)
+INSN(movfrh2gr_s,  rf)
+INSN(movgr2fcsr,   fcsrd_r)
+INSN(movfcsr2gr,   r_fcsrs)
+INSN(movfr2cf,     cf)
+INSN(movcf2fr,     fc)
+INSN(movgr2cf,     cr)
+INSN(movcf2gr,     rc)
+INSN(fcvt_s_d,     ff)
+INSN(fcvt_d_s,     ff)
+INSN(ftintrm_w_s,  ff)
+INSN(ftintrm_w_d,  ff)
+INSN(ftintrm_l_s,  ff)
+INSN(ftintrm_l_d,  ff)
+INSN(ftintrp_w_s,  ff)
+INSN(ftintrp_w_d,  ff)
+INSN(ftintrp_l_s,  ff)
+INSN(ftintrp_l_d,  ff)
+INSN(ftintrz_w_s,  ff)
+INSN(ftintrz_w_d,  ff)
+INSN(ftintrz_l_s,  ff)
+INSN(ftintrz_l_d,  ff)
+INSN(ftintrne_w_s, ff)
+INSN(ftintrne_w_d, ff)
+INSN(ftintrne_l_s, ff)
+INSN(ftintrne_l_d, ff)
+INSN(ftint_w_s,    ff)
+INSN(ftint_w_d,    ff)
+INSN(ftint_l_s,    ff)
+INSN(ftint_l_d,    ff)
+INSN(ffint_s_w,    ff)
+INSN(ffint_s_l,    ff)
+INSN(ffint_d_w,    ff)
+INSN(ffint_d_l,    ff)
+INSN(frint_s,      ff)
+INSN(frint_d,      ff)
+INSN(slti,         rr_i)
+INSN(sltui,        rr_i)
+INSN(addi_w,       rr_i)
+INSN(addi_d,       rr_i)
+INSN(lu52i_d,      rr_i)
+INSN(andi,         rr_i)
+INSN(ori,          rr_i)
+INSN(xori,         rr_i)
+INSN(rdtimel_w,    rr)
+INSN(rdtimeh_w,    rr)
+INSN(fmadd_s,      ffff)
+INSN(fmadd_d,      ffff)
+INSN(fmsub_s,      ffff)
+INSN(fmsub_d,      ffff)
+INSN(fnmadd_s,     ffff)
+INSN(fnmadd_d,     ffff)
+INSN(fnmsub_s,     ffff)
+INSN(fnmsub_d,     ffff)
+INSN(fsel,         fffc)
+INSN(addu16i_d,    rr_i)
+INSN(lu12i_w,      r_i)
+INSN(lu32i_d,      r_i)
+INSN(pcaddi,       r_i)
+INSN(pcalau12i,    r_i)
+INSN(pcaddu12i,    r_i)
+INSN(pcaddu18i,    r_i)
+INSN(ll_w,         rr_i)
+INSN(sc_w,         rr_i)
+INSN(ll_d,         rr_i)
+INSN(sc_d,         rr_i)
+INSN(ldptr_w,      rr_i)
+INSN(stptr_w,      rr_i)
+INSN(ldptr_d,      rr_i)
+INSN(stptr_d,      rr_i)
+INSN(ld_b,         rr_i)
+INSN(ld_h,         rr_i)
+INSN(ld_w,         rr_i)
+INSN(ld_d,         rr_i)
+INSN(st_b,         rr_i)
+INSN(st_h,         rr_i)
+INSN(st_w,         rr_i)
+INSN(st_d,         rr_i)
+INSN(ld_bu,        rr_i)
+INSN(ld_hu,        rr_i)
+INSN(ld_wu,        rr_i)
+INSN(preld,        hint_r_i)
+INSN(fld_s,        fr_i)
+INSN(fst_s,        fr_i)
+INSN(fld_d,        fr_i)
+INSN(fst_d,        fr_i)
+INSN(ldx_b,        rrr)
+INSN(ldx_h,        rrr)
+INSN(ldx_w,        rrr)
+INSN(ldx_d,        rrr)
+INSN(stx_b,        rrr)
+INSN(stx_h,        rrr)
+INSN(stx_w,        rrr)
+INSN(stx_d,        rrr)
+INSN(ldx_bu,       rrr)
+INSN(ldx_hu,       rrr)
+INSN(ldx_wu,       rrr)
+INSN(fldx_s,       frr)
+INSN(fldx_d,       frr)
+INSN(fstx_s,       frr)
+INSN(fstx_d,       frr)
+INSN(amswap_w,     rrr)
+INSN(amswap_d,     rrr)
+INSN(amadd_w,      rrr)
+INSN(amadd_d,      rrr)
+INSN(amand_w,      rrr)
+INSN(amand_d,      rrr)
+INSN(amor_w,       rrr)
+INSN(amor_d,       rrr)
+INSN(amxor_w,      rrr)
+INSN(amxor_d,      rrr)
+INSN(ammax_w,      rrr)
+INSN(ammax_d,      rrr)
+INSN(ammin_w,      rrr)
+INSN(ammin_d,      rrr)
+INSN(ammax_wu,     rrr)
+INSN(ammax_du,     rrr)
+INSN(ammin_wu,     rrr)
+INSN(ammin_du,     rrr)
+INSN(amswap_db_w,  rrr)
+INSN(amswap_db_d,  rrr)
+INSN(amadd_db_w,   rrr)
+INSN(amadd_db_d,   rrr)
+INSN(amand_db_w,   rrr)
+INSN(amand_db_d,   rrr)
+INSN(amor_db_w,    rrr)
+INSN(amor_db_d,    rrr)
+INSN(amxor_db_w,   rrr)
+INSN(amxor_db_d,   rrr)
+INSN(ammax_db_w,   rrr)
+INSN(ammax_db_d,   rrr)
+INSN(ammin_db_w,   rrr)
+INSN(ammin_db_d,   rrr)
+INSN(ammax_db_wu,  rrr)
+INSN(ammax_db_du,  rrr)
+INSN(ammin_db_wu,  rrr)
+INSN(ammin_db_du,  rrr)
+INSN(dbar,         i)
+INSN(ibar,         i)
+INSN(fldgt_s,      frr)
+INSN(fldgt_d,      frr)
+INSN(fldle_s,      frr)
+INSN(fldle_d,      frr)
+INSN(fstgt_s,      frr)
+INSN(fstgt_d,      frr)
+INSN(fstle_s,      frr)
+INSN(fstle_d,      frr)
+INSN(ldgt_b,       rrr)
+INSN(ldgt_h,       rrr)
+INSN(ldgt_w,       rrr)
+INSN(ldgt_d,       rrr)
+INSN(ldle_b,       rrr)
+INSN(ldle_h,       rrr)
+INSN(ldle_w,       rrr)
+INSN(ldle_d,       rrr)
+INSN(stgt_b,       rrr)
+INSN(stgt_h,       rrr)
+INSN(stgt_w,       rrr)
+INSN(stgt_d,       rrr)
+INSN(stle_b,       rrr)
+INSN(stle_h,       rrr)
+INSN(stle_w,       rrr)
+INSN(stle_d,       rrr)
+INSN(beqz,         r_offs)
+INSN(bnez,         r_offs)
+INSN(bceqz,        c_offs)
+INSN(bcnez,        c_offs)
+INSN(jirl,         rr_offs)
+INSN(b,            offs)
+INSN(bl,           offs)
+INSN(beq,          rr_offs)
+INSN(bne,          rr_offs)
+INSN(blt,          rr_offs)
+INSN(bge,          rr_offs)
+INSN(bltu,         rr_offs)
+INSN(bgeu,         rr_offs)
+
+#define output_fcmp(C, PREFIX, SUFFIX)                                         \
+{                                                                              \
+    (C)->info->fprintf_func((C)->info->stream, "%08x   %s%s\tfcc%d, f%d, f%d", \
+                            (C)->insn, PREFIX, SUFFIX, a->cd,                  \
+                            a->fj, a->fk);                                     \
+}
+
+static bool output_cff_fcond(DisasContext *ctx, arg_cff_fcond * a,
+                               const char *suffix)
+{
+    bool ret = true;
+    switch (a->fcond) {
+    case 0x0:
+        output_fcmp(ctx, "fcmp_caf_", suffix);
+        break;
+    case 0x1:
+        output_fcmp(ctx, "fcmp_saf_", suffix);
+        break;
+    case 0x2:
+        output_fcmp(ctx, "fcmp_clt_", suffix);
+        break;
+    case 0x3:
+        output_fcmp(ctx, "fcmp_slt_", suffix);
+        break;
+    case 0x4:
+        output_fcmp(ctx, "fcmp_ceq_", suffix);
+        break;
+    case 0x5:
+        output_fcmp(ctx, "fcmp_seq_", suffix);
+        break;
+    case 0x6:
+        output_fcmp(ctx, "fcmp_cle_", suffix);
+        break;
+    case 0x7:
+        output_fcmp(ctx, "fcmp_sle_", suffix);
+        break;
+    case 0x8:
+        output_fcmp(ctx, "fcmp_cun_", suffix);
+        break;
+    case 0x9:
+        output_fcmp(ctx, "fcmp_sun_", suffix);
+        break;
+    case 0xA:
+        output_fcmp(ctx, "fcmp_cult_", suffix);
+        break;
+    case 0xB:
+        output_fcmp(ctx, "fcmp_sult_", suffix);
+        break;
+    case 0xC:
+        output_fcmp(ctx, "fcmp_cueq_", suffix);
+        break;
+    case 0xD:
+        output_fcmp(ctx, "fcmp_sueq_", suffix);
+        break;
+    case 0xE:
+        output_fcmp(ctx, "fcmp_cule_", suffix);
+        break;
+    case 0xF:
+        output_fcmp(ctx, "fcmp_sule_", suffix);
+        break;
+    case 0x10:
+        output_fcmp(ctx, "fcmp_cne_", suffix);
+        break;
+    case 0x11:
+        output_fcmp(ctx, "fcmp_sne_", suffix);
+        break;
+    case 0x14:
+        output_fcmp(ctx, "fcmp_cor_", suffix);
+        break;
+    case 0x15:
+        output_fcmp(ctx, "fcmp_sor_", suffix);
+        break;
+    case 0x18:
+        output_fcmp(ctx, "fcmp_cune_", suffix);
+        break;
+    case 0x19:
+        output_fcmp(ctx, "fcmp_sune_", suffix);
+        break;
+    default:
+        ret = false;
+    }
+    return ret;
+}
+
+#define FCMP_INSN(suffix)                               \
+static bool trans_fcmp_cond_##suffix(DisasContext *ctx, \
+                                     arg_cff_fcond * a) \
+{                                                       \
+    return output_cff_fcond(ctx, a, #suffix);           \
+}
+
+FCMP_INSN(s)
+FCMP_INSN(d)
-- 
2.27.0



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

* [PATCH v14 17/26] linux-user: Add LoongArch generic header files
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (15 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 16/26] target/loongarch: Add disassembler Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-06  9:41 ` [PATCH v14 18/26] linux-user: Add LoongArch specific structures Song Gao
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé

This includes:
- sockbits.h
- target_errno_defs.h
- target_fcntl.h
- termbits.h

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 linux-user/loongarch64/sockbits.h          | 11 +++++++++++
 linux-user/loongarch64/target_errno_defs.h | 12 ++++++++++++
 linux-user/loongarch64/target_fcntl.h      | 11 +++++++++++
 linux-user/loongarch64/termbits.h          | 11 +++++++++++
 4 files changed, 45 insertions(+)
 create mode 100644 linux-user/loongarch64/sockbits.h
 create mode 100644 linux-user/loongarch64/target_errno_defs.h
 create mode 100644 linux-user/loongarch64/target_fcntl.h
 create mode 100644 linux-user/loongarch64/termbits.h

diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h
new file mode 100644
index 0000000000..1cffcae120
--- /dev/null
+++ b/linux-user/loongarch64/sockbits.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_SOCKBITS_H
+#define LOONGARCH_TARGET_SOCKBITS_H
+
+#include "../generic/sockbits.h"
+
+#endif
diff --git a/linux-user/loongarch64/target_errno_defs.h b/linux-user/loongarch64/target_errno_defs.h
new file mode 100644
index 0000000000..c198b8aca9
--- /dev/null
+++ b/linux-user/loongarch64/target_errno_defs.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_ERRNO_DEFS_H
+#define LOONGARCH_TARGET_ERRNO_DEFS_H
+
+/* Target uses generic errno */
+#include "../generic/target_errno_defs.h"
+
+#endif
diff --git a/linux-user/loongarch64/target_fcntl.h b/linux-user/loongarch64/target_fcntl.h
new file mode 100644
index 0000000000..99bf586854
--- /dev/null
+++ b/linux-user/loongarch64/target_fcntl.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_FCNTL_H
+#define LOONGARCH_TARGET_FCNTL_H
+
+#include "../generic/fcntl.h"
+
+#endif
diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h
new file mode 100644
index 0000000000..d425db8748
--- /dev/null
+++ b/linux-user/loongarch64/termbits.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_TERMBITS_H
+#define LOONGARCH_TARGET_TERMBITS_H
+
+#include "../generic/termbits.h"
+
+#endif
-- 
2.27.0



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

* [PATCH v14 18/26] linux-user: Add LoongArch specific structures
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (16 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 17/26] linux-user: Add LoongArch generic header files Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-07  4:29   ` Richard Henderson
  2022-01-06  9:41 ` [PATCH v14 19/26] linux-user: Add LoongArch signal support Song Gao
                   ` (8 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
---
 linux-user/loongarch64/target_structs.h | 47 +++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 linux-user/loongarch64/target_structs.h

diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h
new file mode 100644
index 0000000000..8be3609fe8
--- /dev/null
+++ b/linux-user/loongarch64/target_structs.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch specific structures for linux-user
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_STRUCTS_H
+#define LOONGARCH_TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+    abi_int __key;                      /* Key.  */
+    abi_uint uid;                       /* Owner's user ID.  */
+    abi_uint gid;                       /* Owner's group ID.  */
+    abi_uint cuid;                      /* Creator's user ID.  */
+    abi_uint cgid;                      /* Creator's group ID.  */
+    abi_ushort mode;                    /* Read/write permission.  */
+    abi_ushort __pad1;
+    abi_ushort __seq;                   /* Sequence number.  */
+    abi_ushort __pad2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
+};
+
+struct target_shmid_ds {
+    struct target_ipc_perm shm_perm;    /* operation permission struct */
+    abi_long shm_segsz;                 /* size of segment in bytes */
+    abi_ulong shm_atime;                /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;                /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;                /* time of last change by shmctl() */
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    abi_int shm_cpid;                   /* pid of creator */
+    abi_int shm_lpid;                   /* pid of last shmop */
+    abi_ulong shm_nattch;               /* number of current attaches */
+    abi_ulong __unused4;
+    abi_ulong __unused5;
+};
+
+#endif
-- 
2.27.0



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

* [PATCH v14 19/26] linux-user: Add LoongArch signal support
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (17 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 18/26] linux-user: Add LoongArch specific structures Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-07  4:58   ` Richard Henderson
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 20/26] linux-user: Add LoongArch elf support Song Gao
                   ` (7 subsequent siblings)
  26 siblings, 2 replies; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
---
 linux-user/loongarch64/signal.c        | 198 +++++++++++++++++++++++++
 linux-user/loongarch64/target_signal.h |  13 ++
 2 files changed, 211 insertions(+)
 create mode 100644 linux-user/loongarch64/signal.c
 create mode 100644 linux-user/loongarch64/target_signal.h

diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c
new file mode 100644
index 0000000000..9f0e6421b2
--- /dev/null
+++ b/linux-user/loongarch64/signal.c
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation of Linux signals
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "signal-common.h"
+#include "user-internals.h"
+#include "linux-user/trace.h"
+
+#define FPU_REG_WIDTH 256
+union fpureg {
+    uint32_t val32[FPU_REG_WIDTH / 32];
+    uint64_t val64[FPU_REG_WIDTH / 64];
+};
+
+struct target_sigcontext {
+    uint64_t sc_pc;
+    uint64_t sc_regs[32];
+    uint32_t sc_flags;
+    uint32_t sc_fcsr;
+    uint32_t sc_vcsr;
+    uint64_t sc_fcc;
+    uint64_t sc_scr[4];
+    union fpureg sc_fpregs[32] __attribute__((aligned(32)));
+    uint8_t sc_reserved[4096] __attribute__((aligned(16)));
+};
+
+struct target_ucontext {
+    target_ulong tuc_flags;
+    struct target_ucontext *tuc_link;
+    target_stack_t tuc_stack;
+    target_sigset_t tuc_sigmask;
+    uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)];
+    struct target_sigcontext tuc_mcontext;
+};
+
+struct target_rt_sigframe {
+    struct target_siginfo rs_info;
+    struct target_ucontext rs_uc;
+};
+
+static uint64_t read_all_fcc(CPULoongArchState *env)
+{
+    uint64_t ret = 0;
+
+    for (int i = 0; i < 8; ++i) {
+        ret |= (uint64_t)env->cf[i] << (i * 8);
+    }
+
+    return ret;
+}
+
+static void write_all_fcc(CPULoongArchState *env, uint64_t val)
+{
+    for (int i = 0; i < 8; ++i) {
+        env->cf[i] = (val >> (i * 8)) & 1;
+    }
+}
+
+static inline void setup_sigcontext(CPULoongArchState *env,
+                                    struct target_sigcontext *sc)
+{
+    int i;
+
+    __put_user(env->pc, &sc->sc_pc);
+    __put_user(0, &sc->sc_regs[0]);
+    __put_user(env->fcsr0, &sc->sc_fcsr);
+    __put_user(0, &sc->sc_vcsr);
+    sc->sc_fcc = read_all_fcc(env);
+
+    for (i = 0; i < 4; ++i) {
+        __put_user(0, &sc->sc_scr[i]);
+    }
+
+    for (i = 1; i < 32; ++i) {
+        __put_user(env->gpr[i], &sc->sc_regs[i]);
+    }
+
+    for (i = 0; i < 32; ++i) {
+        __put_user(env->fpr[i], &sc->sc_fpregs[i].val64[0]);
+    }
+}
+
+static inline void
+restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc)
+{
+    int i;
+
+    __get_user(env->pc, &sc->sc_pc);
+    __get_user(env->fcsr0, &sc->sc_fcsr);
+    write_all_fcc(env, sc->sc_fcc);
+
+    for (i = 1; i < 32; ++i) {
+        __get_user(env->gpr[i], &sc->sc_regs[i]);
+    }
+
+    for (i = 0; i < 32; ++i) {
+        __get_user(env->fpr[i], &sc->sc_fpregs[i].val64[0]);
+    }
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline abi_ulong
+get_sigframe(struct target_sigaction *ka, CPULoongArchState *env,
+             size_t frame_size)
+{
+    unsigned long sp;
+
+    sp = target_sigsp(get_sp_from_cpustate(env) - 32, ka);
+
+    return (sp - frame_size) & ~15;
+}
+
+void setup_rt_frame(int sig, struct target_sigaction *ka,
+                    target_siginfo_t *info,
+                    target_sigset_t *set, CPULoongArchState *env)
+{
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    trace_user_setup_rt_frame(env, frame_addr);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }
+
+    tswap_siginfo(&frame->rs_info, info);
+
+    __put_user(0, &frame->rs_uc.tuc_flags);
+    __put_user(0, &frame->rs_uc.tuc_link);
+    target_save_altstack(&frame->rs_uc.tuc_stack, env);
+
+    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
+    }
+
+    env->gpr[4] = sig;
+    env->gpr[5] = frame_addr + offsetof(struct target_rt_sigframe, rs_info);
+    env->gpr[6] = frame_addr + offsetof(struct target_rt_sigframe, rs_uc);
+    env->gpr[3] = frame_addr;
+    env->gpr[1] = default_rt_sigreturn;
+
+    env->pc = ka->_sa_handler;
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+
+give_sigsegv:
+    unlock_user_struct(frame, frame_addr, 1);
+    force_sigsegv(sig);
+}
+
+long do_rt_sigreturn(CPULoongArchState *env)
+{
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr;
+    sigset_t blocked;
+
+    frame_addr = env->gpr[3];
+    trace_user_do_rt_sigreturn(env, frame_addr);
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
+
+    target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
+    set_sigmask(&blocked);
+
+    restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
+    target_restore_altstack(&frame->rs_uc.tuc_stack, env);
+
+    unlock_user_struct(frame, frame_addr, 0);
+    return -QEMU_ESIGRETURN;
+
+badframe:
+    unlock_user_struct(frame, frame_addr, 0);
+    force_sig(TARGET_SIGSEGV);
+    return -QEMU_ESIGRETURN;
+}
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
+    assert(tramp != NULL);
+
+    __put_user(0x03822c0b, tramp + 0);  /* ori     a7, zero, 0x8b */
+    __put_user(0x002b0000, tramp + 1);  /* syscall 0 */
+
+    default_rt_sigreturn = sigtramp_page;
+    unlock_user(tramp, sigtramp_page, 8);
+}
diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h
new file mode 100644
index 0000000000..ad3aaffcb4
--- /dev/null
+++ b/linux-user/loongarch64/target_signal.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_SIGNAL_H
+#define LOONGARCH_TARGET_SIGNAL_H
+
+#include "../generic/signal.h"
+
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
+#endif /* LOONGARCH_TARGET_SIGNAL_H */
-- 
2.27.0



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

* [PATCH v14 20/26] linux-user: Add LoongArch elf support
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (18 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 19/26] linux-user: Add LoongArch signal support Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 21/26] linux-user: Add LoongArch syscall support Song Gao
                   ` (6 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 linux-user/elfload.c                | 53 +++++++++++++++++++++++++++++
 linux-user/loongarch64/target_elf.h | 12 +++++++
 2 files changed, 65 insertions(+)
 create mode 100644 linux-user/loongarch64/target_elf.h

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 767f54c76d..2ee83778f2 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -914,6 +914,59 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
 
 #endif
 
+#ifdef TARGET_LOONGARCH64
+
+#define ELF_START_MMAP 0x80000000
+
+#define ELF_CLASS   ELFCLASS64
+#define ELF_ARCH    EM_LOONGARCH
+
+#define elf_check_arch(x) ((x) == EM_LOONGARCH)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
+{
+    regs->csr.crmd = 2 << 3;
+    regs->csr.era = infop->entry;
+    regs->regs[3] = infop->start_stack;
+}
+
+/* See linux kernel: arch/loongarch/include/asm/elf.h.  */
+#define ELF_NREG 45
+typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
+
+enum {
+    TARGET_EF_R0 = 0,
+    TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32,
+    TARGET_EF_CSR_BADV = TARGET_EF_R0 + 33,
+};
+
+static void elf_core_copy_regs(target_elf_gregset_t *regs,
+                               const CPULoongArchState *env)
+{
+    int i;
+
+    (*regs)[TARGET_EF_R0] = 0;
+
+    for (i = 1; i < ARRAY_SIZE(env->gpr); i++) {
+        (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]);
+    }
+
+    (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc);
+    (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->badaddr);
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE        4096
+
+#define ELF_HWCAP get_elf_hwcap()
+
+static uint32_t get_elf_hwcap(void)
+{
+    return 0;
+}
+
+#endif /* TARGET_LOONGARCH64 */
+
 #ifdef TARGET_MIPS
 
 #define ELF_START_MMAP 0x80000000
diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h
new file mode 100644
index 0000000000..3c690bbf5b
--- /dev/null
+++ b/linux-user/loongarch64/target_elf.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_ELF_H
+#define LOONGARCH_TARGET_ELF_H
+static inline const char *cpu_get_model(uint32_t eflags)
+{
+    return "Loongson-3A5000";
+}
+#endif
-- 
2.27.0



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

* [PATCH v14 21/26] linux-user: Add LoongArch syscall support
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (19 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 20/26] linux-user: Add LoongArch elf support Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 22/26] linux-user: Add LoongArch cpu_loop support Song Gao
                   ` (5 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé

We should disable '__BITS_PER_LONG' at [1] before run gensyscalls.sh

 [1] arch/loongarch/include/uapi/asm/bitsperlong.h

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 linux-user/loongarch64/syscall_nr.h     | 313 ++++++++++++++++++++++++
 linux-user/loongarch64/target_syscall.h |  48 ++++
 linux-user/syscall_defs.h               |  10 +-
 scripts/gensyscalls.sh                  |   1 +
 4 files changed, 368 insertions(+), 4 deletions(-)
 create mode 100644 linux-user/loongarch64/syscall_nr.h
 create mode 100644 linux-user/loongarch64/target_syscall.h

diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h
new file mode 100644
index 0000000000..713c824dee
--- /dev/null
+++ b/linux-user/loongarch64/syscall_nr.h
@@ -0,0 +1,313 @@
+/*
+ * This file contains the system call numbers.
+ * Do not modify.
+ * This file is generated by scripts/gensyscalls.sh
+ */
+#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H
+#define LINUX_USER_LOONGARCH_SYSCALL_NR_H
+
+#define TARGET_NR_io_setup 0
+#define TARGET_NR_io_destroy 1
+#define TARGET_NR_io_submit 2
+#define TARGET_NR_io_cancel 3
+#define TARGET_NR_io_getevents 4
+#define TARGET_NR_setxattr 5
+#define TARGET_NR_lsetxattr 6
+#define TARGET_NR_fsetxattr 7
+#define TARGET_NR_getxattr 8
+#define TARGET_NR_lgetxattr 9
+#define TARGET_NR_fgetxattr 10
+#define TARGET_NR_listxattr 11
+#define TARGET_NR_llistxattr 12
+#define TARGET_NR_flistxattr 13
+#define TARGET_NR_removexattr 14
+#define TARGET_NR_lremovexattr 15
+#define TARGET_NR_fremovexattr 16
+#define TARGET_NR_getcwd 17
+#define TARGET_NR_lookup_dcookie 18
+#define TARGET_NR_eventfd2 19
+#define TARGET_NR_epoll_create1 20
+#define TARGET_NR_epoll_ctl 21
+#define TARGET_NR_epoll_pwait 22
+#define TARGET_NR_dup 23
+#define TARGET_NR_dup3 24
+#define TARGET_NR_fcntl 25
+#define TARGET_NR_inotify_init1 26
+#define TARGET_NR_inotify_add_watch 27
+#define TARGET_NR_inotify_rm_watch 28
+#define TARGET_NR_ioctl 29
+#define TARGET_NR_ioprio_set 30
+#define TARGET_NR_ioprio_get 31
+#define TARGET_NR_flock 32
+#define TARGET_NR_mknodat 33
+#define TARGET_NR_mkdirat 34
+#define TARGET_NR_unlinkat 35
+#define TARGET_NR_symlinkat 36
+#define TARGET_NR_linkat 37
+#define TARGET_NR_umount2 39
+#define TARGET_NR_mount 40
+#define TARGET_NR_pivot_root 41
+#define TARGET_NR_nfsservctl 42
+#define TARGET_NR_statfs 43
+#define TARGET_NR_fstatfs 44
+#define TARGET_NR_truncate 45
+#define TARGET_NR_ftruncate 46
+#define TARGET_NR_fallocate 47
+#define TARGET_NR_faccessat 48
+#define TARGET_NR_chdir 49
+#define TARGET_NR_fchdir 50
+#define TARGET_NR_chroot 51
+#define TARGET_NR_fchmod 52
+#define TARGET_NR_fchmodat 53
+#define TARGET_NR_fchownat 54
+#define TARGET_NR_fchown 55
+#define TARGET_NR_openat 56
+#define TARGET_NR_close 57
+#define TARGET_NR_vhangup 58
+#define TARGET_NR_pipe2 59
+#define TARGET_NR_quotactl 60
+#define TARGET_NR_getdents64 61
+#define TARGET_NR_lseek 62
+#define TARGET_NR_read 63
+#define TARGET_NR_write 64
+#define TARGET_NR_readv 65
+#define TARGET_NR_writev 66
+#define TARGET_NR_pread64 67
+#define TARGET_NR_pwrite64 68
+#define TARGET_NR_preadv 69
+#define TARGET_NR_pwritev 70
+#define TARGET_NR_sendfile 71
+#define TARGET_NR_pselect6 72
+#define TARGET_NR_ppoll 73
+#define TARGET_NR_signalfd4 74
+#define TARGET_NR_vmsplice 75
+#define TARGET_NR_splice 76
+#define TARGET_NR_tee 77
+#define TARGET_NR_readlinkat 78
+#define TARGET_NR_newfstatat 79
+#define TARGET_NR_fstat 80
+#define TARGET_NR_sync 81
+#define TARGET_NR_fsync 82
+#define TARGET_NR_fdatasync 83
+#define TARGET_NR_sync_file_range 84
+#define TARGET_NR_timerfd_create 85
+#define TARGET_NR_timerfd_settime 86
+#define TARGET_NR_timerfd_gettime 87
+#define TARGET_NR_utimensat 88
+#define TARGET_NR_acct 89
+#define TARGET_NR_capget 90
+#define TARGET_NR_capset 91
+#define TARGET_NR_personality 92
+#define TARGET_NR_exit 93
+#define TARGET_NR_exit_group 94
+#define TARGET_NR_waitid 95
+#define TARGET_NR_set_tid_address 96
+#define TARGET_NR_unshare 97
+#define TARGET_NR_futex 98
+#define TARGET_NR_set_robust_list 99
+#define TARGET_NR_get_robust_list 100
+#define TARGET_NR_nanosleep 101
+#define TARGET_NR_getitimer 102
+#define TARGET_NR_setitimer 103
+#define TARGET_NR_kexec_load 104
+#define TARGET_NR_init_module 105
+#define TARGET_NR_delete_module 106
+#define TARGET_NR_timer_create 107
+#define TARGET_NR_timer_gettime 108
+#define TARGET_NR_timer_getoverrun 109
+#define TARGET_NR_timer_settime 110
+#define TARGET_NR_timer_delete 111
+#define TARGET_NR_clock_settime 112
+#define TARGET_NR_clock_gettime 113
+#define TARGET_NR_clock_getres 114
+#define TARGET_NR_clock_nanosleep 115
+#define TARGET_NR_syslog 116
+#define TARGET_NR_ptrace 117
+#define TARGET_NR_sched_setparam 118
+#define TARGET_NR_sched_setscheduler 119
+#define TARGET_NR_sched_getscheduler 120
+#define TARGET_NR_sched_getparam 121
+#define TARGET_NR_sched_setaffinity 122
+#define TARGET_NR_sched_getaffinity 123
+#define TARGET_NR_sched_yield 124
+#define TARGET_NR_sched_get_priority_max 125
+#define TARGET_NR_sched_get_priority_min 126
+#define TARGET_NR_sched_rr_get_interval 127
+#define TARGET_NR_restart_syscall 128
+#define TARGET_NR_kill 129
+#define TARGET_NR_tkill 130
+#define TARGET_NR_tgkill 131
+#define TARGET_NR_sigaltstack 132
+#define TARGET_NR_rt_sigsuspend 133
+#define TARGET_NR_rt_sigaction 134
+#define TARGET_NR_rt_sigprocmask 135
+#define TARGET_NR_rt_sigpending 136
+#define TARGET_NR_rt_sigtimedwait 137
+#define TARGET_NR_rt_sigqueueinfo 138
+#define TARGET_NR_rt_sigreturn 139
+#define TARGET_NR_setpriority 140
+#define TARGET_NR_getpriority 141
+#define TARGET_NR_reboot 142
+#define TARGET_NR_setregid 143
+#define TARGET_NR_setgid 144
+#define TARGET_NR_setreuid 145
+#define TARGET_NR_setuid 146
+#define TARGET_NR_setresuid 147
+#define TARGET_NR_getresuid 148
+#define TARGET_NR_setresgid 149
+#define TARGET_NR_getresgid 150
+#define TARGET_NR_setfsuid 151
+#define TARGET_NR_setfsgid 152
+#define TARGET_NR_times 153
+#define TARGET_NR_setpgid 154
+#define TARGET_NR_getpgid 155
+#define TARGET_NR_getsid 156
+#define TARGET_NR_setsid 157
+#define TARGET_NR_getgroups 158
+#define TARGET_NR_setgroups 159
+#define TARGET_NR_uname 160
+#define TARGET_NR_sethostname 161
+#define TARGET_NR_setdomainname 162
+#define TARGET_NR_getrusage 165
+#define TARGET_NR_umask 166
+#define TARGET_NR_prctl 167
+#define TARGET_NR_getcpu 168
+#define TARGET_NR_gettimeofday 169
+#define TARGET_NR_settimeofday 170
+#define TARGET_NR_adjtimex 171
+#define TARGET_NR_getpid 172
+#define TARGET_NR_getppid 173
+#define TARGET_NR_getuid 174
+#define TARGET_NR_geteuid 175
+#define TARGET_NR_getgid 176
+#define TARGET_NR_getegid 177
+#define TARGET_NR_gettid 178
+#define TARGET_NR_sysinfo 179
+#define TARGET_NR_mq_open 180
+#define TARGET_NR_mq_unlink 181
+#define TARGET_NR_mq_timedsend 182
+#define TARGET_NR_mq_timedreceive 183
+#define TARGET_NR_mq_notify 184
+#define TARGET_NR_mq_getsetattr 185
+#define TARGET_NR_msgget 186
+#define TARGET_NR_msgctl 187
+#define TARGET_NR_msgrcv 188
+#define TARGET_NR_msgsnd 189
+#define TARGET_NR_semget 190
+#define TARGET_NR_semctl 191
+#define TARGET_NR_semtimedop 192
+#define TARGET_NR_semop 193
+#define TARGET_NR_shmget 194
+#define TARGET_NR_shmctl 195
+#define TARGET_NR_shmat 196
+#define TARGET_NR_shmdt 197
+#define TARGET_NR_socket 198
+#define TARGET_NR_socketpair 199
+#define TARGET_NR_bind 200
+#define TARGET_NR_listen 201
+#define TARGET_NR_accept 202
+#define TARGET_NR_connect 203
+#define TARGET_NR_getsockname 204
+#define TARGET_NR_getpeername 205
+#define TARGET_NR_sendto 206
+#define TARGET_NR_recvfrom 207
+#define TARGET_NR_setsockopt 208
+#define TARGET_NR_getsockopt 209
+#define TARGET_NR_shutdown 210
+#define TARGET_NR_sendmsg 211
+#define TARGET_NR_recvmsg 212
+#define TARGET_NR_readahead 213
+#define TARGET_NR_brk 214
+#define TARGET_NR_munmap 215
+#define TARGET_NR_mremap 216
+#define TARGET_NR_add_key 217
+#define TARGET_NR_request_key 218
+#define TARGET_NR_keyctl 219
+#define TARGET_NR_clone 220
+#define TARGET_NR_execve 221
+#define TARGET_NR_mmap 222
+#define TARGET_NR_fadvise64 223
+#define TARGET_NR_swapon 224
+#define TARGET_NR_swapoff 225
+#define TARGET_NR_mprotect 226
+#define TARGET_NR_msync 227
+#define TARGET_NR_mlock 228
+#define TARGET_NR_munlock 229
+#define TARGET_NR_mlockall 230
+#define TARGET_NR_munlockall 231
+#define TARGET_NR_mincore 232
+#define TARGET_NR_madvise 233
+#define TARGET_NR_remap_file_pages 234
+#define TARGET_NR_mbind 235
+#define TARGET_NR_get_mempolicy 236
+#define TARGET_NR_set_mempolicy 237
+#define TARGET_NR_migrate_pages 238
+#define TARGET_NR_move_pages 239
+#define TARGET_NR_rt_tgsigqueueinfo 240
+#define TARGET_NR_perf_event_open 241
+#define TARGET_NR_accept4 242
+#define TARGET_NR_recvmmsg 243
+#define TARGET_NR_arch_specific_syscall 244
+#define TARGET_NR_wait4 260
+#define TARGET_NR_prlimit64 261
+#define TARGET_NR_fanotify_init 262
+#define TARGET_NR_fanotify_mark 263
+#define TARGET_NR_name_to_handle_at 264
+#define TARGET_NR_open_by_handle_at 265
+#define TARGET_NR_clock_adjtime 266
+#define TARGET_NR_syncfs 267
+#define TARGET_NR_setns 268
+#define TARGET_NR_sendmmsg 269
+#define TARGET_NR_process_vm_readv 270
+#define TARGET_NR_process_vm_writev 271
+#define TARGET_NR_kcmp 272
+#define TARGET_NR_finit_module 273
+#define TARGET_NR_sched_setattr 274
+#define TARGET_NR_sched_getattr 275
+#define TARGET_NR_renameat2 276
+#define TARGET_NR_seccomp 277
+#define TARGET_NR_getrandom 278
+#define TARGET_NR_memfd_create 279
+#define TARGET_NR_bpf 280
+#define TARGET_NR_execveat 281
+#define TARGET_NR_userfaultfd 282
+#define TARGET_NR_membarrier 283
+#define TARGET_NR_mlock2 284
+#define TARGET_NR_copy_file_range 285
+#define TARGET_NR_preadv2 286
+#define TARGET_NR_pwritev2 287
+#define TARGET_NR_pkey_mprotect 288
+#define TARGET_NR_pkey_alloc 289
+#define TARGET_NR_pkey_free 290
+#define TARGET_NR_statx 291
+#define TARGET_NR_io_pgetevents 292
+#define TARGET_NR_rseq 293
+#define TARGET_NR_kexec_file_load 294
+#define TARGET_NR_pidfd_send_signal 424
+#define TARGET_NR_io_uring_setup 425
+#define TARGET_NR_io_uring_enter 426
+#define TARGET_NR_io_uring_register 427
+#define TARGET_NR_open_tree 428
+#define TARGET_NR_move_mount 429
+#define TARGET_NR_fsopen 430
+#define TARGET_NR_fsconfig 431
+#define TARGET_NR_fsmount 432
+#define TARGET_NR_fspick 433
+#define TARGET_NR_pidfd_open 434
+#define TARGET_NR_clone3 435
+#define TARGET_NR_close_range 436
+#define TARGET_NR_openat2 437
+#define TARGET_NR_pidfd_getfd 438
+#define TARGET_NR_faccessat2 439
+#define TARGET_NR_process_madvise 440
+#define TARGET_NR_epoll_pwait2 441
+#define TARGET_NR_mount_setattr 442
+#define TARGET_NR_quotactl_fd 443
+#define TARGET_NR_landlock_create_ruleset 444
+#define TARGET_NR_landlock_add_rule 445
+#define TARGET_NR_landlock_restrict_self 446
+#define TARGET_NR_process_mrelease 448
+#define TARGET_NR_futex_waitv 449
+#define TARGET_NR_syscalls 450
+
+#endif /* LINUX_USER_LOONGARCH_SYSCALL_NR_H */
diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h
new file mode 100644
index 0000000000..9391f49135
--- /dev/null
+++ b/linux-user/loongarch64/target_syscall.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_SYSCALL_H
+#define LOONGARCH_TARGET_SYSCALL_H
+
+#include "qemu/units.h"
+
+/*
+ * this struct defines the way the registers are stored on the
+ * stack during a system call.
+ */
+
+struct target_pt_regs {
+    /* Saved main processor registers. */
+    target_ulong regs[32];
+
+    /* Saved special registers. */
+    struct {
+        target_ulong era;
+        target_ulong badv;
+        target_ulong crmd;
+        target_ulong prmd;
+        target_ulong euen;
+        target_ulong ecfg;
+        target_ulong estat;
+    } csr;
+    target_ulong orig_a0;
+    target_ulong __last[0];
+};
+
+#define UNAME_MACHINE "loongarch64"
+#define UNAME_MINIMUM_RELEASE "5.16.0"
+
+#define TARGET_MCL_CURRENT 1
+#define TARGET_MCL_FUTURE  2
+#define TARGET_MCL_ONFAULT 4
+
+#define TARGET_FORCE_SHMLBA
+
+static inline abi_ulong target_shmlba(CPULoongArchState *env)
+{
+    return 64 * KiB;
+}
+
+#endif
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 0b13975937..2a675bde64 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -74,7 +74,7 @@
     || defined(TARGET_M68K) || defined(TARGET_CRIS) \
     || defined(TARGET_S390X) || defined(TARGET_OPENRISC) \
     || defined(TARGET_NIOS2) || defined(TARGET_RISCV) \
-    || defined(TARGET_XTENSA)
+    || defined(TARGET_XTENSA) || defined(TARGET_LOONGARCH64)
 
 #define TARGET_IOC_SIZEBITS	14
 #define TARGET_IOC_DIRBITS	2
@@ -2133,7 +2133,8 @@ struct target_stat64  {
     abi_ulong __unused5;
 };
 
-#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV)
+#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || \
+      defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64)
 
 /* These are the asm-generic versions of the stat and stat64 structures */
 
@@ -2161,7 +2162,7 @@ struct target_stat {
     unsigned int __unused5;
 };
 
-#if !defined(TARGET_RISCV64)
+#if !defined(TARGET_RISCV64) && !defined(TARGET_LOONGARCH64)
 #define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
     uint64_t st_dev;
@@ -2331,7 +2332,8 @@ struct target_statfs64 {
 };
 #elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \
        defined(TARGET_SPARC64) || defined(TARGET_AARCH64) || \
-       defined(TARGET_RISCV)) && !defined(TARGET_ABI32)
+       defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64)) && \
+       !defined(TARGET_ABI32)
 struct target_statfs {
 	abi_long f_type;
 	abi_long f_bsize;
diff --git a/scripts/gensyscalls.sh b/scripts/gensyscalls.sh
index 8fb450e3c9..b69e1938ab 100755
--- a/scripts/gensyscalls.sh
+++ b/scripts/gensyscalls.sh
@@ -99,4 +99,5 @@ generate_syscall_nr openrisc 32 "$output/linux-user/openrisc/syscall_nr.h"
 generate_syscall_nr riscv 32 "$output/linux-user/riscv/syscall32_nr.h"
 generate_syscall_nr riscv 64 "$output/linux-user/riscv/syscall64_nr.h"
 generate_syscall_nr hexagon 32 "$output/linux-user/hexagon/syscall_nr.h"
+generate_syscall_nr loongarch 64 "$output/linux-user/loongarch64/syscall_nr.h"
 rm -fr "$TMP"
-- 
2.27.0



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

* [PATCH v14 22/26] linux-user: Add LoongArch cpu_loop support
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (20 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 21/26] linux-user: Add LoongArch syscall support Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 23/26] default-configs: Add loongarch linux-user support Song Gao
                   ` (4 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 configure                           |  3 +
 linux-user/loongarch64/cpu_loop.c   | 94 +++++++++++++++++++++++++++++
 linux-user/loongarch64/target_cpu.h | 34 +++++++++++
 3 files changed, 131 insertions(+)
 create mode 100644 linux-user/loongarch64/cpu_loop.c
 create mode 100644 linux-user/loongarch64/target_cpu.h

diff --git a/configure b/configure
index 030728d11e..93c4e5bd92 100755
--- a/configure
+++ b/configure
@@ -659,6 +659,9 @@ case "$cpu" in
   mips*)
     cpu="mips" ;;
 
+  loongarch)
+    cpu="loongarch64" ;;
+
   ppc)
     CPU_CFLAGS="-m32" ;;
   ppc64)
diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c
new file mode 100644
index 0000000000..6628d215ca
--- /dev/null
+++ b/linux-user/loongarch64/cpu_loop.c
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch user cpu_loop.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "qemu-common.h"
+#include "user-internals.h"
+#include "cpu_loop-common.h"
+#include "signal-common.h"
+
+void cpu_loop(CPULoongArchState *env)
+{
+    CPUState *cs = env_cpu(env);
+    int trapnr, si_code;
+    abi_long ret;
+
+    for (;;) {
+        cpu_exec_start(cs);
+        trapnr = cpu_exec(cs);
+        cpu_exec_end(cs);
+        process_queued_cpu_work(cs);
+
+        switch (trapnr) {
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+        case EXCP_SYSCALL:
+            env->pc += 4;
+            ret = do_syscall(env, env->gpr[11],
+                             env->gpr[4], env->gpr[5],
+                             env->gpr[6], env->gpr[7],
+                             env->gpr[8], env->gpr[9],
+                             -1, -1);
+            if (ret == -QEMU_ERESTARTSYS) {
+                env->pc -= 4;
+                break;
+            }
+            if (ret == -QEMU_ESIGRETURN) {
+                /*
+                 * Returning from a successful sigreturn syscall.
+                 * Avoid clobbering register state.
+                 */
+                break;
+            }
+            env->gpr[4] = ret;
+            break;
+        case EXCP_INE:
+            force_sig_fault(TARGET_SIGILL, 0, env->pc);
+            break;
+        case EXCP_FPE:
+            si_code = TARGET_FPE_FLTUNK;
+            if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) {
+                si_code = TARGET_FPE_FLTINV;
+            } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) {
+                si_code = TARGET_FPE_FLTDIV;
+            } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) {
+                si_code = TARGET_FPE_FLTOVF;
+            } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) {
+                si_code = TARGET_FPE_FLTUND;
+            } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) {
+                si_code = TARGET_FPE_FLTRES;
+            }
+            force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
+            break;
+        case EXCP_DEBUG:
+        case EXCP_BREAK:
+            force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
+            break;
+        case EXCP_ATOMIC:
+            cpu_exec_step_atomic(cs);
+            break;
+        default:
+            EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
+                      trapnr);
+            exit(EXIT_FAILURE);
+        }
+        process_pending_signals(env);
+    }
+}
+
+void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
+{
+    int i;
+
+    for (i = 0; i < 32; i++) {
+        env->gpr[i] = regs->regs[i];
+    }
+    env->pc = regs->csr.era;
+
+}
diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h
new file mode 100644
index 0000000000..a29af66156
--- /dev/null
+++ b/linux-user/loongarch64/target_cpu.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_CPU_H
+#define LOONGARCH_TARGET_CPU_H
+
+static inline void cpu_clone_regs_child(CPULoongArchState *env,
+                                        target_ulong newsp, unsigned flags)
+{
+    if (newsp) {
+        env->gpr[3] = newsp;
+    }
+    env->gpr[4] = 0;
+}
+
+static inline void cpu_clone_regs_parent(CPULoongArchState *env,
+                                         unsigned flags)
+{
+}
+
+static inline void cpu_set_tls(CPULoongArchState *env, target_ulong newtls)
+{
+    env->gpr[2] = newtls;
+}
+
+static inline abi_ulong get_sp_from_cpustate(CPULoongArchState *state)
+{
+    return state->gpr[3];
+}
+#endif
-- 
2.27.0



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

* [PATCH v14 23/26] default-configs: Add loongarch linux-user support
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (21 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 22/26] linux-user: Add LoongArch cpu_loop support Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 24/26] target/loongarch: Add target build suport Song Gao
                   ` (3 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

This patch adds loongarch64 linux-user default configs file.

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 configs/targets/loongarch64-linux-user.mak | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 configs/targets/loongarch64-linux-user.mak

diff --git a/configs/targets/loongarch64-linux-user.mak b/configs/targets/loongarch64-linux-user.mak
new file mode 100644
index 0000000000..5b0acfa3ec
--- /dev/null
+++ b/configs/targets/loongarch64-linux-user.mak
@@ -0,0 +1,3 @@
+# Default configuration for loongson64-linux-user
+TARGET_ARCH=loongarch64
+TARGET_BASE_ARCH=loongarch
-- 
2.27.0



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

* [PATCH v14 24/26] target/loongarch: Add target build suport
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (22 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 23/26] default-configs: Add loongarch linux-user support Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:41 ` [PATCH v14 25/26] target/loongarch: 'make check-tcg' support Song Gao
                   ` (2 subsequent siblings)
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé

This patch adds build loongarch-linux-user target support.

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 target/loongarch/meson.build | 19 +++++++++++++++++++
 target/meson.build           |  1 +
 2 files changed, 20 insertions(+)
 create mode 100644 target/loongarch/meson.build

diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
new file mode 100644
index 0000000000..bcb076e55f
--- /dev/null
+++ b/target/loongarch/meson.build
@@ -0,0 +1,19 @@
+gen = decodetree.process('insns.decode')
+
+loongarch_ss = ss.source_set()
+loongarch_ss.add(files(
+  'cpu.c',
+  'disas.c',
+))
+loongarch_tcg_ss = ss.source_set()
+loongarch_tcg_ss.add(gen)
+loongarch_tcg_ss.add(files(
+  'fpu_helper.c',
+  'op_helper.c',
+  'translate.c',
+))
+loongarch_tcg_ss.add(zlib)
+
+loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
+
+target_arch += {'loongarch': loongarch_ss}
diff --git a/target/meson.build b/target/meson.build
index 2f6940255e..a53a60486f 100644
--- a/target/meson.build
+++ b/target/meson.build
@@ -5,6 +5,7 @@ subdir('cris')
 subdir('hexagon')
 subdir('hppa')
 subdir('i386')
+subdir('loongarch')
 subdir('m68k')
 subdir('microblaze')
 subdir('mips')
-- 
2.27.0



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

* [PATCH v14 25/26] target/loongarch: 'make check-tcg' support
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (23 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 24/26] target/loongarch: Add target build suport Song Gao
@ 2022-01-06  9:41 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-06  9:42 ` [PATCH v14 26/26] scripts: add loongarch64 binfmt config Song Gao
  2022-01-07  5:01 ` [PATCH v14 00/26] Add LoongArch linux-user emulation support Richard Henderson
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Xiaojuan Yang, Richard Henderson,
	Philippe Mathieu-Daudé

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Acked-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 tests/tcg/configure.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index 8eb4287c84..c3d7e45524 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -51,6 +51,7 @@ fi
 : ${cross_cc_cflags_armeb="-mbig-endian"}
 : ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"}
 : ${cross_cc_cflags_hexagon="-mv67 -O2 -static"}
+: ${cross_cc_loongarch64="loongarch64-unknown-linux-gnu-gcc"}
 : ${cross_cc_hppa="hppa-linux-gnu-gcc"}
 : ${cross_cc_i386="i686-linux-gnu-gcc"}
 : ${cross_cc_cflags_i386="-m32"}
-- 
2.27.0



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

* [PATCH v14 26/26] scripts: add loongarch64 binfmt config
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (24 preceding siblings ...)
  2022-01-06  9:41 ` [PATCH v14 25/26] target/loongarch: 'make check-tcg' support Song Gao
@ 2022-01-06  9:42 ` Song Gao
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-07  5:01 ` [PATCH v14 00/26] Add LoongArch linux-user emulation support Richard Henderson
  26 siblings, 1 reply; 53+ messages in thread
From: Song Gao @ 2022-01-06  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 scripts/qemu-binfmt-conf.sh | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
index 7de996d536..da6a937be8 100755
--- a/scripts/qemu-binfmt-conf.sh
+++ b/scripts/qemu-binfmt-conf.sh
@@ -4,7 +4,7 @@
 qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \
 ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \
 sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
-microblaze microblazeel or1k x86_64 hexagon"
+microblaze microblazeel or1k x86_64 hexagon loongarch64"
 
 i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
 i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
@@ -140,6 +140,10 @@ hexagon_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x
 hexagon_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
 hexagon_family=hexagon
 
+loongarch64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02\x01'
+loongarch64_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+loongarch64_family=loongarch
+
 qemu_get_family() {
     cpu=${HOST_ARCH:-$(uname -m)}
     case "$cpu" in
-- 
2.27.0



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

* Re: [PATCH v14 18/26] linux-user: Add LoongArch specific structures
  2022-01-06  9:41 ` [PATCH v14 18/26] linux-user: Add LoongArch specific structures Song Gao
@ 2022-01-07  4:29   ` Richard Henderson
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2022-01-07  4:29 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang

On 1/6/22 1:41 AM, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> ---
>   linux-user/loongarch64/target_structs.h | 47 +++++++++++++++++++++++++
>   1 file changed, 47 insertions(+)
>   create mode 100644 linux-user/loongarch64/target_structs.h

I've just sent a patch set such that this need be nothing but a re-include of 
generic/target_structs.h.


r~


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

* Re: [PATCH v14 19/26] linux-user: Add LoongArch signal support
  2022-01-06  9:41 ` [PATCH v14 19/26] linux-user: Add LoongArch signal support Song Gao
@ 2022-01-07  4:58   ` Richard Henderson
  2022-01-09  9:25   ` WANG Xuerui
  1 sibling, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2022-01-07  4:58 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang

On 1/6/22 1:41 AM, Song Gao wrote:
> +struct target_sigcontext {
> +    uint64_t sc_pc;
> +    uint64_t sc_regs[32];
> +    uint32_t sc_flags;
> +    uint32_t sc_fcsr;
> +    uint32_t sc_vcsr;
> +    uint64_t sc_fcc;
> +    uint64_t sc_scr[4];
> +    union fpureg sc_fpregs[32] __attribute__((aligned(32)));
> +    uint8_t sc_reserved[4096] __attribute__((aligned(16)));
> +};

Does not match the current (December 31) kernel source.

> +static inline void setup_sigcontext(CPULoongArchState *env,
> +                                    struct target_sigcontext *sc)

Don't bother with inline markers anywhere in this file.  Let the compiler decide.

> +restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc)
> +{
> +    int i;
> +
> +    __get_user(env->pc, &sc->sc_pc);
> +    __get_user(env->fcsr0, &sc->sc_fcsr);

You need to call restore_fp_status after this assignment, somewhere before the end of the 
function.

Otherwise this looks ok.


r~


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

* Re: [PATCH v14 00/26] Add LoongArch linux-user emulation support
  2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
                   ` (25 preceding siblings ...)
  2022-01-06  9:42 ` [PATCH v14 26/26] scripts: add loongarch64 binfmt config Song Gao
@ 2022-01-07  5:01 ` Richard Henderson
  2022-01-07  7:59   ` gaosong
  26 siblings, 1 reply; 53+ messages in thread
From: Richard Henderson @ 2022-01-07  5:01 UTC (permalink / raw)
  To: Song Gao, qemu-devel

On 1/6/22 1:41 AM, Song Gao wrote:
> Based-on:<20220106074740.1754661-1-gaosong@loongson.cn>
> 
> Hi all,
> 
> This series only support linux-user emulation.
> More about LoongArch at:https://github.com/loongson/
> 
> The latest kernel:
>    *https://github.com/loongson/linux/tree/loongarch-next
> 
> Patches need review:
>    * 0018-linux-user-Add-LoongArch-specific-structures.patch
>    * 0019-linux-user-Add-LoongArch-signal-support.patch

You're still blocked on no upstream kernel support.
As shown in patch 19, the kernel abi is still in flux.

It would be best if you could work toward getting full system emulation completed.  Then 
all of the basic cpu emulation can be merged and all you'd need to keep updating is the 
linux-user portions.


r~


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

* Re: [PATCH v14 00/26] Add LoongArch linux-user emulation support
  2022-01-07  5:01 ` [PATCH v14 00/26] Add LoongArch linux-user emulation support Richard Henderson
@ 2022-01-07  7:59   ` gaosong
  2022-01-09  5:09     ` WANG Xuerui
  0 siblings, 1 reply; 53+ messages in thread
From: gaosong @ 2022-01-07  7:59 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1051 bytes --]

Hi Richard.

On 2022/1/7 下午1:01, Richard Henderson wrote:
> On 1/6/22 1:41 AM, Song Gao wrote:
>> Based-on:<20220106074740.1754661-1-gaosong@loongson.cn>
>>
>> Hi all,
>>
>> This series only support linux-user emulation.
>> More about LoongArch at:https://github.com/loongson/
>>
>> The latest kernel:
>>    *https://github.com/loongson/linux/tree/loongarch-next
>>
>> Patches need review:
>>    * 0018-linux-user-Add-LoongArch-specific-structures.patch
>>    * 0019-linux-user-Add-LoongArch-signal-support.patch
>
> You're still blocked on no upstream kernel support.
> As shown in patch 19, the kernel abi is still in flux.
>
We hope the kernel will support as soon as possible. but ...

> It would be best if you could work toward getting full system 
> emulation completed.  Then all of the basic cpu emulation can be 
> merged and all you'd need to keep updating is the linux-user portions.
>
We are going to submit V4 system emulation, maybe tommorrow or next-week, and We'll keep updating the linux-user portions.

Thanks
Song

> r~

[-- Attachment #2: Type: text/html, Size: 2232 bytes --]

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

* Re: [PATCH v14 00/26] Add LoongArch linux-user emulation support
  2022-01-07  7:59   ` gaosong
@ 2022-01-09  5:09     ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  5:09 UTC (permalink / raw)
  To: gaosong, Richard Henderson; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2405 bytes --]

Hi,

On 1/7/22 15:59, gaosong wrote:
> Hi Richard.
> On 2022/1/7 下午1:01, Richard Henderson wrote:
>> On 1/6/22 1:41 AM, Song Gao wrote:
>>> Based-on:<20220106074740.1754661-1-gaosong@loongson.cn>
>>>
>>> Hi all,
>>>
>>> This series only support linux-user emulation.
>>> More about LoongArch at:https://github.com/loongson/
>>>
>>> The latest kernel:
>>>    *https://github.com/loongson/linux/tree/loongarch-next
>>>
>>> Patches need review:
>>>    * 0018-linux-user-Add-LoongArch-specific-structures.patch
>>>    * 0019-linux-user-Add-LoongArch-signal-support.patch
>>
>> You're still blocked on no upstream kernel support.
>> As shown in patch 19, the kernel abi is still in flux.
>>
> We hope the kernel will support as soon as possible. but ...
>> It would be best if you could work toward getting full system 
>> emulation completed.  Then all of the basic cpu emulation can be 
>> merged and all you'd need to keep updating is the linux-user portions.
>>
> We are going to submit V4 system emulation, maybe tommorrow or next-week, and We'll keep updating the linux-user portions.

I believe what Richard meant is suggesting you to re-order your patches 
so that the CPU emulation part (first half of this series) and the 
system emulation part (Xiaojuan's series) would be combined to one new 
series, to be reviewed and merged independent of the still-unstable 
Linux ABI that's blocking this series at the moment. To "keep updating 
the linux-user portions" without re-arranging the series will just delay 
inclusion further, IMO.

In case the description above is not clear enough:

We basically have 3 parts for full LoongArch target support: (a) CPU 
emulation, (b) privileged architecture & hw emulation, and (c) 
linux-user emulation. Currently this series consists of (a) and (c), 
while Xiaojuan's series has (b). And the tcg-dev branch you seem to be 
staging your work at [1] has the same ordering: (a) then (c) then (b), 
which is consistent with Xiaojuan's series cover letter.

However, because (c) is blocked by kernel port upstreaming, (a) could 
not be merged, and by re-combining (a) with (b) we can speed up review 
and inclusion of things. This would require you to coordinate with 
Xiaojuan and reorder your patches in the tcg-dev branch, so that you can 
generate the right series to send.

[1]: https://github.com/loongson/qemu/tree/tcg-dev

>
> Thanks
> Song
>> r~

[-- Attachment #2: Type: text/html, Size: 4328 bytes --]

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

* Re: [PATCH v14 01/26] target/loongarch: Add README
  2022-01-06  9:41 ` [PATCH v14 01/26] target/loongarch: Add README Song Gao
@ 2022-01-09  9:24   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:24 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson


On 1/6/22 17:41, Song Gao wrote:
> This patch gives an introduction to the LoongArch target.
>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> ---
>   MAINTAINERS             |  5 +++
>   target/loongarch/README | 77 +++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 82 insertions(+)
>   create mode 100644 target/loongarch/README
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f871d759fd..2df0d4a7c2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -213,6 +213,11 @@ S: Maintained
>   F: target/hppa/
>   F: disas/hppa.c
>   
> +LoongArch TCG CPUS
"TCG CPUs" -- notice the case for the plural "s".
> +M: Song Gao<gaosong@loongson.cn>
> +S: Maintained
> +F: target/loongarch/
> +
>   M68K TCG CPUs
>   M: Laurent Vivier<laurent@vivier.eu>
>   S: Maintained
> diff --git a/target/loongarch/README b/target/loongarch/README
> new file mode 100644
> index 0000000000..d5780c5918
> --- /dev/null
> +++ b/target/loongarch/README
> @@ -0,0 +1,77 @@
> +- Introduction
> +
> +  LoongArch is the general processor architecture of Loongson.
> +
> +  The following versions of the LoongArch core are supported
> +    core: 3A5000
> +https://github.com/loongson/LoongArch-Documentation/releases/download/2021.08.17/LoongArch-Vol1-v1.00-EN.pdf
> +
> +  We can get the latest loongarch documents athttps://github.com/loongson/LoongArch-Documentation/tags.
> +
> +
> +- Linux-user emulation
> +
> +  We already support Linux user emulation. We can use LoongArch cross-tools to build LoongArch executables on X86 machines,
> +  and We can also use qemu-loongarch64 to run LoongArch executables.
> +
> +  1. Install LoongArch cross-tools on X86 machines.
> +
> +    Download cross-tools.
> +
> +      wgethttps://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20211202-cross-tools.tar.xz
> +
> +      tar -vxf loongarch64-clfs-20211202-cross-tools.tar.xz -C /opt
> +
> +    Config cross-tools env.
> +
> +      . setenv.sh
> +
> +      setenv.sh:
> +
> +          #!/bin/sh
> +          set -x
> +          CC_PREFIX=/opt/cross-tools
> +
> +          export PATH=$CC_PREFIX/bin:$PATH
> +          export LD_LIBRARY_PATH=$CC_PREFIX/lib:$LD_LIBRARY_PATH
> +          export LD_LIBRARY_PATH=$CC_PREFIX/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH
> +          set +x
> +
> +  2. Test tests/tcg/multiarch.
> +
> +    ./configure --disable-rdma --disable-pvrdma --prefix=/usr  \
> +            --target-list="loongarch64-linux-user"  \
> +            --disable-libiscsi --disable-libnfs --disable-libpmem \
> +            --disable-glusterfs --enable-libusb --enable-usb-redir \
> +            --disable-opengl --disable-xen --enable-spice --disable-werror \
> +            --enable-debug --disable-capstone --disable-kvm --enable-profiler
> +
> +    cd  build/
> +
> +    make && make check-tcg
> +
> +  3. Run LoongArch system basic command with loongarch-clfs-system.
> +
> +    Download clfs-system.
> +
> +      wgethttps://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-system-2021-12-02.tar.bz2
> +
> +      tar -vxf loongarch64-clfs-system-2021-12-02.tar.bz2 -C /opt/clfs
> +      ln -s /opt/clfs/  /opt/clfs/tls
Command with dubious intention -- are you working around some kind of 
LIBPATH priority problem? TLS shouldn't be involved at this level, yet I 
remotely remember that library search paths similar to "/usr/lib/tls" 
were a thing long ago...
> +
> +    Config env.
> +
> +      cp /opt/clfs/lib64/ld-linux-loongarch64.so.1   /lib64
> +
> +      export LD_LIBRARY_PATH="/opt/clfs/lib64"
> +
> +    Run LoongArch system basic command.
> +
> +      ./qemu-loongarch64  /opt/clfs/usr/bin/bash
> +      ./qemu-loongarch64  /opt/clfs/usr/bin/ls
> +      ./qemu-loongarch64  /opt/clfs/usr/bin/pwd
> +      ...
> +
> +
> +- Note.
> +  We can get the latest LoongArch documents or LoongArch tools athttps://github.com/loongson/
I'm afraid this README would require some re-writing due to the amount 
of Chinglish involved, but that's possibly okay after merging. (I don't 
have the time to rewrite this for you currently, so just a mild rant for 
now.)


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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-06  9:41 ` [PATCH v14 02/26] target/loongarch: Add core definition Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  2022-01-09 18:49     ` Richard Henderson
                       ` (2 more replies)
  0 siblings, 3 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel
  Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé


On 1/6/22 17:41, Song Gao wrote:
> This patch adds target state header, target definitions
> and initialization routines.
>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> Reviewed-by: Philippe Mathieu-Daudé<f4bug@amsat.org>
> ---
>   target/loongarch/cpu-param.h |  18 ++
>   target/loongarch/cpu.c       | 314 +++++++++++++++++++++++++++++++++++
>   target/loongarch/cpu.h       | 252 ++++++++++++++++++++++++++++
>   target/loongarch/internals.h |  21 +++
>   4 files changed, 605 insertions(+)
>   create mode 100644 target/loongarch/cpu-param.h
>   create mode 100644 target/loongarch/cpu.c
>   create mode 100644 target/loongarch/cpu.h
>   create mode 100644 target/loongarch/internals.h
>
> diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h
> new file mode 100644
> index 0000000000..9a769b67e0
> --- /dev/null
> +++ b/target/loongarch/cpu-param.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch CPU parameters for QEMU.
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef LOONGARCH_CPU_PARAM_H
> +#define LOONGARCH_CPU_PARAM_H
> +
> +#define TARGET_LONG_BITS 64
> +#define TARGET_PHYS_ADDR_SPACE_BITS 48
> +#define TARGET_VIRT_ADDR_SPACE_BITS 48
> +
> +#define TARGET_PAGE_BITS 14
Aren't we capable of page sizes up to 64KiB? Minimal feasible page size 
is indeed 16KiB though (due to cache aliasing, although 4KiB pages are 
supported in hardware, they don't work in practice).
> +#define NB_MMU_MODES 4
> +
> +#endif
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> new file mode 100644
> index 0000000000..76b89d1606
> --- /dev/null
> +++ b/target/loongarch/cpu.c
> @@ -0,0 +1,314 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU LoongArch CPU
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/qemu-print.h"
> +#include "qapi/error.h"
> +#include "qemu/module.h"
> +#include "sysemu/qtest.h"
> +#include "exec/exec-all.h"
> +#include "qapi/qapi-commands-machine-target.h"
> +#include "cpu.h"
> +#include "internals.h"
> +#include "fpu/softfloat-helpers.h"
> +
> +const char * const regnames[32] = {
> +    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> +    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
> +    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
> +    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
> +};
> +
> +const char * const fregnames[32] = {
> +    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
> +    "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
> +    "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
> +    "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
> +};
> +
> +static const char * const excp_names[EXCP_LAST + 1] = {
> +    [EXCP_SYSCALL] = "Syscall",
> +    [EXCP_BREAK] = "Break",
> +    [EXCP_INE] = "Instruction Non-existent",
Nit: "Instruction Non-Existent" (or is there any authoritative source 
for this spelling? the English translation of the manual?)
> +    [EXCP_FPE] = "Floating Point Exception",
> +};
> +
> +const char *loongarch_exception_name(int32_t exception)
> +{
> +    assert(excp_names[exception]);
> +    return excp_names[exception];
> +}
> +
> +void QEMU_NORETURN do_raise_exception(CPULoongArchState *env,
> +                                      uint32_t exception,
> +                                      uintptr_t pc)
> +{
> +    CPUState *cs = env_cpu(env);
> +
> +    qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n",
> +                  __func__,
> +                  exception,
> +                  loongarch_exception_name(exception));
> +    cs->exception_index = exception;
> +
> +    cpu_loop_exit_restore(cs, pc);
> +}
> +
> +static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
> +    CPULoongArchState *env = &cpu->env;
> +
> +    env->pc = value;
> +}
> +
> +#ifdef CONFIG_TCG
> +static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
> +                                              const TranslationBlock *tb)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
> +    CPULoongArchState *env = &cpu->env;
> +
> +    env->pc = tb->pc;
> +}
> +#endif /* CONFIG_TCG */
> +
> +static bool loongarch_cpu_has_work(CPUState *cs)
> +{
> +    return true;

Note: this is only applicable to CONFIG_USER_ONLY, and needs to be 
changed in the following commits adding system emulation. To better 
convey your intention it may be better to use an #ifdef guard, something 
like this:

#ifndef CONFIG_USER_ONLY
#error System emulation TODO
#else
     return true;
#endif

(I'm not sure if this is okay in QEMU coding style, so please correct me 
if this isn't the case.)

> +}
> +
> +static void loongarch_3a5000_initfn(Object *obj)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
> +    CPULoongArchState *env = &cpu->env;
> +    int i;
> +
> +    for (i = 0; i < 21; i++) {
> +        env->cpucfg[i] = 0x0;
> +    }
> +
> +    env->cpucfg[0] = 0x14c010;  /* PRID */
> +
> +    uint32_t data = 0;
> +    data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
> +    data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
> +    data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
> +    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
> +    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
> +    data = FIELD_DP32(data, CPUCFG1, UAL, 1);
> +    data = FIELD_DP32(data, CPUCFG1, RI, 1);
> +    data = FIELD_DP32(data, CPUCFG1, EP, 1);
> +    data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
> +    data = FIELD_DP32(data, CPUCFG1, HP, 1);
> +    data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
> +    env->cpucfg[1] = data;
> +
> +    data = 0;
> +    data = FIELD_DP32(data, CPUCFG2, FP, 1);
> +    data = FIELD_DP32(data, CPUCFG2, FP_SP, 1);
> +    data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
> +    data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
> +    data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
> +    data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
> +    data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
Do you support the SPW extension in this series? If not you probably 
don't want to set this bit.
> +    data = FIELD_DP32(data, CPUCFG2, LAM, 1);
> +    env->cpucfg[2] = data;
> +
> +    env->cpucfg[4] = 100 * 1000 * 1000; /* Crystal frequency */
> +
> +    data = 0;
> +    data = FIELD_DP32(data, CPUCFG5, CC_MUL, 1);
> +    data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1);
> +    env->cpucfg[5] = data;
> +
> +    data = 0;
> +    data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1);
> +    data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
> +    data = FIELD_DP32(data, CPUCFG16, L2_IUPRE, 1);
> +    data = FIELD_DP32(data, CPUCFG16, L2_IUUNIFY, 1);
> +    data = FIELD_DP32(data, CPUCFG16, L2_IUPRIV, 1);
> +    data = FIELD_DP32(data, CPUCFG16, L3_IUPRE, 1);
> +    data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
> +    data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
> +    env->cpucfg[16] = data;
> +
> +    data = 0;
> +    data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 0x8003);

This seems out-of-place, according to the manual this field is Way-1 for 
the L1I cache, so you have 0x8004=32772 ways in this cache?

Same for all similar constructions below.

> +    data = FIELD_DP32(data, CPUCFG17, L1IU_SETS, 0x60);
> +    env->cpucfg[17] =  data;

Extra space after the "=" operator.

Also it seems the L1IU_SIZE field is not provided initialization value; 
same for all similar constructions below.

> +
> +    data = 0;
> +    data = FIELD_DP32(data, CPUCFG18, L1D_WAYS, 0x8003);
> +    data = FIELD_DP32(data, CPUCFG18, L1D_SETS, 0x60);
> +    env->cpucfg[18] = data;
> +
> +    data = 0;
> +    data = FIELD_DP32(data, CPUCFG19, L2IU_WAYS, 0x800f);
> +    data = FIELD_DP32(data, CPUCFG19, L2IU_SETS, 0x60);
> +    env->cpucfg[19] = data;
> +
> +    data = 0;
> +    data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 0xf00f);
> +    data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 0x60);
> +    env->cpucfg[20] = data;
> +}
> +
> +static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
> +{
> +    const char *typename = object_class_get_name(OBJECT_CLASS(data));
> +
> +    qemu_printf("%s\n", typename);
> +}
> +
> +void loongarch_cpu_list(void)
> +{
> +    GSList *list;
> +    list = object_class_get_list_sorted(TYPE_LOONGARCH_CPU, false);
> +    g_slist_foreach(list, loongarch_cpu_list_entry, NULL);
> +    g_slist_free(list);
> +}
> +
> +static void loongarch_cpu_reset(DeviceState *dev)
> +{
> +    CPUState *cs = CPU(dev);
> +    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
> +    LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(cpu);
> +    CPULoongArchState *env = &cpu->env;
> +
> +    lacc->parent_reset(dev);
> +
> +    env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
> +    env->fcsr0 = 0x0;
> +
> +    cs->exception_index = EXCP_NONE;
> +}
> +
> +static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info)
> +{
> +    info->print_insn = print_insn_loongarch;
> +}
> +
> +static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
> +{
> +    CPUState *cs = CPU(dev);
> +    LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
> +    Error *local_err = NULL;
> +
> +    cpu_exec_realizefn(cs, &local_err);
> +    if (local_err != NULL) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    cpu_reset(cs);
> +    qemu_init_vcpu(cs);
> +
> +    lacc->parent_realize(dev, errp);
> +}
> +
> +static void loongarch_cpu_initfn(Object *obj)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
> +
> +    cpu_set_cpustate_pointers(cpu);
> +}
> +
> +static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
> +{
> +    ObjectClass *oc;
> +    char *typename;
> +
> +    typename = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model);
> +    oc = object_class_by_name(typename);
> +    g_free(typename);
> +    return oc;
> +}
> +
> +void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
> +    CPULoongArchState *env = &cpu->env;
> +    int i;
> +
> +    qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
> +    qemu_fprintf(f, " FCSR0 0x%08x  fp_status 0x%02x\n", env->fcsr0,
> +                 get_float_exception_flags(&env->fp_status));
> +
> +    /* gpr */
> +    for (i = 0; i < 32; i++) {
> +        if ((i & 3) == 0) {
> +            qemu_fprintf(f, " GPR%02d:", i);
> +        }
> +        qemu_fprintf(f, " %s %016" PRIx64, regnames[i], env->gpr[i]);
> +        if ((i & 3) == 3) {
> +            qemu_fprintf(f, "\n");
> +        }
> +    }
> +
> +    /* fpr */
> +    if (flags & CPU_DUMP_FPU) {
> +        for (i = 0; i < 32; i++) {
> +            qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i]);
> +            if ((i & 3) == 3) {
> +                qemu_fprintf(f, "\n");
> +            }
> +        }
> +    }
> +}
> +
> +#ifdef CONFIG_TCG
> +#include "hw/core/tcg-cpu-ops.h"
> +
> +static struct TCGCPUOps loongarch_tcg_ops = {
> +    .initialize = loongarch_translate_init,
> +    .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
> +};
> +#endif /* CONFIG_TCG */
> +
> +static void loongarch_cpu_class_init(ObjectClass *c, void *data)
> +{
> +    LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
> +    CPUClass *cc = CPU_CLASS(c);
> +    DeviceClass *dc = DEVICE_CLASS(c);
> +
> +    device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
> +                                    &lacc->parent_realize);
> +    device_class_set_parent_reset(dc, loongarch_cpu_reset, &lacc->parent_reset);
> +
> +    cc->class_by_name = loongarch_cpu_class_by_name;
> +    cc->has_work = loongarch_cpu_has_work;
> +    cc->dump_state = loongarch_cpu_dump_state;
> +    cc->set_pc = loongarch_cpu_set_pc;
> +    cc->disas_set_info = loongarch_cpu_disas_set_info;
> +#ifdef CONFIG_TCG
> +    cc->tcg_ops = &loongarch_tcg_ops;
> +#endif
> +}
> +
> +#define DEFINE_LOONGARCH_CPU_TYPE(model, initfn) \
> +    { \
> +        .parent = TYPE_LOONGARCH_CPU, \
> +        .instance_init = initfn, \
> +        .name = LOONGARCH_CPU_TYPE_NAME(model), \
> +    }
> +
> +static const TypeInfo loongarch_cpu_type_infos[] = {
> +    {
> +        .name = TYPE_LOONGARCH_CPU,
> +        .parent = TYPE_CPU,
> +        .instance_size = sizeof(LoongArchCPU),
> +        .instance_init = loongarch_cpu_initfn,
> +
> +        .abstract = true,
> +        .class_size = sizeof(LoongArchCPUClass),
> +        .class_init = loongarch_cpu_class_init,
> +    },
> +    DEFINE_LOONGARCH_CPU_TYPE("Loongson-3A5000", loongarch_3a5000_initfn),
> +};
> +
> +DEFINE_TYPES(loongarch_cpu_type_infos)
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> new file mode 100644
> index 0000000000..b036cdee5f
> --- /dev/null
> +++ b/target/loongarch/cpu.h
> @@ -0,0 +1,252 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU LoongArch CPU
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef LOONGARCH_CPU_H
> +#define LOONGARCH_CPU_H
> +
> +#include "exec/cpu-defs.h"
> +#include "fpu/softfloat-types.h"
> +#include "hw/registerfields.h"
> +
> +#define TCG_GUEST_DEFAULT_MO (0)
> +
> +#define FCSR0_M1    0x1f         /* FCSR1 mask, Enables */
> +#define FCSR0_M2    0x1f1f0000   /* FCSR2 mask, Cause and Flags */
> +#define FCSR0_M3    0x300        /* FCSR3 mask, Round Mode */
> +#define FCSR0_RM    8            /* Round Mode bit num on fcsr0 */
> +
> +FIELD(FCSR0, ENABLES, 0, 5)
> +FIELD(FCSR0, RM, 8, 2)
> +FIELD(FCSR0, FLAGS, 16, 5)
> +FIELD(FCSR0, CAUSE, 24, 5)
> +
> +#define GET_FP_CAUSE(REG)      FIELD_EX32(REG, FCSR0, CAUSE)
> +#define SET_FP_CAUSE(REG, V)   FIELD_DP32(REG, FCSR0, CAUSE, V)
> +#define GET_FP_ENABLES(REG)    FIELD_EX32(REG, FCSR0, ENABLES)
> +#define SET_FP_ENABLES(REG, V) FIELD_DP32(REG, FCSR0, ENABLES, V)
> +#define GET_FP_FLAGS(REG)      FIELD_EX32(REG, FCSR0, FLAGS)
> +#define SET_FP_FLAGS(REG, V)   FIELD_DP32(REG, FCSR0, FLAGS, V)
> +#define UPDATE_FP_FLAGS(REG, V) \
> +    do { \
> +        (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \
> +    } while (0)
> +
> +#define FP_INEXACT        1
> +#define FP_UNDERFLOW      2
> +#define FP_OVERFLOW       4
> +#define FP_DIV0           8
> +#define FP_INVALID        16
> +
> +/* cpucfg[0] bits */
> +FIELD(CPUCFG0, PRID, 0, 32)
> +
> +/* cpucfg[1] bits */
> +FIELD(CPUCFG1, ARCH, 0, 2)
> +FIELD(CPUCFG1, PGMMU, 2, 1)
> +FIELD(CPUCFG1, IOCSR, 3, 1)
> +FIELD(CPUCFG1, PALEN, 4, 8)
> +FIELD(CPUCFG1, VALEN, 12, 8)
> +FIELD(CPUCFG1, UAL, 20, 1)
> +FIELD(CPUCFG1, RI, 21, 1)
> +FIELD(CPUCFG1, EP, 22, 1)
> +FIELD(CPUCFG1, RPLV, 23, 1)
> +FIELD(CPUCFG1, HP, 24, 1)
> +FIELD(CPUCFG1, IOCSR_BRD, 25, 1)
> +FIELD(CPUCFG1, MSG_INT, 26, 1)
> +
> +/* cpucfg[2] bits */
> +FIELD(CPUCFG2, FP, 0, 1)
> +FIELD(CPUCFG2, FP_SP, 1, 1)
> +FIELD(CPUCFG2, FP_DP, 2, 1)
> +FIELD(CPUCFG2, FP_VER, 3, 3)
> +FIELD(CPUCFG2, LSX, 6, 1)
> +FIELD(CPUCFG2, LASX, 7, 1)
> +FIELD(CPUCFG2, COMPLEX, 8, 1)
> +FIELD(CPUCFG2, CRYPTO, 9, 1)
> +FIELD(CPUCFG2, LVZ, 10, 1)
> +FIELD(CPUCFG2, LVZ_VER, 11, 3)
> +FIELD(CPUCFG2, LLFTP, 14, 1)
> +FIELD(CPUCFG2, LLFTP_VER, 15, 3)
> +FIELD(CPUCFG2, LBT_X86, 18, 1)
> +FIELD(CPUCFG2, LBT_ARM, 19, 1)
> +FIELD(CPUCFG2, LBT_MIPS, 20, 1)
> +FIELD(CPUCFG2, LSPW, 21, 1)
> +FIELD(CPUCFG2, LAM, 22, 1)
> +
> +/* cpucfg[3] bits */
> +FIELD(CPUCFG3, CCDMA, 0, 1)
> +FIELD(CPUCFG3, SFB, 1, 1)
> +FIELD(CPUCFG3, UCACC, 2, 1)
> +FIELD(CPUCFG3, LLEXC, 3, 1)
> +FIELD(CPUCFG3, SCDLY, 4, 1)
> +FIELD(CPUCFG3, LLDBAR, 5, 1)
> +FIELD(CPUCFG3, ITLBHMC, 6, 1)
> +FIELD(CPUCFG3, ICHMC, 7, 1)
> +FIELD(CPUCFG3, SPW_LVL, 8, 3)
> +FIELD(CPUCFG3, SPW_HP_HF, 11, 1)
> +FIELD(CPUCFG3, RVA, 12, 1)
> +FIELD(CPUCFG3, RVAMAX, 13, 4)
> +
> +/* cpucfg[4] bits */
> +FIELD(CPUCFG4, CC_FREQ, 0, 32)
> +
> +/* cpucfg[5] bits */
> +FIELD(CPUCFG5, CC_MUL, 0, 16)
> +FIELD(CPUCFG5, CC_DIV, 16, 16)
> +
> +/* cpucfg[6] bits */
> +FIELD(CPUCFG6, PMP, 0, 1)
> +FIELD(CPUCFG6, PMVER, 1, 3)
> +FIELD(CPUCFG6, PMNUM, 4, 4)
> +FIELD(CPUCFG6, PMBITS, 8, 6)
> +FIELD(CPUCFG6, UPM, 14, 1)
> +
> +/* cpucfg[16] bits */
> +FIELD(CPUCFG16, L1_IUPRE, 0, 1)
> +FIELD(CPUCFG16, L1_IUUNIFY, 1, 1)
> +FIELD(CPUCFG16, L1_DPRE, 2, 1)
> +FIELD(CPUCFG16, L2_IUPRE, 3, 1)
> +FIELD(CPUCFG16, L2_IUUNIFY, 4, 1)
> +FIELD(CPUCFG16, L2_IUPRIV, 5, 1)
> +FIELD(CPUCFG16, L2_IUINCL, 6, 1)
> +FIELD(CPUCFG16, L2_DPRE, 7, 1)
> +FIELD(CPUCFG16, L2_DPRIV, 8, 1)
> +FIELD(CPUCFG16, L2_DINCL, 9, 1)
> +FIELD(CPUCFG16, L3_IUPRE, 10, 1)
> +FIELD(CPUCFG16, L3_IUUNIFY, 11, 1)
> +FIELD(CPUCFG16, L3_IUPRIV, 12, 1)
> +FIELD(CPUCFG16, L3_IUINCL, 13, 1)
> +FIELD(CPUCFG16, L3_DPRE, 14, 1)
> +FIELD(CPUCFG16, L3_DPRIV, 15, 1)
> +FIELD(CPUCFG16, L3_DINCL, 16, 1)
> +
> +/* cpucfg[17] bits */
> +FIELD(CPUCFG17, L1IU_WAYS, 0, 16)
> +FIELD(CPUCFG17, L1IU_SETS, 16, 8)
> +FIELD(CPUCFG17, L1IU_SIZE, 24, 7)
> +
> +/* cpucfg[18] bits */
> +FIELD(CPUCFG18, L1D_WAYS, 0, 16)
> +FIELD(CPUCFG18, L1D_SETS, 16, 8)
> +FIELD(CPUCFG18, L1D_SIZE, 24, 7)
> +
> +/* cpucfg[19] bits */
> +FIELD(CPUCFG19, L2IU_WAYS, 0, 16)
> +FIELD(CPUCFG19, L2IU_SETS, 16, 8)
> +FIELD(CPUCFG19, L2IU_SIZE, 24, 7)
> +
> +/* cpucfg[20] bits */
> +FIELD(CPUCFG20, L3IU_WAYS, 0, 16)
> +FIELD(CPUCFG20, L3IU_SETS, 16, 8)
> +FIELD(CPUCFG20, L3IU_SIZE, 24, 7)
> +
> +extern const char * const regnames[32];
> +extern const char * const fregnames[32];
> +
> +typedef struct CPULoongArchState CPULoongArchState;
> +struct CPULoongArchState {
> +    uint64_t gpr[32];
> +    uint64_t pc;
> +
> +    uint64_t fpr[32];
> +    float_status fp_status;
> +    bool cf[8];
> +
> +    /*
> +     * fcsr0
> +     * 31:29 |28:24 |23:21 |20:16 |15:10 |9:8 |7:5 |4:0
> +     *        Cause         Flags         RM        Enables
> +     */
> +    uint32_t fcsr0;
> +    uint32_t fcsr0_mask;
With the field definition somewhere above, is this "infographic" necessary?
> +
> +    uint32_t cpucfg[21];
> +
> +    uint64_t lladdr; /* LL virtual address compared against SC */
Similarly, do we explain every field with comments *here*? I think if 
fields are named according to the manuals, people will naturally look up 
names there so there's no worry for misunderstanding.
> +    uint64_t llval;
> +
> +    uint64_t badaddr;
> +};
> +
> +/**
> + * LoongArchCPU:
> + * @env: #CPULoongArchState
> + *
> + * A LoongArch CPU.
> + */
> +struct LoongArchCPU {
> +    /*< private >*/
> +    CPUState parent_obj;
> +    /*< public >*/
> +
> +    CPUNegativeOffsetState neg;
> +    CPULoongArchState env;
> +};
> +
> +#define TYPE_LOONGARCH_CPU "loongarch-cpu"
> +
> +OBJECT_DECLARE_TYPE(LoongArchCPU, LoongArchCPUClass,
> +                    LOONGARCH_CPU)
> +
> +/**
> + * LoongArchCPUClass:
> + * @parent_realize: The parent class' realize handler.
> + * @parent_reset: The parent class' reset handler.
> + *
> + * A LoongArch CPU model.
> + */
> +struct LoongArchCPUClass {
> +    /*< private >*/
> +    CPUClass parent_class;
> +    /*< public >*/
> +
> +    DeviceRealize parent_realize;
> +    DeviceReset parent_reset;
> +};
> +
> +#define MMU_USER_IDX 3
> +
> +static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
> +{
> +    return MMU_USER_IDX;
> +}
> +
> +static inline void cpu_get_tb_cpu_state(CPULoongArchState *env,
> +                                        target_ulong *pc,
> +                                        target_ulong *cs_base,
> +                                        uint32_t *flags)
> +{
> +    *pc = env->pc;
> +    *cs_base = 0;
> +    *flags = cpu_mmu_index(env, false);
> +}
> +
> +void loongarch_cpu_list(void);
> +
> +#define cpu_list loongarch_cpu_list
> +
> +typedef CPULoongArchState CPUArchState;
> +typedef LoongArchCPU ArchCPU;
> +
> +#include "exec/cpu-all.h"
> +
> +/* Exceptions */
> +enum {
> +    EXCP_NONE          = -1,
> +    EXCP_SYSCALL       = 0,
> +    EXCP_BREAK,
> +    EXCP_INE,
> +    EXCP_FPE,
> +
> +    EXCP_LAST = EXCP_FPE,
> +};
> +
> +#define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU
> +#define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX
> +#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
> +
> +#endif /* LOONGARCH_CPU_H */
> diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
> new file mode 100644
> index 0000000000..1e69e7d9d9
> --- /dev/null
> +++ b/target/loongarch/internals.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU LoongArch CPU -- internal functions and types
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef LOONGARCH_INTERNALS_H
> +#define LOONGARCH_INTERNALS_H
> +
> +void loongarch_translate_init(void);
> +
> +void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
> +
> +void QEMU_NORETURN do_raise_exception(CPULoongArchState *env,
> +                                      uint32_t exception,
> +                                      uintptr_t pc);
> +
> +const char *loongarch_exception_name(int32_t exception);
> +
> +#endif


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

* Re: [PATCH v14 03/26] target/loongarch: Add main translation routines
  2022-01-06  9:41 ` [PATCH v14 03/26] target/loongarch: Add main translation routines Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson


On 1/6/22 17:41, Song Gao wrote:
> This patch adds main translation routines and
> basic functions for translation.
>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> ---
>   target/loongarch/helper.h    |   6 ++
>   target/loongarch/op_helper.c |  21 +++++
>   target/loongarch/translate.c | 159 +++++++++++++++++++++++++++++++++++
>   target/loongarch/translate.h |  26 ++++++
>   4 files changed, 212 insertions(+)
>   create mode 100644 target/loongarch/helper.h
>   create mode 100644 target/loongarch/op_helper.c
>   create mode 100644 target/loongarch/translate.c
>   create mode 100644 target/loongarch/translate.h
>
> diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
> new file mode 100644
> index 0000000000..eb771c0628
> --- /dev/null
> +++ b/target/loongarch/helper.h
> @@ -0,0 +1,6 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +DEF_HELPER_2(raise_exception, noreturn, env, i32)
> diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
> new file mode 100644
> index 0000000000..903810951e
> --- /dev/null
> +++ b/target/loongarch/op_helper.c
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch emulation helpers for QEMU.
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/main-loop.h"
> +#include "cpu.h"
> +#include "qemu/host-utils.h"
> +#include "exec/helper-proto.h"
> +#include "exec/exec-all.h"
> +#include "exec/cpu_ldst.h"
> +#include "internals.h"
> +
> +/* Exceptions helpers */
> +void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
> +{
> +    do_raise_exception(env, exception, GETPC());
> +}
> diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
> new file mode 100644
> index 0000000000..048c8953b6
> --- /dev/null
> +++ b/target/loongarch/translate.c
> @@ -0,0 +1,159 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch emulation for QEMU - main translation routines.
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "tcg/tcg-op.h"
> +#include "exec/translator.h"
> +#include "exec/helper-proto.h"
> +#include "exec/helper-gen.h"
> +
> +#include "exec/translator.h"
> +#include "exec/log.h"
> +#include "qemu/qemu-print.h"
> +#include "translate.h"
> +#include "internals.h"
> +
> +/* Global register indices */
> +TCGv cpu_gpr[32], cpu_pc;
> +static TCGv cpu_lladdr, cpu_llval;
> +TCGv_i32 cpu_fcsr0;
> +TCGv_i64 cpu_fpr[32];
> +
> +#define DISAS_STOP       DISAS_TARGET_0
> +
> +void generate_exception(DisasContext *ctx, int excp)
> +{
> +    tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
> +    gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
> +    ctx->base.is_jmp = DISAS_NORETURN;
> +}
> +
> +static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
> +{
> +    if (translator_use_goto_tb(&ctx->base, dest)) {
> +        tcg_gen_goto_tb(n);
> +        tcg_gen_movi_tl(cpu_pc, dest);
> +        tcg_gen_exit_tb(ctx->base.tb, n);
> +    } else {
> +        tcg_gen_movi_tl(cpu_pc, dest);
> +        tcg_gen_lookup_and_goto_ptr();
> +    }
> +}
> +
> +static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
> +                                            CPUState *cs)
> +{
> +    int64_t bound;
> +    DisasContext *ctx = container_of(dcbase, DisasContext, base);
> +
> +    ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
> +    ctx->mem_idx = ctx->base.tb->flags;
> +
> +    /* Bound the number of insns to execute to those left on the page.  */
> +    bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
> +    ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
> +}
> +
> +static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
> +{
> +}
> +
> +static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
> +{
> +    DisasContext *ctx = container_of(dcbase, DisasContext, base);
> +
> +    tcg_gen_insn_start(ctx->base.pc_next);
> +}
> +
> +static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
> +{
> +    CPULoongArchState *env = cs->env_ptr;
> +    DisasContext *ctx = container_of(dcbase, DisasContext, base);
> +
> +    ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
> +
> +    if (!decode(ctx, ctx->opcode)) {
> +        qemu_log_mask(LOG_UNIMP, "Error: unkown opcode. 0x%lx: 0x%x\n",
Typo: "unknown"
> +                      ctx->base.pc_next, ctx->opcode);
> +        generate_exception(ctx, EXCP_INE);
> +    }
> +
> +    ctx->base.pc_next += 4;
> +}
> +
> +static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
> +{
> +    DisasContext *ctx = container_of(dcbase, DisasContext, base);
> +
> +    switch (ctx->base.is_jmp) {
> +    case DISAS_STOP:
> +        tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
> +        tcg_gen_lookup_and_goto_ptr();
> +        break;
> +    case DISAS_TOO_MANY:
> +        gen_goto_tb(ctx, 0, ctx->base.pc_next);
> +        break;
> +    case DISAS_NORETURN:
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
> +static void loongarch_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
> +{
> +    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
> +    log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
> +}
> +
> +static const TranslatorOps loongarch_tr_ops = {
> +    .init_disas_context = loongarch_tr_init_disas_context,
> +    .tb_start           = loongarch_tr_tb_start,
> +    .insn_start         = loongarch_tr_insn_start,
> +    .translate_insn     = loongarch_tr_translate_insn,
> +    .tb_stop            = loongarch_tr_tb_stop,
> +    .disas_log          = loongarch_tr_disas_log,
> +};
> +
> +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
> +{
> +    DisasContext ctx;
> +
> +    translator_loop(&loongarch_tr_ops, &ctx.base, cs, tb, max_insns);
> +}
> +
> +void loongarch_translate_init(void)
> +{
> +    int i;
> +
> +    cpu_gpr[0] = NULL;
> +    for (i = 1; i < 32; i++) {
> +        cpu_gpr[i] = tcg_global_mem_new(cpu_env,
> +                                        offsetof(CPULoongArchState, gpr[i]),
> +                                        regnames[i]);
> +    }
> +
> +    for (i = 0; i < 32; i++) {
> +        int off = offsetof(CPULoongArchState, fpr[i]);
> +        cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
> +    }
> +
> +    cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPULoongArchState, pc), "pc");
> +    cpu_fcsr0 = tcg_global_mem_new_i32(cpu_env,
> +                    offsetof(CPULoongArchState, fcsr0), "fcsr0");
> +    cpu_lladdr = tcg_global_mem_new(cpu_env,
> +                    offsetof(CPULoongArchState, lladdr), "lladdr");
> +    cpu_llval = tcg_global_mem_new(cpu_env,
> +                    offsetof(CPULoongArchState, llval), "llval");
> +}
> +
> +void restore_state_to_opc(CPULoongArchState *env, TranslationBlock *tb,
> +                          target_ulong *data)
> +{
> +    env->pc = data[0];
> +}
> diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
> new file mode 100644
> index 0000000000..6cc7f1a7cd
> --- /dev/null
> +++ b/target/loongarch/translate.h
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch translation routines.
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef TARGET_LOONGARCH_TRANSLATE_H
> +#define TARGET_LOONGARCH_TRANSLATE_H
> +
> +#include "exec/translator.h"
> +
> +typedef struct DisasContext {
> +    DisasContextBase base;
> +    target_ulong page_start;
> +    uint32_t opcode;
> +    int mem_idx;
> +} DisasContext;
> +
> +void generate_exception(DisasContext *ctx, int excp);
> +
> +extern TCGv cpu_gpr[32], cpu_pc;
> +extern TCGv_i32 cpu_fscr0;
> +extern TCGv_i64 cpu_fpr[32];
> +
> +#endif


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

* Re: [PATCH v14 16/26] target/loongarch: Add disassembler
  2022-01-06  9:41 ` [PATCH v14 16/26] target/loongarch: Add disassembler Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  2022-01-09 18:51     ` Richard Henderson
  0 siblings, 1 reply; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson


On 1/6/22 17:41, Song Gao wrote:
> This patch adds support for disassembling via option '-d in_asm'.
>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> ---
>   include/disas/dis-asm.h  |   2 +
>   meson.build              |   1 +
>   target/loongarch/disas.c | 612 +++++++++++++++++++++++++++++++++++++++
>   3 files changed, 615 insertions(+)
>   create mode 100644 target/loongarch/disas.c
>
> diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
> index 08e1beec85..aeab30f19c 100644
> --- a/include/disas/dis-asm.h
> +++ b/include/disas/dis-asm.h
> @@ -253,6 +253,7 @@ enum bfd_architecture
>   #define bfd_mach_rx            0x75
>   #define bfd_mach_rx_v2         0x76
>   #define bfd_mach_rx_v3         0x77
> +  bfd_arch_loongarch,
>     bfd_arch_last
>     };
>   #define bfd_mach_s390_31 31
> @@ -461,6 +462,7 @@ int print_insn_riscv32          (bfd_vma, disassemble_info*);
>   int print_insn_riscv64          (bfd_vma, disassemble_info*);
>   int print_insn_rx(bfd_vma, disassemble_info *);
>   int print_insn_hexagon(bfd_vma, disassemble_info *);
> +int print_insn_loongarch(bfd_vma, disassemble_info *);
>   
>   #ifdef CONFIG_CAPSTONE
>   bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
> diff --git a/meson.build b/meson.build
> index 53065e96ec..fa4c6dd241 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -1848,6 +1848,7 @@ disassemblers = {
>     'sh4' : ['CONFIG_SH4_DIS'],
>     'sparc' : ['CONFIG_SPARC_DIS'],
>     'xtensa' : ['CONFIG_XTENSA_DIS'],
> +  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
>   }
>   if link_language == 'cpp'
>     disassemblers += {
> diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
> new file mode 100644
> index 0000000000..45be34de27
> --- /dev/null
> +++ b/target/loongarch/disas.c
> @@ -0,0 +1,612 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU LoongArch Disassembler
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "disas/dis-asm.h"
> +#include "qemu/bitops.h"
> +
> +typedef struct {
> +    disassemble_info *info;
> +    uint64_t pc;
> +    uint32_t insn;
> +} DisasContext;
> +
> +static inline int plus_1(DisasContext *ctx, int x)
> +{
> +    return x + 1;
> +}
> +
> +static inline int shl_2(DisasContext *ctx, int x)
> +{
> +    return x * 4;
Although "<< 2" has the same effect as "* 4" here, isn't "<< 2" better 
in matching the function name?
> +}
> +
> +#define output(C, INSN, FMT, ...)                                   \
> +{                                                                   \
> +    (C)->info->fprintf_func((C)->info->stream, "%08x   %-9s\t" FMT, \
> +                            (C)->insn, INSN, ##__VA_ARGS__);        \
> +}
> +
> +#include "decode-insns.c.inc"
> +
> +int print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
> +{
> +    bfd_byte buffer[4];
> +    uint32_t insn;
> +    int status;
> +
> +    status = (*info->read_memory_func)(memaddr, buffer, 4, info);
> +    if (status != 0) {
> +        (*info->memory_error_func)(status, memaddr, info);
> +        return -1;
> +    }
> +    insn = bfd_getl32(buffer);
> +    DisasContext ctx = {
> +        .info = info,
> +        .pc = memaddr,
> +        .insn = insn
> +    };
> +
> +    if (!decode(&ctx, insn)) {
> +        output(&ctx, "illegal", "");
> +    }
> +    return 4;
> +}
> +
> +static void output_r_i(DisasContext *ctx, arg_r_i *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, %d", a->rd, a->imm);
> +}
> +
> +static void output_rrr(DisasContext *ctx, arg_rrr *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, r%d, r%d", a->rd, a->rj, a->rk);
> +}
> +
> +static void output_rr_i(DisasContext *ctx, arg_rr_i *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, r%d, %d", a->rd, a->rj, a->imm);
> +}
> +
> +static void output_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
> +                          const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, r%d, r%d, %d", a->rd, a->rj, a->rk, a->sa);
> +}
> +
> +static void output_rr(DisasContext *ctx, arg_rr *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, r%d", a->rd, a->rj);
> +}
> +
> +static void output_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
> +                          const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, r%d, %d, %d", a->rd, a->rj, a->ms, a->ls);
> +}
> +
> +static void output_hint_r_i(DisasContext *ctx, arg_hint_r_i *a,
> +                            const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "%d, r%d, %d", a->hint, a->rj, a->imm);
> +}
> +
> +static void output_i(DisasContext *ctx, arg_i *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "%d", a->imm);
> +}
> +
> +static void output_rr_jk(DisasContext *ctx, arg_rr_jk *a,
> +                         const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, r%d", a->rj, a->rk);
> +}
> +
> +static void output_ff(DisasContext *ctx, arg_ff *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "f%d, f%d", a->fd, a->fj);
> +}
> +
> +static void output_fff(DisasContext *ctx, arg_fff *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "f%d, f%d, f%d", a->fd, a->fj, a->fk);
> +}
> +
> +static void output_ffff(DisasContext *ctx, arg_ffff *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "f%d, f%d, f%d, f%d", a->fd, a->fj, a->fk, a->fa);
> +}
> +
> +static void output_fffc(DisasContext *ctx, arg_fffc *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "f%d, f%d, f%d, %d", a->fd, a->fj, a->fk, a->ca);
> +}
> +
> +static void output_fr(DisasContext *ctx, arg_fr *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "f%d, r%d", a->fd, a->rj);
> +}
> +
> +static void output_rf(DisasContext *ctx, arg_rf *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, f%d", a->rd, a->fj);
> +}
> +
> +static void output_fcsrd_r(DisasContext *ctx, arg_fcsrd_r *a,
> +                           const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "fcsr%d, r%d", a->fcsrd, a->rj);
> +}
> +
> +static void output_r_fcsrs(DisasContext *ctx, arg_r_fcsrs *a,
> +                           const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, fcsr%d", a->rd, a->fcsrs);
> +}
> +
> +static void output_cf(DisasContext *ctx, arg_cf *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "fcc%d, f%d", a->cd, a->fj);
> +}
> +
> +static void output_fc(DisasContext *ctx, arg_fc *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "f%d, fcc%d", a->fd, a->cj);
> +}
> +
> +static void output_cr(DisasContext *ctx, arg_cr *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "fcc%d, r%d", a->cd, a->rj);
> +}
> +
> +static void output_rc(DisasContext *ctx, arg_rc *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, fcc%d", a->rd, a->cj);
> +}
> +
> +static void output_frr(DisasContext *ctx, arg_frr *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "f%d, r%d, r%d", a->fd, a->rj, a->rk);
> +}
> +
> +static void output_fr_i(DisasContext *ctx, arg_fr_i *a, const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "f%d, r%d, %d", a->fd, a->rj, a->imm);
> +}
> +
> +static void output_r_offs(DisasContext *ctx, arg_r_offs *a,
> +                          const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, %d # 0x%" PRIx64, a->rj, a->offs,
> +           ctx->pc + a->offs);
> +}
> +
> +static void output_c_offs(DisasContext *ctx, arg_c_offs *a,
> +                          const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "fcc%d, %d # 0x%" PRIx64, a->cj, a->offs,
> +           ctx->pc + a->offs);
> +}
> +
> +static void output_offs(DisasContext *ctx, arg_offs *a,
> +                        const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "%d # 0x%" PRIx64, a->offs, ctx->pc + a->offs);
> +}
> +
> +static void output_rr_offs(DisasContext *ctx, arg_rr_offs *a,
> +                           const char *mnemonic)
> +{
> +    output(ctx, mnemonic, "r%d, r%d, %d", a->rj, a->rd, a->offs);

Why no "# %d" and "ctx->pc + a->offs" here?

Also the implicit reversal of rj and rd is ugly, but this wart comes 
straight from the manual so you may as well keep it for the time being. 
I'll rewrite all these code using the loongarch-opcodes tables and 
assembler syntax after everything is merged, though.

> +}
> +
> +#define INSN(insn, type)                                    \
> +static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
> +{                                                           \
> +    output_##type(ctx, a, #insn);                           \
> +    return true;                                            \
> +}
> +
> +INSN(clo_w,        rr)
> +INSN(clz_w,        rr)
> +INSN(cto_w,        rr)
> +INSN(ctz_w,        rr)
> +INSN(clo_d,        rr)
> +INSN(clz_d,        rr)
> +INSN(cto_d,        rr)
> +INSN(ctz_d,        rr)
> +INSN(revb_2h,      rr)
> +INSN(revb_4h,      rr)
> +INSN(revb_2w,      rr)
> +INSN(revb_d,       rr)
> +INSN(revh_2w,      rr)
> +INSN(revh_d,       rr)
> +INSN(bitrev_4b,    rr)
> +INSN(bitrev_8b,    rr)
> +INSN(bitrev_w,     rr)
> +INSN(bitrev_d,     rr)
> +INSN(ext_w_h,      rr)
> +INSN(ext_w_b,      rr)
> +INSN(rdtime_d,     rr)
> +INSN(cpucfg,       rr)
> +INSN(asrtle_d,     rr_jk)
> +INSN(asrtgt_d,     rr_jk)
> +INSN(alsl_w,       rrr_sa)
> +INSN(alsl_wu,      rrr_sa)
> +INSN(bytepick_w,   rrr_sa)
> +INSN(bytepick_d,   rrr_sa)
> +INSN(add_w,        rrr)
> +INSN(add_d,        rrr)
> +INSN(sub_w,        rrr)
> +INSN(sub_d,        rrr)
> +INSN(slt,          rrr)
> +INSN(sltu,         rrr)
> +INSN(maskeqz,      rrr)
> +INSN(masknez,      rrr)
> +INSN(nor,          rrr)
> +INSN(and,          rrr)
> +INSN(or,           rrr)
> +INSN(xor,          rrr)
> +INSN(orn,          rrr)
> +INSN(andn,         rrr)
> +INSN(sll_w,        rrr)
> +INSN(srl_w,        rrr)
> +INSN(sra_w,        rrr)
> +INSN(sll_d,        rrr)
> +INSN(srl_d,        rrr)
> +INSN(sra_d,        rrr)
> +INSN(rotr_w,       rrr)
> +INSN(rotr_d,       rrr)
> +INSN(mul_w,        rrr)
> +INSN(mulh_w,       rrr)
> +INSN(mulh_wu,      rrr)
> +INSN(mul_d,        rrr)
> +INSN(mulh_d,       rrr)
> +INSN(mulh_du,      rrr)
> +INSN(mulw_d_w,     rrr)
> +INSN(mulw_d_wu,    rrr)
> +INSN(div_w,        rrr)
> +INSN(mod_w,        rrr)
> +INSN(div_wu,       rrr)
> +INSN(mod_wu,       rrr)
> +INSN(div_d,        rrr)
> +INSN(mod_d,        rrr)
> +INSN(div_du,       rrr)
> +INSN(mod_du,       rrr)
> +INSN(crc_w_b_w,    rrr)
> +INSN(crc_w_h_w,    rrr)
> +INSN(crc_w_w_w,    rrr)
> +INSN(crc_w_d_w,    rrr)
> +INSN(crcc_w_b_w,   rrr)
> +INSN(crcc_w_h_w,   rrr)
> +INSN(crcc_w_w_w,   rrr)
> +INSN(crcc_w_d_w,   rrr)
> +INSN(break,        i)
> +INSN(syscall,      i)
> +INSN(alsl_d,       rrr_sa)
> +INSN(slli_w,       rr_i)
> +INSN(slli_d,       rr_i)
> +INSN(srli_w,       rr_i)
> +INSN(srli_d,       rr_i)
> +INSN(srai_w,       rr_i)
> +INSN(srai_d,       rr_i)
> +INSN(rotri_w,      rr_i)
> +INSN(rotri_d,      rr_i)
> +INSN(bstrins_w,    rr_ms_ls)
> +INSN(bstrpick_w,   rr_ms_ls)
> +INSN(bstrins_d,    rr_ms_ls)
> +INSN(bstrpick_d,   rr_ms_ls)
> +INSN(fadd_s,       fff)
> +INSN(fadd_d,       fff)
> +INSN(fsub_s,       fff)
> +INSN(fsub_d,       fff)
> +INSN(fmul_s,       fff)
> +INSN(fmul_d,       fff)
> +INSN(fdiv_s,       fff)
> +INSN(fdiv_d,       fff)
> +INSN(fmax_s,       fff)
> +INSN(fmax_d,       fff)
> +INSN(fmin_s,       fff)
> +INSN(fmin_d,       fff)
> +INSN(fmaxa_s,      fff)
> +INSN(fmaxa_d,      fff)
> +INSN(fmina_s,      fff)
> +INSN(fmina_d,      fff)
> +INSN(fscaleb_s,    fff)
> +INSN(fscaleb_d,    fff)
> +INSN(fcopysign_s,  fff)
> +INSN(fcopysign_d,  fff)
> +INSN(fabs_s,       ff)
> +INSN(fabs_d,       ff)
> +INSN(fneg_s,       ff)
> +INSN(fneg_d,       ff)
> +INSN(flogb_s,      ff)
> +INSN(flogb_d,      ff)
> +INSN(fclass_s,     ff)
> +INSN(fclass_d,     ff)
> +INSN(fsqrt_s,      ff)
> +INSN(fsqrt_d,      ff)
> +INSN(frecip_s,     ff)
> +INSN(frecip_d,     ff)
> +INSN(frsqrt_s,     ff)
> +INSN(frsqrt_d,     ff)
> +INSN(fmov_s,       ff)
> +INSN(fmov_d,       ff)
> +INSN(movgr2fr_w,   fr)
> +INSN(movgr2fr_d,   fr)
> +INSN(movgr2frh_w,  fr)
> +INSN(movfr2gr_s,   rf)
> +INSN(movfr2gr_d,   rf)
> +INSN(movfrh2gr_s,  rf)
> +INSN(movgr2fcsr,   fcsrd_r)
> +INSN(movfcsr2gr,   r_fcsrs)
> +INSN(movfr2cf,     cf)
> +INSN(movcf2fr,     fc)
> +INSN(movgr2cf,     cr)
> +INSN(movcf2gr,     rc)
> +INSN(fcvt_s_d,     ff)
> +INSN(fcvt_d_s,     ff)
> +INSN(ftintrm_w_s,  ff)
> +INSN(ftintrm_w_d,  ff)
> +INSN(ftintrm_l_s,  ff)
> +INSN(ftintrm_l_d,  ff)
> +INSN(ftintrp_w_s,  ff)
> +INSN(ftintrp_w_d,  ff)
> +INSN(ftintrp_l_s,  ff)
> +INSN(ftintrp_l_d,  ff)
> +INSN(ftintrz_w_s,  ff)
> +INSN(ftintrz_w_d,  ff)
> +INSN(ftintrz_l_s,  ff)
> +INSN(ftintrz_l_d,  ff)
> +INSN(ftintrne_w_s, ff)
> +INSN(ftintrne_w_d, ff)
> +INSN(ftintrne_l_s, ff)
> +INSN(ftintrne_l_d, ff)
> +INSN(ftint_w_s,    ff)
> +INSN(ftint_w_d,    ff)
> +INSN(ftint_l_s,    ff)
> +INSN(ftint_l_d,    ff)
> +INSN(ffint_s_w,    ff)
> +INSN(ffint_s_l,    ff)
> +INSN(ffint_d_w,    ff)
> +INSN(ffint_d_l,    ff)
> +INSN(frint_s,      ff)
> +INSN(frint_d,      ff)
> +INSN(slti,         rr_i)
> +INSN(sltui,        rr_i)
> +INSN(addi_w,       rr_i)
> +INSN(addi_d,       rr_i)
> +INSN(lu52i_d,      rr_i)
> +INSN(andi,         rr_i)
> +INSN(ori,          rr_i)
> +INSN(xori,         rr_i)
> +INSN(rdtimel_w,    rr)
> +INSN(rdtimeh_w,    rr)
> +INSN(fmadd_s,      ffff)
> +INSN(fmadd_d,      ffff)
> +INSN(fmsub_s,      ffff)
> +INSN(fmsub_d,      ffff)
> +INSN(fnmadd_s,     ffff)
> +INSN(fnmadd_d,     ffff)
> +INSN(fnmsub_s,     ffff)
> +INSN(fnmsub_d,     ffff)
> +INSN(fsel,         fffc)
> +INSN(addu16i_d,    rr_i)
> +INSN(lu12i_w,      r_i)
> +INSN(lu32i_d,      r_i)
> +INSN(pcaddi,       r_i)
> +INSN(pcalau12i,    r_i)
> +INSN(pcaddu12i,    r_i)
> +INSN(pcaddu18i,    r_i)
> +INSN(ll_w,         rr_i)
> +INSN(sc_w,         rr_i)
> +INSN(ll_d,         rr_i)
> +INSN(sc_d,         rr_i)
> +INSN(ldptr_w,      rr_i)
> +INSN(stptr_w,      rr_i)
> +INSN(ldptr_d,      rr_i)
> +INSN(stptr_d,      rr_i)
> +INSN(ld_b,         rr_i)
> +INSN(ld_h,         rr_i)
> +INSN(ld_w,         rr_i)
> +INSN(ld_d,         rr_i)
> +INSN(st_b,         rr_i)
> +INSN(st_h,         rr_i)
> +INSN(st_w,         rr_i)
> +INSN(st_d,         rr_i)
> +INSN(ld_bu,        rr_i)
> +INSN(ld_hu,        rr_i)
> +INSN(ld_wu,        rr_i)
> +INSN(preld,        hint_r_i)
> +INSN(fld_s,        fr_i)
> +INSN(fst_s,        fr_i)
> +INSN(fld_d,        fr_i)
> +INSN(fst_d,        fr_i)
> +INSN(ldx_b,        rrr)
> +INSN(ldx_h,        rrr)
> +INSN(ldx_w,        rrr)
> +INSN(ldx_d,        rrr)
> +INSN(stx_b,        rrr)
> +INSN(stx_h,        rrr)
> +INSN(stx_w,        rrr)
> +INSN(stx_d,        rrr)
> +INSN(ldx_bu,       rrr)
> +INSN(ldx_hu,       rrr)
> +INSN(ldx_wu,       rrr)
> +INSN(fldx_s,       frr)
> +INSN(fldx_d,       frr)
> +INSN(fstx_s,       frr)
> +INSN(fstx_d,       frr)
> +INSN(amswap_w,     rrr)
> +INSN(amswap_d,     rrr)
> +INSN(amadd_w,      rrr)
> +INSN(amadd_d,      rrr)
> +INSN(amand_w,      rrr)
> +INSN(amand_d,      rrr)
> +INSN(amor_w,       rrr)
> +INSN(amor_d,       rrr)
> +INSN(amxor_w,      rrr)
> +INSN(amxor_d,      rrr)
> +INSN(ammax_w,      rrr)
> +INSN(ammax_d,      rrr)
> +INSN(ammin_w,      rrr)
> +INSN(ammin_d,      rrr)
> +INSN(ammax_wu,     rrr)
> +INSN(ammax_du,     rrr)
> +INSN(ammin_wu,     rrr)
> +INSN(ammin_du,     rrr)
> +INSN(amswap_db_w,  rrr)
> +INSN(amswap_db_d,  rrr)
> +INSN(amadd_db_w,   rrr)
> +INSN(amadd_db_d,   rrr)
> +INSN(amand_db_w,   rrr)
> +INSN(amand_db_d,   rrr)
> +INSN(amor_db_w,    rrr)
> +INSN(amor_db_d,    rrr)
> +INSN(amxor_db_w,   rrr)
> +INSN(amxor_db_d,   rrr)
> +INSN(ammax_db_w,   rrr)
> +INSN(ammax_db_d,   rrr)
> +INSN(ammin_db_w,   rrr)
> +INSN(ammin_db_d,   rrr)
> +INSN(ammax_db_wu,  rrr)
> +INSN(ammax_db_du,  rrr)
> +INSN(ammin_db_wu,  rrr)
> +INSN(ammin_db_du,  rrr)
> +INSN(dbar,         i)
> +INSN(ibar,         i)
> +INSN(fldgt_s,      frr)
> +INSN(fldgt_d,      frr)
> +INSN(fldle_s,      frr)
> +INSN(fldle_d,      frr)
> +INSN(fstgt_s,      frr)
> +INSN(fstgt_d,      frr)
> +INSN(fstle_s,      frr)
> +INSN(fstle_d,      frr)
> +INSN(ldgt_b,       rrr)
> +INSN(ldgt_h,       rrr)
> +INSN(ldgt_w,       rrr)
> +INSN(ldgt_d,       rrr)
> +INSN(ldle_b,       rrr)
> +INSN(ldle_h,       rrr)
> +INSN(ldle_w,       rrr)
> +INSN(ldle_d,       rrr)
> +INSN(stgt_b,       rrr)
> +INSN(stgt_h,       rrr)
> +INSN(stgt_w,       rrr)
> +INSN(stgt_d,       rrr)
> +INSN(stle_b,       rrr)
> +INSN(stle_h,       rrr)
> +INSN(stle_w,       rrr)
> +INSN(stle_d,       rrr)
> +INSN(beqz,         r_offs)
> +INSN(bnez,         r_offs)
> +INSN(bceqz,        c_offs)
> +INSN(bcnez,        c_offs)
> +INSN(jirl,         rr_offs)
> +INSN(b,            offs)
> +INSN(bl,           offs)
> +INSN(beq,          rr_offs)
> +INSN(bne,          rr_offs)
> +INSN(blt,          rr_offs)
> +INSN(bge,          rr_offs)
> +INSN(bltu,         rr_offs)
> +INSN(bgeu,         rr_offs)
> +
> +#define output_fcmp(C, PREFIX, SUFFIX)                                         \
> +{                                                                              \
> +    (C)->info->fprintf_func((C)->info->stream, "%08x   %s%s\tfcc%d, f%d, f%d", \
> +                            (C)->insn, PREFIX, SUFFIX, a->cd,                  \
> +                            a->fj, a->fk);                                     \
> +}
> +
> +static bool output_cff_fcond(DisasContext *ctx, arg_cff_fcond * a,
> +                               const char *suffix)
> +{
> +    bool ret = true;
> +    switch (a->fcond) {
> +    case 0x0:
> +        output_fcmp(ctx, "fcmp_caf_", suffix);
> +        break;
> +    case 0x1:
> +        output_fcmp(ctx, "fcmp_saf_", suffix);
> +        break;
> +    case 0x2:
> +        output_fcmp(ctx, "fcmp_clt_", suffix);
> +        break;
> +    case 0x3:
> +        output_fcmp(ctx, "fcmp_slt_", suffix);
> +        break;
> +    case 0x4:
> +        output_fcmp(ctx, "fcmp_ceq_", suffix);
> +        break;
> +    case 0x5:
> +        output_fcmp(ctx, "fcmp_seq_", suffix);
> +        break;
> +    case 0x6:
> +        output_fcmp(ctx, "fcmp_cle_", suffix);
> +        break;
> +    case 0x7:
> +        output_fcmp(ctx, "fcmp_sle_", suffix);
> +        break;
> +    case 0x8:
> +        output_fcmp(ctx, "fcmp_cun_", suffix);
> +        break;
> +    case 0x9:
> +        output_fcmp(ctx, "fcmp_sun_", suffix);
> +        break;
> +    case 0xA:
> +        output_fcmp(ctx, "fcmp_cult_", suffix);
> +        break;
> +    case 0xB:
> +        output_fcmp(ctx, "fcmp_sult_", suffix);
> +        break;
> +    case 0xC:
> +        output_fcmp(ctx, "fcmp_cueq_", suffix);
> +        break;
> +    case 0xD:
> +        output_fcmp(ctx, "fcmp_sueq_", suffix);
> +        break;
> +    case 0xE:
> +        output_fcmp(ctx, "fcmp_cule_", suffix);
> +        break;
> +    case 0xF:
> +        output_fcmp(ctx, "fcmp_sule_", suffix);
> +        break;
> +    case 0x10:
> +        output_fcmp(ctx, "fcmp_cne_", suffix);
> +        break;
> +    case 0x11:
> +        output_fcmp(ctx, "fcmp_sne_", suffix);
> +        break;
> +    case 0x14:
> +        output_fcmp(ctx, "fcmp_cor_", suffix);
> +        break;
> +    case 0x15:
> +        output_fcmp(ctx, "fcmp_sor_", suffix);
> +        break;
> +    case 0x18:
> +        output_fcmp(ctx, "fcmp_cune_", suffix);
> +        break;
> +    case 0x19:
> +        output_fcmp(ctx, "fcmp_sune_", suffix);
> +        break;
> +    default:
> +        ret = false;
> +    }
> +    return ret;
> +}
> +
> +#define FCMP_INSN(suffix)                               \
> +static bool trans_fcmp_cond_##suffix(DisasContext *ctx, \
> +                                     arg_cff_fcond * a) \
> +{                                                       \
> +    return output_cff_fcond(ctx, a, #suffix);           \
> +}
> +
> +FCMP_INSN(s)
> +FCMP_INSN(d)


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

* Re: [PATCH v14 19/26] linux-user: Add LoongArch signal support
  2022-01-06  9:41 ` [PATCH v14 19/26] linux-user: Add LoongArch signal support Song Gao
  2022-01-07  4:58   ` Richard Henderson
@ 2022-01-09  9:25   ` WANG Xuerui
  1 sibling, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang


On 1/6/22 17:41, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> ---
>   linux-user/loongarch64/signal.c        | 198 +++++++++++++++++++++++++
>   linux-user/loongarch64/target_signal.h |  13 ++
>   2 files changed, 211 insertions(+)
>   create mode 100644 linux-user/loongarch64/signal.c
>   create mode 100644 linux-user/loongarch64/target_signal.h
>
> diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c
> new file mode 100644
> index 0000000000..9f0e6421b2
> --- /dev/null
> +++ b/linux-user/loongarch64/signal.c
> @@ -0,0 +1,198 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch emulation of Linux signals
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu.h"
> +#include "signal-common.h"
> +#include "user-internals.h"
> +#include "linux-user/trace.h"
> +
> +#define FPU_REG_WIDTH 256
> +union fpureg {
> +    uint32_t val32[FPU_REG_WIDTH / 32];
> +    uint64_t val64[FPU_REG_WIDTH / 64];
> +};
This is code preemptively added to support the LASX extensions? I 
remember the LASX extension in 3A4000/MIPS era uses 256-bit vector 
registers just like this.
> +
> +struct target_sigcontext {
> +    uint64_t sc_pc;
> +    uint64_t sc_regs[32];
> +    uint32_t sc_flags;
> +    uint32_t sc_fcsr;
> +    uint32_t sc_vcsr;
> +    uint64_t sc_fcc;
> +    uint64_t sc_scr[4];
> +    union fpureg sc_fpregs[32] __attribute__((aligned(32)));
> +    uint8_t sc_reserved[4096] __attribute__((aligned(16)));
> +};
As Richard pointed out, you need to have this synchronized to the 
kernel's definition. It's okay to update after SIMD support lands there, 
it's not to be considered code churn.
> +
> +struct target_ucontext {
> +    target_ulong tuc_flags;
> +    struct target_ucontext *tuc_link;
> +    target_stack_t tuc_stack;
> +    target_sigset_t tuc_sigmask;
> +    uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)];
> +    struct target_sigcontext tuc_mcontext;
> +};
> +
> +struct target_rt_sigframe {
> +    struct target_siginfo rs_info;
> +    struct target_ucontext rs_uc;
> +};
> +
> +static uint64_t read_all_fcc(CPULoongArchState *env)
> +{
> +    uint64_t ret = 0;
> +
> +    for (int i = 0; i < 8; ++i) {
> +        ret |= (uint64_t)env->cf[i] << (i * 8);
> +    }
> +
> +    return ret;
> +}
> +
> +static void write_all_fcc(CPULoongArchState *env, uint64_t val)
> +{
> +    for (int i = 0; i < 8; ++i) {
> +        env->cf[i] = (val >> (i * 8)) & 1;
> +    }
> +}
> +
> +static inline void setup_sigcontext(CPULoongArchState *env,
> +                                    struct target_sigcontext *sc)
> +{
> +    int i;
> +
> +    __put_user(env->pc, &sc->sc_pc);
> +    __put_user(0, &sc->sc_regs[0]);
> +    __put_user(env->fcsr0, &sc->sc_fcsr);
> +    __put_user(0, &sc->sc_vcsr);
> +    sc->sc_fcc = read_all_fcc(env);
> +
> +    for (i = 0; i < 4; ++i) {
> +        __put_user(0, &sc->sc_scr[i]);
> +    }
> +
> +    for (i = 1; i < 32; ++i) {
> +        __put_user(env->gpr[i], &sc->sc_regs[i]);
> +    }
> +
> +    for (i = 0; i < 32; ++i) {
> +        __put_user(env->fpr[i], &sc->sc_fpregs[i].val64[0]);
> +    }
> +}
> +
> +static inline void
> +restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc)
> +{
> +    int i;
> +
> +    __get_user(env->pc, &sc->sc_pc);
> +    __get_user(env->fcsr0, &sc->sc_fcsr);
> +    write_all_fcc(env, sc->sc_fcc);
> +
> +    for (i = 1; i < 32; ++i) {
> +        __get_user(env->gpr[i], &sc->sc_regs[i]);
> +    }
> +
> +    for (i = 0; i < 32; ++i) {
> +        __get_user(env->fpr[i], &sc->sc_fpregs[i].val64[0]);
> +    }
> +}
> +
> +/*
> + * Determine which stack to use..
Duplicate period (".").
> + */
> +static inline abi_ulong
> +get_sigframe(struct target_sigaction *ka, CPULoongArchState *env,
> +             size_t frame_size)
> +{
> +    unsigned long sp;
> +
> +    sp = target_sigsp(get_sp_from_cpustate(env) - 32, ka);
> +
> +    return (sp - frame_size) & ~15;
> +}
> +
> +void setup_rt_frame(int sig, struct target_sigaction *ka,
> +                    target_siginfo_t *info,
> +                    target_sigset_t *set, CPULoongArchState *env)
> +{
> +    struct target_rt_sigframe *frame;
> +    abi_ulong frame_addr;
> +    int i;
> +
> +    frame_addr = get_sigframe(ka, env, sizeof(*frame));
> +    trace_user_setup_rt_frame(env, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto give_sigsegv;
> +    }
> +
> +    tswap_siginfo(&frame->rs_info, info);
> +
> +    __put_user(0, &frame->rs_uc.tuc_flags);
> +    __put_user(0, &frame->rs_uc.tuc_link);
> +    target_save_altstack(&frame->rs_uc.tuc_stack, env);
> +
> +    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
> +
> +    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
> +        __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
> +    }
> +
> +    env->gpr[4] = sig;
> +    env->gpr[5] = frame_addr + offsetof(struct target_rt_sigframe, rs_info);
> +    env->gpr[6] = frame_addr + offsetof(struct target_rt_sigframe, rs_uc);
> +    env->gpr[3] = frame_addr;
> +    env->gpr[1] = default_rt_sigreturn;
> +
> +    env->pc = ka->_sa_handler;
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +
> +give_sigsegv:
> +    unlock_user_struct(frame, frame_addr, 1);
> +    force_sigsegv(sig);
> +}
> +
> +long do_rt_sigreturn(CPULoongArchState *env)
> +{
> +    struct target_rt_sigframe *frame;
> +    abi_ulong frame_addr;
> +    sigset_t blocked;
> +
> +    frame_addr = env->gpr[3];
> +    trace_user_do_rt_sigreturn(env, frame_addr);
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
> +    set_sigmask(&blocked);
> +
> +    restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
> +    target_restore_altstack(&frame->rs_uc.tuc_stack, env);
> +
> +    unlock_user_struct(frame, frame_addr, 0);
> +    return -QEMU_ESIGRETURN;
> +
> +badframe:
> +    unlock_user_struct(frame, frame_addr, 0);
> +    force_sig(TARGET_SIGSEGV);
> +    return -QEMU_ESIGRETURN;
> +}
> +
> +void setup_sigtramp(abi_ulong sigtramp_page)
> +{
> +    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
> +    assert(tramp != NULL);
> +
> +    __put_user(0x03822c0b, tramp + 0);  /* ori     a7, zero, 0x8b */
> +    __put_user(0x002b0000, tramp + 1);  /* syscall 0 */
> +
> +    default_rt_sigreturn = sigtramp_page;
> +    unlock_user(tramp, sigtramp_page, 8);
> +}
> diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h
> new file mode 100644
> index 0000000000..ad3aaffcb4
> --- /dev/null
> +++ b/linux-user/loongarch64/target_signal.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef LOONGARCH_TARGET_SIGNAL_H
> +#define LOONGARCH_TARGET_SIGNAL_H
> +
> +#include "../generic/signal.h"
> +
> +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
> +
> +#endif /* LOONGARCH_TARGET_SIGNAL_H */


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

* Re: [PATCH v14 20/26] linux-user: Add LoongArch elf support
  2022-01-06  9:41 ` [PATCH v14 20/26] linux-user: Add LoongArch elf support Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel
  Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé


On 1/6/22 17:41, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> Reviewed-by: Philippe Mathieu-Daudé<f4bug@amsat.org>
> ---
>   linux-user/elfload.c                | 53 +++++++++++++++++++++++++++++
>   linux-user/loongarch64/target_elf.h | 12 +++++++
>   2 files changed, 65 insertions(+)
>   create mode 100644 linux-user/loongarch64/target_elf.h
>
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 767f54c76d..2ee83778f2 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -914,6 +914,59 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
>   
>   #endif
>   
> +#ifdef TARGET_LOONGARCH64
> +
> +#define ELF_START_MMAP 0x80000000
> +
> +#define ELF_CLASS   ELFCLASS64
> +#define ELF_ARCH    EM_LOONGARCH
> +
> +#define elf_check_arch(x) ((x) == EM_LOONGARCH)
> +static inline void init_thread(struct target_pt_regs *regs,
> +                               struct image_info *infop)
> +{
> +    regs->csr.crmd = 2 << 3;
This is just "1 << 4" and means to set the CSR.CRMD.PG bit, indicating 
that page translation is enabled; it's better to explain this somehow. 
(In writing this comment I realized you might be saying "0b10 << 3" 
instead, because the only valid combinations for the DA and PG bits are 
0b01 and 0b10; so "0b10 << 3" is also okay and maybe clearer.)
> +    regs->csr.era = infop->entry;
> +    regs->regs[3] = infop->start_stack;
> +}
> +
> +/* See linux kernel: arch/loongarch/include/asm/elf.h.  */
> +#define ELF_NREG 45
> +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
> +
> +enum {
> +    TARGET_EF_R0 = 0,
> +    TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32,
> +    TARGET_EF_CSR_BADV = TARGET_EF_R0 + 33,
> +};
> +
> +static void elf_core_copy_regs(target_elf_gregset_t *regs,
> +                               const CPULoongArchState *env)
> +{
> +    int i;
> +
> +    (*regs)[TARGET_EF_R0] = 0;
> +
> +    for (i = 1; i < ARRAY_SIZE(env->gpr); i++) {
> +        (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]);
> +    }
> +
> +    (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc);
> +    (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->badaddr);
> +}
> +
> +#define USE_ELF_CORE_DUMP
> +#define ELF_EXEC_PAGESIZE        4096
> +
> +#define ELF_HWCAP get_elf_hwcap()
> +
> +static uint32_t get_elf_hwcap(void)
> +{
> +    return 0;
> +}
> +
> +#endif /* TARGET_LOONGARCH64 */
> +
>   #ifdef TARGET_MIPS
>   
>   #define ELF_START_MMAP 0x80000000
> diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h
> new file mode 100644
> index 0000000000..3c690bbf5b
> --- /dev/null
> +++ b/linux-user/loongarch64/target_elf.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef LOONGARCH_TARGET_ELF_H
> +#define LOONGARCH_TARGET_ELF_H
> +static inline const char *cpu_get_model(uint32_t eflags)
> +{
> +    return "Loongson-3A5000";
> +}
> +#endif


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

* Re: [PATCH v14 21/26] linux-user: Add LoongArch syscall support
  2022-01-06  9:41 ` [PATCH v14 21/26] linux-user: Add LoongArch syscall support Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel
  Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé


On 1/6/22 17:41, Song Gao wrote:
> We should disable '__BITS_PER_LONG' at [1] before run gensyscalls.sh
>
>   [1] arch/loongarch/include/uapi/asm/bitsperlong.h
>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> Reviewed-by: Philippe Mathieu-Daudé<f4bug@amsat.org>
> ---
>   linux-user/loongarch64/syscall_nr.h     | 313 ++++++++++++++++++++++++
>   linux-user/loongarch64/target_syscall.h |  48 ++++
>   linux-user/syscall_defs.h               |  10 +-
>   scripts/gensyscalls.sh                  |   1 +
>   4 files changed, 368 insertions(+), 4 deletions(-)
>   create mode 100644 linux-user/loongarch64/syscall_nr.h
>   create mode 100644 linux-user/loongarch64/target_syscall.h

This is exactly what we don't want to merge before the Linux port (and 
glibc) lands; things like UNAME_MINIMUM_RELEASE and the syscall numbers 
certainly need to be updated afterwards. Otherwise everything looks good 
though.

The "struct { ... } csr" part suggested by Philippe is deviating from 
the kernel sources, but the memory layout is the same, and in looking at 
other targets it seems we're not required to keep exact correspondence 
with kernel -- am I right? (Many targets do use the exact definition as 
kernel, e.g. aarch64, though)



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

* Re: [PATCH v14 22/26] linux-user: Add LoongArch cpu_loop support
  2022-01-06  9:41 ` [PATCH v14 22/26] linux-user: Add LoongArch cpu_loop support Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson


On 1/6/22 17:41, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> ---
>   configure                           |  3 +
>   linux-user/loongarch64/cpu_loop.c   | 94 +++++++++++++++++++++++++++++
>   linux-user/loongarch64/target_cpu.h | 34 +++++++++++
>   3 files changed, 131 insertions(+)
>   create mode 100644 linux-user/loongarch64/cpu_loop.c
>   create mode 100644 linux-user/loongarch64/target_cpu.h
>
> diff --git a/configure b/configure
> index 030728d11e..93c4e5bd92 100755
> --- a/configure
> +++ b/configure
> @@ -659,6 +659,9 @@ case "$cpu" in
>     mips*)
>       cpu="mips" ;;
>   
> +  loongarch)
> +    cpu="loongarch64" ;;
> +
Do you really need this? Looking at the part above setting initial value 
for $cpu, you can only get here if $cpu is given on command-line, or 
returned by uname on a presumably LoongArch system not defining 
__loongarch64. Either would be unlikely though, and we really don't want 
to turn on 64-bit code for 32-bit hosts (that don't exist at the 
moment), so this case seems useless.
>     ppc)
>       CPU_CFLAGS="-m32" ;;
>     ppc64)
> diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c
> new file mode 100644
> index 0000000000..6628d215ca
> --- /dev/null
> +++ b/linux-user/loongarch64/cpu_loop.c
> @@ -0,0 +1,94 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU LoongArch user cpu_loop.
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu.h"
> +#include "qemu-common.h"
> +#include "user-internals.h"
> +#include "cpu_loop-common.h"
> +#include "signal-common.h"
> +
> +void cpu_loop(CPULoongArchState *env)
> +{
> +    CPUState *cs = env_cpu(env);
> +    int trapnr, si_code;
> +    abi_long ret;
> +
> +    for (;;) {
> +        cpu_exec_start(cs);
> +        trapnr = cpu_exec(cs);
> +        cpu_exec_end(cs);
> +        process_queued_cpu_work(cs);
> +
> +        switch (trapnr) {
> +        case EXCP_INTERRUPT:
> +            /* just indicate that signals should be handled asap */
> +            break;
> +        case EXCP_SYSCALL:
> +            env->pc += 4;
> +            ret = do_syscall(env, env->gpr[11],
> +                             env->gpr[4], env->gpr[5],
> +                             env->gpr[6], env->gpr[7],
> +                             env->gpr[8], env->gpr[9],
> +                             -1, -1);
> +            if (ret == -QEMU_ERESTARTSYS) {
> +                env->pc -= 4;
> +                break;
> +            }
> +            if (ret == -QEMU_ESIGRETURN) {
> +                /*
> +                 * Returning from a successful sigreturn syscall.
> +                 * Avoid clobbering register state.
> +                 */
> +                break;
> +            }
> +            env->gpr[4] = ret;
> +            break;
> +        case EXCP_INE:
> +            force_sig_fault(TARGET_SIGILL, 0, env->pc);
> +            break;
> +        case EXCP_FPE:
> +            si_code = TARGET_FPE_FLTUNK;
> +            if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) {
> +                si_code = TARGET_FPE_FLTINV;
> +            } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) {
> +                si_code = TARGET_FPE_FLTDIV;
> +            } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) {
> +                si_code = TARGET_FPE_FLTOVF;
> +            } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) {
> +                si_code = TARGET_FPE_FLTUND;
> +            } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) {
> +                si_code = TARGET_FPE_FLTRES;
> +            }
> +            force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
> +            break;
> +        case EXCP_DEBUG:
> +        case EXCP_BREAK:
> +            force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
> +            break;
> +        case EXCP_ATOMIC:
> +            cpu_exec_step_atomic(cs);
> +            break;
> +        default:
> +            EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
> +                      trapnr);
> +            exit(EXIT_FAILURE);
> +        }
> +        process_pending_signals(env);
> +    }
> +}
> +
> +void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
> +{
> +    int i;
> +
> +    for (i = 0; i < 32; i++) {
> +        env->gpr[i] = regs->regs[i];
> +    }
> +    env->pc = regs->csr.era;
> +
> +}
> diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h
> new file mode 100644
> index 0000000000..a29af66156
> --- /dev/null
> +++ b/linux-user/loongarch64/target_cpu.h
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch specific CPU ABI and functions for linux-user
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef LOONGARCH_TARGET_CPU_H
> +#define LOONGARCH_TARGET_CPU_H
> +
> +static inline void cpu_clone_regs_child(CPULoongArchState *env,
> +                                        target_ulong newsp, unsigned flags)
> +{
> +    if (newsp) {
> +        env->gpr[3] = newsp;
> +    }
> +    env->gpr[4] = 0;
> +}
> +
> +static inline void cpu_clone_regs_parent(CPULoongArchState *env,
> +                                         unsigned flags)
> +{
> +}
> +
> +static inline void cpu_set_tls(CPULoongArchState *env, target_ulong newtls)
> +{
> +    env->gpr[2] = newtls;
> +}
> +
> +static inline abi_ulong get_sp_from_cpustate(CPULoongArchState *state)
> +{
> +    return state->gpr[3];
> +}
> +#endif


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

* Re: [PATCH v14 23/26] default-configs: Add loongarch linux-user support
  2022-01-06  9:41 ` [PATCH v14 23/26] default-configs: Add loongarch linux-user support Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson


On 1/6/22 17:41, Song Gao wrote:
> This patch adds loongarch64 linux-user default configs file.
>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> ---
>   configs/targets/loongarch64-linux-user.mak | 3 +++
>   1 file changed, 3 insertions(+)
>   create mode 100644 configs/targets/loongarch64-linux-user.mak
>
> diff --git a/configs/targets/loongarch64-linux-user.mak b/configs/targets/loongarch64-linux-user.mak
> new file mode 100644
> index 0000000000..5b0acfa3ec
> --- /dev/null
> +++ b/configs/targets/loongarch64-linux-user.mak
> @@ -0,0 +1,3 @@
> +# Default configuration for loongson64-linux-user
"loongarch64-linux-user"?
> +TARGET_ARCH=loongarch64
> +TARGET_BASE_ARCH=loongarch

With that fixed:

Reviewed-by: WANG Xuerui <git@xen0n.name>



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

* Re: [PATCH v14 24/26] target/loongarch: Add target build suport
  2022-01-06  9:41 ` [PATCH v14 24/26] target/loongarch: Add target build suport Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel
  Cc: Xiaojuan Yang, Richard Henderson, Philippe Mathieu-Daudé


On 1/6/22 17:41, Song Gao wrote:
> This patch adds build loongarch-linux-user target support.

Chinglish... You may just say "target: Add the loongarch target_arch" 
and remove this sentence.

> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> Reviewed-by: Philippe Mathieu-Daudé<f4bug@amsat.org>
> ---
>   target/loongarch/meson.build | 19 +++++++++++++++++++
>   target/meson.build           |  1 +
>   2 files changed, 20 insertions(+)
>   create mode 100644 target/loongarch/meson.build
>
> diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
> new file mode 100644
> index 0000000000..bcb076e55f
> --- /dev/null
> +++ b/target/loongarch/meson.build
> @@ -0,0 +1,19 @@
> +gen = decodetree.process('insns.decode')
> +
> +loongarch_ss = ss.source_set()
> +loongarch_ss.add(files(
> +  'cpu.c',
> +  'disas.c',
> +))
> +loongarch_tcg_ss = ss.source_set()
> +loongarch_tcg_ss.add(gen)
> +loongarch_tcg_ss.add(files(
> +  'fpu_helper.c',
> +  'op_helper.c',
> +  'translate.c',
> +))
> +loongarch_tcg_ss.add(zlib)
> +
> +loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
> +
> +target_arch += {'loongarch': loongarch_ss}
> diff --git a/target/meson.build b/target/meson.build
> index 2f6940255e..a53a60486f 100644
> --- a/target/meson.build
> +++ b/target/meson.build
> @@ -5,6 +5,7 @@ subdir('cris')
>   subdir('hexagon')
>   subdir('hppa')
>   subdir('i386')
> +subdir('loongarch')
>   subdir('m68k')
>   subdir('microblaze')
>   subdir('mips')


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

* Re: [PATCH v14 25/26] target/loongarch: 'make check-tcg' support
  2022-01-06  9:41 ` [PATCH v14 25/26] target/loongarch: 'make check-tcg' support Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel
  Cc: Richard Henderson, Xiaojuan Yang, Alex Bennée,
	Philippe Mathieu-Daudé


On 1/6/22 17:41, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> Acked-by: Alex Bennée<alex.bennee@linaro.org>
> Reviewed-by: Philippe Mathieu-Daudé<f4bug@amsat.org>
> ---
>   tests/tcg/configure.sh | 1 +
>   1 file changed, 1 insertion(+)
>
> diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
> index 8eb4287c84..c3d7e45524 100755
> --- a/tests/tcg/configure.sh
> +++ b/tests/tcg/configure.sh
> @@ -51,6 +51,7 @@ fi
>   : ${cross_cc_cflags_armeb="-mbig-endian"}
>   : ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"}
>   : ${cross_cc_cflags_hexagon="-mv67 -O2 -static"}
> +: ${cross_cc_loongarch64="loongarch64-unknown-linux-gnu-gcc"}
>   : ${cross_cc_hppa="hppa-linux-gnu-gcc"}
>   : ${cross_cc_i386="i686-linux-gnu-gcc"}
>   : ${cross_cc_cflags_i386="-m32"}
Reviewed-by: WANG Xuerui <git@xen0n.name>


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

* Re: [PATCH v14 26/26] scripts: add loongarch64 binfmt config
  2022-01-06  9:42 ` [PATCH v14 26/26] scripts: add loongarch64 binfmt config Song Gao
@ 2022-01-09  9:25   ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-09  9:25 UTC (permalink / raw)
  To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, Richard Henderson


On 1/6/22 17:42, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> ---
>   scripts/qemu-binfmt-conf.sh | 6 +++++-
>   1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
> index 7de996d536..da6a937be8 100755
> --- a/scripts/qemu-binfmt-conf.sh
> +++ b/scripts/qemu-binfmt-conf.sh
> @@ -4,7 +4,7 @@
>   qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \
>   ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \
>   sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
> -microblaze microblazeel or1k x86_64 hexagon"
> +microblaze microblazeel or1k x86_64 hexagon loongarch64"
>   
>   i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
>   i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> @@ -140,6 +140,10 @@ hexagon_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x
>   hexagon_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
>   hexagon_family=hexagon
>   
> +loongarch64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02\x01'
> +loongarch64_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
> +loongarch64_family=loongarch
> +
>   qemu_get_family() {
>       cpu=${HOST_ARCH:-$(uname -m)}
>       case "$cpu" in

We don't have code in qemu_get_family to recognize "loongarch*" from 
uname output as "loongarch" family (you can even understand it as I 
missed this change in my TCG port series...), but otherwise this looks OK.

I can add the host CPU family recognition myself; for this patch,

Reviewed-by: WANG Xuerui <git@xen0n.name>



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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-09  9:25   ` WANG Xuerui
@ 2022-01-09 18:49     ` Richard Henderson
  2022-01-10 12:34       ` gaosong
  2022-01-10 13:00     ` gaosong
  2022-01-12  9:28     ` gaosong
  2 siblings, 1 reply; 53+ messages in thread
From: Richard Henderson @ 2022-01-09 18:49 UTC (permalink / raw)
  To: WANG Xuerui, Song Gao, qemu-devel
  Cc: Xiaojuan Yang, Philippe Mathieu-Daudé

On 1/9/22 1:25 AM, WANG Xuerui wrote:
>> +#define TARGET_PAGE_BITS 14
> Aren't we capable of page sizes up to 64KiB? Minimal feasible page size is indeed 16KiB 
> though (due to cache aliasing, although 4KiB pages are supported in hardware, they don't 
> work in practice).

You must use the minimal page size here.  64k pages would be handled solely within 
tlb_fill, as multiples of the minimal page size.

>> +static bool loongarch_cpu_has_work(CPUState *cs)
>> +{
>> +    return true;
> 
> Note: this is only applicable to CONFIG_USER_ONLY, and needs to be changed in the 
> following commits adding system emulation. To better convey your intention it may be 
> better to use an #ifdef guard, something like this:
> 
> #ifndef CONFIG_USER_ONLY
> #error System emulation TODO
> #else
>      return true;
> #endif
> 
> (I'm not sure if this is okay in QEMU coding style, so please correct me if this isn't the 
> case.)

Prefer positive tests over negative tests, so

#ifdef CONFIG_USER_ONLY
     return true;
#else
#error
#endif

>> +    data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
> Do you support the SPW extension in this series? If not you probably don't want to set 
> this bit.

Correct, you can't expose features that you don't implement.

>> +    uint64_t lladdr; /* LL virtual address compared against SC */
> Similarly, do we explain every field with comments *here*? I think if fields are named 
> according to the manuals, people will naturally look up names there so there's no worry 
> for misunderstanding.
>> +    uint64_t llval;

These two fields are not architectural, so they do require explanation.  Not that there 
aren't other targets that lack this documentation...


r~


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

* Re: [PATCH v14 16/26] target/loongarch: Add disassembler
  2022-01-09  9:25   ` WANG Xuerui
@ 2022-01-09 18:51     ` Richard Henderson
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2022-01-09 18:51 UTC (permalink / raw)
  To: WANG Xuerui, Song Gao, qemu-devel; +Cc: Xiaojuan Yang

On 1/9/22 1:25 AM, WANG Xuerui wrote:
>> +static inline int shl_2(DisasContext *ctx, int x)
>> +{
>> +    return x * 4;
> Although "<< 2" has the same effect as "* 4" here, isn't "<< 2" better in matching the 
> function name?

Yes, good point.


r~


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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-09 18:49     ` Richard Henderson
@ 2022-01-10 12:34       ` gaosong
  2022-01-10 15:20         ` WANG Xuerui
  0 siblings, 1 reply; 53+ messages in thread
From: gaosong @ 2022-01-10 12:34 UTC (permalink / raw)
  To: WANG Xuerui
  Cc: Xiaojuan Yang, Richard Henderson, qemu-devel,
	Philippe Mathieu-Daudé

[-- Attachment #1: Type: text/plain, Size: 1747 bytes --]

Hi,

On 2022/1/10 上午2:49, Richard Henderson wrote:
>>> +static bool loongarch_cpu_has_work(CPUState *cs)
>>> +{
>>> +    return true;
>>
>> Note: this is only applicable to CONFIG_USER_ONLY, and needs to be 
>> changed in the following commits adding system emulation. To better 
>> convey your intention it may be better to use an #ifdef guard, 
>> something like this:
>>
>> #ifndef CONFIG_USER_ONLY
>> #error System emulation TODO
>> #else
>>      return true;
>> #endif
>>
>> (I'm not sure if this is okay in QEMU coding style, so please correct 
>> me if this isn't the case.)
>
In my opinion, we don't need to do this. As you pointed out below, SPW shouldn't appear in this series. All CONFIG_USER_ONLY  macors should appear in the system emulation series.

Liks this:

https://patchew.org/QEMU/20220108091419.2027710-1-yangxiaojuan@loongson.cn/20220108091419.2027710-12-yangxiaojuan@loongson.cn/

  static bool loongarch_cpu_has_work(CPUState *cs)
  {
+#ifdef CONFIG_USER_ONLY
      return true;
+#else
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    CPULoongArchState *env = &cpu->env;
+    bool has_work = false;
+
+    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+        cpu_loongarch_hw_interrupts_pending(env)) {
+        has_work = true;
+    }
+
+    return has_work;
+#endif
  }

> Prefer positive tests over negative tests, so
>
> #ifdef CONFIG_USER_ONLY
>     return true;
> #else
> #error
> #endif
>
>>> +    data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
>> Do you support the SPW extension in this series? If not you probably 
>> don't want to set this bit.
>
> Correct, you can't expose features that you don't implement.

Accept this suggesstions.

Thanks
Song


[-- Attachment #2: Type: text/html, Size: 3275 bytes --]

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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-09 18:49     ` Richard Henderson
@ 2022-01-10 13:00     ` gaosong
  2022-01-10 15:11       ` WANG Xuerui
  2022-01-12  9:28     ` gaosong
  2 siblings, 1 reply; 53+ messages in thread
From: gaosong @ 2022-01-10 13:00 UTC (permalink / raw)
  To: WANG Xuerui
  Cc: Xiaojuan Yang, Richard Henderson, qemu-devel,
	Philippe Mathieu-Daudé

[-- Attachment #1: Type: text/plain, Size: 1369 bytes --]

Hi,

On 2022/1/9 下午5:25, WANG Xuerui wrote:
>> +
>> +const char * const fregnames[32] = {
>> +    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
>> +    "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
>> +    "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
>> +    "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
>> +};
>> +
>> +static const char * const excp_names[EXCP_LAST + 1] = {
>> +    [EXCP_SYSCALL] = "Syscall",
>> +    [EXCP_BREAK] = "Break",
>> +    [EXCP_INE] = "Instruction Non-existent",
> Nit: "Instruction Non-Existent" (or is there any authoritative source 
> for this spelling? the English translation of the manual?) 

I must admit that your English is really good, But 'Instruction Non-existent' is what you pointed out in v7.  I have a history [1],

[1] https://patchew.org/QEMU/1634561247-25499-1-git-send-email-gaosong@loongson.cn/1634561247-25499-3-git-send-email-gaosong@loongson.cn/

> +static const char * const excp_names[EXCP_LAST + 1] = {
> +    [EXCP_ADE] = "Address error",
> +    [EXCP_SYSCALL] = "Syscall",
> +    [EXCP_BREAK] = "Break",
> +    [EXCP_INE] = "Inst. Not Exist",
Nit: "Instruction Non-existent", no need to shorten "instruction" like
this IMO; no other similar usages exist so this would not be consistent.

In any case thank you for your other suggestions.

Thanks
Song


[-- Attachment #2: Type: text/html, Size: 3692 bytes --]

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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-10 13:00     ` gaosong
@ 2022-01-10 15:11       ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-10 15:11 UTC (permalink / raw)
  To: gaosong
  Cc: Xiaojuan Yang, Richard Henderson, qemu-devel,
	Philippe Mathieu-Daudé

[-- Attachment #1: Type: text/plain, Size: 1993 bytes --]

Hi,

On 1/10/22 21:00, gaosong wrote:
>
> Hi,
>
> On 2022/1/9 下午5:25, WANG Xuerui wrote:
>>> +
>>> +const char * const fregnames[32] = {
>>> +    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
>>> +    "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
>>> +    "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
>>> +    "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
>>> +};
>>> +
>>> +static const char * const excp_names[EXCP_LAST + 1] = {
>>> +    [EXCP_SYSCALL] = "Syscall",
>>> +    [EXCP_BREAK] = "Break",
>>> +    [EXCP_INE] = "Instruction Non-existent",
>> Nit: "Instruction Non-Existent" (or is there any authoritative source 
>> for this spelling? the English translation of the manual?) 
> I must admit that your English is really good, But 'Instruction Non-existent' is what you pointed out in v7.  I have a history [1],
> [1]https://patchew.org/QEMU/1634561247-25499-1-git-send-email-gaosong@loongson.cn/1634561247-25499-3-git-send-email-gaosong@loongson.cn/
> > +static const char * const excp_names[EXCP_LAST + 1] = {
> > +    [EXCP_ADE] = "Address error",
> > +    [EXCP_SYSCALL] = "Syscall",
> > +    [EXCP_BREAK] = "Break",
> > +    [EXCP_INE] = "Inst. Not Exist",
> Nit: "Instruction Non-existent", no need to shorten "instruction" like
> this IMO; no other similar usages exist so this would not be consistent.
> In any case thank you for your other suggestions.

Well, I do make my mistakes sometimes, and I'll explain a bit: in the 
former review what I noticed was the broken English, and I pointed that 
out, but meanwhile I've forgotten I had done that, and why I didn't 
write "Non-Existent" was because the "Address error" wasn't in full 
Title Case. However, in this revision, what I noticed is the 
inconsistent casing (with EXCP_ADE removed, all other strings are in 
Title Case now), hence the reply.

No need to go full self-defense over this; I think what matters after 
all is just consistency.

>
> Thanks
> Song

[-- Attachment #2: Type: text/html, Size: 3975 bytes --]

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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-10 12:34       ` gaosong
@ 2022-01-10 15:20         ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-10 15:20 UTC (permalink / raw)
  To: gaosong
  Cc: Xiaojuan Yang, Richard Henderson, qemu-devel,
	Philippe Mathieu-Daudé

[-- Attachment #1: Type: text/plain, Size: 1519 bytes --]

Hi,

On 1/10/22 20:34, gaosong wrote:
>
> Hi,
>
> On 2022/1/10 上午2:49, Richard Henderson wrote:
>>>> +static bool loongarch_cpu_has_work(CPUState *cs)
>>>> +{
>>>> +    return true;
>>>
>>> Note: this is only applicable to CONFIG_USER_ONLY, and needs to be 
>>> changed in the following commits adding system emulation. To better 
>>> convey your intention it may be better to use an #ifdef guard, 
>>> something like this:
>>>
>>> #ifndef CONFIG_USER_ONLY
>>> #error System emulation TODO
>>> #else
>>>      return true;
>>> #endif
>>>
>>> (I'm not sure if this is okay in QEMU coding style, so please 
>>> correct me if this isn't the case.)
>>
> In my opinion, we don't need to do this. As you pointed out below, SPW shouldn't appear in this series. All CONFIG_USER_ONLY  macors should appear in the system emulation series.

IMO, preemptively including the guard serves as "paving the road" to the 
full system emulation; in your argument, I feel we're deferring too much 
information to the context (this patch being inside the "linux-user" 
series, and getting merged earlier than full system emulation), while 
context would gradually fade out in the months/years ahead; being 
precise in writing down what you mean doesn't do any harm.

Additionally, we might have to re-order the patches in order to unblock 
as much progress as possible, and in that case, this patch and the other 
patch adding the !CONFIG_USER_ONLY part would probably get squashed into 
one, so this code has to be touched too.

[-- Attachment #2: Type: text/html, Size: 2525 bytes --]

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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-09  9:25   ` WANG Xuerui
  2022-01-09 18:49     ` Richard Henderson
  2022-01-10 13:00     ` gaosong
@ 2022-01-12  9:28     ` gaosong
  2022-01-12 10:17       ` gaosong
  2 siblings, 1 reply; 53+ messages in thread
From: gaosong @ 2022-01-12  9:28 UTC (permalink / raw)
  To: WANG Xuerui
  Cc: Xiaojuan Yang, Richard Henderson, qemu-devel,
	Philippe Mathieu-Daudé

[-- Attachment #1: Type: text/plain, Size: 1224 bytes --]

Hi,

On 2022/1/9 下午5:25, WANG Xuerui wrote:
>> +    data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
>> +    data = FIELD_DP32(data, CPUCFG16, L2_IUPRE, 1);
>> +    data = FIELD_DP32(data, CPUCFG16, L2_IUUNIFY, 1);
>> +    data = FIELD_DP32(data, CPUCFG16, L2_IUPRIV, 1);
>> +    data = FIELD_DP32(data, CPUCFG16, L3_IUPRE, 1);
>> +    data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
>> +    data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
>> +    env->cpucfg[16] = data;
>> +
>> +    data = 0;
>> +    data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 0x8003);
>
> This seems out-of-place, according to the manual this field is Way-1 
> for the L1I cache, so you have 0x8004=32772 ways in this cache?
>
> Same for all similar constructions below.
>
I have time to reply to your comment now.

As in the previous comments, I don't remember which one,these values should be the same as the values of the physical environment. I dumped 'CPUCFG17' value again,
the value is no problem. Maybe you didn't think about dumping these values when you commented. The value of  'L11U_SIZE' is dumped to be 0. and cpucfg[i] has been
initialized to 0 before. There is no need to set it again.

Thanks
Song


[-- Attachment #2: Type: text/html, Size: 1909 bytes --]

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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-12  9:28     ` gaosong
@ 2022-01-12 10:17       ` gaosong
  2022-01-12 10:26         ` WANG Xuerui
  0 siblings, 1 reply; 53+ messages in thread
From: gaosong @ 2022-01-12 10:17 UTC (permalink / raw)
  To: WANG Xuerui
  Cc: Xiaojuan Yang, Richard Henderson, qemu-devel,
	Philippe Mathieu-Daudé

[-- Attachment #1: Type: text/plain, Size: 1149 bytes --]

Hi,

On 2022/1/12 下午5:28, gaosong wrote:
>>> +    data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
>>> +    data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
>>> +    env->cpucfg[16] = data;
>>> +
>>> +    data = 0;
>>> +    data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 0x8003);
>>
>> This seems out-of-place, according to the manual this field is Way-1 
>> for the L1I cache, so you have 0x8004=32772 ways in this cache?
>>
>> Same for all similar constructions below.
>>
> I have time to reply to your comment now.
> As in the previous comments, I don't remember which one,these values should be the same as the values of the physical environment. I dumped 'CPUCFG17' value again,
> the value is no problem. Maybe you didn't think about dumping these values when you commented. The value of  'L11U_SIZE' is dumped to be 0. and cpucfg[i] has been
> initialized to 0 before. There is no need to set it again.

Not quite right,  cpucfg[17] is '0x60800003', I missed a '0',  I don't know from which version it's wrong
Thank you very much,  if I hadn't dumped the value today, I wouldn't have realized the wrong.

> Thanks
> Song

[-- Attachment #2: Type: text/html, Size: 1927 bytes --]

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

* Re: [PATCH v14 02/26] target/loongarch: Add core definition
  2022-01-12 10:17       ` gaosong
@ 2022-01-12 10:26         ` WANG Xuerui
  0 siblings, 0 replies; 53+ messages in thread
From: WANG Xuerui @ 2022-01-12 10:26 UTC (permalink / raw)
  To: gaosong
  Cc: Xiaojuan Yang, Richard Henderson, qemu-devel,
	Philippe Mathieu-Daudé

[-- Attachment #1: Type: text/plain, Size: 2833 bytes --]

Hi,

On 2022/1/12 18:17, gaosong wrote:
>
> Hi,
>
> On 2022/1/12 下午5:28, gaosong wrote:
>>>> +    data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
>>>> +    data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
>>>> +    env->cpucfg[16] = data;
>>>> +
>>>> +    data = 0;
>>>> +    data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 0x8003);
>>>
>>> This seems out-of-place, according to the manual this field is Way-1
>>> for the L1I cache, so you have 0x8004=32772 ways in this cache?
>>>
>>> Same for all similar constructions below.
>>>
>> I have time to reply to your comment now.
>> As in the previous comments, I don't remember which one,these values should be the same as the values of the physical environment. I dumped 'CPUCFG17' value again,
>> the value is no problem. Maybe you didn't think about dumping these values when you commented. The value of  'L11U_SIZE' is dumped to be 0. and cpucfg[i] has been 
>> initialized to 0 before. There is no need to set it again.
> Not quite right,  cpucfg[17] is '0x60800003', I missed a '0',  I don't know from which version it's wrong
> Thank you very much,  if I hadn't dumped the value today, I wouldn't have realized the wrong.  

Still not quite right; maybe you made a typo there as the value is
`0x06080003` (the fields are all whole bytes/shorts, so very easy to
recognize).

I used the following snippet to get real values from the 3A5000 system:

    #include <stdio.h>

    int cpucfg(const int sel)
    {
            int ret;
            __asm__ __volatile__("cpucfg %0, %1" : "=r"(ret) : "r"(sel));
            return ret;
    }

    int main(void)
    {
            int i;
            int c;
            for (i = 0; i < 64; i++) {
                    c = cpucfg(i);
                    if (!c) {
                            continue;
                    }
                    printf("CPUCFG.0x%-2x = 0x%08x\n", i, c);
            }

            return 0;
    }

And I got the following output so we can cross-check:

    CPUCFG.0x0  = 0x0014c010
    CPUCFG.0x1  = 0x03f2f2fe
    CPUCFG.0x2  = 0x007ccfc7
    CPUCFG.0x3  = 0x0000fcff
    CPUCFG.0x4  = 0x05f5e100
    CPUCFG.0x5  = 0x00010001
    CPUCFG.0x6  = 0x00007f33
    CPUCFG.0x10 = 0x00002c3d
    CPUCFG.0x11 = 0x06080003
    CPUCFG.0x12 = 0x06080003
    CPUCFG.0x13 = 0x0608000f
    CPUCFG.0x14 = 0x060e000f
    CPUCFG.0x30 = 0x0000000e

Obviously the 0x30 leaf is undocumented, but not implementing it
shouldn't matter either, as userspace has no way to make use of that
when people aren't even aware of its existence. The other fields are of
course to be checked to only leave the implemented bits set in the QEMU
implementation.

Hope that helps!

[-- Attachment #2: Type: text/html, Size: 4426 bytes --]

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

end of thread, other threads:[~2022-01-12 10:28 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-06  9:41 [PATCH v14 00/26] Add LoongArch linux-user emulation support Song Gao
2022-01-06  9:41 ` [PATCH v14 01/26] target/loongarch: Add README Song Gao
2022-01-09  9:24   ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 02/26] target/loongarch: Add core definition Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-09 18:49     ` Richard Henderson
2022-01-10 12:34       ` gaosong
2022-01-10 15:20         ` WANG Xuerui
2022-01-10 13:00     ` gaosong
2022-01-10 15:11       ` WANG Xuerui
2022-01-12  9:28     ` gaosong
2022-01-12 10:17       ` gaosong
2022-01-12 10:26         ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 03/26] target/loongarch: Add main translation routines Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 04/26] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
2022-01-06  9:41 ` [PATCH v14 05/26] target/loongarch: Add fixed point shift " Song Gao
2022-01-06  9:41 ` [PATCH v14 06/26] target/loongarch: Add fixed point bit " Song Gao
2022-01-06  9:41 ` [PATCH v14 07/26] target/loongarch: Add fixed point load/store " Song Gao
2022-01-06  9:41 ` [PATCH v14 08/26] target/loongarch: Add fixed point atomic " Song Gao
2022-01-06  9:41 ` [PATCH v14 09/26] target/loongarch: Add fixed point extra " Song Gao
2022-01-06  9:41 ` [PATCH v14 10/26] target/loongarch: Add floating point arithmetic " Song Gao
2022-01-06  9:41 ` [PATCH v14 11/26] target/loongarch: Add floating point comparison " Song Gao
2022-01-06  9:41 ` [PATCH v14 12/26] target/loongarch: Add floating point conversion " Song Gao
2022-01-06  9:41 ` [PATCH v14 13/26] target/loongarch: Add floating point move " Song Gao
2022-01-06  9:41 ` [PATCH v14 14/26] target/loongarch: Add floating point load/store " Song Gao
2022-01-06  9:41 ` [PATCH v14 15/26] target/loongarch: Add branch " Song Gao
2022-01-06  9:41 ` [PATCH v14 16/26] target/loongarch: Add disassembler Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-09 18:51     ` Richard Henderson
2022-01-06  9:41 ` [PATCH v14 17/26] linux-user: Add LoongArch generic header files Song Gao
2022-01-06  9:41 ` [PATCH v14 18/26] linux-user: Add LoongArch specific structures Song Gao
2022-01-07  4:29   ` Richard Henderson
2022-01-06  9:41 ` [PATCH v14 19/26] linux-user: Add LoongArch signal support Song Gao
2022-01-07  4:58   ` Richard Henderson
2022-01-09  9:25   ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 20/26] linux-user: Add LoongArch elf support Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 21/26] linux-user: Add LoongArch syscall support Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 22/26] linux-user: Add LoongArch cpu_loop support Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 23/26] default-configs: Add loongarch linux-user support Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 24/26] target/loongarch: Add target build suport Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-06  9:41 ` [PATCH v14 25/26] target/loongarch: 'make check-tcg' support Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-06  9:42 ` [PATCH v14 26/26] scripts: add loongarch64 binfmt config Song Gao
2022-01-09  9:25   ` WANG Xuerui
2022-01-07  5:01 ` [PATCH v14 00/26] Add LoongArch linux-user emulation support Richard Henderson
2022-01-07  7:59   ` gaosong
2022-01-09  5:09     ` WANG Xuerui

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.