* [PATCH v4 00/21] Add LoongArch linux-user emulation support
@ 2021-09-02 12:40 Song Gao
2021-09-02 12:40 ` [PATCH v4 01/21] target/loongarch: Add README Song Gao
` (20 more replies)
0 siblings, 21 replies; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
Hi,
We tested some basic system commands using LoongArch clfs system.
and supported 'make check-tcg'. Of course. this series only support linux-user emulation.
Changes for v4:
* Update README,add LoongArch linux-user emulation Introduction.
* Add 'make check-tcg' support(patch 20).
* Add binfmt config(patch 21).
* Fix bugs when running loongarch basic commands.
Changes for v3:
* Split trans.inc.c.
* Remove csr registers.
* Delete patchs 2, 4, 5.
* Follow Richard's code review comments [1].
* Follow Richard's riscv patches [2].
[1]: https://patchew.org/QEMU/1626861198-6133-1-git-send-email-gaosong@loongson.cn/
[2]: https://patchew.org/QEMU/20210823195529.560295-1-richard.henderson@linaro.org/
Changes for v2:
* Patch 1, remove unnecessary introduction;
* Patch 3, follow the ARM/AVR pattern to add new CPU features;
* Patch 6, remove decode_lsx();
* Patches 7-18, delete opcode definition, modify translation function;
* Patches 20-22, split V1 patch20 to V2 patch20-22.
V3: https://patchew.org/QEMU/1630048494-2143-1-git-send-email-gaosong@loongson.cn/
V2: https://patchew.org/QEMU/1626861198-6133-1-git-send-email-gaosong@loongson.cn/
V1: https://patchew.org/QEMU/1624881885-31692-1-git-send-email-gaosong@loongson.cn/
Please review!
Thanks.
Song Gao (21):
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
LoongArch Linux User Emulation
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 | 6 +
configs/targets/loongarch64-linux-user.mak | 3 +
disas/loongarch.c | 2511 +++++++++++++++++++++++++++
disas/meson.build | 1 +
include/disas/dis-asm.h | 2 +
include/elf.h | 2 +
linux-user/elfload.c | 58 +
linux-user/loongarch64/cpu_loop.c | 108 ++
linux-user/loongarch64/signal.c | 178 ++
linux-user/loongarch64/sockbits.h | 1 +
linux-user/loongarch64/syscall_nr.h | 290 ++++
linux-user/loongarch64/target_cpu.h | 35 +
linux-user/loongarch64/target_elf.h | 14 +
linux-user/loongarch64/target_errno_defs.h | 7 +
linux-user/loongarch64/target_fcntl.h | 12 +
linux-user/loongarch64/target_signal.h | 28 +
linux-user/loongarch64/target_structs.h | 49 +
linux-user/loongarch64/target_syscall.h | 46 +
linux-user/loongarch64/termbits.h | 229 +++
linux-user/syscall_defs.h | 10 +-
meson.build | 1 +
scripts/qemu-binfmt-conf.sh | 6 +-
target/loongarch/README | 76 +
target/loongarch/cpu-param.h | 19 +
target/loongarch/cpu.c | 286 +++
target/loongarch/cpu.h | 145 ++
target/loongarch/fpu_helper.c | 947 ++++++++++
target/loongarch/helper.h | 102 ++
target/loongarch/insn_trans/trans_arith.c | 332 ++++
target/loongarch/insn_trans/trans_atomic.c | 134 ++
target/loongarch/insn_trans/trans_bit.c | 269 +++
target/loongarch/insn_trans/trans_branch.c | 84 +
target/loongarch/insn_trans/trans_extra.c | 88 +
target/loongarch/insn_trans/trans_farith.c | 79 +
target/loongarch/insn_trans/trans_fcmp.c | 279 +++
target/loongarch/insn_trans/trans_fcnv.c | 36 +
target/loongarch/insn_trans/trans_fmemory.c | 143 ++
target/loongarch/insn_trans/trans_fmov.c | 159 ++
target/loongarch/insn_trans/trans_memory.c | 263 +++
target/loongarch/insn_trans/trans_shift.c | 154 ++
target/loongarch/insns.decode | 480 +++++
target/loongarch/internals.h | 24 +
target/loongarch/meson.build | 18 +
target/loongarch/op_helper.c | 85 +
target/loongarch/translate.c | 309 ++++
target/loongarch/translate.h | 54 +
target/meson.build | 1 +
tests/tcg/configure.sh | 1 +
48 files changed, 8159 insertions(+), 5 deletions(-)
create mode 100644 configs/targets/loongarch64-linux-user.mak
create mode 100644 disas/loongarch.c
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/fpu_helper.c
create mode 100644 target/loongarch/helper.h
create mode 100644 target/loongarch/insn_trans/trans_arith.c
create mode 100644 target/loongarch/insn_trans/trans_atomic.c
create mode 100644 target/loongarch/insn_trans/trans_bit.c
create mode 100644 target/loongarch/insn_trans/trans_branch.c
create mode 100644 target/loongarch/insn_trans/trans_extra.c
create mode 100644 target/loongarch/insn_trans/trans_farith.c
create mode 100644 target/loongarch/insn_trans/trans_fcmp.c
create mode 100644 target/loongarch/insn_trans/trans_fcnv.c
create mode 100644 target/loongarch/insn_trans/trans_fmemory.c
create mode 100644 target/loongarch/insn_trans/trans_fmov.c
create mode 100644 target/loongarch/insn_trans/trans_memory.c
create mode 100644 target/loongarch/insn_trans/trans_shift.c
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] 46+ messages in thread
* [PATCH v4 01/21] target/loongarch: Add README
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-02 12:40 ` [PATCH v4 02/21] target/loongarch: Add core definition Song Gao
` (19 subsequent siblings)
20 siblings, 0 replies; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch give an introduction to the LoongArch target.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
MAINTAINERS | 5 ++++
target/loongarch/README | 76 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+)
create mode 100644 target/loongarch/README
diff --git a/MAINTAINERS b/MAINTAINERS
index c822165..96225d8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -210,6 +210,11 @@ F: disas/hppa.c
F: hw/net/*i82596*
F: include/hw/net/lasi_82596.h
+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] 46+ messages in thread
* [PATCH v4 02/21] target/loongarch: Add core definition
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
2021-09-02 12:40 ` [PATCH v4 01/21] target/loongarch: Add README Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-04 9:44 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 03/21] target/loongarch: Add main translation routines Song Gao
` (18 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch add target state header, target definitions
and initialization routines.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
target/loongarch/cpu-param.h | 19 +++
target/loongarch/cpu.c | 285 +++++++++++++++++++++++++++++++++++++++++++
target/loongarch/cpu.h | 145 ++++++++++++++++++++++
target/loongarch/internals.h | 23 ++++
4 files changed, 472 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..83f9624
--- /dev/null
+++ b/target/loongarch/cpu-param.h
@@ -0,0 +1,19 @@
+/*
+ * LoongArch cpu parameters for qemu.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#ifndef LOONGARCH_CPU_PARAM_H
+#define LOONGARCH_CPU_PARAM_H 1
+
+#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..b89bf51
--- /dev/null
+++ b/target/loongarch/cpu.c
@@ -0,0 +1,285 @@
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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", "ra", "tp", "sp", "a0", "a1", "a2", "a3",
+ "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
+ "t4", "t5", "t6", "t7", "t8", "x0", "fp", "s0",
+ "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8",
+};
+
+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] = "Inst. Not Exist",
+ [EXCP_FPE] = "Floating Point Exception",
+};
+
+const char *loongarch_exception_name(int32_t exception)
+{
+ if (exception < 0 || exception > EXCP_LAST) {
+ return "unknown";
+ }
+ 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 set_loongarch_cpucfg(CPULoongArchState *env)
+{
+ int i;
+
+ for (i = 0; i < 15; i++) {
+ env->cpucfg[i] = 0x0;
+ }
+ env->cpucfg[0] = 0x14c010;
+ env->cpucfg[1] = 0x3f2f2fe;
+ env->cpucfg[2] = 0x60c3cf;
+ env->cpucfg[3] = 0xcff;
+ env->cpucfg[4] = 0x5f5e100;
+ env->cpucfg[5] = 0x10001;
+ env->cpucfg[10] = 0x2c3d;
+ env->cpucfg[11] = 0x6080003;
+ env->cpucfg[12] = 0x6080003;
+ env->cpucfg[13] = 0x60800f;
+ env->cpucfg[14] = 0x60f000f;
+}
+
+/* LoongArch CPU definitions */
+static void loongarch_3a5000_initfn(Object *obj)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+ CPULoongArchState *env = &cpu->env;
+
+ set_loongarch_cpucfg(env);
+}
+
+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);
+
+ set_loongarch_cpucfg(env);
+ 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 bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ env->badaddr = address;
+ cs->exception_index = EXCP_ADE;
+ do_raise_exception(env, cs->exception_index, retaddr);
+}
+
+static struct TCGCPUOps loongarch_tcg_ops = {
+ .initialize = loongarch_translate_init,
+ .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
+ .tlb_fill = loongarch_cpu_tlb_fill,
+};
+#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..a0348d0
--- /dev/null
+++ b/target/loongarch/cpu.h
@@ -0,0 +1,145 @@
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#ifndef LOONGARCH_CPU_H
+#define LOONGARCH_CPU_H
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat-types.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 */
+#define GET_FP_CAUSE(reg) (((reg) >> 24) & 0x1f)
+#define GET_FP_ENABLE(reg) (reg & 0x1f)
+#define GET_FP_FLAGS(reg) (((reg) >> 16) & 0x1f)
+#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x1f << 24)) | \
+ ((v & 0x1f) << 24); \
+ } while (0)
+#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f) | (v & 0x1f); \
+ } while (0)
+#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 16)) | \
+ ((v & 0x1f) << 16); \
+ } while (0)
+#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 16); } while (0)
+
+#define FP_INEXACT 1
+#define FP_UNDERFLOW 2
+#define FP_OVERFLOW 4
+#define FP_DIV0 8
+#define FP_INVALID 16
+
+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[15];
+
+ uint64_t lladdr; /* LL virtual address compared against SC */
+ uint64_t llval;
+
+ uint64_t badaddr;
+};
+
+/**
+ * LoongArchCPU:
+ * @env: #CPULoongArchState
+ * @clock: this CPU input clock (may be connected
+ * to an output clock from another device).
+ *
+ * A LoongArch CPU.
+ */
+struct LoongArchCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUNegativeOffsetState neg;
+ CPULoongArchState env;
+};
+
+#define TYPE_LOONGARCH_CPU "loongarch64-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;
+};
+
+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;
+}
+
+void loongarch_cpu_list(void);
+
+#define cpu_signal_handler cpu_loongarch_signal_handler
+#define cpu_list loongarch_cpu_list
+
+#define MMU_USER_IDX 3
+
+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,
+};
+
+int cpu_loongarch_signal_handler(int host_signum, void *pinfo, void *puc);
+
+#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..cfb08df
--- /dev/null
+++ b/target/loongarch/internals.h
@@ -0,0 +1,23 @@
+/*
+ * QEMU LoongArch CPU -- internal functions and types
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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] 46+ messages in thread
* [PATCH v4 03/21] target/loongarch: Add main translation routines
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
2021-09-02 12:40 ` [PATCH v4 01/21] target/loongarch: Add README Song Gao
2021-09-02 12:40 ` [PATCH v4 02/21] target/loongarch: Add core definition Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-04 9:45 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
` (17 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch add main translation routines and
basic functions for translation.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
target/loongarch/helper.h | 9 +++
target/loongarch/op_helper.c | 22 ++++++
target/loongarch/translate.c | 165 +++++++++++++++++++++++++++++++++++++++++++
target/loongarch/translate.h | 27 +++++++
4 files changed, 223 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..09bfcfd
--- /dev/null
+++ b/target/loongarch/helper.h
@@ -0,0 +1,9 @@
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+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..4d10b03
--- /dev/null
+++ b/target/loongarch/op_helper.c
@@ -0,0 +1,22 @@
+/*
+ * LoongArch emulation helpers for qemu.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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..4769004
--- /dev/null
+++ b/target/loongarch/translate.c
@@ -0,0 +1,165 @@
+/*
+ * LoongArch emulation for QEMU - main translation routines.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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 bool use_goto_tb(DisasContext *ctx, target_ulong dest)
+{
+ return true;
+}
+
+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)
+{
+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
+ int64_t bound;
+
+ ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
+ ctx->mem_idx = MMU_USER_IDX ;
+
+ /* 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..dff7d79
--- /dev/null
+++ b/target/loongarch/translate.h
@@ -0,0 +1,27 @@
+/*
+ * LoongArch translation routines.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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] 46+ messages in thread
* [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (2 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 03/21] target/loongarch: Add main translation routines Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-04 11:04 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 05/21] target/loongarch: Add fixed point shift " Song Gao
` (16 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement fixed point arithemtic instruction translation.
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>
---
target/loongarch/insn_trans/trans_arith.c | 332 ++++++++++++++++++++++++++++++
target/loongarch/insns.decode | 89 ++++++++
target/loongarch/internals.h | 1 -
target/loongarch/translate.c | 105 +++++++++-
target/loongarch/translate.h | 20 ++
5 files changed, 541 insertions(+), 6 deletions(-)
create mode 100644 target/loongarch/insn_trans/trans_arith.c
create mode 100644 target/loongarch/insns.decode
diff --git a/target/loongarch/insn_trans/trans_arith.c b/target/loongarch/insn_trans/trans_arith.c
new file mode 100644
index 0000000..85e6d64
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_arith.c
@@ -0,0 +1,332 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+static bool gen_r2_si12(DisasContext *ctx, arg_fmt_rdrjsi12 *a,
+ DisasExtend src_ext, DisasExtend dst_ext,
+ void (*func)(TCGv, TCGv, TCGv))
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+ TCGv src2 = tcg_constant_tl(a->si12);
+
+ func(dest, src1, src2);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ return true;
+}
+
+static bool gen_r3_sa2(DisasContext *ctx, arg_fmt_rdrjrksa2 *a,
+ DisasExtend src_ext, DisasExtend dst_ext,
+ void (*func)(TCGv, TCGv, TCGv, TCGv, target_long))
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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->sa2);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ tcg_temp_free(temp);
+ return true;
+}
+
+static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+
+ tcg_gen_movi_tl(dest, a->si20 << 12);
+ return true;
+}
+
+static bool gen_pc(DisasContext *ctx, arg_fmt_rdsi20 *a,
+ void (*func)(DisasContext *ctx, TCGv, target_long))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+
+ func(ctx, dest, a->si20);
+ return true;
+}
+
+static bool gen_r2_ui12(DisasContext *ctx, arg_fmt_rdrjui12 *a,
+ void (*func)(TCGv, TCGv, target_long))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ func(dest, src1, a->ui12);
+ 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 bool gen_mulh(DisasContext *ctx, arg_add_w *a,
+ void(*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv_i32 discard = tcg_temp_new_i32();
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ TCGv_i32 t1 = tcg_temp_new_i32();
+
+ tcg_gen_trunc_tl_i32(t0, src1);
+ tcg_gen_trunc_tl_i32(t1, src2);
+ func(discard, t0, t0, t1);
+ tcg_gen_ext_i32_tl(dest, t0);
+
+ tcg_temp_free_i32(discard);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
+ return true;
+}
+
+static bool gen_mulh_d(DisasContext *ctx, arg_add_w *a,
+ void(*func)(TCGv, TCGv, TCGv, TCGv))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv discard = tcg_temp_new();
+
+ func(discard, dest, src1, src2);
+ tcg_temp_free(discard);
+ return true;
+}
+
+static bool gen_mulw_d(DisasContext *ctx, arg_add_w *a,
+ void(*func)(TCGv_i64, TCGv))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+ func(src1, src1);
+ func(src2, src2);
+ tcg_gen_mul_i64(dest, src1, src2);
+ return true;
+}
+
+static bool gen_div_w(DisasContext *ctx, arg_fmt_rdrjrk *a,
+ DisasExtend src_ext, DisasExtend dst_ext,
+ void(*func)(TCGv, TCGv, TCGv))
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+ TCGv src2 = gpr_src(ctx, a->rk, src_ext);
+ TCGv t2 = tcg_temp_new();
+ TCGv t3 = tcg_temp_new();
+
+ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src1, INT_MIN);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, -1);
+ tcg_gen_and_tl(t2, t2, t3);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, 0);
+ tcg_gen_or_tl(t2, t2, t3);
+ tcg_gen_movi_tl(t3, 0);
+ tcg_gen_movcond_tl(TCG_COND_NE, src2, t2, t3, t2, src2);
+ func(dest, src1, src2);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+
+ tcg_temp_free(t2);
+ tcg_temp_free(t3);
+ return true;
+}
+
+static bool gen_div_wu(DisasContext *ctx, arg_fmt_rdrjrk *a,
+ DisasExtend src_ext, DisasExtend dst_ext,
+ void(*func)(TCGv, TCGv, TCGv))
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+ TCGv src2 = gpr_src(ctx, a->rk, src_ext);
+ TCGv t2 = tcg_constant_tl(0);
+ TCGv t3 = tcg_constant_tl(1);
+
+ tcg_gen_movcond_tl(TCG_COND_EQ, src1, src1, t2, t3, src1);
+ func(dest, src1, src2);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ return true;
+}
+
+static bool gen_div_d(DisasContext *ctx, arg_fmt_rdrjrk *a,
+ void(*func)(TCGv, TCGv, TCGv))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv t2 = tcg_temp_new();
+ TCGv t3 = tcg_temp_new();
+
+ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src1, -1LL << 63);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, -1LL);
+ tcg_gen_and_tl(t2, t2, t3);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, 0);
+ tcg_gen_or_tl(t2, t2, t3);
+ tcg_gen_movi_tl(t3, 0);
+ tcg_gen_movcond_tl(TCG_COND_NE, src2, t2, t3, t2, src2);
+ func(dest, src1, src2);
+
+ tcg_temp_free(t2);
+ tcg_temp_free(t3);
+
+ return true;
+}
+
+static bool gen_div_du(DisasContext *ctx, arg_fmt_rdrjrk *a,
+ void(*func)(TCGv, TCGv, TCGv))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv t2 = tcg_constant_tl(0);
+ TCGv t3 = tcg_constant_tl(1);
+
+ tcg_gen_movcond_tl(TCG_COND_EQ, src2, src2, t2, t3, src2);
+ func(dest, src1, src2);
+
+ return true;
+}
+
+static void gen_alsl_w(TCGv dest, TCGv src1, TCGv src2,
+ TCGv temp, target_long sa2)
+{
+ tcg_gen_shli_tl(temp, src1, sa2 + 1);
+ tcg_gen_add_tl(dest, temp, src2);
+}
+
+static void gen_alsl_wu(TCGv dest, TCGv src1, TCGv src2,
+ TCGv temp, target_long sa2)
+{
+ tcg_gen_shli_tl(temp, src1, sa2 + 1);
+ tcg_gen_add_tl(dest, temp, src2);
+}
+
+static void gen_alsl_d(TCGv dest, TCGv src1, TCGv src2,
+ TCGv temp, target_long sa2)
+{
+ tcg_gen_shli_tl(temp, src1, sa2 + 1);
+ 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);
+ TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE);
+ TCGv src2 = tcg_constant_tl(a->si20);
+
+ 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);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = tcg_constant_tl(a->si12);
+
+ tcg_gen_deposit_tl(dest, src1, src2, 52, 12);
+ return true;
+}
+
+static void gen_pcaddi(DisasContext *ctx, TCGv dest, target_long si20)
+{
+ target_ulong addr = ctx->base.pc_next + (si20 << 2);
+ tcg_gen_movi_tl(dest, addr);
+}
+
+static void gen_pcalau12i(DisasContext *ctx, TCGv dest, target_long si20)
+{
+ target_ulong addr = (ctx->base.pc_next + (si20 << 12)) & ~0xfff;
+ tcg_gen_movi_tl(dest, addr);
+}
+
+static void gen_pcaddu12i(DisasContext *ctx, TCGv dest, target_long si20)
+{
+ target_ulong addr = ctx->base.pc_next + (si20 << 12);
+ tcg_gen_movi_tl(dest, addr);
+}
+
+static void gen_pcaddu18i(DisasContext *ctx, TCGv dest, target_long si20)
+{
+ target_ulong addr = ctx->base.pc_next + ((target_ulong)(si20) << 18);
+ tcg_gen_movi_tl(dest, addr);
+}
+
+static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ tcg_gen_addi_tl(dest, src1, a->si16 << 16);
+ return true;
+}
+
+TRANS(add_w, gen_r3, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_add_tl)
+TRANS(add_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_add_tl)
+TRANS(sub_w, gen_r3, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_sub_tl)
+TRANS(sub_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_sub_tl)
+TRANS(and, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_and_tl)
+TRANS(or, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_or_tl)
+TRANS(xor, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_xor_tl)
+TRANS(nor, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_nor_tl)
+TRANS(andn, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_andc_tl)
+TRANS(orn, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_orc_tl)
+TRANS(slt, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_slt)
+TRANS(sltu, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_sltu)
+TRANS(mul_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_SIGN, tcg_gen_mul_tl)
+TRANS(mul_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_mul_tl)
+TRANS(mulh_w, gen_mulh, tcg_gen_muls2_i32)
+TRANS(mulh_wu, gen_mulh, tcg_gen_mulu2_i32)
+TRANS(mulh_d, gen_mulh_d, tcg_gen_muls2_tl)
+TRANS(mulh_du, gen_mulh_d, tcg_gen_mulu2_tl)
+TRANS(mulw_d_w, gen_mulw_d, tcg_gen_ext32s_tl)
+TRANS(mulw_d_wu, gen_mulw_d, tcg_gen_ext32u_tl)
+TRANS(div_w, gen_div_w, EXT_SIGN, EXT_SIGN, tcg_gen_div_tl)
+TRANS(mod_w, gen_div_w, EXT_SIGN, EXT_SIGN, tcg_gen_rem_tl)
+TRANS(div_wu, gen_div_wu, EXT_ZERO, EXT_SIGN, tcg_gen_divu_tl)
+TRANS(mod_wu, gen_div_wu, EXT_ZERO, EXT_SIGN, tcg_gen_remu_tl)
+TRANS(div_d, gen_div_d, tcg_gen_div_tl)
+TRANS(mod_d, gen_div_d, tcg_gen_rem_tl)
+TRANS(div_du, gen_div_du, tcg_gen_divu_tl)
+TRANS(mod_du, gen_div_du, tcg_gen_remu_tl)
+TRANS(slti, gen_r2_si12, EXT_NONE, EXT_NONE, gen_slt)
+TRANS(sltui, gen_r2_si12, EXT_NONE, EXT_NONE, gen_sltu)
+TRANS(addi_w, gen_r2_si12, EXT_NONE, EXT_SIGN, tcg_gen_add_tl)
+TRANS(addi_d, gen_r2_si12, EXT_NONE, EXT_NONE, tcg_gen_add_tl)
+TRANS(alsl_w, gen_r3_sa2, EXT_NONE, EXT_SIGN, gen_alsl_w)
+TRANS(alsl_wu, gen_r3_sa2, EXT_NONE, EXT_ZERO, gen_alsl_wu)
+TRANS(alsl_d, gen_r3_sa2, 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_r2_ui12, tcg_gen_andi_tl)
+TRANS(ori, gen_r2_ui12, tcg_gen_ori_tl)
+TRANS(xori, gen_r2_ui12, tcg_gen_xori_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
new file mode 100644
index 0000000..1e0b755
--- /dev/null
+++ b/target/loongarch/insns.decode
@@ -0,0 +1,89 @@
+#
+# LoongArch instruction decode definitions.
+#
+# Copyright (c) 2021 Loongson Technology Corporation Limited
+#
+# SPDX-License-Identifier: LGPL-2.1+
+#
+
+#
+# Fields
+#
+%rd 0:5
+%rj 5:5
+%rk 10:5
+%sa2 15:2
+%si12 10:s12
+%ui12 10:12
+%si16 10:s16
+%si20 5:s20
+
+#
+# Argument sets
+#
+&fmt_rdrjrk rd rj rk
+&fmt_rdrjsi12 rd rj si12
+&fmt_rdrjrksa2 rd rj rk sa2
+&fmt_rdrjsi16 rd rj si16
+&fmt_rdrjui12 rd rj ui12
+&fmt_rdsi20 rd si20
+
+#
+# Formats
+#
+@fmt_rdrjrk .... ........ ..... ..... ..... ..... &fmt_rdrjrk %rd %rj %rk
+@fmt_rdrjsi12 .... ...... ............ ..... ..... &fmt_rdrjsi12 %rd %rj %si12
+@fmt_rdrjui12 .... ...... ............ ..... ..... &fmt_rdrjui12 %rd %rj %ui12
+@fmt_rdrjrksa2 .... ........ ... .. ..... ..... ..... &fmt_rdrjrksa2 %rd %rj %rk %sa2
+@fmt_rdrjsi16 .... .. ................ ..... ..... &fmt_rdrjsi16 %rd %rj %si16
+@fmt_rdsi20 .... ... .................... ..... &fmt_rdsi20 %rd %si20
+
+#
+# Fixed point arithmetic operation instruction
+#
+add_w 0000 00000001 00000 ..... ..... ..... @fmt_rdrjrk
+add_d 0000 00000001 00001 ..... ..... ..... @fmt_rdrjrk
+sub_w 0000 00000001 00010 ..... ..... ..... @fmt_rdrjrk
+sub_d 0000 00000001 00011 ..... ..... ..... @fmt_rdrjrk
+slt 0000 00000001 00100 ..... ..... ..... @fmt_rdrjrk
+sltu 0000 00000001 00101 ..... ..... ..... @fmt_rdrjrk
+slti 0000 001000 ............ ..... ..... @fmt_rdrjsi12
+sltui 0000 001001 ............ ..... ..... @fmt_rdrjsi12
+nor 0000 00000001 01000 ..... ..... ..... @fmt_rdrjrk
+and 0000 00000001 01001 ..... ..... ..... @fmt_rdrjrk
+or 0000 00000001 01010 ..... ..... ..... @fmt_rdrjrk
+xor 0000 00000001 01011 ..... ..... ..... @fmt_rdrjrk
+orn 0000 00000001 01100 ..... ..... ..... @fmt_rdrjrk
+andn 0000 00000001 01101 ..... ..... ..... @fmt_rdrjrk
+mul_w 0000 00000001 11000 ..... ..... ..... @fmt_rdrjrk
+mulh_w 0000 00000001 11001 ..... ..... ..... @fmt_rdrjrk
+mulh_wu 0000 00000001 11010 ..... ..... ..... @fmt_rdrjrk
+mul_d 0000 00000001 11011 ..... ..... ..... @fmt_rdrjrk
+mulh_d 0000 00000001 11100 ..... ..... ..... @fmt_rdrjrk
+mulh_du 0000 00000001 11101 ..... ..... ..... @fmt_rdrjrk
+mulw_d_w 0000 00000001 11110 ..... ..... ..... @fmt_rdrjrk
+mulw_d_wu 0000 00000001 11111 ..... ..... ..... @fmt_rdrjrk
+div_w 0000 00000010 00000 ..... ..... ..... @fmt_rdrjrk
+mod_w 0000 00000010 00001 ..... ..... ..... @fmt_rdrjrk
+div_wu 0000 00000010 00010 ..... ..... ..... @fmt_rdrjrk
+mod_wu 0000 00000010 00011 ..... ..... ..... @fmt_rdrjrk
+div_d 0000 00000010 00100 ..... ..... ..... @fmt_rdrjrk
+mod_d 0000 00000010 00101 ..... ..... ..... @fmt_rdrjrk
+div_du 0000 00000010 00110 ..... ..... ..... @fmt_rdrjrk
+mod_du 0000 00000010 00111 ..... ..... ..... @fmt_rdrjrk
+alsl_w 0000 00000000 010 .. ..... ..... ..... @fmt_rdrjrksa2
+alsl_wu 0000 00000000 011 .. ..... ..... ..... @fmt_rdrjrksa2
+alsl_d 0000 00000010 110 .. ..... ..... ..... @fmt_rdrjrksa2
+lu12i_w 0001 010 .................... ..... @fmt_rdsi20
+lu32i_d 0001 011 .................... ..... @fmt_rdsi20
+lu52i_d 0000 001100 ............ ..... ..... @fmt_rdrjsi12
+pcaddi 0001 100 .................... ..... @fmt_rdsi20
+pcalau12i 0001 101 .................... ..... @fmt_rdsi20
+pcaddu12i 0001 110 .................... ..... @fmt_rdsi20
+pcaddu18i 0001 111 .................... ..... @fmt_rdsi20
+addi_w 0000 001010 ............ ..... ..... @fmt_rdrjsi12
+addi_d 0000 001011 ............ ..... ..... @fmt_rdrjsi12
+addu16i_d 0001 00 ................ ..... ..... @fmt_rdrjsi16
+andi 0000 001101 ............ ..... ..... @fmt_rdrjui12
+ori 0000 001110 ............ ..... ..... @fmt_rdrjui12
+xori 0000 001111 ............ ..... ..... @fmt_rdrjui12
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index cfb08df..1052cb6 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -9,7 +9,6 @@
#ifndef LOONGARCH_INTERNALS_H
#define LOONGARCH_INTERNALS_H
-
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 4769004..e34ab39 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -34,11 +34,6 @@ void generate_exception(DisasContext *ctx, int excp)
ctx->base.is_jmp = DISAS_NORETURN;
}
-static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
-{
- return true;
-}
-
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
{
if (translator_use_goto_tb(&ctx->base, dest)) {
@@ -63,6 +58,12 @@ 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->dst_ext = EXT_NONE;
+ 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)
@@ -76,6 +77,92 @@ 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 ext)
+{
+ TCGv t;
+
+ if (reg_num == 0) {
+ return ctx->zero;
+ }
+
+ switch (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)
+{
+ if (reg_num == 0 || ctx->dst_ext) {
+ return temp_new(ctx);
+ }
+ return cpu_gpr[reg_num];
+}
+
+static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t)
+{
+ if (reg_num != 0) {
+ switch (ctx->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"
+
+/* fmt rd rj rk */
+static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a,
+ DisasExtend src1_ext, DisasExtend src2_ext,
+ DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv))
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, src1_ext);
+ TCGv src2 = gpr_src(ctx, a->rk, src2_ext);
+
+ func(dest, src1, src2);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ return true;
+}
+
+#include "insn_trans/trans_arith.c"
+
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
CPULoongArchState *env = cs->env_ptr;
@@ -89,6 +176,14 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
generate_exception(ctx, EXCP_INE);
}
+ ctx->dst_ext = EXT_NONE;
+
+ 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 dff7d79..f064fdd 100644
--- a/target/loongarch/translate.h
+++ b/target/loongarch/translate.h
@@ -11,11 +11,31 @@
#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;
+ DisasExtend dst_ext;
+ /* 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] 46+ messages in thread
* [PATCH v4 05/21] target/loongarch: Add fixed point shift instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (3 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-04 11:17 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 06/21] target/loongarch: Add fixed point bit " Song Gao
` (15 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement fixed point shift instruction translation.
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>
---
target/loongarch/insn_trans/trans_shift.c | 154 ++++++++++++++++++++++++++++++
target/loongarch/insns.decode | 26 +++++
target/loongarch/translate.c | 1 +
3 files changed, 181 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_shift.c
diff --git a/target/loongarch/insn_trans/trans_shift.c b/target/loongarch/insn_trans/trans_shift.c
new file mode 100644
index 0000000..5fa1162
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_shift.c
@@ -0,0 +1,154 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+static bool gen_r2_ui5(DisasContext *ctx, arg_slli_w *a,
+ void(*func)(TCGv, TCGv, TCGv))
+{
+ ctx->dst_ext = EXT_SIGN;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
+ TCGv src2 = tcg_constant_tl(a->ui5);
+
+ TCGv t0 = temp_new(ctx);
+
+ tcg_gen_andi_tl(t0, src2, 0x1f);
+ func(dest, src1, t0);
+ gen_set_gpr(ctx, a->rd, dest);
+
+ return true;
+}
+
+static bool gen_r2_ui6(DisasContext *ctx, arg_slli_d *a,
+ void(*func)(TCGv, TCGv, TCGv))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = tcg_constant_tl(a->ui6);
+
+ TCGv t0 = temp_new(ctx);
+
+ tcg_gen_andi_tl(t0, src2, 0x7f);
+ func(dest, src1, t0);
+
+ 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 void gen_rotri_w(TCGv dest, TCGv src1, TCGv src2)
+{
+ TCGv_i32 t1 = tcg_temp_new_i32();
+ TCGv_i32 t2 = tcg_temp_new_i32();
+
+ tcg_gen_trunc_tl_i32(t1, src1);
+ tcg_gen_trunc_tl_i32(t2, src2);
+ tcg_gen_rotr_i32(t1, t1, t2);
+ tcg_gen_ext_i32_tl(dest, t1);
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+}
+
+static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
+
+ tcg_gen_sextract_tl(dest, src1, a->ui5, 32 - a->ui5);
+ return true;
+}
+
+TRANS(sll_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sll_w)
+TRANS(srl_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_srl_w)
+TRANS(sra_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sra_w)
+TRANS(sll_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d)
+TRANS(srl_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d)
+TRANS(sra_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d)
+TRANS(rotr_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w)
+TRANS(rotr_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d)
+TRANS(slli_w, gen_r2_ui5, tcg_gen_shl_tl)
+TRANS(slli_d, gen_r2_ui6, tcg_gen_shl_tl)
+TRANS(srli_w, gen_r2_ui5, tcg_gen_shr_tl)
+TRANS(srli_d, gen_r2_ui6, tcg_gen_shr_tl)
+TRANS(srai_d, gen_r2_ui6, tcg_gen_sar_tl)
+TRANS(rotri_w, gen_r2_ui5, gen_rotri_w)
+TRANS(rotri_d, gen_r2_ui6, tcg_gen_rotr_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 1e0b755..9302576 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -17,6 +17,8 @@
%ui12 10:12
%si16 10:s16
%si20 5:s20
+%ui5 10:5
+%ui6 10:6
#
# Argument sets
@@ -27,6 +29,8 @@
&fmt_rdrjsi16 rd rj si16
&fmt_rdrjui12 rd rj ui12
&fmt_rdsi20 rd si20
+&fmt_rdrjui5 rd rj ui5
+&fmt_rdrjui6 rd rj ui6
#
# Formats
@@ -37,6 +41,8 @@
@fmt_rdrjrksa2 .... ........ ... .. ..... ..... ..... &fmt_rdrjrksa2 %rd %rj %rk %sa2
@fmt_rdrjsi16 .... .. ................ ..... ..... &fmt_rdrjsi16 %rd %rj %si16
@fmt_rdsi20 .... ... .................... ..... &fmt_rdsi20 %rd %si20
+@fmt_rdrjui5 .... ........ ..... ..... ..... ..... &fmt_rdrjui5 %rd %rj %ui5
+@fmt_rdrjui6 .... ........ .... ...... ..... ..... &fmt_rdrjui6 %rd %rj %ui6
#
# Fixed point arithmetic operation instruction
@@ -87,3 +93,23 @@ addu16i_d 0001 00 ................ ..... ..... @fmt_rdrjsi16
andi 0000 001101 ............ ..... ..... @fmt_rdrjui12
ori 0000 001110 ............ ..... ..... @fmt_rdrjui12
xori 0000 001111 ............ ..... ..... @fmt_rdrjui12
+
+#
+# Fixed point shift operation instruction
+#
+sll_w 0000 00000001 01110 ..... ..... ..... @fmt_rdrjrk
+srl_w 0000 00000001 01111 ..... ..... ..... @fmt_rdrjrk
+sra_w 0000 00000001 10000 ..... ..... ..... @fmt_rdrjrk
+sll_d 0000 00000001 10001 ..... ..... ..... @fmt_rdrjrk
+srl_d 0000 00000001 10010 ..... ..... ..... @fmt_rdrjrk
+sra_d 0000 00000001 10011 ..... ..... ..... @fmt_rdrjrk
+rotr_w 0000 00000001 10110 ..... ..... ..... @fmt_rdrjrk
+rotr_d 0000 00000001 10111 ..... ..... ..... @fmt_rdrjrk
+slli_w 0000 00000100 00001 ..... ..... ..... @fmt_rdrjui5
+slli_d 0000 00000100 0001 ...... ..... ..... @fmt_rdrjui6
+srli_w 0000 00000100 01001 ..... ..... ..... @fmt_rdrjui5
+srli_d 0000 00000100 0101 ...... ..... ..... @fmt_rdrjui6
+srai_w 0000 00000100 10001 ..... ..... ..... @fmt_rdrjui5
+srai_d 0000 00000100 1001 ...... ..... ..... @fmt_rdrjui6
+rotri_w 0000 00000100 11001 ..... ..... ..... @fmt_rdrjui5
+rotri_d 0000 00000100 1101 ...... ..... ..... @fmt_rdrjui6
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index e34ab39..8d3b96c 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -162,6 +162,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a,
}
#include "insn_trans/trans_arith.c"
+#include "insn_trans/trans_shift.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 06/21] target/loongarch: Add fixed point bit instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (4 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 05/21] target/loongarch: Add fixed point shift " Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-04 12:57 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 07/21] target/loongarch: Add fixed point load/store " Song Gao
` (14 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement fixed point bit instruction translation.
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>
---
target/loongarch/helper.h | 4 +
target/loongarch/insn_trans/trans_bit.c | 269 ++++++++++++++++++++++++++++++++
target/loongarch/insns.decode | 45 ++++++
target/loongarch/op_helper.c | 22 +++
target/loongarch/translate.c | 1 +
5 files changed, 341 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_bit.c
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 09bfcfd..e39574e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -7,3 +7,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 b/target/loongarch/insn_trans/trans_bit.c
new file mode 100644
index 0000000..cf472e55
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_bit.c
@@ -0,0 +1,269 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+/* fmt rd rj */
+static bool gen_r2(DisasContext *ctx, arg_fmt_rdrj *a,
+ DisasExtend src_ext, DisasExtend dst_ext,
+ void (*func)(TCGv, TCGv))
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+ func(dest, src1);
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ return true;
+}
+
+static bool trans_bytepick_w(DisasContext *ctx, arg_bytepick_w *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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->sa2) * 8), 32);
+
+ return true;
+}
+
+static bool trans_bytepick_d(DisasContext *ctx, arg_bytepick_d *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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->sa3) * 8));
+ return true;
+}
+
+static bool trans_bstrins_w(DisasContext *ctx, arg_bstrins_w *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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);
+ 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);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if ((a->lsbw > a->msbw) || (a->msbw > 31)) {
+ 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);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if ((a->lsbd > a->msbd) || (a->msbd > 63)) {
+ 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);
+ 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, 64);
+}
+
+static void gen_cto_w(TCGv dest, TCGv src1)
+{
+ tcg_gen_not_tl(dest, src1);
+ gen_ctz_w(dest, dest);
+}
+
+static void gen_clz_d(TCGv dest, TCGv src1)
+{
+ tcg_gen_clzi_i64(dest, src1, TARGET_LONG_BITS);
+}
+
+static void gen_clo_d(TCGv dest, TCGv src1)
+{
+ tcg_gen_not_tl(dest, src1);
+ gen_clz_d(dest, dest);
+}
+
+static void gen_ctz_d(TCGv dest, TCGv src1)
+{
+ tcg_gen_ctzi_tl(dest, src1, TARGET_LONG_BITS);
+}
+
+static void gen_cto_d(TCGv dest, TCGv src1)
+{
+ tcg_gen_not_tl(dest, src1);
+ gen_ctz_d(dest, dest);
+}
+
+static void gen_revb_2w(TCGv dest, TCGv src1)
+{
+ tcg_gen_bswap64_i64(dest, src1);
+ tcg_gen_rotri_i64(dest, dest, 32);
+}
+
+static bool trans_revb_2h(DisasContext *ctx, arg_revb_2h *a)
+{
+ ctx->dst_ext = EXT_SIGN;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ 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);
+ gen_set_gpr(ctx, a->rd, dest);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ return true;
+}
+
+static bool trans_revb_4h(DisasContext *ctx, arg_revb_4h *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ 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);
+ return true;
+}
+
+static bool trans_revh_2w(DisasContext *ctx, arg_revh_2w *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ 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);
+
+ return true;
+}
+
+static bool trans_revh_d(DisasContext *ctx, arg_revh_d *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ 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_shri_tl(t1, t0, 32);
+ tcg_gen_shli_tl(t0, t0, 32);
+ tcg_gen_or_tl(dest, t0, t1);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+
+ return true;
+}
+
+static void gen_maskeqz(TCGv dest, TCGv src1, TCGv src2)
+{
+ TCGv cond1 = tcg_constant_tl(0);
+
+ tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, cond1, cond1, src1);
+}
+
+static void gen_masknez(TCGv dest, TCGv src1, TCGv src2)
+{
+ TCGv cond1 = tcg_constant_tl(0);
+
+ tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, cond1, cond1, src1);
+}
+
+TRANS(ext_w_h, gen_r2, EXT_NONE, EXT_NONE, tcg_gen_ext16s_tl)
+TRANS(ext_w_b, gen_r2, EXT_NONE, EXT_NONE, tcg_gen_ext8s_tl)
+TRANS(clo_w, gen_r2, EXT_NONE, EXT_NONE, gen_clo_w)
+TRANS(clz_w, gen_r2, EXT_ZERO, EXT_NONE, gen_clz_w)
+TRANS(cto_w, gen_r2, EXT_NONE, EXT_NONE, gen_cto_w)
+TRANS(ctz_w, gen_r2, EXT_NONE, EXT_NONE, gen_ctz_w)
+TRANS(clo_d, gen_r2, EXT_NONE, EXT_NONE, gen_clo_d)
+TRANS(clz_d, gen_r2, EXT_NONE, EXT_NONE, gen_clz_d)
+TRANS(cto_d, gen_r2, EXT_NONE, EXT_NONE, gen_cto_d)
+TRANS(ctz_d, gen_r2, EXT_NONE, EXT_NONE, gen_ctz_d)
+TRANS(revb_2w, gen_r2, EXT_NONE, EXT_NONE, gen_revb_2w)
+TRANS(revb_d, gen_r2, EXT_NONE, EXT_NONE, tcg_gen_bswap64_i64)
+TRANS(bitrev_4b, gen_r2, EXT_ZERO, EXT_SIGN, gen_helper_bitswap)
+TRANS(bitrev_8b, gen_r2, EXT_NONE, EXT_NONE, gen_helper_bitswap)
+TRANS(bitrev_w, gen_r2, EXT_NONE, EXT_SIGN, gen_helper_bitrev_w)
+TRANS(bitrev_d, gen_r2, EXT_NONE, EXT_NONE, gen_helper_bitrev_d)
+TRANS(maskeqz, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_maskeqz)
+TRANS(masknez, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_masknez)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 9302576..ec599a9 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -13,12 +13,17 @@
%rj 5:5
%rk 10:5
%sa2 15:2
+%sa3 15:3
%si12 10:s12
%ui12 10:12
%si16 10:s16
%si20 5:s20
%ui5 10:5
%ui6 10:6
+%msbw 16:5
+%lsbw 10:5
+%msbd 16:6
+%lsbd 10:6
#
# Argument sets
@@ -31,6 +36,10 @@
&fmt_rdsi20 rd si20
&fmt_rdrjui5 rd rj ui5
&fmt_rdrjui6 rd rj ui6
+&fmt_rdrj rd rj
+&fmt_rdrjrksa3 rd rj rk sa3
+&fmt_rdrjmsbwlsbw rd rj msbw lsbw
+&fmt_rdrjmsbdlsbd rd rj msbd lsbd
#
# Formats
@@ -43,6 +52,10 @@
@fmt_rdsi20 .... ... .................... ..... &fmt_rdsi20 %rd %si20
@fmt_rdrjui5 .... ........ ..... ..... ..... ..... &fmt_rdrjui5 %rd %rj %ui5
@fmt_rdrjui6 .... ........ .... ...... ..... ..... &fmt_rdrjui6 %rd %rj %ui6
+@fmt_rdrj .... ........ ..... ..... ..... ..... &fmt_rdrj %rd %rj
+@fmt_rdrjmsbwlsbw .... ....... ..... . ..... ..... ..... &fmt_rdrjmsbwlsbw %rd %rj %msbw %lsbw
+@fmt_rdrjmsbdlsbd .... ...... ...... ...... ..... ..... &fmt_rdrjmsbdlsbd %rd %rj %msbd %lsbd
+@fmt_rdrjrksa3 .... ........ .. ... ..... ..... ..... &fmt_rdrjrksa3 %rd %rj %rk %sa3
#
# Fixed point arithmetic operation instruction
@@ -113,3 +126,35 @@ srai_w 0000 00000100 10001 ..... ..... ..... @fmt_rdrjui5
srai_d 0000 00000100 1001 ...... ..... ..... @fmt_rdrjui6
rotri_w 0000 00000100 11001 ..... ..... ..... @fmt_rdrjui5
rotri_d 0000 00000100 1101 ...... ..... ..... @fmt_rdrjui6
+
+#
+# Fixed point bit operation instruction
+#
+ext_w_h 0000 00000000 00000 10110 ..... ..... @fmt_rdrj
+ext_w_b 0000 00000000 00000 10111 ..... ..... @fmt_rdrj
+clo_w 0000 00000000 00000 00100 ..... ..... @fmt_rdrj
+clz_w 0000 00000000 00000 00101 ..... ..... @fmt_rdrj
+cto_w 0000 00000000 00000 00110 ..... ..... @fmt_rdrj
+ctz_w 0000 00000000 00000 00111 ..... ..... @fmt_rdrj
+clo_d 0000 00000000 00000 01000 ..... ..... @fmt_rdrj
+clz_d 0000 00000000 00000 01001 ..... ..... @fmt_rdrj
+cto_d 0000 00000000 00000 01010 ..... ..... @fmt_rdrj
+ctz_d 0000 00000000 00000 01011 ..... ..... @fmt_rdrj
+revb_2h 0000 00000000 00000 01100 ..... ..... @fmt_rdrj
+revb_4h 0000 00000000 00000 01101 ..... ..... @fmt_rdrj
+revb_2w 0000 00000000 00000 01110 ..... ..... @fmt_rdrj
+revb_d 0000 00000000 00000 01111 ..... ..... @fmt_rdrj
+revh_2w 0000 00000000 00000 10000 ..... ..... @fmt_rdrj
+revh_d 0000 00000000 00000 10001 ..... ..... @fmt_rdrj
+bitrev_4b 0000 00000000 00000 10010 ..... ..... @fmt_rdrj
+bitrev_8b 0000 00000000 00000 10011 ..... ..... @fmt_rdrj
+bitrev_w 0000 00000000 00000 10100 ..... ..... @fmt_rdrj
+bitrev_d 0000 00000000 00000 10101 ..... ..... @fmt_rdrj
+bytepick_w 0000 00000000 100 .. ..... ..... ..... @fmt_rdrjrksa2
+bytepick_d 0000 00000000 11 ... ..... ..... ..... @fmt_rdrjrksa3
+maskeqz 0000 00000001 00110 ..... ..... ..... @fmt_rdrjrk
+masknez 0000 00000001 00111 ..... ..... ..... @fmt_rdrjrk
+bstrins_w 0000 0000011 ..... 0 ..... ..... ..... @fmt_rdrjmsbwlsbw
+bstrpick_w 0000 0000011 ..... 1 ..... ..... ..... @fmt_rdrjmsbwlsbw
+bstrins_d 0000 000010 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd
+bstrpick_d 0000 000011 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 4d10b03..ec04369 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -20,3 +20,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 8d3b96c..4ed3d3b 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -163,6 +163,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a,
#include "insn_trans/trans_arith.c"
#include "insn_trans/trans_shift.c"
+#include "insn_trans/trans_bit.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 07/21] target/loongarch: Add fixed point load/store instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (5 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 06/21] target/loongarch: Add fixed point bit " Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-04 13:03 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 08/21] target/loongarch: Add fixed point atomic " Song Gao
` (13 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement fixed point load/store instruction translation.
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>
---
target/loongarch/helper.h | 3 +
target/loongarch/insn_trans/trans_memory.c | 263 +++++++++++++++++++++++++++++
target/loongarch/insns.decode | 58 +++++++
target/loongarch/op_helper.c | 15 ++
target/loongarch/translate.c | 30 ++++
5 files changed, 369 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_memory.c
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index e39574e..09b5a3d 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -11,3 +11,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 b/target/loongarch/insn_trans/trans_memory.c
new file mode 100644
index 0000000..afc5d67
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_memory.c
@@ -0,0 +1,263 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+static bool gen_load(DisasContext *ctx, arg_fmt_rdrjsi12 *a,
+ DisasExtend dst_ext, MemOp mop)
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv temp = NULL;
+
+ if (a->si12) {
+ temp = tcg_temp_new();
+ tcg_gen_addi_tl(temp, addr, a->si12);
+ addr = temp;
+ }
+
+ tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+
+ if (temp) {
+ tcg_temp_free(temp);
+ }
+ return true;
+}
+
+static bool gen_store(DisasContext *ctx, arg_fmt_rdrjsi12 *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->si12) {
+ temp = tcg_temp_new();
+ tcg_gen_addi_tl(temp, addr, a->si12);
+ 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_fmt_rdrjrk *a,
+ DisasExtend dst_ext, MemOp mop)
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_storex(DisasContext *ctx, arg_fmt_rdrjrk *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_fmt_rdrjrk *a,
+ DisasExtend dst_ext, MemOp mop)
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_load_le(DisasContext *ctx, arg_fmt_rdrjrk *a,
+ DisasExtend dst_ext, MemOp mop)
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_store_gt(DisasContext *ctx, arg_fmt_rdrjrk *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_fmt_rdrjrk *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->whint);
+ 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_fmt_rdrjsi14 *a,
+ DisasExtend dst_ext, MemOp mop)
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv temp = NULL;
+
+ if (a->si14) {
+ temp = tcg_temp_new();
+ tcg_gen_addi_tl(temp, addr, a->si14 << 2);
+ addr = temp;
+ }
+
+ tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+
+ if (temp) {
+ tcg_temp_free(temp);
+ }
+ return true;
+}
+
+static bool gen_stptr(DisasContext *ctx, arg_fmt_rdrjsi14 *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->si14) {
+ temp = tcg_temp_new();
+ tcg_gen_addi_tl(temp, addr, a->si14 << 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, EXT_SIGN, MO_SB)
+TRANS(ld_h, gen_load, EXT_SIGN, MO_TESW)
+TRANS(ld_w, gen_load, EXT_SIGN, MO_TESL)
+TRANS(ld_d, gen_load, EXT_NONE, 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, EXT_ZERO, MO_UB)
+TRANS(ld_hu, gen_load, EXT_ZERO, MO_TEUW)
+TRANS(ld_wu, gen_load, EXT_ZERO, MO_TEUL)
+TRANS(ldx_b, gen_loadx, EXT_SIGN, MO_SB)
+TRANS(ldx_h, gen_loadx, EXT_SIGN, MO_TESW)
+TRANS(ldx_w, gen_loadx, EXT_SIGN, MO_TESL)
+TRANS(ldx_d, gen_loadx, EXT_NONE, 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, EXT_ZERO, MO_UB)
+TRANS(ldx_hu, gen_loadx, EXT_ZERO, MO_TEUW)
+TRANS(ldx_wu, gen_loadx, EXT_ZERO, MO_TEUL)
+TRANS(ldptr_w, gen_ldptr, EXT_SIGN, MO_TESL)
+TRANS(stptr_w, gen_stptr, MO_TESL)
+TRANS(ldptr_d, gen_ldptr, EXT_NONE, MO_TEQ)
+TRANS(stptr_d, gen_stptr, MO_TEQ)
+TRANS(ldgt_b, gen_load_gt, EXT_SIGN, MO_SB)
+TRANS(ldgt_h, gen_load_gt, EXT_SIGN, MO_TESW)
+TRANS(ldgt_w, gen_load_gt, EXT_SIGN, MO_TESL)
+TRANS(ldgt_d, gen_load_gt, EXT_NONE, MO_TEQ)
+TRANS(ldle_b, gen_load_le, EXT_SIGN, MO_SB)
+TRANS(ldle_h, gen_load_le, EXT_SIGN, MO_TESW)
+TRANS(ldle_w, gen_load_le, EXT_SIGN, MO_TESL)
+TRANS(ldle_d, gen_load_le, EXT_NONE, 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 ec599a9..08fd232 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -24,6 +24,9 @@
%lsbw 10:5
%msbd 16:6
%lsbd 10:6
+%si14 10:s14
+%hint 0:5
+%whint 0:15
#
# Argument sets
@@ -40,6 +43,9 @@
&fmt_rdrjrksa3 rd rj rk sa3
&fmt_rdrjmsbwlsbw rd rj msbw lsbw
&fmt_rdrjmsbdlsbd rd rj msbd lsbd
+&fmt_rdrjsi14 rd rj si14
+&fmt_hintrjsi12 hint rj si12
+&fmt_whint whint
#
# Formats
@@ -56,6 +62,9 @@
@fmt_rdrjmsbwlsbw .... ....... ..... . ..... ..... ..... &fmt_rdrjmsbwlsbw %rd %rj %msbw %lsbw
@fmt_rdrjmsbdlsbd .... ...... ...... ...... ..... ..... &fmt_rdrjmsbdlsbd %rd %rj %msbd %lsbd
@fmt_rdrjrksa3 .... ........ .. ... ..... ..... ..... &fmt_rdrjrksa3 %rd %rj %rk %sa3
+@fmt_hintrjsi12 .... ...... ............ ..... ..... &fmt_hintrjsi12 %hint %rj %si12
+@fmt_whint .... ........ ..... ............... &fmt_whint %whint
+@fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14
#
# Fixed point arithmetic operation instruction
@@ -158,3 +167,52 @@ bstrins_w 0000 0000011 ..... 0 ..... ..... ..... @fmt_rdrjmsbwlsbw
bstrpick_w 0000 0000011 ..... 1 ..... ..... ..... @fmt_rdrjmsbwlsbw
bstrins_d 0000 000010 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd
bstrpick_d 0000 000011 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd
+
+#
+# Fixed point load/store instruction
+#
+ld_b 0010 100000 ............ ..... ..... @fmt_rdrjsi12
+ld_h 0010 100001 ............ ..... ..... @fmt_rdrjsi12
+ld_w 0010 100010 ............ ..... ..... @fmt_rdrjsi12
+ld_d 0010 100011 ............ ..... ..... @fmt_rdrjsi12
+st_b 0010 100100 ............ ..... ..... @fmt_rdrjsi12
+st_h 0010 100101 ............ ..... ..... @fmt_rdrjsi12
+st_w 0010 100110 ............ ..... ..... @fmt_rdrjsi12
+st_d 0010 100111 ............ ..... ..... @fmt_rdrjsi12
+ld_bu 0010 101000 ............ ..... ..... @fmt_rdrjsi12
+ld_hu 0010 101001 ............ ..... ..... @fmt_rdrjsi12
+ld_wu 0010 101010 ............ ..... ..... @fmt_rdrjsi12
+ldx_b 0011 10000000 00000 ..... ..... ..... @fmt_rdrjrk
+ldx_h 0011 10000000 01000 ..... ..... ..... @fmt_rdrjrk
+ldx_w 0011 10000000 10000 ..... ..... ..... @fmt_rdrjrk
+ldx_d 0011 10000000 11000 ..... ..... ..... @fmt_rdrjrk
+stx_b 0011 10000001 00000 ..... ..... ..... @fmt_rdrjrk
+stx_h 0011 10000001 01000 ..... ..... ..... @fmt_rdrjrk
+stx_w 0011 10000001 10000 ..... ..... ..... @fmt_rdrjrk
+stx_d 0011 10000001 11000 ..... ..... ..... @fmt_rdrjrk
+ldx_bu 0011 10000010 00000 ..... ..... ..... @fmt_rdrjrk
+ldx_hu 0011 10000010 01000 ..... ..... ..... @fmt_rdrjrk
+ldx_wu 0011 10000010 10000 ..... ..... ..... @fmt_rdrjrk
+preld 0010 101011 ............ ..... ..... @fmt_hintrjsi12
+dbar 0011 10000111 00100 ............... @fmt_whint
+ibar 0011 10000111 00101 ............... @fmt_whint
+ldptr_w 0010 0100 .............. ..... ..... @fmt_rdrjsi14
+stptr_w 0010 0101 .............. ..... ..... @fmt_rdrjsi14
+ldptr_d 0010 0110 .............. ..... ..... @fmt_rdrjsi14
+stptr_d 0010 0111 .............. ..... ..... @fmt_rdrjsi14
+ldgt_b 0011 10000111 10000 ..... ..... ..... @fmt_rdrjrk
+ldgt_h 0011 10000111 10001 ..... ..... ..... @fmt_rdrjrk
+ldgt_w 0011 10000111 10010 ..... ..... ..... @fmt_rdrjrk
+ldgt_d 0011 10000111 10011 ..... ..... ..... @fmt_rdrjrk
+ldle_b 0011 10000111 10100 ..... ..... ..... @fmt_rdrjrk
+ldle_h 0011 10000111 10101 ..... ..... ..... @fmt_rdrjrk
+ldle_w 0011 10000111 10110 ..... ..... ..... @fmt_rdrjrk
+ldle_d 0011 10000111 10111 ..... ..... ..... @fmt_rdrjrk
+stgt_b 0011 10000111 11000 ..... ..... ..... @fmt_rdrjrk
+stgt_h 0011 10000111 11001 ..... ..... ..... @fmt_rdrjrk
+stgt_w 0011 10000111 11010 ..... ..... ..... @fmt_rdrjrk
+stgt_d 0011 10000111 11011 ..... ..... ..... @fmt_rdrjrk
+stle_b 0011 10000111 11100 ..... ..... ..... @fmt_rdrjrk
+stle_h 0011 10000111 11101 ..... ..... ..... @fmt_rdrjrk
+stle_w 0011 10000111 11110 ..... ..... ..... @fmt_rdrjrk
+stle_d 0011 10000111 11111 ..... ..... ..... @fmt_rdrjrk
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index ec04369..a4ffaf9 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -42,3 +42,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 4ed3d3b..b653a4d 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -66,6 +66,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)
{
}
@@ -164,6 +193,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a,
#include "insn_trans/trans_arith.c"
#include "insn_trans/trans_shift.c"
#include "insn_trans/trans_bit.c"
+#include "insn_trans/trans_memory.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 08/21] target/loongarch: Add fixed point atomic instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (6 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 07/21] target/loongarch: Add fixed point load/store " Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-04 13:14 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 09/21] target/loongarch: Add fixed point extra " Song Gao
` (12 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement fixed point atomic instruction translation.
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>
---
target/loongarch/insn_trans/trans_atomic.c | 134 +++++++++++++++++++++++++++++
target/loongarch/insns.decode | 44 ++++++++++
target/loongarch/translate.c | 1 +
3 files changed, 179 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_atomic.c
diff --git a/target/loongarch/insn_trans/trans_atomic.c b/target/loongarch/insn_trans/trans_atomic.c
new file mode 100644
index 0000000..3170346
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_atomic.c
@@ -0,0 +1,134 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+static bool gen_ll(DisasContext *ctx, arg_fmt_rdrjsi14 *a,
+ void (*func)(TCGv, TCGv, int))
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv t0 = tcg_temp_new();
+
+ tcg_gen_addi_tl(t0, src1, a->si14 << 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_fmt_rdrjsi14 *a, MemOp mop)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE);
+ TCGv t0 = tcg_temp_new();
+
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *done = gen_new_label();
+
+ tcg_gen_addi_tl(t0, src1, a->si14 << 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);
+ /* generate cmpxchg */
+ tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval,
+ src2, ctx->mem_idx, mop);
+ tcg_gen_setcond_tl(TCG_COND_EQ, dest, t0, cpu_llval);
+ gen_set_label(done);
+ tcg_temp_free(t0);
+ return true;
+}
+
+static bool gen_am(DisasContext *ctx, arg_fmt_rdrjrk *a, DisasExtend ext,
+ void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+ MemOp mop)
+{
+ ctx->dst_ext = ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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("%s: waring, register equal\n", __func__);
+ return false;
+ }
+
+ func(dest, addr, val, ctx->mem_idx, mop);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ return true;
+}
+
+static bool gen_am_db(DisasContext *ctx, arg_fmt_rdrjrk *a, DisasExtend ext,
+ void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+ MemOp mop)
+{
+ ctx->dst_ext = ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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("%s: waring, register equal\n", __func__);
+ return false;
+ }
+
+ gen_loongarch_sync(0x10);
+
+ func(dest, addr, val, ctx->mem_idx, mop);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ 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, EXT_SIGN, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_d, gen_am, EXT_NONE, tcg_gen_atomic_xchg_tl, MO_TEQ)
+TRANS(amadd_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_add_tl, MO_TEQ)
+TRANS(amand_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_and_tl, MO_TEQ)
+TRANS(amor_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_or_tl, MO_TEQ)
+TRANS(amxor_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
+TRANS(amxor_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_xor_tl, MO_TEQ)
+TRANS(ammax_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
+TRANS(ammax_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_smax_tl, MO_TEQ)
+TRANS(ammin_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
+TRANS(ammin_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_smin_tl, MO_TEQ)
+TRANS(ammax_wu, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
+TRANS(ammax_du, gen_am, EXT_NONE, tcg_gen_atomic_fetch_umax_tl, MO_TEQ)
+TRANS(ammin_wu, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
+TRANS(ammin_du, gen_am, EXT_NONE, tcg_gen_atomic_fetch_umin_tl, MO_TEQ)
+TRANS(amswap_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_xchg_tl, MO_TEQ)
+TRANS(amadd_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_add_tl, MO_TEQ)
+TRANS(amand_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_and_tl, MO_TEQ)
+TRANS(amor_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_or_tl, MO_TEQ)
+TRANS(amxor_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
+TRANS(amxor_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_xor_tl, MO_TEQ)
+TRANS(ammax_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
+TRANS(ammax_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_smax_tl, MO_TEQ)
+TRANS(ammin_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
+TRANS(ammin_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_smin_tl, MO_TEQ)
+TRANS(ammax_db_wu, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
+TRANS(ammax_db_du, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_umax_tl, MO_TEQ)
+TRANS(ammin_db_wu, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
+TRANS(ammin_db_du, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_umin_tl, MO_TEQ)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 08fd232..574c055 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -216,3 +216,47 @@ stle_b 0011 10000111 11100 ..... ..... ..... @fmt_rdrjrk
stle_h 0011 10000111 11101 ..... ..... ..... @fmt_rdrjrk
stle_w 0011 10000111 11110 ..... ..... ..... @fmt_rdrjrk
stle_d 0011 10000111 11111 ..... ..... ..... @fmt_rdrjrk
+
+#
+# Fixed point atomic instruction
+#
+ll_w 0010 0000 .............. ..... ..... @fmt_rdrjsi14
+sc_w 0010 0001 .............. ..... ..... @fmt_rdrjsi14
+ll_d 0010 0010 .............. ..... ..... @fmt_rdrjsi14
+sc_d 0010 0011 .............. ..... ..... @fmt_rdrjsi14
+amswap_w 0011 10000110 00000 ..... ..... ..... @fmt_rdrjrk
+amswap_d 0011 10000110 00001 ..... ..... ..... @fmt_rdrjrk
+amadd_w 0011 10000110 00010 ..... ..... ..... @fmt_rdrjrk
+amadd_d 0011 10000110 00011 ..... ..... ..... @fmt_rdrjrk
+amand_w 0011 10000110 00100 ..... ..... ..... @fmt_rdrjrk
+amand_d 0011 10000110 00101 ..... ..... ..... @fmt_rdrjrk
+amor_w 0011 10000110 00110 ..... ..... ..... @fmt_rdrjrk
+amor_d 0011 10000110 00111 ..... ..... ..... @fmt_rdrjrk
+amxor_w 0011 10000110 01000 ..... ..... ..... @fmt_rdrjrk
+amxor_d 0011 10000110 01001 ..... ..... ..... @fmt_rdrjrk
+ammax_w 0011 10000110 01010 ..... ..... ..... @fmt_rdrjrk
+ammax_d 0011 10000110 01011 ..... ..... ..... @fmt_rdrjrk
+ammin_w 0011 10000110 01100 ..... ..... ..... @fmt_rdrjrk
+ammin_d 0011 10000110 01101 ..... ..... ..... @fmt_rdrjrk
+ammax_wu 0011 10000110 01110 ..... ..... ..... @fmt_rdrjrk
+ammax_du 0011 10000110 01111 ..... ..... ..... @fmt_rdrjrk
+ammin_wu 0011 10000110 10000 ..... ..... ..... @fmt_rdrjrk
+ammin_du 0011 10000110 10001 ..... ..... ..... @fmt_rdrjrk
+amswap_db_w 0011 10000110 10010 ..... ..... ..... @fmt_rdrjrk
+amswap_db_d 0011 10000110 10011 ..... ..... ..... @fmt_rdrjrk
+amadd_db_w 0011 10000110 10100 ..... ..... ..... @fmt_rdrjrk
+amadd_db_d 0011 10000110 10101 ..... ..... ..... @fmt_rdrjrk
+amand_db_w 0011 10000110 10110 ..... ..... ..... @fmt_rdrjrk
+amand_db_d 0011 10000110 10111 ..... ..... ..... @fmt_rdrjrk
+amor_db_w 0011 10000110 11000 ..... ..... ..... @fmt_rdrjrk
+amor_db_d 0011 10000110 11001 ..... ..... ..... @fmt_rdrjrk
+amxor_db_w 0011 10000110 11010 ..... ..... ..... @fmt_rdrjrk
+amxor_db_d 0011 10000110 11011 ..... ..... ..... @fmt_rdrjrk
+ammax_db_w 0011 10000110 11100 ..... ..... ..... @fmt_rdrjrk
+ammax_db_d 0011 10000110 11101 ..... ..... ..... @fmt_rdrjrk
+ammin_db_w 0011 10000110 11110 ..... ..... ..... @fmt_rdrjrk
+ammin_db_d 0011 10000110 11111 ..... ..... ..... @fmt_rdrjrk
+ammax_db_wu 0011 10000111 00000 ..... ..... ..... @fmt_rdrjrk
+ammax_db_du 0011 10000111 00001 ..... ..... ..... @fmt_rdrjrk
+ammin_db_wu 0011 10000111 00010 ..... ..... ..... @fmt_rdrjrk
+ammin_db_du 0011 10000111 00011 ..... ..... ..... @fmt_rdrjrk
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index b653a4d..629da64 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -194,6 +194,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a,
#include "insn_trans/trans_shift.c"
#include "insn_trans/trans_bit.c"
#include "insn_trans/trans_memory.c"
+#include "insn_trans/trans_atomic.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 09/21] target/loongarch: Add fixed point extra instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (7 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 08/21] target/loongarch: Add fixed point atomic " Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-05 8:39 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 10/21] target/loongarch: Add floating point arithmetic " Song Gao
` (11 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement fixed point extra instruction translation.
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>
---
target/loongarch/helper.h | 4 ++
| 88 +++++++++++++++++++++++++++++++
target/loongarch/insns.decode | 25 +++++++++
target/loongarch/op_helper.c | 26 +++++++++
target/loongarch/translate.c | 1 +
5 files changed, 144 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_extra.c
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 09b5a3d..e4b4595 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -14,3 +14,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 b/target/loongarch/insn_trans/trans_extra.c
new file mode 100644
index 0000000..d07e791
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_extra.c
@@ -0,0 +1,88 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+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);
+ 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_fmt_rdrjrk *a,
+ void (*func)(TCGv, TCGv, TCGv, TCGv),
+ TCGv tsz)
+{
+ ctx->dst_ext = EXT_SIGN;
+ TCGv dest = gpr_dst(ctx, a->rd);
+ 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(ctx, a->rd, dest);
+ 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 574c055..66bc314 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -27,6 +27,7 @@
%si14 10:s14
%hint 0:5
%whint 0:15
+%code 0:15
#
# Argument sets
@@ -46,6 +47,8 @@
&fmt_rdrjsi14 rd rj si14
&fmt_hintrjsi12 hint rj si12
&fmt_whint whint
+&fmt_rjrk rj rk
+&fmt_code code
#
# Formats
@@ -65,6 +68,8 @@
@fmt_hintrjsi12 .... ...... ............ ..... ..... &fmt_hintrjsi12 %hint %rj %si12
@fmt_whint .... ........ ..... ............... &fmt_whint %whint
@fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14
+@fmt_rjrk .... ........ ..... ..... ..... ..... &fmt_rjrk %rj %rk
+@fmt_code .... ........ ..... ............... &fmt_code %code
#
# Fixed point arithmetic operation instruction
@@ -260,3 +265,23 @@ ammax_db_wu 0011 10000111 00000 ..... ..... ..... @fmt_rdrjrk
ammax_db_du 0011 10000111 00001 ..... ..... ..... @fmt_rdrjrk
ammin_db_wu 0011 10000111 00010 ..... ..... ..... @fmt_rdrjrk
ammin_db_du 0011 10000111 00011 ..... ..... ..... @fmt_rdrjrk
+
+#
+# Fixed point extra instruction
+#
+crc_w_b_w 0000 00000010 01000 ..... ..... ..... @fmt_rdrjrk
+crc_w_h_w 0000 00000010 01001 ..... ..... ..... @fmt_rdrjrk
+crc_w_w_w 0000 00000010 01010 ..... ..... ..... @fmt_rdrjrk
+crc_w_d_w 0000 00000010 01011 ..... ..... ..... @fmt_rdrjrk
+crcc_w_b_w 0000 00000010 01100 ..... ..... ..... @fmt_rdrjrk
+crcc_w_h_w 0000 00000010 01101 ..... ..... ..... @fmt_rdrjrk
+crcc_w_w_w 0000 00000010 01110 ..... ..... ..... @fmt_rdrjrk
+crcc_w_d_w 0000 00000010 01111 ..... ..... ..... @fmt_rdrjrk
+break 0000 00000010 10100 ............... @fmt_code
+syscall 0000 00000010 10110 ............... @fmt_code
+asrtle_d 0000 00000000 00010 ..... ..... 00000 @fmt_rjrk
+asrtgt_d 0000 00000000 00011 ..... ..... 00000 @fmt_rjrk
+rdtimel_w 0000 00000000 00000 11000 ..... ..... @fmt_rdrj
+rdtimeh_w 0000 00000000 00000 11001 ..... ..... @fmt_rdrj
+rdtime_d 0000 00000000 00000 11010 ..... ..... @fmt_rdrj
+cpucfg 0000 00000000 00000 11011 ..... ..... @fmt_rdrj
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index a4ffaf9..0a1a47b 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -14,6 +14,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)
@@ -57,3 +59,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 629da64..ea2af7e 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -195,6 +195,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a,
#include "insn_trans/trans_bit.c"
#include "insn_trans/trans_memory.c"
#include "insn_trans/trans_atomic.c"
+#include "insn_trans/trans_extra.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 10/21] target/loongarch: Add floating point arithmetic instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (8 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 09/21] target/loongarch: Add fixed point extra " Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-05 9:08 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 11/21] target/loongarch: Add floating point comparison " Song Gao
` (10 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement floating point arithmetic instruction translation.
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>
---
target/loongarch/cpu.c | 1 +
target/loongarch/fpu_helper.c | 438 +++++++++++++++++++++++++++++
target/loongarch/helper.h | 42 +++
target/loongarch/insn_trans/trans_farith.c | 79 ++++++
target/loongarch/insns.decode | 56 ++++
target/loongarch/internals.h | 2 +
target/loongarch/translate.c | 10 +
target/loongarch/translate.h | 2 +
8 files changed, 630 insertions(+)
create mode 100644 target/loongarch/fpu_helper.c
create mode 100644 target/loongarch/insn_trans/trans_farith.c
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index b89bf51..487df05 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -143,6 +143,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..c3bee57
--- /dev/null
+++ b/target/loongarch/fpu_helper.c
@@ -0,0 +1,438 @@
+/*
+ * LoongArch float point emulation helpers for qemu
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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 "translate.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 */
+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);
+}
+
+int ieee_ex_to_loongarch(int xcpt)
+{
+ int ret = 0;
+ if (xcpt) {
+ 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 inline void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
+{
+ int flags = ieee_ex_to_loongarch(get_float_exception_flags(
+ &env->fp_status));
+
+ SET_FP_CAUSE(env->fcsr0, flags);
+ if (flags) {
+ set_float_exception_flags(0, &env->fp_status);
+
+ if (GET_FP_ENABLE(env->fcsr0) & flags) {
+ do_raise_exception(env, EXCP_FPE, pc);
+ } else {
+ UPDATE_FP_FLAGS(env->fcsr0, flags);
+ }
+ }
+}
+
+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_fabs_s(CPULoongArchState *env, uint64_t fj)
+{
+ uint64_t fd;
+
+ fd = nanbox_s(float32_abs((uint32_t)fj));
+ update_fcsr0(env, GETPC());
+ return fd;
+}
+
+uint64_t helper_fabs_d(CPULoongArchState *env, uint64_t fj)
+{
+ uint64_t fd;
+
+ fd = float64_abs(fj);
+ update_fcsr0(env, GETPC());
+ return fd;
+}
+
+uint64_t helper_fneg_s(CPULoongArchState *env, uint64_t fj)
+{
+ uint64_t fd;
+
+ fd = nanbox_s(float32_chs((uint32_t)fj));
+ update_fcsr0(env, GETPC());
+ return fd;
+}
+
+uint64_t helper_fneg_d(CPULoongArchState *env, uint64_t fj)
+{
+ uint64_t fd;
+
+ fd = float64_chs(fj);
+ 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_exception_flags(0, 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);
+ set_float_exception_flags(get_float_exception_flags(status) &
+ (~float_flag_inexact), status);
+ update_fcsr0(env, GETPC());
+ 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_exception_flags(0, 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);
+ set_float_exception_flags(get_float_exception_flags(status) &
+ (~float_flag_inexact), status);
+ update_fcsr0(env, GETPC());
+ 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 e4b4595..62c262e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -18,3 +18,45 @@ 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(fmaxa_s, i64, env, i64, i64)
+DEF_HELPER_3(fmaxa_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(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(fabs_s, i64, env, i64)
+DEF_HELPER_2(fabs_d, i64, env, i64)
+DEF_HELPER_2(fneg_s, i64, env, i64)
+DEF_HELPER_2(fneg_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 b/target/loongarch/insn_trans/trans_farith.c
new file mode 100644
index 0000000..8015d3b
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_farith.c
@@ -0,0 +1,79 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+static bool gen_f3(DisasContext *ctx, arg_fmt_fdfjfk *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_muladd(DisasContext *ctx, arg_fmt_fdfjfkfa *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_fmt_fdfjfk *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_fmt_fdfjfk *a)
+{
+ tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 63);
+ return true;
+}
+
+TRANS(fadd_s, gen_f3, gen_helper_fadd_s)
+TRANS(fadd_d, gen_f3, gen_helper_fadd_d)
+TRANS(fsub_s, gen_f3, gen_helper_fsub_s)
+TRANS(fsub_d, gen_f3, gen_helper_fsub_d)
+TRANS(fmul_s, gen_f3, gen_helper_fmul_s)
+TRANS(fmul_d, gen_f3, gen_helper_fmul_d)
+TRANS(fdiv_s, gen_f3, gen_helper_fdiv_s)
+TRANS(fdiv_d, gen_f3, gen_helper_fdiv_d)
+TRANS(fmax_s, gen_f3, gen_helper_fmax_s)
+TRANS(fmax_d, gen_f3, gen_helper_fmax_d)
+TRANS(fmin_s, gen_f3, gen_helper_fmin_s)
+TRANS(fmin_d, gen_f3, gen_helper_fmin_d)
+TRANS(fmaxa_s, gen_f3, gen_helper_fmaxa_s)
+TRANS(fmaxa_d, gen_f3, gen_helper_fmaxa_d)
+TRANS(fmina_s, gen_f3, gen_helper_fmina_s)
+TRANS(fmina_d, gen_f3, gen_helper_fmina_d)
+TRANS(fscaleb_s, gen_f3, gen_helper_fscaleb_s)
+TRANS(fscaleb_d, gen_f3, gen_helper_fscaleb_d)
+TRANS(fabs_s, gen_f2, gen_helper_fabs_s)
+TRANS(fabs_d, gen_f2, gen_helper_fabs_d)
+TRANS(fneg_s, gen_f2, gen_helper_fneg_s)
+TRANS(fneg_d, gen_f2, gen_helper_fneg_d)
+TRANS(fsqrt_s, gen_f2, gen_helper_fsqrt_s)
+TRANS(fsqrt_d, gen_f2, gen_helper_fsqrt_d)
+TRANS(frecip_s, gen_f2, gen_helper_frecip_s)
+TRANS(frecip_d, gen_f2, gen_helper_frecip_d)
+TRANS(frsqrt_s, gen_f2, gen_helper_frsqrt_s)
+TRANS(frsqrt_d, gen_f2, gen_helper_frsqrt_d)
+TRANS(flogb_s, gen_f2, gen_helper_flogb_s)
+TRANS(flogb_d, gen_f2, gen_helper_flogb_d)
+TRANS(fclass_s, gen_f2, gen_helper_fclass_s)
+TRANS(fclass_d, gen_f2, 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 66bc314..9e6a727 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -28,6 +28,10 @@
%hint 0:5
%whint 0:15
%code 0:15
+%fd 0:5
+%fj 5:5
+%fk 10:5
+%fa 15:5
#
# Argument sets
@@ -49,6 +53,9 @@
&fmt_whint whint
&fmt_rjrk rj rk
&fmt_code code
+&fmt_fdfjfk fd fj fk
+&fmt_fdfjfkfa fd fj fk fa
+&fmt_fdfj fd fj
#
# Formats
@@ -70,6 +77,9 @@
@fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14
@fmt_rjrk .... ........ ..... ..... ..... ..... &fmt_rjrk %rj %rk
@fmt_code .... ........ ..... ............... &fmt_code %code
+@fmt_fdfjfk .... ........ ..... ..... ..... ..... &fmt_fdfjfk %fd %fj %fk
+@fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa
+@fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj
#
# Fixed point arithmetic operation instruction
@@ -285,3 +295,49 @@ rdtimel_w 0000 00000000 00000 11000 ..... ..... @fmt_rdrj
rdtimeh_w 0000 00000000 00000 11001 ..... ..... @fmt_rdrj
rdtime_d 0000 00000000 00000 11010 ..... ..... @fmt_rdrj
cpucfg 0000 00000000 00000 11011 ..... ..... @fmt_rdrj
+
+#
+# Floating point arithmetic operation instruction
+#
+fadd_s 0000 00010000 00001 ..... ..... ..... @fmt_fdfjfk
+fadd_d 0000 00010000 00010 ..... ..... ..... @fmt_fdfjfk
+fsub_s 0000 00010000 00101 ..... ..... ..... @fmt_fdfjfk
+fsub_d 0000 00010000 00110 ..... ..... ..... @fmt_fdfjfk
+fmul_s 0000 00010000 01001 ..... ..... ..... @fmt_fdfjfk
+fmul_d 0000 00010000 01010 ..... ..... ..... @fmt_fdfjfk
+fdiv_s 0000 00010000 01101 ..... ..... ..... @fmt_fdfjfk
+fdiv_d 0000 00010000 01110 ..... ..... ..... @fmt_fdfjfk
+fmadd_s 0000 10000001 ..... ..... ..... ..... @fmt_fdfjfkfa
+fmadd_d 0000 10000010 ..... ..... ..... ..... @fmt_fdfjfkfa
+fmsub_s 0000 10000101 ..... ..... ..... ..... @fmt_fdfjfkfa
+fmsub_d 0000 10000110 ..... ..... ..... ..... @fmt_fdfjfkfa
+fnmadd_s 0000 10001001 ..... ..... ..... ..... @fmt_fdfjfkfa
+fnmadd_d 0000 10001010 ..... ..... ..... ..... @fmt_fdfjfkfa
+fnmsub_s 0000 10001101 ..... ..... ..... ..... @fmt_fdfjfkfa
+fnmsub_d 0000 10001110 ..... ..... ..... ..... @fmt_fdfjfkfa
+fmax_s 0000 00010000 10001 ..... ..... ..... @fmt_fdfjfk
+fmax_d 0000 00010000 10010 ..... ..... ..... @fmt_fdfjfk
+fmin_s 0000 00010000 10101 ..... ..... ..... @fmt_fdfjfk
+fmin_d 0000 00010000 10110 ..... ..... ..... @fmt_fdfjfk
+fmaxa_s 0000 00010000 11001 ..... ..... ..... @fmt_fdfjfk
+fmaxa_d 0000 00010000 11010 ..... ..... ..... @fmt_fdfjfk
+fmina_s 0000 00010000 11101 ..... ..... ..... @fmt_fdfjfk
+fmina_d 0000 00010000 11110 ..... ..... ..... @fmt_fdfjfk
+fabs_s 0000 00010001 01000 00001 ..... ..... @fmt_fdfj
+fabs_d 0000 00010001 01000 00010 ..... ..... @fmt_fdfj
+fneg_s 0000 00010001 01000 00101 ..... ..... @fmt_fdfj
+fneg_d 0000 00010001 01000 00110 ..... ..... @fmt_fdfj
+fsqrt_s 0000 00010001 01000 10001 ..... ..... @fmt_fdfj
+fsqrt_d 0000 00010001 01000 10010 ..... ..... @fmt_fdfj
+frecip_s 0000 00010001 01000 10101 ..... ..... @fmt_fdfj
+frecip_d 0000 00010001 01000 10110 ..... ..... @fmt_fdfj
+frsqrt_s 0000 00010001 01000 11001 ..... ..... @fmt_fdfj
+frsqrt_d 0000 00010001 01000 11010 ..... ..... @fmt_fdfj
+fscaleb_s 0000 00010001 00001 ..... ..... ..... @fmt_fdfjfk
+fscaleb_d 0000 00010001 00010 ..... ..... ..... @fmt_fdfjfk
+flogb_s 0000 00010001 01000 01001 ..... ..... @fmt_fdfj
+flogb_d 0000 00010001 01000 01010 ..... ..... @fmt_fdfj
+fcopysign_s 0000 00010001 00101 ..... ..... ..... @fmt_fdfjfk
+fcopysign_d 0000 00010001 00110 ..... ..... ..... @fmt_fdfjfk
+fclass_s 0000 00010001 01000 01101 ..... ..... @fmt_fdfj
+fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 1052cb6..096a4a7 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -19,4 +19,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 ea2af7e..d3e6f8a 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -16,6 +16,7 @@
#include "exec/translator.h"
#include "exec/log.h"
#include "qemu/qemu-print.h"
+#include "fpu/softfloat.h"
#include "translate.h"
#include "internals.h"
@@ -190,12 +191,21 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a,
return true;
}
+/* fmt fd fj */
+static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a,
+ void (*func)(TCGv, TCGv_env, TCGv))
+{
+ func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj]);
+ return true;
+}
+
#include "insn_trans/trans_arith.c"
#include "insn_trans/trans_shift.c"
#include "insn_trans/trans_bit.c"
#include "insn_trans/trans_memory.c"
#include "insn_trans/trans_atomic.c"
#include "insn_trans/trans_extra.c"
+#include "insn_trans/trans_farith.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
index f064fdd..99ab329 100644
--- a/target/loongarch/translate.h
+++ b/target/loongarch/translate.h
@@ -44,4 +44,6 @@ extern TCGv cpu_gpr[32], cpu_pc;
extern TCGv_i32 cpu_fscr0;
extern TCGv_i64 cpu_fpr[32];
+int ieee_ex_to_loongarch(int xcpt);
+
#endif
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 11/21] target/loongarch: Add floating point comparison instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (9 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 10/21] target/loongarch: Add floating point arithmetic " Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-05 9:24 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 12/21] target/loongarch: Add floating point conversion " Song Gao
` (9 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement floating point comparison instruction translation.
This includes:
- FCMP.cond.{S/D}
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
target/loongarch/fpu_helper.c | 110 ++++++++++++
target/loongarch/helper.h | 9 +
target/loongarch/insn_trans/trans_fcmp.c | 279 +++++++++++++++++++++++++++++++
target/loongarch/insns.decode | 10 ++
target/loongarch/translate.c | 1 +
target/loongarch/translate.h | 5 +
6 files changed, 414 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_fcmp.c
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index c3bee57..bad7238 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -436,3 +436,113 @@ uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj,
update_fcsr0(env, GETPC());
return fd;
}
+
+/* fcmp_cXXX_s */
+uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+ uint32_t t0, t1;
+ uint64_t cmp = 0;
+ t0 = (uint32_t)fj;
+ t1 = (uint32_t)fk;
+
+ if (flags) {
+ if (flags & FCMP_LT) {
+ cmp |= float32_lt_quiet(t0, t1, &env->fp_status);
+ }
+ if (flags & FCMP_EQ) {
+ cmp |= float32_eq_quiet(t0, t1, &env->fp_status);
+ }
+ if (flags & FCMP_GT) {
+ cmp |= float32_lt_quiet(t1, t0, &env->fp_status);
+ }
+ if (flags & FCMP_UN) {
+ cmp |= float32_unordered_quiet(t1, t0, &env->fp_status);
+ }
+ } else {
+ cmp = (float32_unordered_quiet(t1, t0, &env->fp_status), 0);
+ }
+ update_fcsr0(env, GETPC());
+ return cmp;
+}
+
+/* fcmp_sXXX_s */
+uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+ uint32_t t0, t1;
+ uint64_t cmp = 0;
+ t0 = (uint32_t)fj;
+ t1 = (uint32_t)fk;
+
+ if (flags) {
+ if (flags & FCMP_LT) {
+ cmp |= float32_lt(t0, t1, &env->fp_status);
+ }
+ if (flags & FCMP_EQ) {
+ cmp |= float32_eq(t0, t1, &env->fp_status);
+ }
+ if (flags & FCMP_GT) {
+ cmp |= float32_lt(t1, t0, &env->fp_status);
+ }
+ if (flags & FCMP_UN) {
+ cmp |= float32_unordered(t1, t0, &env->fp_status);
+ }
+ } else {
+ cmp = (float32_unordered(t1, t0, &env->fp_status), 0);
+ }
+ update_fcsr0(env, GETPC());
+ return cmp;
+}
+
+/* fcmp_cXXX_d */
+uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+ uint64_t cmp = 0;
+
+ if (flags) {
+ if (flags & FCMP_LT) {
+ cmp |= float64_lt_quiet(fj, fk, &env->fp_status);
+ }
+ if (flags & FCMP_EQ) {
+ cmp |= float64_eq_quiet(fj, fk, &env->fp_status);
+ }
+ if (flags & FCMP_GT) {
+ cmp |= float64_lt_quiet(fk, fj, &env->fp_status);
+ }
+ if (flags & FCMP_UN) {
+ cmp |= float64_unordered_quiet(fk, fj, &env->fp_status);
+ }
+ } else {
+ cmp = (float64_unordered_quiet(fk, fj, &env->fp_status), 0);
+ }
+ update_fcsr0(env, GETPC());
+ return cmp;
+}
+
+/* fcmp_sXXX_d */
+uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+ uint64_t cmp = 0;
+
+ if (flags) {
+ if (flags & FCMP_LT) {
+ cmp |= float64_lt(fj, fk, &env->fp_status);
+ }
+ if (flags & FCMP_EQ) {
+ cmp |= float64_eq(fj, fk, &env->fp_status);
+ }
+ if (flags & FCMP_GT) {
+ cmp |= float64_lt(fk, fj, &env->fp_status);
+ }
+ if (flags & FCMP_UN) {
+ cmp |= float64_unordered(fk, fj, &env->fp_status);
+ }
+ } else {
+ cmp = (float64_unordered(fk, fj, &env->fp_status), 0);
+ }
+ update_fcsr0(env, GETPC());
+ return cmp;
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 62c262e..5f6e60d 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -60,3 +60,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 b/target/loongarch/insn_trans/trans_fcmp.c
new file mode 100644
index 0000000..e9d7c3b
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fcmp.c
@@ -0,0 +1,279 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
+{
+ TCGv var = tcg_temp_new();
+ TCGv_i32 flags = NULL;
+
+ switch (a->fcond) {
+ /* caf */
+ case 0:
+ flags = tcg_constant_i32(0);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* saf */
+ case 1:
+ flags = tcg_constant_i32(0);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* clt */
+ case 2:
+ flags = tcg_constant_i32(FCMP_LT);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* slt */
+ case 3:
+ flags = tcg_constant_i32(FCMP_LT);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* ceq */
+ case 4:
+ flags = tcg_constant_i32(FCMP_EQ);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* seq */
+ case 5:
+ flags = tcg_constant_i32(FCMP_EQ);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* cle */
+ case 6:
+ flags = tcg_constant_i32(FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* sle */
+ case 7:
+ flags = tcg_constant_i32(FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* cun */
+ case 8:
+ flags = tcg_constant_i32(FCMP_UN);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* sun */
+ case 9:
+ flags = tcg_constant_i32(FCMP_UN);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* cult */
+ case 10:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_LT);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* sult */
+ case 11:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_LT);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* cueq */
+ case 12:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_EQ);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* sueq */
+ case 13:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_EQ);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* cule */
+ case 14:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* sule */
+ case 15:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* cne */
+ case 16:
+ flags = tcg_constant_i32(FCMP_GT | FCMP_LT);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* sne */
+ case 17:
+ flags = tcg_constant_i32(FCMP_GT | FCMP_LT);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* cor */
+ case 20:
+ flags = tcg_constant_i32(FCMP_GT | FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* sor */
+ case 21:
+ flags = tcg_constant_i32(FCMP_GT | FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* cune */
+ case 24:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_GT | FCMP_LT);
+ gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ /* sune */
+ case 25:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_GT | FCMP_LT);
+ gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ default:
+ abort();
+ }
+
+ 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();
+ TCGv_i32 flags = NULL;
+
+ switch (a->fcond) {
+ case 0:
+ flags = tcg_constant_i32(0);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 1:
+ flags = tcg_constant_i32(0);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 2:
+ flags = tcg_constant_i32(FCMP_LT);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 3:
+ flags = tcg_constant_i32(FCMP_LT);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 4:
+ flags = tcg_constant_i32(FCMP_EQ);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 5:
+ flags = tcg_constant_i32(FCMP_EQ);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 6:
+ flags = tcg_constant_i32(FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 7:
+ flags = tcg_constant_i32(FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 8:
+ flags = tcg_constant_i32(FCMP_UN);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 9:
+ flags = tcg_constant_i32(FCMP_UN);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 10:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_LT);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 11:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_LT);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 12:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_EQ);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 13:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_EQ);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 14:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 15:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 16:
+ flags = tcg_constant_i32(FCMP_GT | FCMP_LT);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 17:
+ flags = tcg_constant_i32(FCMP_GT | FCMP_LT);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 20:
+ flags = tcg_constant_i32(FCMP_GT | FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 21:
+ flags = tcg_constant_i32(FCMP_GT | FCMP_LT | FCMP_EQ);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 24:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_GT | FCMP_LT);
+ gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ case 25:
+ flags = tcg_constant_i32(FCMP_UN | FCMP_GT | FCMP_LT);
+ gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj],
+ cpu_fpr[a->fk], flags);
+ break;
+ default:
+ abort();
+ }
+
+ 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 9e6a727..8aadcfd 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -32,6 +32,8 @@
%fj 5:5
%fk 10:5
%fa 15:5
+%cd 0:3
+%fcond 15:5
#
# Argument sets
@@ -56,6 +58,7 @@
&fmt_fdfjfk fd fj fk
&fmt_fdfjfkfa fd fj fk fa
&fmt_fdfj fd fj
+&fmt_cdfjfkfcond cd fj fk fcond
#
# Formats
@@ -80,6 +83,7 @@
@fmt_fdfjfk .... ........ ..... ..... ..... ..... &fmt_fdfjfk %fd %fj %fk
@fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa
@fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj
+@fmt_cdfjfkfcond .... ........ ..... ..... ..... .. ... &fmt_cdfjfkfcond %cd %fj %fk %fcond
#
# Fixed point arithmetic operation instruction
@@ -341,3 +345,9 @@ fcopysign_s 0000 00010001 00101 ..... ..... ..... @fmt_fdfjfk
fcopysign_d 0000 00010001 00110 ..... ..... ..... @fmt_fdfjfk
fclass_s 0000 00010001 01000 01101 ..... ..... @fmt_fdfj
fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj
+
+#
+# Floating point compare instruction
+#
+fcmp_cond_s 0000 11000001 ..... ..... ..... 00 ... @fmt_cdfjfkfcond
+fcmp_cond_d 0000 11000010 ..... ..... ..... 00 ... @fmt_cdfjfkfcond
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index d3e6f8a..be99fb7 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -206,6 +206,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a,
#include "insn_trans/trans_atomic.c"
#include "insn_trans/trans_extra.c"
#include "insn_trans/trans_farith.c"
+#include "insn_trans/trans_fcmp.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
index 99ab329..16e570c 100644
--- a/target/loongarch/translate.h
+++ b/target/loongarch/translate.h
@@ -11,6 +11,11 @@
#include "exec/translator.h"
+#define FCMP_LT 0x0001 /* fp0 < fp1 */
+#define FCMP_EQ 0x0010 /* fp0 = fp1 */
+#define FCMP_GT 0x0100 /* fp1 < fp0 */
+#define FCMP_UN 0x1000 /* unordered */
+
#define TRANS(NAME, FUNC, ...) \
static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
{ return FUNC(ctx, a, __VA_ARGS__); }
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 12/21] target/loongarch: Add floating point conversion instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (10 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 11/21] target/loongarch: Add floating point comparison " Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-05 9:29 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 13/21] target/loongarch: Add floating point move " Song Gao
` (8 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement floating point conversion instruction translation.
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>
---
target/loongarch/fpu_helper.c | 393 +++++++++++++++++++++++++++++++
target/loongarch/helper.h | 29 +++
target/loongarch/insn_trans/trans_fcnv.c | 36 +++
target/loongarch/insns.decode | 32 +++
target/loongarch/translate.c | 1 +
5 files changed, 491 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_fcnv.c
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index bad7238..2aef1fa 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -546,3 +546,396 @@ uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
update_fcsr0(env, GETPC());
return cmp;
}
+
+/* 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 5f6e60d..d90b093 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -69,3 +69,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 b/target/loongarch/insn_trans/trans_fcnv.c
new file mode 100644
index 0000000..6788859
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fcnv.c
@@ -0,0 +1,36 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+TRANS(fcvt_s_d, gen_f2, gen_helper_fcvt_s_d)
+TRANS(fcvt_d_s, gen_f2, gen_helper_fcvt_d_s)
+TRANS(ftintrm_w_s, gen_f2, gen_helper_ftintrm_w_s)
+TRANS(ftintrm_w_d, gen_f2, gen_helper_ftintrm_w_d)
+TRANS(ftintrm_l_s, gen_f2, gen_helper_ftintrm_l_s)
+TRANS(ftintrm_l_d, gen_f2, gen_helper_ftintrm_l_d)
+TRANS(ftintrp_w_s, gen_f2, gen_helper_ftintrp_w_s)
+TRANS(ftintrp_w_d, gen_f2, gen_helper_ftintrp_w_d)
+TRANS(ftintrp_l_s, gen_f2, gen_helper_ftintrp_l_s)
+TRANS(ftintrp_l_d, gen_f2, gen_helper_ftintrp_l_d)
+TRANS(ftintrz_w_s, gen_f2, gen_helper_ftintrz_w_s)
+TRANS(ftintrz_w_d, gen_f2, gen_helper_ftintrz_w_d)
+TRANS(ftintrz_l_s, gen_f2, gen_helper_ftintrz_l_s)
+TRANS(ftintrz_l_d, gen_f2, gen_helper_ftintrz_l_d)
+TRANS(ftintrne_w_s, gen_f2, gen_helper_ftintrne_w_s)
+TRANS(ftintrne_w_d, gen_f2, gen_helper_ftintrne_w_d)
+TRANS(ftintrne_l_s, gen_f2, gen_helper_ftintrne_l_s)
+TRANS(ftintrne_l_d, gen_f2, gen_helper_ftintrne_l_d)
+TRANS(ftint_w_s, gen_f2, gen_helper_ftint_w_s)
+TRANS(ftint_w_d, gen_f2, gen_helper_ftint_w_d)
+TRANS(ftint_l_s, gen_f2, gen_helper_ftint_l_s)
+TRANS(ftint_l_d, gen_f2, gen_helper_ftint_l_d)
+TRANS(ffint_s_w, gen_f2, gen_helper_ffint_s_w)
+TRANS(ffint_s_l, gen_f2, gen_helper_ffint_s_l)
+TRANS(ffint_d_w, gen_f2, gen_helper_ffint_d_w)
+TRANS(ffint_d_l, gen_f2, gen_helper_ffint_d_l)
+TRANS(frint_s, gen_f2, gen_helper_frint_s)
+TRANS(frint_d, gen_f2, gen_helper_frint_d)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8aadcfd..c6fd762 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -351,3 +351,35 @@ fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj
#
fcmp_cond_s 0000 11000001 ..... ..... ..... 00 ... @fmt_cdfjfkfcond
fcmp_cond_d 0000 11000010 ..... ..... ..... 00 ... @fmt_cdfjfkfcond
+
+#
+# Floating point conversion instruction
+#
+fcvt_s_d 0000 00010001 10010 00110 ..... ..... @fmt_fdfj
+fcvt_d_s 0000 00010001 10010 01001 ..... ..... @fmt_fdfj
+ftintrm_w_s 0000 00010001 10100 00001 ..... ..... @fmt_fdfj
+ftintrm_w_d 0000 00010001 10100 00010 ..... ..... @fmt_fdfj
+ftintrm_l_s 0000 00010001 10100 01001 ..... ..... @fmt_fdfj
+ftintrm_l_d 0000 00010001 10100 01010 ..... ..... @fmt_fdfj
+ftintrp_w_s 0000 00010001 10100 10001 ..... ..... @fmt_fdfj
+ftintrp_w_d 0000 00010001 10100 10010 ..... ..... @fmt_fdfj
+ftintrp_l_s 0000 00010001 10100 11001 ..... ..... @fmt_fdfj
+ftintrp_l_d 0000 00010001 10100 11010 ..... ..... @fmt_fdfj
+ftintrz_w_s 0000 00010001 10101 00001 ..... ..... @fmt_fdfj
+ftintrz_w_d 0000 00010001 10101 00010 ..... ..... @fmt_fdfj
+ftintrz_l_s 0000 00010001 10101 01001 ..... ..... @fmt_fdfj
+ftintrz_l_d 0000 00010001 10101 01010 ..... ..... @fmt_fdfj
+ftintrne_w_s 0000 00010001 10101 10001 ..... ..... @fmt_fdfj
+ftintrne_w_d 0000 00010001 10101 10010 ..... ..... @fmt_fdfj
+ftintrne_l_s 0000 00010001 10101 11001 ..... ..... @fmt_fdfj
+ftintrne_l_d 0000 00010001 10101 11010 ..... ..... @fmt_fdfj
+ftint_w_s 0000 00010001 10110 00001 ..... ..... @fmt_fdfj
+ftint_w_d 0000 00010001 10110 00010 ..... ..... @fmt_fdfj
+ftint_l_s 0000 00010001 10110 01001 ..... ..... @fmt_fdfj
+ftint_l_d 0000 00010001 10110 01010 ..... ..... @fmt_fdfj
+ffint_s_w 0000 00010001 11010 00100 ..... ..... @fmt_fdfj
+ffint_s_l 0000 00010001 11010 00110 ..... ..... @fmt_fdfj
+ffint_d_w 0000 00010001 11010 01000 ..... ..... @fmt_fdfj
+ffint_d_l 0000 00010001 11010 01010 ..... ..... @fmt_fdfj
+frint_s 0000 00010001 11100 10001 ..... ..... @fmt_fdfj
+frint_d 0000 00010001 11100 10010 ..... ..... @fmt_fdfj
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index be99fb7..e81c26b 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -207,6 +207,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a,
#include "insn_trans/trans_extra.c"
#include "insn_trans/trans_farith.c"
#include "insn_trans/trans_fcmp.c"
+#include "insn_trans/trans_fcnv.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 13/21] target/loongarch: Add floating point move instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (11 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 12/21] target/loongarch: Add floating point conversion " Song Gao
@ 2021-09-02 12:40 ` Song Gao
2021-09-05 9:38 ` Richard Henderson
2021-09-05 9:45 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 14/21] target/loongarch: Add floating point load/store " Song Gao
` (7 subsequent siblings)
20 siblings, 2 replies; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:40 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement floationg point move instruction translation.
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>
---
target/loongarch/fpu_helper.c | 6 ++
target/loongarch/helper.h | 2 +
target/loongarch/insn_trans/trans_fmov.c | 159 +++++++++++++++++++++++++++++++
target/loongarch/insns.decode | 41 ++++++++
target/loongarch/translate.c | 1 +
5 files changed, 209 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_fmov.c
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index 2aef1fa..a5d3897 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -939,3 +939,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 d90b093..b397a52 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -98,3 +98,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 b/target/loongarch/insn_trans/trans_fmov.c
new file mode 100644
index 0000000..c417fb8
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmov.c
@@ -0,0 +1,159 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+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_mov(DisasContext *ctx, arg_fmt_fdfj *a,
+ void (*func)(TCGv, TCGv))
+{
+ TCGv dest = cpu_fpr[a->fd];
+ TCGv src = cpu_fpr[a->fj];
+
+ func(dest, src);
+ return true;
+}
+
+static bool gen_r2f(DisasContext *ctx, arg_fmt_fdrj *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_fmt_rdfj *a,
+ DisasExtend dst_ext, void (*func)(TCGv, TCGv))
+{
+ ctx->dst_ext = dst_ext;
+ TCGv dest = gpr_dst(ctx, a->rd);
+
+ func(dest, cpu_fpr[a->fj]);
+
+ if (ctx->dst_ext) {
+ gen_set_gpr(ctx, a->rd, dest);
+ }
+ 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);
+
+ 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)
+{
+ TCGv t0 = tcg_temp_new();
+
+ tcg_gen_extract_tl(dest, src, 32, 32);
+
+ tcg_temp_free(t0);
+}
+
+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), cpu_env,
+ offsetof(CPULoongArchState, cf[a->cj & 0x7]));
+ return true;
+}
+
+TRANS(fmov_s, gen_mov, tcg_gen_mov_tl)
+TRANS(fmov_d, gen_mov, tcg_gen_mov_tl)
+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, EXT_NONE, tcg_gen_ext32s_tl)
+TRANS(movfr2gr_d, gen_f2r, EXT_NONE, tcg_gen_mov_tl)
+TRANS(movfrh2gr_s, gen_f2r, EXT_SIGN, gen_movfrh2gr_s)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index c6fd762..febf89a 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -34,6 +34,10 @@
%fa 15:5
%cd 0:3
%fcond 15:5
+%cj 5:3
+%ca 15:3
+%fcsrd 0:5
+%fcsrs 5:5
#
# Argument sets
@@ -59,6 +63,15 @@
&fmt_fdfjfkfa fd fj fk fa
&fmt_fdfj fd fj
&fmt_cdfjfkfcond cd fj fk fcond
+&fmt_fdfjfkca fd fj fk ca
+&fmt_fdrj fd rj
+&fmt_rdfj rd fj
+&fmt_fcsrdrj fcsrd rj
+&fmt_rdfcsrs rd fcsrs
+&fmt_cdfj cd fj
+&fmt_fdcj fd cj
+&fmt_cdrj cd rj
+&fmt_rdcj rd cj
#
# Formats
@@ -84,6 +97,15 @@
@fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa
@fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj
@fmt_cdfjfkfcond .... ........ ..... ..... ..... .. ... &fmt_cdfjfkfcond %cd %fj %fk %fcond
+@fmt_fdfjfkca .... ........ .. ... ..... ..... ..... &fmt_fdfjfkca %fd %fj %fk %ca
+@fmt_fdrj .... ........ ..... ..... ..... ..... &fmt_fdrj %fd %rj
+@fmt_rdfj .... ........ ..... ..... ..... ..... &fmt_rdfj %rd %fj
+@fmt_fcsrdrj .... ........ ..... ..... ..... ..... &fmt_fcsrdrj %fcsrd %rj
+@fmt_rdfcsrs .... ........ ..... ..... ..... ..... &fmt_rdfcsrs %rd %fcsrs
+@fmt_cdfj .... ........ ..... ..... ..... .. ... &fmt_cdfj %cd %fj
+@fmt_fdcj .... ........ ..... ..... .. ... ..... &fmt_fdcj %fd %cj
+@fmt_cdrj .... ........ ..... ..... ..... .. ... &fmt_cdrj %cd %rj
+@fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj
#
# Fixed point arithmetic operation instruction
@@ -383,3 +405,22 @@ ffint_d_w 0000 00010001 11010 01000 ..... ..... @fmt_fdfj
ffint_d_l 0000 00010001 11010 01010 ..... ..... @fmt_fdfj
frint_s 0000 00010001 11100 10001 ..... ..... @fmt_fdfj
frint_d 0000 00010001 11100 10010 ..... ..... @fmt_fdfj
+
+#
+# Floating point move instruction
+#
+fmov_s 0000 00010001 01001 00101 ..... ..... @fmt_fdfj
+fmov_d 0000 00010001 01001 00110 ..... ..... @fmt_fdfj
+fsel 0000 11010000 00 ... ..... ..... ..... @fmt_fdfjfkca
+movgr2fr_w 0000 00010001 01001 01001 ..... ..... @fmt_fdrj
+movgr2fr_d 0000 00010001 01001 01010 ..... ..... @fmt_fdrj
+movgr2frh_w 0000 00010001 01001 01011 ..... ..... @fmt_fdrj
+movfr2gr_s 0000 00010001 01001 01101 ..... ..... @fmt_rdfj
+movfr2gr_d 0000 00010001 01001 01110 ..... ..... @fmt_rdfj
+movfrh2gr_s 0000 00010001 01001 01111 ..... ..... @fmt_rdfj
+movgr2fcsr 0000 00010001 01001 10000 ..... ..... @fmt_fcsrdrj
+movfcsr2gr 0000 00010001 01001 10010 ..... ..... @fmt_rdfcsrs
+movfr2cf 0000 00010001 01001 10100 ..... 00 ... @fmt_cdfj
+movcf2fr 0000 00010001 01001 10101 00 ... ..... @fmt_fdcj
+movgr2cf 0000 00010001 01001 10110 ..... 00 ... @fmt_cdrj
+movcf2gr 0000 00010001 01001 10111 00 ... ..... @fmt_rdcj
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index e81c26b..d9cef7e 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -208,6 +208,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a,
#include "insn_trans/trans_farith.c"
#include "insn_trans/trans_fcmp.c"
#include "insn_trans/trans_fcnv.c"
+#include "insn_trans/trans_fmov.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 14/21] target/loongarch: Add floating point load/store instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (12 preceding siblings ...)
2021-09-02 12:40 ` [PATCH v4 13/21] target/loongarch: Add floating point move " Song Gao
@ 2021-09-02 12:41 ` Song Gao
2021-09-05 9:46 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 15/21] target/loongarch: Add branch " Song Gao
` (6 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:41 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement floating point load/store instruction translation.
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>
---
target/loongarch/insn_trans/trans_fmemory.c | 143 ++++++++++++++++++++++++++++
target/loongarch/insns.decode | 24 +++++
target/loongarch/translate.c | 1 +
3 files changed, 168 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_fmemory.c
diff --git a/target/loongarch/insn_trans/trans_fmemory.c b/target/loongarch/insn_trans/trans_fmemory.c
new file mode 100644
index 0000000..88727c3
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmemory.c
@@ -0,0 +1,143 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+static bool gen_fload_imm(DisasContext *ctx, arg_fmt_fdrjsi12 *a, MemOp mop)
+{
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv temp = NULL;
+
+ if (a->si12) {
+ temp = tcg_temp_new();
+ tcg_gen_addi_tl(temp, addr, a->si12);
+ addr = temp;
+ }
+ tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+ if (temp) {
+ tcg_temp_free(temp);
+ }
+ return true;
+}
+
+static bool gen_fstore_imm(DisasContext *ctx, arg_fmt_fdrjsi12 *a, MemOp mop)
+{
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv temp = NULL;
+
+ if (a->si12) {
+ temp = tcg_temp_new();
+ tcg_gen_addi_tl(temp, addr, a->si12);
+ addr = temp;
+ }
+ tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+ if (temp) {
+ tcg_temp_free(temp);
+ }
+ return true;
+}
+
+static bool gen_fload_tl(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop)
+{
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv addr = tcg_temp_new();
+
+ tcg_gen_add_tl(addr, src1, src2);
+ tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_fstore_tl(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop)
+{
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv addr = tcg_temp_new();
+
+ tcg_gen_add_tl(addr, src1, src2);
+ tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_fload_gt(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop)
+{
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv addr = tcg_temp_new();
+
+ gen_helper_asrtgt_d(cpu_env, src1, src2);
+ tcg_gen_add_tl(addr, src1, src2);
+ tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+
+ return true;
+}
+
+static bool gen_fstore_gt(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop)
+{
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv addr = tcg_temp_new();
+
+ gen_helper_asrtgt_d(cpu_env, src1, src2);
+ tcg_gen_add_tl(addr, src1, src2);
+ tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_fload_le(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop)
+{
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv addr = tcg_temp_new();
+
+ gen_helper_asrtle_d(cpu_env, src1, src2);
+ tcg_gen_add_tl(addr, src1, src2);
+ tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+static bool gen_fstore_le(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop)
+{
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv addr = tcg_temp_new();
+
+ gen_helper_asrtle_d(cpu_env, src1, src2);
+ tcg_gen_add_tl(addr, src1, src2);
+ tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+ tcg_temp_free(addr);
+ return true;
+}
+
+TRANS(fld_s, gen_fload_imm, MO_TESL)
+TRANS(fst_s, gen_fstore_imm, MO_TEUL)
+TRANS(fld_d, gen_fload_imm, MO_TEQ)
+TRANS(fst_d, gen_fstore_imm, MO_TEQ)
+TRANS(fldx_s, gen_fload_tl, MO_TESL)
+TRANS(fldx_d, gen_fload_tl, MO_TEQ)
+TRANS(fstx_s, gen_fstore_tl, MO_TEUL)
+TRANS(fstx_d, gen_fstore_tl, MO_TEQ)
+TRANS(fldgt_s, gen_fload_gt, MO_TESL)
+TRANS(fldgt_d, gen_fload_gt, MO_TEQ)
+TRANS(fldle_s, gen_fload_le, MO_TESL)
+TRANS(fldle_d, gen_fload_le, MO_TEQ)
+TRANS(fstgt_s, gen_fstore_gt, MO_TEUL)
+TRANS(fstgt_d, gen_fstore_gt, MO_TEQ)
+TRANS(fstle_s, gen_fstore_le, MO_TEUL)
+TRANS(fstle_d, gen_fstore_le, MO_TEQ)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index febf89a..ea776c2 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -72,6 +72,8 @@
&fmt_fdcj fd cj
&fmt_cdrj cd rj
&fmt_rdcj rd cj
+&fmt_fdrjrk fd rj rk
+&fmt_fdrjsi12 fd rj si12
#
# Formats
@@ -106,6 +108,8 @@
@fmt_fdcj .... ........ ..... ..... .. ... ..... &fmt_fdcj %fd %cj
@fmt_cdrj .... ........ ..... ..... ..... .. ... &fmt_cdrj %cd %rj
@fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj
+@fmt_fdrjrk .... ........ ..... ..... ..... ..... &fmt_fdrjrk %fd %rj %rk
+@fmt_fdrjsi12 .... ...... ............ ..... ..... &fmt_fdrjsi12 %fd %rj %si12
#
# Fixed point arithmetic operation instruction
@@ -424,3 +428,23 @@ movfr2cf 0000 00010001 01001 10100 ..... 00 ... @fmt_cdfj
movcf2fr 0000 00010001 01001 10101 00 ... ..... @fmt_fdcj
movgr2cf 0000 00010001 01001 10110 ..... 00 ... @fmt_cdrj
movcf2gr 0000 00010001 01001 10111 00 ... ..... @fmt_rdcj
+
+#
+# Floating point load/store instruction
+#
+fld_s 0010 101100 ............ ..... ..... @fmt_fdrjsi12
+fst_s 0010 101101 ............ ..... ..... @fmt_fdrjsi12
+fld_d 0010 101110 ............ ..... ..... @fmt_fdrjsi12
+fst_d 0010 101111 ............ ..... ..... @fmt_fdrjsi12
+fldx_s 0011 10000011 00000 ..... ..... ..... @fmt_fdrjrk
+fldx_d 0011 10000011 01000 ..... ..... ..... @fmt_fdrjrk
+fstx_s 0011 10000011 10000 ..... ..... ..... @fmt_fdrjrk
+fstx_d 0011 10000011 11000 ..... ..... ..... @fmt_fdrjrk
+fldgt_s 0011 10000111 01000 ..... ..... ..... @fmt_fdrjrk
+fldgt_d 0011 10000111 01001 ..... ..... ..... @fmt_fdrjrk
+fldle_s 0011 10000111 01010 ..... ..... ..... @fmt_fdrjrk
+fldle_d 0011 10000111 01011 ..... ..... ..... @fmt_fdrjrk
+fstgt_s 0011 10000111 01100 ..... ..... ..... @fmt_fdrjrk
+fstgt_d 0011 10000111 01101 ..... ..... ..... @fmt_fdrjrk
+fstle_s 0011 10000111 01110 ..... ..... ..... @fmt_fdrjrk
+fstle_d 0011 10000111 01111 ..... ..... ..... @fmt_fdrjrk
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index d9cef7e..7c2c80b 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -209,6 +209,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a,
#include "insn_trans/trans_fcmp.c"
#include "insn_trans/trans_fcnv.c"
#include "insn_trans/trans_fmov.c"
+#include "insn_trans/trans_fmemory.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 15/21] target/loongarch: Add branch instruction translation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (13 preceding siblings ...)
2021-09-02 12:41 ` [PATCH v4 14/21] target/loongarch: Add floating point load/store " Song Gao
@ 2021-09-02 12:41 ` Song Gao
2021-09-05 9:49 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 16/21] target/loongarch: Add disassembler Song Gao
` (5 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:41 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch implement branch instruction translation.
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>
---
target/loongarch/insn_trans/trans_branch.c | 84 ++++++++++++++++++++++++++++++
target/loongarch/insns.decode | 30 +++++++++++
target/loongarch/translate.c | 1 +
3 files changed, 115 insertions(+)
create mode 100644 target/loongarch/insn_trans/trans_branch.c
diff --git a/target/loongarch/insn_trans/trans_branch.c b/target/loongarch/insn_trans/trans_branch.c
new file mode 100644
index 0000000..acf1966
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_branch.c
@@ -0,0 +1,84 @@
+/*
+ * LoongArch translate functions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+static bool trans_b(DisasContext *ctx, arg_b *a)
+{
+ gen_goto_tb(ctx, 0, ctx->base.pc_next + (a->offs << 2));
+ 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 << 2));
+ ctx->base.is_jmp = DISAS_NORETURN;
+ return true;
+}
+
+static bool trans_jirl(DisasContext *ctx, arg_jirl *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ tcg_gen_addi_tl(cpu_pc, src1, (a->offs16) << 2);
+ 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_r2_bc(DisasContext *ctx, arg_fmt_rjrdoffs16 *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->offs16 << 2), cond);
+ return true;
+}
+
+static bool gen_rz_bc(DisasContext *ctx, arg_fmt_rjoffs21 *a, TCGCond cond)
+{
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = tcg_constant_tl(0);
+
+ gen_bc(ctx, src1, src2, (a->offs21 << 2), cond);
+ return true;
+}
+static bool gen_cz_bc(DisasContext *ctx, arg_fmt_cjoffs21 *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->offs21 << 2), cond);
+ return true;
+}
+
+TRANS(beq, gen_r2_bc, TCG_COND_EQ)
+TRANS(bne, gen_r2_bc, TCG_COND_NE)
+TRANS(blt, gen_r2_bc, TCG_COND_LT)
+TRANS(bge, gen_r2_bc, TCG_COND_GE)
+TRANS(bltu, gen_r2_bc, TCG_COND_LTU)
+TRANS(bgeu, gen_r2_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 ea776c2..077063e 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -38,6 +38,9 @@
%ca 15:3
%fcsrd 0:5
%fcsrs 5:5
+%offs21 0:s5 10:16
+%offs16 10:s16
+%offs 0:s10 10:16
#
# Argument sets
@@ -74,6 +77,11 @@
&fmt_rdcj rd cj
&fmt_fdrjrk fd rj rk
&fmt_fdrjsi12 fd rj si12
+&fmt_rjoffs21 rj offs21
+&fmt_cjoffs21 cj offs21
+&fmt_rdrjoffs16 rd rj offs16
+&fmt_offs offs
+&fmt_rjrdoffs16 rj rd offs16
#
# Formats
@@ -110,6 +118,11 @@
@fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj
@fmt_fdrjrk .... ........ ..... ..... ..... ..... &fmt_fdrjrk %fd %rj %rk
@fmt_fdrjsi12 .... ...... ............ ..... ..... &fmt_fdrjsi12 %fd %rj %si12
+@fmt_rjoffs21 .... .. ................ ..... ..... &fmt_rjoffs21 %rj %offs21
+@fmt_cjoffs21 .... .. ................ .. ... ..... &fmt_cjoffs21 %cj %offs21
+@fmt_rdrjoffs16 .... .. ................ ..... ..... &fmt_rdrjoffs16 %rd %rj %offs16
+@fmt_offs .... .. .......................... &fmt_offs %offs
+@fmt_rjrdoffs16 .... .. ................ ..... ..... &fmt_rjrdoffs16 %rj %rd %offs16
#
# Fixed point arithmetic operation instruction
@@ -448,3 +461,20 @@ fstgt_s 0011 10000111 01100 ..... ..... ..... @fmt_fdrjrk
fstgt_d 0011 10000111 01101 ..... ..... ..... @fmt_fdrjrk
fstle_s 0011 10000111 01110 ..... ..... ..... @fmt_fdrjrk
fstle_d 0011 10000111 01111 ..... ..... ..... @fmt_fdrjrk
+
+#
+# Branch instructions
+#
+beqz 0100 00 ................ ..... ..... @fmt_rjoffs21
+bnez 0100 01 ................ ..... ..... @fmt_rjoffs21
+bceqz 0100 10 ................ 00 ... ..... @fmt_cjoffs21
+bcnez 0100 10 ................ 01 ... ..... @fmt_cjoffs21
+jirl 0100 11 ................ ..... ..... @fmt_rdrjoffs16
+b 0101 00 .......................... @fmt_offs
+bl 0101 01 .......................... @fmt_offs
+beq 0101 10 ................ ..... ..... @fmt_rjrdoffs16
+bne 0101 11 ................ ..... ..... @fmt_rjrdoffs16
+blt 0110 00 ................ ..... ..... @fmt_rjrdoffs16
+bge 0110 01 ................ ..... ..... @fmt_rjrdoffs16
+bltu 0110 10 ................ ..... ..... @fmt_rjrdoffs16
+bgeu 0110 11 ................ ..... ..... @fmt_rjrdoffs16
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 7c2c80b..6bd3ce1 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -210,6 +210,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a,
#include "insn_trans/trans_fcnv.c"
#include "insn_trans/trans_fmov.c"
#include "insn_trans/trans_fmemory.c"
+#include "insn_trans/trans_branch.c"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 16/21] target/loongarch: Add disassembler
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (14 preceding siblings ...)
2021-09-02 12:41 ` [PATCH v4 15/21] target/loongarch: Add branch " Song Gao
@ 2021-09-02 12:41 ` Song Gao
2021-09-02 12:41 ` [PATCH v4 17/21] LoongArch Linux User Emulation Song Gao
` (4 subsequent siblings)
20 siblings, 0 replies; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:41 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch add support for disassembling via option '-d in_asm'.
Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
MAINTAINERS | 1 +
disas/loongarch.c | 2511 +++++++++++++++++++++++++++++++++++++++++++++++
disas/meson.build | 1 +
include/disas/dis-asm.h | 2 +
meson.build | 1 +
5 files changed, 2516 insertions(+)
create mode 100644 disas/loongarch.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 96225d8..146edbd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -214,6 +214,7 @@ LoongArch TCG CPUS
M: Song Gao <gaosong@loongson.cn>
S: Maintained
F: target/loongarch/
+F: disas/loongarch.c
M68K TCG CPUs
M: Laurent Vivier <laurent@vivier.eu>
diff --git a/disas/loongarch.c b/disas/loongarch.c
new file mode 100644
index 0000000..eb7475b
--- /dev/null
+++ b/disas/loongarch.c
@@ -0,0 +1,2511 @@
+/*
+ * QEMU LoongArch Disassembler
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited.
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+
+#define INSNLEN 4
+
+/* enums */
+typedef enum {
+ la_op_illegal = 0,
+ la_op_clo_w = 1,
+ la_op_clz_w = 2,
+ la_op_cto_w = 3,
+ la_op_ctz_w = 4,
+ la_op_clo_d = 5,
+ la_op_clz_d = 6,
+ la_op_cto_d = 7,
+ la_op_ctz_d = 8,
+ la_op_revb_2h = 9,
+ la_op_revb_4h = 10,
+ la_op_revb_2w = 11,
+ la_op_revb_d = 12,
+ la_op_revh_2w = 13,
+ la_op_revh_d = 14,
+ la_op_bitrev_4b = 15,
+ la_op_bitrev_8b = 16,
+ la_op_bitrev_w = 17,
+ la_op_bitrev_d = 18,
+ la_op_ext_w_h = 19,
+ la_op_ext_w_b = 20,
+ la_op_rdtime_d = 21,
+ la_op_cpucfg = 22,
+ la_op_asrtle_d = 23,
+ la_op_asrtgt_d = 24,
+ la_op_alsl_w = 25,
+ la_op_alsl_wu = 26,
+ la_op_bytepick_w = 27,
+ la_op_bytepick_d = 28,
+ la_op_add_w = 29,
+ la_op_add_d = 30,
+ la_op_sub_w = 31,
+ la_op_sub_d = 32,
+ la_op_slt = 33,
+ la_op_sltu = 34,
+ la_op_maskeqz = 35,
+ la_op_masknez = 36,
+ la_op_nor = 37,
+ la_op_and = 38,
+ la_op_or = 39,
+ la_op_xor = 40,
+ la_op_orn = 41,
+ la_op_andn = 42,
+ la_op_sll_w = 43,
+ la_op_srl_w = 44,
+ la_op_sra_w = 45,
+ la_op_sll_d = 46,
+ la_op_srl_d = 47,
+ la_op_sra_d = 48,
+ la_op_rotr_w = 49,
+ la_op_rotr_d = 50,
+ la_op_mul_w = 51,
+ la_op_mulh_w = 52,
+ la_op_mulh_wu = 53,
+ la_op_mul_d = 54,
+ la_op_mulh_d = 55,
+ la_op_mulh_du = 56,
+ la_op_mulw_d_w = 57,
+ la_op_mulw_d_wu = 58,
+ la_op_div_w = 59,
+ la_op_mod_w = 60,
+ la_op_div_wu = 61,
+ la_op_mod_wu = 62,
+ la_op_div_d = 63,
+ la_op_mod_d = 64,
+ la_op_div_du = 65,
+ la_op_mod_du = 66,
+ la_op_crc_w_b_w = 67,
+ la_op_crc_w_h_w = 68,
+ la_op_crc_w_w_w = 69,
+ la_op_crc_w_d_w = 70,
+ la_op_crcc_w_b_w = 71,
+ la_op_crcc_w_h_w = 72,
+ la_op_crcc_w_w_w = 73,
+ la_op_crcc_w_d_w = 74,
+ la_op_break = 75,
+ la_op_syscall = 76,
+ la_op_alsl_d = 77,
+ la_op_slli_w = 78,
+ la_op_slli_d = 79,
+ la_op_srli_w = 80,
+ la_op_srli_d = 81,
+ la_op_srai_w = 82,
+ la_op_srai_d = 83,
+ la_op_rotri_w = 84,
+ la_op_rotri_d = 85,
+ la_op_bstrins_w = 86,
+ la_op_bstrpick_w = 87,
+ la_op_bstrins_d = 88,
+ la_op_bstrpick_d = 89,
+ la_op_fadd_s = 90,
+ la_op_fadd_d = 91,
+ la_op_fsub_s = 92,
+ la_op_fsub_d = 93,
+ la_op_fmul_s = 94,
+ la_op_fmul_d = 95,
+ la_op_fdiv_s = 96,
+ la_op_fdiv_d = 97,
+ la_op_fmax_s = 98,
+ la_op_fmax_d = 99,
+ la_op_fmin_s = 100,
+ la_op_fmin_d = 101,
+ la_op_fmaxa_s = 102,
+ la_op_fmaxa_d = 103,
+ la_op_fmina_s = 104,
+ la_op_fmina_d = 105,
+ la_op_fscaleb_s = 106,
+ la_op_fscaleb_d = 107,
+ la_op_fcopysign_s = 108,
+ la_op_fcopysign_d = 109,
+ la_op_fabs_s = 110,
+ la_op_fabs_d = 111,
+ la_op_fneg_s = 112,
+ la_op_fneg_d = 113,
+ la_op_flogb_s = 114,
+ la_op_flogb_d = 115,
+ la_op_fclass_s = 116,
+ la_op_fclass_d = 117,
+ la_op_fsqrt_s = 118,
+ la_op_fsqrt_d = 119,
+ la_op_frecip_s = 120,
+ la_op_frecip_d = 121,
+ la_op_frsqrt_s = 122,
+ la_op_frsqrt_d = 123,
+ la_op_fmov_s = 124,
+ la_op_fmov_d = 125,
+ la_op_movgr2fr_w = 126,
+ la_op_movgr2fr_d = 127,
+ la_op_movgr2frh_w = 128,
+ la_op_movfr2gr_s = 129,
+ la_op_movfr2gr_d = 130,
+ la_op_movfrh2gr_s = 131,
+ la_op_movgr2fcsr = 132,
+ la_op_movfcsr2gr = 133,
+ la_op_movfr2cf = 134,
+ la_op_movcf2fr = 135,
+ la_op_movgr2cf = 136,
+ la_op_movcf2gr = 137,
+ la_op_fcvt_s_d = 138,
+ la_op_fcvt_d_s = 139,
+ la_op_ftintrm_w_s = 140,
+ la_op_ftintrm_w_d = 141,
+ la_op_ftintrm_l_s = 142,
+ la_op_ftintrm_l_d = 143,
+ la_op_ftintrp_w_s = 144,
+ la_op_ftintrp_w_d = 145,
+ la_op_ftintrp_l_s = 146,
+ la_op_ftintrp_l_d = 147,
+ la_op_ftintrz_w_s = 148,
+ la_op_ftintrz_w_d = 149,
+ la_op_ftintrz_l_s = 150,
+ la_op_ftintrz_l_d = 151,
+ la_op_ftintrne_w_s = 152,
+ la_op_ftintrne_w_d = 153,
+ la_op_ftintrne_l_s = 154,
+ la_op_ftintrne_l_d = 155,
+ la_op_ftint_w_s = 156,
+ la_op_ftint_w_d = 157,
+ la_op_ftint_l_s = 158,
+ la_op_ftint_l_d = 159,
+ la_op_ffint_s_w = 160,
+ la_op_ffint_s_l = 161,
+ la_op_ffint_d_w = 162,
+ la_op_ffint_d_l = 163,
+ la_op_frint_s = 164,
+ la_op_frint_d = 165,
+ la_op_slti = 166,
+ la_op_sltui = 167,
+ la_op_addi_w = 168,
+ la_op_addi_d = 169,
+ la_op_lu52i_d = 170,
+ la_op_addi = 171,
+ la_op_ori = 172,
+ la_op_xori = 173,
+ la_op_rdtimel_w = 174,
+ la_op_rdtimeh_w = 175,
+ la_op_fmadd_s = 176,
+ la_op_fmadd_d = 177,
+ la_op_fmsub_s = 178,
+ la_op_fmsub_d = 179,
+ la_op_fnmadd_s = 180,
+ la_op_fnmadd_d = 181,
+ la_op_fnmsub_s = 182,
+ la_op_fnmsub_d = 183,
+ la_op_fcmp_cond_s = 184,
+ la_op_fcmp_cond_d = 185,
+ la_op_fsel = 186,
+ la_op_addu16i_d = 187,
+ la_op_lu12i_w = 188,
+ la_op_lu32i_d = 189,
+ la_op_pcaddi = 190,
+ la_op_pcalau12i = 191,
+ la_op_pcaddu12i = 192,
+ la_op_pcaddu18i = 193,
+ la_op_ll_w = 194,
+ la_op_sc_w = 195,
+ la_op_ll_d = 196,
+ la_op_sc_d = 197,
+ la_op_ldptr_w = 198,
+ la_op_stptr_w = 199,
+ la_op_ldptr_d = 200,
+ la_op_stptr_d = 201,
+ la_op_ld_b = 202,
+ la_op_ld_h = 203,
+ la_op_ld_w = 204,
+ la_op_ld_d = 205,
+ la_op_st_b = 206,
+ la_op_st_h = 207,
+ la_op_st_w = 208,
+ la_op_st_d = 209,
+ la_op_ld_bu = 210,
+ la_op_ld_hu = 211,
+ la_op_ld_wu = 212,
+ la_op_preld = 213,
+ la_op_fld_s = 214,
+ la_op_fst_s = 215,
+ la_op_fld_d = 216,
+ la_op_fst_d = 217,
+ la_op_ldx_b = 218,
+ la_op_ldx_h = 219,
+ la_op_ldx_w = 220,
+ la_op_ldx_d = 221,
+ la_op_stx_b = 222,
+ la_op_stx_h = 223,
+ la_op_stx_w = 224,
+ la_op_stx_d = 225,
+ la_op_ldx_bu = 226,
+ la_op_ldx_hu = 227,
+ la_op_ldx_wu = 228,
+ la_op_fldx_s = 229,
+ la_op_fldx_d = 230,
+ la_op_fstx_s = 231,
+ la_op_fstx_d = 232,
+ la_op_amswap_w = 233,
+ la_op_amswap_d = 234,
+ la_op_amadd_w = 235,
+ la_op_amadd_d = 236,
+ la_op_amand_w = 237,
+ la_op_amand_d = 238,
+ la_op_amor_w = 239,
+ la_op_amor_d = 240,
+ la_op_amxor_w = 241,
+ la_op_amxor_d = 242,
+ la_op_ammax_w = 243,
+ la_op_ammax_d = 244,
+ la_op_ammin_w = 245,
+ la_op_ammin_d = 246,
+ la_op_ammax_wu = 247,
+ la_op_ammax_du = 248,
+ la_op_ammin_wu = 249,
+ la_op_ammin_du = 250,
+ la_op_amswap_db_w = 251,
+ la_op_amswap_db_d = 252,
+ la_op_amadd_db_w = 253,
+ la_op_amadd_db_d = 254,
+ la_op_amand_db_w = 255,
+ la_op_amand_db_d = 256,
+ la_op_amor_db_w = 257,
+ la_op_amor_db_d = 258,
+ la_op_amxor_db_w = 259,
+ la_op_amxor_db_d = 260,
+ la_op_ammax_db_w = 261,
+ la_op_ammax_db_d = 262,
+ la_op_ammin_db_w = 263,
+ la_op_ammin_db_d = 264,
+ la_op_ammax_db_wu = 265,
+ la_op_ammax_db_du = 266,
+ la_op_ammin_db_wu = 267,
+ la_op_ammin_db_du = 268,
+ la_op_dbar = 269,
+ la_op_ibar = 270,
+ la_op_fldgt_s = 271,
+ la_op_fldgt_d = 272,
+ la_op_fldle_s = 273,
+ la_op_fldle_d = 274,
+ la_op_fstgt_s = 275,
+ la_op_fstgt_d = 276,
+ ls_op_fstle_s = 277,
+ la_op_fstle_d = 278,
+ la_op_ldgt_b = 279,
+ la_op_ldgt_h = 280,
+ la_op_ldgt_w = 281,
+ la_op_ldgt_d = 282,
+ la_op_ldle_b = 283,
+ la_op_ldle_h = 284,
+ la_op_ldle_w = 285,
+ la_op_ldle_d = 286,
+ la_op_stgt_b = 287,
+ la_op_stgt_h = 288,
+ la_op_stgt_w = 289,
+ la_op_stgt_d = 290,
+ la_op_stle_b = 291,
+ la_op_stle_h = 292,
+ la_op_stle_w = 293,
+ la_op_stle_d = 294,
+ la_op_beqz = 295,
+ la_op_bnez = 296,
+ la_op_bceqz = 297,
+ la_op_bcnez = 298,
+ la_op_jirl = 299,
+ la_op_b = 300,
+ la_op_bl = 301,
+ la_op_beq = 302,
+ la_op_bne = 303,
+ la_op_blt = 304,
+ la_op_bge = 305,
+ la_op_bltu = 306,
+ la_op_bgeu = 307,
+
+} la_op;
+
+typedef enum {
+ la_codec_illegal,
+ la_codec_empty,
+ la_codec_2r,
+ la_codec_2r_u5,
+ la_codec_2r_u6,
+ la_codec_2r_2bw,
+ la_codec_2r_2bd,
+ la_codec_3r,
+ la_codec_3r_rd0,
+ la_codec_3r_sa2,
+ la_codec_3r_sa3,
+ la_codec_4r,
+ la_codec_r_im20,
+ la_codec_2r_im16,
+ la_codec_2r_im14,
+ la_codec_r_im14,
+ la_codec_2r_im12,
+ la_codec_im5_r_im12,
+ la_codec_2r_im8,
+ la_codec_r_sd,
+ la_codec_r_sj,
+ la_codec_r_cd,
+ la_codec_r_cj,
+ la_codec_r_seq,
+ la_codec_code,
+ la_codec_whint,
+ la_codec_invtlb,
+ la_codec_r_ofs21,
+ la_codec_cj_ofs21,
+ la_codec_ofs26,
+ la_codec_cond,
+ la_codec_sel,
+
+} la_codec;
+
+#define la_fmt_illegal "nte"
+#define la_fmt_empty "nt"
+#define la_fmt_sd_rj "ntA,1"
+#define la_fmt_rd_sj "nt0,B"
+#define la_fmt_rd_rj "nt0,1"
+#define la_fmt_rj_rk "nt1,2"
+#define la_fmt_rj_seq "nt1,x"
+#define la_fmt_rd_si20 "nt0,i(x)"
+#define la_fmt_rd_rj_ui5 "nt0,1,C"
+#define la_fmt_rd_rj_ui6 "nt0,1.C"
+#define la_fmt_rd_rj_level "nt0,1,x"
+#define la_fmt_rd_rj_msbw_lsbw "nt0,1,C,D"
+#define la_fmt_rd_rj_msbd_lsbd "nt0,1,C,D"
+#define la_fmt_rd_rj_si12 "nt0,1,i(x)"
+#define la_fmt_hint_rj_si12 "ntE,1,i(x)"
+#define la_fmt_rd_rj_csr "nt0,1,x"
+#define la_fmt_rd_csr "nt0,x"
+#define la_fmt_rd_rj_si14 "nt0,1,i(x)"
+#define la_fmt_rd_rj_si16 "nt0,1,i(x)"
+#define la_fmt_rd_rj_rk "nt0,1,2"
+#define la_fmt_fd_rj_rk "nt3,1,2"
+#define la_fmt_rd_rj_rk_sa2 "nt0,1,2,D"
+#define la_fmt_rd_rj_rk_sa3 "nt0,1,2,D"
+#define la_fmt_fd_rj "nt3,1"
+#define la_fmt_rd_fj "nt0,4"
+#define la_fmt_fd_fj "nt3,4"
+#define la_fmt_fd_fj_si12 "nt3,4,i(x)"
+#define la_fmt_fcsrd_rj "ntF,1"
+#define la_fmt_rd_fcsrs "nt0,G"
+#define la_fmt_cd_fj "ntH,4"
+#define la_fmt_fd_cj "nt3,I"
+#define la_fmt_fd_fj_fk "nt3,4,5"
+#define la_fmt_code "ntJ"
+#define la_fmt_whint "ntx"
+#define la_fmt_invtlb "ntx,1,2"
+#define la_fmt_offs26 "nto(X)p"
+#define la_fmt_rj_offs21 "nt1,o(X)p"
+#define la_fmt_cj_offs21 "ntQ,o(X)p"
+#define la_fmt_rd_rj_offs16 "nt0,1,o(X)"
+#define la_fmt_rj_rd_offs16 "nt1,0,o(X)p"
+#define la_fmt_s_cd_fj_fk "K.stH,4,5"
+#define la_fmt_d_cd_fj_fk "K.dtH,4,5"
+#define la_fmt_fd_fj_fk_fa "nt3,4,5,6"
+#define la_fmt_fd_fj_fk_ca "nt3,4,5,L"
+#define la_fmt_cop_rj_si12 "ntM,1,i(x)"
+
+/* structures */
+typedef struct {
+ uint32_t pc;
+ uint32_t insn;
+ int32_t imm;
+ int32_t imm2;
+ uint16_t op;
+ uint16_t code;
+ uint8_t codec;
+ uint8_t r1;
+ uint8_t r2;
+ uint8_t r3;
+ uint8_t r4;
+ uint8_t bit;
+} la_decode;
+
+typedef struct {
+ const char * const name;
+ const la_codec codec;
+ const char * const format;
+} la_opcode_data;
+
+/* reg names */
+const char * const loongarch_r_normal_name[32] = {
+ "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7",
+ "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
+ "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23",
+ "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31",
+};
+
+const char * const loongarch_f_normal_name[32] = {
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
+};
+
+const char * const loongarch_cr_normal_name[4] = {
+ "$scr0", "$scr1", "$scr2", "$scr3",
+};
+
+const char * const loongarch_c_normal_name[8] = {
+ "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7",
+};
+
+/* instruction data */
+const la_opcode_data opcode_data[] = {
+ { "illegal", la_codec_illegal, la_fmt_illegal },
+ { "clo.w", la_codec_2r, la_fmt_rd_rj },
+ { "clz.w", la_codec_2r, la_fmt_rd_rj },
+ { "cto.w", la_codec_2r, la_fmt_rd_rj },
+ { "ctz.w", la_codec_2r, la_fmt_rd_rj },
+ { "clo.d", la_codec_2r, la_fmt_rd_rj },
+ { "clz.d", la_codec_2r, la_fmt_rd_rj },
+ { "cto.d", la_codec_2r, la_fmt_rd_rj },
+ { "ctz_d", la_codec_2r, la_fmt_rd_rj },
+ { "revb.2h", la_codec_2r, la_fmt_rd_rj },
+ { "revb.4h", la_codec_2r, la_fmt_rd_rj },
+ { "revb.2w", la_codec_2r, la_fmt_rd_rj },
+ { "revb.d", la_codec_2r, la_fmt_rd_rj },
+ { "revh.2w", la_codec_2r, la_fmt_rd_rj },
+ { "revh.d", la_codec_2r, la_fmt_rd_rj },
+ { "bitrev.4b", la_codec_2r, la_fmt_rd_rj },
+ { "bitrev.8b", la_codec_2r, la_fmt_rd_rj },
+ { "bitrev.w", la_codec_2r, la_fmt_rd_rj },
+ { "bitrev.d", la_codec_2r, la_fmt_rd_rj },
+ { "ext.w.h", la_codec_2r, la_fmt_rd_rj },
+ { "ext.w.b", la_codec_2r, la_fmt_rd_rj },
+ { "rdtime.d", la_codec_2r, la_fmt_rd_rj },
+ { "cpucfg", la_codec_2r, la_fmt_rd_rj },
+ { "asrtle.d", la_codec_3r_rd0, la_fmt_rj_rk },
+ { "asrtgt.d", la_codec_3r_rd0, la_fmt_rj_rk },
+ { "alsl.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
+ { "alsl.wu", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
+ { "bytepick.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
+ { "bytepick.d", la_codec_3r_sa3, la_fmt_rd_rj_rk_sa3 },
+ { "add.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "add.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "sub.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "sub.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "slt", la_codec_3r, la_fmt_rd_rj_rk },
+ { "sltu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "maskeqz", la_codec_3r, la_fmt_rd_rj_rk },
+ { "masknez", la_codec_3r, la_fmt_rd_rj_rk },
+ { "nor", la_codec_3r, la_fmt_rd_rj_rk },
+ { "and", la_codec_3r, la_fmt_rd_rj_rk },
+ { "or", la_codec_3r, la_fmt_rd_rj_rk },
+ { "xor", la_codec_3r, la_fmt_rd_rj_rk },
+ { "orn", la_codec_3r, la_fmt_rd_rj_rk },
+ { "andn", la_codec_3r, la_fmt_rd_rj_rk },
+ { "sll.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "srl.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "sra.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "sll.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "srl.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "sra.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "rotr.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "rotr.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mul.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mulh.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mulh.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mul.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mulh.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mulh.du", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mulw.d.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mulw.d.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "div.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mod.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "div.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mod.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "div.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mod.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "div.du", la_codec_3r, la_fmt_rd_rj_rk },
+ { "mod.du", la_codec_3r, la_fmt_rd_rj_rk },
+ { "crc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "crc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "crc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "crc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "crcc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "crcc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "crcc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "crcc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "break", la_codec_code, la_fmt_code },
+ { "syscall", la_codec_code, la_fmt_code },
+ { "alsl.d", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
+ { "slli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
+ { "slli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
+ { "srli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
+ { "srli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
+ { "srai.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
+ { "srai.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
+ { "rotri.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
+ { "rotri.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
+ { "bstrins.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw },
+ { "bstrpick.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw },
+ { "bstrins.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd },
+ { "bstrpick.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd },
+ { "fadd.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fadd.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fsub.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fsub.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmul.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmul.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fdiv.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fdiv.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmax.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmax.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmin.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmin.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmaxa.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmaxa.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmina.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fmina.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fscaleb.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fscaleb.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fcopysign.s", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fcopysign.d", la_codec_3r, la_fmt_fd_fj_fk },
+ { "fabs.s", la_codec_2r, la_fmt_fd_fj },
+ { "fabs.d", la_codec_2r, la_fmt_fd_fj },
+ { "fneg.s", la_codec_2r, la_fmt_fd_fj },
+ { "fneg.d", la_codec_2r, la_fmt_fd_fj },
+ { "flogb.s", la_codec_2r, la_fmt_fd_fj },
+ { "flogb.d", la_codec_2r, la_fmt_fd_fj },
+ { "fclass.s", la_codec_2r, la_fmt_fd_fj },
+ { "fclass.d", la_codec_2r, la_fmt_fd_fj },
+ { "fsqrt.s", la_codec_2r, la_fmt_fd_fj },
+ { "fsqrt.d", la_codec_2r, la_fmt_fd_fj },
+ { "frecip.s", la_codec_2r, la_fmt_fd_fj },
+ { "frecip.d", la_codec_2r, la_fmt_fd_fj },
+ { "frsqrt.s", la_codec_2r, la_fmt_fd_fj },
+ { "frsqrt.d", la_codec_2r, la_fmt_fd_fj },
+ { "fmov.s", la_codec_2r, la_fmt_fd_fj },
+ { "fmov.d", la_codec_2r, la_fmt_fd_fj },
+ { "movgr2fr.w", la_codec_2r, la_fmt_fd_rj },
+ { "movgr2fr.d", la_codec_2r, la_fmt_fd_rj },
+ { "movgr2frh.w", la_codec_2r, la_fmt_fd_rj },
+ { "movfr2gr.s", la_codec_2r, la_fmt_rd_fj },
+ { "movfr2gr.d", la_codec_2r, la_fmt_rd_fj },
+ { "movfrh2gr.s", la_codec_2r, la_fmt_rd_fj },
+ { "movgr2fcsr", la_codec_2r, la_fmt_fcsrd_rj },
+ { "movfcsr2gr", la_codec_2r, la_fmt_rd_fcsrs },
+ { "movfr2cf", la_codec_r_cd, la_fmt_cd_fj },
+ { "movcf2fr", la_codec_r_cj, la_fmt_fd_cj },
+ { "movgr2cf", la_codec_r_cd, la_fmt_cd_fj },
+ { "movcf2gr", la_codec_r_cj, la_fmt_fd_cj },
+ { "fcvt.s.d", la_codec_2r, la_fmt_fd_fj },
+ { "fcvt.d.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrm.w.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrm.w.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrm.l.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrm.l.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrp.w.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrp.w.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrp.l.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrp.l.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrz.w.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrz.w.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrz.l.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrz.l.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrne.w.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrne.w.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrne.l.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftintrne.l.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftint.w.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftint.w.d", la_codec_2r, la_fmt_fd_fj },
+ { "ftint.l.s", la_codec_2r, la_fmt_fd_fj },
+ { "ftint.l.d", la_codec_2r, la_fmt_fd_fj },
+ { "ffint.s.w", la_codec_2r, la_fmt_fd_fj },
+ { "ffint.s.l", la_codec_2r, la_fmt_fd_fj },
+ { "ffint.d.w", la_codec_2r, la_fmt_fd_fj },
+ { "ffint.d.l", la_codec_2r, la_fmt_fd_fj },
+ { "frint.s", la_codec_2r, la_fmt_fd_fj },
+ { "frint.d", la_codec_2r, la_fmt_fd_fj },
+ { "slti", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "sltui", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "addi.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "addi.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "lu52i.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "addi", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "ori", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "xori", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "rdtimel.w", la_codec_2r, la_fmt_rd_rj },
+ { "rdtimeh.w", la_codec_2r, la_fmt_rd_rj },
+ { "fmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
+ { "fmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
+ { "fmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
+ { "fmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
+ { "fnmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
+ { "fnmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
+ { "fnmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
+ { "fnmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
+ { "fcmp.cond.s", la_codec_cond, la_fmt_s_cd_fj_fk },
+ { "fcmp.cond.d", la_codec_cond, la_fmt_d_cd_fj_fk },
+ { "fsel", la_codec_sel, la_fmt_fd_fj_fk_ca },
+ { "addu16i.d", la_codec_2r_im16, la_fmt_rd_rj_si16 },
+ { "lu12i.w", la_codec_r_im20, la_fmt_rd_si20 },
+ { "lu32i.d", la_codec_r_im20, la_fmt_rd_si20 },
+ { "pcaddi", la_codec_r_im20, la_fmt_rd_si20 },
+ { "pcalau12i", la_codec_r_im20, la_fmt_rd_si20 },
+ { "pcaddu12i", la_codec_r_im20, la_fmt_rd_si20 },
+ { "pcaddu18i", la_codec_r_im20, la_fmt_rd_si20 },
+ { "ll.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+ { "sc.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+ { "ll.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+ { "sc.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+ { "ldptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+ { "stptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+ { "ldptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+ { "stptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+ { "ld.b", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "ld.h", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "ld.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "ld.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "st.b", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "st.h", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "st.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "st.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "ld.bu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "ld.hu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "ld.wu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+ { "preld", la_codec_2r_im12, la_fmt_hint_rj_si12 },
+ { "fld.s", la_codec_2r_im12, la_fmt_fd_fj_si12 },
+ { "fst.s", la_codec_2r_im12, la_fmt_fd_fj_si12 },
+ { "fld.d", la_codec_2r_im12, la_fmt_fd_fj_si12 },
+ { "fst.d", la_codec_2r_im12, la_fmt_fd_fj_si12 },
+ { "ldx.b", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldx.h", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldx.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldx.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stx.b", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stx.h", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stx.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stx.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldx.bu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldx.hu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldx.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "fldx.s", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fldx.d", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fstx.s", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fstx.d", la_codec_3r, la_fmt_fd_rj_rk },
+ { "amswap.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amswap.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amadd.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amadd.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amand.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amand.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amor.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amor.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amxor.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amxor.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammax.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammax.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammin.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammin.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammax.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammax.du", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammin.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammin.du", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amswap.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amswap.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amadd.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amadd.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amand.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amand.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amor.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amor.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amxor.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "amxor.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammax.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammax.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammin.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammin.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammax.db.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammax.db.du", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammin.db.wu", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ammin.db.du", la_codec_3r, la_fmt_rd_rj_rk },
+ { "dbar", la_codec_whint, la_fmt_whint },
+ { "ibar", la_codec_whint, la_fmt_whint },
+ { "fldgt.s", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fldgt.d", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fldle.s", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fldle.d", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fstgt.s", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fstgt.d", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fstle.s", la_codec_3r, la_fmt_fd_rj_rk },
+ { "fstle.d", la_codec_3r, la_fmt_fd_rj_rk },
+ { "ldgt.b", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldgt.h", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldgt.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldgt.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldle.b", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldle.h", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldle.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "ldle.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stgt.b", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stgt.h", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stgt.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stgt.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stle.b", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stle.h", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stle.w", la_codec_3r, la_fmt_rd_rj_rk },
+ { "stle.d", la_codec_3r, la_fmt_rd_rj_rk },
+ { "beqz", la_codec_r_ofs21, la_fmt_rj_offs21 },
+ { "bnez", la_codec_r_ofs21, la_fmt_rj_offs21 },
+ { "bceqz", la_codec_cj_ofs21, la_fmt_cj_offs21 },
+ { "bcnez", la_codec_cj_ofs21, la_fmt_cj_offs21 },
+ { "jirl", la_codec_2r_im16, la_fmt_rd_rj_offs16 },
+ { "b", la_codec_ofs26, la_fmt_offs26 },
+ { "bl", la_codec_ofs26, la_fmt_offs26 },
+ { "beq", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+ { "bne", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+ { "blt", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+ { "bge", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+ { "bltu", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+ { "bgeu", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+
+};
+
+
+/* decode opcode */
+static void decode_insn_opcode(la_decode *dec)
+{
+ uint32_t insn = dec->insn;
+ uint16_t op = la_op_illegal;
+ switch ((insn >> 26) & 0x3f) {
+ case 0x0:
+ switch ((insn >> 22) & 0xf) {
+ case 0x0:
+ switch ((insn >> 18) & 0xf) {
+ case 0x0:
+ switch ((insn >> 15) & 0x7) {
+ case 0x0:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x4:
+ op = la_op_clo_w;
+ break;
+ case 0x5:
+ op = la_op_clz_w;
+ break;
+ case 0x6:
+ op = la_op_cto_w;
+ break;
+ case 0x7:
+ op = la_op_ctz_w;
+ break;
+ case 0x8:
+ op = la_op_clo_d;
+ break;
+ case 0x9:
+ op = la_op_clz_d;
+ break;
+ case 0xa:
+ op = la_op_cto_d;
+ break;
+ case 0xb:
+ op = la_op_ctz_d;
+ break;
+ case 0xc:
+ op = la_op_revb_2h;
+ break;
+ case 0xd:
+ op = la_op_revb_4h;
+ break;
+ case 0xe:
+ op = la_op_revb_2w;
+ break;
+ case 0xf:
+ op = la_op_revb_d;
+ break;
+ case 0x10:
+ op = la_op_revh_2w;
+ break;
+ case 0x11:
+ op = la_op_revh_d;
+ break;
+ case 0x12:
+ op = la_op_bitrev_4b;
+ break;
+ case 0x13:
+ op = la_op_bitrev_8b;
+ break;
+ case 0x14:
+ op = la_op_bitrev_w;
+ break;
+ case 0x15:
+ op = la_op_bitrev_d;
+ break;
+ case 0x16:
+ op = la_op_ext_w_h;
+ break;
+ case 0x17:
+ op = la_op_ext_w_b;
+ break;
+ case 0x18:
+ op = la_op_rdtimel_w;
+ break;
+ case 0x19:
+ op = la_op_rdtimeh_w;
+ break;
+ case 0x1a:
+ op = la_op_rdtime_d;
+ break;
+ case 0x1b:
+ op = la_op_cpucfg;
+ break;
+ }
+ break;
+ case 0x2:
+ switch (insn & 0x0000001f) {
+ case 0x00000000:
+ op = la_op_asrtle_d;
+ break;
+ }
+ break;
+ case 0x3:
+ switch (insn & 0x0000001f) {
+ case 0x00000000:
+ op = la_op_asrtgt_d;
+ break;
+ }
+ break;
+ }
+ break;
+ case 0x1:
+ switch ((insn >> 17) & 0x1) {
+ case 0x0:
+ op = la_op_alsl_w;
+ break;
+ case 0x1:
+ op = la_op_alsl_wu;
+ break;
+ }
+ break;
+ case 0x2:
+ switch ((insn >> 17) & 0x1) {
+ case 0x0:
+ op = la_op_bytepick_w;
+ break;
+ }
+ break;
+ case 0x3:
+ op = la_op_bytepick_d;
+ break;
+ case 0x4:
+ switch ((insn >> 15) & 0x7) {
+ case 0x0:
+ op = la_op_add_w;
+ break;
+ case 0x1:
+ op = la_op_add_d;
+ break;
+ case 0x2:
+ op = la_op_sub_w;
+ break;
+ case 0x3:
+ op = la_op_sub_d;
+ break;
+ case 0x4:
+ op = la_op_slt;
+ break;
+ case 0x5:
+ op = la_op_sltu;
+ break;
+ case 0x6:
+ op = la_op_maskeqz;
+ break;
+ case 0x7:
+ op = la_op_masknez;
+ break;
+ }
+ break;
+ case 0x5:
+ switch ((insn >> 15) & 0x7) {
+ case 0x0:
+ op = la_op_nor;
+ break;
+ case 0x1:
+ op = la_op_and;
+ break;
+ case 0x2:
+ op = la_op_or;
+ break;
+ case 0x3:
+ op = la_op_xor;
+ break;
+ case 0x4:
+ op = la_op_orn;
+ break;
+ case 0x5:
+ op = la_op_andn;
+ break;
+ case 0x6:
+ op = la_op_sll_w;
+ break;
+ case 0x7:
+ op = la_op_srl_w;
+ break;
+ }
+ break;
+ case 0x6:
+ switch ((insn >> 15) & 0x7) {
+ case 0x0:
+ op = la_op_sra_w;
+ break;
+ case 0x1:
+ op = la_op_sll_d;
+ break;
+ case 0x2:
+ op = la_op_srl_d;
+ break;
+ case 0x3:
+ op = la_op_sra_d;
+ break;
+ case 0x6:
+ op = la_op_rotr_w;
+ break;
+ case 0x7:
+ op = la_op_rotr_d;
+ break;
+ }
+ break;
+ case 0x7:
+ switch ((insn >> 15) & 0x7) {
+ case 0x0:
+ op = la_op_mul_w;
+ break;
+ case 0x1:
+ op = la_op_mulh_w;
+ break;
+ case 0x2:
+ op = la_op_mulh_wu;
+ break;
+ case 0x3:
+ op = la_op_mul_d;
+ break;
+ case 0x4:
+ op = la_op_mulh_d;
+ break;
+ case 0x5:
+ op = la_op_mulh_du;
+ break;
+ case 0x6:
+ op = la_op_mulw_d_w;
+ break;
+ case 0x7:
+ op = la_op_mulw_d_wu;
+ break;
+ }
+ break;
+ case 0x8:
+ switch ((insn >> 15) & 0x7) {
+ case 0x0:
+ op = la_op_div_w;
+ break;
+ case 0x1:
+ op = la_op_mod_w;
+ break;
+ case 0x2:
+ op = la_op_div_wu;
+ break;
+ case 0x3:
+ op = la_op_mod_wu;
+ break;
+ case 0x4:
+ op = la_op_div_d;
+ break;
+ case 0x5:
+ op = la_op_mod_d;
+ break;
+ case 0x6:
+ op = la_op_div_du;
+ break;
+ case 0x7:
+ op = la_op_mod_du;
+ break;
+ }
+ break;
+ case 0x9:
+ switch ((insn >> 15) & 0x7) {
+ case 0x0:
+ op = la_op_crc_w_b_w;
+ break;
+ case 0x1:
+ op = la_op_crc_w_h_w;
+ break;
+ case 0x2:
+ op = la_op_crc_w_w_w;
+ break;
+ case 0x3:
+ op = la_op_crc_w_d_w;
+ break;
+ case 0x4:
+ op = la_op_crcc_w_b_w;
+ break;
+ case 0x5:
+ op = la_op_crcc_w_h_w;
+ break;
+ case 0x6:
+ op = la_op_crcc_w_w_w;
+ break;
+ case 0x7:
+ op = la_op_crcc_w_d_w;
+ break;
+ }
+ break;
+ case 0xa:
+ switch ((insn >> 15) & 0x7) {
+ case 0x4:
+ op = la_op_break;
+ break;
+ case 0x6:
+ op = la_op_syscall;
+ break;
+ }
+ break;
+ case 0xb:
+ switch ((insn >> 17) & 0x1) {
+ case 0x0:
+ op = la_op_alsl_d;
+ break;
+ }
+ break;
+ }
+ break;
+ case 0x1:
+ switch ((insn >> 21) & 0x1) {
+ case 0x0:
+ switch ((insn >> 16) & 0x1f) {
+ case 0x0:
+ switch ((insn >> 15) & 0x1) {
+ case 0x1:
+ op = la_op_slli_w;
+ break;
+ }
+ break;
+ case 0x1:
+ op = la_op_slli_d;
+ break;
+ case 0x4:
+ switch ((insn >> 15) & 0x1) {
+ case 0x1:
+ op = la_op_srli_w;
+ break;
+ }
+ break;
+ case 0x5:
+ op = la_op_srli_d;
+ break;
+ case 0x8:
+ switch ((insn >> 15) & 0x1) {
+ case 0x1:
+ op = la_op_srai_w;
+ break;
+ }
+ break;
+ case 0x9:
+ op = la_op_srai_d;
+ break;
+ case 0xc:
+ switch ((insn >> 15) & 0x1) {
+ case 0x1:
+ op = la_op_rotri_w;
+ break;
+ }
+ break;
+ case 0xd:
+ op = la_op_rotri_d;
+ break;
+ }
+ break;
+ case 0x1:
+ switch ((insn >> 15) & 0x1) {
+ case 0x0:
+ op = la_op_bstrins_w;
+ break;
+ case 0x1:
+ op = la_op_bstrpick_w;
+ break;
+ }
+ break;
+ }
+ break;
+ case 0x2:
+ op = la_op_bstrins_d;
+ break;
+ case 0x3:
+ op = la_op_bstrpick_d;
+ break;
+ case 0x4:
+ switch ((insn >> 15) & 0x7f) {
+ case 0x1:
+ op = la_op_fadd_s;
+ break;
+ case 0x2:
+ op = la_op_fadd_d;
+ break;
+ case 0x5:
+ op = la_op_fsub_s;
+ break;
+ case 0x6:
+ op = la_op_fsub_d;
+ break;
+ case 0x9:
+ op = la_op_fmul_s;
+ break;
+ case 0xa:
+ op = la_op_fmul_d;
+ break;
+ case 0xd:
+ op = la_op_fdiv_s;
+ break;
+ case 0xe:
+ op = la_op_fdiv_d;
+ break;
+ case 0x11:
+ op = la_op_fmax_s;
+ break;
+ case 0x12:
+ op = la_op_fmax_d;
+ break;
+ case 0x15:
+ op = la_op_fmin_s;
+ break;
+ case 0x16:
+ op = la_op_fmin_d;
+ break;
+ case 0x19:
+ op = la_op_fmaxa_s;
+ break;
+ case 0x1a:
+ op = la_op_fmaxa_d;
+ break;
+ case 0x1d:
+ op = la_op_fmina_s;
+ break;
+ case 0x1e:
+ op = la_op_fmina_d;
+ break;
+ case 0x21:
+ op = la_op_fscaleb_s;
+ break;
+ case 0x22:
+ op = la_op_fscaleb_d;
+ break;
+ case 0x25:
+ op = la_op_fcopysign_s;
+ break;
+ case 0x26:
+ op = la_op_fcopysign_d;
+ break;
+ case 0x28:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x1:
+ op = la_op_fabs_s;
+ break;
+ case 0x2:
+ op = la_op_fabs_d;
+ break;
+ case 0x5:
+ op = la_op_fneg_s;
+ break;
+ case 0x6:
+ op = la_op_fneg_d;
+ break;
+ case 0x9:
+ op = la_op_flogb_s;
+ break;
+ case 0xa:
+ op = la_op_flogb_d;
+ break;
+ case 0xd:
+ op = la_op_fclass_s;
+ break;
+ case 0xe:
+ op = la_op_fclass_d;
+ break;
+ case 0x11:
+ op = la_op_fsqrt_s;
+ break;
+ case 0x12:
+ op = la_op_fsqrt_d;
+ break;
+ case 0x15:
+ op = la_op_frecip_s;
+ break;
+ case 0x16:
+ op = la_op_frecip_d;
+ break;
+ case 0x19:
+ op = la_op_frsqrt_s;
+ break;
+ case 0x1a:
+ op = la_op_frsqrt_d;
+ break;
+ }
+ break;
+ case 0x29:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x5:
+ op = la_op_fmov_s;
+ break;
+ case 0x6:
+ op = la_op_fmov_d;
+ break;
+ case 0x9:
+ op = la_op_movgr2fr_w;
+ break;
+ case 0xa:
+ op = la_op_movgr2fr_d;
+ break;
+ case 0xb:
+ op = la_op_movgr2frh_w;
+ break;
+ case 0xd:
+ op = la_op_movfr2gr_s;
+ break;
+ case 0xe:
+ op = la_op_movfr2gr_d;
+ break;
+ case 0xf:
+ op = la_op_movfrh2gr_s;
+ break;
+ case 0x10:
+ op = la_op_movgr2fcsr;
+ break;
+ case 0x12:
+ op = la_op_movfcsr2gr;
+ break;
+ case 0x14:
+ switch ((insn >> 3) & 0x3) {
+ case 0x0:
+ op = la_op_movfr2cf;
+ break;
+ }
+ break;
+ case 0x15:
+ switch ((insn >> 8) & 0x3) {
+ case 0x0:
+ op = la_op_movcf2fr;
+ break;
+ }
+ break;
+ case 0x16:
+ switch ((insn >> 3) & 0x3) {
+ case 0x0:
+ op = la_op_movgr2cf;
+ break;
+ }
+ break;
+ case 0x17:
+ switch ((insn >> 8) & 0x3) {
+ case 0x0:
+ op = la_op_movcf2gr;
+ break;
+ }
+ break;
+ }
+ break;
+ case 0x32:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x6:
+ op = la_op_fcvt_s_d;
+ break;
+ case 0x9:
+ op = la_op_fcvt_d_s;
+ break;
+ }
+ break;
+ case 0x34:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x1:
+ op = la_op_ftintrm_w_s;
+ break;
+ case 0x2:
+ op = la_op_ftintrm_w_d;
+ break;
+ case 0x9:
+ op = la_op_ftintrm_l_s;
+ break;
+ case 0xa:
+ op = la_op_ftintrm_l_d;
+ break;
+ case 0x11:
+ op = la_op_ftintrp_w_s;
+ break;
+ case 0x12:
+ op = la_op_ftintrp_w_d;
+ break;
+ case 0x19:
+ op = la_op_ftintrp_l_s;
+ break;
+ case 0x1a:
+ op = la_op_ftintrp_l_d;
+ break;
+ }
+ break;
+ case 0x35:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x1:
+ op = la_op_ftintrz_w_s;
+ break;
+ case 0x2:
+ op = la_op_ftintrz_w_d;
+ break;
+ case 0x9:
+ op = la_op_ftintrz_l_s;
+ break;
+ case 0xa:
+ op = la_op_ftintrz_l_d;
+ break;
+ case 0x11:
+ op = la_op_ftintrne_w_s;
+ break;
+ case 0x12:
+ op = la_op_ftintrne_w_d;
+ break;
+ case 0x19:
+ op = la_op_ftintrne_l_s;
+ break;
+ case 0x1a:
+ op = la_op_ftintrne_l_d;
+ break;
+ }
+ break;
+ case 0x36:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x1:
+ op = la_op_ftint_w_s;
+ break;
+ case 0x2:
+ op = la_op_ftint_w_d;
+ break;
+ case 0x9:
+ op = la_op_ftint_l_s;
+ break;
+ case 0xa:
+ op = la_op_ftint_l_d;
+ break;
+ }
+ break;
+ case 0x3a:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x4:
+ op = la_op_ffint_s_w;
+ break;
+ case 0x6:
+ op = la_op_ffint_s_l;
+ break;
+ case 0x8:
+ op = la_op_ffint_d_w;
+ break;
+ case 0xa:
+ op = la_op_ffint_d_l;
+ break;
+ }
+ break;
+ case 0x3c:
+ switch ((insn >> 10) & 0x1f) {
+ case 0x11:
+ op = la_op_frint_s;
+ break;
+ case 0x12:
+ op = la_op_frint_d;
+ break;
+ }
+ break;
+ }
+ break;
+ case 0x8:
+ op = la_op_slti;
+ break;
+ case 0x9:
+ op = la_op_sltui;
+ break;
+ case 0xa:
+ op = la_op_addi_w;
+ break;
+ case 0xb:
+ op = la_op_addi_d;
+ break;
+ case 0xc:
+ op = la_op_lu52i_d;
+ break;
+ case 0xd:
+ op = la_op_addi;
+ break;
+ case 0xe:
+ op = la_op_ori;
+ break;
+ case 0xf:
+ op = la_op_xori;
+ break;
+ }
+ break;
+ case 0x2:
+ switch ((insn >> 20) & 0x3f) {
+ case 0x1:
+ op = la_op_fmadd_s;
+ break;
+ case 0x2:
+ op = la_op_fmadd_d;
+ break;
+ case 0x5:
+ op = la_op_fmsub_s;
+ break;
+ case 0x6:
+ op = la_op_fmsub_d;
+ break;
+ case 0x9:
+ op = la_op_fnmadd_s;
+ break;
+ case 0xa:
+ op = la_op_fnmadd_d;
+ break;
+ case 0xd:
+ op = la_op_fnmsub_s;
+ break;
+ case 0xe:
+ op = la_op_fnmsub_d;
+ break;
+ }
+ break;
+ case 0x3:
+ switch ((insn >> 20) & 0x3f) {
+ case 0x1:
+ switch ((insn >> 3) & 0x3) {
+ case 0x0:
+ op = la_op_fcmp_cond_s;
+ break;
+ }
+ break;
+ case 0x2:
+ switch ((insn >> 3) & 0x3) {
+ case 0x0:
+ op = la_op_fcmp_cond_d;
+ break;
+ }
+ break;
+ case 0x10:
+ switch ((insn >> 18) & 0x3) {
+ case 0x0:
+ op = la_op_fsel;
+ break;
+ }
+ break;
+ }
+ break;
+ case 0x4:
+ op = la_op_addu16i_d;
+ break;
+ case 0x5:
+ switch ((insn >> 25) & 0x1) {
+ case 0x0:
+ op = la_op_lu12i_w;
+ break;
+ case 0x1:
+ op = la_op_lu32i_d;
+ break;
+ }
+ break;
+ case 0x6:
+ switch ((insn >> 25) & 0x1) {
+ case 0x0:
+ op = la_op_pcaddi;
+ break;
+ case 0x1:
+ op = la_op_pcalau12i;
+ break;
+ }
+ break;
+ case 0x7:
+ switch ((insn >> 25) & 0x1) {
+ case 0x0:
+ op = la_op_pcaddu12i;
+ break;
+ case 0x1:
+ op = la_op_pcaddu18i;
+ break;
+ }
+ break;
+ case 0x8:
+ switch ((insn >> 24) & 0x3) {
+ case 0x0:
+ op = la_op_ll_w;
+ break;
+ case 0x1:
+ op = la_op_sc_w;
+ break;
+ case 0x2:
+ op = la_op_ll_d;
+ break;
+ case 0x3:
+ op = la_op_sc_d;
+ break;
+ }
+ break;
+ case 0x9:
+ switch ((insn >> 24) & 0x3) {
+ case 0x0:
+ op = la_op_ldptr_w;
+ break;
+ case 0x1:
+ op = la_op_stptr_w;
+ break;
+ case 0x2:
+ op = la_op_ldptr_d;
+ break;
+ case 0x3:
+ op = la_op_stptr_d;
+ break;
+ }
+ break;
+ case 0xa:
+ switch ((insn >> 22) & 0xf) {
+ case 0x0:
+ op = la_op_ld_b;
+ break;
+ case 0x1:
+ op = la_op_ld_h;
+ break;
+ case 0x2:
+ op = la_op_ld_w;
+ break;
+ case 0x3:
+ op = la_op_ld_d;
+ break;
+ case 0x4:
+ op = la_op_st_b;
+ break;
+ case 0x5:
+ op = la_op_st_h;
+ break;
+ case 0x6:
+ op = la_op_st_w;
+ break;
+ case 0x7:
+ op = la_op_st_d;
+ break;
+ case 0x8:
+ op = la_op_ld_bu;
+ break;
+ case 0x9:
+ op = la_op_ld_hu;
+ break;
+ case 0xa:
+ op = la_op_ld_wu;
+ break;
+ case 0xb:
+ op = la_op_preld;
+ break;
+ case 0xc:
+ op = la_op_fld_s;
+ break;
+ case 0xd:
+ op = la_op_fst_s;
+ break;
+ case 0xe:
+ op = la_op_fld_d;
+ break;
+ case 0xf:
+ op = la_op_fst_d;
+ break;
+ }
+ break;
+ case 0xe:
+ switch ((insn >> 15) & 0x7ff) {
+ case 0x0:
+ op = la_op_ldx_b;
+ break;
+ case 0x8:
+ op = la_op_ldx_h;
+ break;
+ case 0x10:
+ op = la_op_ldx_w;
+ break;
+ case 0x18:
+ op = la_op_ldx_d;
+ break;
+ case 0x20:
+ op = la_op_stx_b;
+ break;
+ case 0x28:
+ op = la_op_stx_h;
+ break;
+ case 0x30:
+ op = la_op_stx_w;
+ break;
+ case 0x38:
+ op = la_op_stx_d;
+ break;
+ case 0x40:
+ op = la_op_ldx_bu;
+ break;
+ case 0x48:
+ op = la_op_ldx_hu;
+ break;
+ case 0x50:
+ op = la_op_ldx_wu;
+ break;
+ case 0x60:
+ op = la_op_fldx_s;
+ break;
+ case 0x68:
+ op = la_op_fldx_d;
+ break;
+ case 0x70:
+ op = la_op_fstx_s;
+ break;
+ case 0x78:
+ op = la_op_fstx_d;
+ break;
+ case 0xc0:
+ op = la_op_amswap_w;
+ break;
+ case 0xc1:
+ op = la_op_amswap_d;
+ break;
+ case 0xc2:
+ op = la_op_amadd_w;
+ break;
+ case 0xc3:
+ op = la_op_amadd_d;
+ break;
+ case 0xc4:
+ op = la_op_amand_w;
+ break;
+ case 0xc5:
+ op = la_op_amand_d;
+ break;
+ case 0xc6:
+ op = la_op_amor_w;
+ break;
+ case 0xc7:
+ op = la_op_amor_d;
+ break;
+ case 0xc8:
+ op = la_op_amxor_w;
+ break;
+ case 0xc9:
+ op = la_op_amxor_d;
+ break;
+ case 0xca:
+ op = la_op_ammax_w;
+ break;
+ case 0xcb:
+ op = la_op_ammax_d;
+ break;
+ case 0xcc:
+ op = la_op_ammin_w;
+ break;
+ case 0xcd:
+ op = la_op_ammin_d;
+ break;
+ case 0xce:
+ op = la_op_ammax_wu;
+ break;
+ case 0xcf:
+ op = la_op_ammax_du;
+ break;
+ case 0xd0:
+ op = la_op_ammin_wu;
+ break;
+ case 0xd1:
+ op = la_op_ammin_du;
+ break;
+ case 0xd2:
+ op = la_op_amswap_db_w;
+ break;
+ case 0xd3:
+ op = la_op_amswap_db_d;
+ break;
+ case 0xd4:
+ op = la_op_amadd_db_w;
+ break;
+ case 0xd5:
+ op = la_op_amadd_db_d;
+ break;
+ case 0xd6:
+ op = la_op_amand_db_w;
+ break;
+ case 0xd7:
+ op = la_op_amand_db_d;
+ break;
+ case 0xd8:
+ op = la_op_amor_db_w;
+ break;
+ case 0xd9:
+ op = la_op_amor_db_d;
+ break;
+ case 0xda:
+ op = la_op_amxor_db_w;
+ break;
+ case 0xdb:
+ op = la_op_amxor_db_d;
+ break;
+ case 0xdc:
+ op = la_op_ammax_db_w;
+ break;
+ case 0xdd:
+ op = la_op_ammax_db_d;
+ break;
+ case 0xde:
+ op = la_op_ammin_db_w;
+ break;
+ case 0xdf:
+ op = la_op_ammin_db_d;
+ break;
+ case 0xe0:
+ op = la_op_ammax_db_wu;
+ break;
+ case 0xe1:
+ op = la_op_ammax_db_du;
+ break;
+ case 0xe2:
+ op = la_op_ammin_db_wu;
+ break;
+ case 0xe3:
+ op = la_op_ammin_db_du;
+ break;
+ case 0xe4:
+ op = la_op_dbar;
+ break;
+ case 0xe5:
+ op = la_op_ibar;
+ break;
+ case 0xe8:
+ op = la_op_fldgt_s;
+ break;
+ case 0xe9:
+ op = la_op_fldgt_d;
+ break;
+ case 0xea:
+ op = la_op_fldle_s;
+ break;
+ case 0xeb:
+ op = la_op_fldle_d;
+ break;
+ case 0xec:
+ op = la_op_fstgt_s;
+ break;
+ case 0xed:
+ op = la_op_fstgt_d;
+ break;
+ case 0xee:
+ op = ls_op_fstle_s;
+ break;
+ case 0xef:
+ op = la_op_fstle_d;
+ break;
+ case 0xf0:
+ op = la_op_ldgt_b;
+ break;
+ case 0xf1:
+ op = la_op_ldgt_h;
+ break;
+ case 0xf2:
+ op = la_op_ldgt_w;
+ break;
+ case 0xf3:
+ op = la_op_ldgt_d;
+ break;
+ case 0xf4:
+ op = la_op_ldle_b;
+ break;
+ case 0xf5:
+ op = la_op_ldle_h;
+ break;
+ case 0xf6:
+ op = la_op_ldle_w;
+ break;
+ case 0xf7:
+ op = la_op_ldle_d;
+ break;
+ case 0xf8:
+ op = la_op_stgt_b;
+ break;
+ case 0xf9:
+ op = la_op_stgt_h;
+ break;
+ case 0xfa:
+ op = la_op_stgt_w;
+ break;
+ case 0xfb:
+ op = la_op_stgt_d;
+ break;
+ case 0xfc:
+ op = la_op_stle_b;
+ break;
+ case 0xfd:
+ op = la_op_stle_h;
+ break;
+ case 0xfe:
+ op = la_op_stle_w;
+ break;
+ case 0xff:
+ op = la_op_stle_d;
+ break;
+ }
+ break;
+ case 0x10:
+ op = la_op_beqz;
+ break;
+ case 0x11:
+ op = la_op_bnez;
+ break;
+ case 0x12:
+ switch ((insn >> 8) & 0x3) {
+ case 0x0:
+ op = la_op_bceqz;
+ break;
+ case 0x1:
+ op = la_op_bcnez;
+ break;
+ }
+ break;
+ case 0x13:
+ op = la_op_jirl;
+ break;
+ case 0x14:
+ op = la_op_b;
+ break;
+ case 0x15:
+ op = la_op_bl;
+ break;
+ case 0x16:
+ op = la_op_beq;
+ break;
+ case 0x17:
+ op = la_op_bne;
+ break;
+ case 0x18:
+ op = la_op_blt;
+ break;
+ case 0x19:
+ op = la_op_bge;
+ break;
+ case 0x1a:
+ op = la_op_bltu;
+ break;
+ case 0x1b:
+ op = la_op_bgeu;
+ break;
+ default:
+ op = la_op_illegal;
+ break;
+ }
+ dec->op = op;
+}
+
+/* operand extractors */
+#define IM_5 5
+#define IM_8 8
+#define IM_12 12
+#define IM_14 14
+#define IM_15 15
+#define IM_16 16
+#define IM_20 20
+#define IM_21 21
+#define IM_26 26
+
+static uint32_t operand_r1(uint32_t insn)
+{
+ return insn & 0x1f;
+}
+
+static uint32_t operand_r2(uint32_t insn)
+{
+ return (insn >> 5) & 0x1f;
+}
+
+static uint32_t operand_r3(uint32_t insn)
+{
+ return (insn >> 10) & 0x1f;
+}
+
+static uint32_t operand_r4(uint32_t insn)
+{
+ return (insn >> 15) & 0x1f;
+}
+
+static uint32_t operand_u6(uint32_t insn)
+{
+ return (insn >> 10) & 0x3f;
+}
+
+static uint32_t operand_bw1(uint32_t insn)
+{
+ return (insn >> 10) & 0x1f;
+}
+
+static uint32_t operand_bw2(uint32_t insn)
+{
+ return (insn >> 16) & 0x1f;
+}
+
+static uint32_t operand_bd1(uint32_t insn)
+{
+ return (insn >> 10) & 0x3f;
+}
+
+static uint32_t operand_bd2(uint32_t insn)
+{
+ return (insn >> 16) & 0x3f;
+}
+
+static uint32_t operand_sa2(uint32_t insn)
+{
+ return (insn >> 15) & 0x3;
+}
+
+static uint32_t operand_sa3(uint32_t insn)
+{
+ return (insn >> 15) & 0x3;
+}
+
+static int32_t operand_im20(uint32_t insn)
+{
+ int32_t imm = (int32_t)((insn >> 5) & 0xfffff);
+ return imm > (1 << 19) ? imm - (1 << 20) : imm;
+}
+
+static int32_t operand_im16(uint32_t insn)
+{
+ int32_t imm = (int32_t)((insn >> 10) & 0xffff);
+ return imm > (1 << 15) ? imm - (1 << 16) : imm;
+}
+
+static int32_t operand_im14(uint32_t insn)
+{
+ int32_t imm = (int32_t)((insn >> 10) & 0x3fff);
+ return imm > (1 << 13) ? imm - (1 << 14) : imm;
+}
+
+static int32_t operand_im12(uint32_t insn)
+{
+ int32_t imm = (int32_t)((insn >> 10) & 0xfff);
+ return imm > (1 << 11) ? imm - (1 << 12) : imm;
+}
+
+static int32_t operand_im8(uint32_t insn)
+{
+ int32_t imm = (int32_t)((insn >> 10) & 0xff);
+ return imm > (1 << 7) ? imm - (1 << 8) : imm;
+}
+
+static uint32_t operand_sd(uint32_t insn)
+{
+ return insn & 0x3;
+}
+
+static uint32_t operand_sj(uint32_t insn)
+{
+ return (insn >> 5) & 0x3;
+}
+
+static uint32_t operand_cd(uint32_t insn)
+{
+ return insn & 0x7;
+}
+
+static uint32_t operand_cj(uint32_t insn)
+{
+ return (insn >> 5) & 0x7;
+}
+
+static uint32_t operand_code(uint32_t insn)
+{
+ return insn & 0x7fff;
+}
+
+static int32_t operand_whint(uint32_t insn)
+{
+ int32_t imm = (int32_t)(insn & 0x7fff);
+ return imm > (1 << 14) ? imm - (1 << 15) : imm;
+}
+
+static int32_t operand_invop(uint32_t insn)
+{
+ int32_t imm = (int32_t)(insn & 0x1f);
+ return imm > (1 << 4) ? imm - (1 << 5) : imm;
+}
+
+static int32_t operand_ofs21(uint32_t insn)
+{
+ int32_t imm = (((int32_t)insn & 0x1f) << 16) |
+ ((insn >> 10) & 0xffff);
+ return imm > (1 << 20) ? imm - (1 << 21) : imm;
+}
+
+static int32_t operand_ofs26(uint32_t insn)
+{
+ int32_t imm = (((int32_t)insn & 0x3ff) << 16) |
+ ((insn >> 10) & 0xffff);
+ return imm > (1 << 25) ? imm - (1 << 26) : imm;
+}
+
+static uint32_t operand_fcond(uint32_t insn)
+{
+ return (insn >> 15) & 0x1f;
+}
+
+static uint32_t operand_sel(uint32_t insn)
+{
+ return (insn >> 15) & 0x7;
+}
+
+/* decode operands */
+static void decode_insn_operands(la_decode *dec)
+{
+ uint32_t insn = dec->insn;
+ dec->codec = opcode_data[dec->op].codec;
+ switch (dec->codec) {
+ case la_codec_illegal:
+ case la_codec_empty:
+ break;
+ case la_codec_2r:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ break;
+ case la_codec_2r_u5:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ break;
+ case la_codec_2r_u6:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_u6(insn);
+ break;
+ case la_codec_2r_2bw:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_bw1(insn);
+ dec->r4 = operand_bw2(insn);
+ break;
+ case la_codec_2r_2bd:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_bd1(insn);
+ dec->r4 = operand_bd2(insn);
+ break;
+ case la_codec_3r:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ break;
+ case la_codec_3r_rd0:
+ dec->r1 = 0;
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ break;
+ case la_codec_3r_sa2:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ dec->r4 = operand_sa2(insn);
+ break;
+ case la_codec_3r_sa3:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ dec->r4 = operand_sa3(insn);
+ break;
+ case la_codec_4r:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ dec->r4 = operand_r4(insn);
+ break;
+ case la_codec_r_im20:
+ dec->r1 = operand_r1(insn);
+ dec->imm = operand_im20(insn);
+ dec->bit = IM_20;
+ break;
+ case la_codec_2r_im16:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->imm = operand_im16(insn);
+ dec->bit = IM_16;
+ break;
+ case la_codec_2r_im14:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->imm = operand_im14(insn);
+ dec->bit = IM_14;
+ break;
+ case la_codec_r_im14:
+ dec->r1 = operand_r1(insn);
+ dec->imm = operand_im14(insn);
+ dec->bit = IM_14;
+ break;
+ case la_codec_im5_r_im12:
+ dec->imm2 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->imm = operand_im12(insn);
+ dec->bit = IM_12;
+ break;
+ case la_codec_2r_im12:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->imm = operand_im12(insn);
+ dec->bit = IM_12;
+ break;
+ case la_codec_2r_im8:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->imm = operand_im8(insn);
+ dec->bit = IM_8;
+ break;
+ case la_codec_r_sd:
+ dec->r1 = operand_sd(insn);
+ dec->r2 = operand_r2(insn);
+ break;
+ case la_codec_r_sj:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_sj(insn);
+ break;
+ case la_codec_r_cd:
+ dec->r1 = operand_cd(insn);
+ dec->r2 = operand_r2(insn);
+ break;
+ case la_codec_r_cj:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_cj(insn);
+ break;
+ case la_codec_r_seq:
+ dec->r1 = 0;
+ dec->r2 = operand_r1(insn);
+ dec->imm = operand_im8(insn);
+ dec->bit = IM_8;
+ break;
+ case la_codec_code:
+ dec->code = operand_code(insn);
+ break;
+ case la_codec_whint:
+ dec->imm = operand_whint(insn);
+ dec->bit = IM_15;
+ break;
+ case la_codec_invtlb:
+ dec->imm = operand_invop(insn);
+ dec->bit = IM_5;
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ break;
+ case la_codec_r_ofs21:
+ dec->imm = operand_ofs21(insn);
+ dec->bit = IM_21;
+ dec->r2 = operand_r2(insn);
+ break;
+ case la_codec_cj_ofs21:
+ dec->imm = operand_ofs21(insn);
+ dec->bit = IM_21;
+ dec->r2 = operand_cj(insn);
+ break;
+ case la_codec_ofs26:
+ dec->imm = operand_ofs26(insn);
+ dec->bit = IM_26;
+ break;
+ case la_codec_cond:
+ dec->r1 = operand_cd(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ dec->r4 = operand_fcond(insn);
+ break;
+ case la_codec_sel:
+ dec->r1 = operand_r1(insn);
+ dec->r2 = operand_r2(insn);
+ dec->r3 = operand_r3(insn);
+ dec->r4 = operand_sel(insn);
+ break;
+ }
+}
+
+/* format instruction */
+static void append(char *s1, const char *s2, size_t n)
+{
+ size_t l1 = strlen(s1);
+ if (n - l1 - 1 > 0) {
+ strncat(s1, s2, n - l1);
+ }
+}
+
+static void format_insn(char *buf, size_t buflen, size_t tab, la_decode *dec)
+{
+ char tmp[16];
+ const char *fmt;
+
+ fmt = opcode_data[dec->op].format;
+ while (*fmt) {
+ switch (*fmt) {
+ case 'n': /* name */
+ append(buf, opcode_data[dec->op].name, buflen);
+ break;
+ case 's':
+ append(buf, "s", buflen);
+ break;
+ case 'd':
+ append(buf, "d", buflen);
+ break;
+ case 'e': /* illegal */
+ snprintf(tmp, sizeof(tmp), "%x", dec->insn);
+ append(buf, tmp, buflen);
+ break;
+ case 't':
+ while (strlen(buf) < tab) {
+ append(buf, " ", buflen);
+ }
+ break;
+ case '(':
+ append(buf, "(", buflen);
+ break;
+ case ',':
+ append(buf, ",", buflen);
+ break;
+ case '.':
+ append(buf, ".", buflen);
+ break;
+ case ')':
+ append(buf, ")", buflen);
+ break;
+ case '0': /* rd */
+ append(buf, loongarch_r_normal_name[dec->r1], buflen);
+ break;
+ case '1': /* rj */
+ append(buf, loongarch_r_normal_name[dec->r2], buflen);
+ break;
+ case '2': /* rk */
+ append(buf, loongarch_r_normal_name[dec->r3], buflen);
+ break;
+ case '3': /* fd */
+ append(buf, loongarch_f_normal_name[dec->r1], buflen);
+ break;
+ case '4': /* fj */
+ append(buf, loongarch_f_normal_name[dec->r2], buflen);
+ break;
+ case '5': /* fk */
+ append(buf, loongarch_f_normal_name[dec->r3], buflen);
+ break;
+ case '6': /* fa */
+ append(buf, loongarch_f_normal_name[dec->r4], buflen);
+ break;
+ case 'A': /* sd */
+ append(buf, loongarch_cr_normal_name[dec->r1], buflen);
+ break;
+ case 'B': /* sj */
+ append(buf, loongarch_cr_normal_name[dec->r2], buflen);
+ break;
+ case 'C': /* r3 */
+ snprintf(tmp, sizeof(tmp), "%x", dec->r3);
+ append(buf, tmp, buflen);
+ break;
+ case 'D': /* r4 */
+ snprintf(tmp, sizeof(tmp), "%x", dec->r4);
+ append(buf, tmp, buflen);
+ break;
+ case 'E': /* r1 */
+ snprintf(tmp, sizeof(tmp), "%x", dec->r1);
+ append(buf, tmp, buflen);
+ break;
+ case 'F': /* fcsrd */
+ append(buf, loongarch_r_normal_name[dec->r1], buflen);
+ break;
+ case 'G': /* fcsrs */
+ append(buf, loongarch_r_normal_name[dec->r2], buflen);
+ break;
+ case 'H': /* cd */
+ append(buf, loongarch_c_normal_name[dec->r1], buflen);
+ break;
+ case 'I': /* cj */
+ append(buf, loongarch_c_normal_name[dec->r2], buflen);
+ break;
+ case 'J': /* code */
+ snprintf(tmp, sizeof(tmp), "0x%x", dec->code);
+ append(buf, tmp, buflen);
+ break;
+ case 'K': /* cond */
+ switch (dec->r4) {
+ case 0x0:
+ append(buf, "caf", buflen);
+ break;
+ case 0x1:
+ append(buf, "saf", buflen);
+ break;
+ case 0x2:
+ append(buf, "clt", buflen);
+ break;
+ case 0x3:
+ append(buf, "slt", buflen);
+ break;
+ case 0x4:
+ append(buf, "ceq", buflen);
+ break;
+ case 0x5:
+ append(buf, "seq", buflen);
+ break;
+ case 0x6:
+ append(buf, "cle", buflen);
+ break;
+ case 0x7:
+ append(buf, "sle", buflen);
+ break;
+ case 0x8:
+ append(buf, "cun", buflen);
+ break;
+ case 0x9:
+ append(buf, "sun", buflen);
+ break;
+ case 0xA:
+ append(buf, "cult", buflen);
+ break;
+ case 0xB:
+ append(buf, "sult", buflen);
+ break;
+ case 0xC:
+ append(buf, "cueq", buflen);
+ break;
+ case 0xD:
+ append(buf, "sueq", buflen);
+ break;
+ case 0xE:
+ append(buf, "cule", buflen);
+ break;
+ case 0xF:
+ append(buf, "sule", buflen);
+ break;
+ case 0x10:
+ append(buf, "cne", buflen);
+ break;
+ case 0x11:
+ append(buf, "sne", buflen);
+ break;
+ case 0x14:
+ append(buf, "cor", buflen);
+ break;
+ case 0x15:
+ append(buf, "sor", buflen);
+ break;
+ case 0x18:
+ append(buf, "cune", buflen);
+ break;
+ case 0x19:
+ append(buf, "sune", buflen);
+ break;
+ }
+ break;
+ case 'L': /* ca */
+ append(buf, loongarch_c_normal_name[dec->r4], buflen);
+ break;
+ case 'M': /* cop */
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm2) & 0x1f);
+ append(buf, tmp, buflen);
+ break;
+ case 'i': /* sixx d */
+ snprintf(tmp, sizeof(tmp), "%d", dec->imm);
+ append(buf, tmp, buflen);
+ break;
+ case 'o': /* offset */
+ snprintf(tmp, sizeof(tmp), "%d", (dec->imm) << 2);
+ append(buf, tmp, buflen);
+ break;
+ case 'x': /* sixx x */
+ switch (dec->bit) {
+ case IM_5:
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x1f);
+ append(buf, tmp, buflen);
+ break;
+ case IM_8:
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xff);
+ append(buf, tmp, buflen);
+ break;
+ case IM_12:
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfff);
+ append(buf, tmp, buflen);
+ break;
+ case IM_14:
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x3fff);
+ append(buf, tmp, buflen);
+ break;
+ case IM_15:
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x7fff);
+ append(buf, tmp, buflen);
+ break;
+ case IM_16:
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xffff);
+ append(buf, tmp, buflen);
+ break;
+ case IM_20:
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfffff);
+ append(buf, tmp, buflen);
+ break;
+ default:
+ snprintf(tmp, sizeof(tmp), "0x%x", dec->imm);
+ append(buf, tmp, buflen);
+ break;
+ }
+ break;
+ case 'X': /* offset x*/
+ switch (dec->bit) {
+ case IM_16:
+ snprintf(tmp, sizeof(tmp), "0x%x",
+ ((dec->imm) << 2) & 0xffff);
+ append(buf, tmp, buflen);
+ break;
+ case IM_21:
+ snprintf(tmp, sizeof(tmp), "0x%x",
+ ((dec->imm) << 2) & 0x1fffff);
+ append(buf, tmp, buflen);
+ break;
+ case IM_26:
+ snprintf(tmp, sizeof(tmp), "0x%x",
+ ((dec->imm) << 2) & 0x3ffffff);
+ append(buf, tmp, buflen);
+ break;
+ default:
+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) << 2);
+ append(buf, tmp, buflen);
+ break;
+ }
+ break;
+ case 'p': /* pc */
+ snprintf(tmp, sizeof(tmp), " # 0x%"PRIx32"",
+ dec->pc + ((dec->imm) << 2));
+ append(buf, tmp, buflen);
+ break;
+ default:
+ break;
+ }
+ fmt++;
+ }
+}
+
+/* disassemble instruction */
+static void
+disasm_insn(char *buf, size_t buflen, bfd_vma pc, unsigned long int insn)
+{
+ la_decode dec = { 0 };
+ dec.pc = pc;
+ dec.insn = insn;
+ decode_insn_opcode(&dec);
+ decode_insn_operands(&dec);
+ format_insn(buf, buflen, 16, &dec);
+}
+
+int
+print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
+{
+ char buf[128] = { 0 };
+ bfd_byte buffer[INSNLEN];
+ unsigned long insn;
+ int status;
+
+ status = (*info->read_memory_func)(memaddr, buffer, INSNLEN, info);
+ if (status == 0) {
+ insn = (uint32_t) bfd_getl32(buffer);
+ (*info->fprintf_func)(info->stream, "%08" PRIx64 " ", insn);
+ } else {
+ (*info->memory_error_func)(status, memaddr, info);
+ return -1;
+ }
+ disasm_insn(buf, sizeof(buf), memaddr, insn);
+ (*info->fprintf_func)(info->stream, "\t%s", buf);
+ return INSNLEN;
+}
diff --git a/disas/meson.build b/disas/meson.build
index 449f99e..a1bd8b8 100644
--- a/disas/meson.build
+++ b/disas/meson.build
@@ -9,6 +9,7 @@ common_ss.add(when: 'CONFIG_CRIS_DIS', if_true: files('cris.c'))
common_ss.add(when: 'CONFIG_HEXAGON_DIS', if_true: files('hexagon.c'))
common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c'))
common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c'))
+common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: files('loongarch.c'))
common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c'))
common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c'))
common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c'))
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 524f291..009a03a 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
@@ -462,6 +463,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 bf63784..08131fc 100644
--- a/meson.build
+++ b/meson.build
@@ -1499,6 +1499,7 @@ disassemblers = {
'sh4' : ['CONFIG_SH4_DIS'],
'sparc' : ['CONFIG_SPARC_DIS'],
'xtensa' : ['CONFIG_XTENSA_DIS'],
+ 'loongarch' : ['CONFIG_LOONGARCH_DIS'],
}
if link_language == 'cpp'
disassemblers += {
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 17/21] LoongArch Linux User Emulation
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (15 preceding siblings ...)
2021-09-02 12:41 ` [PATCH v4 16/21] target/loongarch: Add disassembler Song Gao
@ 2021-09-02 12:41 ` Song Gao
2021-09-05 10:04 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 18/21] default-configs: Add loongarch linux-user support Song Gao
` (3 subsequent siblings)
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:41 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
Implementation of linux user emulation for LoongArch.
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/cpu_loop.c | 108 +++++++++++
linux-user/loongarch64/signal.c | 178 ++++++++++++++++++
linux-user/loongarch64/sockbits.h | 1 +
linux-user/loongarch64/syscall_nr.h | 290 +++++++++++++++++++++++++++++
linux-user/loongarch64/target_cpu.h | 35 ++++
linux-user/loongarch64/target_elf.h | 14 ++
linux-user/loongarch64/target_errno_defs.h | 7 +
linux-user/loongarch64/target_fcntl.h | 12 ++
linux-user/loongarch64/target_signal.h | 28 +++
linux-user/loongarch64/target_structs.h | 49 +++++
linux-user/loongarch64/target_syscall.h | 46 +++++
linux-user/loongarch64/termbits.h | 229 +++++++++++++++++++++++
linux-user/syscall_defs.h | 10 +-
15 files changed, 1063 insertions(+), 4 deletions(-)
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
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 01e9a83..cf47ccd 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -909,6 +909,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/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c
new file mode 100644
index 0000000..bc81d22
--- /dev/null
+++ b/linux-user/loongarch64/cpu_loop.c
@@ -0,0 +1,108 @@
+/*
+ * QEMU LoongArch user cpu loop.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "qemu-common.h"
+#include "cpu_loop-common.h"
+#include "elf.h"
+
+void cpu_loop(CPULoongArchState *env)
+{
+ CPUState *cs = env_cpu(env);
+ target_siginfo_t info;
+ int trapnr;
+ 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:
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = env->badaddr;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case EXCP_INE:
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = 0;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case EXCP_FPE:
+ info.si_signo = TARGET_SIGFPE;
+ info.si_errno = 0;
+ info.si_code = TARGET_FPE_FLTUNK;
+ if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) {
+ info.si_code = TARGET_FPE_FLTINV;
+ } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) {
+ info.si_code = TARGET_FPE_FLTDIV;
+ } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) {
+ info.si_code = TARGET_FPE_FLTOVF;
+ } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) {
+ info.si_code = TARGET_FPE_FLTUND;
+ } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) {
+ info.si_code = TARGET_FPE_FLTRES;
+ }
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+ case EXCP_BREAK:
+ info.si_signo = TARGET_SIGTRAP;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ 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 & ~(target_ulong)1;
+
+}
diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c
new file mode 100644
index 0000000..2da8317
--- /dev/null
+++ b/linux-user/loongarch64/signal.c
@@ -0,0 +1,178 @@
+/*
+ * LoongArch emulation of Linux signals
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "signal-common.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 sigframe {
+ uint32_t sf_ass[4]; /* argument save space for o32 */
+ uint32_t sf_code[2]; /* signal trampoline */
+ struct target_sigcontext sf_sc;
+ target_sigset_t sf_mask;
+};
+
+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 {
+ uint32_t rs_ass[4]; /* argument save space for o32 */
+ uint32_t rs_code[2]; /* signal trampoline */
+ struct target_siginfo rs_info;
+ struct target_ucontext rs_uc;
+};
+
+/* Install trampoline to jump back from signal handler */
+static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
+{
+ int err = 0;
+
+ /*
+ * Set up the return code ...
+ *
+ * li a7, 139
+ * syscall
+ */
+
+ __put_user(0x03822c0b, tramp + 0); /* ori a7, a7, 0x8b */
+ __put_user(0x002b0000, tramp + 1); /* syscall 0 */
+ return err;
+}
+
+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;
+ }
+
+ install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
+
+ 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] = frame_addr + offsetof(struct target_rt_sigframe, rs_code);
+
+ 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;
+}
diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h
new file mode 100644
index 0000000..0e4c8f0
--- /dev/null
+++ b/linux-user/loongarch64/sockbits.h
@@ -0,0 +1 @@
+#include "../generic/sockbits.h"
diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h
new file mode 100644
index 0000000..503d87b
--- /dev/null
+++ b/linux-user/loongarch64/syscall_nr.h
@@ -0,0 +1,290 @@
+/*
+ * 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_getrlimit 163
+#define TARGET_NR_setrlimit 164
+#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_clone3 435
+#define TARGET_NR_syscalls 436
+
+#endif /* LINUX_USER_LOONGARCH_SYSCALL_NR_H */
diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h
new file mode 100644
index 0000000..5bd13a7
--- /dev/null
+++ b/linux-user/loongarch64/target_cpu.h
@@ -0,0 +1,35 @@
+/*
+ * LoongArch specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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
diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h
new file mode 100644
index 0000000..7c88394
--- /dev/null
+++ b/linux-user/loongarch64/target_elf.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+
+#ifndef LOONGARCH_TARGET_ELF_H
+#define LOONGARCH_TARGET_ELF_H
+static inline const char *cpu_get_model(uint32_t eflags)
+{
+ return "Loongson-3A5000";
+}
+#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..17165c1
--- /dev/null
+++ b/linux-user/loongarch64/target_errno_defs.h
@@ -0,0 +1,7 @@
+#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..b810293
--- /dev/null
+++ b/linux-user/loongarch64/target_fcntl.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#ifndef LOONGARCH_TARGET_FCNTL_H
+#define LOONGARCH_TARGET_FCNTL_H
+
+#include "../generic/fcntl.h"
+
+#endif /* LOONGARCH_TARGET_FCNTL_H */
diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h
new file mode 100644
index 0000000..713c26a
--- /dev/null
+++ b/linux-user/loongarch64/target_signal.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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"
+
+#endif /* LOONGARCH_TARGET_SIGNAL_H */
diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h
new file mode 100644
index 0000000..818e8d6
--- /dev/null
+++ b/linux-user/loongarch64/target_structs.h
@@ -0,0 +1,49 @@
+/*
+ * LoongArch specific structures for linux-user
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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
diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h
new file mode 100644
index 0000000..b98ac12
--- /dev/null
+++ b/linux-user/loongarch64/target_syscall.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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 "loongarch"
+#define UNAME_MINIMUM_RELEASE "4.19.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/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h
new file mode 100644
index 0000000..33e74ed
--- /dev/null
+++ b/linux-user/loongarch64/termbits.h
@@ -0,0 +1,229 @@
+#ifndef LINUX_USER_LOONGARCH_TERMBITS_H
+#define LINUX_USER_LOONGARCH_TERMBITS_H
+
+#define TARGET_NCCS 19
+
+typedef unsigned char target_cc_t; /* cc_t */
+typedef unsigned int target_speed_t; /* speed_t */
+typedef unsigned int target_tcflag_t; /* tcflag_t */
+
+struct target_termios {
+ target_tcflag_t c_iflag; /* input mode flags */
+ target_tcflag_t c_oflag; /* output mode flags */
+ target_tcflag_t c_cflag; /* control mode flags */
+ target_tcflag_t c_lflag; /* local mode flags */
+ target_cc_t c_line; /* line discipline */
+ target_cc_t c_cc[TARGET_NCCS]; /* control characters */
+};
+
+/* c_iflag bits */
+#define TARGET_IGNBRK 0000001
+#define TARGET_BRKINT 0000002
+#define TARGET_IGNPAR 0000004
+#define TARGET_PARMRK 0000010
+#define TARGET_INPCK 0000020
+#define TARGET_ISTRIP 0000040
+#define TARGET_INLCR 0000100
+#define TARGET_IGNCR 0000200
+#define TARGET_ICRNL 0000400
+#define TARGET_IUCLC 0001000
+#define TARGET_IXON 0002000
+#define TARGET_IXANY 0004000
+#define TARGET_IXOFF 0010000
+#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
+
+/* c_oflag bits */
+#define TARGET_OPOST 0000001
+#define TARGET_OLCUC 0000002
+#define TARGET_ONLCR 0000004
+#define TARGET_OCRNL 0000010
+#define TARGET_ONOCR 0000020
+#define TARGET_ONLRET 0000040
+#define TARGET_OFILL 0000100
+#define TARGET_OFDEL 0000200
+#define TARGET_NLDLY 0000400
+#define TARGET_NL0 0000000
+#define TARGET_NL1 0000400
+#define TARGET_CRDLY 0003000
+#define TARGET_CR0 0000000
+#define TARGET_CR1 0001000
+#define TARGET_CR2 0002000
+#define TARGET_CR3 0003000
+#define TARGET_TABDLY 0014000
+#define TARGET_TAB0 0000000
+#define TARGET_TAB1 0004000
+#define TARGET_TAB2 0010000
+#define TARGET_TAB3 0014000
+#define TARGET_XTABS 0014000
+#define TARGET_BSDLY 0020000
+#define TARGET_BS0 0000000
+#define TARGET_BS1 0020000
+#define TARGET_VTDLY 0040000
+#define TARGET_VT0 0000000
+#define TARGET_VT1 0040000
+#define TARGET_FFDLY 0100000
+#define TARGET_FF0 0000000
+#define TARGET_FF1 0100000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD 0010017
+#define TARGET_B0 0000000 /* hang up */
+#define TARGET_B50 0000001
+#define TARGET_B75 0000002
+#define TARGET_B110 0000003
+#define TARGET_B134 0000004
+#define TARGET_B150 0000005
+#define TARGET_B200 0000006
+#define TARGET_B300 0000007
+#define TARGET_B600 0000010
+#define TARGET_B1200 0000011
+#define TARGET_B1800 0000012
+#define TARGET_B2400 0000013
+#define TARGET_B4800 0000014
+#define TARGET_B9600 0000015
+#define TARGET_B19200 0000016
+#define TARGET_B38400 0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE 0000060
+#define TARGET_CS5 0000000
+#define TARGET_CS6 0000020
+#define TARGET_CS7 0000040
+#define TARGET_CS8 0000060
+#define TARGET_CSTOPB 0000100
+#define TARGET_CREAD 0000200
+#define TARGET_PARENB 0000400
+#define TARGET_PARODD 0001000
+#define TARGET_HUPCL 0002000
+#define TARGET_CLOCAL 0004000
+#define TARGET_CBAUDEX 0010000
+#define TARGET_B57600 0010001
+#define TARGET_B115200 0010002
+#define TARGET_B230400 0010003
+#define TARGET_B460800 0010004
+#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG 0000001
+#define TARGET_ICANON 0000002
+#define TARGET_XCASE 0000004
+#define TARGET_ECHO 0000010
+#define TARGET_ECHOE 0000020
+#define TARGET_ECHOK 0000040
+#define TARGET_ECHONL 0000100
+#define TARGET_NOFLSH 0000200
+#define TARGET_TOSTOP 0000400
+#define TARGET_ECHOCTL 0001000
+#define TARGET_ECHOPRT 0002000
+#define TARGET_ECHOKE 0004000
+#define TARGET_FLUSHO 0010000
+#define TARGET_PENDIN 0040000
+#define TARGET_IEXTEN 0100000
+#define TARGET_EXTPROC 0200000
+
+/* c_cc character offsets */
+#define TARGET_VINTR 0
+#define TARGET_VQUIT 1
+#define TARGET_VERASE 2
+#define TARGET_VKILL 3
+#define TARGET_VEOF 4
+#define TARGET_VTIME 5
+#define TARGET_VMIN 6
+#define TARGET_VSWTC 7
+#define TARGET_VSTART 8
+#define TARGET_VSTOP 9
+#define TARGET_VSUSP 10
+#define TARGET_VEOL 11
+#define TARGET_VREPRINT 12
+#define TARGET_VDISCARD 13
+#define TARGET_VWERASE 14
+#define TARGET_VLNEXT 15
+#define TARGET_VEOL2 16
+
+/* ioctls */
+
+#define TARGET_TCGETS 0x5401
+#define TARGET_TCSETS 0x5402
+#define TARGET_TCSETSW 0x5403
+#define TARGET_TCSETSF 0x5404
+#define TARGET_TCGETA 0x5405
+#define TARGET_TCSETA 0x5406
+#define TARGET_TCSETAW 0x5407
+#define TARGET_TCSETAF 0x5408
+#define TARGET_TCSBRK 0x5409
+#define TARGET_TCXONC 0x540A
+#define TARGET_TCFLSH 0x540B
+
+#define TARGET_TIOCEXCL 0x540C
+#define TARGET_TIOCNXCL 0x540D
+#define TARGET_TIOCSCTTY 0x540E
+#define TARGET_TIOCGPGRP 0x540F
+#define TARGET_TIOCSPGRP 0x5410
+#define TARGET_TIOCOUTQ 0x5411
+#define TARGET_TIOCSTI 0x5412
+#define TARGET_TIOCGWINSZ 0x5413
+#define TARGET_TIOCSWINSZ 0x5414
+#define TARGET_TIOCMGET 0x5415
+#define TARGET_TIOCMBIS 0x5416
+#define TARGET_TIOCMBIC 0x5417
+#define TARGET_TIOCMSET 0x5418
+#define TARGET_TIOCGSOFTCAR 0x5419
+#define TARGET_TIOCSSOFTCAR 0x541A
+#define TARGET_FIONREAD 0x541B
+#define TARGET_TIOCINQ TARGET_FIONREAD
+#define TARGET_TIOCLINUX 0x541C
+#define TARGET_TIOCCONS 0x541D
+#define TARGET_TIOCGSERIAL 0x541E
+#define TARGET_TIOCSSERIAL 0x541F
+#define TARGET_TIOCPKT 0x5420
+#define TARGET_FIONBIO 0x5421
+#define TARGET_TIOCNOTTY 0x5422
+#define TARGET_TIOCSETD 0x5423
+#define TARGET_TIOCGETD 0x5424
+#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
+#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
+#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
+#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int)
+ /* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int)
+ /* Lock/unlock Pty */
+#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41)
+ /* Safely open the slave */
+
+#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */
+#define TARGET_FIOCLEX 0x5451
+#define TARGET_FIOASYNC 0x5452
+#define TARGET_TIOCSERCONFIG 0x5453
+#define TARGET_TIOCSERGWILD 0x5454
+#define TARGET_TIOCSERSWILD 0x5455
+#define TARGET_TIOCGLCKTRMIOS 0x5456
+#define TARGET_TIOCSLCKTRMIOS 0x5457
+#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TARGET_TIOCMIWAIT 0x545C
+ /* wait for a change on serial input line(s) */
+#define TARGET_TIOCGICOUNT 0x545D
+ /* read serial port inline interrupt counts */
+#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
+#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
+
+/* Used for packet mode */
+#define TARGET_TIOCPKT_DATA 0
+#define TARGET_TIOCPKT_FLUSHREAD 1
+#define TARGET_TIOCPKT_FLUSHWRITE 2
+#define TARGET_TIOCPKT_STOP 4
+#define TARGET_TIOCPKT_START 8
+#define TARGET_TIOCPKT_NOSTOP 16
+#define TARGET_TIOCPKT_DOSTOP 32
+
+#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+
+#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;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [PATCH v4 18/21] default-configs: Add loongarch linux-user support
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (16 preceding siblings ...)
2021-09-02 12:41 ` [PATCH v4 17/21] LoongArch Linux User Emulation Song Gao
@ 2021-09-02 12:41 ` Song Gao
2021-09-02 12:41 ` [PATCH v4 19/21] target/loongarch: Add target build suport Song Gao
` (2 subsequent siblings)
20 siblings, 0 replies; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:41 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
Add loongarch64 linux-user default configs file.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
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] 46+ messages in thread
* [PATCH v4 19/21] target/loongarch: Add target build suport
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (17 preceding siblings ...)
2021-09-02 12:41 ` [PATCH v4 18/21] default-configs: Add loongarch linux-user support Song Gao
@ 2021-09-02 12:41 ` Song Gao
2021-09-05 10:05 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 20/21] target/loongarch: 'make check-tcg' support Song Gao
2021-09-02 12:41 ` [PATCH v4 21/21] scripts: add loongarch64 binfmt config Song Gao
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:41 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch add build loongarch-linux-user target support.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
target/loongarch/meson.build | 18 ++++++++++++++++++
target/meson.build | 1 +
2 files changed, 19 insertions(+)
create mode 100644 target/loongarch/meson.build
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
new file mode 100644
index 0000000..31f9e9f
--- /dev/null
+++ b/target/loongarch/meson.build
@@ -0,0 +1,18 @@
+gen = decodetree.process('insns.decode')
+
+loongarch_ss = ss.source_set()
+loongarch_ss.add(files(
+ 'cpu.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] 46+ messages in thread
* [PATCH v4 20/21] target/loongarch: 'make check-tcg' support
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (18 preceding siblings ...)
2021-09-02 12:41 ` [PATCH v4 19/21] target/loongarch: Add target build suport Song Gao
@ 2021-09-02 12:41 ` Song Gao
2021-09-05 10:06 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 21/21] scripts: add loongarch64 binfmt config Song Gao
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:41 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
This patch support 'make check-tcg' after install cross-tools.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
tests/tcg/configure.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index 1f985cc..d8f677d 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] 46+ messages in thread
* [PATCH v4 21/21] scripts: add loongarch64 binfmt config
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
` (19 preceding siblings ...)
2021-09-02 12:41 ` [PATCH v4 20/21] target/loongarch: 'make check-tcg' support Song Gao
@ 2021-09-02 12:41 ` Song Gao
2021-09-05 10:08 ` Richard Henderson
20 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-02 12:41 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
richard.henderson, groug, maobibo, mrolnik, shorne, alex.bennee,
david, kbastian, crwulff, laurent, palmer, pbonzini, aurelien
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: XiaoJuan Yang <yangxiaojuan@loongson.cn>
---
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..5575bdd 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\x00\xff\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] 46+ messages in thread
* Re: [PATCH v4 02/21] target/loongarch: Add core definition
2021-09-02 12:40 ` [PATCH v4 02/21] target/loongarch: Add core definition Song Gao
@ 2021-09-04 9:44 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-04 9:44 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +#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 */
> +#define GET_FP_CAUSE(reg) (((reg) >> 24) & 0x1f)
> +#define GET_FP_ENABLE(reg) (reg & 0x1f)
> +#define GET_FP_FLAGS(reg) (((reg) >> 16) & 0x1f)
> +#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x1f << 24)) | \
> + ((v & 0x1f) << 24); \
> + } while (0)
> +#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f) | (v & 0x1f); \
> + } while (0)
> +#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 16)) | \
> + ((v & 0x1f) << 16); \
> + } while (0)
> +#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 16); } while (0)
Better to use "hw/registerfields.h":
FIELD(FCSR, ENABLES, 0, 5)
FIELD(FCSR, RM, 8, 2)
FIELD(FCSR, FLAGS, 16, 5)
FIELD(FCSR, CAUSE, 24, 5)
Then e.g.
#define GET_FP_CAUSE(REG) FIELD_EX32(REG, FCSR, CAUSE)
#define SET_FP_CAUSE(REG, V) FIELD_DP32(REG, FCSR, CAUSE, V)
#define UPDATE_FP_FLAGS(REG, V) \
do {
(REG) |= FIELD_DP32(0, FCSR, FLAGS, V);
} while (0)
> +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;
> +}
Missing *flags = 0.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 03/21] target/loongarch: Add main translation routines
2021-09-02 12:40 ` [PATCH v4 03/21] target/loongarch: Add main translation routines Song Gao
@ 2021-09-04 9:45 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-04 9:45 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
> +{
> + return true;
> +}
This is unused. Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation
2021-09-02 12:40 ` [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
@ 2021-09-04 11:04 ` Richard Henderson
2021-09-07 12:36 ` Song Gao
0 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-09-04 11:04 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +static bool gen_r2_si12(DisasContext *ctx, arg_fmt_rdrjsi12 *a,
> + DisasExtend src_ext, DisasExtend dst_ext,
> + void (*func)(TCGv, TCGv, TCGv))
> +{
> + ctx->dst_ext = dst_ext;
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, src_ext);
> + TCGv src2 = tcg_constant_tl(a->si12);
Prefer to put declarations before statements, as per old C90 still.
> + func(dest, src1, src2);
> +
> + if (ctx->dst_ext) {
Given that func does not receive ctx, why store dst_ext into ctx and then read it back?
It seems like you should just use the parameter directly.
> +static bool gen_pc(DisasContext *ctx, arg_fmt_rdsi20 *a,
> + void (*func)(DisasContext *ctx, TCGv, target_long))
> +{
> + TCGv dest = gpr_dst(ctx, a->rd);
> +
> + func(ctx, dest, a->si20);
> + return true;
> +}
Perhaps clearer with:
target_long (*func)(target_long pc, target_long si20)
target_long addr = func(ctx->base.pc_next, a->si20);
TCGv dest = gpr_dst(ctx, a->rd);
tcg_gen_movi_tl(dest, addr);
return true;
> +static bool gen_mulh(DisasContext *ctx, arg_add_w *a,
> + void(*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32))
> +{
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
> + TCGv_i32 discard = tcg_temp_new_i32();
> + TCGv_i32 t0 = tcg_temp_new_i32();
> + TCGv_i32 t1 = tcg_temp_new_i32();
> +
> + tcg_gen_trunc_tl_i32(t0, src1);
> + tcg_gen_trunc_tl_i32(t1, src2);
> + func(discard, t0, t0, t1);
> + tcg_gen_ext_i32_tl(dest, t0);
> +
> + tcg_temp_free_i32(discard);
> + tcg_temp_free_i32(t0);
> + tcg_temp_free_i32(t1);
> + return true;
> +}
You should be able to use gen_r3 for these.
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);
}
TRANS(mulh_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w)
TRANS(mulh_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_wu)
TRANS(mulh_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d)
TRANS(mulh_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du)
> +static bool gen_mulw_d(DisasContext *ctx, arg_add_w *a,
> + void(*func)(TCGv_i64, TCGv))
> +{
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
> +
> + func(src1, src1);
> + func(src2, src2);
> + tcg_gen_mul_i64(dest, src1, src2);
> + return true;
> +}
The func parameter here serves the same purpose as DisasExtend, so again you can use gen_r3:
TRANS(mulw_d_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl)
TRANS(mulw_d_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_NONE, tcg_gen_mul_tl)
> +
> +static bool gen_div_w(DisasContext *ctx, arg_fmt_rdrjrk *a,
> + DisasExtend src_ext, DisasExtend dst_ext,
> + void(*func)(TCGv, TCGv, TCGv))
> +{
> + ctx->dst_ext = dst_ext;
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, src_ext);
> + TCGv src2 = gpr_src(ctx, a->rk, src_ext);
> + TCGv t2 = tcg_temp_new();
> + TCGv t3 = tcg_temp_new();
> +
> + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src1, INT_MIN);
> + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, -1);
> + tcg_gen_and_tl(t2, t2, t3);
> + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, 0);
> + tcg_gen_or_tl(t2, t2, t3);
> + tcg_gen_movi_tl(t3, 0);
> + tcg_gen_movcond_tl(TCG_COND_NE, src2, t2, t3, t2, src2);
Bug, writing back to src2.
> + func(dest, src1, src2);
You can split this out differently so that you can use gen_r3.
static TCGv prep_divisor_d(TCGv src1, TCGv src2)
{
TCGv t0 = temp_new();
TCGv t1 = tcg_temp_new();
TCGv t2 = 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, t0, src1, INT64_MIN);
tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, -1);
tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, 0);
tcg_gen_and_tl(t0, t0, t1);
tcg_gen_or_tl(t0, t0, t2);
tcg_gen_movcond_tl(TCG_COND_NE, t0, t0, zero, t0, src2);
tcg_temp_free(t1);
tcg_temp_free(t2);
return t0;
}
static TCGv prep_divisor_du(TCGv src2)
{
TCGv t0 = temp_new();
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, t0, src2, zero, one, src2);
return t0;
}
static void gen_div_d(TCGv dest, TCGv src1, TCGv src2)
{
src2 = prep_divisor_d(src1, src2);
tcg_gen_div_tl(dest, src1, src2);
}
static void gen_rem_d(TCGv dest, TCGv src1, TCGv src2)
{
src2 = prep_divisor_d(src1, src2);
tcg_gen_rem_tl(dest, src1, src2);
}
static void gen_div_du(TCGv dest, TCGv src1, TCGv src2)
{
src2 = prep_divisor_du(src2);
tcg_gen_divu_tl(dest, src1, src2);
}
static void gen_rem_du(TCGv dest, TCGv src1, TCGv src2)
{
src2 = prep_divisor_du(src2);
tcg_gen_remu_tl(dest, src1, src2);
}
static void gen_div_w(TCGv dest, TCGv src1, TCGv src2)
{
/* We need not check for integer overflow for div_w. */
src2 = prep_divisor_du(src2);
tcg_gen_div_tl(dest, src1, src2);
}
static void gen_rem_w(TCGv dest, TCGv src1, TCGv src2)
{
/* We need not check for integer overflow for rem_w. */
src2 = prep_divisor_du(src2);
tcg_gen_rem_tl(dest, src1, src2);
}
TRANS(div_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_div_w)
TRANS(mod_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_rem_w)
TRANS(div_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
TRANS(mod_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
TRANS(div_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_d)
TRANS(mod_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_d)
TRANS(div_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_du)
TRANS(mod_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_du)
> --- a/target/loongarch/internals.h
> +++ b/target/loongarch/internals.h
> @@ -9,7 +9,6 @@
> #ifndef LOONGARCH_INTERNALS_H
> #define LOONGARCH_INTERNALS_H
>
> -
> void loongarch_translate_init(void);
>
> void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
Fold this back to a previous patch.
> -static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
> -{
> - return true;
> -}
Yes indeed, fold this patch to a previous patch.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 05/21] target/loongarch: Add fixed point shift instruction translation
2021-09-02 12:40 ` [PATCH v4 05/21] target/loongarch: Add fixed point shift " Song Gao
@ 2021-09-04 11:17 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-04 11:17 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +static bool gen_r2_ui6(DisasContext *ctx, arg_slli_d *a,
> + void(*func)(TCGv, TCGv, TCGv))
> +{
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + TCGv src2 = tcg_constant_tl(a->ui6);
> +
> + TCGv t0 = temp_new(ctx);
> +
> + tcg_gen_andi_tl(t0, src2, 0x7f);
0x3f.
That said, these shouldn't require masking, because they've just come from the decoder as
5 and 6-bit operands.
You should prefer to use the tcg_gen_* functions that take integers:
void (*func)(TCGv, TCGv, target_long)
passing tcg_gen_shli_tl, etc. It will make all of these simpler.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 06/21] target/loongarch: Add fixed point bit instruction translation
2021-09-02 12:40 ` [PATCH v4 06/21] target/loongarch: Add fixed point bit " Song Gao
@ 2021-09-04 12:57 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-04 12:57 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +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);
> + gen_clz_w(dest, dest);
> +}
This doesn't work, quite. You need
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, 64);
> +}
> +
> +static void gen_cto_w(TCGv dest, TCGv src1)
> +{
> + tcg_gen_not_tl(dest, src1);
> + gen_ctz_w(dest, dest);
> +}
Likewise, this needs the OR after the NOT.
Alternately, zero-extend and use
tcg_gen_ctzi_tl(dest, dest, 32);
> +static void gen_revb_2w(TCGv dest, TCGv src1)
> +{
> + tcg_gen_bswap64_i64(dest, src1);
> + tcg_gen_rotri_i64(dest, dest, 32);
> +}
> +
> +static bool trans_revb_2h(DisasContext *ctx, arg_revb_2h *a)
> +{
> + ctx->dst_ext = EXT_SIGN;
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + 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);
> + gen_set_gpr(ctx, a->rd, dest);
> +
> + tcg_temp_free(t0);
> + tcg_temp_free(t1);
> + return true;
> +}
Split out the center of this so you can use gen_r2.
> +static bool trans_revb_4h(DisasContext *ctx, arg_revb_4h *a)
> +{
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + 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);
> + return true;
> +}
Likewise.
> +static bool trans_revh_2w(DisasContext *ctx, arg_revh_2w *a)
> +{
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + 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);
> +
> + return true;
> +}
Likewise.
> +
> +static bool trans_revh_d(DisasContext *ctx, arg_revh_d *a)
> +{
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + 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_shri_tl(t1, t0, 32);
> + tcg_gen_shli_tl(t0, t0, 32);
> + tcg_gen_or_tl(dest, t0, t1);
This last is rotate by 32.
> +static void gen_maskeqz(TCGv dest, TCGv src1, TCGv src2)
> +{
> + TCGv cond1 = tcg_constant_tl(0);
> +
> + tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, cond1, cond1, src1);
> +}
> +
> +static void gen_masknez(TCGv dest, TCGv src1, TCGv src2)
> +{
> + TCGv cond1 = tcg_constant_tl(0);
> +
> + tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, cond1, cond1, src1);
> +}
s/cond1/zero/g
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 07/21] target/loongarch: Add fixed point load/store instruction translation
2021-09-02 12:40 ` [PATCH v4 07/21] target/loongarch: Add fixed point load/store " Song Gao
@ 2021-09-04 13:03 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-04 13:03 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +static bool gen_load(DisasContext *ctx, arg_fmt_rdrjsi12 *a,
> + DisasExtend dst_ext, MemOp mop)
> +{
> + ctx->dst_ext = dst_ext;
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
> + TCGv temp = NULL;
> +
> + if (a->si12) {
> + temp = tcg_temp_new();
> + tcg_gen_addi_tl(temp, addr, a->si12);
> + addr = temp;
> + }
> +
> + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
> +
> + if (ctx->dst_ext) {
> + gen_set_gpr(ctx, a->rd, dest);
> + }
You shouldn't ever need dst_ext for loads, since mop can control the extension.
> +static bool gen_loadx(DisasContext *ctx, arg_fmt_rdrjrk *a,
> + DisasExtend dst_ext, MemOp mop)
Likewise.
> +static bool gen_load_le(DisasContext *ctx, arg_fmt_rdrjrk *a,
> + DisasExtend dst_ext, MemOp mop)
Etc.
> +TRANS(ld_b, gen_load, EXT_SIGN, MO_SB)
> +TRANS(ld_h, gen_load, EXT_SIGN, MO_TESW)
> +TRANS(ld_w, gen_load, EXT_SIGN, MO_TESL)
...
> +TRANS(ld_bu, gen_load, EXT_ZERO, MO_UB)
> +TRANS(ld_hu, gen_load, EXT_ZERO, MO_TEUW)
> +TRANS(ld_wu, gen_load, EXT_ZERO, MO_TEUL)
Note that dst_ext is already matching the sign of mop.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 08/21] target/loongarch: Add fixed point atomic instruction translation
2021-09-02 12:40 ` [PATCH v4 08/21] target/loongarch: Add fixed point atomic " Song Gao
@ 2021-09-04 13:14 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-04 13:14 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +static bool gen_sc(DisasContext *ctx, arg_fmt_rdrjsi14 *a, MemOp mop)
> +{
> + TCGv dest = gpr_dst(ctx, a->rd);
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE);
> + TCGv t0 = tcg_temp_new();
> +
> + TCGLabel *l1 = gen_new_label();
> + TCGLabel *done = gen_new_label();
> +
> + tcg_gen_addi_tl(t0, src1, a->si14 << 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);
> + /* generate cmpxchg */
> + tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval,
> + src2, ctx->mem_idx, mop);
This is incorrect when dest and src2 overlap, as you've already clobbered dest.
> +static bool gen_am(DisasContext *ctx, arg_fmt_rdrjrk *a, DisasExtend ext,
> + void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
> + MemOp mop)
> +{
> + ctx->dst_ext = ext;
> + TCGv dest = gpr_dst(ctx, a->rd);
> + 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("%s: waring, register equal\n", __func__);
> + return false;
> + }
> +
> + func(dest, addr, val, ctx->mem_idx, mop);
> +
> + if (ctx->dst_ext) {
> + gen_set_gpr(ctx, a->rd, dest);
> + }
> + return true;
> +}
> +
> +static bool gen_am_db(DisasContext *ctx, arg_fmt_rdrjrk *a, DisasExtend ext,
> + void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
> + MemOp mop)
> +{
> + ctx->dst_ext = ext;
> + TCGv dest = gpr_dst(ctx, a->rd);
> + 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("%s: waring, register equal\n", __func__);
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);
> + if (ctx->dst_ext) {
> + gen_set_gpr(ctx, a->rd, dest);
> + }
Again, extension should be taken care of by mop.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 09/21] target/loongarch: Add fixed point extra instruction translation
2021-09-02 12:40 ` [PATCH v4 09/21] target/loongarch: Add fixed point extra " Song Gao
@ 2021-09-05 8:39 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 8:39 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> This patch implement fixed point extra instruction translation.
>
> 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>
> ---
> target/loongarch/helper.h | 4 ++
> target/loongarch/insn_trans/trans_extra.c | 88 +++++++++++++++++++++++++++++++
> target/loongarch/insns.decode | 25 +++++++++
> target/loongarch/op_helper.c | 26 +++++++++
> target/loongarch/translate.c | 1 +
> 5 files changed, 144 insertions(+)
> create mode 100644 target/loongarch/insn_trans/trans_extra.c
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 10/21] target/loongarch: Add floating point arithmetic instruction translation
2021-09-02 12:40 ` [PATCH v4 10/21] target/loongarch: Add floating point arithmetic " Song Gao
@ 2021-09-05 9:08 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 9:08 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +const FloatRoundMode ieee_rm[4] = {
Make static.
> +int ieee_ex_to_loongarch(int xcpt)
This function is only used in this file. Better to make it static and remove the
declaration from translate.h, which allows you to remove that include.
> +static inline void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
Remove inline.
> +{
> + int flags = ieee_ex_to_loongarch(get_float_exception_flags(
> + &env->fp_status));
> +
> + SET_FP_CAUSE(env->fcsr0, flags);
> + if (flags) {
Hmm. Between the two functions you're testing for zero twice. Perhaps better to rearrange as
{
int flags = get_float_exception_flags(&env->fp_status);
if (!flags) {
SET_FP_CAUSE(env->fcsr0, 0);
return;
}
set_float_exception_flags(0, &env->fp_status);
flags = ieee_ex_to_loongarch(flags);
SET_FP_CAUSE(env->fcsr0, flags);
if (GET_FP_ENABLE(env->fcsr0) & flags) {
do_raise_exception(env, EXCP_FPE, pc);
}
UPDATE_FP_FLAGS(env->fcsr0, flags);
}
and remove the explicit zero test in ieee_ex_to_loongarch.
> +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_exception_flags(0, status);
Unnecessary, since the steady-state is already zero.
> + set_float_exception_flags(get_float_exception_flags(status) &
> + (~float_flag_inexact), status);
> + update_fcsr0(env, GETPC());
Hmm. Worth adding a parameter to update_fcsr0, a mask to suppress? Or a common
subroutine like
update_fcsr0_mask(env, GETPC(), float_flag_inexact);
static void update_fcsr0(env, ra)
{
update_fcsr0_mask(env, ra, 0);
}
> +static bool trans_fcopysign_s(DisasContext *ctx, arg_fmt_fdfjfk *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_fmt_fdfjfk *a)
> +{
> + tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 63);
> + return true;
> +}
For what it's worth, you could treat the abs and neg instructions similarly, inline.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 11/21] target/loongarch: Add floating point comparison instruction translation
2021-09-02 12:40 ` [PATCH v4 11/21] target/loongarch: Add floating point comparison " Song Gao
@ 2021-09-05 9:24 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 9:24 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +/* fcmp_cXXX_s */
> +uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
> + uint64_t fk, uint32_t flags)
> +{
> + uint32_t t0, t1;
> + uint64_t cmp = 0;
> + t0 = (uint32_t)fj;
> + t1 = (uint32_t)fk;
> +
> + if (flags) {
> + if (flags & FCMP_LT) {
> + cmp |= float32_lt_quiet(t0, t1, &env->fp_status);
> + }
> + if (flags & FCMP_EQ) {
> + cmp |= float32_eq_quiet(t0, t1, &env->fp_status);
> + }
> + if (flags & FCMP_GT) {
> + cmp |= float32_lt_quiet(t1, t0, &env->fp_status);
> + }
> + if (flags & FCMP_UN) {
> + cmp |= float32_unordered_quiet(t1, t0, &env->fp_status);
> + }
> + } else {
> + cmp = (float32_unordered_quiet(t1, t0, &env->fp_status), 0);
> + }
This is silly, especially the form of the last. You want
FloatRelation cmp = float32_unordered_quiet(t1, t0, &env->fp_status);
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();
}
return ret;
And of course the switch can be split out to a common subroutine for use with the other 3
comparison helpers.
> +static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
> +{
> + TCGv var = tcg_temp_new();
> + TCGv_i32 flags = NULL;
> +
> + switch (a->fcond) {
> + /* caf */
> + case 0:
> + flags = tcg_constant_i32(0);
> + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj],
> + cpu_fpr[a->fk], flags);
> + break;
> + /* saf */
> + case 1:
> + flags = tcg_constant_i32(0);
> + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj],
> + cpu_fpr[a->fk], flags);
> + break;
Hmm. Perhaps put the integer flags into a table?
fn = (a->fcond & 1 ? gen_helper_fcmp_s_s : gen_helper_fcmp_c_s);
flags = fcond_table[a->fcond >> 1];
fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk],
tcg_constant_i32(flags));
> +static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a)
You'd get to share the table with this function.
> --- a/target/loongarch/translate.h
> +++ b/target/loongarch/translate.h
> @@ -11,6 +11,11 @@
>
> #include "exec/translator.h"
>
> +#define FCMP_LT 0x0001 /* fp0 < fp1 */
> +#define FCMP_EQ 0x0010 /* fp0 = fp1 */
> +#define FCMP_GT 0x0100 /* fp1 < fp0 */
> +#define FCMP_UN 0x1000 /* unordered */
Hmm. Better in internals.h? I don't think you want to include translate.h into fpu_helper.c.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 12/21] target/loongarch: Add floating point conversion instruction translation
2021-09-02 12:40 ` [PATCH v4 12/21] target/loongarch: Add floating point conversion " Song Gao
@ 2021-09-05 9:29 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 9:29 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> This patch implement floating point conversion instruction translation.
>
> 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>
> ---
> target/loongarch/fpu_helper.c | 393 +++++++++++++++++++++++++++++++
> target/loongarch/helper.h | 29 +++
> target/loongarch/insn_trans/trans_fcnv.c | 36 +++
> target/loongarch/insns.decode | 32 +++
> target/loongarch/translate.c | 1 +
> 5 files changed, 491 insertions(+)
> create mode 100644 target/loongarch/insn_trans/trans_fcnv.c
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 13/21] target/loongarch: Add floating point move instruction translation
2021-09-02 12:40 ` [PATCH v4 13/21] target/loongarch: Add floating point move " Song Gao
@ 2021-09-05 9:38 ` Richard Henderson
2021-09-05 9:45 ` Richard Henderson
1 sibling, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 9:38 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +static bool gen_mov(DisasContext *ctx, arg_fmt_fdfj *a,
> + void (*func)(TCGv, TCGv))
> +{
> + TCGv dest = cpu_fpr[a->fd];
> + TCGv src = cpu_fpr[a->fj];
Maybe clearer as gen_f2f, to match the others?
> +static void gen_movfrh2gr_s(TCGv dest, TCGv src)
> +{
> + TCGv t0 = tcg_temp_new();
> +
> + tcg_gen_extract_tl(dest, src, 32, 32);
> +
> + tcg_temp_free(t0);
> +}
t0 is unused.
Use sextract_tl, or sari_tl...
> +TRANS(movfr2gr_s, gen_f2r, EXT_NONE, tcg_gen_ext32s_tl)
> +TRANS(movfr2gr_d, gen_f2r, EXT_NONE, tcg_gen_mov_tl)
> +TRANS(movfrh2gr_s, gen_f2r, EXT_SIGN, gen_movfrh2gr_s)
... which then means you don't need the EXT_SIGN here, and can drop the parameter entirely.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 13/21] target/loongarch: Add floating point move instruction translation
2021-09-02 12:40 ` [PATCH v4 13/21] target/loongarch: Add floating point move " Song Gao
2021-09-05 9:38 ` Richard Henderson
@ 2021-09-05 9:45 ` Richard Henderson
1 sibling, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 9:45 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:40 PM, Song Gao wrote:
> +TRANS(fmov_s, gen_mov, tcg_gen_mov_tl)
Hmm. The spec says only the low 32-bits are modified? But is also says that if the
source is not in the single-precision format the result is uncertain?
I'm not sure how to reconcile these two statements.
Ideally the language would allow the result to be nanboxed...
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 14/21] target/loongarch: Add floating point load/store instruction translation
2021-09-02 12:41 ` [PATCH v4 14/21] target/loongarch: Add floating point load/store " Song Gao
@ 2021-09-05 9:46 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 9:46 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:41 PM, Song Gao wrote:
> This patch implement floating point load/store instruction translation.
>
> 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>
> ---
> target/loongarch/insn_trans/trans_fmemory.c | 143 ++++++++++++++++++++++++++++
> target/loongarch/insns.decode | 24 +++++
> target/loongarch/translate.c | 1 +
> 3 files changed, 168 insertions(+)
> create mode 100644 target/loongarch/insn_trans/trans_fmemory.c
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
I wonder if you want to add nanboxing for loads, since you did it for the arithmetic? But
certainly this is correct per spec as-is.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 15/21] target/loongarch: Add branch instruction translation
2021-09-02 12:41 ` [PATCH v4 15/21] target/loongarch: Add branch " Song Gao
@ 2021-09-05 9:49 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 9:49 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:41 PM, Song Gao wrote:
> +static bool gen_rz_bc(DisasContext *ctx, arg_fmt_rjoffs21 *a, TCGCond cond)
> +{
> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> + TCGv src2 = tcg_constant_tl(0);
> +
> + gen_bc(ctx, src1, src2, (a->offs21 << 2), cond);
> + return true;
> +}
> +static bool gen_cz_bc(DisasContext *ctx, arg_fmt_cjoffs21 *a, TCGCond cond)
Missing space. Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 17/21] LoongArch Linux User Emulation
2021-09-02 12:41 ` [PATCH v4 17/21] LoongArch Linux User Emulation Song Gao
@ 2021-09-05 10:04 ` Richard Henderson
2021-09-08 9:50 ` Song Gao
0 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 10:04 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:41 PM, Song Gao wrote:
> +#include "qemu/osdep.h"
> +#include "qemu.h"
> +#include "qemu-common.h"
> +#include "cpu_loop-common.h"
> +#include "elf.h"
> +
> +void cpu_loop(CPULoongArchState *env)
> +{
> + CPUState *cs = env_cpu(env);
> + target_siginfo_t info;
> + int trapnr;
> + 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:
> + info.si_signo = TARGET_SIGSEGV;
> + info.si_errno = 0;
> + info.si_code = TARGET_SEGV_MAPERR;
> + info._sifields._sigfault._addr = env->badaddr;
> + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> + break;
> + case EXCP_INE:
> + info.si_signo = TARGET_SIGILL;
> + info.si_errno = 0;
> + info.si_code = 0;
> + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
Missing _addr = pc.
> + break;
> + case EXCP_FPE:
> + info.si_signo = TARGET_SIGFPE;
> + info.si_errno = 0;
> + info.si_code = TARGET_FPE_FLTUNK;
> + if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) {
> + info.si_code = TARGET_FPE_FLTINV;
> + } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) {
> + info.si_code = TARGET_FPE_FLTDIV;
> + } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) {
> + info.si_code = TARGET_FPE_FLTOVF;
> + } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) {
> + info.si_code = TARGET_FPE_FLTUND;
> + } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) {
> + info.si_code = TARGET_FPE_FLTRES;
> + }
> + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
Likewise.
> + case EXCP_BREAK:
> + info.si_signo = TARGET_SIGTRAP;
> + info.si_code = TARGET_TRAP_BRKPT;
> + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
Likewise.
Note that there are a set of patches on list that introduce a force_sig_fault(signo, code,
addr) function, so that none of these parameters get missed.
Missing an entry for EXCP_DEBUG, which should share code with EXCP_BREAK.
> +struct sigframe {
> + uint32_t sf_ass[4]; /* argument save space for o32 */
Surely there is no "o32" for loongarch?
> + uint32_t sf_code[2]; /* signal trampoline */
Note that there are patches on-list for moving the signal trampoline off of the stack.
> diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h
> new file mode 100644
> index 0000000..33e74ed
> --- /dev/null
> +++ b/linux-user/loongarch64/termbits.h
> @@ -0,0 +1,229 @@
> +#ifndef LINUX_USER_LOONGARCH_TERMBITS_H
> +#define LINUX_USER_LOONGARCH_TERMBITS_H
> +
> +#define TARGET_NCCS 19
Surely you should be using generic/termbits.h?
We will prefer not to merge a linux-user port that is not upstream, because the ABI may
change in between. Can you provide a pointer to your kernel port in the meantime?
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 19/21] target/loongarch: Add target build suport
2021-09-02 12:41 ` [PATCH v4 19/21] target/loongarch: Add target build suport Song Gao
@ 2021-09-05 10:05 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 10:05 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:41 PM, Song Gao wrote:
> This patch add build loongarch-linux-user target support.
>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: XiaoJuan Yang<yangxiaojuan@loongson.cn>
> ---
> target/loongarch/meson.build | 18 ++++++++++++++++++
> target/meson.build | 1 +
> 2 files changed, 19 insertions(+)
> create mode 100644 target/loongarch/meson.build
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 20/21] target/loongarch: 'make check-tcg' support
2021-09-02 12:41 ` [PATCH v4 20/21] target/loongarch: 'make check-tcg' support Song Gao
@ 2021-09-05 10:06 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 10:06 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:41 PM, Song Gao wrote:
> This patch support 'make check-tcg' after install cross-tools.
>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: XiaoJuan Yang<yangxiaojuan@loongson.cn>
> ---
> tests/tcg/configure.sh | 1 +
> 1 file changed, 1 insertion(+)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 21/21] scripts: add loongarch64 binfmt config
2021-09-02 12:41 ` [PATCH v4 21/21] scripts: add loongarch64 binfmt config Song Gao
@ 2021-09-05 10:08 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-05 10:08 UTC (permalink / raw)
To: Song Gao, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
On 9/2/21 2:41 PM, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: XiaoJuan Yang<yangxiaojuan@loongson.cn>
> ---
> scripts/qemu-binfmt-conf.sh | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation
2021-09-04 11:04 ` Richard Henderson
@ 2021-09-07 12:36 ` Song Gao
0 siblings, 0 replies; 46+ messages in thread
From: Song Gao @ 2021-09-07 12:36 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, chenhuacai, philmd, atar4qemu, thuth, ehabkost,
groug, maobibo, mrolnik, shorne, alex.bennee, david, kbastian,
crwulff, laurent, palmer, pbonzini, aurelien
Hi, Richard,
Thank you for your comments!
On 09/04/2021 07:04 PM, Richard Henderson wrote:
> On 9/2/21 2:40 PM, Song Gao wrote:
>> +static bool gen_r2_si12(DisasContext *ctx, arg_fmt_rdrjsi12 *a,
>> + DisasExtend src_ext, DisasExtend dst_ext,
>> + void (*func)(TCGv, TCGv, TCGv))
>> +{
>> + ctx->dst_ext = dst_ext;
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> + TCGv src1 = gpr_src(ctx, a->rj, src_ext);
>> + TCGv src2 = tcg_constant_tl(a->si12);
>
> Prefer to put declarations before statements, as per old C90 still.
>
OK.
>> + func(dest, src1, src2);
>> +
>> + if (ctx->dst_ext) {
>
> Given that func does not receive ctx, why store dst_ext into ctx and then read it back? It seems like you should just use the parameter directly.
>
OK, ctx->dst_ext will be deleted.
>> +static bool gen_pc(DisasContext *ctx, arg_fmt_rdsi20 *a,
>> + void (*func)(DisasContext *ctx, TCGv, target_long))
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> +
>> + func(ctx, dest, a->si20);
>> + return true;
>> +}
>
> Perhaps clearer with:
>
> target_long (*func)(target_long pc, target_long si20)
>
> target_long addr = func(ctx->base.pc_next, a->si20);> OK, ctx->dst_ext will be deleted.
> TCGv dest = gpr_dst(ctx, a->rd);
>
> tcg_gen_movi_tl(dest, addr);
> return true;
>
>
Surely.
>
>
>> +static bool gen_mulh(DisasContext *ctx, arg_add_w *a,
>> + void(*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32))
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
>> + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
>> + TCGv_i32 discard = tcg_temp_new_i32();
>> + TCGv_i32 t0 = tcg_temp_new_i32();
>> + TCGv_i32 t1 = tcg_temp_new_i32();
>> +
>> + tcg_gen_trunc_tl_i32(t0, src1);
>> + tcg_gen_trunc_tl_i32(t1, src2);
>> + func(discard, t0, t0, t1);
>> + tcg_gen_ext_i32_tl(dest, t0);
>> +
>> + tcg_temp_free_i32(discard);
>> + tcg_temp_free_i32(t0);
>> + tcg_temp_free_i32(t1);
>> + return true;
>> +}
>
> You should be able to use gen_r3 for these.
>
> 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);
> }
>
> TRANS(mulh_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w)
> TRANS(mulh_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_wu)
> TRANS(mulh_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d)
> TRANS(mulh_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du)
>
>> +static bool gen_mulw_d(DisasContext *ctx, arg_add_w *a,
>> + void(*func)(TCGv_i64, TCGv))
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
>> + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
>> +
>> + func(src1, src1);
>> + func(src2, src2);
>> + tcg_gen_mul_i64(dest, src1, src2);
>> + return true;
>> +}
>
> The func parameter here serves the same purpose as DisasExtend, so again you can use gen_r3:
>
> TRANS(mulw_d_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl)
> TRANS(mulw_d_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_NONE, tcg_gen_mul_tl)
>
>
OK.
>
>> +
>> +static bool gen_div_w(DisasContext *ctx, arg_fmt_rdrjrk *a,
>> + DisasExtend src_ext, DisasExtend dst_ext,
>> + void(*func)(TCGv, TCGv, TCGv))
>> +{
>> + ctx->dst_ext = dst_ext;
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> + TCGv src1 = gpr_src(ctx, a->rj, src_ext);
>> + TCGv src2 = gpr_src(ctx, a->rk, src_ext);
>> + TCGv t2 = tcg_temp_new();
>> + TCGv t3 = tcg_temp_new();
>> +
>> + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src1, INT_MIN);
>> + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, -1);
>> + tcg_gen_and_tl(t2, t2, t3);
>> + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, 0);
>> + tcg_gen_or_tl(t2, t2, t3);
>> + tcg_gen_movi_tl(t3, 0);
>> + tcg_gen_movcond_tl(TCG_COND_NE, src2, t2, t3, t2, src2);
>
> Bug, writing back to src2.
> OK.
>> + func(dest, src1, src2);
>
> You can split this out differently so that you can use gen_r3.
>
> static TCGv prep_divisor_d(TCGv src1, TCGv src2)
> {
> TCGv t0 = temp_new();
> TCGv t1 = tcg_temp_new();
> TCGv t2 = 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, t0, src1, INT64_MIN);
> tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, -1);
> tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, 0);
> tcg_gen_and_tl(t0, t0, t1);
> tcg_gen_or_tl(t0, t0, t2);
> tcg_gen_movcond_tl(TCG_COND_NE, t0, t0, zero, t0, src2);
>
> tcg_temp_free(t1);
> tcg_temp_free(t2);
> return t0;
> }
>
> static TCGv prep_divisor_du(TCGv src2)
> {
> TCGv t0 = temp_new();
> 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, t0, src2, zero, one, src2);
> return t0;
> }
>
> static void gen_div_d(TCGv dest, TCGv src1, TCGv src2)
> {
> src2 = prep_divisor_d(src1, src2);
> tcg_gen_div_tl(dest, src1, src2);
> }
>
> static void gen_rem_d(TCGv dest, TCGv src1, TCGv src2)
> {
> src2 = prep_divisor_d(src1, src2);
> tcg_gen_rem_tl(dest, src1, src2);
> }
>
> static void gen_div_du(TCGv dest, TCGv src1, TCGv src2)
> {
> src2 = prep_divisor_du(src2);
> tcg_gen_divu_tl(dest, src1, src2);
> }
>
> static void gen_rem_du(TCGv dest, TCGv src1, TCGv src2)
> {
> src2 = prep_divisor_du(src2);
> tcg_gen_remu_tl(dest, src1, src2);
> }
>
> static void gen_div_w(TCGv dest, TCGv src1, TCGv src2)
> {
> /* We need not check for integer overflow for div_w. */
> src2 = prep_divisor_du(src2);
> tcg_gen_div_tl(dest, src1, src2);
> }
>
> static void gen_rem_w(TCGv dest, TCGv src1, TCGv src2)
> {
> /* We need not check for integer overflow for rem_w. */
> src2 = prep_divisor_du(src2);
> tcg_gen_rem_tl(dest, src1, src2);
> }
>
> TRANS(div_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_div_w)
> TRANS(mod_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_rem_w)
> TRANS(div_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
> TRANS(mod_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
> TRANS(div_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_d)
> TRANS(mod_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_d)
> TRANS(div_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_du)
> TRANS(mod_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_du)
>
Nice.
>> --- a/target/loongarch/internals.h
>> +++ b/target/loongarch/internals.h
>> @@ -9,7 +9,6 @@
>> #ifndef LOONGARCH_INTERNALS_H
>> #define LOONGARCH_INTERNALS_H
>> -
>> void loongarch_translate_init(void);
>> void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
>
> Fold this back to a previous patch.
>
OK
>> -static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
>> -{
>> - return true;
>> -}
>
> Yes indeed, fold this patch to a previous patch.
>
OK.
Song Gao
Thanks.
>
> r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 17/21] LoongArch Linux User Emulation
2021-09-05 10:04 ` Richard Henderson
@ 2021-09-08 9:50 ` Song Gao
2021-09-10 12:52 ` Richard Henderson
0 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-08 9:50 UTC (permalink / raw)
To: Richard Henderson, qemu-devel, chenhuacai
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, philmd, atar4qemu, thuth, ehabkost, groug,
maobibo, mrolnik, shorne, alex.bennee, david, kbastian, crwulff,
laurent, palmer, pbonzini, aurelien
Hi Richard,
On 09/05/2021 06:04 PM, Richard Henderson wrote:
>> +struct sigframe {
>> + uint32_t sf_ass[4]; /* argument save space for o32 */
>
> Surely there is no "o32" for loongarch?
>
Yes, qemu only support 64bit. but the kernel has 'o32'. Should we have to be consistent with the kernel?
>> + uint32_t sf_code[2]; /* signal trampoline */
>
> Note that there are patches on-list for moving the signal trampoline off of the stack.
>
>> diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h
>> new file mode 100644
>> index 0000000..33e74ed
>> --- /dev/null
>> +++ b/linux-user/loongarch64/termbits.h
>> @@ -0,0 +1,229 @@
>> +#ifndef LINUX_USER_LOONGARCH_TERMBITS_H
>> +#define LINUX_USER_LOONGARCH_TERMBITS_H
>> +
>> +#define TARGET_NCCS 19
>
> Surely you should be using generic/termbits.h?
> OK.
> We will prefer not to merge a linux-user port that is not upstream, because the ABI may change in between. Can you provide a pointer to your kernel port in the meantime?
Latest kernel: https://github.com/loongson/linux/tree/loongarch-next
Song Gao
Thanks.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 17/21] LoongArch Linux User Emulation
2021-09-08 9:50 ` Song Gao
@ 2021-09-10 12:52 ` Richard Henderson
2021-09-11 5:58 ` Song Gao
0 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-09-10 12:52 UTC (permalink / raw)
To: Song Gao, qemu-devel, chenhuacai
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, philmd, atar4qemu, thuth, ehabkost, groug,
maobibo, mrolnik, shorne, alex.bennee, david, kbastian, crwulff,
laurent, palmer, pbonzini, aurelien
On 9/8/21 11:50 AM, Song Gao wrote:
>
> Hi Richard,
>
> On 09/05/2021 06:04 PM, Richard Henderson wrote:
>>> +struct sigframe {
>>> + uint32_t sf_ass[4]; /* argument save space for o32 */
>>
>> Surely there is no "o32" for loongarch?
>>
>
> Yes, qemu only support 64bit. but the kernel has 'o32'. Should we have to be consistent with the kernel?
Yes, you need to be consistent with the kernel. However... the kernel is not yet
upstream, and therefore the ABI is (officially) still malleable.
Anyway, this padding was copied from mips o32, and should not have been. Looking at the
loongarch gcc sources, REG_PARM_STACK_SPACE is always 0, and thus the 4 words reserved
here are never used.
I see that gcc/libgcc/config/loongarch/linux-unwind.h builds in knowledge of these unused
words. I also see that linux/arch/loongarch/vdso/sigreturn.S does not provide correct
unwind info. Certainly the kernel vdso should be fixed, so that code within gcc should
not be needed. At which point the ABI for the signal frame is entirely private to the kernel.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 17/21] LoongArch Linux User Emulation
2021-09-10 12:52 ` Richard Henderson
@ 2021-09-11 5:58 ` Song Gao
2021-09-12 12:38 ` Richard Henderson
0 siblings, 1 reply; 46+ messages in thread
From: Song Gao @ 2021-09-11 5:58 UTC (permalink / raw)
To: Richard Henderson, qemu-devel, chenhuacai
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, philmd, atar4qemu, thuth, ehabkost, groug,
maobibo, mrolnik, shorne, alex.bennee, david, kbastian, crwulff,
laurent, palmer, pbonzini, aurelien
Hi, Richard.
On 09/10/2021 08:52 PM, Richard Henderson wrote:
> On 9/8/21 11:50 AM, Song Gao wrote:
>>
>> Hi Richard,
>>
>> On 09/05/2021 06:04 PM, Richard Henderson wrote:
>>>> +struct sigframe {
>>>> + uint32_t sf_ass[4]; /* argument save space for o32 */
>>>
>>> Surely there is no "o32" for loongarch?
>>>
>>
>> Yes, qemu only support 64bit. but the kernel has 'o32'. Should we have to be consistent with the kernel?
>
> Yes, you need to be consistent with the kernel. However... the kernel is not yet upstream, and therefore the ABI is (officially) still malleable.
>
> Anyway, this padding was copied from mips o32, and should not have been. Looking at the loongarch gcc sources, REG_PARM_STACK_SPACE is always 0, and thus the 4 words reserved here are never used.
>
> I see that gcc/libgcc/config/loongarch/linux-unwind.h builds in knowledge of these unused words. I also see that linux/arch/loongarch/vdso/sigreturn.S does not provide correct unwind info. Certainly the kernel vdso should be fixed, so that code within gcc should not be needed. At which point the ABI for the signal frame is entirely private to the kernel.
>
We are cleanning up 'o32' code for gcc and kernel.
By the way, We have already prepared V5 patches. but I see that patches [1] and [2] have not push into master. How can I use these patches?
[1]: https://patchew.org/QEMU/20210618192951.125651-1-richard.henderson@linaro.org/
[2]: https://patchew.org/QEMU/20210822035537.283193-1-richard.henderson@linaro.org/
Song Gao
thanks
>
> r~
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v4 17/21] LoongArch Linux User Emulation
2021-09-11 5:58 ` Song Gao
@ 2021-09-12 12:38 ` Richard Henderson
0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-09-12 12:38 UTC (permalink / raw)
To: Song Gao, qemu-devel, chenhuacai
Cc: peter.maydell, yangxiaojuan, david, bin.meng, mark.cave-ayland,
aleksandar.rikalo, jcmvbkbc, tsimpson, alistair.francis,
edgar.iglesias, philmd, atar4qemu, thuth, ehabkost, groug,
maobibo, mrolnik, shorne, alex.bennee, david, kbastian, crwulff,
laurent, palmer, pbonzini, aurelien
On 9/10/21 10:58 PM, Song Gao wrote:
> By the way, We have already prepared V5 patches. but I see that patches [1] and [2] have not push into master. How can I use these patches?
>
> [1]: https://patchew.org/QEMU/20210618192951.125651-1-richard.henderson@linaro.org/
> [2]: https://patchew.org/QEMU/20210822035537.283193-1-richard.henderson@linaro.org/
Now that development is open for 6.2, and I'm back from holiday, I'll work on getting this
upstream.
In the short term, you can add
Based-on: <message-id>
in the cover-letter, to indicate what the dependencies are. It can also be helpful to
provide a git tag for the complete patch set in the cover-letter.
r~
^ permalink raw reply [flat|nested] 46+ messages in thread
end of thread, other threads:[~2021-09-12 12:38 UTC | newest]
Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-02 12:40 [PATCH v4 00/21] Add LoongArch linux-user emulation support Song Gao
2021-09-02 12:40 ` [PATCH v4 01/21] target/loongarch: Add README Song Gao
2021-09-02 12:40 ` [PATCH v4 02/21] target/loongarch: Add core definition Song Gao
2021-09-04 9:44 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 03/21] target/loongarch: Add main translation routines Song Gao
2021-09-04 9:45 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
2021-09-04 11:04 ` Richard Henderson
2021-09-07 12:36 ` Song Gao
2021-09-02 12:40 ` [PATCH v4 05/21] target/loongarch: Add fixed point shift " Song Gao
2021-09-04 11:17 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 06/21] target/loongarch: Add fixed point bit " Song Gao
2021-09-04 12:57 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 07/21] target/loongarch: Add fixed point load/store " Song Gao
2021-09-04 13:03 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 08/21] target/loongarch: Add fixed point atomic " Song Gao
2021-09-04 13:14 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 09/21] target/loongarch: Add fixed point extra " Song Gao
2021-09-05 8:39 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 10/21] target/loongarch: Add floating point arithmetic " Song Gao
2021-09-05 9:08 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 11/21] target/loongarch: Add floating point comparison " Song Gao
2021-09-05 9:24 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 12/21] target/loongarch: Add floating point conversion " Song Gao
2021-09-05 9:29 ` Richard Henderson
2021-09-02 12:40 ` [PATCH v4 13/21] target/loongarch: Add floating point move " Song Gao
2021-09-05 9:38 ` Richard Henderson
2021-09-05 9:45 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 14/21] target/loongarch: Add floating point load/store " Song Gao
2021-09-05 9:46 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 15/21] target/loongarch: Add branch " Song Gao
2021-09-05 9:49 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 16/21] target/loongarch: Add disassembler Song Gao
2021-09-02 12:41 ` [PATCH v4 17/21] LoongArch Linux User Emulation Song Gao
2021-09-05 10:04 ` Richard Henderson
2021-09-08 9:50 ` Song Gao
2021-09-10 12:52 ` Richard Henderson
2021-09-11 5:58 ` Song Gao
2021-09-12 12:38 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 18/21] default-configs: Add loongarch linux-user support Song Gao
2021-09-02 12:41 ` [PATCH v4 19/21] target/loongarch: Add target build suport Song Gao
2021-09-05 10:05 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 20/21] target/loongarch: 'make check-tcg' support Song Gao
2021-09-05 10:06 ` Richard Henderson
2021-09-02 12:41 ` [PATCH v4 21/21] scripts: add loongarch64 binfmt config Song Gao
2021-09-05 10:08 ` Richard Henderson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.