* [PATCH v11 00/26] Add LoongArch linux-user emulation support
@ 2021-11-19 6:13 Song Gao
2021-11-19 6:13 ` [PATCH v11 01/26] target/loongarch: Add README Song Gao
` (25 more replies)
0 siblings, 26 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson, laurent
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:
* 0016-target-loongarch-Add-disassembler.patch
* 0017-linux-user-Add-LoongArch-generic-header-files.patch
* 0018-linux-user-Add-LoongArch-specific-structures.patch
* 0019-linux-user-Add-LoongArch-signal-support.patch
* 0020-linux-user-Add-LoongArch-elf-support.patch
* 0021-linux-user-Add-LoongArch-syscall-support.patch
* 0022-linux-user-Add-LoongArch-cpu_loop-support.patch
Changes for v11:
* Clean up insns.decode.
Changes for v10:
* Delete format_insn(), use output_XXX.
Changes for v9:
* Use GPL-2.0+ SPDX license identifier.
* Move set_loongarch_cpucfg() in loongarch_3a5000_initfn().
* target/loongarch/insn_trans/trans_xxx.c rename to
target/loongarch/insn_trans/trans_xxx.c.inc.
* Split host_signal_pc and host_signal_write out of user-exec.c.
Changes for v8:
* Use the FIELD functions to define cpucfg[i].
* Re-use the decodetree to disassembler description.
* Split v7 patch(0017-LoongArch-Linux-User-Emulation.patch).
Changes for v7:
* scripts/gensyscalls.sh support loongarch64
if we use gensyscalls.sh, we need disable __BITS_PER_LONG at arch/loongarch/include/uapi/asm/bitsperlong.h
V10:https://patchew.org/QEMU/1636700049-24381-1-git-send-email-gaosong@loongson.cn/
V9: https://patchew.org/QEMU/1636340895-5255-1-git-send-email-gaosong@loongson.cn/
V8: https://patchew.org/QEMU/1635760311-20015-1-git-send-email-gaosong@loongson.cn/
V7: https://patchew.org/QEMU/1634561247-25499-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 | 5 +
include/disas/dis-asm.h | 2 +
include/elf.h | 2 +
linux-user/elfload.c | 58 ++
linux-user/loongarch64/cpu_loop.c | 97 +++
linux-user/loongarch64/signal.c | 162 +++++
linux-user/loongarch64/sockbits.h | 11 +
linux-user/loongarch64/syscall_nr.h | 312 +++++++++
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 | 29 +
linux-user/loongarch64/target_structs.h | 48 ++
linux-user/loongarch64/target_syscall.h | 45 ++
linux-user/loongarch64/termbits.h | 11 +
linux-user/syscall_defs.h | 10 +-
meson.build | 3 +-
scripts/gensyscalls.sh | 1 +
scripts/qemu-binfmt-conf.sh | 6 +-
target/loongarch/README | 76 +++
target/loongarch/cpu-param.h | 18 +
target/loongarch/cpu.c | 315 +++++++++
target/loongarch/cpu.h | 253 +++++++
target/loongarch/disas.c | 625 +++++++++++++++++
target/loongarch/fpu_helper.c | 864 ++++++++++++++++++++++++
target/loongarch/helper.h | 94 +++
target/loongarch/insn_trans/trans_arith.c.inc | 309 +++++++++
target/loongarch/insn_trans/trans_atomic.c.inc | 130 ++++
target/loongarch/insn_trans/trans_bit.c.inc | 252 +++++++
target/loongarch/insn_trans/trans_branch.c.inc | 82 +++
target/loongarch/insn_trans/trans_extra.c.inc | 84 +++
target/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 +
target/loongarch/insn_trans/trans_fmemory.c.inc | 184 +++++
target/loongarch/insn_trans/trans_fmov.c.inc | 150 ++++
target/loongarch/insn_trans/trans_memory.c.inc | 232 +++++++
target/loongarch/insn_trans/trans_shift.c.inc | 128 ++++
target/loongarch/insns.decode | 444 ++++++++++++
target/loongarch/internals.h | 28 +
target/loongarch/meson.build | 19 +
target/loongarch/op_helper.c | 84 +++
target/loongarch/translate.c | 297 ++++++++
target/loongarch/translate.h | 45 ++
target/meson.build | 1 +
tests/tcg/configure.sh | 1 +
49 files changed, 5782 insertions(+), 6 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
--
1.8.3.1
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH v11 01/26] target/loongarch: Add README
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-19 6:13 ` [PATCH v11 02/26] target/loongarch: Add core definition Song Gao
` (24 subsequent siblings)
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 | 76 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+)
create mode 100644 target/loongarch/README
diff --git a/MAINTAINERS b/MAINTAINERS
index d3879aa..935bbce 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 0000000..09f809c
--- /dev/null
+++ b/target/loongarch/README
@@ -0,0 +1,76 @@
+- 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-20210831-cross-tools.tar.xz
+
+ tar -vxf loongarch64-clfs-20210831-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-08-31.tar.bz2
+
+ tar -vxf loongarch64-clfs-system-2021-08-31.tar.bz2 -C /opt/clfs
+
+ 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/
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 02/26] target/loongarch: Add core definition
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
2021-11-19 6:13 ` [PATCH v11 01/26] target/loongarch: Add README Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-19 6:13 ` [PATCH v11 03/26] target/loongarch: Add main translation routines Song Gao
` (23 subsequent siblings)
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
target/loongarch/cpu-param.h | 18 +++
target/loongarch/cpu.c | 314 +++++++++++++++++++++++++++++++++++++++++++
target/loongarch/cpu.h | 253 ++++++++++++++++++++++++++++++++++
target/loongarch/internals.h | 21 +++
4 files changed, 606 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 0000000..9a769b6
--- /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 0000000..b3f4444
--- /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[] = {
+ "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[] = {
+ "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_ADE] = "Address error",
+ [EXCP_SYSCALL] = "Syscall",
+ [EXCP_BREAK] = "Break",
+ [EXCP_INE] = "Instruction Non-existent",
+ [EXCP_FPE] = "Floating Point Exception",
+};
+
+const char *loongarch_exception_name(int32_t 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] = 0x5f5e100; /* 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 = 0x1f1f031f;
+ 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 0000000..7509c77
--- /dev/null
+++ b/target/loongarch/cpu.h
@@ -0,0 +1,253 @@
+/* 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[];
+extern const char * const fregnames[];
+
+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_ADE = 0,
+ EXCP_SYSCALL,
+ 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 0000000..1e69e7d
--- /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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 03/26] target/loongarch: Add main translation routines
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
2021-11-19 6:13 ` [PATCH v11 01/26] target/loongarch: Add README Song Gao
2021-11-19 6:13 ` [PATCH v11 02/26] target/loongarch: Add core definition Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-19 6:13 ` [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
` (22 subsequent siblings)
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 0000000..eb771c0
--- /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 0000000..9038109
--- /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 0000000..048c895
--- /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 0000000..6cc7f1a
--- /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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (2 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 03/26] target/loongarch: Add main translation routines Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 7:10 ` Richard Henderson
2021-11-20 7:17 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 05/26] target/loongarch: Add fixed point shift " Song Gao
` (21 subsequent siblings)
25 siblings, 2 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 | 309 ++++++++++++++++++++++++++
target/loongarch/insns.decode | 79 +++++++
target/loongarch/translate.c | 83 +++++++
target/loongarch/translate.h | 19 ++
4 files changed, 490 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 0000000..ae1e113
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_arith.c.inc
@@ -0,0 +1,309 @@
+/* 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);
+
+ /* dst_ext is EXT_NONE and input is dest, We don't run gen_set_gpr. */
+ if (dst_ext) {
+ gen_set_gpr(a->rd, dest, dst_ext);
+ }
+ return true;
+}
+
+static bool gen_rr_i(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);
+
+ if (dst_ext) {
+ 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, 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);
+ TCGv temp = tcg_temp_new();
+
+ func(dest, src1, src2, temp, a->sa);
+
+ if (dst_ext) {
+ gen_set_gpr(a->rd, dest, dst_ext);
+ }
+ tcg_temp_free(temp);
+ 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);
+ 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);
+ 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_wu(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_w(TCGv dest, TCGv src1, TCGv src2,
+ TCGv temp, target_long sa)
+{
+ tcg_gen_shli_tl(temp, src1, sa);
+ tcg_gen_add_tl(dest, temp, src2);
+}
+
+static void gen_alsl_wu(TCGv dest, TCGv src1, TCGv src2,
+ TCGv temp, target_long sa)
+{
+ tcg_gen_shli_tl(temp, src1, sa);
+ tcg_gen_add_tl(dest, temp, src2);
+}
+
+static void gen_alsl_d(TCGv dest, TCGv src1, TCGv src2,
+ TCGv temp, target_long sa)
+{
+ tcg_gen_shli_tl(temp, src1, sa);
+ tcg_gen_add_tl(dest, temp, src2);
+}
+
+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);
+ 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);
+ 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);
+ 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_wu)
+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_rr_i, EXT_NONE, EXT_NONE, gen_slt)
+TRANS(sltui, gen_rr_i, EXT_NONE, EXT_NONE, gen_sltu)
+TRANS(addi_w, gen_rr_i, EXT_NONE, EXT_SIGN, tcg_gen_add_tl)
+TRANS(addi_d, gen_rr_i, EXT_NONE, EXT_NONE, tcg_gen_add_tl)
+TRANS(alsl_w, gen_rrr_sa, EXT_NONE, EXT_SIGN, gen_alsl_w)
+TRANS(alsl_wu, gen_rrr_sa, EXT_NONE, EXT_ZERO, gen_alsl_wu)
+TRANS(alsl_d, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_alsl_d)
+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_rr_i, EXT_NONE, EXT_NONE, tcg_gen_and_tl)
+TRANS(ori, gen_rr_i, EXT_NONE, EXT_NONE, tcg_gen_or_tl)
+TRANS(xori, gen_rr_i, EXT_NONE, EXT_NONE, tcg_gen_xor_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
new file mode 100644
index 0000000..8579c11
--- /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 048c895..3de18ef 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 6cc7f1a..9cc1251 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);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 05/26] target/loongarch: Add fixed point shift instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (3 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 7:42 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 06/26] target/loongarch: Add fixed point bit " Song Gao
` (20 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 | 128 ++++++++++++++++++++++++++
target/loongarch/insns.decode | 22 +++++
target/loongarch/translate.c | 1 +
3 files changed, 151 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 0000000..ea2a612
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_shift.c.inc
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_shift(DisasContext *ctx, arg_rr_i *a,
+ void(*func)(TCGv, TCGv, TCGv))
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
+ TCGv src2 = tcg_constant_tl(a->imm);
+
+ func(dest, src1, src2);
+ gen_set_gpr(a->rd, dest, EXT_SIGN);
+
+ return true;
+}
+
+static bool gen_shift_i(DisasContext *ctx, arg_rr_i *a,
+ void(*func)(TCGv, TCGv, target_long))
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ func(dest, src1, a->imm);
+
+ return true;
+}
+
+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);
+ 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_shift, tcg_gen_shl_tl)
+TRANS(slli_d, gen_shift_i, tcg_gen_shli_tl)
+TRANS(srli_w, gen_shift, tcg_gen_shr_tl)
+TRANS(srli_d, gen_shift_i, tcg_gen_shri_tl)
+TRANS(srai_d, gen_shift_i, tcg_gen_sari_tl)
+TRANS(rotri_w, gen_shift, gen_rotr_w)
+TRANS(rotri_d, gen_shift_i, tcg_gen_rotri_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8579c11..673aee4 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 3de18ef..f90b63a 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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 06/26] target/loongarch: Add fixed point bit instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (4 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 05/26] target/loongarch: Add fixed point shift " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 8:05 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 07/26] target/loongarch: Add fixed point load/store " Song Gao
` (19 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 | 252 ++++++++++++++++++++++++++++
target/loongarch/insns.decode | 40 +++++
target/loongarch/op_helper.c | 22 +++
target/loongarch/translate.c | 1 +
5 files changed, 319 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 eb771c0..04e0245 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 0000000..5063773
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_bit.c.inc
@@ -0,0 +1,252 @@
+/* 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);
+
+ if (dst_ext) {
+ gen_set_gpr(a->rd, dest, dst_ext);
+ }
+ return true;
+}
+
+static bool trans_bytepick_w(DisasContext *ctx, arg_bytepick_w *a)
+{
+ 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);
+
+ tcg_gen_concat_tl_i64(dest, src1, src2);
+ tcg_gen_sextract_i64(dest, dest, (32 - (a->sa) * 8), 32);
+
+ return true;
+}
+
+static bool trans_bytepick_d(DisasContext *ctx, arg_bytepick_d *a)
+{
+ 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);
+
+ tcg_gen_extract2_i64(dest, src1, src2, (64 - (a->sa) * 8));
+ return true;
+}
+
+static bool trans_bstrins_w(DisasContext *ctx, arg_bstrins_w *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (a->lsbw > a->msbw) {
+ return false;
+ }
+
+ tcg_gen_deposit_tl(dest, dest, src1, a->lsbw, a->msbw - a->lsbw + 1);
+ tcg_gen_ext32s_tl(dest, dest);
+
+ return true;
+}
+
+static bool trans_bstrins_d(DisasContext *ctx, arg_bstrins_d *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (a->lsbd > a->msbd) {
+ return false;
+ }
+
+ tcg_gen_deposit_tl(dest, dest, src1, a->lsbd, a->msbd - a->lsbd + 1);
+ return true;
+}
+
+static bool trans_bstrpick_w(DisasContext *ctx, arg_bstrpick_w *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (a->lsbw > a->msbw) {
+ return false;
+ }
+
+ tcg_gen_extract_tl(dest, src1, a->lsbw, a->msbw - a->lsbw + 1);
+ tcg_gen_ext32s_tl(dest, dest);
+ return true;
+}
+
+static bool trans_bstrpick_d(DisasContext *ctx, arg_bstrpick_d *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (a->lsbd > a->msbd) {
+ return false;
+ }
+
+ tcg_gen_extract_tl(dest, src1, a->lsbd, a->msbd - a->lsbd + 1);
+ 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, 32);
+}
+
+static void gen_cto_w(TCGv dest, TCGv src1)
+{
+ tcg_gen_not_tl(dest, src1);
+ tcg_gen_ext32u_tl(dest, dest);
+ 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)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 673aee4..4533706 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -14,13 +14,17 @@
# 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_2bw rd rj msbw lsbw
+&rr_2bd rd rj msbd lsbd
#
# 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 +33,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 .... ....... msbw:5 . lsbw:5 rj:5 rd:5 &rr_2bw
+@rr_2bd .... ...... msbd:6 lsbd:6 rj:5 rd:5 &rr_2bd
#
# Fixed point arithmetic operation instruction
@@ -99,3 +107,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 9038109..1fc9d81 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -19,3 +19,25 @@ 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 f90b63a..c0875db 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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 07/26] target/loongarch: Add fixed point load/store instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (5 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 06/26] target/loongarch: Add fixed point bit " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 8:20 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 08/26] target/loongarch: Add fixed point atomic " Song Gao
` (18 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 +
target/loongarch/insn_trans/trans_memory.c.inc | 232 +++++++++++++++++++++++++
target/loongarch/insns.decode | 54 ++++++
target/loongarch/op_helper.c | 15 ++
target/loongarch/translate.c | 30 ++++
5 files changed, 334 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 04e0245..2fe4e63 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_3(asrtle_d, void, env, tl, tl)
+DEF_HELPER_3(asrtgt_d, 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 0000000..1dd7deb
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_memory.c.inc
@@ -0,0 +1,232 @@
+/* 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);
+
+ 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);
+
+ 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);
+ 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(dest, addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ 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);
+ 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(dest, addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ 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);
+ 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(data, addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ 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);
+ 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(data, addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool trans_preld(DisasContext *ctx, arg_preld *a)
+{
+ return true;
+}
+
+static bool trans_dbar(DisasContext *ctx, arg_dbar * a)
+{
+ gen_loongarch_sync(a->imm);
+ 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 << 2);
+ addr = temp;
+ }
+
+ tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+
+ 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->imm << 2);
+ 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 4533706..3f4ac76 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -13,10 +13,12 @@
#
# 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_2bw rd rj msbw lsbw
&rr_2bd rd rj msbd lsbd
@@ -24,6 +26,7 @@
#
# 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
@@ -31,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_i14 .... .... imm:s14 rj:5 rd:5 &rr_i
@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
@@ -139,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_i14
+stptr_w 0010 0101 .............. ..... ..... @rr_i14
+ldptr_d 0010 0110 .............. ..... ..... @rr_i14
+stptr_d 0010 0111 .............. ..... ..... @rr_i14
+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 1fc9d81..53ee9ff 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -41,3 +41,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 c0875db..9ff83cf 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -69,6 +69,35 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
ctx->zero = tcg_constant_tl(0);
}
+/* loongarch sync */
+static void gen_loongarch_sync(int stype)
+{
+ TCGBar tcg_mo = TCG_BAR_SC;
+
+ switch (stype) {
+ case 0x4: /* SYNC_WMB */
+ tcg_mo |= TCG_MO_ST_ST;
+ break;
+ case 0x10: /* SYNC_MB */
+ tcg_mo |= TCG_MO_ALL;
+ break;
+ case 0x11: /* SYNC_ACQUIRE */
+ tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
+ break;
+ case 0x12: /* SYNC_RELEASE */
+ tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
+ break;
+ case 0x13: /* SYNC_RMB */
+ tcg_mo |= TCG_MO_LD_LD;
+ break;
+ default:
+ tcg_mo |= TCG_MO_ALL;
+ break;
+ }
+
+ tcg_gen_mb(tcg_mo);
+}
+
static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
{
}
@@ -148,6 +177,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 08/26] target/loongarch: Add fixed point atomic instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (6 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 07/26] target/loongarch: Add fixed point load/store " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 8:30 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 09/26] target/loongarch: Add fixed point extra " Song Gao
` (17 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
target/loongarch/insn_trans/trans_atomic.c.inc | 130 +++++++++++++++++++++++++
target/loongarch/insns.decode | 44 +++++++++
target/loongarch/translate.c | 1 +
3 files changed, 175 insertions(+)
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 0000000..96957bb
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_atomic.c.inc
@@ -0,0 +1,130 @@
+/* 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 << 2);
+ 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));
+ 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 << 2);
+ 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);
+ 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);
+ return true;
+}
+
+static bool gen_am_db(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;
+ }
+
+ gen_loongarch_sync(0x10);
+ func(dest, addr, val, ctx->mem_idx, mop);
+
+ 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_db, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_db_d, gen_am_db, tcg_gen_atomic_xchg_tl, MO_TEQ)
+TRANS(amadd_db_w, gen_am_db, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_db_d, gen_am_db, tcg_gen_atomic_fetch_add_tl, MO_TEQ)
+TRANS(amand_db_w, gen_am_db, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_db_d, gen_am_db, tcg_gen_atomic_fetch_and_tl, MO_TEQ)
+TRANS(amor_db_w, gen_am_db, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_db_d, gen_am_db, tcg_gen_atomic_fetch_or_tl, MO_TEQ)
+TRANS(amxor_db_w, gen_am_db, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
+TRANS(amxor_db_d, gen_am_db, tcg_gen_atomic_fetch_xor_tl, MO_TEQ)
+TRANS(ammax_db_w, gen_am_db, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
+TRANS(ammax_db_d, gen_am_db, tcg_gen_atomic_fetch_smax_tl, MO_TEQ)
+TRANS(ammin_db_w, gen_am_db, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
+TRANS(ammin_db_d, gen_am_db, tcg_gen_atomic_fetch_smin_tl, MO_TEQ)
+TRANS(ammax_db_wu, gen_am_db, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
+TRANS(ammax_db_du, gen_am_db, tcg_gen_atomic_fetch_umax_tl, MO_TEQ)
+TRANS(ammin_db_wu, gen_am_db, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
+TRANS(ammin_db_du, gen_am_db, tcg_gen_atomic_fetch_umin_tl, MO_TEQ)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 3f4ac76..c222c4a 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_i14
+sc_w 0010 0001 .............. ..... ..... @rr_i14
+ll_d 0010 0010 .............. ..... ..... @rr_i14
+sc_d 0010 0011 .............. ..... ..... @rr_i14
+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 9ff83cf..1be899f 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -178,6 +178,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 09/26] target/loongarch: Add fixed point extra instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (7 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 08/26] target/loongarch: Add fixed point atomic " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 8:52 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 10/26] target/loongarch: Add floating point arithmetic " Song Gao
` (16 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 ++
| 84 +++++++++++++++++++++++++++
target/loongarch/insns.decode | 22 +++++++
target/loongarch/op_helper.c | 26 +++++++++
target/loongarch/translate.c | 1 +
5 files changed, 137 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_extra.c.inc
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 2fe4e63..ec6760d 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_3(asrtle_d, void, env, tl, tl)
DEF_HELPER_3(asrtgt_d, void, env, tl, tl)
+
+DEF_HELPER_3(crc32, tl, tl, tl, tl)
+DEF_HELPER_3(crc32c, tl, tl, tl, tl)
+DEF_HELPER_2(cpucfg, tl, env, tl)
--git a/target/loongarch/insn_trans/trans_extra.c.inc b/target/loongarch/insn_trans/trans_extra.c.inc
new file mode 100644
index 0000000..8c2d482
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_extra.c.inc
@@ -0,0 +1,84 @@
+/* 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);
+ 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 c222c4a..8dca6f2 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -16,6 +16,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 53ee9ff..fdd4303 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)
@@ -56,3 +58,27 @@ void helper_asrtgt_d(CPULoongArchState *env, target_ulong rj, target_ulong rk)
do_raise_exception(env, EXCP_ADE, 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 env->cpucfg[rj];
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 1be899f..ca3ee23 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -179,6 +179,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 10/26] target/loongarch: Add floating point arithmetic instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (8 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 09/26] target/loongarch: Add fixed point extra " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 8:54 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 11/26] target/loongarch: Add floating point comparison " Song Gao
` (15 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 | 405 +++++++++++++++++++++++++
target/loongarch/helper.h | 37 +++
target/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, 613 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 b3f4444..ad11b98 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 = 0x1f1f031f;
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 0000000..d0ef675
--- /dev/null
+++ b/target/loongarch/fpu_helper.c
@@ -0,0 +1,405 @@
+/* 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);
+
+ if (~mask) {
+ flags = flags & (~mask);
+ }
+
+ if (!flags) {
+ SET_FP_CAUSE(env->fcsr0, flags);
+ return;
+ }
+
+ 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 ec6760d..d6bb412 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -15,3 +15,40 @@ DEF_HELPER_3(asrtgt_d, void, env, tl, tl)
DEF_HELPER_3(crc32, tl, tl, tl, tl)
DEF_HELPER_3(crc32c, tl, tl, tl, tl)
DEF_HELPER_2(cpucfg, tl, env, tl)
+
+/* Floating-point helper */
+DEF_HELPER_3(fadd_s, i64, env, i64, i64)
+DEF_HELPER_3(fadd_d, i64, env, i64, i64)
+DEF_HELPER_3(fsub_s, i64, env, i64, i64)
+DEF_HELPER_3(fsub_d, i64, env, i64, i64)
+DEF_HELPER_3(fmul_s, i64, env, i64, i64)
+DEF_HELPER_3(fmul_d, i64, env, i64, i64)
+DEF_HELPER_3(fdiv_s, i64, env, i64, i64)
+DEF_HELPER_3(fdiv_d, i64, env, i64, i64)
+DEF_HELPER_3(fmax_s, i64, env, i64, i64)
+DEF_HELPER_3(fmax_d, i64, env, i64, i64)
+DEF_HELPER_3(fmin_s, i64, env, i64, i64)
+DEF_HELPER_3(fmin_d, i64, env, i64, i64)
+DEF_HELPER_3(fmaxa_s, i64, env, i64, i64)
+DEF_HELPER_3(fmaxa_d, i64, env, i64, i64)
+DEF_HELPER_3(fmina_s, i64, env, i64, i64)
+DEF_HELPER_3(fmina_d, i64, env, i64, i64)
+
+DEF_HELPER_5(fmuladd_s, i64, env, i64, i64, i64, i32)
+DEF_HELPER_5(fmuladd_d, i64, env, i64, i64, i64, i32)
+
+DEF_HELPER_3(fscaleb_s, i64, env, i64, i64)
+DEF_HELPER_3(fscaleb_d, i64, env, i64, i64)
+
+DEF_HELPER_2(flogb_s, i64, env, i64)
+DEF_HELPER_2(flogb_d, i64, env, i64)
+
+DEF_HELPER_2(fsqrt_s, i64, env, i64)
+DEF_HELPER_2(fsqrt_d, i64, env, i64)
+DEF_HELPER_2(frsqrt_s, i64, env, i64)
+DEF_HELPER_2(frsqrt_d, i64, env, i64)
+DEF_HELPER_2(frecip_s, i64, env, i64)
+DEF_HELPER_2(frecip_d, 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 0000000..a2bdf33
--- /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_fff *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_fff *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_ff *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_ff *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_ff *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_ff *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 8dca6f2..28a2f5e 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -23,6 +23,9 @@
&rrr_sa rd rj rk sa
&rr_2bw rd rj msbw lsbw
&rr_2bd rd rj msbd lsbd
+&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 .... ....... msbw:5 . lsbw:5 rj:5 rd:5 &rr_2bw
@rr_2bd .... ...... msbd:6 lsbd:6 rj:5 rd:5 &rr_2bd
+@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 1e69e7d..17219d4 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 ca3ee23..b7ace9e 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"
@@ -31,6 +32,15 @@ static inline int plus_1(DisasContext *ctx, int x)
return x + 1;
}
+/*
+ * 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);
@@ -180,6 +190,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 11/26] target/loongarch: Add floating point comparison instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (9 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 10/26] target/loongarch: Add floating point arithmetic " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 9:02 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 12/26] target/loongarch: Add floating point conversion " Song Gao
` (14 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 d0ef675..807ffd0 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -403,3 +403,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 d6bb412..30b270a 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -52,3 +52,12 @@ DEF_HELPER_2(frecip_d, 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 0000000..ce39c07
--- /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 & 0x7]));
+ 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 & 0x7]));
+
+ tcg_temp_free(var);
+ return true;
+}
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 28a2f5e..17e1df8 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 17219d4..e9e6374 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 0x0001 /* fp0 < fp1 */
+#define FCMP_EQ 0x0010 /* fp0 = fp1 */
+#define FCMP_UN 0x0100 /* unordered */
+#define FCMP_GT 0x1000 /* 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 b7ace9e..fd43e1b 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -191,6 +191,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 12/26] target/loongarch: Add floating point conversion instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (10 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 11/26] target/loongarch: Add floating point comparison " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-19 6:13 ` [PATCH v11 13/26] target/loongarch: Add floating point move " Song Gao
` (13 subsequent siblings)
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 807ffd0..4799b47 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -463,3 +463,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 30b270a..51bbf25 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 0000000..c1c6918
--- /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 17e1df8..a7e0a7e 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 fd43e1b..8da4e12 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -192,6 +192,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 13/26] target/loongarch: Add floating point move instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (11 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 12/26] target/loongarch: Add floating point conversion " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-19 6:13 ` [PATCH v11 14/26] target/loongarch: Add floating point load/store " Song Gao
` (12 subsequent siblings)
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 | 150 +++++++++++++++++++++++++++
target/loongarch/insns.decode | 37 +++++++
target/loongarch/translate.c | 1 +
5 files changed, 196 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 4799b47..babaa16 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -856,3 +856,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 51bbf25..26ca6d2 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 0000000..8acf49e
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmov.c.inc
@@ -0,0 +1,150 @@
+/* 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]);
+ 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);
+ 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 a7e0a7e..86f7284 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 8da4e12..f3e590c 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -193,6 +193,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 14/26] target/loongarch: Add floating point load/store instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (12 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 13/26] target/loongarch: Add floating point move " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 9:36 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 15/26] target/loongarch: Add branch " Song Gao
` (11 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
target/loongarch/insn_trans/trans_fmemory.c.inc | 184 ++++++++++++++++++++++++
target/loongarch/insns.decode | 24 ++++
target/loongarch/translate.c | 1 +
3 files changed, 209 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 0000000..a9c66b2
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmemory.c.inc
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_fload_imm(DisasContext *ctx, arg_fr_i *a,
+ MemOp mop, bool nanbox)
+{
+ 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);
+
+ if (nanbox) {
+ gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+ }
+
+ if (temp) {
+ tcg_temp_free(temp);
+ }
+ return true;
+}
+
+static bool gen_fstore_imm(DisasContext *ctx, arg_fr_i *a,
+ MemOp mop, bool nanbox)
+{
+ 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;
+ }
+
+ if (nanbox) {
+ gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+ }
+
+ 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_fload_tl(DisasContext *ctx, arg_frr *a,
+ MemOp mop, bool nanbox)
+{
+ 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);
+
+ if (nanbox) {
+ gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+ }
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_fstore_tl(DisasContext *ctx, arg_frr *a,
+ MemOp mop, bool nanbox)
+{
+ 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);
+
+ if (nanbox) {
+ gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+ }
+
+ 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, bool nanbox)
+{
+ 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);
+
+ if (nanbox) {
+ gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+ }
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a,
+ MemOp mop, bool nanbox)
+{
+ 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);
+
+ if (nanbox) {
+ gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+ }
+
+ 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, bool nanbox)
+{
+ 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);
+
+ if (nanbox) {
+ gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+ }
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_fstore_le(DisasContext *ctx, arg_frr *a,
+ MemOp mop, bool nanbox)
+{
+ 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);
+
+ if (nanbox) {
+ gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+ }
+
+ 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_imm, MO_TESL, true)
+TRANS(fst_s, gen_fstore_imm, MO_TEUL, true)
+TRANS(fld_d, gen_fload_imm, MO_TEQ, false)
+TRANS(fst_d, gen_fstore_imm, MO_TEQ, false)
+TRANS(fldx_s, gen_fload_tl, MO_TESL, true)
+TRANS(fldx_d, gen_fload_tl, MO_TEQ, false)
+TRANS(fstx_s, gen_fstore_tl, MO_TEUL, true)
+TRANS(fstx_d, gen_fstore_tl, MO_TEQ, false)
+TRANS(fldgt_s, gen_fload_gt, MO_TESL, true)
+TRANS(fldgt_d, gen_fload_gt, MO_TEQ, false)
+TRANS(fldle_s, gen_fload_le, MO_TESL, true)
+TRANS(fldle_d, gen_fload_le, MO_TEQ, false)
+TRANS(fstgt_s, gen_fstore_gt, MO_TEUL, true)
+TRANS(fstgt_d, gen_fstore_gt, MO_TEQ, false)
+TRANS(fstle_s, gen_fstore_le, MO_TEUL, true)
+TRANS(fstle_d, gen_fstore_le, MO_TEQ, false)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 86f7284..2560c24 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 f3e590c..5be5e26 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -194,6 +194,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 15/26] target/loongarch: Add branch instruction translation
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (13 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 14/26] target/loongarch: Add floating point load/store " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 9:46 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 16/26] target/loongarch: Add disassembler Song Gao
` (10 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
target/loongarch/insn_trans/trans_branch.c.inc | 82 ++++++++++++++++++++++++++
target/loongarch/insns.decode | 30 ++++++++++
target/loongarch/translate.c | 6 ++
3 files changed, 118 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 0000000..73fd048
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_branch.c.inc
@@ -0,0 +1,82 @@
+/* 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);
+ 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 & 0x7]));
+ 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 2560c24..5118a1e 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -9,6 +9,9 @@
# Fields
#
%sa2p1 15:2 !function=plus_1
+%offs21 0:s5 10:16 !function=times_4
+%offs16 10:s16 !function=times_4
+%offs26 0:s10 10:16 !function=times_4
#
# Argument sets
@@ -38,6 +41,11 @@
&rc rd cj
&frr fd rj rk
&fr_i fd rj imm
+&r_offs rj offs
+&c_offs cj offs
+&rr_dj_offs rd rj offs
+&offs offs
+&rr_offs rj rd offs
#
# Formats
@@ -74,6 +82,11 @@
@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
+@rr_dj_offs16 .... .. ................ rj:5 rd:5 &rr_dj_offs offs=%offs16
+@offs26 .... .. .......................... &offs offs=%offs26
+@rr_offs16 .... .. ................ rj:5 rd:5 &rr_offs offs=%offs16
#
# Fixed point arithmetic operation instruction
@@ -412,3 +425,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_dj_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 5be5e26..9a491d2 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -32,6 +32,11 @@ static inline int plus_1(DisasContext *ctx, int x)
return x + 1;
}
+static inline int times_4(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.
@@ -195,6 +200,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)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 16/26] target/loongarch: Add disassembler
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (14 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 15/26] target/loongarch: Add branch " Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 9:53 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 17/26] linux-user: Add LoongArch generic header files Song Gao
` (9 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
include/disas/dis-asm.h | 2 +
meson.build | 1 +
target/loongarch/disas.c | 625 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 628 insertions(+)
create mode 100644 target/loongarch/disas.c
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1bee..aeab30f 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 e2d38a4..d03fec6 100644
--- a/meson.build
+++ b/meson.build
@@ -1807,6 +1807,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 0000000..4748d0d
--- /dev/null
+++ b/target/loongarch/disas.c
@@ -0,0 +1,625 @@
+/* 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 times_4(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_2bw(DisasContext *ctx, arg_rr_2bw *a,
+ const char *mnemonic)
+{
+ output(ctx, mnemonic, "r%d, r%d, %d, %d", a->rd, a->rj, a->msbw, a->lsbw);
+}
+
+static void output_rr_2bd(DisasContext *ctx, arg_rr_2bd *a,
+ const char *mnemonic)
+{
+ output(ctx, mnemonic, "r%d, r%d, %d, %d", a->rd, a->rj, a->msbd, a->lsbd);
+}
+
+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%lx", 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%lx", a->cj, a->offs,
+ ctx->pc + a->offs);
+}
+
+static void output_rr_dj_offs(DisasContext *ctx, arg_rr_dj_offs *a,
+ const char *mnemonic)
+{
+ output(ctx, mnemonic, "r%d, r%d, %d # 0x%lx", a->rd, a->rj,
+ a->offs, ctx->pc + a->offs);
+}
+
+static void output_offs(DisasContext *ctx, arg_offs *a,
+ const char *mnemonic)
+{
+ output(ctx, mnemonic, "%d # 0x%lx", 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_2bw)
+INSN(bstrpick_w, rr_2bw)
+INSN(bstrins_d, rr_2bd)
+INSN(bstrpick_d, rr_2bd)
+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_dj_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)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 17/26] linux-user: Add LoongArch generic header files
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (15 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 16/26] target/loongarch: Add disassembler Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 9:54 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 18/26] linux-user: Add LoongArch specific structures Song Gao
` (8 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
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 0000000..1cffcae
--- /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 0000000..c198b8a
--- /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 0000000..99bf586
--- /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 0000000..d425db8
--- /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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 18/26] linux-user: Add LoongArch specific structures
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (16 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 17/26] linux-user: Add LoongArch generic header files Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 10:06 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 19/26] linux-user: Add LoongArch signal support Song Gao
` (7 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
---
linux-user/loongarch64/target_structs.h | 48 +++++++++++++++++++++++++++++++++
1 file changed, 48 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 0000000..cc7928a
--- /dev/null
+++ b/linux-user/loongarch64/target_structs.h
@@ -0,0 +1,48 @@
+/* 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_uint mode; /* Read/write permission. */
+ abi_ushort __seq; /* Sequence number. */
+ abi_ushort __pad1;
+ 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() */
+ abi_ulong shm_dtime; /* time of last shmdt() */
+ abi_ulong shm_ctime; /* time of last change by shmctl() */
+ 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 __unused1;
+ abi_ulong __unused2;
+};
+
+#define TARGET_SEMID64_DS
+
+struct target_semid64_ds {
+ struct target_ipc_perm sem_perm;
+ abi_ulong sem_otime;
+ abi_ulong sem_ctime;
+ abi_ulong sem_nsems;
+ abi_ulong __unused1;
+ abi_ulong __unused2;
+};
+
+#endif
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (17 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 18/26] linux-user: Add LoongArch specific structures Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 10:33 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 20/26] linux-user: Add LoongArch elf support Song Gao
` (6 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
---
linux-user/loongarch64/signal.c | 162 +++++++++++++++++++++++++++++++++
linux-user/loongarch64/target_signal.h | 29 ++++++
2 files changed, 191 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 0000000..8fbc827
--- /dev/null
+++ b/linux-user/loongarch64/signal.c
@@ -0,0 +1,162 @@
+/* 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"
+
+struct target_sigcontext {
+ uint64_t sc_pc;
+ uint64_t sc_gpr[32];
+ uint64_t sc_fpr[32];
+ uint64_t sc_fcc;
+ uint32_t sc_fcsr;
+ uint32_t sc_flags;
+};
+
+struct target_ucontext {
+ target_ulong tuc_flags;
+ target_ulong tuc_link;
+ target_stack_t tuc_stack;
+ target_ulong pad0;
+ struct target_sigcontext tuc_mcontext;
+ target_sigset_t tuc_sigmask;
+};
+
+struct target_rt_sigframe {
+ struct target_siginfo rs_info;
+ struct target_ucontext rs_uc;
+};
+
+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_gpr[0]);
+ for (i = 1; i < 32; ++i) {
+ __put_user(env->gpr[i], &sc->sc_gpr[i]);
+ }
+
+ for (i = 0; i < 32; ++i) {
+ __put_user(env->fpr[i], &sc->sc_fpr[i]);
+ }
+}
+
+static inline void
+restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc)
+{
+ int i;
+
+ __get_user(env->pc, &sc->sc_pc);
+
+ for (i = 1; i < 32; ++i) {
+ __get_user(env->gpr[i], &sc->sc_gpr[i]);
+ }
+
+ for (i = 0; i < 32; ++i) {
+ __get_user(env->fpr[i], &sc->sc_fpr[i]);
+ }
+}
+
+/*
+ * 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) & ~7;
+}
+
+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 = env->gpr[20] = 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 -TARGET_QEMU_ESIGRETURN;
+
+badframe:
+ unlock_user_struct(frame, frame_addr, 0);
+ force_sig(TARGET_SIGSEGV);
+ return -TARGET_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, a7, 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 0000000..c5f467b
--- /dev/null
+++ b/linux-user/loongarch64/target_signal.h
@@ -0,0 +1,29 @@
+/* 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
+
+/* this struct defines a stack used during syscall handling */
+typedef struct target_sigaltstack {
+ abi_long ss_sp;
+ abi_int ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+#include "../generic/signal.h"
+
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
+#endif /* LOONGARCH_TARGET_SIGNAL_H */
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 20/26] linux-user: Add LoongArch elf support
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (18 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 19/26] linux-user: Add LoongArch signal support Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 10:35 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 21/26] linux-user: Add LoongArch syscall support Song Gao
` (5 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
---
include/elf.h | 2 ++
linux-user/elfload.c | 58 +++++++++++++++++++++++++++++++++++++
linux-user/loongarch64/target_elf.h | 12 ++++++++
3 files changed, 72 insertions(+)
create mode 100644 linux-user/loongarch64/target_elf.h
diff --git a/include/elf.h b/include/elf.h
index 811bf4a..3a4bcb6 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 {
#define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */
+#define EM_LOONGARCH 258 /* LoongArch */
+
/*
* This is an interim value that we will use until the committee comes
* up with a final number.
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5da8c02..7827e25 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -914,6 +914,64 @@ 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];
+
+/* See linux kernel: arch/loongarch/include/asm/reg.h. */
+enum {
+ TARGET_EF_R0 = 0,
+ TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32,
+ TARGET_EF_CSR_BADVADDR = TARGET_EF_R0 + 33,
+};
+
+/* See linux kernel: arch/loongarch/kernel/process.c:loongarch_dump_regs64. */
+static void elf_core_copy_regs(target_elf_gregset_t *regs,
+ const CPULoongArchState *env)
+{
+ int i;
+
+ for (i = 0; i < TARGET_EF_R0; i++) {
+ (*regs)[i] = 0;
+ }
+ (*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_BADVADDR] = 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 0000000..3c690bb
--- /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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 21/26] linux-user: Add LoongArch syscall support
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (19 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 20/26] linux-user: Add LoongArch elf support Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 10:47 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 22/26] linux-user: Add LoongArch cpu_loop support Song Gao
` (4 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
linux-user/loongarch64/syscall_nr.h | 312 ++++++++++++++++++++++++++++++++
linux-user/loongarch64/target_syscall.h | 45 +++++
linux-user/syscall_defs.h | 10 +-
scripts/gensyscalls.sh | 1 +
4 files changed, 364 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 0000000..8fbf287
--- /dev/null
+++ b/linux-user/loongarch64/syscall_nr.h
@@ -0,0 +1,312 @@
+/*
+ * 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_syscalls 449
+
+#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 0000000..b1d2a39
--- /dev/null
+++ b/linux-user/loongarch64/target_syscall.h
@@ -0,0 +1,45 @@
+/* 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
+
+/*
+ * 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. */
+ target_ulong csr_crmd;
+ target_ulong csr_prmd;
+ target_ulong csr_euen;
+ target_ulong csr_ecfg;
+ target_ulong csr_estat;
+ target_ulong csr_era;
+ target_ulong csr_badvaddr;
+ target_ulong orig_a0;
+ target_ulong __last[0];
+};
+
+#define UNAME_MACHINE "loongarch64"
+#define UNAME_MINIMUM_RELEASE "5.16.0"
+
+#define TARGET_MINSIGSTKSZ 2048
+#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 0x40000;
+}
+
+#endif
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index a5ce487..bec125f 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
@@ -2129,7 +2129,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 */
@@ -2157,7 +2158,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;
@@ -2327,7 +2328,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 8fb450e..b69e193 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"
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 22/26] linux-user: Add LoongArch cpu_loop support
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (20 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 21/26] linux-user: Add LoongArch syscall support Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-20 10:53 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 23/26] default-configs: Add loongarch linux-user support Song Gao
` (3 subsequent siblings)
25 siblings, 1 reply; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
---
configure | 5 ++
linux-user/loongarch64/cpu_loop.c | 97 +++++++++++++++++++++++++++++++++++++
linux-user/loongarch64/target_cpu.h | 34 +++++++++++++
3 files changed, 136 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 48c2177..9df99f6 100755
--- a/configure
+++ b/configure
@@ -581,6 +581,8 @@ elif check_define __arm__ ; then
cpu="arm"
elif check_define __aarch64__ ; then
cpu="aarch64"
+elif check_define __loongarch64__ ; then
+ cpu="loongarch64"
else
cpu=$(uname -m)
fi
@@ -612,6 +614,9 @@ case "$cpu" in
sparc|sun4[cdmuv])
cpu="sparc"
;;
+ loongarch)
+ cpu="loongarch"
+ ;;
*)
# This will result in either an error or falling back to TCI later
ARCH=unknown
diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c
new file mode 100644
index 0000000..f211304
--- /dev/null
+++ b/linux-user/loongarch64/cpu_loop.c
@@ -0,0 +1,97 @@
+/* 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 == -TARGET_ERESTARTSYS) {
+ env->pc -= 4;
+ break;
+ }
+ if (ret == -TARGET_QEMU_ESIGRETURN) {
+ /*
+ * Returning from a successful sigreturn syscall.
+ * Avoid clobbering register state.
+ */
+ break;
+ }
+ env->gpr[4] = ret;
+ break;
+ case EXCP_ADE:
+ force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->badaddr);
+ 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 0000000..a29af66
--- /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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 23/26] default-configs: Add loongarch linux-user support
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (21 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 22/26] linux-user: Add LoongArch cpu_loop support Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-19 6:13 ` [PATCH v11 24/26] target/loongarch: Add target build suport Song Gao
` (2 subsequent siblings)
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 0000000..5b0acfa
--- /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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 24/26] target/loongarch: Add target build suport
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (22 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 23/26] default-configs: Add loongarch linux-user support Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-19 6:13 ` [PATCH v11 25/26] target/loongarch: 'make check-tcg' support Song Gao
2021-11-19 6:13 ` [PATCH v11 26/26] scripts: add loongarch64 binfmt config Song Gao
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
meson.build | 2 +-
target/loongarch/meson.build | 19 +++++++++++++++++++
target/meson.build | 1 +
3 files changed, 21 insertions(+), 1 deletion(-)
create mode 100644 target/loongarch/meson.build
diff --git a/meson.build b/meson.build
index d03fec6..7ba3aeb 100644
--- a/meson.build
+++ b/meson.build
@@ -56,7 +56,7 @@ python = import('python').find_installation()
supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64',
- 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
+ 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64', 'loongarch64']
cpu = host_machine.cpu_family()
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
new file mode 100644
index 0000000..bcb076e
--- /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 2f69402..a53a604 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')
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 25/26] target/loongarch: 'make check-tcg' support
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (23 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 24/26] target/loongarch: Add target build suport Song Gao
@ 2021-11-19 6:13 ` Song Gao
2021-11-19 6:13 ` [PATCH v11 26/26] scripts: add loongarch64 binfmt config Song Gao
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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>
---
tests/tcg/configure.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index 9b76f58..49a05ec 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"}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* [PATCH v11 26/26] scripts: add loongarch64 binfmt config
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
` (24 preceding siblings ...)
2021-11-19 6:13 ` [PATCH v11 25/26] target/loongarch: 'make check-tcg' support Song Gao
@ 2021-11-19 6:13 ` Song Gao
25 siblings, 0 replies; 65+ messages in thread
From: Song Gao @ 2021-11-19 6:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Xiaojuan Yang, richard.henderson, laurent
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 7de996d..da6a937 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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 65+ messages in thread
* Re: [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation
2021-11-19 6:13 ` [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
@ 2021-11-20 7:10 ` Richard Henderson
2021-11-20 7:17 ` Richard Henderson
1 sibling, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 7:10 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +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_wu(TCGv dest, TCGv src1, TCGv src2)
> +{
> + tcg_gen_mul_i64(dest, src1, src2);
> + tcg_gen_sari_i64(dest, dest, 32);
> +}
These two are the same; you only need one of them. The difference between the two insns
is in the EXT_{SIGN,ZERO} parameter that precedes these callbacks.
> +static void gen_alsl_w(TCGv dest, TCGv src1, TCGv src2,
> + TCGv temp, target_long sa)
> +{
> + tcg_gen_shli_tl(temp, src1, sa);
> + tcg_gen_add_tl(dest, temp, src2);
> +}
> +
> +static void gen_alsl_wu(TCGv dest, TCGv src1, TCGv src2,
> + TCGv temp, target_long sa)
> +{
> + tcg_gen_shli_tl(temp, src1, sa);
> + tcg_gen_add_tl(dest, temp, src2);
> +}
> +
> +static void gen_alsl_d(TCGv dest, TCGv src1, TCGv src2,
> + TCGv temp, target_long sa)
> +{
> + tcg_gen_shli_tl(temp, src1, sa);
> + tcg_gen_add_tl(dest, temp, src2);
> +}
Likewise, these are identical.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation
2021-11-19 6:13 ` [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
2021-11-20 7:10 ` Richard Henderson
@ 2021-11-20 7:17 ` Richard Henderson
2021-11-20 8:52 ` gaosong
1 sibling, 1 reply; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 7:17 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +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);
> +
> + /* dst_ext is EXT_NONE and input is dest, We don't run gen_set_gpr. */
> + if (dst_ext) {
> + gen_set_gpr(a->rd, dest, dst_ext);
> + }
Why the (incomplete) condition around gen_set_gpr?
I think it's a bug to not name EXT_NONE in the test (just because EXT_NONE == 0 now...),
but I also think you should not have added the test at all. We will not generate any code
in the end within gen_set_gpr, but it allows the routines to be self-contained. You
shouldn't assume what gpr_dst returned.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 05/26] target/loongarch: Add fixed point shift instruction translation
2021-11-19 6:13 ` [PATCH v11 05/26] target/loongarch: Add fixed point shift " Song Gao
@ 2021-11-20 7:42 ` Richard Henderson
2021-11-20 9:03 ` gaosong
0 siblings, 1 reply; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 7:42 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +static bool gen_shift(DisasContext *ctx, arg_rr_i *a,
> + void(*func)(TCGv, TCGv, TCGv))
> +{
> + TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
> + TCGv src2 = tcg_constant_tl(a->imm);
> +
> + func(dest, src1, src2);
> + gen_set_gpr(a->rd, dest, EXT_SIGN);
> +
> + return true;
> +}
This is no longer generic; it's specific to word operations. But there's nothing in here
that can't be done with gen_rr_i, so I think you should remove it.
> +
> +static bool gen_shift_i(DisasContext *ctx, arg_rr_i *a,
> + void(*func)(TCGv, TCGv, target_long))
> +{
> + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> +
> + func(dest, src1, a->imm);
> +
> + return true;
> +}
This one has dropped gen_set_gpr.
I think that your current gen_rr_i should be named gen_rri_v (variable) and this one
should regain the DisasExtend and be named gen_rri_c (constant).
Then, in the previous,
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(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)
There are a few identity tests within these tcg_gen_opi_tl functions which would be nice
to apply. Particularly because the canonical "nop" instruction for loongarch is "andi
r0,r0,0".
> +TRANS(slli_w, gen_shift, tcg_gen_shl_tl)
> +TRANS(slli_d, gen_shift_i, tcg_gen_shli_tl)
> +TRANS(srli_w, gen_shift, tcg_gen_shr_tl)
> +TRANS(srli_d, gen_shift_i, tcg_gen_shri_tl)
> +TRANS(srai_d, gen_shift_i, tcg_gen_sari_tl)
> +TRANS(rotri_w, gen_shift, gen_rotr_w)
> +TRANS(rotri_d, gen_shift_i, tcg_gen_rotri_tl)
Then these become
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_SIGN, 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)
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 06/26] target/loongarch: Add fixed point bit instruction translation
2021-11-19 6:13 ` [PATCH v11 06/26] target/loongarch: Add fixed point bit " Song Gao
@ 2021-11-20 8:05 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 8:05 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +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);
> +
> + if (dst_ext) {
> + gen_set_gpr(a->rd, dest, dst_ext);
> + }
Again, I think you should call gen_set_gpr unconditionally.
> +static bool trans_bytepick_w(DisasContext *ctx, arg_bytepick_w *a)
> +{
> + 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);
> +
> + tcg_gen_concat_tl_i64(dest, src1, src2);
> + tcg_gen_sextract_i64(dest, dest, (32 - (a->sa) * 8), 32);
> +
> + return true;
> +}
Better to use gen_rrr_sa.
> +static bool trans_bytepick_d(DisasContext *ctx, arg_bytepick_d *a)
> +{
> + 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);
> +
> + tcg_gen_extract2_i64(dest, src1, src2, (64 - (a->sa) * 8));
> + return true;
> +}
Likewise.
> +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, 32);
This should be TARGET_LONG_BITS. It will never happen, because the value is not zero per
the OR, but it's what is most efficient for a tcg backend that naturally produces
TARGET_LONG_BITS for a TL-sized ctz.
> +}
> +
> +static void gen_cto_w(TCGv dest, TCGv src1)
> +{
> + tcg_gen_not_tl(dest, src1);
> + tcg_gen_ext32u_tl(dest, dest);
> + gen_ctz_w(dest, dest);
> +}
The EXT32U here is useless, as the OR within gen_ctz_w overrides it.
> +&rr_2bw rd rj msbw lsbw
> +&rr_2bd rd rj msbd lsbd
Merge these.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 07/26] target/loongarch: Add fixed point load/store instruction translation
2021-11-19 6:13 ` [PATCH v11 07/26] target/loongarch: Add fixed point load/store " Song Gao
@ 2021-11-20 8:20 ` Richard Henderson
2021-11-20 9:39 ` Richard Henderson
0 siblings, 1 reply; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 8:20 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
> +
> +DEF_HELPER_3(asrtle_d, void, env, tl, tl)
> +DEF_HELPER_3(asrtgt_d, void, env, tl, tl)
Use DEF_HELPER_FLAGS_3 and TCG_CALL_NO_WG.
(They do not write globals, but do implicitly read them via the exception path, and of
course the exception is a side-effect.)
> +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);
> + 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(dest, addr, ctx->mem_idx, mop);
This add is incorrect. The address is rj (src1).
Likewise for the rest of the bound check memory ops.
> +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 << 2);
> + addr = temp;
> + }
I think it would be cleaner to have this immediate shift handled by decodetree, so that
gen_ldptr is dropped in favor of gen_load (and also for stores). It would also print the
correct logical offset on the disassembly side.
%i14s2 10:s14 !function=shl_2
@rr_i14s2 .... .... .............. rj:5 rd:5 &rr_i imm=%i14s2
> +/* loongarch sync */
> +static void gen_loongarch_sync(int stype)
> +{
> + TCGBar tcg_mo = TCG_BAR_SC;
> +
> + switch (stype) {
> + case 0x4: /* SYNC_WMB */
> + tcg_mo |= TCG_MO_ST_ST;
> + break;
> + case 0x10: /* SYNC_MB */
> + tcg_mo |= TCG_MO_ALL;
> + break;
> + case 0x11: /* SYNC_ACQUIRE */
> + tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
> + break;
> + case 0x12: /* SYNC_RELEASE */
> + tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
> + break;
> + case 0x13: /* SYNC_RMB */
> + tcg_mo |= TCG_MO_LD_LD;
> + break;
> + default:
> + tcg_mo |= TCG_MO_ALL;
> + break;
> + }
> +
> + tcg_gen_mb(tcg_mo);
> +}
This is copied from mips, I think. The only defined hint for dbar is 0. I think this
function should be removed, and just emit the tcg barrier directly within trans_dbar.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 08/26] target/loongarch: Add fixed point atomic instruction translation
2021-11-19 6:13 ` [PATCH v11 08/26] target/loongarch: Add fixed point atomic " Song Gao
@ 2021-11-20 8:30 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 8:30 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> 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>
> ---
> target/loongarch/insn_trans/trans_atomic.c.inc | 130 +++++++++++++++++++++++++
> target/loongarch/insns.decode | 44 +++++++++
> target/loongarch/translate.c | 1 +
> 3 files changed, 175 insertions(+)
> 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 0000000..96957bb
> --- /dev/null
> +++ b/target/loongarch/insn_trans/trans_atomic.c.inc
> @@ -0,0 +1,130 @@
> +/* 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 << 2);
The ll/sc instructions would of course use the same pre-shifted immediate as for
ldptr/stptr, as discussed wrt the previous patch.
> +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))) {
BTW, you don't need to overdo it with the parenthesis.
if (a != b && (c == d || e == f)) {
is fine.
> +static bool gen_am_db(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;
> + }
> +
> + gen_loongarch_sync(0x10);
> + func(dest, addr, val, ctx->mem_idx, mop);
All tcg atomic ops are sequentially consistent, so you don't need the extra sync, and thus
this entire function.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 09/26] target/loongarch: Add fixed point extra instruction translation
2021-11-19 6:13 ` [PATCH v11 09/26] target/loongarch: Add fixed point extra " Song Gao
@ 2021-11-20 8:52 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 8:52 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +DEF_HELPER_3(crc32, tl, tl, tl, tl)
> +DEF_HELPER_3(crc32c, tl, tl, tl, tl)
> +DEF_HELPER_2(cpucfg, tl, env, tl)
DEF_HELPER_FLAGS_N, TCG_CALL_NO_RWG_SE.
> +target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj)
> +{
> + return env->cpucfg[rj];
> +}
The value of the source register should be bounded by ARRAY_SIZE(env->cpucfg);
out-of-bound indicies read 0.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation
2021-11-20 7:17 ` Richard Henderson
@ 2021-11-20 8:52 ` gaosong
2021-11-20 8:56 ` Richard Henderson
0 siblings, 1 reply; 65+ messages in thread
From: gaosong @ 2021-11-20 8:52 UTC (permalink / raw)
To: Richard Henderson; +Cc: Xiaojuan Yang, qemu-devel, laurent
[-- Attachment #1: Type: text/plain, Size: 1341 bytes --]
Hi Richard,
On 2021/11/20 下午3:17, Richard Henderson wrote:
> On 11/19/21 7:13 AM, Song Gao wrote:
>> +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);
>> +
>> + /* dst_ext is EXT_NONE and input is dest, We don't run
>> gen_set_gpr. */
>> + if (dst_ext) {
>> + gen_set_gpr(a->rd, dest, dst_ext);
>> + }
>
> Why the (incomplete) condition around gen_set_gpr?
>
> I think it's a bug to not name EXT_NONE in the test (just because
> EXT_NONE == 0 now...), but I also think you should not have added the
> test at all. We will not generate any code in the end within
> gen_set_gpr, but it allows the routines to be self-contained. You
> shouldn't assume what gpr_dst returned.
>
You're right, gen_set_gpr not need EXT_NONE at all, and we need not condition around gen_set_gpr.
I think that if we know the dst_ext is EXT_NONE, we do't need gen_set_gpr. I'll correct them on v12.
Thanks
Song Gao
>
> r~
[-- Attachment #2: Type: text/html, Size: 2205 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 10/26] target/loongarch: Add floating point arithmetic instruction translation
2021-11-19 6:13 ` [PATCH v11 10/26] target/loongarch: Add floating point arithmetic " Song Gao
@ 2021-11-20 8:54 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 8:54 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +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);
> +
> + if (~mask) {
> + flags = flags & (~mask);
> + }
No need for if -- mask will always be valid.
flags &= ~mask.
> + if (!flags) {
> + SET_FP_CAUSE(env->fcsr0, flags);
> + return;
> + }
> +
> + flags = ieee_ex_to_loongarch(flags);
> + SET_FP_CAUSE(env->fcsr0, flags);
It looks like this could be hoisted above the !flags check to unify the two statements.
> +/* Floating-point helper */
> +DEF_HELPER_3(fadd_s, i64, env, i64, i64)
> +DEF_HELPER_3(fadd_d, i64, env, i64, i64)
> +DEF_HELPER_3(fsub_s, i64, env, i64, i64)
> +DEF_HELPER_3(fsub_d, i64, env, i64, i64)
> +DEF_HELPER_3(fmul_s, i64, env, i64, i64)
> +DEF_HELPER_3(fmul_d, i64, env, i64, i64)
> +DEF_HELPER_3(fdiv_s, i64, env, i64, i64)
> +DEF_HELPER_3(fdiv_d, i64, env, i64, i64)
> +DEF_HELPER_3(fmax_s, i64, env, i64, i64)
> +DEF_HELPER_3(fmax_d, i64, env, i64, i64)
> +DEF_HELPER_3(fmin_s, i64, env, i64, i64)
> +DEF_HELPER_3(fmin_d, i64, env, i64, i64)
> +DEF_HELPER_3(fmaxa_s, i64, env, i64, i64)
> +DEF_HELPER_3(fmaxa_d, i64, env, i64, i64)
> +DEF_HELPER_3(fmina_s, i64, env, i64, i64)
> +DEF_HELPER_3(fmina_d, i64, env, i64, i64)
> +
> +DEF_HELPER_5(fmuladd_s, i64, env, i64, i64, i64, i32)
> +DEF_HELPER_5(fmuladd_d, i64, env, i64, i64, i64, i32)
> +
> +DEF_HELPER_3(fscaleb_s, i64, env, i64, i64)
> +DEF_HELPER_3(fscaleb_d, i64, env, i64, i64)
> +
> +DEF_HELPER_2(flogb_s, i64, env, i64)
> +DEF_HELPER_2(flogb_d, i64, env, i64)
> +
> +DEF_HELPER_2(fsqrt_s, i64, env, i64)
> +DEF_HELPER_2(fsqrt_d, i64, env, i64)
> +DEF_HELPER_2(frsqrt_s, i64, env, i64)
> +DEF_HELPER_2(frsqrt_d, i64, env, i64)
> +DEF_HELPER_2(frecip_s, i64, env, i64)
> +DEF_HELPER_2(frecip_d, i64, env, i64)
DEF_HELPER_FLAGS_N, TCG_CALL_NO_WG.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation
2021-11-20 8:52 ` gaosong
@ 2021-11-20 8:56 ` Richard Henderson
2021-11-22 8:23 ` gaosong
0 siblings, 1 reply; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 8:56 UTC (permalink / raw)
To: gaosong; +Cc: Xiaojuan Yang, qemu-devel, laurent
On 11/20/21 9:52 AM, gaosong wrote:
> You're right, gen_set_gpr not need EXT_NONE at all, and we need not condition around gen_set_gpr.
> I think that if we know the dst_ext is EXT_NONE, we do't need gen_set_gpr.
But that assumes that gpr_dst did not return a temporary.
I think it's cleaner to assume that gen_set_gpr is needed.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 11/26] target/loongarch: Add floating point comparison instruction translation
2021-11-19 6:13 ` [PATCH v11 11/26] target/loongarch: Add floating point comparison " Song Gao
@ 2021-11-20 9:02 ` Richard Henderson
2021-11-30 8:22 ` gaosong
0 siblings, 1 reply; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 9:02 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +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 & 0x7]));
No need to mask cd; the decode took care of that.
> +#define FCMP_LT 0x0001 /* fp0 < fp1 */
> +#define FCMP_EQ 0x0010 /* fp0 = fp1 */
> +#define FCMP_UN 0x0100 /* unordered */
> +#define FCMP_GT 0x1000 /* fp0 > fp1 */
Any reason why these bits are not sequential?
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 05/26] target/loongarch: Add fixed point shift instruction translation
2021-11-20 7:42 ` Richard Henderson
@ 2021-11-20 9:03 ` gaosong
0 siblings, 0 replies; 65+ messages in thread
From: gaosong @ 2021-11-20 9:03 UTC (permalink / raw)
To: Richard Henderson; +Cc: Xiaojuan Yang, qemu-devel, laurent
[-- Attachment #1: Type: text/plain, Size: 2673 bytes --]
Hi Richard,
On 2021/11/20 下午3:42, Richard Henderson wrote:
> On 11/19/21 7:13 AM, Song Gao wrote:
>> +static bool gen_shift(DisasContext *ctx, arg_rr_i *a,
>> + void(*func)(TCGv, TCGv, TCGv))
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN);
>> + TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
>> + TCGv src2 = tcg_constant_tl(a->imm);
>> +
>> + func(dest, src1, src2);
>> + gen_set_gpr(a->rd, dest, EXT_SIGN);
>> +
>> + return true;
>> +}
>
> This is no longer generic; it's specific to word operations. But
> there's nothing in here that can't be done with gen_rr_i, so I think
> you should remove it.
>
OK.
>> +
>> +static bool gen_shift_i(DisasContext *ctx, arg_rr_i *a,
>> + void(*func)(TCGv, TCGv, target_long))
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
>> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
>> +
>> + func(dest, src1, a->imm);
>> +
>> + return true;
>> +}
>
> This one has dropped gen_set_gpr.
>
We need't gen_set_gpr, the dst_ext is EXT_NONE.
> I think that your current gen_rr_i should be named gen_rri_v
> (variable) and this one should regain the DisasExtend and be named
> gen_rri_c (constant).
>
> Then, in the previous,
>
> 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(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)
>
> There are a few identity tests within these tcg_gen_opi_tl functions
> which would be nice to apply. Particularly because the canonical
> "nop" instruction for loongarch is "andi r0,r0,0".
>
>> +TRANS(slli_w, gen_shift, tcg_gen_shl_tl)
>> +TRANS(slli_d, gen_shift_i, tcg_gen_shli_tl)
>> +TRANS(srli_w, gen_shift, tcg_gen_shr_tl)
>> +TRANS(srli_d, gen_shift_i, tcg_gen_shri_tl)
>> +TRANS(srai_d, gen_shift_i, tcg_gen_sari_tl)
>> +TRANS(rotri_w, gen_shift, gen_rotr_w)
>> +TRANS(rotri_d, gen_shift_i, tcg_gen_rotri_tl)
>
> Then these become
>
> 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_SIGN, 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)
>
Very nice, very clean.
Thanks
Song Gao
> r~
[-- Attachment #2: Type: text/html, Size: 4502 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 14/26] target/loongarch: Add floating point load/store instruction translation
2021-11-19 6:13 ` [PATCH v11 14/26] target/loongarch: Add floating point load/store " Song Gao
@ 2021-11-20 9:36 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 9:36 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +static bool gen_fload_imm(DisasContext *ctx, arg_fr_i *a,
> + MemOp mop, bool nanbox)
Don't pass nanbox, as it can be determined from mop.
I think you should split out
static void maybe_nanbox_load(TCGv freg, MemOp mop)
{
if ((mop & MO_SIZE) == MO_32) {
gen_nanbox_s(freg, freg);
}
}
for use in the 4 different fload functions.
> +static bool gen_fstore_imm(DisasContext *ctx, arg_fr_i *a,
> + MemOp mop, bool nanbox)
Don't pass nanbox, because it's useless for stores.
> + if (nanbox) {
> + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
> + }
(1) nanboxing not needed for store,
(2) incorrect to modify fd.
> +static bool gen_fload_tl(DisasContext *ctx, arg_frr *a,
> + MemOp mop, bool nanbox)
Similarly.
Since the integer version is called gen_loadx, should this one be called gen_floadx?
> +static bool gen_fstore_tl(DisasContext *ctx, arg_frr *a,
> + MemOp mop, bool nanbox)
...
> +static bool gen_fload_gt(DisasContext *ctx, arg_frr *a,
> + MemOp mop, bool nanbox)
...
> +static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a,
> + MemOp mop, bool nanbox)
...
> +static bool gen_fload_le(DisasContext *ctx, arg_frr *a,
> + MemOp mop, bool nanbox)
...
> +static bool gen_fstore_le(DisasContext *ctx, arg_frr *a,
> + MemOp mop, bool nanbox)
Simiarly.
> +TRANS(fld_s, gen_fload_imm, MO_TESL, true)
Use TEUL for everything here, because you don't need sign extension.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 07/26] target/loongarch: Add fixed point load/store instruction translation
2021-11-20 8:20 ` Richard Henderson
@ 2021-11-20 9:39 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 9:39 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/20/21 9:20 AM, Richard Henderson wrote:
> %i14s2 10:s14 !function=shl_2
Of course you have a times_4 function introduced later which could be used for this.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 15/26] target/loongarch: Add branch instruction translation
2021-11-19 6:13 ` [PATCH v11 15/26] target/loongarch: Add branch " Song Gao
@ 2021-11-20 9:46 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 9:46 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> + tcg_gen_ld8u_tl(src1, cpu_env,
> + offsetof(CPULoongArchState, cf[a->cj & 0x7]));
Mask of cj not needed; it's done by decode.
> +&rr_dj_offs rd rj offs
> +&rr_offs rj rd offs
...
> +@rr_dj_offs16 .... .. ................ rj:5 rd:5 &rr_dj_offs offs=%offs16
> +@rr_offs16 .... .. ................ rj:5 rd:5 &rr_offs offs=%offs16
These two are the same.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 16/26] target/loongarch: Add disassembler
2021-11-19 6:13 ` [PATCH v11 16/26] target/loongarch: Add disassembler Song Gao
@ 2021-11-20 9:53 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 9:53 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +static void output_r_offs(DisasContext *ctx, arg_r_offs *a,
> + const char *mnemonic)
> +{
> + output(ctx, mnemonic, "r%d, %d # 0x%lx", a->rj, a->offs,
%lx is wrong; use PRIx64.
Many instances.
If you use
make docker-test-build@fedora-i386-cross
you should see errors here.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 17/26] linux-user: Add LoongArch generic header files
2021-11-19 6:13 ` [PATCH v11 17/26] linux-user: Add LoongArch generic header files Song Gao
@ 2021-11-20 9:54 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 9:54 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> 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>
> ---
> 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
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 18/26] linux-user: Add LoongArch specific structures
2021-11-19 6:13 ` [PATCH v11 18/26] linux-user: Add LoongArch specific structures Song Gao
@ 2021-11-20 10:06 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 10:06 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 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 | 48 +++++++++++++++++++++++++++++++++
> 1 file changed, 48 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 0000000..cc7928a
> --- /dev/null
> +++ b/linux-user/loongarch64/target_structs.h
> @@ -0,0 +1,48 @@
> +/* 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_uint mode; /* Read/write permission. */
> + abi_ushort __seq; /* Sequence number. */
> + abi_ushort __pad1;
> + abi_ulong __unused1;
> + abi_ulong __unused2;
> +};
We should most definitely create a generic version of this file before we do any more
replication.
The aarch64 version is generic, with copies in cris, hexagon, i386, m68k, microblaze,
nios2, openrisc, riscv, and sh4.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-19 6:13 ` [PATCH v11 19/26] linux-user: Add LoongArch signal support Song Gao
@ 2021-11-20 10:33 ` Richard Henderson
2021-11-22 11:41 ` gaosong
` (3 more replies)
0 siblings, 4 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 10:33 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> ---
> linux-user/loongarch64/signal.c | 162 +++++++++++++++++++++++++++++++++
> linux-user/loongarch64/target_signal.h | 29 ++++++
> 2 files changed, 191 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 0000000..8fbc827
> --- /dev/null
> +++ b/linux-user/loongarch64/signal.c
> @@ -0,0 +1,162 @@
> +/* 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"
> +
> +struct target_sigcontext {
> + uint64_t sc_pc;
> + uint64_t sc_gpr[32];
> + uint64_t sc_fpr[32];
> + uint64_t sc_fcc;
> + uint32_t sc_fcsr;
> + uint32_t sc_flags;
> +};
Does not match
https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/sigcontext.h
> +
> +struct target_ucontext {
> + target_ulong tuc_flags;
> + target_ulong tuc_link;
> + target_stack_t tuc_stack;
> + target_ulong pad0;
> + struct target_sigcontext tuc_mcontext;
> + target_sigset_t tuc_sigmask;
> +};
Does not match
https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/ucontext.h
> +static inline void setup_sigcontext(CPULoongArchState *env,
> + struct target_sigcontext *sc)
Drop all of the the inline markers.
> +{
> + int i;
> +
> + __put_user(env->pc, &sc->sc_pc);
> +
> + __put_user(0, &sc->sc_gpr[0]);
> + for (i = 1; i < 32; ++i) {
> + __put_user(env->gpr[i], &sc->sc_gpr[i]);
> + }
> +
> + for (i = 0; i < 32; ++i) {
> + __put_user(env->fpr[i], &sc->sc_fpr[i]);
> + }
> +}
Missing fcsr and fcc.
I'll note that the kernel is missing sets of vscr and scr[0-3]. IMO they should at least
be zeroed in advance of supporting the vector extension.
> +static inline void
> +restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc)
> +{
> + int i;
> +
> + __get_user(env->pc, &sc->sc_pc);
> +
> + for (i = 1; i < 32; ++i) {
> + __get_user(env->gpr[i], &sc->sc_gpr[i]);
> + }
> +
> + for (i = 0; i < 32; ++i) {
> + __get_user(env->fpr[i], &sc->sc_fpr[i]);
> + }
> +}
Similarly.
> + return (sp - frame_size) & ~7;
include/asm/asm.h:#define ALMASK ~15
kernel/signal.c: return (void __user *)((sp - frame_size) & ALMASK);
> + env->pc = env->gpr[20] = ka->_sa_handler;
There is no set of gpr[20].
> +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, a7, 0x8b */
The comment is incorrect: "ori a7, zero, 0x8b", but the hex is right.
> +/* this struct defines a stack used during syscall handling */
> +typedef struct target_sigaltstack {
> + abi_long ss_sp;
> + abi_int ss_flags;
> + abi_ulong ss_size;
> +} target_stack_t;
> +
> +/*
> + * sigaltstack controls
> + */
> +#define TARGET_SS_ONSTACK 1
> +#define TARGET_SS_DISABLE 2
> +
> +#define TARGET_MINSIGSTKSZ 2048
> +#define TARGET_SIGSTKSZ 8192
We should move these to generic/signal.h.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 20/26] linux-user: Add LoongArch elf support
2021-11-19 6:13 ` [PATCH v11 20/26] linux-user: Add LoongArch elf support Song Gao
@ 2021-11-20 10:35 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 10:35 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> ---
> include/elf.h | 2 ++
> linux-user/elfload.c | 58 +++++++++++++++++++++++++++++++++++++
> linux-user/loongarch64/target_elf.h | 12 ++++++++
> 3 files changed, 72 insertions(+)
> create mode 100644 linux-user/loongarch64/target_elf.h
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 21/26] linux-user: Add LoongArch syscall support
2021-11-19 6:13 ` [PATCH v11 21/26] linux-user: Add LoongArch syscall support Song Gao
@ 2021-11-20 10:47 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 10:47 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> +static inline abi_ulong target_shmlba(CPULoongArchState *env)
> +{
> + return 0x40000;
> +}
include/asm/shmparam.h:#define SHMLBA SZ_64K
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 22/26] linux-user: Add LoongArch cpu_loop support
2021-11-19 6:13 ` [PATCH v11 22/26] linux-user: Add LoongArch cpu_loop support Song Gao
@ 2021-11-20 10:53 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-20 10:53 UTC (permalink / raw)
To: Song Gao, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/19/21 7:13 AM, Song Gao wrote:
> + case EXCP_ADE:
> + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->badaddr);
> + break;
No longer required; should be handled correctly by cpu_loop_exit_sigsegv.
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation
2021-11-20 8:56 ` Richard Henderson
@ 2021-11-22 8:23 ` gaosong
2021-11-22 8:28 ` Richard Henderson
0 siblings, 1 reply; 65+ messages in thread
From: gaosong @ 2021-11-22 8:23 UTC (permalink / raw)
To: Richard Henderson; +Cc: Xiaojuan Yang, qemu-devel, laurent
[-- Attachment #1: Type: text/plain, Size: 635 bytes --]
Hi Richard,
Sorry for the late reply.
On 2021/11/20 下午4:56, Richard Henderson wrote:
> On 11/20/21 9:52 AM, gaosong wrote:
>> You're right, gen_set_gpr not need EXT_NONE at all, and we need not
>> condition around gen_set_gpr.
>> I think that if we know the dst_ext is EXT_NONE, we do't need
>> gen_set_gpr.
>
> But that assumes that gpr_dst did not return a temporary.
> I think it's cleaner to assume that gen_set_gpr is needed.
>
Does this mean that we gen_set_gpr where used gpr_dst, and gen_set_gpr need EXT_NONE?
Such as gpr_dst in trans_atomic.c.inc/trans_memory.c.inc, should we need gen_set_gpr?
Thanks
Song Gao
> r~
[-- Attachment #2: Type: text/html, Size: 1225 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation
2021-11-22 8:23 ` gaosong
@ 2021-11-22 8:28 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-22 8:28 UTC (permalink / raw)
To: gaosong; +Cc: Xiaojuan Yang, qemu-devel, laurent
On 11/22/21 9:23 AM, gaosong wrote:
> On 2021/11/20 下午4:56, Richard Henderson wrote:
>> On 11/20/21 9:52 AM, gaosong wrote:
>>> You're right, gen_set_gpr not need EXT_NONE at all, and we need not condition around
>>> gen_set_gpr.
>>> I think that if we know the dst_ext is EXT_NONE, we do't need gen_set_gpr.
>>
>> But that assumes that gpr_dst did not return a temporary.
>> I think it's cleaner to assume that gen_set_gpr is needed.
>>
> Does this mean that we gen_set_gpr where used gpr_dst, and gen_set_gpr need EXT_NONE?
> Such as gpr_dst in trans_atomic.c.inc/trans_memory.c.inc, should we need gen_set_gpr?
Yes.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-20 10:33 ` Richard Henderson
@ 2021-11-22 11:41 ` gaosong
2021-11-22 11:44 ` chen huacai
2021-11-22 12:31 ` Richard Henderson
2021-11-24 2:46 ` gaosong
` (2 subsequent siblings)
3 siblings, 2 replies; 65+ messages in thread
From: gaosong @ 2021-11-22 11:41 UTC (permalink / raw)
To: Richard Henderson, zltjiangshi
Cc: Xiaojuan Yang, chenhuacai, qemu-devel, maobibo, laurent
[-- Attachment #1: Type: text/plain, Size: 865 bytes --]
Hi Richard,
On 2021/11/20 下午6:33, Richard Henderson wrote:
>
> Drop all of the the inline markers.
>
>> +{
>> + int i;
>> +
>> + __put_user(env->pc, &sc->sc_pc);
>> +
>> + __put_user(0, &sc->sc_gpr[0]);
>> + for (i = 1; i < 32; ++i) {
>> + __put_user(env->gpr[i], &sc->sc_gpr[i]);
>> + }
>> +
>> + for (i = 0; i < 32; ++i) {
>> + __put_user(env->fpr[i], &sc->sc_fpr[i]);
>> + }
>> +}
>
> Missing fcsr and fcc.
>
> I'll note that the kernel is missing sets of vscr and scr[0-3]. IMO
> they should at least be zeroed in advance of supporting the vector
> extension.
I see that vcsr set at [1]:178.
[1]
https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/kernel/signal.c
and I also see that the kernel is missing sets of scr[0-3], Huacai is that right?
Thanks
Song Gao
[-- Attachment #2: Type: text/html, Size: 1751 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-22 11:41 ` gaosong
@ 2021-11-22 11:44 ` chen huacai
2021-11-22 12:31 ` Richard Henderson
1 sibling, 0 replies; 65+ messages in thread
From: chen huacai @ 2021-11-22 11:44 UTC (permalink / raw)
To: gaosong
Cc: Xiaojuan Yang, Richard Henderson, qemu-level, maobibo,
Laurent Vivier, chenhuacai
Hi, all,
On Mon, Nov 22, 2021 at 7:41 PM gaosong <gaosong@loongson.cn> wrote:
>
> Hi Richard,
>
> On 2021/11/20 下午6:33, Richard Henderson wrote:
>
>
> Drop all of the the inline markers.
>
> +{
> + int i;
> +
> + __put_user(env->pc, &sc->sc_pc);
> +
> + __put_user(0, &sc->sc_gpr[0]);
> + for (i = 1; i < 32; ++i) {
> + __put_user(env->gpr[i], &sc->sc_gpr[i]);
> + }
> +
> + for (i = 0; i < 32; ++i) {
> + __put_user(env->fpr[i], &sc->sc_fpr[i]);
> + }
> +}
>
>
> Missing fcsr and fcc.
>
> I'll note that the kernel is missing sets of vscr and scr[0-3]. IMO they should at least be zeroed in advance of supporting the vector extension.
>
> I see that vcsr set at [1]:178.
> [1]
> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/kernel/signal.c
>
> and I also see that the kernel is missing sets of scr[0-3], Huacai is that right?
scr[0-3] is reserved for binary translation, it doesn't need to be set now.
Huacai
>
> Thanks
> Song Gao
--
Huacai Chen
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-22 11:41 ` gaosong
2021-11-22 11:44 ` chen huacai
@ 2021-11-22 12:31 ` Richard Henderson
1 sibling, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-22 12:31 UTC (permalink / raw)
To: gaosong, zltjiangshi
Cc: Xiaojuan Yang, chenhuacai, qemu-devel, maobibo, laurent
On 11/22/21 12:41 PM, gaosong wrote:
> Hi Richard,
>
> On 2021/11/20 下午6:33, Richard Henderson wrote:
>>
>> Drop all of the the inline markers.
>>
>>> +{
>>> + int i;
>>> +
>>> + __put_user(env->pc, &sc->sc_pc);
>>> +
>>> + __put_user(0, &sc->sc_gpr[0]);
>>> + for (i = 1; i < 32; ++i) {
>>> + __put_user(env->gpr[i], &sc->sc_gpr[i]);
>>> + }
>>> +
>>> + for (i = 0; i < 32; ++i) {
>>> + __put_user(env->fpr[i], &sc->sc_fpr[i]);
>>> + }
>>> +}
>>
>> Missing fcsr and fcc.
>>
>> I'll note that the kernel is missing sets of vscr and scr[0-3]. IMO they should at least
>> be zeroed in advance of supporting the vector extension.
>
> I see that vcsr set at [1]:178.
> [1]
> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/kernel/signal.c
That happens after line 171:
if (likely(!err))
break;
It seems most unlikely that there would be an error...
There is a macro for sc_save_vcsr in fpu.S, but it isn't used.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-20 10:33 ` Richard Henderson
2021-11-22 11:41 ` gaosong
@ 2021-11-24 2:46 ` gaosong
2021-11-24 7:27 ` Richard Henderson
2021-11-24 10:22 ` gaosong
2021-11-25 3:03 ` gaosong
3 siblings, 1 reply; 65+ messages in thread
From: gaosong @ 2021-11-24 2:46 UTC (permalink / raw)
To: Richard Henderson; +Cc: Xiaojuan Yang, qemu-devel, laurent
[-- Attachment #1: Type: text/plain, Size: 1564 bytes --]
Hi Richard,
On 2021/11/20 下午6:33, Richard Henderson wrote:
> On 11/19/21 7:13 AM, Song Gao wrote:
>>
>> +
>> +struct target_sigcontext {
>> + uint64_t sc_pc;
>> + uint64_t sc_gpr[32];
>> + uint64_t sc_fpr[32];
>> + uint64_t sc_fcc;
>> + uint32_t sc_fcsr;
>> + uint32_t sc_flags;
>> +};
>
> Does not match
> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/sigcontext.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 scr[4];
union fpureg sc_fpregs[32] __attribute__((aligned(32)));
uint32_t sc_reserved;
};
Is this OK?
>> +
>> +struct target_ucontext {
>> + target_ulong tuc_flags;
>> + target_ulong tuc_link;
>> + target_stack_t tuc_stack;
>> + target_ulong pad0;
>> + struct target_sigcontext tuc_mcontext;
>> + target_sigset_t tuc_sigmask;
>> +};
>
> Does not match
> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/ucontext.h
>
>
struct target_ucontext {
target_ulong tuc_flags;
target_ulong tuc_link;
target_stack_t tuc_stack;
target_sigset_t tuc_sigmask;
target_ulong pad0;
struct target_sigcontext tuc_mcontext;
};
Is this OK?
Thanks
Song Gao
[-- Attachment #2: Type: text/html, Size: 2791 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-24 2:46 ` gaosong
@ 2021-11-24 7:27 ` Richard Henderson
2021-11-24 7:50 ` gaosong
0 siblings, 1 reply; 65+ messages in thread
From: Richard Henderson @ 2021-11-24 7:27 UTC (permalink / raw)
To: gaosong; +Cc: Xiaojuan Yang, qemu-devel, laurent
On 11/24/21 3:46 AM, gaosong wrote:
> Hi Richard,
>
> On 2021/11/20 下午6:33, Richard Henderson wrote:
>> On 11/19/21 7:13 AM, Song Gao wrote:
>>>
>>> +
>>> +struct target_sigcontext {
>>> + uint64_t sc_pc;
>>> + uint64_t sc_gpr[32];
>>> + uint64_t sc_fpr[32];
>>> + uint64_t sc_fcc;
>>> + uint32_t sc_fcsr;
>>> + uint32_t sc_flags;
>>> +};
>>
>> Does not match
>> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/sigcontext.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 scr[4];
> union fpureg sc_fpregs[32] __attribute__((aligned(32)));
>
> uint32_t sc_reserved;
> };
>
> Is this OK?
No, sc_reserved does not match.
>
>>> +
>>> +struct target_ucontext {
>>> + target_ulong tuc_flags;
>>> + target_ulong tuc_link;
>>> + target_stack_t tuc_stack;
>>> + target_ulong pad0;
>>> + struct target_sigcontext tuc_mcontext;
>>> + target_sigset_t tuc_sigmask;
>>> +};
>>
>> Does not match
>> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/ucontext.h
>>
>>
> struct target_ucontext {
> target_ulong tuc_flags;
> target_ulong tuc_link;
> target_stack_t tuc_stack;
> target_sigset_t tuc_sigmask;
> target_ulong pad0;
> struct target_sigcontext tuc_mcontext;
> };
>
> Is this OK?
No, pad0 does not match __unused.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-24 7:27 ` Richard Henderson
@ 2021-11-24 7:50 ` gaosong
2021-11-24 9:40 ` Richard Henderson
0 siblings, 1 reply; 65+ messages in thread
From: gaosong @ 2021-11-24 7:50 UTC (permalink / raw)
To: Richard Henderson; +Cc: Xiaojuan Yang, qemu-devel, laurent
[-- Attachment #1: Type: text/plain, Size: 2164 bytes --]
Hi Richard,
On 2021/11/24 下午3:27, Richard Henderson wrote:
> On 11/24/21 3:46 AM, gaosong wrote:
>> Hi Richard,
>>
>> On 2021/11/20 下午6:33, Richard Henderson wrote:
>>> On 11/19/21 7:13 AM, Song Gao wrote:
>>>>
>>>> +
>>>> +struct target_sigcontext {
>>>> + uint64_t sc_pc;
>>>> + uint64_t sc_gpr[32];
>>>> + uint64_t sc_fpr[32];
>>>> + uint64_t sc_fcc;
>>>> + uint32_t sc_fcsr;
>>>> + uint32_t sc_flags;
>>>> +};
>>>
>>> Does not match
>>> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/sigcontext.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 scr[4];
>> union fpureg sc_fpregs[32] __attribute__((aligned(32)));
>>
>> uint32_t sc_reserved;
>> };
>>
>> Is this OK?
>
> No, sc_reserved does not match.
>
uint8 sc_reserved[4096] __attribute__((aligned(16)));
BTW, should we set scr[0-3] as 0 ?
>>
>>>> +
>>>> +struct target_ucontext {
>>>> + target_ulong tuc_flags;
>>>> + target_ulong tuc_link;
>>>> + target_stack_t tuc_stack;
>>>> + target_ulong pad0;
>>>> + struct target_sigcontext tuc_mcontext;
>>>> + target_sigset_t tuc_sigmask;
>>>> +};
>>>
>>> Does not match
>>> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/ucontext.h
>>>
>>>
>> struct target_ucontext {
>> target_ulong tuc_flags;
>> target_ulong tuc_link;
>> target_stack_t tuc_stack;
>> target_sigset_t tuc_sigmask;
>> target_ulong pad0;
>> struct target_sigcontext tuc_mcontext;
>> };
>>
>> Is this OK?
>
> No, pad0 does not match __unused.
>
uint8 unused[1024 / 8 - sizeof(target_sigset_t)];
Is this right?
Thanks
Song Gao
>
> r~
[-- Attachment #2: Type: text/html, Size: 4548 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-24 7:50 ` gaosong
@ 2021-11-24 9:40 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-24 9:40 UTC (permalink / raw)
To: gaosong; +Cc: Xiaojuan Yang, qemu-devel, laurent
On 11/24/21 8:50 AM, gaosong wrote:
>> No, sc_reserved does not match.
>>
> uint8 sc_reserved[4096] __attribute__((aligned(16)));
Yes.
> BTW, should we set scr[0-3] as 0 ?
I think so. The LoongArch Reference Manual, Volume 3: Virtualization and Binary
Translation Extensions, v1.00, is empty. But I do not imagine a world in which 0 is not a
safe indication of "this field is empty/unused".
>> No, pad0 does not match __unused.
>>
> uint8 unused[1024 / 8 - sizeof(target_sigset_t)];
> Is this right?
Yes.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-20 10:33 ` Richard Henderson
2021-11-22 11:41 ` gaosong
2021-11-24 2:46 ` gaosong
@ 2021-11-24 10:22 ` gaosong
2021-11-24 10:44 ` Richard Henderson
2021-11-25 3:03 ` gaosong
3 siblings, 1 reply; 65+ messages in thread
From: gaosong @ 2021-11-24 10:22 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: Xiaojuan Yang, laurent
[-- Attachment #1: Type: text/plain, Size: 803 bytes --]
Hi Richard,
On 2021/11/20 下午6:33, Richard Henderson wrote:
>> +{
>> + int i;
>> +
>> + __put_user(env->pc, &sc->sc_pc);
>> +
>> + __put_user(0, &sc->sc_gpr[0]);
>> + for (i = 1; i < 32; ++i) {
>> + __put_user(env->gpr[i], &sc->sc_gpr[i]);
>> + }
>> +
>> + for (i = 0; i < 32; ++i) {
>> + __put_user(env->fpr[i], &sc->sc_fpr[i]);
>> + }
>> +}
>
> Missing fcsr and fcc.
I see that kernel define the fcc used type uint64_t, and used
movgr2cf/movcf2gr save and restore the fcc0-fcc7.
but qemu define fcc0-fcc7 as bool cf[8] at target/loongarch/cpu.h,
how qemu can save/restore fcc, Do you have any idea?
Does we can define the fcc as bool cf[8] at struct target_sigcontext?
Thanks
Song Gao
[-- Attachment #2: Type: text/html, Size: 1540 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-24 10:22 ` gaosong
@ 2021-11-24 10:44 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-24 10:44 UTC (permalink / raw)
To: gaosong, qemu-devel; +Cc: Xiaojuan Yang, laurent
On 11/24/21 11:22 AM, gaosong wrote:
> I see that kernel define the fcc used type uint64_t, and used movgr2cf/movcf2gr
> save and restore the fcc0-fcc7.
> but qemu define fcc0-fcc7 as bool cf[8] at target/loongarch/cpu.h, how qemu can
> save/restore fcc, Do you have any idea?
> Does we can define the fcc as bool cf[8] at struct target_sigcontext?
No, you need to leave the declaration the same.
To create the uint64_t, you do what the kernel does in sc_save_fcc: insert each bit into
the first bit of each byte.
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;
}
And similarly from sc_restore_fcc:
static void write_all_fcc(CPULoongArchState *env, uint64_t val)
{
for (int i = 0; i < 8; ++i) {
env->cf[i] = (val >> (i * 8)) & 1;
}
}
Remembering that movcf2gr copies the least significant bit.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-20 10:33 ` Richard Henderson
` (2 preceding siblings ...)
2021-11-24 10:22 ` gaosong
@ 2021-11-25 3:03 ` gaosong
2021-11-25 10:11 ` Richard Henderson
3 siblings, 1 reply; 65+ messages in thread
From: gaosong @ 2021-11-25 3:03 UTC (permalink / raw)
To: Richard Henderson; +Cc: Xiaojuan Yang, qemu-devel, laurent
[-- Attachment #1: Type: text/plain, Size: 671 bytes --]
Hi Richard,
On 2021/11/20 下午6:33, Richard Henderson wrote:
>> +/* this struct defines a stack used during syscall handling */
>> +typedef struct target_sigaltstack {
>> + abi_long ss_sp;
>> + abi_int ss_flags;
>> + abi_ulong ss_size;
>> +} target_stack_t;
>> +
>> +/*
>> + * sigaltstack controls
>> + */
>> +#define TARGET_SS_ONSTACK 1
>> +#define TARGET_SS_DISABLE 2
>> +
>> +#define TARGET_MINSIGSTKSZ 2048
>> +#define TARGET_SIGSTKSZ 8192
>
> We should move these to generic/signal.h.
Yes.
I also see that TARGET_SIGSTKSZ is not used. I think we should delete it.
Thanks
Song Gao
[-- Attachment #2: Type: text/html, Size: 1374 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support
2021-11-25 3:03 ` gaosong
@ 2021-11-25 10:11 ` Richard Henderson
0 siblings, 0 replies; 65+ messages in thread
From: Richard Henderson @ 2021-11-25 10:11 UTC (permalink / raw)
To: gaosong; +Cc: Xiaojuan Yang, qemu-devel, laurent
On 11/25/21 4:03 AM, gaosong wrote:
> I also see that TARGET_SIGSTKSZ is not used. I think we should delete it.
Agreed. This constant will have been baked into the guest executable.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 11/26] target/loongarch: Add floating point comparison instruction translation
2021-11-20 9:02 ` Richard Henderson
@ 2021-11-30 8:22 ` gaosong
2021-11-30 8:37 ` Richard Henderson
0 siblings, 1 reply; 65+ messages in thread
From: gaosong @ 2021-11-30 8:22 UTC (permalink / raw)
To: Richard Henderson; +Cc: Xiaojuan Yang, qemu-devel, laurent
[-- Attachment #1: Type: text/plain, Size: 2418 bytes --]
Hi Richard,
On 2021/11/20 下午5:02, Richard Henderson wrote:
>
>> +#define FCMP_LT 0x0001 /* fp0 < fp1 */
>> +#define FCMP_EQ 0x0010 /* fp0 = fp1 */
>> +#define FCMP_UN 0x0100 /* unordered */
>> +#define FCMP_GT 0x1000 /* fp0 > fp1 */
>
> Any reason why these bits are not sequential?
I think this is consistent with the description in Table 9, and the
FCMP_GT is need 0x7.
In get_fcmp_flags(int cond) the param 'cond' is table 9 COND >> 1,
table 9
COND True Condition
0x2 LT
0x4 EQ
0x6 EQ LT
0x8 UN
0x10 GT LT
...
COND >> 1 Flags
0x1 FCMP_LT FCMP_LT 0x1
0x2 FCMP_EQ FCMP_EQ 0x2
0x3 FCMP_EQ | FCMP_LT
0x4 FCMP_UN FCMP_UN 0x4
0x8 FCMP_GT | FCMP_LT FCMP_GT 0x7
...
so our definitions :
#define FCMP_LT 0x1 /* fp0 < fp1 */
#define FCMP_EQ 0x2 /* fp0 = fp1 */
#define FCMP_UN 0x4 /* unordered */
#define FCMP_GT 0x7 /* fp0 > fp1 */
get_fcmp_flags:
/* 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;
}
If not .
We should like:
#define FCMP_LT 0x1 /* fp0 < fp1 */
#define FCMP_EQ 0x2 /* fp0 = fp1 */
#define FCMP_UN 0x3 /* unordered */
#define FCMP_GT 0x4 /* fp0 > fp1 */
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 & 0x3) {
flags |= FCMP_UN;
}
if (cond & 0x4) {
flags |= FCMP_GT;
}
return flags;
}
Is this right?
Thanks
Song Gao
[-- Attachment #2: Type: text/html, Size: 4178 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 11/26] target/loongarch: Add floating point comparison instruction translation
2021-11-30 8:22 ` gaosong
@ 2021-11-30 8:37 ` Richard Henderson
2021-11-30 8:50 ` gaosong
0 siblings, 1 reply; 65+ messages in thread
From: Richard Henderson @ 2021-11-30 8:37 UTC (permalink / raw)
To: gaosong; +Cc: Xiaojuan Yang, qemu-devel, laurent
On 11/30/21 9:22 AM, gaosong wrote:
> On 2021/11/20 下午5:02, Richard Henderson wrote:
>>
>>> +#define FCMP_LT 0x0001 /* fp0 < fp1 */
>>> +#define FCMP_EQ 0x0010 /* fp0 = fp1 */
>>> +#define FCMP_UN 0x0100 /* unordered */
>>> +#define FCMP_GT 0x1000 /* fp0 > fp1 */
>>
>> Any reason why these bits are not sequential?
...
> We should like:
>
> #define FCMP_LT 0x1 /* fp0 < fp1 */
> #define FCMP_EQ 0x2 /* fp0 = fp1 */
> #define FCMP_UN 0x3 /* unordered */
> #define FCMP_GT 0x4 /* fp0 > fp1 */
>
> 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 & 0x3) {
> flags |= FCMP_UN;
> }
> if (cond & 0x4) {
> flags |= FCMP_GT;
> }
> return flags;
> }
>
> Is this right?
No. You're not converting anything here.
I think you should simply replace "0x" with "0b" so that the bits of FCMP are more
compact. I assume that's what you were originally thinking.
#define FCMP_LT 0b0001 /* fp0 < fp1 */
#define FCMP_EQ 0b0010 /* fp0 = fp1 */
#define FCMP_UN 0b0100 /* unordered */
#define FCMP_GT 0b1000 /* fp0 > fp1 */
or identically with the form (1 << 0), (1 << 1), etc.
r~
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH v11 11/26] target/loongarch: Add floating point comparison instruction translation
2021-11-30 8:37 ` Richard Henderson
@ 2021-11-30 8:50 ` gaosong
0 siblings, 0 replies; 65+ messages in thread
From: gaosong @ 2021-11-30 8:50 UTC (permalink / raw)
To: Richard Henderson; +Cc: Xiaojuan Yang, qemu-devel, laurent
[-- Attachment #1: Type: text/plain, Size: 274 bytes --]
Hi Richard.
On 2021/11/30 下午4:37, Richard Henderson wrote:
>
> I think you should simply replace "0x" with "0b" so that the bits of
> FCMP are more compact. I assume that's what you were originally
> thinking.
Ooh, suddenly become clear-minded.
Thanks
Song Gao
[-- Attachment #2: Type: text/html, Size: 2155 bytes --]
^ permalink raw reply [flat|nested] 65+ messages in thread
end of thread, other threads:[~2021-11-30 8:51 UTC | newest]
Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-19 6:13 [PATCH v11 00/26] Add LoongArch linux-user emulation support Song Gao
2021-11-19 6:13 ` [PATCH v11 01/26] target/loongarch: Add README Song Gao
2021-11-19 6:13 ` [PATCH v11 02/26] target/loongarch: Add core definition Song Gao
2021-11-19 6:13 ` [PATCH v11 03/26] target/loongarch: Add main translation routines Song Gao
2021-11-19 6:13 ` [PATCH v11 04/26] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
2021-11-20 7:10 ` Richard Henderson
2021-11-20 7:17 ` Richard Henderson
2021-11-20 8:52 ` gaosong
2021-11-20 8:56 ` Richard Henderson
2021-11-22 8:23 ` gaosong
2021-11-22 8:28 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 05/26] target/loongarch: Add fixed point shift " Song Gao
2021-11-20 7:42 ` Richard Henderson
2021-11-20 9:03 ` gaosong
2021-11-19 6:13 ` [PATCH v11 06/26] target/loongarch: Add fixed point bit " Song Gao
2021-11-20 8:05 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 07/26] target/loongarch: Add fixed point load/store " Song Gao
2021-11-20 8:20 ` Richard Henderson
2021-11-20 9:39 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 08/26] target/loongarch: Add fixed point atomic " Song Gao
2021-11-20 8:30 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 09/26] target/loongarch: Add fixed point extra " Song Gao
2021-11-20 8:52 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 10/26] target/loongarch: Add floating point arithmetic " Song Gao
2021-11-20 8:54 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 11/26] target/loongarch: Add floating point comparison " Song Gao
2021-11-20 9:02 ` Richard Henderson
2021-11-30 8:22 ` gaosong
2021-11-30 8:37 ` Richard Henderson
2021-11-30 8:50 ` gaosong
2021-11-19 6:13 ` [PATCH v11 12/26] target/loongarch: Add floating point conversion " Song Gao
2021-11-19 6:13 ` [PATCH v11 13/26] target/loongarch: Add floating point move " Song Gao
2021-11-19 6:13 ` [PATCH v11 14/26] target/loongarch: Add floating point load/store " Song Gao
2021-11-20 9:36 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 15/26] target/loongarch: Add branch " Song Gao
2021-11-20 9:46 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 16/26] target/loongarch: Add disassembler Song Gao
2021-11-20 9:53 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 17/26] linux-user: Add LoongArch generic header files Song Gao
2021-11-20 9:54 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 18/26] linux-user: Add LoongArch specific structures Song Gao
2021-11-20 10:06 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 19/26] linux-user: Add LoongArch signal support Song Gao
2021-11-20 10:33 ` Richard Henderson
2021-11-22 11:41 ` gaosong
2021-11-22 11:44 ` chen huacai
2021-11-22 12:31 ` Richard Henderson
2021-11-24 2:46 ` gaosong
2021-11-24 7:27 ` Richard Henderson
2021-11-24 7:50 ` gaosong
2021-11-24 9:40 ` Richard Henderson
2021-11-24 10:22 ` gaosong
2021-11-24 10:44 ` Richard Henderson
2021-11-25 3:03 ` gaosong
2021-11-25 10:11 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 20/26] linux-user: Add LoongArch elf support Song Gao
2021-11-20 10:35 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 21/26] linux-user: Add LoongArch syscall support Song Gao
2021-11-20 10:47 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 22/26] linux-user: Add LoongArch cpu_loop support Song Gao
2021-11-20 10:53 ` Richard Henderson
2021-11-19 6:13 ` [PATCH v11 23/26] default-configs: Add loongarch linux-user support Song Gao
2021-11-19 6:13 ` [PATCH v11 24/26] target/loongarch: Add target build suport Song Gao
2021-11-19 6:13 ` [PATCH v11 25/26] target/loongarch: 'make check-tcg' support Song Gao
2021-11-19 6:13 ` [PATCH v11 26/26] scripts: add loongarch64 binfmt config Song Gao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).