From patchwork Tue Sep 14 13:00:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493161 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-21.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A622FC433EF for ; Tue, 14 Sep 2021 13:08:48 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 64EF961056 for ; Tue, 14 Sep 2021 13:08:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 64EF961056 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:39392 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8B5-00023v-I5 for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:08:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37424) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83k-0005J4-15 for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:12 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57502 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83Y-0007oh-Ea for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:11 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S3; Tue, 14 Sep 2021 21:00:55 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 01/21] target/loongarch: Add README Date: Tue, 14 Sep 2021 21:00:11 +0800 Message-Id: <1631624431-30658-2-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S3 X-Coremail-Antispam: 1UD129KBjvJXoWxXrWUuF18ZrW7Kw18Kw4xCrg_yoW5tr13pF 1fuFyfKrWUX3sxKrnag343WF1Fyws3Gr1xWanIkw1rC3sxtryqkw1fta4jqF17Jwn5trWv vrykCr1UW3WUCa7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, FORGED_SPF_HELO=1, KHOP_HELO_FCRDNS=0.399, SPF_HELO_PASS=-0.001, T_SPF_TEMPERROR=0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch give an introduction to the LoongArch target. Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang --- MAINTAINERS | 5 ++++ target/loongarch/README | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 target/loongarch/README diff --git a/MAINTAINERS b/MAINTAINERS index 6c20634..ad372a2 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 +S: Maintained +F: target/loongarch/ + M68K TCG CPUs M: Laurent Vivier 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/ From patchwork Tue Sep 14 13:00:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493155 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 98A45C433F5 for ; Tue, 14 Sep 2021 13:05:52 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 45DB460F58 for ; Tue, 14 Sep 2021 13:05:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 45DB460F58 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:59452 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ88F-0004px-Dt for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:05:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37386) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83h-0005CF-6G for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:09 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57516 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83Y-0007p1-Ec for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:08 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S4; Tue, 14 Sep 2021 21:00:56 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 02/21] target/loongarch: Add core definition Date: Tue, 14 Sep 2021 21:00:12 +0800 Message-Id: <1631624431-30658-3-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S4 X-Coremail-Antispam: 1UD129KBjvAXoWfXr17Cr4Dtry7JrWUuFWruFg_yoW8Gr1kCo WrZFy3X3ykGr4Sva9Y9rnaqay2qFy8CFW5Aa4xZw4Uua18trW5Gr98Kw1FvFy7Xrs5GrW7 uasagFnxJ3y7Jr1fn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch add target state header, target definitions and initialization routines. Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang --- target/loongarch/cpu-param.h | 19 +++ target/loongarch/cpu.c | 285 +++++++++++++++++++++++++++++++++++++++++++ target/loongarch/cpu.h | 151 +++++++++++++++++++++++ target/loongarch/internals.h | 23 ++++ 4 files changed, 478 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..02cb4af --- /dev/null +++ b/target/loongarch/cpu.h @@ -0,0 +1,151 @@ +/* + * 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" +#include "hw/registerfields.h" + +#define TCG_GUEST_DEFAULT_MO (0) + +#define FCSR0_M1 0x1f /* FCSR1 mask, Enables */ +#define FCSR0_M2 0x1f1f0000 /* FCSR2 mask, Cause and Flags */ +#define FCSR0_M3 0x300 /* FCSR3 mask, Round Mode */ +#define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */ + +FIELD(FCSR0, ENABLES, 0, 5) +FIELD(FCSR0, RM, 8, 2) +FIELD(FCSR0, FLAGS, 16, 5) +FIELD(FCSR0, CAUSE, 24, 5) + +#define GET_FP_CAUSE(REG) FIELD_EX32(REG, FCSR0, CAUSE) +#define SET_FP_CAUSE(REG, V) FIELD_DP32(REG, FCSR0, CAUSE, V) +#define GET_FP_ENABLES(REG) FIELD_EX32(REG, FCSR0, ENABLES) +#define SET_FP_ENABLES(REG, V) FIELD_DP32(REG, FCSR0, ENABLES, V) +#define GET_FP_FLAGS(REG) FIELD_EX32(REG, FCSR0, FLAGS) +#define SET_FP_FLAGS(REG, V) FIELD_DP32(REG, FCSR0, FLAGS, V) +#define UPDATE_FP_FLAGS(REG, V) \ + do { \ + (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \ + } while (0) + +#define FP_INEXACT 1 +#define FP_UNDERFLOW 2 +#define FP_OVERFLOW 4 +#define FP_DIV0 8 +#define FP_INVALID 16 + +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; + *flags = 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 From patchwork Tue Sep 14 13:00:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493159 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F28CC433F5 for ; Tue, 14 Sep 2021 13:08:21 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D079661056 for ; Tue, 14 Sep 2021 13:08:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org D079661056 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:38078 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8Ac-0001Bx-VK for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:08:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37476) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83o-0005Ut-J7 for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:16 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57526 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83a-0007pQ-Ah for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:16 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S5; Tue, 14 Sep 2021 21:00:57 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 03/21] target/loongarch: Add main translation routines Date: Tue, 14 Sep 2021 21:00:13 +0800 Message-Id: <1631624431-30658-4-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S5 X-Coremail-Antispam: 1UD129KBjvJXoW3Xr4DJrW3Gr47KryxtFW5ZFb_yoW3Cw1DpF 17Cr13Kr48Ja4fZas3G3yYqr15Aa1xGry2qa4ak395Cr42qrykZryktrZrKFWUC3y8WFyj vFs0y3Wj9F48XaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch add main translation routines and basic functions for translation. Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/helper.h | 9 +++ target/loongarch/internals.h | 1 - target/loongarch/op_helper.c | 22 ++++++ target/loongarch/translate.c | 160 +++++++++++++++++++++++++++++++++++++++++++ target/loongarch/translate.h | 27 ++++++++ 5 files changed, 218 insertions(+), 1 deletion(-) 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/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/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..2399b1a --- /dev/null +++ b/target/loongarch/translate.c @@ -0,0 +1,160 @@ +/* + * 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 void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) +{ + if (translator_use_goto_tb(&ctx->base, dest)) { + tcg_gen_goto_tb(n); + tcg_gen_movi_tl(cpu_pc, dest); + tcg_gen_exit_tb(ctx->base.tb, n); + } else { + tcg_gen_movi_tl(cpu_pc, dest); + tcg_gen_lookup_and_goto_ptr(); + } +} + +static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, + CPUState *cs) +{ + int64_t bound; + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK; + ctx->mem_idx = 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 From patchwork Tue Sep 14 13:00:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493167 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F132DC433EF for ; Tue, 14 Sep 2021 13:11:00 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 92DE461056 for ; Tue, 14 Sep 2021 13:11:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 92DE461056 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:46428 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8DD-0006wx-Pp for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:10:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37514) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83r-0005cK-DT for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:19 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57546 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83Z-0007pV-Iw for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:19 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S6; Tue, 14 Sep 2021 21:00:58 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 04/21] target/loongarch: Add fixed point arithmetic instruction translation Date: Tue, 14 Sep 2021 21:00:14 +0800 Message-Id: <1631624431-30658-5-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S6 X-Coremail-Antispam: 1UD129KBjvAXoWfGrW8ur43ZF45Xw4UCrykXwb_yoW8CF48Go WUGF45Jr48GryjvryY93W8Xa4xXr1j9an3JrWru3WUWF4xJr13Jr12krn5ZayrJw1qkFyr GF1SgFyfJ3yfXrn7n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/insn_trans/trans_arith.c | 322 ++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 89 +++++++++ target/loongarch/translate.c | 78 ++++++++ target/loongarch/translate.h | 19 ++ 4 files changed, 508 insertions(+) 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..4e8b9dd --- /dev/null +++ b/target/loongarch/insn_trans/trans_arith.c @@ -0,0 +1,322 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, + DisasExtend src1_ext, DisasExtend src2_ext, + DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd, dst_ext); + TCGv src1 = gpr_src(ctx, a->rj, src1_ext); + TCGv src2 = gpr_src(ctx, a->rk, src2_ext); + + func(dest, src1, src2); + + /* dst_ext is EXT_NONE and input is dest, We don't run gen_set_gpr. */ + if (dst_ext) { + gen_set_gpr(a->rd, dest, dst_ext); + } + return true; +} + +static bool gen_r2_si12(DisasContext *ctx, arg_fmt_rdrjsi12 *a, + DisasExtend src_ext, DisasExtend dst_ext, + void (*func)(TCGv, TCGv, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd, dst_ext); + TCGv src1 = gpr_src(ctx, a->rj, src_ext); + TCGv src2 = tcg_constant_tl(a->si12); + + func(dest, src1, src2); + + if (dst_ext) { + gen_set_gpr(a->rd, dest, dst_ext); + } + 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)) +{ + TCGv dest = gpr_dst(ctx, a->rd, dst_ext); + TCGv src1 = gpr_src(ctx, a->rj, src_ext); + TCGv src2 = gpr_src(ctx, a->rk, src_ext); + TCGv temp = tcg_temp_new(); + + func(dest, src1, src2, temp, a->sa2); + + if (dst_ext) { + gen_set_gpr(a->rd, dest, dst_ext); + } + tcg_temp_free(temp); + return true; +} + +static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + + tcg_gen_movi_tl(dest, a->si20 << 12); + return true; +} + +static bool gen_pc(DisasContext *ctx, arg_fmt_rdsi20 *a, + target_ulong (*func)(target_ulong, int)) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + target_ulong addr = func(ctx->base.pc_next, a->si20); + + tcg_gen_movi_tl(dest, addr); + 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, EXT_NONE); + 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 void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2) +{ + tcg_gen_mul_i64(dest, src1, src2); + tcg_gen_sari_i64(dest, dest, 32); +} + +static void gen_mulh_wu(TCGv dest, TCGv src1, TCGv src2) +{ + tcg_gen_mul_i64(dest, src1, src2); + tcg_gen_sari_i64(dest, dest, 32); +} + +static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv discard = tcg_temp_new(); + tcg_gen_muls2_tl(discard, dest, src1, src2); + tcg_temp_free(discard); +} + +static void gen_mulh_du(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv discard = tcg_temp_new(); + tcg_gen_mulu2_tl(discard, dest, src1, src2); + tcg_temp_free(discard); +} + +static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv zero = tcg_constant_tl(0); + + /* + * If min / -1, set the divisor to 1. + * This avoids potential host overflow trap and produces min. + * If x / 0, set the divisor to 1. + * This avoids potential host overflow trap; + * the required result is undefined. + */ + tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, INT64_MIN); + tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1); + tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0); + tcg_gen_and_tl(ret, ret, t0); + tcg_gen_or_tl(ret, ret, t1); + tcg_gen_movcond_tl(TCG_COND_NE, ret, ret, zero, ret, src2); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void prep_divisor_du(TCGv ret, TCGv src2) +{ + TCGv zero = tcg_constant_tl(0); + TCGv one = tcg_constant_tl(1); + + /* + * If x / 0, set the divisor to 1. + * This avoids potential host overflow trap; + * the required result is undefined. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, ret, src2, zero, one, src2); +} + +static void gen_div_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + prep_divisor_d(t0, src1, src2); + tcg_gen_div_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_rem_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + prep_divisor_d(t0, src1, src2); + tcg_gen_rem_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_div_du(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + prep_divisor_du(t0, src2); + tcg_gen_divu_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_rem_du(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + prep_divisor_du(t0, src2); + tcg_gen_remu_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_div_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + /* We need not check for integer overflow for div_w. */ + prep_divisor_du(t0, src2); + tcg_gen_div_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_rem_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + /* We need not check for integer overflow for rem_w. */ + prep_divisor_du(t0, src2); + tcg_gen_rem_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_alsl_w(TCGv dest, TCGv src1, TCGv src2, + TCGv temp, target_long 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, EXT_NONE); + 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, EXT_NONE); + 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 target_ulong gen_pcaddi(target_ulong pc, int si20) +{ + return pc + (si20 << 2); +} + +static target_ulong gen_pcalau12i(target_ulong pc, int si20) +{ + return (pc + (si20 << 12)) & ~0xfff; +} + +static target_ulong gen_pcaddu12i(target_ulong pc, int si20) +{ + return pc + (si20 << 12); +} + +static target_ulong gen_pcaddu18i(target_ulong pc, int si20) +{ + return pc + ((target_ulong)(si20) << 18); +} + +static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + tcg_gen_addi_tl(dest, src1, a->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_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) +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) +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_rem_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) +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/translate.c b/target/loongarch/translate.c index 2399b1a..69207f1 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -58,6 +58,11 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, /* Bound the number of insns to execute to those left on the page. */ bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; ctx->base.max_insns = MIN(ctx->base.max_insns, bound); + + ctx->ntemp = 0; + memset(ctx->temp, 0, sizeof(ctx->temp)); + + ctx->zero = tcg_constant_tl(0); } static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) @@ -71,6 +76,73 @@ static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) tcg_gen_insn_start(ctx->base.pc_next); } +/* + * Wrappers for getting reg values. + * + * The $zero register does not have cpu_gpr[0] allocated -- we supply the + * constant zero as a source, and an uninitialized sink as destination. + * + * Further, we may provide an extension for word operations. + */ +static TCGv temp_new(DisasContext *ctx) +{ + assert(ctx->ntemp < ARRAY_SIZE(ctx->temp)); + return ctx->temp[ctx->ntemp++] = tcg_temp_new(); +} + +static TCGv gpr_src(DisasContext *ctx, int reg_num, DisasExtend src_ext) +{ + TCGv t; + + if (reg_num == 0) { + return ctx->zero; + } + + switch (src_ext) { + case EXT_NONE: + return cpu_gpr[reg_num]; + case EXT_SIGN: + t = temp_new(ctx); + tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]); + return t; + case EXT_ZERO: + t = temp_new(ctx); + tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]); + return t; + } + g_assert_not_reached(); +} + +static TCGv gpr_dst(DisasContext *ctx, int reg_num, DisasExtend dst_ext) +{ + if (reg_num == 0 || dst_ext) { + return temp_new(ctx); + } + return cpu_gpr[reg_num]; +} + +static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) +{ + if (reg_num != 0) { + switch (dst_ext) { + case EXT_NONE: + tcg_gen_mov_tl(cpu_gpr[reg_num], t); + break; + case EXT_SIGN: + tcg_gen_ext32s_tl(cpu_gpr[reg_num], t); + break; + case EXT_ZERO: + tcg_gen_ext32u_tl(cpu_gpr[reg_num], t); + break; + default: + g_assert_not_reached(); + } + } +} + +#include "decode-insns.c.inc" +#include "insn_trans/trans_arith.c" + static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { CPULoongArchState *env = cs->env_ptr; @@ -84,6 +156,12 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) generate_exception(ctx, EXCP_INE); } + for (int i = ctx->ntemp - 1; i >= 0; --i) { + tcg_temp_free(ctx->temp[i]); + ctx->temp[i] = NULL; + } + ctx->ntemp = 0; + ctx->base.pc_next += 4; } diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h index dff7d79..832434c 100644 --- a/target/loongarch/translate.h +++ b/target/loongarch/translate.h @@ -11,11 +11,30 @@ #include "exec/translator.h" +#define TRANS(NAME, FUNC, ...) \ + static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \ + { return FUNC(ctx, a, __VA_ARGS__); } + +/* + * If an operation is being performed on less than TARGET_LONG_BITS, + * it may require the inputs to be sign- or zero-extended; which will + * depend on the exact operation being performed. + */ +typedef enum { + EXT_NONE, + EXT_SIGN, + EXT_ZERO, +} DisasExtend; + typedef struct DisasContext { DisasContextBase base; target_ulong page_start; uint32_t opcode; int mem_idx; + TCGv zero; + /* Space for 3 operands plus 1 extra for address computation. */ + TCGv temp[4]; + uint8_t ntemp; } DisasContext; void generate_exception(DisasContext *ctx, int excp); From patchwork Tue Sep 14 13:00:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493163 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8B1BFC433EF for ; Tue, 14 Sep 2021 13:09:26 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 479A1610CE for ; Tue, 14 Sep 2021 13:09:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 479A1610CE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:40806 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8Bh-00033X-Bn for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:09:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37464) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83n-0005RQ-Hf for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:16 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57594 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83c-0007qx-5U for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:15 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S7; Tue, 14 Sep 2021 21:00:58 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 05/21] target/loongarch: Add fixed point shift instruction translation Date: Tue, 14 Sep 2021 21:00:15 +0800 Message-Id: <1631624431-30658-6-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S7 X-Coremail-Antispam: 1UD129KBjvJXoWxKw47uw4fXr4kur1rCF1kAFb_yoWxKrWkpr 18CryUGr48XrnrJr9Ivw45uF98JrnrCa1jqrWSyr15CF4UX3WDJF1DC3y3KrW7twn3ZFW8 ZF95uFyqgFyrJaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/insn_trans/trans_shift.c | 131 ++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 26 ++++++ target/loongarch/translate.c | 1 + 3 files changed, 158 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..759d22b --- /dev/null +++ b/target/loongarch/insn_trans/trans_shift.c @@ -0,0 +1,131 @@ +/* + * 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)) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN); + TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO); + TCGv src2 = tcg_constant_tl(a->ui5); + + func(dest, src1, src2); + gen_set_gpr(a->rd, dest, EXT_SIGN); + + return true; +} + +static bool gen_r2_ui6(DisasContext *ctx, arg_slli_d *a, + void(*func)(TCGv, TCGv, target_long)) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + func(dest, src1, a->ui6); + + return true; +} + +static void gen_sll_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x1f); + tcg_gen_shl_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_srl_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x1f); + tcg_gen_shr_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_sra_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x1f); + tcg_gen_sar_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_sll_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x3f); + tcg_gen_shl_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_srl_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x3f); + tcg_gen_shr_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_sra_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x3f); + tcg_gen_sar_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_rotr_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv t0 = tcg_temp_new(); + + tcg_gen_andi_tl(t0, src2, 0x1f); + + tcg_gen_trunc_tl_i32(t1, src1); + tcg_gen_trunc_tl_i32(t2, t0); + + tcg_gen_rotr_i32(t1, t1, t2); + tcg_gen_ext_i32_tl(dest, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); + tcg_temp_free(t0); +} + +static void gen_rotr_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x3f); + tcg_gen_rotr_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO); + + tcg_gen_sextract_tl(dest, src1, a->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_SIGN, 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_shli_tl) +TRANS(srli_w, gen_r2_ui5, tcg_gen_shr_tl) +TRANS(srli_d, gen_r2_ui6, tcg_gen_shri_tl) +TRANS(srai_d, gen_r2_ui6, tcg_gen_sari_tl) +TRANS(rotri_w, gen_r2_ui5, gen_rotr_w) +TRANS(rotri_d, gen_r2_ui6, tcg_gen_rotri_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 69207f1..5ef572f 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -142,6 +142,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #include "decode-insns.c.inc" #include "insn_trans/trans_arith.c" +#include "insn_trans/trans_shift.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Tue Sep 14 13:00:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493171 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E0C14C433F5 for ; Tue, 14 Sep 2021 13:11:58 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8F25761056 for ; Tue, 14 Sep 2021 13:11:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 8F25761056 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:49040 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8E9-0000Pl-F5 for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:11:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37468) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83o-0005SZ-CD for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:16 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57610 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83c-0007r6-Na for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:15 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S8; Tue, 14 Sep 2021 21:01:01 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 06/21] target/loongarch: Add fixed point bit instruction translation Date: Tue, 14 Sep 2021 21:00:16 +0800 Message-Id: <1631624431-30658-7-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S8 X-Coremail-Antispam: 1UD129KBjvAXoW3Kw1rGFyfJr1UJry3JF4rGrg_yoW8Jw4fJo W7GF45Jr48Gr1Yvryaka48XrW8tr12ka1xJ3s5uF4jg3WxJrnrJr1UKFs8Zw48Jw1q9Fyr JF9aqFy3J3y3Xrn7n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/helper.h | 4 + target/loongarch/insn_trans/trans_bit.c | 255 ++++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 45 ++++++ target/loongarch/op_helper.c | 22 +++ target/loongarch/translate.c | 1 + 5 files changed, 327 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..fb4c44e --- /dev/null +++ b/target/loongarch/insn_trans/trans_bit.c @@ -0,0 +1,255 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_r2(DisasContext *ctx, arg_fmt_rdrj *a, + DisasExtend src_ext, DisasExtend dst_ext, + void (*func)(TCGv, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd, dst_ext); + TCGv src1 = gpr_src(ctx, a->rj, src_ext); + + func(dest, src1); + + if (dst_ext) { + gen_set_gpr(a->rd, dest, dst_ext); + } + return true; +} + +static bool trans_bytepick_w(DisasContext *ctx, arg_bytepick_w *a) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + tcg_gen_concat_tl_i64(dest, src1, src2); + tcg_gen_sextract_i64(dest, dest, (32 - (a->sa2) * 8), 32); + + return true; +} + +static bool trans_bytepick_d(DisasContext *ctx, arg_bytepick_d *a) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + tcg_gen_extract2_i64(dest, src1, src2, (64 - (a->sa3) * 8)); + return true; +} + +static bool trans_bstrins_w(DisasContext *ctx, arg_bstrins_w *a) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + if (a->lsbw > a->msbw) { + return false; + } + + tcg_gen_deposit_tl(dest, dest, src1, a->lsbw, a->msbw - a->lsbw + 1); + tcg_gen_ext32s_tl(dest, dest); + + return true; +} + +static bool trans_bstrins_d(DisasContext *ctx, arg_bstrins_d *a) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + if (a->lsbd > a->msbd) { + return false; + } + + tcg_gen_deposit_tl(dest, dest, src1, a->lsbd, a->msbd - a->lsbd + 1); + return true; +} + +static bool trans_bstrpick_w(DisasContext *ctx, arg_bstrpick_w *a) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + if ((a->lsbw > a->msbw) || (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, EXT_NONE); + 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); + tcg_gen_ext32u_tl(dest, dest); + gen_clz_w(dest, dest); +} + +static void gen_ctz_w(TCGv dest, TCGv src1) +{ + tcg_gen_ori_tl(dest, src1, (target_ulong)MAKE_64BIT_MASK(32, 32)); + tcg_gen_ctzi_tl(dest, dest, 32); +} + +static void gen_cto_w(TCGv dest, TCGv src1) +{ + tcg_gen_not_tl(dest, src1); + tcg_gen_ext32u_tl(dest, dest); + gen_ctz_w(dest, dest); +} + +static void gen_clz_d(TCGv dest, TCGv src1) +{ + tcg_gen_clzi_i64(dest, src1, TARGET_LONG_BITS); +} + +static void gen_clo_d(TCGv dest, TCGv src1) +{ + tcg_gen_not_tl(dest, src1); + gen_clz_d(dest, dest); +} + +static void gen_ctz_d(TCGv dest, TCGv src1) +{ + tcg_gen_ctzi_tl(dest, src1, TARGET_LONG_BITS); +} + +static void gen_cto_d(TCGv dest, TCGv src1) +{ + tcg_gen_not_tl(dest, src1); + gen_ctz_d(dest, dest); +} + +static void gen_revb_2w(TCGv dest, TCGv src1) +{ + tcg_gen_bswap64_i64(dest, src1); + tcg_gen_rotri_i64(dest, dest, 32); +} + +static void gen_revb_2h(TCGv dest, TCGv src1) +{ + TCGv mask = tcg_constant_tl(0x00FF00FF); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + tcg_gen_shri_tl(t0, src1, 8); + tcg_gen_and_tl(t0, t0, mask); + tcg_gen_and_tl(t1, src1, mask); + tcg_gen_shli_tl(t1, t1, 8); + tcg_gen_or_tl(dest, t0, t1); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_revb_4h(TCGv dest, TCGv src1) +{ + TCGv mask = tcg_constant_tl(0x00FF00FF00FF00FFULL); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + tcg_gen_shri_tl(t0, src1, 8); + tcg_gen_and_tl(t0, t0, mask); + tcg_gen_and_tl(t1, src1, mask); + tcg_gen_shli_tl(t1, t1, 8); + tcg_gen_or_tl(dest, t0, t1); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_revh_2w(TCGv dest, TCGv src1) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 mask = tcg_constant_i64(0x0000ffff0000ffffull); + + tcg_gen_shri_i64(t0, src1, 16); + tcg_gen_and_i64(t1, src1, mask); + tcg_gen_and_i64(t0, t0, mask); + tcg_gen_shli_i64(t1, t1, 16); + tcg_gen_or_i64(dest, t1, t0); + + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); +} + +static void gen_revh_d(TCGv dest, TCGv src1) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv mask = tcg_constant_tl(0x0000FFFF0000FFFFULL); + + tcg_gen_shri_tl(t1, src1, 16); + tcg_gen_and_tl(t1, t1, mask); + tcg_gen_and_tl(t0, src1, mask); + tcg_gen_shli_tl(t0, t0, 16); + tcg_gen_or_tl(t0, t0, t1); + tcg_gen_rotri_tl(dest, t0, 32); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_maskeqz(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv zero = tcg_constant_tl(0); + + tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, zero, zero, src1); +} + +static void gen_masknez(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv zero = tcg_constant_tl(0); + + tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, zero, zero, src1); +} + +TRANS(ext_w_h, gen_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_2h, gen_r2, EXT_NONE, EXT_SIGN, gen_revb_2h) +TRANS(revb_4h, gen_r2, EXT_NONE, EXT_NONE, gen_revb_4h) +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(revh_2w, gen_r2, EXT_NONE, EXT_NONE, gen_revh_2w) +TRANS(revh_d, gen_r2, EXT_NONE, EXT_NONE, gen_revh_d) +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 5ef572f..38e6d17 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -143,6 +143,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #include "decode-insns.c.inc" #include "insn_trans/trans_arith.c" #include "insn_trans/trans_shift.c" +#include "insn_trans/trans_bit.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Tue Sep 14 13:00:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493229 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A2C3C433F5 for ; Tue, 14 Sep 2021 13:14:18 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 07EFC610D1 for ; Tue, 14 Sep 2021 13:14:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 07EFC610D1 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:57344 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8GP-00065R-8B for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:14:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37504) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83p-0005Wv-G3 for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:17 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57632 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83d-0007rF-7b for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:17 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S9; Tue, 14 Sep 2021 21:01:02 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 07/21] target/loongarch: Add fixed point load/store instruction translation Date: Tue, 14 Sep 2021 21:00:17 +0800 Message-Id: <1631624431-30658-8-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S9 X-Coremail-Antispam: 1UD129KBjvAXoW3Zw17Ar45Zw17Zr18AFy3twb_yoW8GF4fto WUGa15Jr48Gr1Yyr13Kwn5XrWayr1j9397A398ua1DK3W7Jr17Jr17Crn5Za1fJ3yqgryf Gr1SqF15tw1aqrnrn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/helper.h | 3 + target/loongarch/insn_trans/trans_memory.c | 235 +++++++++++++++++++++++++++++ target/loongarch/insns.decode | 58 +++++++ target/loongarch/op_helper.c | 15 ++ target/loongarch/translate.c | 30 ++++ 5 files changed, 341 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..343d51c --- /dev/null +++ b/target/loongarch/insn_trans/trans_memory.c @@ -0,0 +1,235 @@ +/* + * 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, MemOp mop) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv temp = NULL; + + if (a->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 (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, MemOp mop) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_storex(DisasContext *ctx, arg_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, MemOp mop) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtgt_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_load_le(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtle_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_store_gt(DisasContext *ctx, arg_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, MemOp mop) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv temp = NULL; + + if (a->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 (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, MO_SB) +TRANS(ld_h, gen_load, MO_TESW) +TRANS(ld_w, gen_load, MO_TESL) +TRANS(ld_d, gen_load, MO_TEQ) +TRANS(st_b, gen_store, MO_SB) +TRANS(st_h, gen_store, MO_TESW) +TRANS(st_w, gen_store, MO_TESL) +TRANS(st_d, gen_store, MO_TEQ) +TRANS(ld_bu, gen_load, MO_UB) +TRANS(ld_hu, gen_load, MO_TEUW) +TRANS(ld_wu, gen_load, MO_TEUL) +TRANS(ldx_b, gen_loadx, MO_SB) +TRANS(ldx_h, gen_loadx, MO_TESW) +TRANS(ldx_w, gen_loadx, MO_TESL) +TRANS(ldx_d, gen_loadx, MO_TEQ) +TRANS(stx_b, gen_storex, MO_SB) +TRANS(stx_h, gen_storex, MO_TESW) +TRANS(stx_w, gen_storex, MO_TESL) +TRANS(stx_d, gen_storex, MO_TEQ) +TRANS(ldx_bu, gen_loadx, MO_UB) +TRANS(ldx_hu, gen_loadx, MO_TEUW) +TRANS(ldx_wu, gen_loadx, MO_TEUL) +TRANS(ldptr_w, gen_ldptr, MO_TESL) +TRANS(stptr_w, gen_stptr, MO_TESL) +TRANS(ldptr_d, gen_ldptr, MO_TEQ) +TRANS(stptr_d, gen_stptr, MO_TEQ) +TRANS(ldgt_b, gen_load_gt, MO_SB) +TRANS(ldgt_h, gen_load_gt, MO_TESW) +TRANS(ldgt_w, gen_load_gt, MO_TESL) +TRANS(ldgt_d, gen_load_gt, MO_TEQ) +TRANS(ldle_b, gen_load_le, MO_SB) +TRANS(ldle_h, gen_load_le, MO_TESW) +TRANS(ldle_w, gen_load_le, MO_TESL) +TRANS(ldle_d, gen_load_le, MO_TEQ) +TRANS(stgt_b, gen_store_gt, MO_SB) +TRANS(stgt_h, gen_store_gt, MO_TESW) +TRANS(stgt_w, gen_store_gt, MO_TESL) +TRANS(stgt_d, gen_store_gt, MO_TEQ) +TRANS(stle_b, gen_store_le, MO_SB) +TRANS(stle_h, gen_store_le, MO_TESW) +TRANS(stle_w, gen_store_le, MO_TESL) +TRANS(stle_d, gen_store_le, MO_TEQ) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 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 38e6d17..807cb54 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -65,6 +65,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) { } @@ -144,6 +173,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #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) { From patchwork Tue Sep 14 13:00:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493165 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1098C433F5 for ; Tue, 14 Sep 2021 13:09:48 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 51185610CE for ; Tue, 14 Sep 2021 13:09:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 51185610CE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:42946 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8C3-0004VV-GX for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:09:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37566) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83y-0005eg-8x for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:26 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57662 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83h-0007sg-2p for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:24 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S10; Tue, 14 Sep 2021 21:01:02 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 08/21] target/loongarch: Add fixed point atomic instruction translation Date: Tue, 14 Sep 2021 21:00:18 +0800 Message-Id: <1631624431-30658-9-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S10 X-Coremail-Antispam: 1UD129KBjvJXoW3Jw4xKw43XFWxWFy8Gr4rZrb_yoWDGw1kpr 42kryxXr4Fqry5Jr95tws0g343GFnIv347Wry3tr1kZF1UGF15JF18J39IkFWUXws5ZFW8 KFWay34jkFy5JaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: 0 X-Spam_score: -0.0 X-Spam_bar: / X-Spam_report: (-0.0 / 5.0 requ) SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/insn_trans/trans_atomic.c | 133 +++++++++++++++++++++++++++++ target/loongarch/insns.decode | 44 ++++++++++ target/loongarch/translate.c | 1 + 3 files changed, 178 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..7613f21 --- /dev/null +++ b/target/loongarch/insn_trans/trans_atomic.c @@ -0,0 +1,133 @@ +/* + * 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, EXT_NONE); + 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, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE); + TCGv t0 = tcg_temp_new(); + TCGv val = tcg_temp_new(); + + TCGLabel *l1 = gen_new_label(); + TCGLabel *done = gen_new_label(); + + tcg_gen_addi_tl(t0, src1, a->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); + tcg_gen_mov_tl(val, src2); + /* generate cmpxchg */ + tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, + val, ctx->mem_idx, mop); + tcg_gen_setcond_tl(TCG_COND_EQ, dest, t0, cpu_llval); + gen_set_label(done); + tcg_temp_free(t0); + tcg_temp_free(val); + return true; +} + +static bool gen_am(DisasContext *ctx, arg_fmt_rdrjrk *a, + void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), + MemOp mop) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv val = gpr_src(ctx, a->rk, EXT_NONE); + + if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { + qemu_log_mask(LOG_GUEST_ERROR, + "Warning: source register overlaps destination register" + "in atomic insn at pc=0x" TARGET_FMT_lx "\n", + ctx->base.pc_next - 4); + return false; + } + + func(dest, addr, val, ctx->mem_idx, mop); + return true; +} + +static bool gen_am_db(DisasContext *ctx, arg_fmt_rdrjrk *a, + void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), + MemOp mop) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv val = gpr_src(ctx, a->rk, EXT_NONE); + + if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { + qemu_log_mask(LOG_GUEST_ERROR, + "Warning: source register overlaps destination register" + "in atomic insn at pc=0x" TARGET_FMT_lx "\n", + ctx->base.pc_next - 4); + return false; + } + + gen_loongarch_sync(0x10); + func(dest, addr, val, ctx->mem_idx, mop); + + return true; +} + +TRANS(ll_w, gen_ll, tcg_gen_qemu_ld32s) +TRANS(sc_w, gen_sc, MO_TESL) +TRANS(ll_d, gen_ll, tcg_gen_qemu_ld64) +TRANS(sc_d, gen_sc, MO_TEQ) +TRANS(amswap_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL) +TRANS(amswap_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEQ) +TRANS(amadd_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL) +TRANS(amadd_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEQ) +TRANS(amand_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL) +TRANS(amand_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEQ) +TRANS(amor_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL) +TRANS(amor_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEQ) +TRANS(amxor_w, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL) +TRANS(amxor_d, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEQ) +TRANS(ammax_w, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL) +TRANS(ammax_d, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEQ) +TRANS(ammin_w, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL) +TRANS(ammin_d, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEQ) +TRANS(ammax_wu, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL) +TRANS(ammax_du, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEQ) +TRANS(ammin_wu, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL) +TRANS(ammin_du, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEQ) +TRANS(amswap_db_w, gen_am_db, tcg_gen_atomic_xchg_tl, MO_TESL) +TRANS(amswap_db_d, gen_am_db, tcg_gen_atomic_xchg_tl, MO_TEQ) +TRANS(amadd_db_w, gen_am_db, tcg_gen_atomic_fetch_add_tl, MO_TESL) +TRANS(amadd_db_d, gen_am_db, tcg_gen_atomic_fetch_add_tl, MO_TEQ) +TRANS(amand_db_w, gen_am_db, tcg_gen_atomic_fetch_and_tl, MO_TESL) +TRANS(amand_db_d, gen_am_db, tcg_gen_atomic_fetch_and_tl, MO_TEQ) +TRANS(amor_db_w, gen_am_db, tcg_gen_atomic_fetch_or_tl, MO_TESL) +TRANS(amor_db_d, gen_am_db, tcg_gen_atomic_fetch_or_tl, MO_TEQ) +TRANS(amxor_db_w, gen_am_db, tcg_gen_atomic_fetch_xor_tl, MO_TESL) +TRANS(amxor_db_d, gen_am_db, tcg_gen_atomic_fetch_xor_tl, MO_TEQ) +TRANS(ammax_db_w, gen_am_db, tcg_gen_atomic_fetch_smax_tl, MO_TESL) +TRANS(ammax_db_d, gen_am_db, tcg_gen_atomic_fetch_smax_tl, MO_TEQ) +TRANS(ammin_db_w, gen_am_db, tcg_gen_atomic_fetch_smin_tl, MO_TESL) +TRANS(ammin_db_d, gen_am_db, tcg_gen_atomic_fetch_smin_tl, MO_TEQ) +TRANS(ammax_db_wu, gen_am_db, tcg_gen_atomic_fetch_umax_tl, MO_TESL) +TRANS(ammax_db_du, gen_am_db, tcg_gen_atomic_fetch_umax_tl, MO_TEQ) +TRANS(ammin_db_wu, gen_am_db, tcg_gen_atomic_fetch_umin_tl, MO_TESL) +TRANS(ammin_db_du, gen_am_db, tcg_gen_atomic_fetch_umin_tl, MO_TEQ) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 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 807cb54..1ec3be6 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -174,6 +174,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #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) { From patchwork Tue Sep 14 13:00:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493341 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8FD50C433EF for ; Tue, 14 Sep 2021 13:20:55 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5049E610A6 for ; Tue, 14 Sep 2021 13:20:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5049E610A6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:46024 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8Mo-00012M-B0 for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:20:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37574) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83y-0005h5-JI for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:26 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57694 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83h-0007sm-Tf for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:26 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S11; Tue, 14 Sep 2021 21:01:04 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 09/21] target/loongarch: Add fixed point extra instruction translation Date: Tue, 14 Sep 2021 21:00:19 +0800 Message-Id: <1631624431-30658-10-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S11 X-Coremail-Antispam: 1UD129KBjvJXoW3Xr4kZr4kArW8XF4rWF1UGFg_yoW3CrWDpF 1xCryUGrW8Jry7Z3s5Kw45tr15Xr4fuF47X3yftw1rAF17XF1DJr48t39IkFWUJw1DXryj qa13AryDKFyUXaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/helper.h | 4 ++ target/loongarch/insn_trans/trans_extra.c | 87 +++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 25 +++++++++ target/loongarch/op_helper.c | 26 +++++++++ target/loongarch/translate.c | 1 + 5 files changed, 143 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) diff --git a/target/loongarch/insn_trans/trans_extra.c b/target/loongarch/insn_trans/trans_extra.c new file mode 100644 index 0000000..8da3b40 --- /dev/null +++ b/target/loongarch/insn_trans/trans_extra.c @@ -0,0 +1,87 @@ +/* + * 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, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + gen_helper_cpucfg(dest, cpu_env, src1); + return true; +} + +static bool gen_crc(DisasContext *ctx, arg_fmt_rdrjrk *a, + void (*func)(TCGv, TCGv, TCGv, TCGv), + TCGv tsz) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + func(dest, src2, src1, tsz); + + gen_set_gpr(a->rd, dest, EXT_SIGN); + return true; +} + +TRANS(crc_w_b_w, gen_crc, gen_helper_crc32, tcg_constant_tl(1)) +TRANS(crc_w_h_w, gen_crc, gen_helper_crc32, tcg_constant_tl(2)) +TRANS(crc_w_w_w, gen_crc, gen_helper_crc32, tcg_constant_tl(4)) +TRANS(crc_w_d_w, gen_crc, gen_helper_crc32, tcg_constant_tl(8)) +TRANS(crcc_w_b_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(1)) +TRANS(crcc_w_h_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(2)) +TRANS(crcc_w_w_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(4)) +TRANS(crcc_w_d_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(8)) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 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 /* 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 1ec3be6..d0e1daa 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -175,6 +175,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #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) { From patchwork Tue Sep 14 13:00:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493235 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7A0E8C433F5 for ; Tue, 14 Sep 2021 13:17:52 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 27E19610E6 for ; Tue, 14 Sep 2021 13:17:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 27E19610E6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:37574 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8Jq-0003i3-1f for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:17:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37568) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ83y-0005fK-Ae for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:26 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57700 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83i-0007so-Cx for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:26 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S12; Tue, 14 Sep 2021 21:01:07 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 10/21] target/loongarch: Add floating point arithmetic instruction translation Date: Tue, 14 Sep 2021 21:00:20 +0800 Message-Id: <1631624431-30658-11-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S12 X-Coremail-Antispam: 1UD129KBjvAXoWfXw43uw1Utr4DAFyxJry8AFb_yoW8tFy5uo W7u3W5Ar48G3yxuF98KwnYqr47XryUA3ZxJrWrZw15Ka4xGry7K3W5G3s5Aa1fGrWktrW5 Jrnayw15JwnIvr93n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang --- target/loongarch/cpu.c | 1 + target/loongarch/fpu_helper.c | 365 +++++++++++++++++++++++++++++ target/loongarch/helper.h | 33 +++ target/loongarch/insn_trans/trans_farith.c | 131 +++++++++++ target/loongarch/insns.decode | 56 +++++ target/loongarch/internals.h | 2 + target/loongarch/translate.c | 11 + 7 files changed, 599 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..e7d3454 --- /dev/null +++ b/target/loongarch/fpu_helper.c @@ -0,0 +1,365 @@ +/* + * 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 "internals.h" + +#define FLOAT_TO_INT32_OVERFLOW 0x7fffffff +#define FLOAT_TO_INT64_OVERFLOW 0x7fffffffffffffffULL + +static inline uint64_t nanbox_s(float32 fp) +{ + return fp | MAKE_64BIT_MASK(32, 32); +} + +/* convert loongarch rounding mode in fcsr0 to IEEE library */ +static const FloatRoundMode ieee_rm[4] = { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down +}; + +void restore_fp_status(CPULoongArchState *env) +{ + set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3], + &env->fp_status); + set_flush_to_zero(0, &env->fp_status); +} + +static int ieee_ex_to_loongarch(int xcpt) +{ + int ret = 0; + if (xcpt & float_flag_invalid) { + ret |= FP_INVALID; + } + if (xcpt & float_flag_overflow) { + ret |= FP_OVERFLOW; + } + if (xcpt & float_flag_underflow) { + ret |= FP_UNDERFLOW; + } + if (xcpt & float_flag_divbyzero) { + ret |= FP_DIV0; + } + if (xcpt & float_flag_inexact) { + ret |= FP_INEXACT; + } + return ret; +} + +static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask) +{ + int flags = get_float_exception_flags(&env->fp_status) & (~mask); + + if (!flags) { + SET_FP_CAUSE(env->fcsr0, flags); + return; + } + + flags = ieee_ex_to_loongarch(flags); + set_float_exception_flags(0, &env->fp_status); + SET_FP_CAUSE(env->fcsr0, flags); + + if (GET_FP_ENABLES(env->fcsr0) & flags) { + do_raise_exception(env, EXCP_FPE, pc); + } else { + UPDATE_FP_FLAGS(env->fcsr0, flags); + } +} + +static void update_fcsr0(CPULoongArchState *env, uintptr_t pc) +{ + update_fcsr0_mask(env, pc, 0); +} + +uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_add(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_sub(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_mul(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_div(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_maxnummag((uint32_t)fj, + (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_maxnummag(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_minnummag((uint32_t)fj, + (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_minnummag(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + int32_t n = (int32_t)fk; + + fd = nanbox_s(float32_scalbn((uint32_t)fj, + n > 0x200 ? 0x200 : + n < -0x200 ? -0x200 : n, + &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + int64_t n = (int64_t)fk; + + fd = float64_scalbn(fj, + n > 0x1000 ? 0x1000 : + n < -0x1000 ? -0x1000 : n, + &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_sqrt(fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_div(float64_one, fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + uint32_t fp; + + fp = float32_sqrt((uint32_t)fj, &env->fp_status); + fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fp, fd; + + fp = float64_sqrt(fj, &env->fp_status); + fd = float64_div(float64_one, fp, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + uint32_t fp; + float_status *status = &env->fp_status; + FloatRoundMode old_mode = get_float_rounding_mode(status); + + set_float_rounding_mode(float_round_down, status); + fp = float32_log2((uint32_t)fj, status); + fd = nanbox_s(float32_round_to_int(fp, status)); + set_float_rounding_mode(old_mode, status); + update_fcsr0_mask(env, GETPC(), float_flag_inexact); + return fd; +} + +uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + float_status *status = &env->fp_status; + FloatRoundMode old_mode = get_float_rounding_mode(status); + + set_float_rounding_mode(float_round_down, status); + fd = float64_log2(fj, status); + fd = float64_round_to_int(fd, status); + set_float_rounding_mode(old_mode, status); + update_fcsr0_mask(env, GETPC(), float_flag_inexact); + return fd; +} + +uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj) +{ + float32 f = fj; + bool sign = float32_is_neg(f); + + if (float32_is_infinity(f)) { + return sign ? 1 << 0 : 1 << 7; + } else if (float32_is_zero(f)) { + return sign ? 1 << 3 : 1 << 4; + } else if (float32_is_zero_or_denormal(f)) { + return sign ? 1 << 2 : 1 << 5; + } else if (float32_is_any_nan(f)) { + float_status s = { }; /* for snan_bit_is_one */ + return float32_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; + } else { + return sign ? 1 << 1 : 1 << 6; + } +} + +uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj) +{ + float64 f = fj; + bool sign = float64_is_neg(f); + + if (float64_is_infinity(f)) { + return sign ? 1 << 0 : 1 << 7; + } else if (float64_is_zero(f)) { + return sign ? 1 << 3 : 1 << 4; + } else if (float64_is_zero_or_denormal(f)) { + return sign ? 1 << 2 : 1 << 5; + } else if (float64_is_any_nan(f)) { + float_status s = { }; /* for snan_bit_is_one */ + return float64_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; + } else { + return sign ? 1 << 1 : 1 << 6; + } +} + +uint64_t helper_fmuladd_s(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint64_t fa, uint32_t flag) +{ + uint64_t fd; + + fd = nanbox_s(float32_muladd((uint32_t)fj, (uint32_t)fk, + (uint32_t)fa, flag, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint64_t fa, uint32_t flag) +{ + uint64_t fd; + + fd = float64_muladd(fj, fk, fa, flag, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index e4b4595..25a67fd 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -18,3 +18,36 @@ 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(fmaxa_s, i64, env, i64, i64) +DEF_HELPER_3(fmaxa_d, i64, env, i64, i64) +DEF_HELPER_3(fmina_s, i64, env, i64, i64) +DEF_HELPER_3(fmina_d, i64, env, i64, i64) + +DEF_HELPER_5(fmuladd_s, i64, env, i64, i64, i64, i32) +DEF_HELPER_5(fmuladd_d, i64, env, i64, i64, i64, i32) + +DEF_HELPER_3(fscaleb_s, i64, env, i64, i64) +DEF_HELPER_3(fscaleb_d, i64, env, i64, i64) + +DEF_HELPER_2(flogb_s, i64, env, i64) +DEF_HELPER_2(flogb_d, i64, env, i64) + +DEF_HELPER_2(fsqrt_s, i64, env, i64) +DEF_HELPER_2(fsqrt_d, i64, env, i64) +DEF_HELPER_2(frsqrt_s, i64, env, i64) +DEF_HELPER_2(frsqrt_d, i64, env, i64) +DEF_HELPER_2(frecip_s, i64, env, i64) +DEF_HELPER_2(frecip_d, i64, env, i64) + +DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64) +DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64) diff --git a/target/loongarch/insn_trans/trans_farith.c b/target/loongarch/insn_trans/trans_farith.c new file mode 100644 index 0000000..005fa85 --- /dev/null +++ b/target/loongarch/insn_trans/trans_farith.c @@ -0,0 +1,131 @@ +/* + * 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_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; +} + +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; +} + +static bool trans_fmax_s(DisasContext *ctx, arg_fmt_fdfjfk *a) +{ + tcg_gen_umax_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], cpu_fpr[a->fk]); + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + return true; +} + +static bool trans_fmax_d(DisasContext *ctx, arg_fmt_fdfjfk *a) +{ + tcg_gen_umax_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], cpu_fpr[a->fk]); + return true; +} + +static bool trans_fmin_s(DisasContext *ctx, arg_fmt_fdfjfk *a) +{ + tcg_gen_umin_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], cpu_fpr[a->fk]); + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + return true; +} + +static bool trans_fmin_d(DisasContext *ctx, arg_fmt_fdfjfk *a) +{ + tcg_gen_umin_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], cpu_fpr[a->fk]); + return true; +} + +static bool trans_fabs_s(DisasContext *ctx, arg_fmt_fdfj *a) +{ + tcg_gen_ext32u_tl(cpu_fpr[a->fj], cpu_fpr[a->fj]); + tcg_gen_abs_i64(cpu_fpr[a->fd], cpu_fpr[a->fj]); + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + return true; +} + +static bool trans_fabs_d(DisasContext *ctx, arg_fmt_fdfj *a) +{ + tcg_gen_abs_i64(cpu_fpr[a->fd], cpu_fpr[a->fj]); + return true; +} + +static bool trans_fneg_s(DisasContext *ctx, arg_fmt_fdfj *a) +{ + tcg_gen_xori_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], 0x80000000); + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + return true; +} + +static bool trans_fneg_d(DisasContext *ctx, arg_fmt_fdfj *a) +{ + tcg_gen_xori_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], 0x8000000000000000LL); + 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(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(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 d0e1daa..9befe8e 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" @@ -27,6 +28,15 @@ TCGv_i64 cpu_fpr[32]; #define DISAS_STOP DISAS_TARGET_0 +/* + * LoongArch requires NaN-boxing of narrower width floating point values. + * This applies when a 32-bit value is assigned to a 64-bit FP register. + */ +static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in) +{ + tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32)); +} + void generate_exception(DisasContext *ctx, int excp) { tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); @@ -176,6 +186,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #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) { From patchwork Tue Sep 14 13:00:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493417 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 357F4C433EF for ; Tue, 14 Sep 2021 13:35:16 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CE13360E74 for ; Tue, 14 Sep 2021 13:35:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org CE13360E74 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:58098 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8ag-0003OG-SG for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:35:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39784) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ8AB-0000mb-LP for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:07:51 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59620 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8A8-0003IQ-Jl for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:07:51 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S13; Tue, 14 Sep 2021 21:01:07 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 11/21] target/loongarch: Add floating point comparison instruction translation Date: Tue, 14 Sep 2021 21:00:21 +0800 Message-Id: <1631624431-30658-12-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S13 X-Coremail-Antispam: 1UD129KBjvJXoW3Xr4DJF17KFyfurW8XryrJFb_yoW3Jr43pF W7Zry3GF48WFWfJas2qay5GF15Jr48Ka17uFy3t34vyF45XFn7ZFy8ta429FWUG3s5ury8 X3WSyryUWFy7XaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch implement floating point comparison instruction translation. This includes: - FCMP.cond.{S/D} Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/fpu_helper.c | 60 ++++++++++++++++++++++++++++++++ target/loongarch/helper.h | 9 +++++ target/loongarch/insn_trans/trans_fcmp.c | 59 +++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 10 ++++++ target/loongarch/internals.h | 5 +++ target/loongarch/translate.c | 1 + 6 files changed, 144 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 e7d3454..390bf5c 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -363,3 +363,63 @@ uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj, update_fcsr0(env, GETPC()); return fd; } + +static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp, + uint32_t flags) +{ + bool ret; + + switch (cmp) { + case float_relation_less: + ret = (flags & FCMP_LT); + break; + case float_relation_equal: + ret = (flags & FCMP_EQ); + break; + case float_relation_greater: + ret = (flags & FCMP_GT); + break; + case float_relation_unordered: + ret = (flags & FCMP_UN); + break; + default: + g_assert_not_reached(); + } + update_fcsr0(env, GETPC()); + + return ret; +} + +/* fcmp_cXXX_s */ +uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ + FloatRelation cmp = float32_compare_quiet((uint32_t)fj, + (uint32_t)fk, &env->fp_status); + return fcmp_common(env, cmp, flags); +} + +/* fcmp_sXXX_s */ +uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ + FloatRelation cmp = float32_compare((uint32_t)fj, + (uint32_t)fk, &env->fp_status); + return fcmp_common(env, cmp, flags); +} + +/* fcmp_cXXX_d */ +uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ + FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status); + return fcmp_common(env, cmp, flags); +} + +/* fcmp_sXXX_d */ +uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ + FloatRelation cmp = float64_compare(fj, fk, &env->fp_status); + return fcmp_common(env, cmp, flags); +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 25a67fd..91140aa 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -51,3 +51,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..1c5945b --- /dev/null +++ b/target/loongarch/insn_trans/trans_fcmp.c @@ -0,0 +1,59 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +/* bit0(signaling/quiet) bit1(lt) bit2(eq) bit3(un) bit4(neq) */ +static uint32_t get_fcmp_flags(int cond) +{ + uint32_t flags = 0; + + if (cond & 0x1) { + flags |= FCMP_LT; + } + if (cond & 0x2) { + flags |= FCMP_EQ; + } + if (cond & 0x4) { + flags |= FCMP_UN; + } + if (cond & 0x8) { + flags |= FCMP_GT | FCMP_LT; + } + return flags; +} + +static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a) +{ + TCGv var = tcg_temp_new(); + uint32_t flags; + void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32); + + fn = (a->fcond & 1 ? gen_helper_fcmp_s_s : gen_helper_fcmp_c_s); + flags = get_fcmp_flags(a->fcond >> 1); + + fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], tcg_constant_i32(flags)); + + tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + tcg_temp_free(var); + return true; +} + +static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a) +{ + TCGv var = tcg_temp_new(); + uint32_t flags; + void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32); + fn = (a->fcond & 1 ? gen_helper_fcmp_s_d : gen_helper_fcmp_c_d); + flags = get_fcmp_flags(a->fcond >> 1); + + fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], tcg_constant_i32(flags)); + + tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + + tcg_temp_free(var); + return true; +} diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 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/internals.h b/target/loongarch/internals.h index 096a4a7..b408aed 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -9,6 +9,11 @@ #ifndef LOONGARCH_INTERNALS_H #define LOONGARCH_INTERNALS_H +#define FCMP_LT 0x0001 /* fp0 < fp1 */ +#define FCMP_EQ 0x0010 /* fp0 = fp1 */ +#define FCMP_UN 0x0100 /* unordered */ +#define FCMP_GT 0x1000 /* fp0 > fp1 */ + void loongarch_translate_init(void); void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 9befe8e..e7abc53 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -187,6 +187,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #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) { From patchwork Tue Sep 14 13:00:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493169 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 000DCC433EF for ; Tue, 14 Sep 2021 13:11:38 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A16B86008E for ; Tue, 14 Sep 2021 13:11:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org A16B86008E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:47882 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8Dp-0007xU-Hi for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:11:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37626) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ841-0005pC-4h for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:29 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57764 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83w-0007v3-UN for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:28 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S14; Tue, 14 Sep 2021 21:01:09 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 12/21] target/loongarch: Add floating point conversion instruction translation Date: Tue, 14 Sep 2021 21:00:22 +0800 Message-Id: <1631624431-30658-13-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S14 X-Coremail-Antispam: 1UD129KBjvAXoW3Zr47Ww17Kr4UtrWxGrWUtwb_yoW8Zr1UCo Z8uF4rZr4rG3yfuFZIkwnYqF1xXry8ArnxCF4rZryaga4xA34xKFWrCwn5AFyrKrWYqry5 Xrn3Z3W5Aw4aqr93n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- 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 390bf5c..7944ced 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -423,3 +423,396 @@ uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj, FloatRelation cmp = float64_compare(fj, fk, &env->fp_status); return fcmp_common(env, cmp, flags); } + +/* floating point conversion */ +uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(float64_to_float32(fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float32_to_float64((uint32_t)fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(int64_to_float32(fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = int32_to_float64((int32_t)fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = int64_to_float64(fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_round_to_int(fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_down, &env->fp_status); + fd = float64_to_int64(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_down, &env->fp_status); + fd = float32_to_int64((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_down, &env->fp_status); + fd = (uint64_t)float64_to_int32(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_down, &env->fp_status); + fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_up, &env->fp_status); + fd = float64_to_int64(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrp_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_up, &env->fp_status); + fd = float32_to_int64((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrp_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_up, &env->fp_status); + fd = (uint64_t)float64_to_int32(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrp_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_up, &env->fp_status); + fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrz_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + fd = float64_to_int64_round_to_zero(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrz_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + fd = float32_to_int64_round_to_zero((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrz_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + fd = (uint64_t)float64_to_int32_round_to_zero(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrz_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint32_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + fd = float32_to_int32_round_to_zero((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return (uint64_t)fd; +} + +uint64_t helper_ftintrne_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + fd = float64_to_int64(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrne_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + fd = float32_to_int64((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrne_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + fd = (uint64_t)float64_to_int32(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrne_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint32_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + fd = float32_to_int32((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return (uint64_t)fd; +} + +uint64_t helper_ftint_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_to_int64(fj, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftint_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float32_to_int64((uint32_t)fj, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftint_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) + & (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = (uint64_t)float64_to_int32(fj, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) + & (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 91140aa..84c02d8 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -60,3 +60,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 e7abc53..16275fb 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -188,6 +188,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #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) { From patchwork Tue Sep 14 13:00:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493347 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4EAA5C433EF for ; Tue, 14 Sep 2021 13:23:41 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D9B07606A5 for ; Tue, 14 Sep 2021 13:23:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org D9B07606A5 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:54242 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8PU-0006ca-21 for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:23:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37656) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ844-0005xF-O9 for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:32 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57808 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ83y-0007wt-6l for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:32 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S15; Tue, 14 Sep 2021 21:01:10 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 13/21] target/loongarch: Add floating point move instruction translation Date: Tue, 14 Sep 2021 21:00:23 +0800 Message-Id: <1631624431-30658-14-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S15 X-Coremail-Antispam: 1UD129KBjvJXoWxuw1Dtw43ury5trW5tw1DWrg_yoWfZFWfpr 12kryUCr48JFy3JF97K3yYgF45Jr1xCa4jq3yayry8AF1UJF1UAF1kJ3y2krW5Wwn3uFyU JF4YyFyUKFyUXaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/fpu_helper.c | 6 ++ target/loongarch/helper.h | 2 + target/loongarch/insn_trans/trans_fmov.c | 153 +++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 41 +++++++++ target/loongarch/translate.c | 1 + 5 files changed, 203 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 7944ced..52844f6 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -816,3 +816,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 84c02d8..ed215cb 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -89,3 +89,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..0024c0d --- /dev/null +++ b/target/loongarch/insn_trans/trans_fmov.c @@ -0,0 +1,153 @@ +/* + * 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_f2f(DisasContext *ctx, arg_fmt_fdfj *a, + void (*func)(TCGv, TCGv), bool nanbox) +{ + TCGv dest = cpu_fpr[a->fd]; + TCGv src = cpu_fpr[a->fj]; + + func(dest, src); + if (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + return true; +} + +static bool gen_r2f(DisasContext *ctx, arg_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, + void (*func)(TCGv, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + + func(dest, cpu_fpr[a->fj]); + return true; +} + +static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a) +{ + uint32_t mask = fcsr_mask[a->fcsrd]; + TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE); + + if (mask == UINT32_MAX) { + tcg_gen_extrl_i64_i32(cpu_fcsr0, Rj); + } else { + TCGv_i32 temp = tcg_temp_new_i32(); + + tcg_gen_extrl_i64_i32(temp, Rj); + tcg_gen_andi_i32(temp, temp, mask); + tcg_gen_andi_i32(cpu_fcsr0, cpu_fcsr0, ~mask); + tcg_gen_or_i32(cpu_fcsr0, cpu_fcsr0, temp); + tcg_temp_free_i32(temp); + + /* + * Install the new rounding mode to fpu_status, if changed. + * Note that FCSR3 is exactly the rounding mode field. + */ + if (mask != FCSR0_M3) { + return true; + } + } + gen_helper_set_rounding_mode(cpu_env, cpu_fcsr0); + return true; +} + +static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a) +{ + TCGv_i32 temp = tcg_temp_new_i32(); + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + + tcg_gen_andi_i32(temp, cpu_fcsr0, fcsr_mask[a->fcsrs]); + tcg_gen_ext_i32_i64(dest, temp); + tcg_temp_free_i32(temp); + return true; +} + +static void gen_movgr2fr_w(TCGv dest, TCGv src) +{ + tcg_gen_deposit_i64(dest, dest, src, 0, 32); +} + +static void gen_movgr2frh_w(TCGv dest, TCGv src) +{ + tcg_gen_deposit_i64(dest, dest, src, 32, 32); +} + +static void gen_movfrh2gr_s(TCGv dest, TCGv src) +{ + tcg_gen_sextract_tl(dest, src, 32, 32); +} + +static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a) +{ + TCGv t0 = tcg_temp_new(); + + tcg_gen_andi_tl(t0, cpu_fpr[a->fj], 0x1); + tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + + tcg_temp_free(t0); + return true; +} + +static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a) +{ + tcg_gen_ld8u_tl(cpu_fpr[a->fd], cpu_env, + offsetof(CPULoongArchState, cf[a->cj & 0x7])); + return true; +} + +static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a) +{ + TCGv t0 = tcg_temp_new(); + + tcg_gen_andi_tl(t0, gpr_src(ctx, a->rj, EXT_NONE), 0x1); + tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + + tcg_temp_free(t0); + return true; +} + +static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a) +{ + tcg_gen_ld8u_tl(gpr_dst(ctx, a->rd, EXT_NONE), cpu_env, + offsetof(CPULoongArchState, cf[a->cj & 0x7])); + return true; +} + +TRANS(fmov_s, gen_f2f, tcg_gen_mov_tl, true) +TRANS(fmov_d, gen_f2f, tcg_gen_mov_tl, false) +TRANS(movgr2fr_w, gen_r2f, gen_movgr2fr_w) +TRANS(movgr2fr_d, gen_r2f, tcg_gen_mov_tl) +TRANS(movgr2frh_w, gen_r2f, gen_movgr2frh_w) +TRANS(movfr2gr_s, gen_f2r, tcg_gen_ext32s_tl) +TRANS(movfr2gr_d, gen_f2r, tcg_gen_mov_tl) +TRANS(movfrh2gr_s, gen_f2r, gen_movfrh2gr_s) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 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 16275fb..c57c8ee 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -189,6 +189,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #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) { From patchwork Tue Sep 14 13:00:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493175 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4059EC433EF for ; Tue, 14 Sep 2021 13:13:47 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E0397610A6 for ; Tue, 14 Sep 2021 13:13:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org E0397610A6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:54688 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8Fu-0004Gf-4x for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:13:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37650) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ843-0005tp-BS for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:31 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57846 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ840-00082H-JT for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:30 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S16; Tue, 14 Sep 2021 21:01:13 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 14/21] target/loongarch: Add floating point load/store instruction translation Date: Tue, 14 Sep 2021 21:00:24 +0800 Message-Id: <1631624431-30658-15-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S16 X-Coremail-Antispam: 1UD129KBjvJXoW3Jw4xur17Aw18JFWUtr47urg_yoW3tF4Upr 4Ikry8Gr40qF13Ar93Kw45WFn8ZFnxC3yjg3yayr1IyF1rJF1UJFs7J3y2krWUXw1kXFWU JFZ0yFyUtFyrX3JanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/insn_trans/trans_fmemory.c | 187 ++++++++++++++++++++++++++++ target/loongarch/insns.decode | 24 ++++ target/loongarch/translate.c | 1 + 3 files changed, 212 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..eca2b8b --- /dev/null +++ b/target/loongarch/insn_trans/trans_fmemory.c @@ -0,0 +1,187 @@ +/* + * 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, bool nanbox) +{ + 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 (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + + if (temp) { + tcg_temp_free(temp); + } + return true; +} + +static bool gen_fstore_imm(DisasContext *ctx, arg_fmt_fdrjsi12 *a, + MemOp mop, bool nanbox) +{ + 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; + } + + if (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + + tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + if (temp) { + tcg_temp_free(temp); + } + return true; +} + +static bool gen_fload_tl(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + if (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + + tcg_temp_free(addr); + return true; +} + +static bool gen_fstore_tl(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + tcg_gen_add_tl(addr, src1, src2); + + if (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + + tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_fload_gt(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtgt_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + if (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + + tcg_temp_free(addr); + return true; +} + +static bool gen_fstore_gt(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtgt_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + + if (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + + tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_fload_le(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtle_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + if (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + + tcg_temp_free(addr); + return true; +} + +static bool gen_fstore_le(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtle_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + + if (nanbox) { + gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); + } + + tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +TRANS(fld_s, gen_fload_imm, MO_TESL, true) +TRANS(fst_s, gen_fstore_imm, MO_TEUL, true) +TRANS(fld_d, gen_fload_imm, MO_TEQ, false) +TRANS(fst_d, gen_fstore_imm, MO_TEQ, false) +TRANS(fldx_s, gen_fload_tl, MO_TESL, true) +TRANS(fldx_d, gen_fload_tl, MO_TEQ, false) +TRANS(fstx_s, gen_fstore_tl, MO_TEUL, true) +TRANS(fstx_d, gen_fstore_tl, MO_TEQ, false) +TRANS(fldgt_s, gen_fload_gt, MO_TESL, true) +TRANS(fldgt_d, gen_fload_gt, MO_TEQ, false) +TRANS(fldle_s, gen_fload_le, MO_TESL, true) +TRANS(fldle_d, gen_fload_le, MO_TEQ, false) +TRANS(fstgt_s, gen_fstore_gt, MO_TEUL, true) +TRANS(fstgt_d, gen_fstore_gt, MO_TEQ, false) +TRANS(fstle_s, gen_fstore_le, MO_TEUL, true) +TRANS(fstle_d, gen_fstore_le, MO_TEQ, false) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 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 c57c8ee..5c2e9ee 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -190,6 +190,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #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) { From patchwork Tue Sep 14 13:00:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493231 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3B72C433EF for ; Tue, 14 Sep 2021 13:16:31 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 723D5610A6 for ; Tue, 14 Sep 2021 13:16:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 723D5610A6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:34272 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8IY-0001QJ-GW for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:16:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37792) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ84G-0006Hz-Ur for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:45 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57890 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ847-00084Q-Jn for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:42 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S17; Tue, 14 Sep 2021 21:01:15 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 15/21] target/loongarch: Add branch instruction translation Date: Tue, 14 Sep 2021 21:00:25 +0800 Message-Id: <1631624431-30658-16-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S17 X-Coremail-Antispam: 1UD129KBjvJXoW3Xr4Dur13tr4kGrW3JryUAwb_yoWxGFy8pr 1UCryUKrWkJry3Jrn5tw45Xr13Jrs8Gw17G3y3twn3JF42q3WUAF18AryUKr4jv34kZry8 tF45AryUKFy8XwUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- target/loongarch/insn_trans/trans_branch.c | 85 ++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 30 +++++++++++ target/loongarch/translate.c | 1 + 3 files changed, 116 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..77a6ae6 --- /dev/null +++ b/target/loongarch/insn_trans/trans_branch.c @@ -0,0 +1,85 @@ +/* + * 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, EXT_NONE); + 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 5c2e9ee..cf136f9 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -191,6 +191,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) #include "insn_trans/trans_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) { From patchwork Tue Sep 14 13:00:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493339 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2D0C1C433F5 for ; Tue, 14 Sep 2021 13:19:31 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9783D610E6 for ; Tue, 14 Sep 2021 13:19:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 9783D610E6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:43548 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8LR-0007ig-QM for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:19:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37780) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ84G-0006Hv-3y for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:45 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57914 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ848-00085j-7W for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:43 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S18; Tue, 14 Sep 2021 21:01:19 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 16/21] target/loongarch: Add disassembler Date: Tue, 14 Sep 2021 21:00:26 +0800 Message-Id: <1631624431-30658-17-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S18 X-Coremail-Antispam: 1UD129KBjvAXoWDWFy7Zw4DGF1xZF1rKw1DAwb_yoW7tF47Wo WUJrs5Xws5Ar4DXFZFyF1akayrWr95XFy7Jry8Zwnrtrs3Aw1DWr98Jas5AFy3AFs0krWx G3Z7Cry8KrZ7GFW8n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch add support for disassembling via option '-d in_asm'. Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang Acked-by: Richard Henderson --- 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 ad372a2..44b37ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -214,6 +214,7 @@ LoongArch TCG CPUS M: Song Gao S: Maintained F: target/loongarch/ +F: disas/loongarch.c M68K TCG CPUs M: Laurent Vivier diff --git a/disas/loongarch.c b/disas/loongarch.c new file mode 100644 index 0000000..0647a99 --- /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 */ +static 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 7d7d14a..45bd486 100644 --- a/meson.build +++ b/meson.build @@ -1501,6 +1501,7 @@ disassemblers = { 'sh4' : ['CONFIG_SH4_DIS'], 'sparc' : ['CONFIG_SPARC_DIS'], 'xtensa' : ['CONFIG_XTENSA_DIS'], + 'loongarch' : ['CONFIG_LOONGARCH_DIS'], } if link_language == 'cpp' disassemblers += { From patchwork Tue Sep 14 13:00:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493337 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3634C433EF for ; Tue, 14 Sep 2021 13:19:23 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5F020610A6 for ; Tue, 14 Sep 2021 13:19:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5F020610A6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:42876 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8LK-0007HO-Dp for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:19:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37800) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ84H-0006IF-JD for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:46 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57950 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ847-00085n-7H for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:44 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S19; Tue, 14 Sep 2021 21:01:20 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 17/21] LoongArch Linux User Emulation Date: Tue, 14 Sep 2021 21:00:27 +0800 Message-Id: <1631624431-30658-18-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S19 X-Coremail-Antispam: 1UD129KBjvAXoWfZrW8Xw1rWFW8urW5WFW5Awb_yoW5ZFWxAo WfJF1aqw1kJr1fua1kWw17Wr17ZF9rJr18Ar4UAFy8GFnFqr1DWr13tay8WFn3CrySgFW5 tFyjqr1qyFZYyF97n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Implementation of linux user emulation for LoongArch. Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang --- accel/tcg/user-exec.c | 15 ++ configure | 5 + include/elf.h | 2 + linux-user/elfload.c | 58 ++++++ linux-user/host/loongarch/hostdep.h | 11 + linux-user/loongarch64/cpu_loop.c | 97 +++++++++ linux-user/loongarch64/signal.c | 162 +++++++++++++++ linux-user/loongarch64/sockbits.h | 1 + linux-user/loongarch64/syscall_nr.h | 312 +++++++++++++++++++++++++++++ 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 | 30 +++ linux-user/loongarch64/target_structs.h | 49 +++++ linux-user/loongarch64/target_syscall.h | 46 +++++ linux-user/loongarch64/termbits.h | 1 + linux-user/syscall_defs.h | 10 +- 18 files changed, 863 insertions(+), 4 deletions(-) create mode 100644 linux-user/host/loongarch/hostdep.h 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/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 90d1a2d..0de2819 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -769,6 +769,21 @@ int cpu_signal_handler(int host_signum, void *pinfo, return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } +#elif defined(__loongarch__) + +int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) +{ + siginfo_t *info = pinfo; + ucontext_t *uc = puc; + greg_t pc = uc->uc_mcontext.__pc; + int is_write; + + /* XXX: compute is_write */ + is_write = 0; + return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); +} + #elif defined(__riscv) int cpu_signal_handler(int host_signum, void *pinfo, diff --git a/configure b/configure index da25014..3f90d14 100755 --- a/configure +++ b/configure @@ -659,6 +659,8 @@ elif check_define __arm__ ; then cpu="arm" elif check_define __aarch64__ ; then cpu="aarch64" +elif check_define __loongarch__ ; then + cpu="loongarch" else cpu=$(uname -m) fi @@ -690,6 +692,9 @@ case "$cpu" in sparc|sun4[cdmuv]) cpu="sparc" ;; + loongarch) + cpu="loongarch" + ;; *) # This will result in either an error or falling back to TCI later ARCH=unknown diff --git a/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/host/loongarch/hostdep.h b/linux-user/host/loongarch/hostdep.h new file mode 100644 index 0000000..c1b1537 --- /dev/null +++ b/linux-user/host/loongarch/hostdep.h @@ -0,0 +1,11 @@ +/* + * hostdep.h : things which are dependent on the host architecture + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef LOONGARCH_HOSTDEP_H +#define LOONGARCH_HOSTDEP_H + +#endif diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c new file mode 100644 index 0000000..ccaa0a1 --- /dev/null +++ b/linux-user/loongarch64/cpu_loop.c @@ -0,0 +1,97 @@ +/* + * 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 "signal-common.h" + +void cpu_loop(CPULoongArchState *env) +{ + CPUState *cs = env_cpu(env); + int trapnr, si_code; + abi_long ret; + + for (;;) { + cpu_exec_start(cs); + trapnr = cpu_exec(cs); + cpu_exec_end(cs); + process_queued_cpu_work(cs); + + switch (trapnr) { + case EXCP_INTERRUPT: + /* just indicate that signals should be handled asap */ + break; + case EXCP_SYSCALL: + env->pc += 4; + ret = do_syscall(env, env->gpr[11], + env->gpr[4], env->gpr[5], + env->gpr[6], env->gpr[7], + env->gpr[8], env->gpr[9], + -1, -1); + if (ret == -TARGET_ERESTARTSYS) { + env->pc -= 4; + break; + } + if (ret == -TARGET_QEMU_ESIGRETURN) { + /* + * Returning from a successful sigreturn syscall. + * Avoid clobbering register state. + */ + break; + } + env->gpr[4] = ret; + break; + case EXCP_ADE: + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->badaddr); + break; + case EXCP_INE: + force_sig_fault(TARGET_SIGILL, 0, env->pc); + break; + case EXCP_FPE: + si_code = TARGET_FPE_FLTUNK; + if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) { + si_code = TARGET_FPE_FLTINV; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) { + si_code = TARGET_FPE_FLTDIV; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) { + si_code = TARGET_FPE_FLTOVF; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) { + si_code = TARGET_FPE_FLTUND; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) { + si_code = TARGET_FPE_FLTRES; + } + force_sig_fault(TARGET_SIGFPE, si_code, env->pc); + break; + case EXCP_DEBUG: + case EXCP_BREAK: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); + break; + case EXCP_ATOMIC: + cpu_exec_step_atomic(cs); + break; + default: + EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", + trapnr); + exit(EXIT_FAILURE); + } + process_pending_signals(env); + } +} + +void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) +{ + int i; + + for (i = 0; i < 32; i++) { + env->gpr[i] = regs->regs[i]; + } + env->pc = regs->csr_era; + +} diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c new file mode 100644 index 0000000..f2839e0 --- /dev/null +++ b/linux-user/loongarch64/signal.c @@ -0,0 +1,162 @@ +/* + * 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 target_ucontext { + target_ulong tuc_flags; + target_ulong tuc_link; + target_stack_t tuc_stack; + target_ulong pad0; + struct target_sigcontext tuc_mcontext; + target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe { + struct target_siginfo rs_info; + struct target_ucontext rs_uc; +}; + +static inline void setup_sigcontext(CPULoongArchState *env, + struct target_sigcontext *sc) +{ + int i; + + __put_user(env->pc, &sc->sc_pc); + + __put_user(0, &sc->sc_gpr[0]); + for (i = 1; i < 32; ++i) { + __put_user(env->gpr[i], &sc->sc_gpr[i]); + } + + for (i = 0; i < 32; ++i) { + __put_user(env->fpr[i], &sc->sc_fpr[i]); + } +} + +static inline void +restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc) +{ + int i; + + __get_user(env->pc, &sc->sc_pc); + + for (i = 1; i < 32; ++i) { + __get_user(env->gpr[i], &sc->sc_gpr[i]); + } + + for (i = 0; i < 32; ++i) { + __get_user(env->fpr[i], &sc->sc_fpr[i]); + } +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPULoongArchState *env, + size_t frame_size) +{ + unsigned long sp; + + sp = target_sigsp(get_sp_from_cpustate(env) - 32, ka); + + return (sp - frame_size) & ~7; +} + +void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPULoongArchState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + int i; + + frame_addr = get_sigframe(ka, env, sizeof(*frame)); + trace_user_setup_rt_frame(env, frame_addr); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + goto give_sigsegv; + } + + tswap_siginfo(&frame->rs_info, info); + + __put_user(0, &frame->rs_uc.tuc_flags); + __put_user(0, &frame->rs_uc.tuc_link); + target_save_altstack(&frame->rs_uc.tuc_stack, env); + + setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); + + for (i = 0; i < TARGET_NSIG_WORDS; i++) { + __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); + } + + env->gpr[4] = sig; + env->gpr[5] = frame_addr + offsetof(struct target_rt_sigframe, rs_info); + env->gpr[6] = frame_addr + offsetof(struct target_rt_sigframe, rs_uc); + env->gpr[3] = frame_addr; + env->gpr[1] = default_rt_sigreturn; + + env->pc = env->gpr[20] = ka->_sa_handler; + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sigsegv(sig); +} + +long do_rt_sigreturn(CPULoongArchState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + sigset_t blocked; + + frame_addr = env->gpr[3]; + trace_user_do_rt_sigreturn(env, frame_addr); + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { + goto badframe; + } + + target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); + set_sigmask(&blocked); + + restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); + target_restore_altstack(&frame->rs_uc.tuc_stack, env); + + unlock_user_struct(frame, frame_addr, 0); + return -TARGET_QEMU_ESIGRETURN; + +badframe: + unlock_user_struct(frame, frame_addr, 0); + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; +} + +void setup_sigtramp(abi_ulong sigtramp_page) +{ + uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0); + assert(tramp != NULL); + + __put_user(0x03822c0b, tramp + 0); /* ori a7, a7, 0x8b */ + __put_user(0x002b0000, tramp + 1); /* syscall 0 */ + + default_rt_sigreturn = sigtramp_page; + unlock_user(tramp, sigtramp_page, 8); +} diff --git a/linux-user/loongarch64/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..8fbf287 --- /dev/null +++ b/linux-user/loongarch64/syscall_nr.h @@ -0,0 +1,312 @@ +/* + * This file contains the system call numbers. + * Do not modify. + * This file is generated by scripts/gensyscalls.sh + */ +#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H +#define LINUX_USER_LOONGARCH_SYSCALL_NR_H + +#define TARGET_NR_io_setup 0 +#define TARGET_NR_io_destroy 1 +#define TARGET_NR_io_submit 2 +#define TARGET_NR_io_cancel 3 +#define TARGET_NR_io_getevents 4 +#define TARGET_NR_setxattr 5 +#define TARGET_NR_lsetxattr 6 +#define TARGET_NR_fsetxattr 7 +#define TARGET_NR_getxattr 8 +#define TARGET_NR_lgetxattr 9 +#define TARGET_NR_fgetxattr 10 +#define TARGET_NR_listxattr 11 +#define TARGET_NR_llistxattr 12 +#define TARGET_NR_flistxattr 13 +#define TARGET_NR_removexattr 14 +#define TARGET_NR_lremovexattr 15 +#define TARGET_NR_fremovexattr 16 +#define TARGET_NR_getcwd 17 +#define TARGET_NR_lookup_dcookie 18 +#define TARGET_NR_eventfd2 19 +#define TARGET_NR_epoll_create1 20 +#define TARGET_NR_epoll_ctl 21 +#define TARGET_NR_epoll_pwait 22 +#define TARGET_NR_dup 23 +#define TARGET_NR_dup3 24 +#define TARGET_NR_fcntl 25 +#define TARGET_NR_inotify_init1 26 +#define TARGET_NR_inotify_add_watch 27 +#define TARGET_NR_inotify_rm_watch 28 +#define TARGET_NR_ioctl 29 +#define TARGET_NR_ioprio_set 30 +#define TARGET_NR_ioprio_get 31 +#define TARGET_NR_flock 32 +#define TARGET_NR_mknodat 33 +#define TARGET_NR_mkdirat 34 +#define TARGET_NR_unlinkat 35 +#define TARGET_NR_symlinkat 36 +#define TARGET_NR_linkat 37 +#define TARGET_NR_umount2 39 +#define TARGET_NR_mount 40 +#define TARGET_NR_pivot_root 41 +#define TARGET_NR_nfsservctl 42 +#define TARGET_NR_statfs 43 +#define TARGET_NR_fstatfs 44 +#define TARGET_NR_truncate 45 +#define TARGET_NR_ftruncate 46 +#define TARGET_NR_fallocate 47 +#define TARGET_NR_faccessat 48 +#define TARGET_NR_chdir 49 +#define TARGET_NR_fchdir 50 +#define TARGET_NR_chroot 51 +#define TARGET_NR_fchmod 52 +#define TARGET_NR_fchmodat 53 +#define TARGET_NR_fchownat 54 +#define TARGET_NR_fchown 55 +#define TARGET_NR_openat 56 +#define TARGET_NR_close 57 +#define TARGET_NR_vhangup 58 +#define TARGET_NR_pipe2 59 +#define TARGET_NR_quotactl 60 +#define TARGET_NR_getdents64 61 +#define TARGET_NR_lseek 62 +#define TARGET_NR_read 63 +#define TARGET_NR_write 64 +#define TARGET_NR_readv 65 +#define TARGET_NR_writev 66 +#define TARGET_NR_pread64 67 +#define TARGET_NR_pwrite64 68 +#define TARGET_NR_preadv 69 +#define TARGET_NR_pwritev 70 +#define TARGET_NR_sendfile 71 +#define TARGET_NR_pselect6 72 +#define TARGET_NR_ppoll 73 +#define TARGET_NR_signalfd4 74 +#define TARGET_NR_vmsplice 75 +#define TARGET_NR_splice 76 +#define TARGET_NR_tee 77 +#define TARGET_NR_readlinkat 78 +#define TARGET_NR_newfstatat 79 +#define TARGET_NR_fstat 80 +#define TARGET_NR_sync 81 +#define TARGET_NR_fsync 82 +#define TARGET_NR_fdatasync 83 +#define TARGET_NR_sync_file_range 84 +#define TARGET_NR_timerfd_create 85 +#define TARGET_NR_timerfd_settime 86 +#define TARGET_NR_timerfd_gettime 87 +#define TARGET_NR_utimensat 88 +#define TARGET_NR_acct 89 +#define TARGET_NR_capget 90 +#define TARGET_NR_capset 91 +#define TARGET_NR_personality 92 +#define TARGET_NR_exit 93 +#define TARGET_NR_exit_group 94 +#define TARGET_NR_waitid 95 +#define TARGET_NR_set_tid_address 96 +#define TARGET_NR_unshare 97 +#define TARGET_NR_futex 98 +#define TARGET_NR_set_robust_list 99 +#define TARGET_NR_get_robust_list 100 +#define TARGET_NR_nanosleep 101 +#define TARGET_NR_getitimer 102 +#define TARGET_NR_setitimer 103 +#define TARGET_NR_kexec_load 104 +#define TARGET_NR_init_module 105 +#define TARGET_NR_delete_module 106 +#define TARGET_NR_timer_create 107 +#define TARGET_NR_timer_gettime 108 +#define TARGET_NR_timer_getoverrun 109 +#define TARGET_NR_timer_settime 110 +#define TARGET_NR_timer_delete 111 +#define TARGET_NR_clock_settime 112 +#define TARGET_NR_clock_gettime 113 +#define TARGET_NR_clock_getres 114 +#define TARGET_NR_clock_nanosleep 115 +#define TARGET_NR_syslog 116 +#define TARGET_NR_ptrace 117 +#define TARGET_NR_sched_setparam 118 +#define TARGET_NR_sched_setscheduler 119 +#define TARGET_NR_sched_getscheduler 120 +#define TARGET_NR_sched_getparam 121 +#define TARGET_NR_sched_setaffinity 122 +#define TARGET_NR_sched_getaffinity 123 +#define TARGET_NR_sched_yield 124 +#define TARGET_NR_sched_get_priority_max 125 +#define TARGET_NR_sched_get_priority_min 126 +#define TARGET_NR_sched_rr_get_interval 127 +#define TARGET_NR_restart_syscall 128 +#define TARGET_NR_kill 129 +#define TARGET_NR_tkill 130 +#define TARGET_NR_tgkill 131 +#define TARGET_NR_sigaltstack 132 +#define TARGET_NR_rt_sigsuspend 133 +#define TARGET_NR_rt_sigaction 134 +#define TARGET_NR_rt_sigprocmask 135 +#define TARGET_NR_rt_sigpending 136 +#define TARGET_NR_rt_sigtimedwait 137 +#define TARGET_NR_rt_sigqueueinfo 138 +#define TARGET_NR_rt_sigreturn 139 +#define TARGET_NR_setpriority 140 +#define TARGET_NR_getpriority 141 +#define TARGET_NR_reboot 142 +#define TARGET_NR_setregid 143 +#define TARGET_NR_setgid 144 +#define TARGET_NR_setreuid 145 +#define TARGET_NR_setuid 146 +#define TARGET_NR_setresuid 147 +#define TARGET_NR_getresuid 148 +#define TARGET_NR_setresgid 149 +#define TARGET_NR_getresgid 150 +#define TARGET_NR_setfsuid 151 +#define TARGET_NR_setfsgid 152 +#define TARGET_NR_times 153 +#define TARGET_NR_setpgid 154 +#define TARGET_NR_getpgid 155 +#define TARGET_NR_getsid 156 +#define TARGET_NR_setsid 157 +#define TARGET_NR_getgroups 158 +#define TARGET_NR_setgroups 159 +#define TARGET_NR_uname 160 +#define TARGET_NR_sethostname 161 +#define TARGET_NR_setdomainname 162 +#define TARGET_NR_getrusage 165 +#define TARGET_NR_umask 166 +#define TARGET_NR_prctl 167 +#define TARGET_NR_getcpu 168 +#define TARGET_NR_gettimeofday 169 +#define TARGET_NR_settimeofday 170 +#define TARGET_NR_adjtimex 171 +#define TARGET_NR_getpid 172 +#define TARGET_NR_getppid 173 +#define TARGET_NR_getuid 174 +#define TARGET_NR_geteuid 175 +#define TARGET_NR_getgid 176 +#define TARGET_NR_getegid 177 +#define TARGET_NR_gettid 178 +#define TARGET_NR_sysinfo 179 +#define TARGET_NR_mq_open 180 +#define TARGET_NR_mq_unlink 181 +#define TARGET_NR_mq_timedsend 182 +#define TARGET_NR_mq_timedreceive 183 +#define TARGET_NR_mq_notify 184 +#define TARGET_NR_mq_getsetattr 185 +#define TARGET_NR_msgget 186 +#define TARGET_NR_msgctl 187 +#define TARGET_NR_msgrcv 188 +#define TARGET_NR_msgsnd 189 +#define TARGET_NR_semget 190 +#define TARGET_NR_semctl 191 +#define TARGET_NR_semtimedop 192 +#define TARGET_NR_semop 193 +#define TARGET_NR_shmget 194 +#define TARGET_NR_shmctl 195 +#define TARGET_NR_shmat 196 +#define TARGET_NR_shmdt 197 +#define TARGET_NR_socket 198 +#define TARGET_NR_socketpair 199 +#define TARGET_NR_bind 200 +#define TARGET_NR_listen 201 +#define TARGET_NR_accept 202 +#define TARGET_NR_connect 203 +#define TARGET_NR_getsockname 204 +#define TARGET_NR_getpeername 205 +#define TARGET_NR_sendto 206 +#define TARGET_NR_recvfrom 207 +#define TARGET_NR_setsockopt 208 +#define TARGET_NR_getsockopt 209 +#define TARGET_NR_shutdown 210 +#define TARGET_NR_sendmsg 211 +#define TARGET_NR_recvmsg 212 +#define TARGET_NR_readahead 213 +#define TARGET_NR_brk 214 +#define TARGET_NR_munmap 215 +#define TARGET_NR_mremap 216 +#define TARGET_NR_add_key 217 +#define TARGET_NR_request_key 218 +#define TARGET_NR_keyctl 219 +#define TARGET_NR_clone 220 +#define TARGET_NR_execve 221 +#define TARGET_NR_mmap 222 +#define TARGET_NR_fadvise64 223 +#define TARGET_NR_swapon 224 +#define TARGET_NR_swapoff 225 +#define TARGET_NR_mprotect 226 +#define TARGET_NR_msync 227 +#define TARGET_NR_mlock 228 +#define TARGET_NR_munlock 229 +#define TARGET_NR_mlockall 230 +#define TARGET_NR_munlockall 231 +#define TARGET_NR_mincore 232 +#define TARGET_NR_madvise 233 +#define TARGET_NR_remap_file_pages 234 +#define TARGET_NR_mbind 235 +#define TARGET_NR_get_mempolicy 236 +#define TARGET_NR_set_mempolicy 237 +#define TARGET_NR_migrate_pages 238 +#define TARGET_NR_move_pages 239 +#define TARGET_NR_rt_tgsigqueueinfo 240 +#define TARGET_NR_perf_event_open 241 +#define TARGET_NR_accept4 242 +#define TARGET_NR_recvmmsg 243 +#define TARGET_NR_arch_specific_syscall 244 +#define TARGET_NR_wait4 260 +#define TARGET_NR_prlimit64 261 +#define TARGET_NR_fanotify_init 262 +#define TARGET_NR_fanotify_mark 263 +#define TARGET_NR_name_to_handle_at 264 +#define TARGET_NR_open_by_handle_at 265 +#define TARGET_NR_clock_adjtime 266 +#define TARGET_NR_syncfs 267 +#define TARGET_NR_setns 268 +#define TARGET_NR_sendmmsg 269 +#define TARGET_NR_process_vm_readv 270 +#define TARGET_NR_process_vm_writev 271 +#define TARGET_NR_kcmp 272 +#define TARGET_NR_finit_module 273 +#define TARGET_NR_sched_setattr 274 +#define TARGET_NR_sched_getattr 275 +#define TARGET_NR_renameat2 276 +#define TARGET_NR_seccomp 277 +#define TARGET_NR_getrandom 278 +#define TARGET_NR_memfd_create 279 +#define TARGET_NR_bpf 280 +#define TARGET_NR_execveat 281 +#define TARGET_NR_userfaultfd 282 +#define TARGET_NR_membarrier 283 +#define TARGET_NR_mlock2 284 +#define TARGET_NR_copy_file_range 285 +#define TARGET_NR_preadv2 286 +#define TARGET_NR_pwritev2 287 +#define TARGET_NR_pkey_mprotect 288 +#define TARGET_NR_pkey_alloc 289 +#define TARGET_NR_pkey_free 290 +#define TARGET_NR_statx 291 +#define TARGET_NR_io_pgetevents 292 +#define TARGET_NR_rseq 293 +#define TARGET_NR_kexec_file_load 294 +#define TARGET_NR_pidfd_send_signal 424 +#define TARGET_NR_io_uring_setup 425 +#define TARGET_NR_io_uring_enter 426 +#define TARGET_NR_io_uring_register 427 +#define TARGET_NR_open_tree 428 +#define TARGET_NR_move_mount 429 +#define TARGET_NR_fsopen 430 +#define TARGET_NR_fsconfig 431 +#define TARGET_NR_fsmount 432 +#define TARGET_NR_fspick 433 +#define TARGET_NR_pidfd_open 434 +#define TARGET_NR_clone3 435 +#define TARGET_NR_close_range 436 +#define TARGET_NR_openat2 437 +#define TARGET_NR_pidfd_getfd 438 +#define TARGET_NR_faccessat2 439 +#define TARGET_NR_process_madvise 440 +#define TARGET_NR_epoll_pwait2 441 +#define TARGET_NR_mount_setattr 442 +#define TARGET_NR_quotactl_fd 443 +#define TARGET_NR_landlock_create_ruleset 444 +#define TARGET_NR_landlock_add_rule 445 +#define TARGET_NR_landlock_restrict_self 446 +#define TARGET_NR_process_mrelease 448 +#define TARGET_NR_syscalls 449 + +#endif /* LINUX_USER_LOONGARCH_SYSCALL_NR_H */ diff --git a/linux-user/loongarch64/target_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..2deb88c --- /dev/null +++ b/linux-user/loongarch64/target_signal.h @@ -0,0 +1,30 @@ +/* + * 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" + +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 + +#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..393160d --- /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 "loongarch64" +#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..b1d4f4f --- /dev/null +++ b/linux-user/loongarch64/termbits.h @@ -0,0 +1 @@ +#include "../generic/termbits.h" 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; From patchwork Tue Sep 14 13:00:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493173 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 97E20C433EF for ; Tue, 14 Sep 2021 13:13:43 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 38280610CE for ; Tue, 14 Sep 2021 13:13:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 38280610CE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:54286 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8Fq-00040L-EE for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:13:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37716) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ849-0006AV-B2 for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:37 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57960 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ847-00085r-6F for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:36 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S20; Tue, 14 Sep 2021 21:01:21 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 18/21] default-configs: Add loongarch linux-user support Date: Tue, 14 Sep 2021 21:00:28 +0800 Message-Id: <1631624431-30658-19-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S20 X-Coremail-Antispam: 1UD129KBjvdXoWrZry3XryrKw15JrWDuryxGrg_yoW3Arg_uF yfJr4vgFWUZryUCw10v3yrAr4ru3W8AF1ruF4DKw4xXwsFqr43t34vva1rAa4ay393urnx ZrWkArn5Cr10qjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUUUUUUU X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add loongarch64 linux-user default configs file. Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- 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 From patchwork Tue Sep 14 13:00:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493233 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0505DC4332F for ; Tue, 14 Sep 2021 13:16:54 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A066860724 for ; Tue, 14 Sep 2021 13:16:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org A066860724 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:34904 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8Iu-0001sA-Qi for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:16:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37758) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ84A-0006Es-TL for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:42 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57972 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ848-000867-7U for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:38 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S21; Tue, 14 Sep 2021 21:01:22 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 19/21] target/loongarch: Add target build suport Date: Tue, 14 Sep 2021 21:00:29 +0800 Message-Id: <1631624431-30658-20-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S21 X-Coremail-Antispam: 1UD129KBjvJXoW7Zw4xXr4fZw1rury5trWkJFb_yoW8ZFyDpr 47Aw15KFW8ZF93J3s3Ja4FqFZ5Jw1DGw47XanxKrWfCrZxJayUXwn5KFZ8GF17X3W0kFyS gFn3C34rGF4UJa7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: 0 X-Spam_score: -0.0 X-Spam_bar: / X-Spam_report: (-0.0 / 5.0 requ) SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch add build loongarch-linux-user target support. Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- meson.build | 2 +- target/loongarch/meson.build | 18 ++++++++++++++++++ target/meson.build | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 target/loongarch/meson.build diff --git a/meson.build b/meson.build index 45bd486..5c80fed 100644 --- a/meson.build +++ b/meson.build @@ -57,7 +57,7 @@ python = import('python').find_installation() supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64', - 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] + 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64', 'loongarch64'] cpu = host_machine.cpu_family() targetos = host_machine.system() 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') From patchwork Tue Sep 14 13:00:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493409 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1ECA8C433EF for ; Tue, 14 Sep 2021 13:26:40 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ADDA160184 for ; Tue, 14 Sep 2021 13:26:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org ADDA160184 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:35870 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8SM-0004o1-TG for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:26:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39778) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ8AB-0000ma-Fu for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:07:51 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59622 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8A8-0003IP-JS for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:07:51 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S22; Tue, 14 Sep 2021 21:01:22 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 20/21] target/loongarch: 'make check-tcg' support Date: Tue, 14 Sep 2021 21:00:30 +0800 Message-Id: <1631624431-30658-21-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S22 X-Coremail-Antispam: 1UD129KBjvdXoWrZry3XryrKw4DWryxJrWUArb_yoWfWrg_A3 WSkr1kCF4Yyr1xGF18WFn5Gr4Fg3y7Zw1SgF1DXF1fX3y2van8ta1xAanxWF15Zw13urnI qaykAw4Ikw1UAjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUUUUUUU X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch support 'make check-tcg' after install cross-tools. Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- 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"} From patchwork Tue Sep 14 13:00:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12493227 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 134FDC433EF for ; Tue, 14 Sep 2021 13:14:04 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D0E90610A6 for ; Tue, 14 Sep 2021 13:14:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org D0E90610A6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:56130 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ8GB-0005G6-1D for qemu-devel@archiver.kernel.org; Tue, 14 Sep 2021 09:14:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37754) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQ84A-0006Eq-RA for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:42 -0400 Received: from mail.loongson.cn ([114.242.206.163]:57998 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQ848-00087J-7T for qemu-devel@nongnu.org; Tue, 14 Sep 2021 09:01:38 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxheXvnEBhNJ0GAA--.21668S23; Tue, 14 Sep 2021 21:01:23 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v5 21/21] scripts: add loongarch64 binfmt config Date: Tue, 14 Sep 2021 21:00:31 +0800 Message-Id: <1631624431-30658-22-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> References: <1631624431-30658-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9DxheXvnEBhNJ0GAA--.21668S23 X-Coremail-Antispam: 1UD129KBjvJXoW7Zw4xXr4kArWDGFyfXF17trb_yoW8WF4Dpr 15A3W8CF4jg3WUA3WkXw13Gr1DGrn0kas7Xr43tr1UAF15tw1rZr1fJr18J3WDJF48JF1j 9F95Ja1DJF4IkF7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5jdr20tqj6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=gaosong@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, gaosong@loongson.cn, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, pbonzini@redhat.com, bmeng.cn@gmail.com, alex.bennee@linaro.org, chenhuacai@loongson.cn Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Song Gao Signed-off-by: XiaoJuan Yang Reviewed-by: Richard Henderson --- 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