From patchwork Fri Aug 27 07:14:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461413 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 217EBC432BE for ; Fri, 27 Aug 2021 07:42: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 BBE4D60F42 for ; Fri, 27 Aug 2021 07:42:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org BBE4D60F42 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]:60114 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWVi-0001K3-Rc for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:42:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53088) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW4z-0000gG-35 for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:09 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59308 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW4v-00033s-IV for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:08 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S3; Fri, 27 Aug 2021 15:14:56 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 01/19] target/loongarch: Add README Date: Fri, 27 Aug 2021 15:14:36 +0800 Message-Id: <1630048494-2143-2-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S3 X-Coremail-Antispam: 1UD129KBjvdXoW7GryUWF1rWw4ktF1fZFy7ZFb_yoWkGrc_GF WfZFWkGr48W3WUt39Ygr98Jw15GF48GF1Sk3Z3Xr4xCa4Ut3y7J3yqy3ZrZF1ayrZ7Wrsx Xay7Jr1DCr1a9jkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-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: 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- MAINTAINERS | 5 +++++ target/loongarch/README | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 target/loongarch/README diff --git a/MAINTAINERS b/MAINTAINERS index dffcb65..396f970 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..fe7a36f --- /dev/null +++ b/target/loongarch/README @@ -0,0 +1,5 @@ +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/LoongArch-Vol1-v3/LoongArch-Vol1-v1.00-EN.pdf From patchwork Fri Aug 27 07:14:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461383 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 3AE29C432BE for ; Fri, 27 Aug 2021 07:27:28 +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 C0F6260F92 for ; Fri, 27 Aug 2021 07:27:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C0F6260F92 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]:60620 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWGt-0007aD-0e for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:27:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53126) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW52-0000i6-2Y for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:19 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59350 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW4w-00037s-4h for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:10 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S4; Fri, 27 Aug 2021 15:14:58 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 02/19] target/loongarch: Add core definition Date: Fri, 27 Aug 2021 15:14:37 +0800 Message-Id: <1630048494-2143-3-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S4 X-Coremail-Antispam: 1UD129KBjvAXoWfXr17Cr4Dtry7JrWUuFWruFg_yoW8Jw48to W5ZFy3Xw48Gr4SvasY9rnIqay2qFy8CFW5Aa4xZw4Uu3W8try5Gr98Kw1FvFy2qrZ5GrW7 CasagFnxJ347Jrn3n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/cpu-param.h | 19 +++ target/loongarch/cpu.c | 285 +++++++++++++++++++++++++++++++++++++++++++ target/loongarch/cpu.h | 145 ++++++++++++++++++++++ target/loongarch/internals.h | 23 ++++ 4 files changed, 472 insertions(+) create mode 100644 target/loongarch/cpu-param.h create mode 100644 target/loongarch/cpu.c create mode 100644 target/loongarch/cpu.h create mode 100644 target/loongarch/internals.h diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h new file mode 100644 index 0000000..83f9624 --- /dev/null +++ b/target/loongarch/cpu-param.h @@ -0,0 +1,19 @@ +/* + * LoongArch cpu parameters for qemu. + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_CPU_PARAM_H +#define LOONGARCH_CPU_PARAM_H 1 + +#define TARGET_LONG_BITS 64 +#define TARGET_PHYS_ADDR_SPACE_BITS 48 +#define TARGET_VIRT_ADDR_SPACE_BITS 48 + +#define TARGET_PAGE_BITS 14 +#define NB_MMU_MODES 4 + +#endif diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c new file mode 100644 index 0000000..b89bf51 --- /dev/null +++ b/target/loongarch/cpu.c @@ -0,0 +1,285 @@ +/* + * QEMU LoongArch CPU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu/qemu-print.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "sysemu/qtest.h" +#include "exec/exec-all.h" +#include "qapi/qapi-commands-machine-target.h" +#include "cpu.h" +#include "internals.h" +#include "fpu/softfloat-helpers.h" + +const char * const regnames[] = { + "r0", "ra", "tp", "sp", "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", + "t4", "t5", "t6", "t7", "t8", "x0", "fp", "s0", + "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", +}; + +const char * const fregnames[] = { + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", +}; + +static const char * const excp_names[EXCP_LAST + 1] = { + [EXCP_ADE] = "Address error", + [EXCP_SYSCALL] = "Syscall", + [EXCP_BREAK] = "Break", + [EXCP_INE] = "Inst. Not Exist", + [EXCP_FPE] = "Floating Point Exception", +}; + +const char *loongarch_exception_name(int32_t exception) +{ + if (exception < 0 || exception > EXCP_LAST) { + return "unknown"; + } + return excp_names[exception]; +} + +void QEMU_NORETURN do_raise_exception(CPULoongArchState *env, + uint32_t exception, + uintptr_t pc) +{ + CPUState *cs = env_cpu(env); + + qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n", + __func__, + exception, + loongarch_exception_name(exception)); + cs->exception_index = exception; + + cpu_loop_exit_restore(cs, pc); +} + +static void loongarch_cpu_set_pc(CPUState *cs, vaddr value) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + + env->pc = value; +} + +#ifdef CONFIG_TCG +static void loongarch_cpu_synchronize_from_tb(CPUState *cs, + const TranslationBlock *tb) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + + env->pc = tb->pc; +} +#endif /* CONFIG_TCG */ + +static bool loongarch_cpu_has_work(CPUState *cs) +{ + return true; +} + +static void set_loongarch_cpucfg(CPULoongArchState *env) +{ + int i; + + for (i = 0; i < 15; i++) { + env->cpucfg[i] = 0x0; + } + env->cpucfg[0] = 0x14c010; + env->cpucfg[1] = 0x3f2f2fe; + env->cpucfg[2] = 0x60c3cf; + env->cpucfg[3] = 0xcff; + env->cpucfg[4] = 0x5f5e100; + env->cpucfg[5] = 0x10001; + env->cpucfg[10] = 0x2c3d; + env->cpucfg[11] = 0x6080003; + env->cpucfg[12] = 0x6080003; + env->cpucfg[13] = 0x60800f; + env->cpucfg[14] = 0x60f000f; +} + +/* LoongArch CPU definitions */ +static void loongarch_3a5000_initfn(Object *obj) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(obj); + CPULoongArchState *env = &cpu->env; + + set_loongarch_cpucfg(env); +} + +static void loongarch_cpu_list_entry(gpointer data, gpointer user_data) +{ + const char *typename = object_class_get_name(OBJECT_CLASS(data)); + + qemu_printf("%s\n", typename); +} + +void loongarch_cpu_list(void) +{ + GSList *list; + list = object_class_get_list_sorted(TYPE_LOONGARCH_CPU, false); + g_slist_foreach(list, loongarch_cpu_list_entry, NULL); + g_slist_free(list); +} + +static void loongarch_cpu_reset(DeviceState *dev) +{ + CPUState *cs = CPU(dev); + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(cpu); + CPULoongArchState *env = &cpu->env; + + lacc->parent_reset(dev); + + set_loongarch_cpucfg(env); + env->fcsr0_mask = 0x1f1f031f; + env->fcsr0 = 0x0; + + cs->exception_index = EXCP_NONE; +} + +static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info) +{ + info->print_insn = print_insn_loongarch; +} + +static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) +{ + CPUState *cs = CPU(dev); + LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev); + Error *local_err = NULL; + + cpu_exec_realizefn(cs, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + + cpu_reset(cs); + qemu_init_vcpu(cs); + + lacc->parent_realize(dev, errp); +} + +static void loongarch_cpu_initfn(Object *obj) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(obj); + + cpu_set_cpustate_pointers(cpu); +} + +static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + char *typename; + + typename = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model); + oc = object_class_by_name(typename); + g_free(typename); + return oc; +} + +void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + int i; + + qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc); + qemu_fprintf(f, " FCSR0 0x%08x fp_status 0x%02x\n", env->fcsr0, + get_float_exception_flags(&env->fp_status)); + + /* gpr */ + for (i = 0; i < 32; i++) { + if ((i & 3) == 0) { + qemu_fprintf(f, " GPR%02d:", i); + } + qemu_fprintf(f, " %s %016" PRIx64, regnames[i], env->gpr[i]); + if ((i & 3) == 3) { + qemu_fprintf(f, "\n"); + } + } + + /* fpr */ + if (flags & CPU_DUMP_FPU) { + for (i = 0; i < 32; i++) { + qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i]); + if ((i & 3) == 3) { + qemu_fprintf(f, "\n"); + } + } + } +} + +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" + +static bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + + env->badaddr = address; + cs->exception_index = EXCP_ADE; + do_raise_exception(env, cs->exception_index, retaddr); +} + +static struct TCGCPUOps loongarch_tcg_ops = { + .initialize = loongarch_translate_init, + .synchronize_from_tb = loongarch_cpu_synchronize_from_tb, + .tlb_fill = loongarch_cpu_tlb_fill, +}; +#endif /* CONFIG_TCG */ + +static void loongarch_cpu_class_init(ObjectClass *c, void *data) +{ + LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c); + CPUClass *cc = CPU_CLASS(c); + DeviceClass *dc = DEVICE_CLASS(c); + + device_class_set_parent_realize(dc, loongarch_cpu_realizefn, + &lacc->parent_realize); + device_class_set_parent_reset(dc, loongarch_cpu_reset, &lacc->parent_reset); + + cc->class_by_name = loongarch_cpu_class_by_name; + cc->has_work = loongarch_cpu_has_work; + cc->dump_state = loongarch_cpu_dump_state; + cc->set_pc = loongarch_cpu_set_pc; + cc->disas_set_info = loongarch_cpu_disas_set_info; +#ifdef CONFIG_TCG + cc->tcg_ops = &loongarch_tcg_ops; +#endif +} + +#define DEFINE_LOONGARCH_CPU_TYPE(model, initfn) \ + { \ + .parent = TYPE_LOONGARCH_CPU, \ + .instance_init = initfn, \ + .name = LOONGARCH_CPU_TYPE_NAME(model), \ + } + +static const TypeInfo loongarch_cpu_type_infos[] = { + { + .name = TYPE_LOONGARCH_CPU, + .parent = TYPE_CPU, + .instance_size = sizeof(LoongArchCPU), + .instance_init = loongarch_cpu_initfn, + + .abstract = true, + .class_size = sizeof(LoongArchCPUClass), + .class_init = loongarch_cpu_class_init, + }, + DEFINE_LOONGARCH_CPU_TYPE("Loongson-3A5000", loongarch_3a5000_initfn), +}; + +DEFINE_TYPES(loongarch_cpu_type_infos) diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h new file mode 100644 index 0000000..a0348d0 --- /dev/null +++ b/target/loongarch/cpu.h @@ -0,0 +1,145 @@ +/* + * QEMU LoongArch CPU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_CPU_H +#define LOONGARCH_CPU_H + +#include "exec/cpu-defs.h" +#include "fpu/softfloat-types.h" + +#define TCG_GUEST_DEFAULT_MO (0) + +#define FCSR0_M1 0x1f /* FCSR1 mask, Enables */ +#define FCSR0_M2 0x1f1f0000 /* FCSR2 mask, Cause and Flags */ +#define FCSR0_M3 0x300 /* FCSR3 mask, Round Mode */ +#define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */ +#define GET_FP_CAUSE(reg) (((reg) >> 24) & 0x1f) +#define GET_FP_ENABLE(reg) (reg & 0x1f) +#define GET_FP_FLAGS(reg) (((reg) >> 16) & 0x1f) +#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x1f << 24)) | \ + ((v & 0x1f) << 24); \ + } while (0) +#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f) | (v & 0x1f); \ + } while (0) +#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 16)) | \ + ((v & 0x1f) << 16); \ + } while (0) +#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 16); } while (0) + +#define FP_INEXACT 1 +#define FP_UNDERFLOW 2 +#define FP_OVERFLOW 4 +#define FP_DIV0 8 +#define FP_INVALID 16 + +extern const char * const regnames[]; +extern const char * const fregnames[]; + +typedef struct CPULoongArchState CPULoongArchState; +struct CPULoongArchState { + uint64_t gpr[32]; + uint64_t pc; + + uint64_t fpr[32]; + float_status fp_status; + bool cf[8]; + + /* + * fcsr0 + * 31:29 |28:24 |23:21 |20:16 |15:10 |9:8 |7:5 |4:0 + * Cause Flags RM Enables + */ + uint32_t fcsr0; + uint32_t fcsr0_mask; + + uint32_t cpucfg[15]; + + uint64_t lladdr; /* LL virtual address compared against SC */ + uint64_t llval; + + uint64_t badaddr; +}; + +/** + * LoongArchCPU: + * @env: #CPULoongArchState + * @clock: this CPU input clock (may be connected + * to an output clock from another device). + * + * A LoongArch CPU. + */ +struct LoongArchCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPUNegativeOffsetState neg; + CPULoongArchState env; +}; + +#define TYPE_LOONGARCH_CPU "loongarch64-cpu" + +OBJECT_DECLARE_TYPE(LoongArchCPU, LoongArchCPUClass, + LOONGARCH_CPU) + +/** + * LoongArchCPUClass: + * @parent_realize: The parent class' realize handler. + * @parent_reset: The parent class' reset handler. + * + * A LoongArch CPU model. + */ +struct LoongArchCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + + DeviceRealize parent_realize; + DeviceReset parent_reset; +}; + +static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, + target_ulong *pc, + target_ulong *cs_base, + uint32_t *flags) +{ + *pc = env->pc; + *cs_base = 0; +} + +void loongarch_cpu_list(void); + +#define cpu_signal_handler cpu_loongarch_signal_handler +#define cpu_list loongarch_cpu_list + +#define MMU_USER_IDX 3 + +typedef CPULoongArchState CPUArchState; +typedef LoongArchCPU ArchCPU; + +#include "exec/cpu-all.h" + +/* Exceptions */ +enum { + EXCP_NONE = -1, + EXCP_ADE = 0, + EXCP_SYSCALL, + EXCP_BREAK, + EXCP_INE, + EXCP_FPE, + + EXCP_LAST = EXCP_FPE, +}; + +int cpu_loongarch_signal_handler(int host_signum, void *pinfo, void *puc); + +#define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU +#define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX +#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU + +#endif /* LOONGARCH_CPU_H */ diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h new file mode 100644 index 0000000..cfb08df --- /dev/null +++ b/target/loongarch/internals.h @@ -0,0 +1,23 @@ +/* + * QEMU LoongArch CPU -- internal functions and types + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_INTERNALS_H +#define LOONGARCH_INTERNALS_H + + +void loongarch_translate_init(void); + +void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); + +void QEMU_NORETURN do_raise_exception(CPULoongArchState *env, + uint32_t exception, + uintptr_t pc); + +const char *loongarch_exception_name(int32_t exception); + +#endif From patchwork Fri Aug 27 07:14:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461421 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=-14.0 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 4A266C432BE for ; Fri, 27 Aug 2021 07:45:46 +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 CA9D160F92 for ; Fri, 27 Aug 2021 07:45:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org CA9D160F92 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]:37950 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWYa-0005N6-Sq for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:45:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53156) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW59-0000iW-EH for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:19 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59406 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW4w-00039N-A9 for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:17 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S5; Fri, 27 Aug 2021 15:15:01 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 03/19] target/loongarch: Add main translation routines Date: Fri, 27 Aug 2021 15:14:38 +0800 Message-Id: <1630048494-2143-4-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S5 X-Coremail-Antispam: 1UD129KBjvJXoWxtrykZr1UZF13XrykuFWUXFb_yoW3Wr1fpF 17Cr13Kr4kJa4fZ3Z3G3yYqr15Aa1xGry2q3s2k395Cr42grykZryktrZrKFW8C3y8WFyj vFsxA3Wj9F48XaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/helper.h | 9 +++ target/loongarch/op_helper.c | 22 ++++++ target/loongarch/translate.c | 171 +++++++++++++++++++++++++++++++++++++++++++ target/loongarch/translate.h | 27 +++++++ 4 files changed, 229 insertions(+) create mode 100644 target/loongarch/helper.h create mode 100644 target/loongarch/op_helper.c create mode 100644 target/loongarch/translate.c create mode 100644 target/loongarch/translate.h diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h new file mode 100644 index 0000000..09bfcfd --- /dev/null +++ b/target/loongarch/helper.h @@ -0,0 +1,9 @@ +/* + * QEMU LoongArch CPU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +DEF_HELPER_2(raise_exception, noreturn, env, i32) diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c new file mode 100644 index 0000000..4d10b03 --- /dev/null +++ b/target/loongarch/op_helper.c @@ -0,0 +1,22 @@ +/* + * LoongArch emulation helpers for qemu. + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "cpu.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "internals.h" + +/* Exceptions helpers */ +void helper_raise_exception(CPULoongArchState *env, uint32_t exception) +{ + do_raise_exception(env, exception, GETPC()); +} diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c new file mode 100644 index 0000000..bdbd7a9 --- /dev/null +++ b/target/loongarch/translate.c @@ -0,0 +1,171 @@ +/* + * 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 "fpu_helper.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 +#define DISAS_EXIT DISAS_TARGET_1 + +void generate_exception(DisasContext *ctx, int excp) +{ + tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); + gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); + ctx->base.is_jmp = DISAS_NORETURN; +} + +static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) +{ + return true; +} + +static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) +{ + if (translator_use_goto_tb(&ctx->base, dest)) { + tcg_gen_goto_tb(n); + tcg_gen_movi_tl(cpu_pc, dest); + tcg_gen_exit_tb(ctx->base.tb, n); + } else { + tcg_gen_movi_tl(cpu_pc, dest); + tcg_gen_lookup_and_goto_ptr(); + } +} + +static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, + CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + int64_t bound; + + ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK; + ctx->mem_idx = MMU_USER_IDX ; + + /* Bound the number of insns to execute to those left on the page. */ + bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; + ctx->base.max_insns = MIN(ctx->base.max_insns, bound); +} + +static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) +{ +} + +static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + tcg_gen_insn_start(ctx->base.pc_next); +} + +static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ + CPULoongArchState *env = cs->env_ptr; + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); + + if (!decode(ctx, ctx->opcode)) { + qemu_log_mask(LOG_UNIMP, "Error: unkown opcode. 0x%lx: 0x%x\n", + ctx->base.pc_next, ctx->opcode); + generate_exception(ctx, EXCP_INE); + } + + ctx->base.pc_next += 4; +} + +static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + switch (ctx->base.is_jmp) { + case DISAS_STOP: + tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); + tcg_gen_lookup_and_goto_ptr(); + break; + case DISAS_NEXT: + case DISAS_TOO_MANY: + gen_goto_tb(ctx, 0, ctx->base.pc_next); + break; + case DISAS_EXIT: + tcg_gen_exit_tb(NULL, 0); + 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 Fri Aug 27 07:14:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461391 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 86D39C432BE for ; Fri, 27 Aug 2021 07:29:35 +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 142BD60F92 for ; Fri, 27 Aug 2021 07:29:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 142BD60F92 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]:36532 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWIw-0001z7-2a for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:29:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53176) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5A-0000ld-PV for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:20 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59432 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW4w-00039R-AF for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:20 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S6; Fri, 27 Aug 2021 15:15:03 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 04/19] target/loongarch: Add fixed point arithmetic instruction translation Date: Fri, 27 Aug 2021 15:14:39 +0800 Message-Id: <1630048494-2143-5-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S6 X-Coremail-Antispam: 1UD129KBjvAXoWfXFyDtrWkZFW3XF4rZw4Utwb_yoW8Zw18Ko W7GF45Ar48GryYvr1ag3W8XFWxXr1j9anxA395u3WDWF4xCr13tr12krn5ZayrJa1DKFyr GF1SgF9xJ3yfXr1kn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/insn_trans/trans_arith.c | 334 ++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 89 ++++++++ target/loongarch/internals.h | 1 - target/loongarch/translate.c | 100 ++++++++- target/loongarch/translate.h | 20 ++ 5 files changed, 538 insertions(+), 6 deletions(-) create mode 100644 target/loongarch/insn_trans/trans_arith.c create mode 100644 target/loongarch/insns.decode diff --git a/target/loongarch/insn_trans/trans_arith.c b/target/loongarch/insn_trans/trans_arith.c new file mode 100644 index 0000000..5f23bcd --- /dev/null +++ b/target/loongarch/insn_trans/trans_arith.c @@ -0,0 +1,334 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_r2_si12(DisasContext *ctx, arg_fmt_rdrjsi12 *a, + DisasExtend src_ext, DisasExtend dst_ext, + void (*func)(TCGv, TCGv, TCGv)) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, src_ext); + TCGv src2 = tcg_constant_tl(a->si12); + + func(dest, src1, src2); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +static bool gen_r3_sa2(DisasContext *ctx, arg_fmt_rdrjrksa2 *a, + DisasExtend src_ext, DisasExtend dst_ext, + void (*func)(TCGv, TCGv, TCGv, TCGv, target_long)) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, src_ext); + TCGv src2 = gpr_src(ctx, a->rk, src_ext); + TCGv temp = tcg_temp_new(); + + func(dest, src1, src2, temp, a->sa2); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + tcg_temp_free(temp); + return true; +} + +static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + + tcg_gen_movi_tl(dest, a->si20 << 12); + return true; +} + +static bool gen_pc(DisasContext *ctx, arg_fmt_rdsi20 *a, + void (*func)(DisasContext *ctx, TCGv, target_long)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + + func(ctx, dest, a->si20); + return true; +} + +static bool gen_r2_ui12(DisasContext *ctx, arg_fmt_rdrjui12 *a, + void (*func)(TCGv, TCGv, target_long)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + func(dest, src1, a->ui12); + return true; +} + +static void gen_slt(TCGv dest, TCGv src1, TCGv src2) +{ + tcg_gen_setcond_tl(TCG_COND_LT, dest, src1, src2); +} + +static void gen_sltu(TCGv dest, TCGv src1, TCGv src2) +{ + tcg_gen_setcond_tl(TCG_COND_LTU, dest, src1, src2); +} + +static bool gen_mulh(DisasContext *ctx, arg_add_w *a, + void(*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv_i32 discard = tcg_temp_new_i32(); + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t0, src1); + tcg_gen_trunc_tl_i32(t1, src2); + func(discard, t0, t0, t1); + tcg_gen_ext_i32_tl(dest, t0); + + tcg_temp_free_i32(discard); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); + return true; +} + +static bool gen_mulh_d(DisasContext *ctx, arg_add_w *a, + void(*func)(TCGv, TCGv, TCGv, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv discard = tcg_temp_new(); + + func(discard, dest, src1, src2); + tcg_temp_free(discard); + return true; +} + +static bool gen_mulw_d(DisasContext *ctx, arg_add_w *a, + void(*func)(TCGv_i64, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + func(src1, src1); + func(src2, src2); + tcg_gen_mul_i64(dest, src1, src2); + return true; +} + +static bool gen_div_w(DisasContext *ctx, arg_fmt_rdrjrk *a, + DisasExtend src_ext, DisasExtend dst_ext, + void(*func)(TCGv, TCGv, TCGv)) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, src_ext); + TCGv src2 = gpr_src(ctx, a->rk, src_ext); + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src1, INT_MIN); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, -1); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, src2, t2, t3, t2, src2); + func(dest, src1, src2); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + + tcg_temp_free(t2); + tcg_temp_free(t3); + return true; +} + +static bool gen_div_wu(DisasContext *ctx, arg_fmt_rdrjrk *a, + DisasExtend src_ext, DisasExtend dst_ext, + void(*func)(TCGv, TCGv, TCGv)) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, src_ext); + TCGv src2 = gpr_src(ctx, a->rk, src_ext); + TCGv t2 = tcg_constant_tl(0); + TCGv t3 = tcg_constant_tl(1); + + tcg_gen_movcond_tl(TCG_COND_EQ, src1, src1, t2, t3, src1); + func(dest, src1, src2); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +static bool gen_div_d(DisasContext *ctx, arg_fmt_rdrjrk *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src1, -1LL << 63); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, -1LL); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, src2, t2, t3, t2, src2); + func(dest, src1, src2); + + tcg_temp_free(t2); + tcg_temp_free(t3); + + return true; +} + +static bool gen_div_du(DisasContext *ctx, arg_fmt_rdrjrk *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv t2 = tcg_constant_tl(0); + TCGv t3 = tcg_constant_tl(1); + + tcg_gen_movcond_tl(TCG_COND_EQ, src2, src2, t2, t3, src2); + func(dest, src1, src2); + + return true; +} + +static void gen_alsl_w(TCGv dest, TCGv src1, TCGv src2, + TCGv temp, target_long sa2) +{ + tcg_gen_shli_tl(temp, src1, sa2 + 1); + tcg_gen_add_tl(dest, temp, src2); +} + +static void gen_alsl_wu(TCGv dest, TCGv src1, TCGv src2, + TCGv temp, target_long sa2) +{ + tcg_gen_shli_tl(temp, src1, sa2 + 1); + tcg_gen_add_tl(dest, temp, src2); +} + +static void gen_alsl_d(TCGv dest, TCGv src1, TCGv src2, + TCGv temp, target_long sa2) +{ + tcg_gen_shli_tl(temp, src1, sa2 + 1); + tcg_gen_add_tl(dest, temp, src2); +} + +static bool trans_lu32i_d(DisasContext *ctx, arg_lu32i_d *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE); + TCGv src2 = tcg_constant_tl(a->si20); + + tcg_gen_deposit_tl(dest, src1, src2, 32, 32); + return true; +} + +static bool trans_lu52i_d(DisasContext *ctx, arg_lu52i_d *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = tcg_constant_tl(a->si12); + + tcg_gen_deposit_tl(dest, src1, src2, 52, 12); + return true; +} + +static void gen_pcaddi(DisasContext *ctx, TCGv dest, target_long si20) +{ + target_ulong addr = ctx->base.pc_next + (si20 << 2); + tcg_gen_movi_tl(dest, addr); +} + +static void gen_pcalau12i(DisasContext *ctx, TCGv dest, target_long si20) +{ + + target_ulong addr = (ctx->base.pc_next + (si20 << 12)) & ~0xfff; + tcg_gen_movi_tl(dest, addr); +} + +static void gen_pcaddu12i(DisasContext *ctx, TCGv dest, target_long si20) +{ + + target_ulong addr = ctx->base.pc_next + (si20 << 12); + tcg_gen_movi_tl(dest, addr); +} + +static void gen_pcaddu18i(DisasContext *ctx, TCGv dest, target_long si20) +{ + target_ulong addr = ctx->base.pc_next + ((target_ulong)(si20) << 18); + tcg_gen_movi_tl(dest, addr); +} + +static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + tcg_gen_addi_tl(dest, src1, a->si16 << 16); + return true; +} + +TRANS(add_w, gen_r3, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_add_tl) +TRANS(add_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_add_tl) +TRANS(sub_w, gen_r3, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_sub_tl) +TRANS(sub_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_sub_tl) +TRANS(and, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_and_tl) +TRANS(or, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_or_tl) +TRANS(xor, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_xor_tl) +TRANS(nor, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_nor_tl) +TRANS(andn, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_andc_tl) +TRANS(orn, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_orc_tl) +TRANS(slt, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_slt) +TRANS(sltu, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_sltu) +TRANS(mul_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_SIGN, tcg_gen_mul_tl) +TRANS(mul_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_mul_tl) +TRANS(mulh_w, gen_mulh, tcg_gen_muls2_i32) +TRANS(mulh_wu, gen_mulh, tcg_gen_mulu2_i32) +TRANS(mulh_d, gen_mulh_d, tcg_gen_muls2_tl) +TRANS(mulh_du, gen_mulh_d, tcg_gen_mulu2_tl) +TRANS(mulw_d_w, gen_mulw_d, tcg_gen_ext32s_tl) +TRANS(mulw_d_wu, gen_mulw_d, tcg_gen_ext32u_tl) +TRANS(div_w, gen_div_w, EXT_SIGN, EXT_SIGN, tcg_gen_div_tl) +TRANS(mod_w, gen_div_w, EXT_SIGN, EXT_SIGN, tcg_gen_rem_tl) +TRANS(div_wu, gen_div_wu, EXT_ZERO, EXT_SIGN, tcg_gen_divu_tl) +TRANS(mod_wu, gen_div_wu, EXT_ZERO, EXT_SIGN, tcg_gen_remu_tl) +TRANS(div_d, gen_div_d, tcg_gen_div_tl) +TRANS(mod_d, gen_div_d, tcg_gen_rem_tl) +TRANS(div_du, gen_div_du, tcg_gen_divu_tl) +TRANS(mod_du, gen_div_du, tcg_gen_remu_tl) +TRANS(slti, gen_r2_si12, EXT_NONE, EXT_NONE, gen_slt) +TRANS(sltui, gen_r2_si12, EXT_NONE, EXT_NONE, gen_sltu) +TRANS(addi_w, gen_r2_si12, EXT_NONE, EXT_SIGN, tcg_gen_add_tl) +TRANS(addi_d, gen_r2_si12, EXT_NONE, EXT_NONE, tcg_gen_add_tl) +TRANS(alsl_w, gen_r3_sa2, EXT_NONE, EXT_SIGN, gen_alsl_w) +TRANS(alsl_wu, gen_r3_sa2, EXT_NONE, EXT_ZERO, gen_alsl_wu) +TRANS(alsl_d, gen_r3_sa2, EXT_NONE, EXT_NONE, gen_alsl_d) +TRANS(pcaddi, gen_pc, gen_pcaddi) +TRANS(pcalau12i, gen_pc, gen_pcalau12i) +TRANS(pcaddu12i, gen_pc, gen_pcaddu12i) +TRANS(pcaddu18i, gen_pc, gen_pcaddu18i) +TRANS(andi, gen_r2_ui12, tcg_gen_andi_tl) +TRANS(ori, gen_r2_ui12, tcg_gen_ori_tl) +TRANS(xori, gen_r2_ui12, tcg_gen_xori_tl) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode new file mode 100644 index 0000000..1e0b755 --- /dev/null +++ b/target/loongarch/insns.decode @@ -0,0 +1,89 @@ +# +# LoongArch instruction decode definitions. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited +# +# SPDX-License-Identifier: LGPL-2.1+ +# + +# +# Fields +# +%rd 0:5 +%rj 5:5 +%rk 10:5 +%sa2 15:2 +%si12 10:s12 +%ui12 10:12 +%si16 10:s16 +%si20 5:s20 + +# +# Argument sets +# +&fmt_rdrjrk rd rj rk +&fmt_rdrjsi12 rd rj si12 +&fmt_rdrjrksa2 rd rj rk sa2 +&fmt_rdrjsi16 rd rj si16 +&fmt_rdrjui12 rd rj ui12 +&fmt_rdsi20 rd si20 + +# +# Formats +# +@fmt_rdrjrk .... ........ ..... ..... ..... ..... &fmt_rdrjrk %rd %rj %rk +@fmt_rdrjsi12 .... ...... ............ ..... ..... &fmt_rdrjsi12 %rd %rj %si12 +@fmt_rdrjui12 .... ...... ............ ..... ..... &fmt_rdrjui12 %rd %rj %ui12 +@fmt_rdrjrksa2 .... ........ ... .. ..... ..... ..... &fmt_rdrjrksa2 %rd %rj %rk %sa2 +@fmt_rdrjsi16 .... .. ................ ..... ..... &fmt_rdrjsi16 %rd %rj %si16 +@fmt_rdsi20 .... ... .................... ..... &fmt_rdsi20 %rd %si20 + +# +# Fixed point arithmetic operation instruction +# +add_w 0000 00000001 00000 ..... ..... ..... @fmt_rdrjrk +add_d 0000 00000001 00001 ..... ..... ..... @fmt_rdrjrk +sub_w 0000 00000001 00010 ..... ..... ..... @fmt_rdrjrk +sub_d 0000 00000001 00011 ..... ..... ..... @fmt_rdrjrk +slt 0000 00000001 00100 ..... ..... ..... @fmt_rdrjrk +sltu 0000 00000001 00101 ..... ..... ..... @fmt_rdrjrk +slti 0000 001000 ............ ..... ..... @fmt_rdrjsi12 +sltui 0000 001001 ............ ..... ..... @fmt_rdrjsi12 +nor 0000 00000001 01000 ..... ..... ..... @fmt_rdrjrk +and 0000 00000001 01001 ..... ..... ..... @fmt_rdrjrk +or 0000 00000001 01010 ..... ..... ..... @fmt_rdrjrk +xor 0000 00000001 01011 ..... ..... ..... @fmt_rdrjrk +orn 0000 00000001 01100 ..... ..... ..... @fmt_rdrjrk +andn 0000 00000001 01101 ..... ..... ..... @fmt_rdrjrk +mul_w 0000 00000001 11000 ..... ..... ..... @fmt_rdrjrk +mulh_w 0000 00000001 11001 ..... ..... ..... @fmt_rdrjrk +mulh_wu 0000 00000001 11010 ..... ..... ..... @fmt_rdrjrk +mul_d 0000 00000001 11011 ..... ..... ..... @fmt_rdrjrk +mulh_d 0000 00000001 11100 ..... ..... ..... @fmt_rdrjrk +mulh_du 0000 00000001 11101 ..... ..... ..... @fmt_rdrjrk +mulw_d_w 0000 00000001 11110 ..... ..... ..... @fmt_rdrjrk +mulw_d_wu 0000 00000001 11111 ..... ..... ..... @fmt_rdrjrk +div_w 0000 00000010 00000 ..... ..... ..... @fmt_rdrjrk +mod_w 0000 00000010 00001 ..... ..... ..... @fmt_rdrjrk +div_wu 0000 00000010 00010 ..... ..... ..... @fmt_rdrjrk +mod_wu 0000 00000010 00011 ..... ..... ..... @fmt_rdrjrk +div_d 0000 00000010 00100 ..... ..... ..... @fmt_rdrjrk +mod_d 0000 00000010 00101 ..... ..... ..... @fmt_rdrjrk +div_du 0000 00000010 00110 ..... ..... ..... @fmt_rdrjrk +mod_du 0000 00000010 00111 ..... ..... ..... @fmt_rdrjrk +alsl_w 0000 00000000 010 .. ..... ..... ..... @fmt_rdrjrksa2 +alsl_wu 0000 00000000 011 .. ..... ..... ..... @fmt_rdrjrksa2 +alsl_d 0000 00000010 110 .. ..... ..... ..... @fmt_rdrjrksa2 +lu12i_w 0001 010 .................... ..... @fmt_rdsi20 +lu32i_d 0001 011 .................... ..... @fmt_rdsi20 +lu52i_d 0000 001100 ............ ..... ..... @fmt_rdrjsi12 +pcaddi 0001 100 .................... ..... @fmt_rdsi20 +pcalau12i 0001 101 .................... ..... @fmt_rdsi20 +pcaddu12i 0001 110 .................... ..... @fmt_rdsi20 +pcaddu18i 0001 111 .................... ..... @fmt_rdsi20 +addi_w 0000 001010 ............ ..... ..... @fmt_rdrjsi12 +addi_d 0000 001011 ............ ..... ..... @fmt_rdrjsi12 +addu16i_d 0001 00 ................ ..... ..... @fmt_rdrjsi16 +andi 0000 001101 ............ ..... ..... @fmt_rdrjui12 +ori 0000 001110 ............ ..... ..... @fmt_rdrjui12 +xori 0000 001111 ............ ..... ..... @fmt_rdrjui12 diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index cfb08df..1052cb6 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -9,7 +9,6 @@ #ifndef LOONGARCH_INTERNALS_H #define LOONGARCH_INTERNALS_H - void loongarch_translate_init(void); void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index bdbd7a9..1806d2c 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -36,11 +36,6 @@ void generate_exception(DisasContext *ctx, int excp) ctx->base.is_jmp = DISAS_NORETURN; } -static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) -{ - return true; -} - static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) { if (translator_use_goto_tb(&ctx->base, dest)) { @@ -65,6 +60,12 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, /* Bound the number of insns to execute to those left on the page. */ bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; ctx->base.max_insns = MIN(ctx->base.max_insns, bound); + + ctx->dst_ext = EXT_NONE; + ctx->ntemp = 0; + memset(ctx->temp, 0, sizeof(ctx->temp)); + + ctx->zero = tcg_constant_tl(0); } static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) @@ -78,6 +79,87 @@ static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) tcg_gen_insn_start(ctx->base.pc_next); } +/* + * Wrappers for getting reg values. + * + * The $zero register does not have cpu_gpr[0] allocated -- we supply the + * constant zero as a source, and an uninitialized sink as destination. + * + * Further, we may provide an extension for word operations. + */ +static TCGv temp_new(DisasContext *ctx) +{ + assert(ctx->ntemp < ARRAY_SIZE(ctx->temp)); + return ctx->temp[ctx->ntemp++] = tcg_temp_new(); +} + +static TCGv gpr_src(DisasContext *ctx, int reg_num, DisasExtend ext) +{ + TCGv t; + + if (reg_num == 0) { + return ctx->zero; + } + + switch (ext) { + case EXT_NONE: + return cpu_gpr[reg_num]; + case EXT_SIGN: + t = temp_new(ctx); + tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]); + return t; + case EXT_ZERO: + t = temp_new(ctx); + tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]); + return t; + } + g_assert_not_reached(); +} + +static TCGv gpr_dst(DisasContext *ctx, int reg_num) +{ + if (reg_num == 0 || ctx->dst_ext) { + return temp_new(ctx); + } + return cpu_gpr[reg_num]; +} + +static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) +{ + if (reg_num != 0) { + switch (ctx->dst_ext) { + case EXT_NONE: + return tcg_gen_mov_tl(cpu_gpr[reg_num], t); + case EXT_SIGN: + return tcg_gen_ext32s_tl(cpu_gpr[reg_num], t); + case EXT_ZERO: + return tcg_gen_ext32u_tl(cpu_gpr[reg_num], t); + } + } +} + +#include "decode-insns.c.inc" + +/* fmt rd rj rk */ +static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, + DisasExtend src1_ext, DisasExtend src2_ext, + DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv)) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, src1_ext); + TCGv src2 = gpr_src(ctx, a->rk, src2_ext); + + func(dest, src1, src2); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +#include "insn_trans/trans_arith.c" + static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { CPULoongArchState *env = cs->env_ptr; @@ -91,6 +173,14 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) generate_exception(ctx, EXCP_INE); } + ctx->dst_ext = EXT_NONE; + + for (int i = ctx->ntemp - 1; i >= 0; --i) { + tcg_temp_free(ctx->temp[i]); + ctx->temp[i] = NULL; + } + ctx->ntemp = 0; + ctx->base.pc_next += 4; } diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h index dff7d79..f064fdd 100644 --- a/target/loongarch/translate.h +++ b/target/loongarch/translate.h @@ -11,11 +11,31 @@ #include "exec/translator.h" +#define TRANS(NAME, FUNC, ...) \ + static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \ + { return FUNC(ctx, a, __VA_ARGS__); } + +/* + * If an operation is being performed on less than TARGET_LONG_BITS, + * it may require the inputs to be sign- or zero-extended; which will + * depend on the exact operation being performed. + */ +typedef enum { + EXT_NONE, + EXT_SIGN, + EXT_ZERO, +} DisasExtend; + typedef struct DisasContext { DisasContextBase base; target_ulong page_start; uint32_t opcode; int mem_idx; + TCGv zero; + DisasExtend dst_ext; + /* Space for 3 operands plus 1 extra for address computation. */ + TCGv temp[4]; + uint8_t ntemp; } DisasContext; void generate_exception(DisasContext *ctx, int excp); From patchwork Fri Aug 27 07:14:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461429 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 332F7C432BE for ; Fri, 27 Aug 2021 07:50:42 +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 90DAD60F92 for ; Fri, 27 Aug 2021 07:50:41 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 90DAD60F92 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]:45998 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWdM-0002Tu-RS for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:50:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53164) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW59-0000ia-Fw for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:19 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59462 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW4z-0003CH-JZ for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:19 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S7; Fri, 27 Aug 2021 15:15:03 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 05/19] target/loongarch: Add fixed point shift instruction translation Date: Fri, 27 Aug 2021 15:14:40 +0800 Message-Id: <1630048494-2143-6-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S7 X-Coremail-Antispam: 1UD129KBjvJXoWxKw47uw48Xw1DCw1DGF1kuFg_yoW3XF47pr 18CryUGr48Xr9rJr9Ivw45uFZ8JFnrCa1jg3ySyr15CF4UX3WDJF1DC3ya9rW7twn3ZrW8 ZFZ5uFyqgFyrGaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/insn_trans/trans_shift.c | 154 ++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 26 +++++ target/loongarch/translate.c | 1 + 3 files changed, 181 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_shift.c diff --git a/target/loongarch/insn_trans/trans_shift.c b/target/loongarch/insn_trans/trans_shift.c new file mode 100644 index 0000000..5fa1162 --- /dev/null +++ b/target/loongarch/insn_trans/trans_shift.c @@ -0,0 +1,154 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_r2_ui5(DisasContext *ctx, arg_slli_w *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + ctx->dst_ext = EXT_SIGN; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO); + TCGv src2 = tcg_constant_tl(a->ui5); + + TCGv t0 = temp_new(ctx); + + tcg_gen_andi_tl(t0, src2, 0x1f); + func(dest, src1, t0); + gen_set_gpr(ctx, a->rd, dest); + + return true; +} + +static bool gen_r2_ui6(DisasContext *ctx, arg_slli_d *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = tcg_constant_tl(a->ui6); + + TCGv t0 = temp_new(ctx); + + tcg_gen_andi_tl(t0, src2, 0x7f); + func(dest, src1, t0); + + return true; +} + +static void gen_sll_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + + tcg_gen_andi_tl(t0, src2, 0x1f); + tcg_gen_shl_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_srl_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x1f); + tcg_gen_shr_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_sra_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x1f); + tcg_gen_sar_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_sll_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x3f); + tcg_gen_shl_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_srl_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x3f); + tcg_gen_shr_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_sra_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x3f); + tcg_gen_sar_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_rotr_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv t0 = tcg_temp_new(); + + tcg_gen_andi_tl(t0, src2, 0x1f); + + tcg_gen_trunc_tl_i32(t1, src1); + tcg_gen_trunc_tl_i32(t2, t0); + + tcg_gen_rotr_i32(t1, t1, t2); + tcg_gen_ext_i32_tl(dest, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); + tcg_temp_free(t0); +} + +static void gen_rotr_d(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, src2, 0x3f); + tcg_gen_rotr_tl(dest, src1, t0); + tcg_temp_free(t0); +} + +static void gen_rotri_w(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t1, src1); + tcg_gen_trunc_tl_i32(t2, src2); + tcg_gen_rotr_i32(t1, t1, t2); + tcg_gen_ext_i32_tl(dest, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); +} + +static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO); + + tcg_gen_sextract_tl(dest, src1, a->ui5, 32 - a->ui5); + return true; +} + +TRANS(sll_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sll_w) +TRANS(srl_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_srl_w) +TRANS(sra_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sra_w) +TRANS(sll_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d) +TRANS(srl_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d) +TRANS(sra_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d) +TRANS(rotr_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w) +TRANS(rotr_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d) +TRANS(slli_w, gen_r2_ui5, tcg_gen_shl_tl) +TRANS(slli_d, gen_r2_ui6, tcg_gen_shl_tl) +TRANS(srli_w, gen_r2_ui5, tcg_gen_shr_tl) +TRANS(srli_d, gen_r2_ui6, tcg_gen_shr_tl) +TRANS(srai_d, gen_r2_ui6, tcg_gen_sar_tl) +TRANS(rotri_w, gen_r2_ui5, gen_rotri_w) +TRANS(rotri_d, gen_r2_ui6, tcg_gen_rotr_tl) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 1e0b755..9302576 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -17,6 +17,8 @@ %ui12 10:12 %si16 10:s16 %si20 5:s20 +%ui5 10:5 +%ui6 10:6 # # Argument sets @@ -27,6 +29,8 @@ &fmt_rdrjsi16 rd rj si16 &fmt_rdrjui12 rd rj ui12 &fmt_rdsi20 rd si20 +&fmt_rdrjui5 rd rj ui5 +&fmt_rdrjui6 rd rj ui6 # # Formats @@ -37,6 +41,8 @@ @fmt_rdrjrksa2 .... ........ ... .. ..... ..... ..... &fmt_rdrjrksa2 %rd %rj %rk %sa2 @fmt_rdrjsi16 .... .. ................ ..... ..... &fmt_rdrjsi16 %rd %rj %si16 @fmt_rdsi20 .... ... .................... ..... &fmt_rdsi20 %rd %si20 +@fmt_rdrjui5 .... ........ ..... ..... ..... ..... &fmt_rdrjui5 %rd %rj %ui5 +@fmt_rdrjui6 .... ........ .... ...... ..... ..... &fmt_rdrjui6 %rd %rj %ui6 # # Fixed point arithmetic operation instruction @@ -87,3 +93,23 @@ addu16i_d 0001 00 ................ ..... ..... @fmt_rdrjsi16 andi 0000 001101 ............ ..... ..... @fmt_rdrjui12 ori 0000 001110 ............ ..... ..... @fmt_rdrjui12 xori 0000 001111 ............ ..... ..... @fmt_rdrjui12 + +# +# Fixed point shift operation instruction +# +sll_w 0000 00000001 01110 ..... ..... ..... @fmt_rdrjrk +srl_w 0000 00000001 01111 ..... ..... ..... @fmt_rdrjrk +sra_w 0000 00000001 10000 ..... ..... ..... @fmt_rdrjrk +sll_d 0000 00000001 10001 ..... ..... ..... @fmt_rdrjrk +srl_d 0000 00000001 10010 ..... ..... ..... @fmt_rdrjrk +sra_d 0000 00000001 10011 ..... ..... ..... @fmt_rdrjrk +rotr_w 0000 00000001 10110 ..... ..... ..... @fmt_rdrjrk +rotr_d 0000 00000001 10111 ..... ..... ..... @fmt_rdrjrk +slli_w 0000 00000100 00001 ..... ..... ..... @fmt_rdrjui5 +slli_d 0000 00000100 0001 ...... ..... ..... @fmt_rdrjui6 +srli_w 0000 00000100 01001 ..... ..... ..... @fmt_rdrjui5 +srli_d 0000 00000100 0101 ...... ..... ..... @fmt_rdrjui6 +srai_w 0000 00000100 10001 ..... ..... ..... @fmt_rdrjui5 +srai_d 0000 00000100 1001 ...... ..... ..... @fmt_rdrjui6 +rotri_w 0000 00000100 11001 ..... ..... ..... @fmt_rdrjui5 +rotri_d 0000 00000100 1101 ...... ..... ..... @fmt_rdrjui6 diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 1806d2c..e9cccca 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -159,6 +159,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, } #include "insn_trans/trans_arith.c" +#include "insn_trans/trans_shift.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Fri Aug 27 07:14:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461423 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 CFDA4C432BE for ; Fri, 27 Aug 2021 07:48:17 +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 4EED960F92 for ; Fri, 27 Aug 2021 07:48:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 4EED960F92 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]:41606 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWb2-0007wP-I4 for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:48:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53158) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW59-0000iX-Dv for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:19 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59480 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW51-0003Co-5r for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:18 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S8; Fri, 27 Aug 2021 15:15:07 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 06/19] target/loongarch: Add fixed point bit instruction translation Date: Fri, 27 Aug 2021 15:14:41 +0800 Message-Id: <1630048494-2143-7-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S8 X-Coremail-Antispam: 1UD129KBjvAXoW3Kw1rGF1UWw4fGryxur4rKrg_yoW8Gw1fXo W7GF45Jr48Gr1a9ryak3WkXF48tr1UKa1xJ3s5ua1UW3WxJr17Jr1UKFs5Zw48Jw1q9Fyr GF1SqFy3J3yfXrn7n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/helper.h | 4 + target/loongarch/insn_trans/trans_bit.c | 297 ++++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 45 +++++ target/loongarch/op_helper.c | 22 +++ target/loongarch/translate.c | 1 + 5 files changed, 369 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..ff29623 --- /dev/null +++ b/target/loongarch/insn_trans/trans_bit.c @@ -0,0 +1,297 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +/* fmt rd rj */ +static bool gen_r2(DisasContext *ctx, arg_fmt_rdrj *a, + DisasExtend src_ext, DisasExtend dst_ext, + void (*func)(TCGv, TCGv)) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, src_ext); + + func(dest, src1); + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +static bool gen_bpw(DisasContext *ctx, arg_fmt_rdrjrksa2 *a, + void (*func)(TCGv, TCGv, TCGv, target_long)) +{ + ctx->dst_ext = EXT_SIGN; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + func(dest, src1, src2, a->sa2); + + gen_set_gpr(ctx, a->rd, dest); + return true; +} + +static bool gen_bpd(DisasContext *ctx, arg_fmt_rdrjrksa3 *a, + void (*func)(TCGv, TCGv, TCGv, target_long)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + func(dest, src1, src2, a->sa3); + return true; +} + +static bool gen_r2_bw2(DisasContext *ctx, arg_fmt_rdrjmsbwlsbw *a, + void (*func)(TCGv, TCGv, target_long, target_long)) +{ + ctx->dst_ext = EXT_SIGN; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + if (a->lsbw > a->msbw) { + return false; + } + + func(dest, src1, a->msbw, a->lsbw); + + gen_set_gpr(ctx, a->rd, dest); + return true; +} + +static bool gen_r2_bd2(DisasContext *ctx, arg_fmt_rdrjmsbdlsbd *a, + DisasExtend dst_ext, + void (*func)(TCGv, TCGv, target_long, target_long)) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + if (a->lsbd > a->msbd) { + return false; + } + + func(dest, src1, a->msbd, a->lsbd); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +static void gen_clz_w(TCGv dest, TCGv src1) +{ + tcg_gen_ext32u_tl(dest, src1); + tcg_gen_clzi_tl(dest, dest, TARGET_LONG_BITS); + tcg_gen_subi_tl(dest, dest, TARGET_LONG_BITS - 32); +} + +static void gen_clo_w(TCGv dest, TCGv src1) +{ + tcg_gen_not_tl(dest, src1); + gen_clz_w(dest, dest); +} + +static void gen_ctz_w(TCGv dest, TCGv src1) +{ + tcg_gen_ori_tl(dest, src1, (target_ulong)MAKE_64BIT_MASK(32, 32)); + tcg_gen_ctzi_tl(dest, dest, 64); +} + +static void gen_cto_w(TCGv dest, TCGv src1) +{ + tcg_gen_not_tl(dest, src1); + gen_ctz_w(dest, dest); +} + +static void gen_clz_d(TCGv dest, TCGv src1) +{ + tcg_gen_clzi_i64(dest, src1, TARGET_LONG_BITS); +} + +static void gen_clo_d(TCGv dest, TCGv src1) +{ + tcg_gen_not_tl(dest, src1); + gen_clz_d(dest, dest); +} + +static void gen_ctz_d(TCGv dest, TCGv src1) +{ + tcg_gen_ctzi_tl(dest, src1, TARGET_LONG_BITS); +} + +static void gen_cto_d(TCGv dest, TCGv src1) +{ + tcg_gen_not_tl(dest, src1); + gen_ctz_d(dest, dest); +} + +static void gen_revb_2w(TCGv dest, TCGv src1) +{ + tcg_gen_bswap64_i64(dest, src1); + tcg_gen_rotri_i64(dest, dest, 32); +} + +static bool trans_revb_2h(DisasContext *ctx, arg_revb_2h *a) +{ + ctx->dst_ext = EXT_SIGN; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv mask = tcg_constant_tl(0x00FF00FF); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + tcg_gen_shri_tl(t0, src1, 8); + tcg_gen_and_tl(t0, t0, mask); + tcg_gen_and_tl(t1, src1, mask); + tcg_gen_shli_tl(t1, t1, 8); + tcg_gen_or_tl(dest, t0, t1); + gen_set_gpr(ctx, a->rd, dest); + + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_revb_4h(DisasContext *ctx, arg_revb_4h *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv mask = tcg_constant_tl(0x00FF00FF00FF00FFULL); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + tcg_gen_shri_tl(t0, src1, 8); + tcg_gen_and_tl(t0, t0, mask); + tcg_gen_and_tl(t1, src1, mask); + tcg_gen_shli_tl(t1, t1, 8); + tcg_gen_or_tl(dest, t0, t1); + + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_revh_2w(DisasContext *ctx, arg_revh_2w *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 mask = tcg_constant_i64(0x0000ffff0000ffffull); + + tcg_gen_shri_i64(t0, src1, 16); + tcg_gen_and_i64(t1, src1, mask); + tcg_gen_and_i64(t0, t0, mask); + tcg_gen_shli_i64(t1, t1, 16); + tcg_gen_or_i64(dest, t1, t0); + + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + + return true; +} + +static bool trans_revh_d(DisasContext *ctx, arg_revh_d *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv mask = tcg_constant_tl(0x0000FFFF0000FFFFULL); + + tcg_gen_shri_tl(t1, src1, 16); + tcg_gen_and_tl(t1, t1, mask); + tcg_gen_and_tl(t0, src1, mask); + tcg_gen_shli_tl(t0, t0, 16); + tcg_gen_or_tl(t0, t0, t1); + tcg_gen_shri_tl(t1, t0, 32); + tcg_gen_shli_tl(t0, t0, 32); + tcg_gen_or_tl(dest, t0, t1); + + tcg_temp_free(t0); + tcg_temp_free(t1); + + return true; +} + +static void gen_maskeqz(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv cond1 = tcg_constant_tl(0); + + tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, cond1, cond1, src1); +} + +static void gen_masknez(TCGv dest, TCGv src1, TCGv src2) +{ + TCGv cond1 = tcg_constant_tl(0); + + tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, cond1, cond1, src1); +} + +static void gen_bytepick_w(TCGv dest, TCGv src1, TCGv src2, target_long sa2) +{ + tcg_gen_concat_tl_i64(dest, src1, src2); + tcg_gen_sextract_i64(dest, dest, (32 - sa2 * 8), 32); +} + +static void gen_bytepick_d(TCGv dest, TCGv src1, TCGv src2, target_long sa3) +{ + tcg_gen_extract2_i64(dest, src1, src2, (64 - sa3 * 8)); +} + +static void gen_bstrins_w(TCGv dest, TCGv src1, + target_long msb, target_long lsb) +{ + tcg_gen_deposit_tl(dest, dest, src1, lsb, msb - lsb + 1); + tcg_gen_ext32s_tl(dest, dest); +} + +static void gen_bstrpick_w(TCGv dest, TCGv src1, + target_long msb, target_long lsb) +{ + tcg_gen_extract_tl(dest, src1, lsb, msb - lsb + 1); + tcg_gen_ext32s_tl(dest, dest); +} + +static void gen_bstrins_d(TCGv dest, TCGv src1, + target_long msb, target_long lsb) +{ + tcg_gen_deposit_tl(dest, dest, src1, lsb, msb - lsb + 1); +} + +static void gen_bstrpick_d(TCGv dest, TCGv src1, + target_long msb, target_long lsb) +{ + tcg_gen_extract_tl(dest, src1, lsb, msb - lsb + 1); +} + +TRANS(ext_w_h, gen_r2, EXT_NONE, EXT_NONE, tcg_gen_ext16s_tl) +TRANS(ext_w_b, gen_r2, EXT_NONE, EXT_NONE, tcg_gen_ext8s_tl) +TRANS(clo_w, gen_r2, EXT_NONE, EXT_NONE, gen_clo_w) +TRANS(clz_w, gen_r2, EXT_ZERO, EXT_NONE, gen_clz_w) +TRANS(cto_w, gen_r2, EXT_NONE, EXT_NONE, gen_cto_w) +TRANS(ctz_w, gen_r2, EXT_NONE, EXT_NONE, gen_ctz_w) +TRANS(clo_d, gen_r2, EXT_NONE, EXT_NONE, gen_clo_d) +TRANS(clz_d, gen_r2, EXT_NONE, EXT_NONE, gen_clz_d) +TRANS(cto_d, gen_r2, EXT_NONE, EXT_NONE, gen_cto_d) +TRANS(ctz_d, gen_r2, EXT_NONE, EXT_NONE, gen_ctz_d) +TRANS(revb_2w, gen_r2, EXT_NONE, EXT_NONE, gen_revb_2w) +TRANS(revb_d, gen_r2, EXT_NONE, EXT_NONE, tcg_gen_bswap64_i64) +TRANS(bitrev_4b, gen_r2, EXT_ZERO, EXT_SIGN, gen_helper_bitswap) +TRANS(bitrev_8b, gen_r2, EXT_NONE, EXT_NONE, gen_helper_bitswap) +TRANS(bitrev_w, gen_r2, EXT_NONE, EXT_SIGN, gen_helper_bitrev_w) +TRANS(bitrev_d, gen_r2, EXT_NONE, EXT_NONE, gen_helper_bitrev_d) +TRANS(maskeqz, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_maskeqz) +TRANS(masknez, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_masknez) +TRANS(bytepick_w, gen_bpw, gen_bytepick_w) +TRANS(bytepick_d, gen_bpd, gen_bytepick_d) +TRANS(bstrins_w, gen_r2_bw2, gen_bstrins_w) +TRANS(bstrpick_w, gen_r2_bw2, gen_bstrpick_w) +TRANS(bstrins_d, gen_r2_bd2, EXT_NONE, gen_bstrins_d) +TRANS(bstrpick_d, gen_r2_bd2, EXT_ZERO, gen_bstrpick_d) 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 e9cccca..0f18d06 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -160,6 +160,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, #include "insn_trans/trans_arith.c" #include "insn_trans/trans_shift.c" +#include "insn_trans/trans_bit.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Fri Aug 27 07:14:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461431 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 C9FECC432BE for ; Fri, 27 Aug 2021 07:52:03 +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 6551C60F92 for ; Fri, 27 Aug 2021 07:52:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 6551C60F92 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]:49096 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWee-0004cn-Jb for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:52:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53170) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5A-0000jq-2p for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:20 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59506 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW52-0003Et-Mh for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:19 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S9; Fri, 27 Aug 2021 15:15:08 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 07/19] target/loongarch: Add fixed point load/store instruction translation Date: Fri, 27 Aug 2021 15:14:42 +0800 Message-Id: <1630048494-2143-8-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S9 X-Coremail-Antispam: 1UD129KBjvAXoW3Zw17Jr43urW5JFWUJFykuFg_yoW8Xr47to WUGa15Jr48Gr15tr13Kw18Xr4Yyryj93yDArZ8ua1DG3WxJr17Jr17Crn5Za1fJ3yqgFyf GF1SgF15t3yaqrnrn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/helper.h | 3 + target/loongarch/insn_trans/trans_memory.c | 263 +++++++++++++++++++++++++++++ target/loongarch/insns.decode | 58 +++++++ target/loongarch/op_helper.c | 15 ++ target/loongarch/translate.c | 30 ++++ 5 files changed, 369 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_memory.c diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index e39574e..09b5a3d 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -11,3 +11,6 @@ DEF_HELPER_2(raise_exception, noreturn, env, i32) DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) + +DEF_HELPER_3(asrtle_d, void, env, tl, tl) +DEF_HELPER_3(asrtgt_d, void, env, tl, tl) diff --git a/target/loongarch/insn_trans/trans_memory.c b/target/loongarch/insn_trans/trans_memory.c new file mode 100644 index 0000000..afc5d67 --- /dev/null +++ b/target/loongarch/insn_trans/trans_memory.c @@ -0,0 +1,263 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_load(DisasContext *ctx, arg_fmt_rdrjsi12 *a, + DisasExtend dst_ext, MemOp mop) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv temp = NULL; + + if (a->si12) { + temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, addr, a->si12); + addr = temp; + } + + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + + if (temp) { + tcg_temp_free(temp); + } + return true; +} + +static bool gen_store(DisasContext *ctx, arg_fmt_rdrjsi12 *a, MemOp mop) +{ + TCGv data = gpr_src(ctx, a->rd, EXT_NONE); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv temp = NULL; + + if (a->si12) { + temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, addr, a->si12); + addr = temp; + } + + tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop); + + if (temp) { + tcg_temp_free(temp); + } + return true; +} + +static bool gen_loadx(DisasContext *ctx, arg_fmt_rdrjrk *a, + DisasExtend dst_ext, MemOp mop) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + + tcg_temp_free(addr); + return true; +} + +static bool gen_storex(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ + TCGv data = gpr_src(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_load_gt(DisasContext *ctx, arg_fmt_rdrjrk *a, + DisasExtend dst_ext, MemOp mop) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtgt_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + tcg_temp_free(addr); + return true; +} + +static bool gen_load_le(DisasContext *ctx, arg_fmt_rdrjrk *a, + DisasExtend dst_ext, MemOp mop) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtle_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + tcg_temp_free(addr); + return true; +} + +static bool gen_store_gt(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ + TCGv data = gpr_src(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtgt_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_store_le(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ + TCGv data = gpr_src(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtle_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool trans_preld(DisasContext *ctx, arg_preld *a) +{ + return true; +} + +static bool trans_dbar(DisasContext *ctx, arg_dbar * a) +{ + gen_loongarch_sync(a->whint); + return true; +} + +static bool trans_ibar(DisasContext *ctx, arg_ibar *a) +{ + ctx->base.is_jmp = DISAS_STOP; + return true; +} + +static bool gen_ldptr(DisasContext *ctx, arg_fmt_rdrjsi14 *a, + DisasExtend dst_ext, MemOp mop) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv temp = NULL; + + if (a->si14) { + temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, addr, a->si14 << 2); + addr = temp; + } + + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + + if (temp) { + tcg_temp_free(temp); + } + return true; +} + +static bool gen_stptr(DisasContext *ctx, arg_fmt_rdrjsi14 *a, MemOp mop) +{ + TCGv data = gpr_src(ctx, a->rd, EXT_NONE); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv temp = NULL; + + if (a->si14) { + temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, addr, a->si14 << 2); + addr = temp; + } + + tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop); + + if (temp) { + tcg_temp_free(temp); + } + return true; +} + +TRANS(ld_b, gen_load, EXT_SIGN, MO_SB) +TRANS(ld_h, gen_load, EXT_SIGN, MO_TESW) +TRANS(ld_w, gen_load, EXT_SIGN, MO_TESL) +TRANS(ld_d, gen_load, EXT_NONE, MO_TEQ) +TRANS(st_b, gen_store, MO_SB) +TRANS(st_h, gen_store, MO_TESW) +TRANS(st_w, gen_store, MO_TESL) +TRANS(st_d, gen_store, MO_TEQ) +TRANS(ld_bu, gen_load, EXT_ZERO, MO_UB) +TRANS(ld_hu, gen_load, EXT_ZERO, MO_TEUW) +TRANS(ld_wu, gen_load, EXT_ZERO, MO_TEUL) +TRANS(ldx_b, gen_loadx, EXT_SIGN, MO_SB) +TRANS(ldx_h, gen_loadx, EXT_SIGN, MO_TESW) +TRANS(ldx_w, gen_loadx, EXT_SIGN, MO_TESL) +TRANS(ldx_d, gen_loadx, EXT_NONE, MO_TEQ) +TRANS(stx_b, gen_storex, MO_SB) +TRANS(stx_h, gen_storex, MO_TESW) +TRANS(stx_w, gen_storex, MO_TESL) +TRANS(stx_d, gen_storex, MO_TEQ) +TRANS(ldx_bu, gen_loadx, EXT_ZERO, MO_UB) +TRANS(ldx_hu, gen_loadx, EXT_ZERO, MO_TEUW) +TRANS(ldx_wu, gen_loadx, EXT_ZERO, MO_TEUL) +TRANS(ldptr_w, gen_ldptr, EXT_SIGN, MO_TESL) +TRANS(stptr_w, gen_stptr, MO_TESL) +TRANS(ldptr_d, gen_ldptr, EXT_NONE, MO_TEQ) +TRANS(stptr_d, gen_stptr, MO_TEQ) +TRANS(ldgt_b, gen_load_gt, EXT_SIGN, MO_SB) +TRANS(ldgt_h, gen_load_gt, EXT_SIGN, MO_TESW) +TRANS(ldgt_w, gen_load_gt, EXT_SIGN, MO_TESL) +TRANS(ldgt_d, gen_load_gt, EXT_NONE, MO_TEQ) +TRANS(ldle_b, gen_load_le, EXT_SIGN, MO_SB) +TRANS(ldle_h, gen_load_le, EXT_SIGN, MO_TESW) +TRANS(ldle_w, gen_load_le, EXT_SIGN, MO_TESL) +TRANS(ldle_d, gen_load_le, EXT_NONE, MO_TEQ) +TRANS(stgt_b, gen_store_gt, MO_SB) +TRANS(stgt_h, gen_store_gt, MO_TESW) +TRANS(stgt_w, gen_store_gt, MO_TESL) +TRANS(stgt_d, gen_store_gt, MO_TEQ) +TRANS(stle_b, gen_store_le, MO_SB) +TRANS(stle_h, gen_store_le, MO_TESW) +TRANS(stle_w, gen_store_le, MO_TESL) +TRANS(stle_d, gen_store_le, MO_TEQ) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index ec599a9..08fd232 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -24,6 +24,9 @@ %lsbw 10:5 %msbd 16:6 %lsbd 10:6 +%si14 10:s14 +%hint 0:5 +%whint 0:15 # # Argument sets @@ -40,6 +43,9 @@ &fmt_rdrjrksa3 rd rj rk sa3 &fmt_rdrjmsbwlsbw rd rj msbw lsbw &fmt_rdrjmsbdlsbd rd rj msbd lsbd +&fmt_rdrjsi14 rd rj si14 +&fmt_hintrjsi12 hint rj si12 +&fmt_whint whint # # Formats @@ -56,6 +62,9 @@ @fmt_rdrjmsbwlsbw .... ....... ..... . ..... ..... ..... &fmt_rdrjmsbwlsbw %rd %rj %msbw %lsbw @fmt_rdrjmsbdlsbd .... ...... ...... ...... ..... ..... &fmt_rdrjmsbdlsbd %rd %rj %msbd %lsbd @fmt_rdrjrksa3 .... ........ .. ... ..... ..... ..... &fmt_rdrjrksa3 %rd %rj %rk %sa3 +@fmt_hintrjsi12 .... ...... ............ ..... ..... &fmt_hintrjsi12 %hint %rj %si12 +@fmt_whint .... ........ ..... ............... &fmt_whint %whint +@fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14 # # Fixed point arithmetic operation instruction @@ -158,3 +167,52 @@ bstrins_w 0000 0000011 ..... 0 ..... ..... ..... @fmt_rdrjmsbwlsbw bstrpick_w 0000 0000011 ..... 1 ..... ..... ..... @fmt_rdrjmsbwlsbw bstrins_d 0000 000010 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd bstrpick_d 0000 000011 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd + +# +# Fixed point load/store instruction +# +ld_b 0010 100000 ............ ..... ..... @fmt_rdrjsi12 +ld_h 0010 100001 ............ ..... ..... @fmt_rdrjsi12 +ld_w 0010 100010 ............ ..... ..... @fmt_rdrjsi12 +ld_d 0010 100011 ............ ..... ..... @fmt_rdrjsi12 +st_b 0010 100100 ............ ..... ..... @fmt_rdrjsi12 +st_h 0010 100101 ............ ..... ..... @fmt_rdrjsi12 +st_w 0010 100110 ............ ..... ..... @fmt_rdrjsi12 +st_d 0010 100111 ............ ..... ..... @fmt_rdrjsi12 +ld_bu 0010 101000 ............ ..... ..... @fmt_rdrjsi12 +ld_hu 0010 101001 ............ ..... ..... @fmt_rdrjsi12 +ld_wu 0010 101010 ............ ..... ..... @fmt_rdrjsi12 +ldx_b 0011 10000000 00000 ..... ..... ..... @fmt_rdrjrk +ldx_h 0011 10000000 01000 ..... ..... ..... @fmt_rdrjrk +ldx_w 0011 10000000 10000 ..... ..... ..... @fmt_rdrjrk +ldx_d 0011 10000000 11000 ..... ..... ..... @fmt_rdrjrk +stx_b 0011 10000001 00000 ..... ..... ..... @fmt_rdrjrk +stx_h 0011 10000001 01000 ..... ..... ..... @fmt_rdrjrk +stx_w 0011 10000001 10000 ..... ..... ..... @fmt_rdrjrk +stx_d 0011 10000001 11000 ..... ..... ..... @fmt_rdrjrk +ldx_bu 0011 10000010 00000 ..... ..... ..... @fmt_rdrjrk +ldx_hu 0011 10000010 01000 ..... ..... ..... @fmt_rdrjrk +ldx_wu 0011 10000010 10000 ..... ..... ..... @fmt_rdrjrk +preld 0010 101011 ............ ..... ..... @fmt_hintrjsi12 +dbar 0011 10000111 00100 ............... @fmt_whint +ibar 0011 10000111 00101 ............... @fmt_whint +ldptr_w 0010 0100 .............. ..... ..... @fmt_rdrjsi14 +stptr_w 0010 0101 .............. ..... ..... @fmt_rdrjsi14 +ldptr_d 0010 0110 .............. ..... ..... @fmt_rdrjsi14 +stptr_d 0010 0111 .............. ..... ..... @fmt_rdrjsi14 +ldgt_b 0011 10000111 10000 ..... ..... ..... @fmt_rdrjrk +ldgt_h 0011 10000111 10001 ..... ..... ..... @fmt_rdrjrk +ldgt_w 0011 10000111 10010 ..... ..... ..... @fmt_rdrjrk +ldgt_d 0011 10000111 10011 ..... ..... ..... @fmt_rdrjrk +ldle_b 0011 10000111 10100 ..... ..... ..... @fmt_rdrjrk +ldle_h 0011 10000111 10101 ..... ..... ..... @fmt_rdrjrk +ldle_w 0011 10000111 10110 ..... ..... ..... @fmt_rdrjrk +ldle_d 0011 10000111 10111 ..... ..... ..... @fmt_rdrjrk +stgt_b 0011 10000111 11000 ..... ..... ..... @fmt_rdrjrk +stgt_h 0011 10000111 11001 ..... ..... ..... @fmt_rdrjrk +stgt_w 0011 10000111 11010 ..... ..... ..... @fmt_rdrjrk +stgt_d 0011 10000111 11011 ..... ..... ..... @fmt_rdrjrk +stle_b 0011 10000111 11100 ..... ..... ..... @fmt_rdrjrk +stle_h 0011 10000111 11101 ..... ..... ..... @fmt_rdrjrk +stle_w 0011 10000111 11110 ..... ..... ..... @fmt_rdrjrk +stle_d 0011 10000111 11111 ..... ..... ..... @fmt_rdrjrk diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c index ec04369..a4ffaf9 100644 --- a/target/loongarch/op_helper.c +++ b/target/loongarch/op_helper.c @@ -42,3 +42,18 @@ target_ulong helper_bitswap(target_ulong v) ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4); return v; } + +/* loongarch assert op */ +void helper_asrtle_d(CPULoongArchState *env, target_ulong rj, target_ulong rk) +{ + if (rj > rk) { + do_raise_exception(env, EXCP_ADE, GETPC()); + } +} + +void helper_asrtgt_d(CPULoongArchState *env, target_ulong rj, target_ulong rk) +{ + if (rj <= rk) { + do_raise_exception(env, EXCP_ADE, GETPC()); + } +} diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 0f18d06..2695c0b 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -68,6 +68,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) { } @@ -161,6 +190,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, #include "insn_trans/trans_arith.c" #include "insn_trans/trans_shift.c" #include "insn_trans/trans_bit.c" +#include "insn_trans/trans_memory.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Fri Aug 27 07:14:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461467 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 416C1C432BE for ; Fri, 27 Aug 2021 07:54:15 +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 AAD0E60FD8 for ; Fri, 27 Aug 2021 07:54:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org AAD0E60FD8 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]:53356 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWgn-0007Sr-TN for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:54:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53198) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5B-0000ny-Rn for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:21 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59594 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW59-0003GY-DM for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:21 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S10; Fri, 27 Aug 2021 15:15:09 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 08/19] target/loongarch: Add fixed point atomic instruction translation Date: Fri, 27 Aug 2021 15:14:43 +0800 Message-Id: <1630048494-2143-9-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S10 X-Coremail-Antispam: 1UD129KBjvJXoW3uryUZry5Kr1DGF43JrWfGrg_yoWDXF1Dpr 4jkryxJr4Fqr15Jr95tws8K343GFnFv347WrW3tFn5ZF4UGF15JF18J39IkFWjgw4DZrW8 KFWay3yjkFy5J3JanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/insn_trans/trans_atomic.c | 132 +++++++++++++++++++++++++++++ target/loongarch/insns.decode | 44 ++++++++++ target/loongarch/translate.c | 1 + 3 files changed, 177 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..fe22eb7 --- /dev/null +++ b/target/loongarch/insn_trans/trans_atomic.c @@ -0,0 +1,132 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_ll(DisasContext *ctx, arg_fmt_rdrjsi14 *a, + void (*func)(TCGv, TCGv, int)) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + tcg_gen_addi_tl(src1, src1, a->si14 << 2); + func(dest, src1, ctx->mem_idx); + tcg_gen_st_tl(src1, cpu_env, offsetof(CPULoongArchState, lladdr)); + tcg_gen_st_tl(dest, cpu_env, offsetof(CPULoongArchState, llval)); + + return true; +} + +static bool gen_sc(DisasContext *ctx, arg_fmt_rdrjsi14 *a, MemOp mop) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv t0 = tcg_temp_new(); + + TCGLabel *l1 = gen_new_label(); + TCGLabel *done = gen_new_label(); + + tcg_gen_addi_tl(t0, src1, a->si14 << 2); + tcg_gen_brcond_tl(TCG_COND_EQ, t0, cpu_lladdr, l1); + tcg_gen_movi_tl(dest, 0); + tcg_gen_br(done); + + gen_set_label(l1); + /* generate cmpxchg */ + tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, + dest, ctx->mem_idx, mop); + tcg_gen_setcond_tl(TCG_COND_EQ, dest, t0, cpu_llval); + gen_set_label(done); + tcg_temp_free(t0); + return true; +} + +static bool gen_am(DisasContext *ctx, arg_fmt_rdrjrk *a, DisasExtend ext, + void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), + MemOp mop) +{ + ctx->dst_ext = ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv val = gpr_src(ctx, a->rk, EXT_NONE); + + if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { + qemu_log("%s: waring, register equal\n", __func__); + return false; + } + + func(dest, addr, val, ctx->mem_idx, mop); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +static bool gen_am_db(DisasContext *ctx, arg_fmt_rdrjrk *a, DisasExtend ext, + void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), + MemOp mop) +{ + ctx->dst_ext = ext; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv val = gpr_src(ctx, a->rk, EXT_NONE); + + if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { + qemu_log("%s: waring, register equal\n", __func__); + return false; + } + + gen_loongarch_sync(0x10); + + func(dest, addr, val, ctx->mem_idx, mop); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +TRANS(ll_w, gen_ll, tcg_gen_qemu_ld32s) +TRANS(sc_w, gen_sc, MO_TESL) +TRANS(ll_d, gen_ll, tcg_gen_qemu_ld64) +TRANS(sc_d, gen_sc, MO_TEQ) +TRANS(amswap_w, gen_am, EXT_SIGN, tcg_gen_atomic_xchg_tl, MO_TESL) +TRANS(amswap_d, gen_am, EXT_NONE, tcg_gen_atomic_xchg_tl, MO_TEQ) +TRANS(amadd_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_add_tl, MO_TESL) +TRANS(amadd_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_add_tl, MO_TEQ) +TRANS(amand_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_and_tl, MO_TESL) +TRANS(amand_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_and_tl, MO_TEQ) +TRANS(amor_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_or_tl, MO_TESL) +TRANS(amor_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_or_tl, MO_TEQ) +TRANS(amxor_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_xor_tl, MO_TESL) +TRANS(amxor_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_xor_tl, MO_TEQ) +TRANS(ammax_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_smax_tl, MO_TESL) +TRANS(ammax_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_smax_tl, MO_TEQ) +TRANS(ammin_w, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_smin_tl, MO_TESL) +TRANS(ammin_d, gen_am, EXT_NONE, tcg_gen_atomic_fetch_smin_tl, MO_TEQ) +TRANS(ammax_wu, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_umax_tl, MO_TESL) +TRANS(ammax_du, gen_am, EXT_NONE, tcg_gen_atomic_fetch_umax_tl, MO_TEQ) +TRANS(ammin_wu, gen_am, EXT_SIGN, tcg_gen_atomic_fetch_umin_tl, MO_TESL) +TRANS(ammin_du, gen_am, EXT_NONE, tcg_gen_atomic_fetch_umin_tl, MO_TEQ) +TRANS(amswap_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_xchg_tl, MO_TESL) +TRANS(amswap_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_xchg_tl, MO_TEQ) +TRANS(amadd_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_add_tl, MO_TESL) +TRANS(amadd_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_add_tl, MO_TEQ) +TRANS(amand_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_and_tl, MO_TESL) +TRANS(amand_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_and_tl, MO_TEQ) +TRANS(amor_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_or_tl, MO_TESL) +TRANS(amor_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_or_tl, MO_TEQ) +TRANS(amxor_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_xor_tl, MO_TESL) +TRANS(amxor_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_xor_tl, MO_TEQ) +TRANS(ammax_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_smax_tl, MO_TESL) +TRANS(ammax_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_smax_tl, MO_TEQ) +TRANS(ammin_db_w, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_smin_tl, MO_TESL) +TRANS(ammin_db_d, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_smin_tl, MO_TEQ) +TRANS(ammax_db_wu, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_umax_tl, MO_TESL) +TRANS(ammax_db_du, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_umax_tl, MO_TEQ) +TRANS(ammin_db_wu, gen_am_db, EXT_SIGN, tcg_gen_atomic_fetch_umin_tl, MO_TESL) +TRANS(ammin_db_du, gen_am_db, EXT_NONE, tcg_gen_atomic_fetch_umin_tl, MO_TEQ) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 08fd232..574c055 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -216,3 +216,47 @@ stle_b 0011 10000111 11100 ..... ..... ..... @fmt_rdrjrk stle_h 0011 10000111 11101 ..... ..... ..... @fmt_rdrjrk stle_w 0011 10000111 11110 ..... ..... ..... @fmt_rdrjrk stle_d 0011 10000111 11111 ..... ..... ..... @fmt_rdrjrk + +# +# Fixed point atomic instruction +# +ll_w 0010 0000 .............. ..... ..... @fmt_rdrjsi14 +sc_w 0010 0001 .............. ..... ..... @fmt_rdrjsi14 +ll_d 0010 0010 .............. ..... ..... @fmt_rdrjsi14 +sc_d 0010 0011 .............. ..... ..... @fmt_rdrjsi14 +amswap_w 0011 10000110 00000 ..... ..... ..... @fmt_rdrjrk +amswap_d 0011 10000110 00001 ..... ..... ..... @fmt_rdrjrk +amadd_w 0011 10000110 00010 ..... ..... ..... @fmt_rdrjrk +amadd_d 0011 10000110 00011 ..... ..... ..... @fmt_rdrjrk +amand_w 0011 10000110 00100 ..... ..... ..... @fmt_rdrjrk +amand_d 0011 10000110 00101 ..... ..... ..... @fmt_rdrjrk +amor_w 0011 10000110 00110 ..... ..... ..... @fmt_rdrjrk +amor_d 0011 10000110 00111 ..... ..... ..... @fmt_rdrjrk +amxor_w 0011 10000110 01000 ..... ..... ..... @fmt_rdrjrk +amxor_d 0011 10000110 01001 ..... ..... ..... @fmt_rdrjrk +ammax_w 0011 10000110 01010 ..... ..... ..... @fmt_rdrjrk +ammax_d 0011 10000110 01011 ..... ..... ..... @fmt_rdrjrk +ammin_w 0011 10000110 01100 ..... ..... ..... @fmt_rdrjrk +ammin_d 0011 10000110 01101 ..... ..... ..... @fmt_rdrjrk +ammax_wu 0011 10000110 01110 ..... ..... ..... @fmt_rdrjrk +ammax_du 0011 10000110 01111 ..... ..... ..... @fmt_rdrjrk +ammin_wu 0011 10000110 10000 ..... ..... ..... @fmt_rdrjrk +ammin_du 0011 10000110 10001 ..... ..... ..... @fmt_rdrjrk +amswap_db_w 0011 10000110 10010 ..... ..... ..... @fmt_rdrjrk +amswap_db_d 0011 10000110 10011 ..... ..... ..... @fmt_rdrjrk +amadd_db_w 0011 10000110 10100 ..... ..... ..... @fmt_rdrjrk +amadd_db_d 0011 10000110 10101 ..... ..... ..... @fmt_rdrjrk +amand_db_w 0011 10000110 10110 ..... ..... ..... @fmt_rdrjrk +amand_db_d 0011 10000110 10111 ..... ..... ..... @fmt_rdrjrk +amor_db_w 0011 10000110 11000 ..... ..... ..... @fmt_rdrjrk +amor_db_d 0011 10000110 11001 ..... ..... ..... @fmt_rdrjrk +amxor_db_w 0011 10000110 11010 ..... ..... ..... @fmt_rdrjrk +amxor_db_d 0011 10000110 11011 ..... ..... ..... @fmt_rdrjrk +ammax_db_w 0011 10000110 11100 ..... ..... ..... @fmt_rdrjrk +ammax_db_d 0011 10000110 11101 ..... ..... ..... @fmt_rdrjrk +ammin_db_w 0011 10000110 11110 ..... ..... ..... @fmt_rdrjrk +ammin_db_d 0011 10000110 11111 ..... ..... ..... @fmt_rdrjrk +ammax_db_wu 0011 10000111 00000 ..... ..... ..... @fmt_rdrjrk +ammax_db_du 0011 10000111 00001 ..... ..... ..... @fmt_rdrjrk +ammin_db_wu 0011 10000111 00010 ..... ..... ..... @fmt_rdrjrk +ammin_db_du 0011 10000111 00011 ..... ..... ..... @fmt_rdrjrk diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 2695c0b..a6482c3 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -191,6 +191,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, #include "insn_trans/trans_shift.c" #include "insn_trans/trans_bit.c" #include "insn_trans/trans_memory.c" +#include "insn_trans/trans_atomic.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Fri Aug 27 07:14:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461471 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 85917C4320A for ; Fri, 27 Aug 2021 07:55: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 BBF1760F45 for ; Fri, 27 Aug 2021 07:55:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org BBF1760F45 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]:57646 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWiI-0001zD-T1 for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:55:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53208) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5C-0000qC-Qi for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:22 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59610 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5A-0003H3-BR for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:22 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S11; Fri, 27 Aug 2021 15:15:15 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 09/19] target/loongarch: Add fixed point extra instruction translation Date: Fri, 27 Aug 2021 15:14:44 +0800 Message-Id: <1630048494-2143-10-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S11 X-Coremail-Antispam: 1UD129KBjvJXoWxtrWUtw18uw1UXw18AF48Crg_yoW3Ary8pF 18CryUGr48Jry7Z3s5tw45tr15Xr4fuF47X3yftw1rAF17XF1DJr48t3yakFWUJw1DXryj 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/helper.h | 4 ++ target/loongarch/insn_trans/trans_extra.c | 88 +++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 25 +++++++++ target/loongarch/op_helper.c | 26 +++++++++ target/loongarch/translate.c | 1 + 5 files changed, 144 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_extra.c 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..d07e791 --- /dev/null +++ b/target/loongarch/insn_trans/trans_extra.c @@ -0,0 +1,88 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool trans_break(DisasContext *ctx, arg_break *a) +{ + generate_exception(ctx, EXCP_BREAK); + return true; +} + +static bool trans_syscall(DisasContext *ctx, arg_syscall *a) +{ + generate_exception(ctx, EXCP_SYSCALL); + return true; +} + +static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + gen_helper_asrtle_d(cpu_env, src1, src2); + return true; +} + +static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + gen_helper_asrtgt_d(cpu_env, src1, src2); + return true; +} + +static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a) +{ + tcg_gen_movi_tl(cpu_gpr[a->rd], 0); + return true; +} + +static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a) +{ + tcg_gen_movi_tl(cpu_gpr[a->rd], 0); + return true; +} + +static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) +{ + tcg_gen_movi_tl(cpu_gpr[a->rd], 0); + return true; +} + +static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + gen_helper_cpucfg(dest, cpu_env, src1); + return true; +} + +static bool gen_crc(DisasContext *ctx, arg_fmt_rdrjrk *a, + void (*func)(TCGv, TCGv, TCGv, TCGv), + TCGv tsz) +{ + ctx->dst_ext = EXT_SIGN; + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + + func(dest, src2, src1, tsz); + + gen_set_gpr(ctx, a->rd, dest); + return true; +} + +TRANS(crc_w_b_w, gen_crc, gen_helper_crc32, tcg_constant_tl(1)) +TRANS(crc_w_h_w, gen_crc, gen_helper_crc32, tcg_constant_tl(2)) +TRANS(crc_w_w_w, gen_crc, gen_helper_crc32, tcg_constant_tl(4)) +TRANS(crc_w_d_w, gen_crc, gen_helper_crc32, tcg_constant_tl(8)) +TRANS(crcc_w_b_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(1)) +TRANS(crcc_w_h_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(2)) +TRANS(crcc_w_w_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(4)) +TRANS(crcc_w_d_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(8)) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 574c055..66bc314 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -27,6 +27,7 @@ %si14 10:s14 %hint 0:5 %whint 0:15 +%code 0:15 # # Argument sets @@ -46,6 +47,8 @@ &fmt_rdrjsi14 rd rj si14 &fmt_hintrjsi12 hint rj si12 &fmt_whint whint +&fmt_rjrk rj rk +&fmt_code code # # Formats @@ -65,6 +68,8 @@ @fmt_hintrjsi12 .... ...... ............ ..... ..... &fmt_hintrjsi12 %hint %rj %si12 @fmt_whint .... ........ ..... ............... &fmt_whint %whint @fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14 +@fmt_rjrk .... ........ ..... ..... ..... ..... &fmt_rjrk %rj %rk +@fmt_code .... ........ ..... ............... &fmt_code %code # # Fixed point arithmetic operation instruction @@ -260,3 +265,23 @@ ammax_db_wu 0011 10000111 00000 ..... ..... ..... @fmt_rdrjrk ammax_db_du 0011 10000111 00001 ..... ..... ..... @fmt_rdrjrk ammin_db_wu 0011 10000111 00010 ..... ..... ..... @fmt_rdrjrk ammin_db_du 0011 10000111 00011 ..... ..... ..... @fmt_rdrjrk + +# +# Fixed point extra instruction +# +crc_w_b_w 0000 00000010 01000 ..... ..... ..... @fmt_rdrjrk +crc_w_h_w 0000 00000010 01001 ..... ..... ..... @fmt_rdrjrk +crc_w_w_w 0000 00000010 01010 ..... ..... ..... @fmt_rdrjrk +crc_w_d_w 0000 00000010 01011 ..... ..... ..... @fmt_rdrjrk +crcc_w_b_w 0000 00000010 01100 ..... ..... ..... @fmt_rdrjrk +crcc_w_h_w 0000 00000010 01101 ..... ..... ..... @fmt_rdrjrk +crcc_w_w_w 0000 00000010 01110 ..... ..... ..... @fmt_rdrjrk +crcc_w_d_w 0000 00000010 01111 ..... ..... ..... @fmt_rdrjrk +break 0000 00000010 10100 ............... @fmt_code +syscall 0000 00000010 10110 ............... @fmt_code +asrtle_d 0000 00000000 00010 ..... ..... 00000 @fmt_rjrk +asrtgt_d 0000 00000000 00011 ..... ..... 00000 @fmt_rjrk +rdtimel_w 0000 00000000 00000 11000 ..... ..... @fmt_rdrj +rdtimeh_w 0000 00000000 00000 11001 ..... ..... @fmt_rdrj +rdtime_d 0000 00000000 00000 11010 ..... ..... @fmt_rdrj +cpucfg 0000 00000000 00000 11011 ..... ..... @fmt_rdrj diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c index a4ffaf9..0a1a47b 100644 --- a/target/loongarch/op_helper.c +++ b/target/loongarch/op_helper.c @@ -14,6 +14,8 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "internals.h" +#include "qemu/crc32c.h" +#include /* 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 a6482c3..77b0180 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -192,6 +192,7 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, #include "insn_trans/trans_bit.c" #include "insn_trans/trans_memory.c" #include "insn_trans/trans_atomic.c" +#include "insn_trans/trans_extra.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Fri Aug 27 07:14:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461395 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 E0EDDC432BE for ; Fri, 27 Aug 2021 07:31:14 +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 8FF3460F25 for ; Fri, 27 Aug 2021 07:31:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 8FF3460F25 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]:40488 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWKX-0004gz-R1 for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:31:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53232) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5E-0000sk-Lz for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:24 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59632 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5B-0003Hw-5y for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:24 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S12; Fri, 27 Aug 2021 15:15:17 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 10/19] target/loongarch: Add floating point arithmetic instruction translation Date: Fri, 27 Aug 2021 15:14:45 +0800 Message-Id: <1630048494-2143-11-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S12 X-Coremail-Antispam: 1UD129KBjvAXoWfXw4DJry7CF1kKFWfCw1kuFg_yoW8KrWUWo W3uF15Ar48G3yfuF98KwnYvr47XryUZ3ZxJrWrZr13Ka4xGry7KF15G3sYya1fKrs5trW5 Jrn3A3W5JwnIvr93n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/cpu.c | 1 + target/loongarch/fpu_helper.c | 438 +++++++++++++++++++++++++++++ target/loongarch/helper.h | 42 +++ target/loongarch/insn_trans/trans_farith.c | 79 ++++++ target/loongarch/insns.decode | 56 ++++ target/loongarch/internals.h | 2 + target/loongarch/translate.c | 11 +- target/loongarch/translate.h | 2 + 8 files changed, 630 insertions(+), 1 deletion(-) create mode 100644 target/loongarch/fpu_helper.c create mode 100644 target/loongarch/insn_trans/trans_farith.c diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index b89bf51..487df05 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -143,6 +143,7 @@ static void loongarch_cpu_reset(DeviceState *dev) env->fcsr0_mask = 0x1f1f031f; env->fcsr0 = 0x0; + restore_fp_status(env); cs->exception_index = EXCP_NONE; } diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c new file mode 100644 index 0000000..c3bee57 --- /dev/null +++ b/target/loongarch/fpu_helper.c @@ -0,0 +1,438 @@ +/* + * LoongArch float point emulation helpers for qemu + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "fpu/softfloat.h" +#include "translate.h" +#include "internals.h" + +#define FLOAT_TO_INT32_OVERFLOW 0x7fffffff +#define FLOAT_TO_INT64_OVERFLOW 0x7fffffffffffffffULL + +static inline uint64_t nanbox_s(float32 fp) +{ + return fp | MAKE_64BIT_MASK(32, 32); +} + +/* convert loongarch rounding mode in fcsr0 to IEEE library */ +const FloatRoundMode ieee_rm[4] = { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down +}; + +void restore_fp_status(CPULoongArchState *env) +{ + set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3], + &env->fp_status); + set_flush_to_zero(0, &env->fp_status); +} + +int ieee_ex_to_loongarch(int xcpt) +{ + int ret = 0; + if (xcpt) { + if (xcpt & float_flag_invalid) { + ret |= FP_INVALID; + } + if (xcpt & float_flag_overflow) { + ret |= FP_OVERFLOW; + } + if (xcpt & float_flag_underflow) { + ret |= FP_UNDERFLOW; + } + if (xcpt & float_flag_divbyzero) { + ret |= FP_DIV0; + } + if (xcpt & float_flag_inexact) { + ret |= FP_INEXACT; + } + } + return ret; +} + +static inline void update_fcsr0(CPULoongArchState *env, uintptr_t pc) +{ + int flags = ieee_ex_to_loongarch(get_float_exception_flags( + &env->fp_status)); + + SET_FP_CAUSE(env->fcsr0, flags); + if (flags) { + set_float_exception_flags(0, &env->fp_status); + + if (GET_FP_ENABLE(env->fcsr0) & flags) { + do_raise_exception(env, EXCP_FPE, pc); + } else { + UPDATE_FP_FLAGS(env->fcsr0, flags); + } + } +} + +uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_add(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_sub(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_mul(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_div(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmax_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_maxnum((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmax_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_maxnum(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmin_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_minnum((uint32_t)fj, (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmin_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_minnum(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_maxnummag((uint32_t)fj, + (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_maxnummag(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = nanbox_s(float32_minnummag((uint32_t)fj, + (uint32_t)fk, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + + fd = float64_minnummag(fj, fk, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + int32_t n = (int32_t)fk; + + fd = nanbox_s(float32_scalbn((uint32_t)fj, + n > 0x200 ? 0x200 : + n < -0x200 ? -0x200 : n, + &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ + uint64_t fd; + int64_t n = (int64_t)fk; + + fd = float64_scalbn(fj, + n > 0x1000 ? 0x1000 : + n < -0x1000 ? -0x1000 : n, + &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fabs_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(float32_abs((uint32_t)fj)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fabs_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_abs(fj); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fneg_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(float32_chs((uint32_t)fj)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fneg_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_chs(fj); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_sqrt(fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_div(float64_one, fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + uint32_t fp; + + fp = float32_sqrt((uint32_t)fj, &env->fp_status); + fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fp, fd; + + fp = float64_sqrt(fj, &env->fp_status); + fd = float64_div(float64_one, fp, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + uint32_t fp; + float_status *status = &env->fp_status; + FloatRoundMode old_mode = get_float_rounding_mode(status); + + set_float_exception_flags(0, status); + set_float_rounding_mode(float_round_down, status); + fp = float32_log2((uint32_t)fj, status); + fd = nanbox_s(float32_round_to_int(fp, status)); + set_float_rounding_mode(old_mode, status); + set_float_exception_flags(get_float_exception_flags(status) & + (~float_flag_inexact), status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + float_status *status = &env->fp_status; + FloatRoundMode old_mode = get_float_rounding_mode(status); + + set_float_exception_flags(0, status); + set_float_rounding_mode(float_round_down, status); + fd = float64_log2(fj, status); + fd = float64_round_to_int(fd, status); + set_float_rounding_mode(old_mode, status); + set_float_exception_flags(get_float_exception_flags(status) & + (~float_flag_inexact), status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj) +{ + float32 f = fj; + bool sign = float32_is_neg(f); + + if (float32_is_infinity(f)) { + return sign ? 1 << 0 : 1 << 7; + } else if (float32_is_zero(f)) { + return sign ? 1 << 3 : 1 << 4; + } else if (float32_is_zero_or_denormal(f)) { + return sign ? 1 << 2 : 1 << 5; + } else if (float32_is_any_nan(f)) { + float_status s = { }; /* for snan_bit_is_one */ + return float32_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; + } else { + return sign ? 1 << 1 : 1 << 6; + } +} + +uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj) +{ + float64 f = fj; + bool sign = float64_is_neg(f); + + if (float64_is_infinity(f)) { + return sign ? 1 << 0 : 1 << 7; + } else if (float64_is_zero(f)) { + return sign ? 1 << 3 : 1 << 4; + } else if (float64_is_zero_or_denormal(f)) { + return sign ? 1 << 2 : 1 << 5; + } else if (float64_is_any_nan(f)) { + float_status s = { }; /* for snan_bit_is_one */ + return float64_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; + } else { + return sign ? 1 << 1 : 1 << 6; + } +} + +uint64_t helper_fmuladd_s(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint64_t fa, uint32_t flag) +{ + uint64_t fd; + + fd = nanbox_s(float32_muladd((uint32_t)fj, (uint32_t)fk, + (uint32_t)fa, flag, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint64_t fa, uint32_t flag) +{ + uint64_t fd; + + fd = float64_muladd(fj, fk, fa, flag, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index e4b4595..62c262e 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -18,3 +18,45 @@ DEF_HELPER_3(asrtgt_d, void, env, tl, tl) DEF_HELPER_3(crc32, tl, tl, tl, tl) DEF_HELPER_3(crc32c, tl, tl, tl, tl) DEF_HELPER_2(cpucfg, tl, env, tl) + +/* Floating-point helper */ +DEF_HELPER_3(fadd_s, i64, env, i64, i64) +DEF_HELPER_3(fadd_d, i64, env, i64, i64) +DEF_HELPER_3(fsub_s, i64, env, i64, i64) +DEF_HELPER_3(fsub_d, i64, env, i64, i64) +DEF_HELPER_3(fmul_s, i64, env, i64, i64) +DEF_HELPER_3(fmul_d, i64, env, i64, i64) +DEF_HELPER_3(fdiv_s, i64, env, i64, i64) +DEF_HELPER_3(fdiv_d, i64, env, i64, i64) +DEF_HELPER_3(fmax_s, i64, env, i64, i64) +DEF_HELPER_3(fmax_d, i64, env, i64, i64) +DEF_HELPER_3(fmaxa_s, i64, env, i64, i64) +DEF_HELPER_3(fmaxa_d, i64, env, i64, i64) +DEF_HELPER_3(fmin_s, i64, env, i64, i64) +DEF_HELPER_3(fmin_d, i64, env, i64, i64) +DEF_HELPER_3(fmina_s, i64, env, i64, i64) +DEF_HELPER_3(fmina_d, i64, env, i64, i64) + +DEF_HELPER_5(fmuladd_s, i64, env, i64, i64, i64, i32) +DEF_HELPER_5(fmuladd_d, i64, env, i64, i64, i64, i32) + +DEF_HELPER_3(fscaleb_s, i64, env, i64, i64) +DEF_HELPER_3(fscaleb_d, i64, env, i64, i64) + +DEF_HELPER_2(flogb_s, i64, env, i64) +DEF_HELPER_2(flogb_d, i64, env, i64) + +DEF_HELPER_2(fabs_s, i64, env, i64) +DEF_HELPER_2(fabs_d, i64, env, i64) +DEF_HELPER_2(fneg_s, i64, env, i64) +DEF_HELPER_2(fneg_d, i64, env, i64) + +DEF_HELPER_2(fsqrt_s, i64, env, i64) +DEF_HELPER_2(fsqrt_d, i64, env, i64) +DEF_HELPER_2(frsqrt_s, i64, env, i64) +DEF_HELPER_2(frsqrt_d, i64, env, i64) +DEF_HELPER_2(frecip_s, i64, env, i64) +DEF_HELPER_2(frecip_d, i64, env, i64) + +DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64) +DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64) diff --git a/target/loongarch/insn_trans/trans_farith.c b/target/loongarch/insn_trans/trans_farith.c new file mode 100644 index 0000000..8015d3b --- /dev/null +++ b/target/loongarch/insn_trans/trans_farith.c @@ -0,0 +1,79 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_f3(DisasContext *ctx, arg_fmt_fdfjfk *a, + void (*func)(TCGv, TCGv_env, TCGv, TCGv)) +{ + func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk]); + return true; +} + +static bool gen_muladd(DisasContext *ctx, arg_fmt_fdfjfkfa *a, + void (*func)(TCGv, TCGv_env, TCGv, TCGv, TCGv, TCGv_i32), + int flag) +{ + TCGv_i32 tflag = tcg_constant_i32(flag); + func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], cpu_fpr[a->fa], tflag); + return true; +} + +static bool trans_fcopysign_s(DisasContext *ctx, arg_fmt_fdfjfk *a) +{ + tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 31); + return true; +} + +static bool trans_fcopysign_d(DisasContext *ctx, arg_fmt_fdfjfk *a) +{ + tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 63); + return true; +} + +TRANS(fadd_s, gen_f3, gen_helper_fadd_s) +TRANS(fadd_d, gen_f3, gen_helper_fadd_d) +TRANS(fsub_s, gen_f3, gen_helper_fsub_s) +TRANS(fsub_d, gen_f3, gen_helper_fsub_d) +TRANS(fmul_s, gen_f3, gen_helper_fmul_s) +TRANS(fmul_d, gen_f3, gen_helper_fmul_d) +TRANS(fdiv_s, gen_f3, gen_helper_fdiv_s) +TRANS(fdiv_d, gen_f3, gen_helper_fdiv_d) +TRANS(fmax_s, gen_f3, gen_helper_fmax_s) +TRANS(fmax_d, gen_f3, gen_helper_fmax_d) +TRANS(fmin_s, gen_f3, gen_helper_fmin_s) +TRANS(fmin_d, gen_f3, gen_helper_fmin_d) +TRANS(fmaxa_s, gen_f3, gen_helper_fmaxa_s) +TRANS(fmaxa_d, gen_f3, gen_helper_fmaxa_d) +TRANS(fmina_s, gen_f3, gen_helper_fmina_s) +TRANS(fmina_d, gen_f3, gen_helper_fmina_d) +TRANS(fscaleb_s, gen_f3, gen_helper_fscaleb_s) +TRANS(fscaleb_d, gen_f3, gen_helper_fscaleb_d) +TRANS(fabs_s, gen_f2, gen_helper_fabs_s) +TRANS(fabs_d, gen_f2, gen_helper_fabs_d) +TRANS(fneg_s, gen_f2, gen_helper_fneg_s) +TRANS(fneg_d, gen_f2, gen_helper_fneg_d) +TRANS(fsqrt_s, gen_f2, gen_helper_fsqrt_s) +TRANS(fsqrt_d, gen_f2, gen_helper_fsqrt_d) +TRANS(frecip_s, gen_f2, gen_helper_frecip_s) +TRANS(frecip_d, gen_f2, gen_helper_frecip_d) +TRANS(frsqrt_s, gen_f2, gen_helper_frsqrt_s) +TRANS(frsqrt_d, gen_f2, gen_helper_frsqrt_d) +TRANS(flogb_s, gen_f2, gen_helper_flogb_s) +TRANS(flogb_d, gen_f2, gen_helper_flogb_d) +TRANS(fclass_s, gen_f2, gen_helper_fclass_s) +TRANS(fclass_d, gen_f2, gen_helper_fclass_d) +TRANS(fmadd_s, gen_muladd, gen_helper_fmuladd_s, 0) +TRANS(fmadd_d, gen_muladd, gen_helper_fmuladd_d, 0) +TRANS(fmsub_s, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_c) +TRANS(fmsub_d, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_c) +TRANS(fnmadd_s, gen_muladd, gen_helper_fmuladd_s, + float_muladd_negate_product | float_muladd_negate_c) +TRANS(fnmadd_d, gen_muladd, gen_helper_fmuladd_d, + float_muladd_negate_product | float_muladd_negate_c) +TRANS(fnmsub_s, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_product) +TRANS(fnmsub_d, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_product) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 66bc314..9e6a727 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -28,6 +28,10 @@ %hint 0:5 %whint 0:15 %code 0:15 +%fd 0:5 +%fj 5:5 +%fk 10:5 +%fa 15:5 # # Argument sets @@ -49,6 +53,9 @@ &fmt_whint whint &fmt_rjrk rj rk &fmt_code code +&fmt_fdfjfk fd fj fk +&fmt_fdfjfkfa fd fj fk fa +&fmt_fdfj fd fj # # Formats @@ -70,6 +77,9 @@ @fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14 @fmt_rjrk .... ........ ..... ..... ..... ..... &fmt_rjrk %rj %rk @fmt_code .... ........ ..... ............... &fmt_code %code +@fmt_fdfjfk .... ........ ..... ..... ..... ..... &fmt_fdfjfk %fd %fj %fk +@fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa +@fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj # # Fixed point arithmetic operation instruction @@ -285,3 +295,49 @@ rdtimel_w 0000 00000000 00000 11000 ..... ..... @fmt_rdrj rdtimeh_w 0000 00000000 00000 11001 ..... ..... @fmt_rdrj rdtime_d 0000 00000000 00000 11010 ..... ..... @fmt_rdrj cpucfg 0000 00000000 00000 11011 ..... ..... @fmt_rdrj + +# +# Floating point arithmetic operation instruction +# +fadd_s 0000 00010000 00001 ..... ..... ..... @fmt_fdfjfk +fadd_d 0000 00010000 00010 ..... ..... ..... @fmt_fdfjfk +fsub_s 0000 00010000 00101 ..... ..... ..... @fmt_fdfjfk +fsub_d 0000 00010000 00110 ..... ..... ..... @fmt_fdfjfk +fmul_s 0000 00010000 01001 ..... ..... ..... @fmt_fdfjfk +fmul_d 0000 00010000 01010 ..... ..... ..... @fmt_fdfjfk +fdiv_s 0000 00010000 01101 ..... ..... ..... @fmt_fdfjfk +fdiv_d 0000 00010000 01110 ..... ..... ..... @fmt_fdfjfk +fmadd_s 0000 10000001 ..... ..... ..... ..... @fmt_fdfjfkfa +fmadd_d 0000 10000010 ..... ..... ..... ..... @fmt_fdfjfkfa +fmsub_s 0000 10000101 ..... ..... ..... ..... @fmt_fdfjfkfa +fmsub_d 0000 10000110 ..... ..... ..... ..... @fmt_fdfjfkfa +fnmadd_s 0000 10001001 ..... ..... ..... ..... @fmt_fdfjfkfa +fnmadd_d 0000 10001010 ..... ..... ..... ..... @fmt_fdfjfkfa +fnmsub_s 0000 10001101 ..... ..... ..... ..... @fmt_fdfjfkfa +fnmsub_d 0000 10001110 ..... ..... ..... ..... @fmt_fdfjfkfa +fmax_s 0000 00010000 10001 ..... ..... ..... @fmt_fdfjfk +fmax_d 0000 00010000 10010 ..... ..... ..... @fmt_fdfjfk +fmin_s 0000 00010000 10101 ..... ..... ..... @fmt_fdfjfk +fmin_d 0000 00010000 10110 ..... ..... ..... @fmt_fdfjfk +fmaxa_s 0000 00010000 11001 ..... ..... ..... @fmt_fdfjfk +fmaxa_d 0000 00010000 11010 ..... ..... ..... @fmt_fdfjfk +fmina_s 0000 00010000 11101 ..... ..... ..... @fmt_fdfjfk +fmina_d 0000 00010000 11110 ..... ..... ..... @fmt_fdfjfk +fabs_s 0000 00010001 01000 00001 ..... ..... @fmt_fdfj +fabs_d 0000 00010001 01000 00010 ..... ..... @fmt_fdfj +fneg_s 0000 00010001 01000 00101 ..... ..... @fmt_fdfj +fneg_d 0000 00010001 01000 00110 ..... ..... @fmt_fdfj +fsqrt_s 0000 00010001 01000 10001 ..... ..... @fmt_fdfj +fsqrt_d 0000 00010001 01000 10010 ..... ..... @fmt_fdfj +frecip_s 0000 00010001 01000 10101 ..... ..... @fmt_fdfj +frecip_d 0000 00010001 01000 10110 ..... ..... @fmt_fdfj +frsqrt_s 0000 00010001 01000 11001 ..... ..... @fmt_fdfj +frsqrt_d 0000 00010001 01000 11010 ..... ..... @fmt_fdfj +fscaleb_s 0000 00010001 00001 ..... ..... ..... @fmt_fdfjfk +fscaleb_d 0000 00010001 00010 ..... ..... ..... @fmt_fdfjfk +flogb_s 0000 00010001 01000 01001 ..... ..... @fmt_fdfj +flogb_d 0000 00010001 01000 01010 ..... ..... @fmt_fdfj +fcopysign_s 0000 00010001 00101 ..... ..... ..... @fmt_fdfjfk +fcopysign_d 0000 00010001 00110 ..... ..... ..... @fmt_fdfjfk +fclass_s 0000 00010001 01000 01101 ..... ..... @fmt_fdfj +fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index 1052cb6..096a4a7 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -19,4 +19,6 @@ void QEMU_NORETURN do_raise_exception(CPULoongArchState *env, const char *loongarch_exception_name(int32_t exception); +void restore_fp_status(CPULoongArchState *env); + #endif diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 77b0180..a4a9e9a 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -16,7 +16,7 @@ #include "exec/translator.h" #include "exec/log.h" #include "qemu/qemu-print.h" -#include "fpu_helper.h" +#include "fpu/softfloat.h" #include "translate.h" #include "internals.h" @@ -187,12 +187,21 @@ static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, return true; } +/* fmt fd fj */ +static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a, + void (*func)(TCGv, TCGv_env, TCGv)) +{ + func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj]); + return true; +} + #include "insn_trans/trans_arith.c" #include "insn_trans/trans_shift.c" #include "insn_trans/trans_bit.c" #include "insn_trans/trans_memory.c" #include "insn_trans/trans_atomic.c" #include "insn_trans/trans_extra.c" +#include "insn_trans/trans_farith.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h index f064fdd..99ab329 100644 --- a/target/loongarch/translate.h +++ b/target/loongarch/translate.h @@ -44,4 +44,6 @@ extern TCGv cpu_gpr[32], cpu_pc; extern TCGv_i32 cpu_fscr0; extern TCGv_i64 cpu_fpr[32]; +int ieee_ex_to_loongarch(int xcpt); + #endif From patchwork Fri Aug 27 07:14:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461397 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 43774C4320A for ; Fri, 27 Aug 2021 07:33:53 +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 C94D160F92 for ; Fri, 27 Aug 2021 07:33:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C94D160F92 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]:43916 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWN5-0006zk-Vb for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:33:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53234) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5F-0000vw-TX for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:26 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59642 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5B-0003Jf-Rg for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:25 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S13; Fri, 27 Aug 2021 15:15:18 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 11/19] target/loongarch: Add floating point comparison instruction translation Date: Fri, 27 Aug 2021 15:14:46 +0800 Message-Id: <1630048494-2143-12-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S13 X-Coremail-Antispam: 1UD129KBjvAXoW3Kr4xuryUKFW3Cry5CFyUJrb_yoW8Gw1xWo W5Gr15Cr4ft3sxWr90yas0qrsrJ3WxJwsrta90gas0ka4fGr12ka1aq34fAayfWr4I9Fy5 A39rXa43twsrAr97n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/fpu_helper.c | 110 ++++++++++++ target/loongarch/helper.h | 9 + target/loongarch/insn_trans/trans_fcmp.c | 279 +++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 10 ++ target/loongarch/translate.c | 1 + target/loongarch/translate.h | 5 + 6 files changed, 414 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_fcmp.c diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c index c3bee57..bad7238 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -436,3 +436,113 @@ uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj, update_fcsr0(env, GETPC()); return fd; } + +/* fcmp_cXXX_s */ +uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ + uint32_t t0, t1; + uint64_t cmp = 0; + t0 = (uint32_t)fj; + t1 = (uint32_t)fk; + + if (flags) { + if (flags & FCMP_LT) { + cmp |= float32_lt_quiet(t0, t1, &env->fp_status); + } + if (flags & FCMP_EQ) { + cmp |= float32_eq_quiet(t0, t1, &env->fp_status); + } + if (flags & FCMP_GT) { + cmp |= float32_lt_quiet(t1, t0, &env->fp_status); + } + if (flags & FCMP_UN) { + cmp |= float32_unordered_quiet(t1, t0, &env->fp_status); + } + } else { + cmp = (float32_unordered_quiet(t1, t0, &env->fp_status), 0); + } + update_fcsr0(env, GETPC()); + return cmp; +} + +/* fcmp_sXXX_s */ +uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ + uint32_t t0, t1; + uint64_t cmp = 0; + t0 = (uint32_t)fj; + t1 = (uint32_t)fk; + + if (flags) { + if (flags & FCMP_LT) { + cmp |= float32_lt(t0, t1, &env->fp_status); + } + if (flags & FCMP_EQ) { + cmp |= float32_eq(t0, t1, &env->fp_status); + } + if (flags & FCMP_GT) { + cmp |= float32_lt(t1, t0, &env->fp_status); + } + if (flags & FCMP_UN) { + cmp |= float32_unordered(t1, t0, &env->fp_status); + } + } else { + cmp = (float32_unordered(t1, t0, &env->fp_status), 0); + } + update_fcsr0(env, GETPC()); + return cmp; +} + +/* fcmp_cXXX_d */ +uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ + uint64_t cmp = 0; + + if (flags) { + if (flags & FCMP_LT) { + cmp |= float64_lt_quiet(fj, fk, &env->fp_status); + } + if (flags & FCMP_EQ) { + cmp |= float64_eq_quiet(fj, fk, &env->fp_status); + } + if (flags & FCMP_GT) { + cmp |= float64_lt_quiet(fk, fj, &env->fp_status); + } + if (flags & FCMP_UN) { + cmp |= float64_unordered_quiet(fk, fj, &env->fp_status); + } + } else { + cmp = (float64_unordered_quiet(fk, fj, &env->fp_status), 0); + } + update_fcsr0(env, GETPC()); + return cmp; +} + +/* fcmp_sXXX_d */ +uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ + uint64_t cmp = 0; + + if (flags) { + if (flags & FCMP_LT) { + cmp |= float64_lt(fj, fk, &env->fp_status); + } + if (flags & FCMP_EQ) { + cmp |= float64_eq(fj, fk, &env->fp_status); + } + if (flags & FCMP_GT) { + cmp |= float64_lt(fk, fj, &env->fp_status); + } + if (flags & FCMP_UN) { + cmp |= float64_unordered(fk, fj, &env->fp_status); + } + } else { + cmp = (float64_unordered(fk, fj, &env->fp_status), 0); + } + update_fcsr0(env, GETPC()); + return cmp; +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 62c262e..5f6e60d 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -60,3 +60,12 @@ DEF_HELPER_2(frecip_d, i64, env, i64) DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64) DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64) + +/* fcmp.cXXX.s */ +DEF_HELPER_4(fcmp_c_s, i64, env, i64, i64, i32) +/* fcmp.sXXX.s */ +DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32) +/* fcmp.cXXX.d */ +DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32) +/* fcmp.sXXX.d */ +DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32) diff --git a/target/loongarch/insn_trans/trans_fcmp.c b/target/loongarch/insn_trans/trans_fcmp.c new file mode 100644 index 0000000..e9d7c3b --- /dev/null +++ b/target/loongarch/insn_trans/trans_fcmp.c @@ -0,0 +1,279 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a) +{ + TCGv var = tcg_temp_new(); + TCGv_i32 flags = NULL; + + switch (a->fcond) { + /* caf */ + case 0: + flags = tcg_constant_i32(0); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* saf */ + case 1: + flags = tcg_constant_i32(0); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* clt */ + case 2: + flags = tcg_constant_i32(FCMP_LT); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* slt */ + case 3: + flags = tcg_constant_i32(FCMP_LT); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* ceq */ + case 4: + flags = tcg_constant_i32(FCMP_EQ); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* seq */ + case 5: + flags = tcg_constant_i32(FCMP_EQ); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* cle */ + case 6: + flags = tcg_constant_i32(FCMP_LT | FCMP_EQ); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* sle */ + case 7: + flags = tcg_constant_i32(FCMP_LT | FCMP_EQ); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* cun */ + case 8: + flags = tcg_constant_i32(FCMP_UN); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* sun */ + case 9: + flags = tcg_constant_i32(FCMP_UN); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* cult */ + case 10: + flags = tcg_constant_i32(FCMP_UN | FCMP_LT); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* sult */ + case 11: + flags = tcg_constant_i32(FCMP_UN | FCMP_LT); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* cueq */ + case 12: + flags = tcg_constant_i32(FCMP_UN | FCMP_EQ); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* sueq */ + case 13: + flags = tcg_constant_i32(FCMP_UN | FCMP_EQ); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* cule */ + case 14: + flags = tcg_constant_i32(FCMP_UN | FCMP_LT | FCMP_EQ); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* sule */ + case 15: + flags = tcg_constant_i32(FCMP_UN | FCMP_LT | FCMP_EQ); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* cne */ + case 16: + flags = tcg_constant_i32(FCMP_GT | FCMP_LT); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* sne */ + case 17: + flags = tcg_constant_i32(FCMP_GT | FCMP_LT); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* cor */ + case 20: + flags = tcg_constant_i32(FCMP_GT | FCMP_LT | FCMP_EQ); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* sor */ + case 21: + flags = tcg_constant_i32(FCMP_GT | FCMP_LT | FCMP_EQ); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* cune */ + case 24: + flags = tcg_constant_i32(FCMP_UN | FCMP_GT | FCMP_LT); + gen_helper_fcmp_c_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + /* sune */ + case 25: + flags = tcg_constant_i32(FCMP_UN | FCMP_GT | FCMP_LT); + gen_helper_fcmp_s_s(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + default: + abort(); + } + + tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + tcg_temp_free(var); + return true; +} + +static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a) +{ + TCGv var = tcg_temp_new(); + TCGv_i32 flags = NULL; + + switch (a->fcond) { + case 0: + flags = tcg_constant_i32(0); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 1: + flags = tcg_constant_i32(0); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 2: + flags = tcg_constant_i32(FCMP_LT); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 3: + flags = tcg_constant_i32(FCMP_LT); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 4: + flags = tcg_constant_i32(FCMP_EQ); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 5: + flags = tcg_constant_i32(FCMP_EQ); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 6: + flags = tcg_constant_i32(FCMP_LT | FCMP_EQ); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 7: + flags = tcg_constant_i32(FCMP_LT | FCMP_EQ); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 8: + flags = tcg_constant_i32(FCMP_UN); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 9: + flags = tcg_constant_i32(FCMP_UN); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 10: + flags = tcg_constant_i32(FCMP_UN | FCMP_LT); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 11: + flags = tcg_constant_i32(FCMP_UN | FCMP_LT); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 12: + flags = tcg_constant_i32(FCMP_UN | FCMP_EQ); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 13: + flags = tcg_constant_i32(FCMP_UN | FCMP_EQ); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 14: + flags = tcg_constant_i32(FCMP_UN | FCMP_LT | FCMP_EQ); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 15: + flags = tcg_constant_i32(FCMP_UN | FCMP_LT | FCMP_EQ); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 16: + flags = tcg_constant_i32(FCMP_GT | FCMP_LT); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 17: + flags = tcg_constant_i32(FCMP_GT | FCMP_LT); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 20: + flags = tcg_constant_i32(FCMP_GT | FCMP_LT | FCMP_EQ); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 21: + flags = tcg_constant_i32(FCMP_GT | FCMP_LT | FCMP_EQ); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 24: + flags = tcg_constant_i32(FCMP_UN | FCMP_GT | FCMP_LT); + gen_helper_fcmp_c_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + case 25: + flags = tcg_constant_i32(FCMP_UN | FCMP_GT | FCMP_LT); + gen_helper_fcmp_s_d(var, cpu_env, cpu_fpr[a->fj], + cpu_fpr[a->fk], flags); + break; + default: + abort(); + } + + tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + tcg_temp_free(var); + return true; +} diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 9e6a727..8aadcfd 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -32,6 +32,8 @@ %fj 5:5 %fk 10:5 %fa 15:5 +%cd 0:3 +%fcond 15:5 # # Argument sets @@ -56,6 +58,7 @@ &fmt_fdfjfk fd fj fk &fmt_fdfjfkfa fd fj fk fa &fmt_fdfj fd fj +&fmt_cdfjfkfcond cd fj fk fcond # # Formats @@ -80,6 +83,7 @@ @fmt_fdfjfk .... ........ ..... ..... ..... ..... &fmt_fdfjfk %fd %fj %fk @fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa @fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj +@fmt_cdfjfkfcond .... ........ ..... ..... ..... .. ... &fmt_cdfjfkfcond %cd %fj %fk %fcond # # Fixed point arithmetic operation instruction @@ -341,3 +345,9 @@ fcopysign_s 0000 00010001 00101 ..... ..... ..... @fmt_fdfjfk fcopysign_d 0000 00010001 00110 ..... ..... ..... @fmt_fdfjfk fclass_s 0000 00010001 01000 01101 ..... ..... @fmt_fdfj fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj + +# +# Floating point compare instruction +# +fcmp_cond_s 0000 11000001 ..... ..... ..... 00 ... @fmt_cdfjfkfcond +fcmp_cond_d 0000 11000010 ..... ..... ..... 00 ... @fmt_cdfjfkfcond diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index a4a9e9a..8cce6cc 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -202,6 +202,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a, #include "insn_trans/trans_atomic.c" #include "insn_trans/trans_extra.c" #include "insn_trans/trans_farith.c" +#include "insn_trans/trans_fcmp.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h index 99ab329..16e570c 100644 --- a/target/loongarch/translate.h +++ b/target/loongarch/translate.h @@ -11,6 +11,11 @@ #include "exec/translator.h" +#define FCMP_LT 0x0001 /* fp0 < fp1 */ +#define FCMP_EQ 0x0010 /* fp0 = fp1 */ +#define FCMP_GT 0x0100 /* fp1 < fp0 */ +#define FCMP_UN 0x1000 /* unordered */ + #define TRANS(NAME, FUNC, ...) \ static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \ { return FUNC(ctx, a, __VA_ARGS__); } From patchwork Fri Aug 27 07:14:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461433 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 D46C4C432BE for ; Fri, 27 Aug 2021 07:52:42 +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 78ECF60F92 for ; Fri, 27 Aug 2021 07:52:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 78ECF60F92 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]:49930 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWfJ-0005CG-Hm for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:52:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53254) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5Q-0000yT-8I for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:37 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59656 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5M-0003K0-WA for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:36 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S14; Fri, 27 Aug 2021 15:15:19 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 12/19] target/loongarch: Add floating point conversion instruction translation Date: Fri, 27 Aug 2021 15:14:47 +0800 Message-Id: <1630048494-2143-13-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S14 X-Coremail-Antispam: 1UD129KBjvAXoW3Zr47Ww17Kr4UtrWxGrWUtwb_yoW8Cw1rWo Z8uF45Zr4rG3yfuFZIkwnYqF1xXryUArnxCF4rZryaga4xA34xKFWfCwn5AFyrKrWYqry5 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/fpu_helper.c | 393 +++++++++++++++++++++++++++++++ target/loongarch/helper.h | 29 +++ target/loongarch/insn_trans/trans_fcnv.c | 36 +++ target/loongarch/insns.decode | 32 +++ target/loongarch/translate.c | 1 + 5 files changed, 491 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_fcnv.c diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c index bad7238..2aef1fa 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -546,3 +546,396 @@ uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj, update_fcsr0(env, GETPC()); return cmp; } + +/* floating point conversion */ +uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(float64_to_float32(fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float32_to_float64((uint32_t)fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = nanbox_s(int64_to_float32(fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = int32_to_float64((int32_t)fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = int64_to_float64(fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status)); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_round_to_int(fj, &env->fp_status); + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_down, &env->fp_status); + fd = float64_to_int64(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_down, &env->fp_status); + fd = float32_to_int64((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_down, &env->fp_status); + fd = (uint64_t)float64_to_int32(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_down, &env->fp_status); + fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_up, &env->fp_status); + fd = float64_to_int64(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrp_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_up, &env->fp_status); + fd = float32_to_int64((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrp_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_up, &env->fp_status); + fd = (uint64_t)float64_to_int32(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrp_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_up, &env->fp_status); + fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrz_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + fd = float64_to_int64_round_to_zero(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrz_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + fd = float32_to_int64_round_to_zero((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrz_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + fd = (uint64_t)float64_to_int32_round_to_zero(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrz_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint32_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + fd = float32_to_int32_round_to_zero((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return (uint64_t)fd; +} + +uint64_t helper_ftintrne_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + fd = float64_to_int64(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrne_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + fd = float32_to_int64((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrne_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + fd = (uint64_t)float64_to_int32(fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftintrne_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint32_t fd; + FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + fd = float32_to_int32((uint32_t)fj, &env->fp_status); + set_float_rounding_mode(old_mode, &env->fp_status); + + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return (uint64_t)fd; +} + +uint64_t helper_ftint_l_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float64_to_int64(fj, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftint_l_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = float32_to_int64((uint32_t)fj, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & + (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftint_w_s(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) + & (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} + +uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj) +{ + uint64_t fd; + + fd = (uint64_t)float64_to_int32(fj, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) + & (float_flag_invalid | float_flag_overflow)) { + fd = FLOAT_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return fd; +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 5f6e60d..d90b093 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -69,3 +69,32 @@ DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32) DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32) /* fcmp.sXXX.d */ DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32) + +DEF_HELPER_2(fcvt_d_s, i64, env, i64) +DEF_HELPER_2(fcvt_s_d, i64, env, i64) +DEF_HELPER_2(ffint_d_w, i64, env, i64) +DEF_HELPER_2(ffint_d_l, i64, env, i64) +DEF_HELPER_2(ffint_s_w, i64, env, i64) +DEF_HELPER_2(ffint_s_l, i64, env, i64) +DEF_HELPER_2(ftintrm_l_s, i64, env, i64) +DEF_HELPER_2(ftintrm_l_d, i64, env, i64) +DEF_HELPER_2(ftintrm_w_s, i64, env, i64) +DEF_HELPER_2(ftintrm_w_d, i64, env, i64) +DEF_HELPER_2(ftintrp_l_s, i64, env, i64) +DEF_HELPER_2(ftintrp_l_d, i64, env, i64) +DEF_HELPER_2(ftintrp_w_s, i64, env, i64) +DEF_HELPER_2(ftintrp_w_d, i64, env, i64) +DEF_HELPER_2(ftintrz_l_s, i64, env, i64) +DEF_HELPER_2(ftintrz_l_d, i64, env, i64) +DEF_HELPER_2(ftintrz_w_s, i64, env, i64) +DEF_HELPER_2(ftintrz_w_d, i64, env, i64) +DEF_HELPER_2(ftintrne_l_s, i64, env, i64) +DEF_HELPER_2(ftintrne_l_d, i64, env, i64) +DEF_HELPER_2(ftintrne_w_s, i64, env, i64) +DEF_HELPER_2(ftintrne_w_d, i64, env, i64) +DEF_HELPER_2(ftint_l_s, i64, env, i64) +DEF_HELPER_2(ftint_l_d, i64, env, i64) +DEF_HELPER_2(ftint_w_s, i64, env, i64) +DEF_HELPER_2(ftint_w_d, i64, env, i64) +DEF_HELPER_2(frint_s, i64, env, i64) +DEF_HELPER_2(frint_d, i64, env, i64) diff --git a/target/loongarch/insn_trans/trans_fcnv.c b/target/loongarch/insn_trans/trans_fcnv.c new file mode 100644 index 0000000..6788859 --- /dev/null +++ b/target/loongarch/insn_trans/trans_fcnv.c @@ -0,0 +1,36 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +TRANS(fcvt_s_d, gen_f2, gen_helper_fcvt_s_d) +TRANS(fcvt_d_s, gen_f2, gen_helper_fcvt_d_s) +TRANS(ftintrm_w_s, gen_f2, gen_helper_ftintrm_w_s) +TRANS(ftintrm_w_d, gen_f2, gen_helper_ftintrm_w_d) +TRANS(ftintrm_l_s, gen_f2, gen_helper_ftintrm_l_s) +TRANS(ftintrm_l_d, gen_f2, gen_helper_ftintrm_l_d) +TRANS(ftintrp_w_s, gen_f2, gen_helper_ftintrp_w_s) +TRANS(ftintrp_w_d, gen_f2, gen_helper_ftintrp_w_d) +TRANS(ftintrp_l_s, gen_f2, gen_helper_ftintrp_l_s) +TRANS(ftintrp_l_d, gen_f2, gen_helper_ftintrp_l_d) +TRANS(ftintrz_w_s, gen_f2, gen_helper_ftintrz_w_s) +TRANS(ftintrz_w_d, gen_f2, gen_helper_ftintrz_w_d) +TRANS(ftintrz_l_s, gen_f2, gen_helper_ftintrz_l_s) +TRANS(ftintrz_l_d, gen_f2, gen_helper_ftintrz_l_d) +TRANS(ftintrne_w_s, gen_f2, gen_helper_ftintrne_w_s) +TRANS(ftintrne_w_d, gen_f2, gen_helper_ftintrne_w_d) +TRANS(ftintrne_l_s, gen_f2, gen_helper_ftintrne_l_s) +TRANS(ftintrne_l_d, gen_f2, gen_helper_ftintrne_l_d) +TRANS(ftint_w_s, gen_f2, gen_helper_ftint_w_s) +TRANS(ftint_w_d, gen_f2, gen_helper_ftint_w_d) +TRANS(ftint_l_s, gen_f2, gen_helper_ftint_l_s) +TRANS(ftint_l_d, gen_f2, gen_helper_ftint_l_d) +TRANS(ffint_s_w, gen_f2, gen_helper_ffint_s_w) +TRANS(ffint_s_l, gen_f2, gen_helper_ffint_s_l) +TRANS(ffint_d_w, gen_f2, gen_helper_ffint_d_w) +TRANS(ffint_d_l, gen_f2, gen_helper_ffint_d_l) +TRANS(frint_s, gen_f2, gen_helper_frint_s) +TRANS(frint_d, gen_f2, gen_helper_frint_d) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 8aadcfd..c6fd762 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -351,3 +351,35 @@ fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj # fcmp_cond_s 0000 11000001 ..... ..... ..... 00 ... @fmt_cdfjfkfcond fcmp_cond_d 0000 11000010 ..... ..... ..... 00 ... @fmt_cdfjfkfcond + +# +# Floating point conversion instruction +# +fcvt_s_d 0000 00010001 10010 00110 ..... ..... @fmt_fdfj +fcvt_d_s 0000 00010001 10010 01001 ..... ..... @fmt_fdfj +ftintrm_w_s 0000 00010001 10100 00001 ..... ..... @fmt_fdfj +ftintrm_w_d 0000 00010001 10100 00010 ..... ..... @fmt_fdfj +ftintrm_l_s 0000 00010001 10100 01001 ..... ..... @fmt_fdfj +ftintrm_l_d 0000 00010001 10100 01010 ..... ..... @fmt_fdfj +ftintrp_w_s 0000 00010001 10100 10001 ..... ..... @fmt_fdfj +ftintrp_w_d 0000 00010001 10100 10010 ..... ..... @fmt_fdfj +ftintrp_l_s 0000 00010001 10100 11001 ..... ..... @fmt_fdfj +ftintrp_l_d 0000 00010001 10100 11010 ..... ..... @fmt_fdfj +ftintrz_w_s 0000 00010001 10101 00001 ..... ..... @fmt_fdfj +ftintrz_w_d 0000 00010001 10101 00010 ..... ..... @fmt_fdfj +ftintrz_l_s 0000 00010001 10101 01001 ..... ..... @fmt_fdfj +ftintrz_l_d 0000 00010001 10101 01010 ..... ..... @fmt_fdfj +ftintrne_w_s 0000 00010001 10101 10001 ..... ..... @fmt_fdfj +ftintrne_w_d 0000 00010001 10101 10010 ..... ..... @fmt_fdfj +ftintrne_l_s 0000 00010001 10101 11001 ..... ..... @fmt_fdfj +ftintrne_l_d 0000 00010001 10101 11010 ..... ..... @fmt_fdfj +ftint_w_s 0000 00010001 10110 00001 ..... ..... @fmt_fdfj +ftint_w_d 0000 00010001 10110 00010 ..... ..... @fmt_fdfj +ftint_l_s 0000 00010001 10110 01001 ..... ..... @fmt_fdfj +ftint_l_d 0000 00010001 10110 01010 ..... ..... @fmt_fdfj +ffint_s_w 0000 00010001 11010 00100 ..... ..... @fmt_fdfj +ffint_s_l 0000 00010001 11010 00110 ..... ..... @fmt_fdfj +ffint_d_w 0000 00010001 11010 01000 ..... ..... @fmt_fdfj +ffint_d_l 0000 00010001 11010 01010 ..... ..... @fmt_fdfj +frint_s 0000 00010001 11100 10001 ..... ..... @fmt_fdfj +frint_d 0000 00010001 11100 10010 ..... ..... @fmt_fdfj diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 8cce6cc..99e5678 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -203,6 +203,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a, #include "insn_trans/trans_extra.c" #include "insn_trans/trans_farith.c" #include "insn_trans/trans_fcmp.c" +#include "insn_trans/trans_fcnv.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Fri Aug 27 07:14:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461469 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 D44C0C432BE for ; Fri, 27 Aug 2021 07:54:27 +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 8828E60F92 for ; Fri, 27 Aug 2021 07:54:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 8828E60F92 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]:54164 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWh0-00083O-PA for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:54:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53274) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5T-00011Z-9b for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:39 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59692 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5Q-0003NU-2s for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:38 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S15; Fri, 27 Aug 2021 15:15:20 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 13/19] target/loongarch: Add floating point move instruction translation Date: Fri, 27 Aug 2021 15:14:48 +0800 Message-Id: <1630048494-2143-14-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S15 X-Coremail-Antispam: 1UD129KBjvJXoWxuw1fWw1DXryrJr47Jr1DWrg_yoWfZFy3pr 12kryUCr48JFy3JF93tw4YgF45Jr1xC3Wjq3yay348AF4UJF1UAF1kJ3y2krW5Wws3WryU JF15AFyUKFyUXaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/fpu_helper.c | 6 ++ target/loongarch/helper.h | 2 + target/loongarch/insn_trans/trans_fmov.c | 159 +++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 41 ++++++++ target/loongarch/translate.c | 1 + 5 files changed, 209 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_fmov.c diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c index 2aef1fa..125e102 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -939,3 +939,9 @@ uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj) update_fcsr0(env, GETPC()); return fd; } + +void helper_set_rounding_mode(CPULoongArchState *env, uint32_t fcsr0) +{ + set_float_rounding_mode(ieee_rm[fcsr0 >> FCSR0_RM] & 0x3, + &env->fp_status); +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index d90b093..b397a52 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -98,3 +98,5 @@ DEF_HELPER_2(ftint_w_s, i64, env, i64) DEF_HELPER_2(ftint_w_d, i64, env, i64) DEF_HELPER_2(frint_s, i64, env, i64) DEF_HELPER_2(frint_d, i64, env, i64) + +DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32) diff --git a/target/loongarch/insn_trans/trans_fmov.c b/target/loongarch/insn_trans/trans_fmov.c new file mode 100644 index 0000000..c417fb8 --- /dev/null +++ b/target/loongarch/insn_trans/trans_fmov.c @@ -0,0 +1,159 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static const uint32_t fcsr_mask[4] = { + UINT32_MAX, FCSR0_M1, FCSR0_M2, FCSR0_M3 +}; + +static bool trans_fsel(DisasContext *ctx, arg_fsel *a) +{ + TCGv zero = tcg_constant_tl(0); + TCGv cond = tcg_temp_new(); + + tcg_gen_ld8u_tl(cond, cpu_env, offsetof(CPULoongArchState, cf[a->ca])); + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_fpr[a->fd], cond, zero, + cpu_fpr[a->fj], cpu_fpr[a->fk]); + tcg_temp_free(cond); + return true; +} + +static bool gen_mov(DisasContext *ctx, arg_fmt_fdfj *a, + void (*func)(TCGv, TCGv)) +{ + TCGv dest = cpu_fpr[a->fd]; + TCGv src = cpu_fpr[a->fj]; + + func(dest, src); + return true; +} + +static bool gen_r2f(DisasContext *ctx, arg_fmt_fdrj *a, + void (*func)(TCGv, TCGv)) +{ + TCGv src = gpr_src(ctx, a->rj, EXT_NONE); + + func(cpu_fpr[a->fd], src); + return true; +} + +static bool gen_f2r(DisasContext *ctx, arg_fmt_rdfj *a, + DisasExtend dst_ext, void (*func)(TCGv, TCGv)) +{ + ctx->dst_ext = dst_ext; + TCGv dest = gpr_dst(ctx, a->rd); + + func(dest, cpu_fpr[a->fj]); + + if (ctx->dst_ext) { + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a) +{ + uint32_t mask = fcsr_mask[a->fcsrd]; + TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE); + + if (mask == UINT32_MAX) { + tcg_gen_extrl_i64_i32(cpu_fcsr0, Rj); + } else { + TCGv_i32 temp = tcg_temp_new_i32(); + + tcg_gen_extrl_i64_i32(temp, Rj); + tcg_gen_andi_i32(temp, temp, mask); + tcg_gen_andi_i32(cpu_fcsr0, cpu_fcsr0, ~mask); + tcg_gen_or_i32(cpu_fcsr0, cpu_fcsr0, temp); + tcg_temp_free_i32(temp); + + /* + * Install the new rounding mode to fpu_status, if changed. + * Note that FCSR3 is exactly the rounding mode field. + */ + if (mask != FCSR0_M3) { + return true; + } + } + gen_helper_set_rounding_mode(cpu_env, cpu_fcsr0); + return true; +} + +static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a) +{ + TCGv_i32 temp = tcg_temp_new_i32(); + TCGv dest = gpr_dst(ctx, a->rd); + + tcg_gen_andi_i32(temp, cpu_fcsr0, fcsr_mask[a->fcsrs]); + tcg_gen_ext_i32_i64(dest, temp); + tcg_temp_free_i32(temp); + return true; +} + +static void gen_movgr2fr_w(TCGv dest, TCGv src) +{ + tcg_gen_deposit_i64(dest, dest, src, 0, 32); +} + +static void gen_movgr2frh_w(TCGv dest, TCGv src) +{ + tcg_gen_deposit_i64(dest, dest, src, 32, 32); +} + +static void gen_movfrh2gr_s(TCGv dest, TCGv src) +{ + TCGv t0 = tcg_temp_new(); + + tcg_gen_extract_tl(dest, src, 32, 32); + + tcg_temp_free(t0); +} + +static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a) +{ + TCGv t0 = tcg_temp_new(); + + tcg_gen_andi_tl(t0, cpu_fpr[a->fj], 0x1); + tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + + tcg_temp_free(t0); + return true; +} + +static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a) +{ + tcg_gen_ld8u_tl(cpu_fpr[a->fd], cpu_env, + offsetof(CPULoongArchState, cf[a->cj & 0x7])); + return true; +} + +static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a) +{ + TCGv t0 = tcg_temp_new(); + + tcg_gen_andi_tl(t0, gpr_src(ctx, a->rj, EXT_NONE), 0x1); + tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + + tcg_temp_free(t0); + return true; +} + +static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a) +{ + tcg_gen_ld8u_tl(gpr_dst(ctx, a->rd), cpu_env, + offsetof(CPULoongArchState, cf[a->cj & 0x7])); + return true; +} + +TRANS(fmov_s, gen_mov, tcg_gen_mov_tl) +TRANS(fmov_d, gen_mov, tcg_gen_mov_tl) +TRANS(movgr2fr_w, gen_r2f, gen_movgr2fr_w) +TRANS(movgr2fr_d, gen_r2f, tcg_gen_mov_tl) +TRANS(movgr2frh_w, gen_r2f, gen_movgr2frh_w) +TRANS(movfr2gr_s, gen_f2r, EXT_NONE, tcg_gen_ext32s_tl) +TRANS(movfr2gr_d, gen_f2r, EXT_NONE, tcg_gen_mov_tl) +TRANS(movfrh2gr_s, gen_f2r, EXT_SIGN, gen_movfrh2gr_s) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index c6fd762..febf89a 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -34,6 +34,10 @@ %fa 15:5 %cd 0:3 %fcond 15:5 +%cj 5:3 +%ca 15:3 +%fcsrd 0:5 +%fcsrs 5:5 # # Argument sets @@ -59,6 +63,15 @@ &fmt_fdfjfkfa fd fj fk fa &fmt_fdfj fd fj &fmt_cdfjfkfcond cd fj fk fcond +&fmt_fdfjfkca fd fj fk ca +&fmt_fdrj fd rj +&fmt_rdfj rd fj +&fmt_fcsrdrj fcsrd rj +&fmt_rdfcsrs rd fcsrs +&fmt_cdfj cd fj +&fmt_fdcj fd cj +&fmt_cdrj cd rj +&fmt_rdcj rd cj # # Formats @@ -84,6 +97,15 @@ @fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa @fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj @fmt_cdfjfkfcond .... ........ ..... ..... ..... .. ... &fmt_cdfjfkfcond %cd %fj %fk %fcond +@fmt_fdfjfkca .... ........ .. ... ..... ..... ..... &fmt_fdfjfkca %fd %fj %fk %ca +@fmt_fdrj .... ........ ..... ..... ..... ..... &fmt_fdrj %fd %rj +@fmt_rdfj .... ........ ..... ..... ..... ..... &fmt_rdfj %rd %fj +@fmt_fcsrdrj .... ........ ..... ..... ..... ..... &fmt_fcsrdrj %fcsrd %rj +@fmt_rdfcsrs .... ........ ..... ..... ..... ..... &fmt_rdfcsrs %rd %fcsrs +@fmt_cdfj .... ........ ..... ..... ..... .. ... &fmt_cdfj %cd %fj +@fmt_fdcj .... ........ ..... ..... .. ... ..... &fmt_fdcj %fd %cj +@fmt_cdrj .... ........ ..... ..... ..... .. ... &fmt_cdrj %cd %rj +@fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj # # Fixed point arithmetic operation instruction @@ -383,3 +405,22 @@ ffint_d_w 0000 00010001 11010 01000 ..... ..... @fmt_fdfj ffint_d_l 0000 00010001 11010 01010 ..... ..... @fmt_fdfj frint_s 0000 00010001 11100 10001 ..... ..... @fmt_fdfj frint_d 0000 00010001 11100 10010 ..... ..... @fmt_fdfj + +# +# Floating point move instruction +# +fmov_s 0000 00010001 01001 00101 ..... ..... @fmt_fdfj +fmov_d 0000 00010001 01001 00110 ..... ..... @fmt_fdfj +fsel 0000 11010000 00 ... ..... ..... ..... @fmt_fdfjfkca +movgr2fr_w 0000 00010001 01001 01001 ..... ..... @fmt_fdrj +movgr2fr_d 0000 00010001 01001 01010 ..... ..... @fmt_fdrj +movgr2frh_w 0000 00010001 01001 01011 ..... ..... @fmt_fdrj +movfr2gr_s 0000 00010001 01001 01101 ..... ..... @fmt_rdfj +movfr2gr_d 0000 00010001 01001 01110 ..... ..... @fmt_rdfj +movfrh2gr_s 0000 00010001 01001 01111 ..... ..... @fmt_rdfj +movgr2fcsr 0000 00010001 01001 10000 ..... ..... @fmt_fcsrdrj +movfcsr2gr 0000 00010001 01001 10010 ..... ..... @fmt_rdfcsrs +movfr2cf 0000 00010001 01001 10100 ..... 00 ... @fmt_cdfj +movcf2fr 0000 00010001 01001 10101 00 ... ..... @fmt_fdcj +movgr2cf 0000 00010001 01001 10110 ..... 00 ... @fmt_cdrj +movcf2gr 0000 00010001 01001 10111 00 ... ..... @fmt_rdcj diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 99e5678..55185ae 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -204,6 +204,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a, #include "insn_trans/trans_farith.c" #include "insn_trans/trans_fcmp.c" #include "insn_trans/trans_fcnv.c" +#include "insn_trans/trans_fmov.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Fri Aug 27 07:14:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461473 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 AEA45C432BE for ; Fri, 27 Aug 2021 07:57:36 +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 0193260F92 for ; Fri, 27 Aug 2021 07:57:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0193260F92 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]:35618 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWk3-0006LO-6v for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:57:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53290) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5Z-00015d-Ky for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:46 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59748 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5V-0003Pp-LY for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:45 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S16; Fri, 27 Aug 2021 15:15:23 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 14/19] target/loongarch: Add floating point load/store instruction translation Date: Fri, 27 Aug 2021 15:14:49 +0800 Message-Id: <1630048494-2143-15-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S16 X-Coremail-Antispam: 1UD129KBjvJXoW3Jw47Gw4fGry5Cr45tF4fZrb_yoW3JFy7pF 4Iyry8Gr40qr1fAr93Kw45WrnxJFnak3y2g34ayw1xAF1rXF18JF4kJ3ya9rWUXwn5XFW5 JFW5AryUtFy5J3JanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/insn_trans/trans_fmemory.c | 143 ++++++++++++++++++++++++++++ target/loongarch/insns.decode | 24 +++++ target/loongarch/translate.c | 1 + 3 files changed, 168 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_fmemory.c diff --git a/target/loongarch/insn_trans/trans_fmemory.c b/target/loongarch/insn_trans/trans_fmemory.c new file mode 100644 index 0000000..88727c3 --- /dev/null +++ b/target/loongarch/insn_trans/trans_fmemory.c @@ -0,0 +1,143 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_fload_imm(DisasContext *ctx, arg_fmt_fdrjsi12 *a, MemOp mop) +{ + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv temp = NULL; + + if (a->si12) { + temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, addr, a->si12); + addr = temp; + } + tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + if (temp) { + tcg_temp_free(temp); + } + return true; +} + +static bool gen_fstore_imm(DisasContext *ctx, arg_fmt_fdrjsi12 *a, MemOp mop) +{ + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + TCGv temp = NULL; + + if (a->si12) { + temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, addr, a->si12); + addr = temp; + } + tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + if (temp) { + tcg_temp_free(temp); + } + return true; +} + +static bool gen_fload_tl(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_fstore_tl(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_fload_gt(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtgt_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + + return true; +} + +static bool gen_fstore_gt(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtgt_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_fload_le(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtle_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +static bool gen_fstore_le(DisasContext *ctx, arg_fmt_fdrjrk *a, MemOp mop) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + TCGv addr = tcg_temp_new(); + + gen_helper_asrtle_d(cpu_env, src1, src2); + tcg_gen_add_tl(addr, src1, src2); + tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + + tcg_temp_free(addr); + return true; +} + +TRANS(fld_s, gen_fload_imm, MO_TESL) +TRANS(fst_s, gen_fstore_imm, MO_TEUL) +TRANS(fld_d, gen_fload_imm, MO_TEQ) +TRANS(fst_d, gen_fstore_imm, MO_TEQ) +TRANS(fldx_s, gen_fload_tl, MO_TESL) +TRANS(fldx_d, gen_fload_tl, MO_TEQ) +TRANS(fstx_s, gen_fstore_tl, MO_TEUL) +TRANS(fstx_d, gen_fstore_tl, MO_TEQ) +TRANS(fldgt_s, gen_fload_gt, MO_TESL) +TRANS(fldgt_d, gen_fload_gt, MO_TEQ) +TRANS(fldle_s, gen_fload_le, MO_TESL) +TRANS(fldle_d, gen_fload_le, MO_TEQ) +TRANS(fstgt_s, gen_fstore_gt, MO_TEUL) +TRANS(fstgt_d, gen_fstore_gt, MO_TEQ) +TRANS(fstle_s, gen_fstore_le, MO_TEUL) +TRANS(fstle_d, gen_fstore_le, MO_TEQ) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index febf89a..ea776c2 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -72,6 +72,8 @@ &fmt_fdcj fd cj &fmt_cdrj cd rj &fmt_rdcj rd cj +&fmt_fdrjrk fd rj rk +&fmt_fdrjsi12 fd rj si12 # # Formats @@ -106,6 +108,8 @@ @fmt_fdcj .... ........ ..... ..... .. ... ..... &fmt_fdcj %fd %cj @fmt_cdrj .... ........ ..... ..... ..... .. ... &fmt_cdrj %cd %rj @fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj +@fmt_fdrjrk .... ........ ..... ..... ..... ..... &fmt_fdrjrk %fd %rj %rk +@fmt_fdrjsi12 .... ...... ............ ..... ..... &fmt_fdrjsi12 %fd %rj %si12 # # Fixed point arithmetic operation instruction @@ -424,3 +428,23 @@ movfr2cf 0000 00010001 01001 10100 ..... 00 ... @fmt_cdfj movcf2fr 0000 00010001 01001 10101 00 ... ..... @fmt_fdcj movgr2cf 0000 00010001 01001 10110 ..... 00 ... @fmt_cdrj movcf2gr 0000 00010001 01001 10111 00 ... ..... @fmt_rdcj + +# +# Floating point load/store instruction +# +fld_s 0010 101100 ............ ..... ..... @fmt_fdrjsi12 +fst_s 0010 101101 ............ ..... ..... @fmt_fdrjsi12 +fld_d 0010 101110 ............ ..... ..... @fmt_fdrjsi12 +fst_d 0010 101111 ............ ..... ..... @fmt_fdrjsi12 +fldx_s 0011 10000011 00000 ..... ..... ..... @fmt_fdrjrk +fldx_d 0011 10000011 01000 ..... ..... ..... @fmt_fdrjrk +fstx_s 0011 10000011 10000 ..... ..... ..... @fmt_fdrjrk +fstx_d 0011 10000011 11000 ..... ..... ..... @fmt_fdrjrk +fldgt_s 0011 10000111 01000 ..... ..... ..... @fmt_fdrjrk +fldgt_d 0011 10000111 01001 ..... ..... ..... @fmt_fdrjrk +fldle_s 0011 10000111 01010 ..... ..... ..... @fmt_fdrjrk +fldle_d 0011 10000111 01011 ..... ..... ..... @fmt_fdrjrk +fstgt_s 0011 10000111 01100 ..... ..... ..... @fmt_fdrjrk +fstgt_d 0011 10000111 01101 ..... ..... ..... @fmt_fdrjrk +fstle_s 0011 10000111 01110 ..... ..... ..... @fmt_fdrjrk +fstle_d 0011 10000111 01111 ..... ..... ..... @fmt_fdrjrk diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 55185ae..d4a622f 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -205,6 +205,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a, #include "insn_trans/trans_fcmp.c" #include "insn_trans/trans_fcnv.c" #include "insn_trans/trans_fmov.c" +#include "insn_trans/trans_fmemory.c" static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { From patchwork Fri Aug 27 07:14:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461475 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 611C7C4320A for ; Fri, 27 Aug 2021 07:59:17 +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 0CAB260E93 for ; Fri, 27 Aug 2021 07:59:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0CAB260E93 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]:39676 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWlg-0000eh-AE for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:59:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53302) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5e-0001Cr-1W for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:50 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59820 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5b-0003Ul-OP for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:49 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S17; Fri, 27 Aug 2021 15:15:29 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 15/19] target/loongarch: Add branch instruction translation Date: Fri, 27 Aug 2021 15:14:50 +0800 Message-Id: <1630048494-2143-16-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S17 X-Coremail-Antispam: 1UD129KBjvJXoWxtrykurWkGw1xAFyxJrW3trb_yoWxJrW5pr 1UCryUGrWkJry3Jrn5tw45Xr13Jrs5Gw17Gw43twn3JF42q3WUAF18AryUKF4jv34kZry8 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/insn_trans/trans_branch.c | 84 ++++++++++++++++++++++++++++++ target/loongarch/insns.decode | 30 +++++++++++ target/loongarch/translate.c | 1 + 3 files changed, 115 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_branch.c diff --git a/target/loongarch/insn_trans/trans_branch.c b/target/loongarch/insn_trans/trans_branch.c new file mode 100644 index 0000000..acf1966 --- /dev/null +++ b/target/loongarch/insn_trans/trans_branch.c @@ -0,0 +1,84 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool trans_b(DisasContext *ctx, arg_b *a) +{ + gen_goto_tb(ctx, 0, ctx->base.pc_next + (a->offs << 2)); + ctx->base.is_jmp = DISAS_NORETURN; + return true; +} + +static bool trans_bl(DisasContext *ctx, arg_bl *a) +{ + tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4); + gen_goto_tb(ctx, 0, ctx->base.pc_next + (a->offs << 2)); + ctx->base.is_jmp = DISAS_NORETURN; + return true; +} + +static bool trans_jirl(DisasContext *ctx, arg_jirl *a) +{ + TCGv dest = gpr_dst(ctx, a->rd); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + tcg_gen_addi_tl(cpu_pc, src1, (a->offs16) << 2); + tcg_gen_movi_tl(dest, ctx->base.pc_next + 4); + tcg_gen_lookup_and_goto_ptr(); + ctx->base.is_jmp = DISAS_NORETURN; + return true; +} + +static void gen_bc(DisasContext *ctx, TCGv src1, TCGv src2, + target_long offs, TCGCond cond) +{ + TCGLabel *l = gen_new_label(); + tcg_gen_brcond_tl(cond, src1, src2, l); + gen_goto_tb(ctx, 1, ctx->base.pc_next + 4); + gen_set_label(l); + gen_goto_tb(ctx, 0, ctx->base.pc_next + offs); + ctx->base.is_jmp = DISAS_NORETURN; +} + +static bool gen_r2_bc(DisasContext *ctx, arg_fmt_rjrdoffs16 *a, TCGCond cond) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE); + + gen_bc(ctx, src1, src2, (a->offs16 << 2), cond); + return true; +} + +static bool gen_rz_bc(DisasContext *ctx, arg_fmt_rjoffs21 *a, TCGCond cond) +{ + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + TCGv src2 = tcg_constant_tl(0); + + gen_bc(ctx, src1, src2, (a->offs21 << 2), cond); + return true; +} +static bool gen_cz_bc(DisasContext *ctx, arg_fmt_cjoffs21 *a, TCGCond cond) +{ + TCGv src1 = tcg_temp_new(); + TCGv src2 = tcg_constant_tl(0); + + tcg_gen_ld8u_tl(src1, cpu_env, + offsetof(CPULoongArchState, cf[a->cj & 0x7])); + gen_bc(ctx, src1, src2, (a->offs21 << 2), cond); + return true; +} + +TRANS(beq, gen_r2_bc, TCG_COND_EQ) +TRANS(bne, gen_r2_bc, TCG_COND_NE) +TRANS(blt, gen_r2_bc, TCG_COND_LT) +TRANS(bge, gen_r2_bc, TCG_COND_GE) +TRANS(bltu, gen_r2_bc, TCG_COND_LTU) +TRANS(bgeu, gen_r2_bc, TCG_COND_GEU) +TRANS(beqz, gen_rz_bc, TCG_COND_EQ) +TRANS(bnez, gen_rz_bc, TCG_COND_NE) +TRANS(bceqz, gen_cz_bc, TCG_COND_EQ) +TRANS(bcnez, gen_cz_bc, TCG_COND_NE) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index ea776c2..077063e 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -38,6 +38,9 @@ %ca 15:3 %fcsrd 0:5 %fcsrs 5:5 +%offs21 0:s5 10:16 +%offs16 10:s16 +%offs 0:s10 10:16 # # Argument sets @@ -74,6 +77,11 @@ &fmt_rdcj rd cj &fmt_fdrjrk fd rj rk &fmt_fdrjsi12 fd rj si12 +&fmt_rjoffs21 rj offs21 +&fmt_cjoffs21 cj offs21 +&fmt_rdrjoffs16 rd rj offs16 +&fmt_offs offs +&fmt_rjrdoffs16 rj rd offs16 # # Formats @@ -110,6 +118,11 @@ @fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj @fmt_fdrjrk .... ........ ..... ..... ..... ..... &fmt_fdrjrk %fd %rj %rk @fmt_fdrjsi12 .... ...... ............ ..... ..... &fmt_fdrjsi12 %fd %rj %si12 +@fmt_rjoffs21 .... .. ................ ..... ..... &fmt_rjoffs21 %rj %offs21 +@fmt_cjoffs21 .... .. ................ .. ... ..... &fmt_cjoffs21 %cj %offs21 +@fmt_rdrjoffs16 .... .. ................ ..... ..... &fmt_rdrjoffs16 %rd %rj %offs16 +@fmt_offs .... .. .......................... &fmt_offs %offs +@fmt_rjrdoffs16 .... .. ................ ..... ..... &fmt_rjrdoffs16 %rj %rd %offs16 # # Fixed point arithmetic operation instruction @@ -448,3 +461,20 @@ fstgt_s 0011 10000111 01100 ..... ..... ..... @fmt_fdrjrk fstgt_d 0011 10000111 01101 ..... ..... ..... @fmt_fdrjrk fstle_s 0011 10000111 01110 ..... ..... ..... @fmt_fdrjrk fstle_d 0011 10000111 01111 ..... ..... ..... @fmt_fdrjrk + +# +# Branch instructions +# +beqz 0100 00 ................ ..... ..... @fmt_rjoffs21 +bnez 0100 01 ................ ..... ..... @fmt_rjoffs21 +bceqz 0100 10 ................ 00 ... ..... @fmt_cjoffs21 +bcnez 0100 10 ................ 01 ... ..... @fmt_cjoffs21 +jirl 0100 11 ................ ..... ..... @fmt_rdrjoffs16 +b 0101 00 .......................... @fmt_offs +bl 0101 01 .......................... @fmt_offs +beq 0101 10 ................ ..... ..... @fmt_rjrdoffs16 +bne 0101 11 ................ ..... ..... @fmt_rjrdoffs16 +blt 0110 00 ................ ..... ..... @fmt_rjrdoffs16 +bge 0110 01 ................ ..... ..... @fmt_rjrdoffs16 +bltu 0110 10 ................ ..... ..... @fmt_rjrdoffs16 +bgeu 0110 11 ................ ..... ..... @fmt_rjrdoffs16 diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index d4a622f..db90399 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -206,6 +206,7 @@ static bool gen_f2(DisasContext *ctx, arg_fmt_fdfj *a, #include "insn_trans/trans_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 Fri Aug 27 07:14:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461499 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 3FDA2C432BE for ; Fri, 27 Aug 2021 08:07:06 +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 9792B60F92 for ; Fri, 27 Aug 2021 08:07:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 9792B60F92 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]:52450 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWtE-00017H-Rt for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 04:07:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53380) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5s-0001Yt-HR for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:16:05 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59840 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5d-0003V4-Ox for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:16:04 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S18; Fri, 27 Aug 2021 15:15:35 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 16/19] target/loongarch: Add disassembler Date: Fri, 27 Aug 2021 15:14:51 +0800 Message-Id: <1630048494-2143-17-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S18 X-Coremail-Antispam: 1UD129KBjvAXoWDWFy7Zw4DGF1xZF1rKw1DAwb_yoW7tF1DCo 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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'. Acked-by: Richard Henderson Signed-off-by: Song Gao --- 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 396f970..073cda2 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..eb7475b --- /dev/null +++ b/disas/loongarch.c @@ -0,0 +1,2511 @@ +/* + * QEMU LoongArch Disassembler + * + * Copyright (c) 2021 Loongson Technology Corporation Limited. + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "disas/dis-asm.h" + +#define INSNLEN 4 + +/* enums */ +typedef enum { + la_op_illegal = 0, + la_op_clo_w = 1, + la_op_clz_w = 2, + la_op_cto_w = 3, + la_op_ctz_w = 4, + la_op_clo_d = 5, + la_op_clz_d = 6, + la_op_cto_d = 7, + la_op_ctz_d = 8, + la_op_revb_2h = 9, + la_op_revb_4h = 10, + la_op_revb_2w = 11, + la_op_revb_d = 12, + la_op_revh_2w = 13, + la_op_revh_d = 14, + la_op_bitrev_4b = 15, + la_op_bitrev_8b = 16, + la_op_bitrev_w = 17, + la_op_bitrev_d = 18, + la_op_ext_w_h = 19, + la_op_ext_w_b = 20, + la_op_rdtime_d = 21, + la_op_cpucfg = 22, + la_op_asrtle_d = 23, + la_op_asrtgt_d = 24, + la_op_alsl_w = 25, + la_op_alsl_wu = 26, + la_op_bytepick_w = 27, + la_op_bytepick_d = 28, + la_op_add_w = 29, + la_op_add_d = 30, + la_op_sub_w = 31, + la_op_sub_d = 32, + la_op_slt = 33, + la_op_sltu = 34, + la_op_maskeqz = 35, + la_op_masknez = 36, + la_op_nor = 37, + la_op_and = 38, + la_op_or = 39, + la_op_xor = 40, + la_op_orn = 41, + la_op_andn = 42, + la_op_sll_w = 43, + la_op_srl_w = 44, + la_op_sra_w = 45, + la_op_sll_d = 46, + la_op_srl_d = 47, + la_op_sra_d = 48, + la_op_rotr_w = 49, + la_op_rotr_d = 50, + la_op_mul_w = 51, + la_op_mulh_w = 52, + la_op_mulh_wu = 53, + la_op_mul_d = 54, + la_op_mulh_d = 55, + la_op_mulh_du = 56, + la_op_mulw_d_w = 57, + la_op_mulw_d_wu = 58, + la_op_div_w = 59, + la_op_mod_w = 60, + la_op_div_wu = 61, + la_op_mod_wu = 62, + la_op_div_d = 63, + la_op_mod_d = 64, + la_op_div_du = 65, + la_op_mod_du = 66, + la_op_crc_w_b_w = 67, + la_op_crc_w_h_w = 68, + la_op_crc_w_w_w = 69, + la_op_crc_w_d_w = 70, + la_op_crcc_w_b_w = 71, + la_op_crcc_w_h_w = 72, + la_op_crcc_w_w_w = 73, + la_op_crcc_w_d_w = 74, + la_op_break = 75, + la_op_syscall = 76, + la_op_alsl_d = 77, + la_op_slli_w = 78, + la_op_slli_d = 79, + la_op_srli_w = 80, + la_op_srli_d = 81, + la_op_srai_w = 82, + la_op_srai_d = 83, + la_op_rotri_w = 84, + la_op_rotri_d = 85, + la_op_bstrins_w = 86, + la_op_bstrpick_w = 87, + la_op_bstrins_d = 88, + la_op_bstrpick_d = 89, + la_op_fadd_s = 90, + la_op_fadd_d = 91, + la_op_fsub_s = 92, + la_op_fsub_d = 93, + la_op_fmul_s = 94, + la_op_fmul_d = 95, + la_op_fdiv_s = 96, + la_op_fdiv_d = 97, + la_op_fmax_s = 98, + la_op_fmax_d = 99, + la_op_fmin_s = 100, + la_op_fmin_d = 101, + la_op_fmaxa_s = 102, + la_op_fmaxa_d = 103, + la_op_fmina_s = 104, + la_op_fmina_d = 105, + la_op_fscaleb_s = 106, + la_op_fscaleb_d = 107, + la_op_fcopysign_s = 108, + la_op_fcopysign_d = 109, + la_op_fabs_s = 110, + la_op_fabs_d = 111, + la_op_fneg_s = 112, + la_op_fneg_d = 113, + la_op_flogb_s = 114, + la_op_flogb_d = 115, + la_op_fclass_s = 116, + la_op_fclass_d = 117, + la_op_fsqrt_s = 118, + la_op_fsqrt_d = 119, + la_op_frecip_s = 120, + la_op_frecip_d = 121, + la_op_frsqrt_s = 122, + la_op_frsqrt_d = 123, + la_op_fmov_s = 124, + la_op_fmov_d = 125, + la_op_movgr2fr_w = 126, + la_op_movgr2fr_d = 127, + la_op_movgr2frh_w = 128, + la_op_movfr2gr_s = 129, + la_op_movfr2gr_d = 130, + la_op_movfrh2gr_s = 131, + la_op_movgr2fcsr = 132, + la_op_movfcsr2gr = 133, + la_op_movfr2cf = 134, + la_op_movcf2fr = 135, + la_op_movgr2cf = 136, + la_op_movcf2gr = 137, + la_op_fcvt_s_d = 138, + la_op_fcvt_d_s = 139, + la_op_ftintrm_w_s = 140, + la_op_ftintrm_w_d = 141, + la_op_ftintrm_l_s = 142, + la_op_ftintrm_l_d = 143, + la_op_ftintrp_w_s = 144, + la_op_ftintrp_w_d = 145, + la_op_ftintrp_l_s = 146, + la_op_ftintrp_l_d = 147, + la_op_ftintrz_w_s = 148, + la_op_ftintrz_w_d = 149, + la_op_ftintrz_l_s = 150, + la_op_ftintrz_l_d = 151, + la_op_ftintrne_w_s = 152, + la_op_ftintrne_w_d = 153, + la_op_ftintrne_l_s = 154, + la_op_ftintrne_l_d = 155, + la_op_ftint_w_s = 156, + la_op_ftint_w_d = 157, + la_op_ftint_l_s = 158, + la_op_ftint_l_d = 159, + la_op_ffint_s_w = 160, + la_op_ffint_s_l = 161, + la_op_ffint_d_w = 162, + la_op_ffint_d_l = 163, + la_op_frint_s = 164, + la_op_frint_d = 165, + la_op_slti = 166, + la_op_sltui = 167, + la_op_addi_w = 168, + la_op_addi_d = 169, + la_op_lu52i_d = 170, + la_op_addi = 171, + la_op_ori = 172, + la_op_xori = 173, + la_op_rdtimel_w = 174, + la_op_rdtimeh_w = 175, + la_op_fmadd_s = 176, + la_op_fmadd_d = 177, + la_op_fmsub_s = 178, + la_op_fmsub_d = 179, + la_op_fnmadd_s = 180, + la_op_fnmadd_d = 181, + la_op_fnmsub_s = 182, + la_op_fnmsub_d = 183, + la_op_fcmp_cond_s = 184, + la_op_fcmp_cond_d = 185, + la_op_fsel = 186, + la_op_addu16i_d = 187, + la_op_lu12i_w = 188, + la_op_lu32i_d = 189, + la_op_pcaddi = 190, + la_op_pcalau12i = 191, + la_op_pcaddu12i = 192, + la_op_pcaddu18i = 193, + la_op_ll_w = 194, + la_op_sc_w = 195, + la_op_ll_d = 196, + la_op_sc_d = 197, + la_op_ldptr_w = 198, + la_op_stptr_w = 199, + la_op_ldptr_d = 200, + la_op_stptr_d = 201, + la_op_ld_b = 202, + la_op_ld_h = 203, + la_op_ld_w = 204, + la_op_ld_d = 205, + la_op_st_b = 206, + la_op_st_h = 207, + la_op_st_w = 208, + la_op_st_d = 209, + la_op_ld_bu = 210, + la_op_ld_hu = 211, + la_op_ld_wu = 212, + la_op_preld = 213, + la_op_fld_s = 214, + la_op_fst_s = 215, + la_op_fld_d = 216, + la_op_fst_d = 217, + la_op_ldx_b = 218, + la_op_ldx_h = 219, + la_op_ldx_w = 220, + la_op_ldx_d = 221, + la_op_stx_b = 222, + la_op_stx_h = 223, + la_op_stx_w = 224, + la_op_stx_d = 225, + la_op_ldx_bu = 226, + la_op_ldx_hu = 227, + la_op_ldx_wu = 228, + la_op_fldx_s = 229, + la_op_fldx_d = 230, + la_op_fstx_s = 231, + la_op_fstx_d = 232, + la_op_amswap_w = 233, + la_op_amswap_d = 234, + la_op_amadd_w = 235, + la_op_amadd_d = 236, + la_op_amand_w = 237, + la_op_amand_d = 238, + la_op_amor_w = 239, + la_op_amor_d = 240, + la_op_amxor_w = 241, + la_op_amxor_d = 242, + la_op_ammax_w = 243, + la_op_ammax_d = 244, + la_op_ammin_w = 245, + la_op_ammin_d = 246, + la_op_ammax_wu = 247, + la_op_ammax_du = 248, + la_op_ammin_wu = 249, + la_op_ammin_du = 250, + la_op_amswap_db_w = 251, + la_op_amswap_db_d = 252, + la_op_amadd_db_w = 253, + la_op_amadd_db_d = 254, + la_op_amand_db_w = 255, + la_op_amand_db_d = 256, + la_op_amor_db_w = 257, + la_op_amor_db_d = 258, + la_op_amxor_db_w = 259, + la_op_amxor_db_d = 260, + la_op_ammax_db_w = 261, + la_op_ammax_db_d = 262, + la_op_ammin_db_w = 263, + la_op_ammin_db_d = 264, + la_op_ammax_db_wu = 265, + la_op_ammax_db_du = 266, + la_op_ammin_db_wu = 267, + la_op_ammin_db_du = 268, + la_op_dbar = 269, + la_op_ibar = 270, + la_op_fldgt_s = 271, + la_op_fldgt_d = 272, + la_op_fldle_s = 273, + la_op_fldle_d = 274, + la_op_fstgt_s = 275, + la_op_fstgt_d = 276, + ls_op_fstle_s = 277, + la_op_fstle_d = 278, + la_op_ldgt_b = 279, + la_op_ldgt_h = 280, + la_op_ldgt_w = 281, + la_op_ldgt_d = 282, + la_op_ldle_b = 283, + la_op_ldle_h = 284, + la_op_ldle_w = 285, + la_op_ldle_d = 286, + la_op_stgt_b = 287, + la_op_stgt_h = 288, + la_op_stgt_w = 289, + la_op_stgt_d = 290, + la_op_stle_b = 291, + la_op_stle_h = 292, + la_op_stle_w = 293, + la_op_stle_d = 294, + la_op_beqz = 295, + la_op_bnez = 296, + la_op_bceqz = 297, + la_op_bcnez = 298, + la_op_jirl = 299, + la_op_b = 300, + la_op_bl = 301, + la_op_beq = 302, + la_op_bne = 303, + la_op_blt = 304, + la_op_bge = 305, + la_op_bltu = 306, + la_op_bgeu = 307, + +} la_op; + +typedef enum { + la_codec_illegal, + la_codec_empty, + la_codec_2r, + la_codec_2r_u5, + la_codec_2r_u6, + la_codec_2r_2bw, + la_codec_2r_2bd, + la_codec_3r, + la_codec_3r_rd0, + la_codec_3r_sa2, + la_codec_3r_sa3, + la_codec_4r, + la_codec_r_im20, + la_codec_2r_im16, + la_codec_2r_im14, + la_codec_r_im14, + la_codec_2r_im12, + la_codec_im5_r_im12, + la_codec_2r_im8, + la_codec_r_sd, + la_codec_r_sj, + la_codec_r_cd, + la_codec_r_cj, + la_codec_r_seq, + la_codec_code, + la_codec_whint, + la_codec_invtlb, + la_codec_r_ofs21, + la_codec_cj_ofs21, + la_codec_ofs26, + la_codec_cond, + la_codec_sel, + +} la_codec; + +#define la_fmt_illegal "nte" +#define la_fmt_empty "nt" +#define la_fmt_sd_rj "ntA,1" +#define la_fmt_rd_sj "nt0,B" +#define la_fmt_rd_rj "nt0,1" +#define la_fmt_rj_rk "nt1,2" +#define la_fmt_rj_seq "nt1,x" +#define la_fmt_rd_si20 "nt0,i(x)" +#define la_fmt_rd_rj_ui5 "nt0,1,C" +#define la_fmt_rd_rj_ui6 "nt0,1.C" +#define la_fmt_rd_rj_level "nt0,1,x" +#define la_fmt_rd_rj_msbw_lsbw "nt0,1,C,D" +#define la_fmt_rd_rj_msbd_lsbd "nt0,1,C,D" +#define la_fmt_rd_rj_si12 "nt0,1,i(x)" +#define la_fmt_hint_rj_si12 "ntE,1,i(x)" +#define la_fmt_rd_rj_csr "nt0,1,x" +#define la_fmt_rd_csr "nt0,x" +#define la_fmt_rd_rj_si14 "nt0,1,i(x)" +#define la_fmt_rd_rj_si16 "nt0,1,i(x)" +#define la_fmt_rd_rj_rk "nt0,1,2" +#define la_fmt_fd_rj_rk "nt3,1,2" +#define la_fmt_rd_rj_rk_sa2 "nt0,1,2,D" +#define la_fmt_rd_rj_rk_sa3 "nt0,1,2,D" +#define la_fmt_fd_rj "nt3,1" +#define la_fmt_rd_fj "nt0,4" +#define la_fmt_fd_fj "nt3,4" +#define la_fmt_fd_fj_si12 "nt3,4,i(x)" +#define la_fmt_fcsrd_rj "ntF,1" +#define la_fmt_rd_fcsrs "nt0,G" +#define la_fmt_cd_fj "ntH,4" +#define la_fmt_fd_cj "nt3,I" +#define la_fmt_fd_fj_fk "nt3,4,5" +#define la_fmt_code "ntJ" +#define la_fmt_whint "ntx" +#define la_fmt_invtlb "ntx,1,2" +#define la_fmt_offs26 "nto(X)p" +#define la_fmt_rj_offs21 "nt1,o(X)p" +#define la_fmt_cj_offs21 "ntQ,o(X)p" +#define la_fmt_rd_rj_offs16 "nt0,1,o(X)" +#define la_fmt_rj_rd_offs16 "nt1,0,o(X)p" +#define la_fmt_s_cd_fj_fk "K.stH,4,5" +#define la_fmt_d_cd_fj_fk "K.dtH,4,5" +#define la_fmt_fd_fj_fk_fa "nt3,4,5,6" +#define la_fmt_fd_fj_fk_ca "nt3,4,5,L" +#define la_fmt_cop_rj_si12 "ntM,1,i(x)" + +/* structures */ +typedef struct { + uint32_t pc; + uint32_t insn; + int32_t imm; + int32_t imm2; + uint16_t op; + uint16_t code; + uint8_t codec; + uint8_t r1; + uint8_t r2; + uint8_t r3; + uint8_t r4; + uint8_t bit; +} la_decode; + +typedef struct { + const char * const name; + const la_codec codec; + const char * const format; +} la_opcode_data; + +/* reg names */ +const char * const loongarch_r_normal_name[32] = { + "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", + "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", + "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", + "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31", +}; + +const char * const loongarch_f_normal_name[32] = { + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", + "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", + "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", + "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", +}; + +const char * const loongarch_cr_normal_name[4] = { + "$scr0", "$scr1", "$scr2", "$scr3", +}; + +const char * const loongarch_c_normal_name[8] = { + "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7", +}; + +/* instruction data */ +const la_opcode_data opcode_data[] = { + { "illegal", la_codec_illegal, la_fmt_illegal }, + { "clo.w", la_codec_2r, la_fmt_rd_rj }, + { "clz.w", la_codec_2r, la_fmt_rd_rj }, + { "cto.w", la_codec_2r, la_fmt_rd_rj }, + { "ctz.w", la_codec_2r, la_fmt_rd_rj }, + { "clo.d", la_codec_2r, la_fmt_rd_rj }, + { "clz.d", la_codec_2r, la_fmt_rd_rj }, + { "cto.d", la_codec_2r, la_fmt_rd_rj }, + { "ctz_d", la_codec_2r, la_fmt_rd_rj }, + { "revb.2h", la_codec_2r, la_fmt_rd_rj }, + { "revb.4h", la_codec_2r, la_fmt_rd_rj }, + { "revb.2w", la_codec_2r, la_fmt_rd_rj }, + { "revb.d", la_codec_2r, la_fmt_rd_rj }, + { "revh.2w", la_codec_2r, la_fmt_rd_rj }, + { "revh.d", la_codec_2r, la_fmt_rd_rj }, + { "bitrev.4b", la_codec_2r, la_fmt_rd_rj }, + { "bitrev.8b", la_codec_2r, la_fmt_rd_rj }, + { "bitrev.w", la_codec_2r, la_fmt_rd_rj }, + { "bitrev.d", la_codec_2r, la_fmt_rd_rj }, + { "ext.w.h", la_codec_2r, la_fmt_rd_rj }, + { "ext.w.b", la_codec_2r, la_fmt_rd_rj }, + { "rdtime.d", la_codec_2r, la_fmt_rd_rj }, + { "cpucfg", la_codec_2r, la_fmt_rd_rj }, + { "asrtle.d", la_codec_3r_rd0, la_fmt_rj_rk }, + { "asrtgt.d", la_codec_3r_rd0, la_fmt_rj_rk }, + { "alsl.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, + { "alsl.wu", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, + { "bytepick.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, + { "bytepick.d", la_codec_3r_sa3, la_fmt_rd_rj_rk_sa3 }, + { "add.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "add.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "sub.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "sub.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "slt", la_codec_3r, la_fmt_rd_rj_rk }, + { "sltu", la_codec_3r, la_fmt_rd_rj_rk }, + { "maskeqz", la_codec_3r, la_fmt_rd_rj_rk }, + { "masknez", la_codec_3r, la_fmt_rd_rj_rk }, + { "nor", la_codec_3r, la_fmt_rd_rj_rk }, + { "and", la_codec_3r, la_fmt_rd_rj_rk }, + { "or", la_codec_3r, la_fmt_rd_rj_rk }, + { "xor", la_codec_3r, la_fmt_rd_rj_rk }, + { "orn", la_codec_3r, la_fmt_rd_rj_rk }, + { "andn", la_codec_3r, la_fmt_rd_rj_rk }, + { "sll.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "srl.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "sra.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "sll.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "srl.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "sra.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "rotr.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "rotr.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "mul.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulh.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulh.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "mul.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulh.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulh.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulw.d.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulw.d.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "div.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "mod.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "div.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "mod.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "div.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "mod.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "div.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "mod.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "crc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crcc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crcc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crcc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crcc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "break", la_codec_code, la_fmt_code }, + { "syscall", la_codec_code, la_fmt_code }, + { "alsl.d", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, + { "slli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, + { "slli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, + { "srli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, + { "srli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, + { "srai.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, + { "srai.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, + { "rotri.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, + { "rotri.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, + { "bstrins.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw }, + { "bstrpick.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw }, + { "bstrins.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd }, + { "bstrpick.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd }, + { "fadd.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fadd.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fsub.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fsub.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmul.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmul.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fdiv.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fdiv.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmax.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmax.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmin.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmin.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmaxa.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmaxa.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmina.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmina.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fscaleb.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fscaleb.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fcopysign.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fcopysign.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fabs.s", la_codec_2r, la_fmt_fd_fj }, + { "fabs.d", la_codec_2r, la_fmt_fd_fj }, + { "fneg.s", la_codec_2r, la_fmt_fd_fj }, + { "fneg.d", la_codec_2r, la_fmt_fd_fj }, + { "flogb.s", la_codec_2r, la_fmt_fd_fj }, + { "flogb.d", la_codec_2r, la_fmt_fd_fj }, + { "fclass.s", la_codec_2r, la_fmt_fd_fj }, + { "fclass.d", la_codec_2r, la_fmt_fd_fj }, + { "fsqrt.s", la_codec_2r, la_fmt_fd_fj }, + { "fsqrt.d", la_codec_2r, la_fmt_fd_fj }, + { "frecip.s", la_codec_2r, la_fmt_fd_fj }, + { "frecip.d", la_codec_2r, la_fmt_fd_fj }, + { "frsqrt.s", la_codec_2r, la_fmt_fd_fj }, + { "frsqrt.d", la_codec_2r, la_fmt_fd_fj }, + { "fmov.s", la_codec_2r, la_fmt_fd_fj }, + { "fmov.d", la_codec_2r, la_fmt_fd_fj }, + { "movgr2fr.w", la_codec_2r, la_fmt_fd_rj }, + { "movgr2fr.d", la_codec_2r, la_fmt_fd_rj }, + { "movgr2frh.w", la_codec_2r, la_fmt_fd_rj }, + { "movfr2gr.s", la_codec_2r, la_fmt_rd_fj }, + { "movfr2gr.d", la_codec_2r, la_fmt_rd_fj }, + { "movfrh2gr.s", la_codec_2r, la_fmt_rd_fj }, + { "movgr2fcsr", la_codec_2r, la_fmt_fcsrd_rj }, + { "movfcsr2gr", la_codec_2r, la_fmt_rd_fcsrs }, + { "movfr2cf", la_codec_r_cd, la_fmt_cd_fj }, + { "movcf2fr", la_codec_r_cj, la_fmt_fd_cj }, + { "movgr2cf", la_codec_r_cd, la_fmt_cd_fj }, + { "movcf2gr", la_codec_r_cj, la_fmt_fd_cj }, + { "fcvt.s.d", la_codec_2r, la_fmt_fd_fj }, + { "fcvt.d.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrm.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrm.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrm.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrm.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrp.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrp.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrp.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrp.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrz.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrz.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrz.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrz.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrne.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrne.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrne.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrne.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ftint.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftint.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftint.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftint.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ffint.s.w", la_codec_2r, la_fmt_fd_fj }, + { "ffint.s.l", la_codec_2r, la_fmt_fd_fj }, + { "ffint.d.w", la_codec_2r, la_fmt_fd_fj }, + { "ffint.d.l", la_codec_2r, la_fmt_fd_fj }, + { "frint.s", la_codec_2r, la_fmt_fd_fj }, + { "frint.d", la_codec_2r, la_fmt_fd_fj }, + { "slti", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "sltui", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "addi.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "addi.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "lu52i.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "addi", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ori", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "xori", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "rdtimel.w", la_codec_2r, la_fmt_rd_rj }, + { "rdtimeh.w", la_codec_2r, la_fmt_rd_rj }, + { "fmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fnmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fnmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fnmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fnmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fcmp.cond.s", la_codec_cond, la_fmt_s_cd_fj_fk }, + { "fcmp.cond.d", la_codec_cond, la_fmt_d_cd_fj_fk }, + { "fsel", la_codec_sel, la_fmt_fd_fj_fk_ca }, + { "addu16i.d", la_codec_2r_im16, la_fmt_rd_rj_si16 }, + { "lu12i.w", la_codec_r_im20, la_fmt_rd_si20 }, + { "lu32i.d", la_codec_r_im20, la_fmt_rd_si20 }, + { "pcaddi", la_codec_r_im20, la_fmt_rd_si20 }, + { "pcalau12i", la_codec_r_im20, la_fmt_rd_si20 }, + { "pcaddu12i", la_codec_r_im20, la_fmt_rd_si20 }, + { "pcaddu18i", la_codec_r_im20, la_fmt_rd_si20 }, + { "ll.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "sc.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "ll.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "sc.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "ldptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "stptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "ldptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "stptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "ld.b", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.h", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "st.b", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "st.h", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "st.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "st.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.bu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.hu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.wu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "preld", la_codec_2r_im12, la_fmt_hint_rj_si12 }, + { "fld.s", la_codec_2r_im12, la_fmt_fd_fj_si12 }, + { "fst.s", la_codec_2r_im12, la_fmt_fd_fj_si12 }, + { "fld.d", la_codec_2r_im12, la_fmt_fd_fj_si12 }, + { "fst.d", la_codec_2r_im12, la_fmt_fd_fj_si12 }, + { "ldx.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "stx.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "stx.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "stx.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "stx.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.bu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.hu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "fldx.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fldx.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstx.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstx.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "amswap.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amswap.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amadd.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amadd.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amand.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amand.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amor.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amor.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amxor.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amxor.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "amswap.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amswap.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amadd.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amadd.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amand.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amand.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amor.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amor.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amxor.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amxor.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.db.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.db.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.db.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.db.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "dbar", la_codec_whint, la_fmt_whint }, + { "ibar", la_codec_whint, la_fmt_whint }, + { "fldgt.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fldgt.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "fldle.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fldle.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstgt.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstgt.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstle.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstle.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "ldgt.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldgt.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldgt.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldgt.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldle.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldle.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldle.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldle.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "stgt.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "stgt.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "stgt.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "stgt.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "stle.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "stle.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "stle.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "stle.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "beqz", la_codec_r_ofs21, la_fmt_rj_offs21 }, + { "bnez", la_codec_r_ofs21, la_fmt_rj_offs21 }, + { "bceqz", la_codec_cj_ofs21, la_fmt_cj_offs21 }, + { "bcnez", la_codec_cj_ofs21, la_fmt_cj_offs21 }, + { "jirl", la_codec_2r_im16, la_fmt_rd_rj_offs16 }, + { "b", la_codec_ofs26, la_fmt_offs26 }, + { "bl", la_codec_ofs26, la_fmt_offs26 }, + { "beq", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "bne", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "blt", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "bge", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "bltu", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "bgeu", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + +}; + + +/* decode opcode */ +static void decode_insn_opcode(la_decode *dec) +{ + uint32_t insn = dec->insn; + uint16_t op = la_op_illegal; + switch ((insn >> 26) & 0x3f) { + case 0x0: + switch ((insn >> 22) & 0xf) { + case 0x0: + switch ((insn >> 18) & 0xf) { + case 0x0: + switch ((insn >> 15) & 0x7) { + case 0x0: + switch ((insn >> 10) & 0x1f) { + case 0x4: + op = la_op_clo_w; + break; + case 0x5: + op = la_op_clz_w; + break; + case 0x6: + op = la_op_cto_w; + break; + case 0x7: + op = la_op_ctz_w; + break; + case 0x8: + op = la_op_clo_d; + break; + case 0x9: + op = la_op_clz_d; + break; + case 0xa: + op = la_op_cto_d; + break; + case 0xb: + op = la_op_ctz_d; + break; + case 0xc: + op = la_op_revb_2h; + break; + case 0xd: + op = la_op_revb_4h; + break; + case 0xe: + op = la_op_revb_2w; + break; + case 0xf: + op = la_op_revb_d; + break; + case 0x10: + op = la_op_revh_2w; + break; + case 0x11: + op = la_op_revh_d; + break; + case 0x12: + op = la_op_bitrev_4b; + break; + case 0x13: + op = la_op_bitrev_8b; + break; + case 0x14: + op = la_op_bitrev_w; + break; + case 0x15: + op = la_op_bitrev_d; + break; + case 0x16: + op = la_op_ext_w_h; + break; + case 0x17: + op = la_op_ext_w_b; + break; + case 0x18: + op = la_op_rdtimel_w; + break; + case 0x19: + op = la_op_rdtimeh_w; + break; + case 0x1a: + op = la_op_rdtime_d; + break; + case 0x1b: + op = la_op_cpucfg; + break; + } + break; + case 0x2: + switch (insn & 0x0000001f) { + case 0x00000000: + op = la_op_asrtle_d; + break; + } + break; + case 0x3: + switch (insn & 0x0000001f) { + case 0x00000000: + op = la_op_asrtgt_d; + break; + } + break; + } + break; + case 0x1: + switch ((insn >> 17) & 0x1) { + case 0x0: + op = la_op_alsl_w; + break; + case 0x1: + op = la_op_alsl_wu; + break; + } + break; + case 0x2: + switch ((insn >> 17) & 0x1) { + case 0x0: + op = la_op_bytepick_w; + break; + } + break; + case 0x3: + op = la_op_bytepick_d; + break; + case 0x4: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_add_w; + break; + case 0x1: + op = la_op_add_d; + break; + case 0x2: + op = la_op_sub_w; + break; + case 0x3: + op = la_op_sub_d; + break; + case 0x4: + op = la_op_slt; + break; + case 0x5: + op = la_op_sltu; + break; + case 0x6: + op = la_op_maskeqz; + break; + case 0x7: + op = la_op_masknez; + break; + } + break; + case 0x5: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_nor; + break; + case 0x1: + op = la_op_and; + break; + case 0x2: + op = la_op_or; + break; + case 0x3: + op = la_op_xor; + break; + case 0x4: + op = la_op_orn; + break; + case 0x5: + op = la_op_andn; + break; + case 0x6: + op = la_op_sll_w; + break; + case 0x7: + op = la_op_srl_w; + break; + } + break; + case 0x6: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_sra_w; + break; + case 0x1: + op = la_op_sll_d; + break; + case 0x2: + op = la_op_srl_d; + break; + case 0x3: + op = la_op_sra_d; + break; + case 0x6: + op = la_op_rotr_w; + break; + case 0x7: + op = la_op_rotr_d; + break; + } + break; + case 0x7: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_mul_w; + break; + case 0x1: + op = la_op_mulh_w; + break; + case 0x2: + op = la_op_mulh_wu; + break; + case 0x3: + op = la_op_mul_d; + break; + case 0x4: + op = la_op_mulh_d; + break; + case 0x5: + op = la_op_mulh_du; + break; + case 0x6: + op = la_op_mulw_d_w; + break; + case 0x7: + op = la_op_mulw_d_wu; + break; + } + break; + case 0x8: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_div_w; + break; + case 0x1: + op = la_op_mod_w; + break; + case 0x2: + op = la_op_div_wu; + break; + case 0x3: + op = la_op_mod_wu; + break; + case 0x4: + op = la_op_div_d; + break; + case 0x5: + op = la_op_mod_d; + break; + case 0x6: + op = la_op_div_du; + break; + case 0x7: + op = la_op_mod_du; + break; + } + break; + case 0x9: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_crc_w_b_w; + break; + case 0x1: + op = la_op_crc_w_h_w; + break; + case 0x2: + op = la_op_crc_w_w_w; + break; + case 0x3: + op = la_op_crc_w_d_w; + break; + case 0x4: + op = la_op_crcc_w_b_w; + break; + case 0x5: + op = la_op_crcc_w_h_w; + break; + case 0x6: + op = la_op_crcc_w_w_w; + break; + case 0x7: + op = la_op_crcc_w_d_w; + break; + } + break; + case 0xa: + switch ((insn >> 15) & 0x7) { + case 0x4: + op = la_op_break; + break; + case 0x6: + op = la_op_syscall; + break; + } + break; + case 0xb: + switch ((insn >> 17) & 0x1) { + case 0x0: + op = la_op_alsl_d; + break; + } + break; + } + break; + case 0x1: + switch ((insn >> 21) & 0x1) { + case 0x0: + switch ((insn >> 16) & 0x1f) { + case 0x0: + switch ((insn >> 15) & 0x1) { + case 0x1: + op = la_op_slli_w; + break; + } + break; + case 0x1: + op = la_op_slli_d; + break; + case 0x4: + switch ((insn >> 15) & 0x1) { + case 0x1: + op = la_op_srli_w; + break; + } + break; + case 0x5: + op = la_op_srli_d; + break; + case 0x8: + switch ((insn >> 15) & 0x1) { + case 0x1: + op = la_op_srai_w; + break; + } + break; + case 0x9: + op = la_op_srai_d; + break; + case 0xc: + switch ((insn >> 15) & 0x1) { + case 0x1: + op = la_op_rotri_w; + break; + } + break; + case 0xd: + op = la_op_rotri_d; + break; + } + break; + case 0x1: + switch ((insn >> 15) & 0x1) { + case 0x0: + op = la_op_bstrins_w; + break; + case 0x1: + op = la_op_bstrpick_w; + break; + } + break; + } + break; + case 0x2: + op = la_op_bstrins_d; + break; + case 0x3: + op = la_op_bstrpick_d; + break; + case 0x4: + switch ((insn >> 15) & 0x7f) { + case 0x1: + op = la_op_fadd_s; + break; + case 0x2: + op = la_op_fadd_d; + break; + case 0x5: + op = la_op_fsub_s; + break; + case 0x6: + op = la_op_fsub_d; + break; + case 0x9: + op = la_op_fmul_s; + break; + case 0xa: + op = la_op_fmul_d; + break; + case 0xd: + op = la_op_fdiv_s; + break; + case 0xe: + op = la_op_fdiv_d; + break; + case 0x11: + op = la_op_fmax_s; + break; + case 0x12: + op = la_op_fmax_d; + break; + case 0x15: + op = la_op_fmin_s; + break; + case 0x16: + op = la_op_fmin_d; + break; + case 0x19: + op = la_op_fmaxa_s; + break; + case 0x1a: + op = la_op_fmaxa_d; + break; + case 0x1d: + op = la_op_fmina_s; + break; + case 0x1e: + op = la_op_fmina_d; + break; + case 0x21: + op = la_op_fscaleb_s; + break; + case 0x22: + op = la_op_fscaleb_d; + break; + case 0x25: + op = la_op_fcopysign_s; + break; + case 0x26: + op = la_op_fcopysign_d; + break; + case 0x28: + switch ((insn >> 10) & 0x1f) { + case 0x1: + op = la_op_fabs_s; + break; + case 0x2: + op = la_op_fabs_d; + break; + case 0x5: + op = la_op_fneg_s; + break; + case 0x6: + op = la_op_fneg_d; + break; + case 0x9: + op = la_op_flogb_s; + break; + case 0xa: + op = la_op_flogb_d; + break; + case 0xd: + op = la_op_fclass_s; + break; + case 0xe: + op = la_op_fclass_d; + break; + case 0x11: + op = la_op_fsqrt_s; + break; + case 0x12: + op = la_op_fsqrt_d; + break; + case 0x15: + op = la_op_frecip_s; + break; + case 0x16: + op = la_op_frecip_d; + break; + case 0x19: + op = la_op_frsqrt_s; + break; + case 0x1a: + op = la_op_frsqrt_d; + break; + } + break; + case 0x29: + switch ((insn >> 10) & 0x1f) { + case 0x5: + op = la_op_fmov_s; + break; + case 0x6: + op = la_op_fmov_d; + break; + case 0x9: + op = la_op_movgr2fr_w; + break; + case 0xa: + op = la_op_movgr2fr_d; + break; + case 0xb: + op = la_op_movgr2frh_w; + break; + case 0xd: + op = la_op_movfr2gr_s; + break; + case 0xe: + op = la_op_movfr2gr_d; + break; + case 0xf: + op = la_op_movfrh2gr_s; + break; + case 0x10: + op = la_op_movgr2fcsr; + break; + case 0x12: + op = la_op_movfcsr2gr; + break; + case 0x14: + switch ((insn >> 3) & 0x3) { + case 0x0: + op = la_op_movfr2cf; + break; + } + break; + case 0x15: + switch ((insn >> 8) & 0x3) { + case 0x0: + op = la_op_movcf2fr; + break; + } + break; + case 0x16: + switch ((insn >> 3) & 0x3) { + case 0x0: + op = la_op_movgr2cf; + break; + } + break; + case 0x17: + switch ((insn >> 8) & 0x3) { + case 0x0: + op = la_op_movcf2gr; + break; + } + break; + } + break; + case 0x32: + switch ((insn >> 10) & 0x1f) { + case 0x6: + op = la_op_fcvt_s_d; + break; + case 0x9: + op = la_op_fcvt_d_s; + break; + } + break; + case 0x34: + switch ((insn >> 10) & 0x1f) { + case 0x1: + op = la_op_ftintrm_w_s; + break; + case 0x2: + op = la_op_ftintrm_w_d; + break; + case 0x9: + op = la_op_ftintrm_l_s; + break; + case 0xa: + op = la_op_ftintrm_l_d; + break; + case 0x11: + op = la_op_ftintrp_w_s; + break; + case 0x12: + op = la_op_ftintrp_w_d; + break; + case 0x19: + op = la_op_ftintrp_l_s; + break; + case 0x1a: + op = la_op_ftintrp_l_d; + break; + } + break; + case 0x35: + switch ((insn >> 10) & 0x1f) { + case 0x1: + op = la_op_ftintrz_w_s; + break; + case 0x2: + op = la_op_ftintrz_w_d; + break; + case 0x9: + op = la_op_ftintrz_l_s; + break; + case 0xa: + op = la_op_ftintrz_l_d; + break; + case 0x11: + op = la_op_ftintrne_w_s; + break; + case 0x12: + op = la_op_ftintrne_w_d; + break; + case 0x19: + op = la_op_ftintrne_l_s; + break; + case 0x1a: + op = la_op_ftintrne_l_d; + break; + } + break; + case 0x36: + switch ((insn >> 10) & 0x1f) { + case 0x1: + op = la_op_ftint_w_s; + break; + case 0x2: + op = la_op_ftint_w_d; + break; + case 0x9: + op = la_op_ftint_l_s; + break; + case 0xa: + op = la_op_ftint_l_d; + break; + } + break; + case 0x3a: + switch ((insn >> 10) & 0x1f) { + case 0x4: + op = la_op_ffint_s_w; + break; + case 0x6: + op = la_op_ffint_s_l; + break; + case 0x8: + op = la_op_ffint_d_w; + break; + case 0xa: + op = la_op_ffint_d_l; + break; + } + break; + case 0x3c: + switch ((insn >> 10) & 0x1f) { + case 0x11: + op = la_op_frint_s; + break; + case 0x12: + op = la_op_frint_d; + break; + } + break; + } + break; + case 0x8: + op = la_op_slti; + break; + case 0x9: + op = la_op_sltui; + break; + case 0xa: + op = la_op_addi_w; + break; + case 0xb: + op = la_op_addi_d; + break; + case 0xc: + op = la_op_lu52i_d; + break; + case 0xd: + op = la_op_addi; + break; + case 0xe: + op = la_op_ori; + break; + case 0xf: + op = la_op_xori; + break; + } + break; + case 0x2: + switch ((insn >> 20) & 0x3f) { + case 0x1: + op = la_op_fmadd_s; + break; + case 0x2: + op = la_op_fmadd_d; + break; + case 0x5: + op = la_op_fmsub_s; + break; + case 0x6: + op = la_op_fmsub_d; + break; + case 0x9: + op = la_op_fnmadd_s; + break; + case 0xa: + op = la_op_fnmadd_d; + break; + case 0xd: + op = la_op_fnmsub_s; + break; + case 0xe: + op = la_op_fnmsub_d; + break; + } + break; + case 0x3: + switch ((insn >> 20) & 0x3f) { + case 0x1: + switch ((insn >> 3) & 0x3) { + case 0x0: + op = la_op_fcmp_cond_s; + break; + } + break; + case 0x2: + switch ((insn >> 3) & 0x3) { + case 0x0: + op = la_op_fcmp_cond_d; + break; + } + break; + case 0x10: + switch ((insn >> 18) & 0x3) { + case 0x0: + op = la_op_fsel; + break; + } + break; + } + break; + case 0x4: + op = la_op_addu16i_d; + break; + case 0x5: + switch ((insn >> 25) & 0x1) { + case 0x0: + op = la_op_lu12i_w; + break; + case 0x1: + op = la_op_lu32i_d; + break; + } + break; + case 0x6: + switch ((insn >> 25) & 0x1) { + case 0x0: + op = la_op_pcaddi; + break; + case 0x1: + op = la_op_pcalau12i; + break; + } + break; + case 0x7: + switch ((insn >> 25) & 0x1) { + case 0x0: + op = la_op_pcaddu12i; + break; + case 0x1: + op = la_op_pcaddu18i; + break; + } + break; + case 0x8: + switch ((insn >> 24) & 0x3) { + case 0x0: + op = la_op_ll_w; + break; + case 0x1: + op = la_op_sc_w; + break; + case 0x2: + op = la_op_ll_d; + break; + case 0x3: + op = la_op_sc_d; + break; + } + break; + case 0x9: + switch ((insn >> 24) & 0x3) { + case 0x0: + op = la_op_ldptr_w; + break; + case 0x1: + op = la_op_stptr_w; + break; + case 0x2: + op = la_op_ldptr_d; + break; + case 0x3: + op = la_op_stptr_d; + break; + } + break; + case 0xa: + switch ((insn >> 22) & 0xf) { + case 0x0: + op = la_op_ld_b; + break; + case 0x1: + op = la_op_ld_h; + break; + case 0x2: + op = la_op_ld_w; + break; + case 0x3: + op = la_op_ld_d; + break; + case 0x4: + op = la_op_st_b; + break; + case 0x5: + op = la_op_st_h; + break; + case 0x6: + op = la_op_st_w; + break; + case 0x7: + op = la_op_st_d; + break; + case 0x8: + op = la_op_ld_bu; + break; + case 0x9: + op = la_op_ld_hu; + break; + case 0xa: + op = la_op_ld_wu; + break; + case 0xb: + op = la_op_preld; + break; + case 0xc: + op = la_op_fld_s; + break; + case 0xd: + op = la_op_fst_s; + break; + case 0xe: + op = la_op_fld_d; + break; + case 0xf: + op = la_op_fst_d; + break; + } + break; + case 0xe: + switch ((insn >> 15) & 0x7ff) { + case 0x0: + op = la_op_ldx_b; + break; + case 0x8: + op = la_op_ldx_h; + break; + case 0x10: + op = la_op_ldx_w; + break; + case 0x18: + op = la_op_ldx_d; + break; + case 0x20: + op = la_op_stx_b; + break; + case 0x28: + op = la_op_stx_h; + break; + case 0x30: + op = la_op_stx_w; + break; + case 0x38: + op = la_op_stx_d; + break; + case 0x40: + op = la_op_ldx_bu; + break; + case 0x48: + op = la_op_ldx_hu; + break; + case 0x50: + op = la_op_ldx_wu; + break; + case 0x60: + op = la_op_fldx_s; + break; + case 0x68: + op = la_op_fldx_d; + break; + case 0x70: + op = la_op_fstx_s; + break; + case 0x78: + op = la_op_fstx_d; + break; + case 0xc0: + op = la_op_amswap_w; + break; + case 0xc1: + op = la_op_amswap_d; + break; + case 0xc2: + op = la_op_amadd_w; + break; + case 0xc3: + op = la_op_amadd_d; + break; + case 0xc4: + op = la_op_amand_w; + break; + case 0xc5: + op = la_op_amand_d; + break; + case 0xc6: + op = la_op_amor_w; + break; + case 0xc7: + op = la_op_amor_d; + break; + case 0xc8: + op = la_op_amxor_w; + break; + case 0xc9: + op = la_op_amxor_d; + break; + case 0xca: + op = la_op_ammax_w; + break; + case 0xcb: + op = la_op_ammax_d; + break; + case 0xcc: + op = la_op_ammin_w; + break; + case 0xcd: + op = la_op_ammin_d; + break; + case 0xce: + op = la_op_ammax_wu; + break; + case 0xcf: + op = la_op_ammax_du; + break; + case 0xd0: + op = la_op_ammin_wu; + break; + case 0xd1: + op = la_op_ammin_du; + break; + case 0xd2: + op = la_op_amswap_db_w; + break; + case 0xd3: + op = la_op_amswap_db_d; + break; + case 0xd4: + op = la_op_amadd_db_w; + break; + case 0xd5: + op = la_op_amadd_db_d; + break; + case 0xd6: + op = la_op_amand_db_w; + break; + case 0xd7: + op = la_op_amand_db_d; + break; + case 0xd8: + op = la_op_amor_db_w; + break; + case 0xd9: + op = la_op_amor_db_d; + break; + case 0xda: + op = la_op_amxor_db_w; + break; + case 0xdb: + op = la_op_amxor_db_d; + break; + case 0xdc: + op = la_op_ammax_db_w; + break; + case 0xdd: + op = la_op_ammax_db_d; + break; + case 0xde: + op = la_op_ammin_db_w; + break; + case 0xdf: + op = la_op_ammin_db_d; + break; + case 0xe0: + op = la_op_ammax_db_wu; + break; + case 0xe1: + op = la_op_ammax_db_du; + break; + case 0xe2: + op = la_op_ammin_db_wu; + break; + case 0xe3: + op = la_op_ammin_db_du; + break; + case 0xe4: + op = la_op_dbar; + break; + case 0xe5: + op = la_op_ibar; + break; + case 0xe8: + op = la_op_fldgt_s; + break; + case 0xe9: + op = la_op_fldgt_d; + break; + case 0xea: + op = la_op_fldle_s; + break; + case 0xeb: + op = la_op_fldle_d; + break; + case 0xec: + op = la_op_fstgt_s; + break; + case 0xed: + op = la_op_fstgt_d; + break; + case 0xee: + op = ls_op_fstle_s; + break; + case 0xef: + op = la_op_fstle_d; + break; + case 0xf0: + op = la_op_ldgt_b; + break; + case 0xf1: + op = la_op_ldgt_h; + break; + case 0xf2: + op = la_op_ldgt_w; + break; + case 0xf3: + op = la_op_ldgt_d; + break; + case 0xf4: + op = la_op_ldle_b; + break; + case 0xf5: + op = la_op_ldle_h; + break; + case 0xf6: + op = la_op_ldle_w; + break; + case 0xf7: + op = la_op_ldle_d; + break; + case 0xf8: + op = la_op_stgt_b; + break; + case 0xf9: + op = la_op_stgt_h; + break; + case 0xfa: + op = la_op_stgt_w; + break; + case 0xfb: + op = la_op_stgt_d; + break; + case 0xfc: + op = la_op_stle_b; + break; + case 0xfd: + op = la_op_stle_h; + break; + case 0xfe: + op = la_op_stle_w; + break; + case 0xff: + op = la_op_stle_d; + break; + } + break; + case 0x10: + op = la_op_beqz; + break; + case 0x11: + op = la_op_bnez; + break; + case 0x12: + switch ((insn >> 8) & 0x3) { + case 0x0: + op = la_op_bceqz; + break; + case 0x1: + op = la_op_bcnez; + break; + } + break; + case 0x13: + op = la_op_jirl; + break; + case 0x14: + op = la_op_b; + break; + case 0x15: + op = la_op_bl; + break; + case 0x16: + op = la_op_beq; + break; + case 0x17: + op = la_op_bne; + break; + case 0x18: + op = la_op_blt; + break; + case 0x19: + op = la_op_bge; + break; + case 0x1a: + op = la_op_bltu; + break; + case 0x1b: + op = la_op_bgeu; + break; + default: + op = la_op_illegal; + break; + } + dec->op = op; +} + +/* operand extractors */ +#define IM_5 5 +#define IM_8 8 +#define IM_12 12 +#define IM_14 14 +#define IM_15 15 +#define IM_16 16 +#define IM_20 20 +#define IM_21 21 +#define IM_26 26 + +static uint32_t operand_r1(uint32_t insn) +{ + return insn & 0x1f; +} + +static uint32_t operand_r2(uint32_t insn) +{ + return (insn >> 5) & 0x1f; +} + +static uint32_t operand_r3(uint32_t insn) +{ + return (insn >> 10) & 0x1f; +} + +static uint32_t operand_r4(uint32_t insn) +{ + return (insn >> 15) & 0x1f; +} + +static uint32_t operand_u6(uint32_t insn) +{ + return (insn >> 10) & 0x3f; +} + +static uint32_t operand_bw1(uint32_t insn) +{ + return (insn >> 10) & 0x1f; +} + +static uint32_t operand_bw2(uint32_t insn) +{ + return (insn >> 16) & 0x1f; +} + +static uint32_t operand_bd1(uint32_t insn) +{ + return (insn >> 10) & 0x3f; +} + +static uint32_t operand_bd2(uint32_t insn) +{ + return (insn >> 16) & 0x3f; +} + +static uint32_t operand_sa2(uint32_t insn) +{ + return (insn >> 15) & 0x3; +} + +static uint32_t operand_sa3(uint32_t insn) +{ + return (insn >> 15) & 0x3; +} + +static int32_t operand_im20(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 5) & 0xfffff); + return imm > (1 << 19) ? imm - (1 << 20) : imm; +} + +static int32_t operand_im16(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 10) & 0xffff); + return imm > (1 << 15) ? imm - (1 << 16) : imm; +} + +static int32_t operand_im14(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 10) & 0x3fff); + return imm > (1 << 13) ? imm - (1 << 14) : imm; +} + +static int32_t operand_im12(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 10) & 0xfff); + return imm > (1 << 11) ? imm - (1 << 12) : imm; +} + +static int32_t operand_im8(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 10) & 0xff); + return imm > (1 << 7) ? imm - (1 << 8) : imm; +} + +static uint32_t operand_sd(uint32_t insn) +{ + return insn & 0x3; +} + +static uint32_t operand_sj(uint32_t insn) +{ + return (insn >> 5) & 0x3; +} + +static uint32_t operand_cd(uint32_t insn) +{ + return insn & 0x7; +} + +static uint32_t operand_cj(uint32_t insn) +{ + return (insn >> 5) & 0x7; +} + +static uint32_t operand_code(uint32_t insn) +{ + return insn & 0x7fff; +} + +static int32_t operand_whint(uint32_t insn) +{ + int32_t imm = (int32_t)(insn & 0x7fff); + return imm > (1 << 14) ? imm - (1 << 15) : imm; +} + +static int32_t operand_invop(uint32_t insn) +{ + int32_t imm = (int32_t)(insn & 0x1f); + return imm > (1 << 4) ? imm - (1 << 5) : imm; +} + +static int32_t operand_ofs21(uint32_t insn) +{ + int32_t imm = (((int32_t)insn & 0x1f) << 16) | + ((insn >> 10) & 0xffff); + return imm > (1 << 20) ? imm - (1 << 21) : imm; +} + +static int32_t operand_ofs26(uint32_t insn) +{ + int32_t imm = (((int32_t)insn & 0x3ff) << 16) | + ((insn >> 10) & 0xffff); + return imm > (1 << 25) ? imm - (1 << 26) : imm; +} + +static uint32_t operand_fcond(uint32_t insn) +{ + return (insn >> 15) & 0x1f; +} + +static uint32_t operand_sel(uint32_t insn) +{ + return (insn >> 15) & 0x7; +} + +/* decode operands */ +static void decode_insn_operands(la_decode *dec) +{ + uint32_t insn = dec->insn; + dec->codec = opcode_data[dec->op].codec; + switch (dec->codec) { + case la_codec_illegal: + case la_codec_empty: + break; + case la_codec_2r: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + break; + case la_codec_2r_u5: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + break; + case la_codec_2r_u6: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_u6(insn); + break; + case la_codec_2r_2bw: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_bw1(insn); + dec->r4 = operand_bw2(insn); + break; + case la_codec_2r_2bd: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_bd1(insn); + dec->r4 = operand_bd2(insn); + break; + case la_codec_3r: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + break; + case la_codec_3r_rd0: + dec->r1 = 0; + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + break; + case la_codec_3r_sa2: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_sa2(insn); + break; + case la_codec_3r_sa3: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_sa3(insn); + break; + case la_codec_4r: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_r4(insn); + break; + case la_codec_r_im20: + dec->r1 = operand_r1(insn); + dec->imm = operand_im20(insn); + dec->bit = IM_20; + break; + case la_codec_2r_im16: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im16(insn); + dec->bit = IM_16; + break; + case la_codec_2r_im14: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im14(insn); + dec->bit = IM_14; + break; + case la_codec_r_im14: + dec->r1 = operand_r1(insn); + dec->imm = operand_im14(insn); + dec->bit = IM_14; + break; + case la_codec_im5_r_im12: + dec->imm2 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im12(insn); + dec->bit = IM_12; + break; + case la_codec_2r_im12: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im12(insn); + dec->bit = IM_12; + break; + case la_codec_2r_im8: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im8(insn); + dec->bit = IM_8; + break; + case la_codec_r_sd: + dec->r1 = operand_sd(insn); + dec->r2 = operand_r2(insn); + break; + case la_codec_r_sj: + dec->r1 = operand_r1(insn); + dec->r2 = operand_sj(insn); + break; + case la_codec_r_cd: + dec->r1 = operand_cd(insn); + dec->r2 = operand_r2(insn); + break; + case la_codec_r_cj: + dec->r1 = operand_r1(insn); + dec->r2 = operand_cj(insn); + break; + case la_codec_r_seq: + dec->r1 = 0; + dec->r2 = operand_r1(insn); + dec->imm = operand_im8(insn); + dec->bit = IM_8; + break; + case la_codec_code: + dec->code = operand_code(insn); + break; + case la_codec_whint: + dec->imm = operand_whint(insn); + dec->bit = IM_15; + break; + case la_codec_invtlb: + dec->imm = operand_invop(insn); + dec->bit = IM_5; + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + break; + case la_codec_r_ofs21: + dec->imm = operand_ofs21(insn); + dec->bit = IM_21; + dec->r2 = operand_r2(insn); + break; + case la_codec_cj_ofs21: + dec->imm = operand_ofs21(insn); + dec->bit = IM_21; + dec->r2 = operand_cj(insn); + break; + case la_codec_ofs26: + dec->imm = operand_ofs26(insn); + dec->bit = IM_26; + break; + case la_codec_cond: + dec->r1 = operand_cd(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_fcond(insn); + break; + case la_codec_sel: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_sel(insn); + break; + } +} + +/* format instruction */ +static void append(char *s1, const char *s2, size_t n) +{ + size_t l1 = strlen(s1); + if (n - l1 - 1 > 0) { + strncat(s1, s2, n - l1); + } +} + +static void format_insn(char *buf, size_t buflen, size_t tab, la_decode *dec) +{ + char tmp[16]; + const char *fmt; + + fmt = opcode_data[dec->op].format; + while (*fmt) { + switch (*fmt) { + case 'n': /* name */ + append(buf, opcode_data[dec->op].name, buflen); + break; + case 's': + append(buf, "s", buflen); + break; + case 'd': + append(buf, "d", buflen); + break; + case 'e': /* illegal */ + snprintf(tmp, sizeof(tmp), "%x", dec->insn); + append(buf, tmp, buflen); + break; + case 't': + while (strlen(buf) < tab) { + append(buf, " ", buflen); + } + break; + case '(': + append(buf, "(", buflen); + break; + case ',': + append(buf, ",", buflen); + break; + case '.': + append(buf, ".", buflen); + break; + case ')': + append(buf, ")", buflen); + break; + case '0': /* rd */ + append(buf, loongarch_r_normal_name[dec->r1], buflen); + break; + case '1': /* rj */ + append(buf, loongarch_r_normal_name[dec->r2], buflen); + break; + case '2': /* rk */ + append(buf, loongarch_r_normal_name[dec->r3], buflen); + break; + case '3': /* fd */ + append(buf, loongarch_f_normal_name[dec->r1], buflen); + break; + case '4': /* fj */ + append(buf, loongarch_f_normal_name[dec->r2], buflen); + break; + case '5': /* fk */ + append(buf, loongarch_f_normal_name[dec->r3], buflen); + break; + case '6': /* fa */ + append(buf, loongarch_f_normal_name[dec->r4], buflen); + break; + case 'A': /* sd */ + append(buf, loongarch_cr_normal_name[dec->r1], buflen); + break; + case 'B': /* sj */ + append(buf, loongarch_cr_normal_name[dec->r2], buflen); + break; + case 'C': /* r3 */ + snprintf(tmp, sizeof(tmp), "%x", dec->r3); + append(buf, tmp, buflen); + break; + case 'D': /* r4 */ + snprintf(tmp, sizeof(tmp), "%x", dec->r4); + append(buf, tmp, buflen); + break; + case 'E': /* r1 */ + snprintf(tmp, sizeof(tmp), "%x", dec->r1); + append(buf, tmp, buflen); + break; + case 'F': /* fcsrd */ + append(buf, loongarch_r_normal_name[dec->r1], buflen); + break; + case 'G': /* fcsrs */ + append(buf, loongarch_r_normal_name[dec->r2], buflen); + break; + case 'H': /* cd */ + append(buf, loongarch_c_normal_name[dec->r1], buflen); + break; + case 'I': /* cj */ + append(buf, loongarch_c_normal_name[dec->r2], buflen); + break; + case 'J': /* code */ + snprintf(tmp, sizeof(tmp), "0x%x", dec->code); + append(buf, tmp, buflen); + break; + case 'K': /* cond */ + switch (dec->r4) { + case 0x0: + append(buf, "caf", buflen); + break; + case 0x1: + append(buf, "saf", buflen); + break; + case 0x2: + append(buf, "clt", buflen); + break; + case 0x3: + append(buf, "slt", buflen); + break; + case 0x4: + append(buf, "ceq", buflen); + break; + case 0x5: + append(buf, "seq", buflen); + break; + case 0x6: + append(buf, "cle", buflen); + break; + case 0x7: + append(buf, "sle", buflen); + break; + case 0x8: + append(buf, "cun", buflen); + break; + case 0x9: + append(buf, "sun", buflen); + break; + case 0xA: + append(buf, "cult", buflen); + break; + case 0xB: + append(buf, "sult", buflen); + break; + case 0xC: + append(buf, "cueq", buflen); + break; + case 0xD: + append(buf, "sueq", buflen); + break; + case 0xE: + append(buf, "cule", buflen); + break; + case 0xF: + append(buf, "sule", buflen); + break; + case 0x10: + append(buf, "cne", buflen); + break; + case 0x11: + append(buf, "sne", buflen); + break; + case 0x14: + append(buf, "cor", buflen); + break; + case 0x15: + append(buf, "sor", buflen); + break; + case 0x18: + append(buf, "cune", buflen); + break; + case 0x19: + append(buf, "sune", buflen); + break; + } + break; + case 'L': /* ca */ + append(buf, loongarch_c_normal_name[dec->r4], buflen); + break; + case 'M': /* cop */ + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm2) & 0x1f); + append(buf, tmp, buflen); + break; + case 'i': /* sixx d */ + snprintf(tmp, sizeof(tmp), "%d", dec->imm); + append(buf, tmp, buflen); + break; + case 'o': /* offset */ + snprintf(tmp, sizeof(tmp), "%d", (dec->imm) << 2); + append(buf, tmp, buflen); + break; + case 'x': /* sixx x */ + switch (dec->bit) { + case IM_5: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x1f); + append(buf, tmp, buflen); + break; + case IM_8: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xff); + append(buf, tmp, buflen); + break; + case IM_12: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfff); + append(buf, tmp, buflen); + break; + case IM_14: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x3fff); + append(buf, tmp, buflen); + break; + case IM_15: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x7fff); + append(buf, tmp, buflen); + break; + case IM_16: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xffff); + append(buf, tmp, buflen); + break; + case IM_20: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfffff); + append(buf, tmp, buflen); + break; + default: + snprintf(tmp, sizeof(tmp), "0x%x", dec->imm); + append(buf, tmp, buflen); + break; + } + break; + case 'X': /* offset x*/ + switch (dec->bit) { + case IM_16: + snprintf(tmp, sizeof(tmp), "0x%x", + ((dec->imm) << 2) & 0xffff); + append(buf, tmp, buflen); + break; + case IM_21: + snprintf(tmp, sizeof(tmp), "0x%x", + ((dec->imm) << 2) & 0x1fffff); + append(buf, tmp, buflen); + break; + case IM_26: + snprintf(tmp, sizeof(tmp), "0x%x", + ((dec->imm) << 2) & 0x3ffffff); + append(buf, tmp, buflen); + break; + default: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) << 2); + append(buf, tmp, buflen); + break; + } + break; + case 'p': /* pc */ + snprintf(tmp, sizeof(tmp), " # 0x%"PRIx32"", + dec->pc + ((dec->imm) << 2)); + append(buf, tmp, buflen); + break; + default: + break; + } + fmt++; + } +} + +/* disassemble instruction */ +static void +disasm_insn(char *buf, size_t buflen, bfd_vma pc, unsigned long int insn) +{ + la_decode dec = { 0 }; + dec.pc = pc; + dec.insn = insn; + decode_insn_opcode(&dec); + decode_insn_operands(&dec); + format_insn(buf, buflen, 16, &dec); +} + +int +print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info) +{ + char buf[128] = { 0 }; + bfd_byte buffer[INSNLEN]; + unsigned long insn; + int status; + + status = (*info->read_memory_func)(memaddr, buffer, INSNLEN, info); + if (status == 0) { + insn = (uint32_t) bfd_getl32(buffer); + (*info->fprintf_func)(info->stream, "%08" PRIx64 " ", insn); + } else { + (*info->memory_error_func)(status, memaddr, info); + return -1; + } + disasm_insn(buf, sizeof(buf), memaddr, insn); + (*info->fprintf_func)(info->stream, "\t%s", buf); + return INSNLEN; +} diff --git a/disas/meson.build b/disas/meson.build index 449f99e..a1bd8b8 100644 --- a/disas/meson.build +++ b/disas/meson.build @@ -9,6 +9,7 @@ common_ss.add(when: 'CONFIG_CRIS_DIS', if_true: files('cris.c')) common_ss.add(when: 'CONFIG_HEXAGON_DIS', if_true: files('hexagon.c')) common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c')) common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c')) +common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: files('loongarch.c')) common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c')) common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c')) common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c')) diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h index 524f291..009a03a 100644 --- a/include/disas/dis-asm.h +++ b/include/disas/dis-asm.h @@ -253,6 +253,7 @@ enum bfd_architecture #define bfd_mach_rx 0x75 #define bfd_mach_rx_v2 0x76 #define bfd_mach_rx_v3 0x77 + bfd_arch_loongarch, bfd_arch_last }; #define bfd_mach_s390_31 31 @@ -462,6 +463,7 @@ int print_insn_riscv32 (bfd_vma, disassemble_info*); int print_insn_riscv64 (bfd_vma, disassemble_info*); int print_insn_rx(bfd_vma, disassemble_info *); int print_insn_hexagon(bfd_vma, disassemble_info *); +int print_insn_loongarch(bfd_vma, disassemble_info *); #ifdef CONFIG_CAPSTONE bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size); diff --git a/meson.build b/meson.build index bf63784..08131fc 100644 --- a/meson.build +++ b/meson.build @@ -1499,6 +1499,7 @@ disassemblers = { 'sh4' : ['CONFIG_SH4_DIS'], 'sparc' : ['CONFIG_SPARC_DIS'], 'xtensa' : ['CONFIG_XTENSA_DIS'], + 'loongarch' : ['CONFIG_LOONGARCH_DIS'], } if link_language == 'cpp' disassemblers += { From patchwork Fri Aug 27 07:14:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461401 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=-14.0 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 72B6CC4320E for ; Fri, 27 Aug 2021 07:35: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 1074360FD9 for ; Fri, 27 Aug 2021 07:35:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1074360FD9 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]:47300 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWOn-0000rU-2i for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 03:35:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53384) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5s-0001Yu-SK for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:16:05 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59876 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5g-0003XX-5O for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:16:04 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S19; Fri, 27 Aug 2021 15:15:36 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 17/19] LoongArch Linux User Emulation Date: Fri, 27 Aug 2021 15:14:52 +0800 Message-Id: <1630048494-2143-18-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S19 X-Coremail-Antispam: 1UD129KBjvAXoWfZrWrAr4fGr4DKF4rGw45KFg_yoWrXr1kAo WxJF1aqw1kGr1fua1kWw17Wr1UZF9rJF18Jr4UAFy8GFnFqr1DWr13tay8WFn3ArySgFy5 tFyjqr1qya90yF1kn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- include/elf.h | 2 + linux-user/elfload.c | 58 ++++++ linux-user/loongarch64/cpu_loop.c | 108 ++++++++++ linux-user/loongarch64/signal.c | 178 +++++++++++++++++ linux-user/loongarch64/sockbits.h | 1 + linux-user/loongarch64/syscall_nr.h | 307 +++++++++++++++++++++++++++++ linux-user/loongarch64/target_cpu.h | 36 ++++ linux-user/loongarch64/target_elf.h | 14 ++ linux-user/loongarch64/target_errno_defs.h | 7 + linux-user/loongarch64/target_fcntl.h | 12 ++ linux-user/loongarch64/target_signal.h | 28 +++ linux-user/loongarch64/target_structs.h | 49 +++++ linux-user/loongarch64/target_syscall.h | 46 +++++ linux-user/loongarch64/termbits.h | 229 +++++++++++++++++++++ linux-user/syscall_defs.h | 10 +- 15 files changed, 1081 insertions(+), 4 deletions(-) create mode 100644 linux-user/loongarch64/cpu_loop.c create mode 100644 linux-user/loongarch64/signal.c create mode 100644 linux-user/loongarch64/sockbits.h create mode 100644 linux-user/loongarch64/syscall_nr.h create mode 100644 linux-user/loongarch64/target_cpu.h create mode 100644 linux-user/loongarch64/target_elf.h create mode 100644 linux-user/loongarch64/target_errno_defs.h create mode 100644 linux-user/loongarch64/target_fcntl.h create mode 100644 linux-user/loongarch64/target_signal.h create mode 100644 linux-user/loongarch64/target_structs.h create mode 100644 linux-user/loongarch64/target_syscall.h create mode 100644 linux-user/loongarch64/termbits.h diff --git a/include/elf.h b/include/elf.h index 811bf4a..3a4bcb6 100644 --- a/include/elf.h +++ b/include/elf.h @@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ +#define EM_LOONGARCH 258 /* LoongArch */ + /* * This is an interim value that we will use until the committee comes * up with a final number. diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 01e9a83..cf47ccd 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -909,6 +909,64 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en #endif +#ifdef TARGET_LOONGARCH64 + +#define ELF_START_MMAP 0x80000000 + +#define ELF_CLASS ELFCLASS64 +#define ELF_ARCH EM_LOONGARCH + +#define elf_check_arch(x) ((x) == EM_LOONGARCH) +static inline void init_thread(struct target_pt_regs *regs, + struct image_info *infop) +{ + regs->csr_crmd = 2 << 3; + regs->csr_era = infop->entry; + regs->regs[3] = infop->start_stack; +} + +/* See linux kernel: arch/loongarch/include/asm/elf.h. */ +#define ELF_NREG 45 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +/* See linux kernel: arch/loongarch/include/asm/reg.h. */ +enum { + TARGET_EF_R0 = 0, + TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32, + TARGET_EF_CSR_BADVADDR = TARGET_EF_R0 + 33, +}; + +/* See linux kernel: arch/loongarch/kernel/process.c:loongarch_dump_regs64. */ +static void elf_core_copy_regs(target_elf_gregset_t *regs, + const CPULoongArchState *env) +{ + int i; + + for (i = 0; i < TARGET_EF_R0; i++) { + (*regs)[i] = 0; + } + (*regs)[TARGET_EF_R0] = 0; + + for (i = 1; i < ARRAY_SIZE(env->gpr); i++) { + (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]); + } + + (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc); + (*regs)[TARGET_EF_CSR_BADVADDR] = tswapreg(env->badaddr); +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ + return 0; +} + +#endif /* TARGET_LOONGARCH64 */ + #ifdef TARGET_MIPS #define ELF_START_MMAP 0x80000000 diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c new file mode 100644 index 0000000..bc81d22 --- /dev/null +++ b/linux-user/loongarch64/cpu_loop.c @@ -0,0 +1,108 @@ +/* + * QEMU LoongArch user cpu loop. + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu.h" +#include "qemu-common.h" +#include "cpu_loop-common.h" +#include "elf.h" + +void cpu_loop(CPULoongArchState *env) +{ + CPUState *cs = env_cpu(env); + target_siginfo_t info; + int trapnr; + abi_long ret; + + for (;;) { + cpu_exec_start(cs); + trapnr = cpu_exec(cs); + cpu_exec_end(cs); + process_queued_cpu_work(cs); + + switch (trapnr) { + case EXCP_INTERRUPT: + /* just indicate that signals should be handled asap */ + break; + case EXCP_SYSCALL: + env->pc += 4; + ret = do_syscall(env, env->gpr[11], + env->gpr[4], env->gpr[5], + env->gpr[6], env->gpr[7], + env->gpr[8], env->gpr[9], + -1, -1); + if (ret == -TARGET_ERESTARTSYS) { + env->pc -= 4; + break; + } + if (ret == -TARGET_QEMU_ESIGRETURN) { + /* + * Returning from a successful sigreturn syscall. + * Avoid clobbering register state. + */ + break; + } + env->gpr[4] = ret; + break; + case EXCP_ADE: + info.si_signo = TARGET_SIGSEGV; + info.si_errno = 0; + info.si_code = TARGET_SEGV_MAPERR; + info._sifields._sigfault._addr = env->badaddr; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_INE: + info.si_signo = TARGET_SIGILL; + info.si_errno = 0; + info.si_code = 0; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_FPE: + info.si_signo = TARGET_SIGFPE; + info.si_errno = 0; + info.si_code = TARGET_FPE_FLTUNK; + if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) { + info.si_code = TARGET_FPE_FLTINV; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) { + info.si_code = TARGET_FPE_FLTDIV; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) { + info.si_code = TARGET_FPE_FLTOVF; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) { + info.si_code = TARGET_FPE_FLTUND; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) { + info.si_code = TARGET_FPE_FLTRES; + } + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_BREAK: + info.si_signo = TARGET_SIGTRAP; + info.si_code = TARGET_TRAP_BRKPT; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_ATOMIC: + cpu_exec_step_atomic(cs); + break; + default: + EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", + trapnr); + exit(EXIT_FAILURE); + } + process_pending_signals(env); + } +} + +void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) +{ + int i; + + for (i = 0; i < 32; i++) { + env->gpr[i] = regs->regs[i]; + } + env->pc = regs->csr_era & ~(target_ulong)1; + +} diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c new file mode 100644 index 0000000..2da8317 --- /dev/null +++ b/linux-user/loongarch64/signal.c @@ -0,0 +1,178 @@ +/* + * LoongArch emulation of Linux signals + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu.h" +#include "signal-common.h" +#include "linux-user/trace.h" + +struct target_sigcontext { + uint64_t sc_pc; + uint64_t sc_gpr[32]; + uint64_t sc_fpr[32]; + uint64_t sc_fcc; + uint32_t sc_fcsr; + uint32_t sc_flags; +}; + +struct sigframe { + uint32_t sf_ass[4]; /* argument save space for o32 */ + uint32_t sf_code[2]; /* signal trampoline */ + struct target_sigcontext sf_sc; + target_sigset_t sf_mask; +}; + +struct target_ucontext { + target_ulong tuc_flags; + target_ulong tuc_link; + target_stack_t tuc_stack; + target_ulong pad0; + struct target_sigcontext tuc_mcontext; + target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe { + uint32_t rs_ass[4]; /* argument save space for o32 */ + uint32_t rs_code[2]; /* signal trampoline */ + struct target_siginfo rs_info; + struct target_ucontext rs_uc; +}; + +/* Install trampoline to jump back from signal handler */ +static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall) +{ + int err = 0; + + /* + * Set up the return code ... + * + * li a7, 139 + * syscall + */ + + __put_user(0x03822c0b, tramp + 0); /* ori a7, a7, 0x8b */ + __put_user(0x002b0000, tramp + 1); /* syscall 0 */ + return err; +} + +static inline void setup_sigcontext(CPULoongArchState *env, + struct target_sigcontext *sc) +{ + int i; + + __put_user(env->pc, &sc->sc_pc); + + __put_user(0, &sc->sc_gpr[0]); + for (i = 1; i < 32; ++i) { + __put_user(env->gpr[i], &sc->sc_gpr[i]); + } + + for (i = 0; i < 32; ++i) { + __put_user(env->fpr[i], &sc->sc_fpr[i]); + } +} + +static inline void +restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc) +{ + int i; + + __get_user(env->pc, &sc->sc_pc); + + for (i = 1; i < 32; ++i) { + __get_user(env->gpr[i], &sc->sc_gpr[i]); + } + + for (i = 0; i < 32; ++i) { + __get_user(env->fpr[i], &sc->sc_fpr[i]); + } +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPULoongArchState *env, + size_t frame_size) +{ + unsigned long sp; + + sp = target_sigsp(get_sp_from_cpustate(env) - 32, ka); + + return (sp - frame_size) & ~7; +} + +void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPULoongArchState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + int i; + + frame_addr = get_sigframe(ka, env, sizeof(*frame)); + trace_user_setup_rt_frame(env, frame_addr); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + goto give_sigsegv; + } + + install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn); + + tswap_siginfo(&frame->rs_info, info); + + __put_user(0, &frame->rs_uc.tuc_flags); + __put_user(0, &frame->rs_uc.tuc_link); + target_save_altstack(&frame->rs_uc.tuc_stack, env); + + setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); + + for (i = 0; i < TARGET_NSIG_WORDS; i++) { + __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); + } + + env->gpr[4] = sig; + env->gpr[5] = frame_addr + offsetof(struct target_rt_sigframe, rs_info); + env->gpr[6] = frame_addr + offsetof(struct target_rt_sigframe, rs_uc); + env->gpr[3] = frame_addr; + env->gpr[1] = frame_addr + offsetof(struct target_rt_sigframe, rs_code); + + env->pc = env->gpr[20] = ka->_sa_handler; + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sigsegv(sig); +} + +long do_rt_sigreturn(CPULoongArchState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + sigset_t blocked; + + frame_addr = env->gpr[3]; + trace_user_do_rt_sigreturn(env, frame_addr); + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { + goto badframe; + } + + target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); + set_sigmask(&blocked); + + restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); + target_restore_altstack(&frame->rs_uc.tuc_stack, env); + + unlock_user_struct(frame, frame_addr, 0); + return -TARGET_QEMU_ESIGRETURN; + +badframe: + unlock_user_struct(frame, frame_addr, 0); + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; +} diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h new file mode 100644 index 0000000..0e4c8f0 --- /dev/null +++ b/linux-user/loongarch64/sockbits.h @@ -0,0 +1 @@ +#include "../generic/sockbits.h" diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h new file mode 100644 index 0000000..64cb17d --- /dev/null +++ b/linux-user/loongarch64/syscall_nr.h @@ -0,0 +1,307 @@ +#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H +#define LINUX_USER_LOONGARCH_SYSCALL_NR_H + +/* copy from kernel: include/uapi/asm-generic/unistd.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_renameat 38 +#define TARGET_NR_umount2 39 +#define TARGET_NR_mount 40 +#define TARGET_NR_pivot_root 41 +#define TARGET_NR_nfsservctl 42 +#define TARGET_NR_statfs 43 +#define TARGET_NR_fstatfs 44 +#define TARGET_NR_truncate 45 +#define TARGET_NR_ftruncate 46 +#define TARGET_NR_fallocate 47 +#define TARGET_NR_faccessat 48 +#define TARGET_NR_chdir 49 +#define TARGET_NR_fchdir 50 +#define TARGET_NR_chroot 51 +#define TARGET_NR_fchmod 52 +#define TARGET_NR_fchmodat 53 +#define TARGET_NR_fchownat 54 +#define TARGET_NR_fchown 55 +#define TARGET_NR_openat 56 +#define TARGET_NR_close 57 +#define TARGET_NR_vhangup 58 +#define TARGET_NR_pipe2 59 +#define TARGET_NR_quotactl 60 +#define TARGET_NR_getdents64 61 +#define TARGET_NR_lseek 62 +#define TARGET_NR_read 63 +#define TARGET_NR_write 64 +#define TARGET_NR_readv 65 +#define TARGET_NR_writev 66 +#define TARGET_NR_pread64 67 +#define TARGET_NR_pwrite64 68 +#define TARGET_NR_preadv 69 +#define TARGET_NR_pwritev 70 +#define TARGET_NR_sendfile 71 +#define TARGET_NR_pselect6 72 +#define TARGET_NR_ppoll 73 +#define TARGET_NR_signalfd4 74 +#define TARGET_NR_vmsplice 75 +#define TARGET_NR_splice 76 +#define TARGET_NR_tee 77 +#define TARGET_NR_readlinkat 78 +#define TARGET_NR_newfstatat 79 +#define TARGET_NR_fstat 80 +#define TARGET_NR_sync 81 +#define TARGET_NR_fsync 82 +#define TARGET_NR_fdatasync 83 +#define TARGET_NR_sync_file_range 84 +#define TARGET_NR_timerfd_create 85 +#define TARGET_NR_timerfd_settime 86 +#define TARGET_NR_timerfd_gettime 87 +#define TARGET_NR_utimensat 88 +#define TARGET_NR_acct 89 +#define TARGET_NR_capget 90 +#define TARGET_NR_capset 91 +#define TARGET_NR_personality 92 +#define TARGET_NR_exit 93 +#define TARGET_NR_exit_group 94 +#define TARGET_NR_waitid 95 +#define TARGET_NR_set_tid_address 96 +#define TARGET_NR_unshare 97 +#define TARGET_NR_futex 98 +#define TARGET_NR_set_robust_list 99 +#define TARGET_NR_get_robust_list 100 +#define TARGET_NR_nanosleep 101 +#define TARGET_NR_getitimer 102 +#define TARGET_NR_setitimer 103 +#define TARGET_NR_kexec_load 104 +#define TARGET_NR_init_module 105 +#define TARGET_NR_delete_module 106 +#define TARGET_NR_timer_create 107 +#define TARGET_NR_timer_gettime 108 +#define TARGET_NR_timer_getoverrun 109 +#define TARGET_NR_timer_settime 110 +#define TARGET_NR_timer_delete 111 +#define TARGET_NR_clock_settime 112 +#define TARGET_NR_clock_gettime 113 +#define TARGET_NR_clock_getres 114 +#define TARGET_NR_clock_nanosleep 115 +#define TARGET_NR_syslog 116 +#define TARGET_NR_ptrace 117 +#define TARGET_NR_sched_setparam 118 +#define TARGET_NR_sched_setscheduler 119 +#define TARGET_NR_sched_getscheduler 120 +#define TARGET_NR_sched_getparam 121 +#define TARGET_NR_sched_setaffinity 122 +#define TARGET_NR_sched_getaffinity 123 +#define TARGET_NR_sched_yield 124 +#define TARGET_NR_sched_get_priority_max 125 +#define TARGET_NR_sched_get_priority_min 126 +#define TARGET_NR_sched_rr_get_interval 127 +#define TARGET_NR_restart_syscall 128 +#define TARGET_NR_kill 129 +#define TARGET_NR_tkill 130 +#define TARGET_NR_tgkill 131 +#define TARGET_NR_sigaltstack 132 +#define TARGET_NR_rt_sigsuspend 133 +#define TARGET_NR_rt_sigaction 134 +#define TARGET_NR_rt_sigprocmask 135 +#define TARGET_NR_rt_sigpending 136 +#define TARGET_NR_rt_sigtimedwait 137 +#define TARGET_NR_rt_sigqueueinfo 138 +#define TARGET_NR_rt_sigreturn 139 +#define TARGET_NR_setpriority 140 +#define TARGET_NR_getpriority 141 +#define TARGET_NR_reboot 142 +#define TARGET_NR_setregid 143 +#define TARGET_NR_setgid 144 +#define TARGET_NR_setreuid 145 +#define TARGET_NR_setuid 146 +#define TARGET_NR_setresuid 147 +#define TARGET_NR_getresuid 148 +#define TARGET_NR_setresgid 149 +#define TARGET_NR_getresgid 150 +#define TARGET_NR_setfsuid 151 +#define TARGET_NR_setfsgid 152 +#define TARGET_NR_times 153 +#define TARGET_NR_setpgid 154 +#define TARGET_NR_getpgid 155 +#define TARGET_NR_getsid 156 +#define TARGET_NR_setsid 157 +#define TARGET_NR_getgroups 158 +#define TARGET_NR_setgroups 159 +#define TARGET_NR_uname 160 +#define TARGET_NR_sethostname 161 +#define TARGET_NR_setdomainname 162 +#define TARGET_NR_getrlimit 163 +#define TARGET_NR_setrlimit 164 +#define TARGET_NR_getrusage 165 +#define TARGET_NR_umask 166 +#define TARGET_NR_prctl 167 +#define TARGET_NR_getcpu 168 +#define TARGET_NR_gettimeofday 169 +#define TARGET_NR_settimeofday 170 +#define TARGET_NR_adjtimex 171 +#define TARGET_NR_getpid 172 +#define TARGET_NR_getppid 173 +#define TARGET_NR_getuid 174 +#define TARGET_NR_geteuid 175 +#define TARGET_NR_getgid 176 +#define TARGET_NR_getegid 177 +#define TARGET_NR_gettid 178 +#define TARGET_NR_sysinfo 179 +#define TARGET_NR_mq_open 180 +#define TARGET_NR_mq_unlink 181 +#define TARGET_NR_mq_timedsend 182 +#define TARGET_NR_mq_timedreceive 183 +#define TARGET_NR_mq_notify 184 +#define TARGET_NR_mq_getsetattr 185 +#define TARGET_NR_msgget 186 +#define TARGET_NR_msgctl 187 +#define TARGET_NR_msgrcv 188 +#define TARGET_NR_msgsnd 189 +#define TARGET_NR_semget 190 +#define TARGET_NR_semctl 191 +#define TARGET_NR_semtimedop 192 +#define TARGET_NR_semop 193 +#define TARGET_NR_shmget 194 +#define TARGET_NR_shmctl 195 +#define TARGET_NR_shmat 196 +#define TARGET_NR_shmdt 197 +#define TARGET_NR_socket 198 +#define TARGET_NR_socketpair 199 +#define TARGET_NR_bind 200 +#define TARGET_NR_listen 201 +#define TARGET_NR_accept 202 +#define TARGET_NR_connect 203 +#define TARGET_NR_getsockname 204 +#define TARGET_NR_getpeername 205 +#define TARGET_NR_sendto 206 +#define TARGET_NR_recvfrom 207 +#define TARGET_NR_setsockopt 208 +#define TARGET_NR_getsockopt 209 +#define TARGET_NR_shutdown 210 +#define TARGET_NR_sendmsg 211 +#define TARGET_NR_recvmsg 212 +#define TARGET_NR_readahead 213 +#define TARGET_NR_brk 214 +#define TARGET_NR_munmap 215 +#define TARGET_NR_mremap 216 +#define TARGET_NR_add_key 217 +#define TARGET_NR_request_key 218 +#define TARGET_NR_keyctl 219 +#define TARGET_NR_clone 220 +#define TARGET_NR_execve 221 +#define TARGET_NR_mmap 222 +#define TARGET_NR_fadvise64 223 +#define TARGET_NR_swapon 224 +#define TARGET_NR_swapoff 225 +#define TARGET_NR_mprotect 226 +#define TARGET_NR_msync 227 +#define TARGET_NR_mlock 228 +#define TARGET_NR_munlock 229 +#define TARGET_NR_mlockall 230 +#define TARGET_NR_munlockall 231 +#define TARGET_NR_mincore 232 +#define TARGET_NR_madvise 233 +#define TARGET_NR_remap_file_pages 234 +#define TARGET_NR_mbind 235 +#define TARGET_NR_get_mempolicy 236 +#define TARGET_NR_set_mempolicy 237 +#define TARGET_NR_migrate_pages 238 +#define TARGET_NR_move_pages 239 +#define TARGET_NR_rt_tgsigqueueinfo 240 +#define TARGET_NR_perf_event_open 241 +#define TARGET_NR_accept4 242 +#define TARGET_NR_recvmmsg 243 +#define TARGET_NR_arch_specific_syscall 244 +#define TARGET_NR_wait4 260 +#define TARGET_NR_prlimit64 261 +#define TARGET_NR_fanotify_init 262 +#define TARGET_NR_fanotify_mark 263 +#define TARGET_NR_name_to_handle_at 264 +#define TARGET_NR_open_by_handle_at 265 +#define TARGET_NR_clock_adjtime 266 +#define TARGET_NR_syncfs 267 +#define TARGET_NR_setns 268 +#define TARGET_NR_sendmmsg 269 +#define TARGET_NR_process_vm_readv 270 +#define TARGET_NR_process_vm_writev 271 +#define TARGET_NR_kcmp 272 +#define TARGET_NR_finit_module 273 +#define TARGET_NR_sched_setattr 274 +#define TARGET_NR_sched_getattr 275 +#define TARGET_NR_renameat2 276 +#define TARGET_NR_seccomp 277 +#define TARGET_NR_getrandom 278 +#define TARGET_NR_memfd_create 279 +#define TARGET_NR_bpf 280 +#define TARGET_NR_execveat 281 +#define TARGET_NR_userfaultfd 282 +#define TARGET_NR_membarrier 283 +#define TARGET_NR_mlock2 284 +#define TARGET_NR_copy_file_range 285 +#define TARGET_NR_preadv2 286 +#define TARGET_NR_pwritev2 287 +#define TARGET_NR_pkey_mprotect 288 +#define TARGET_NR_pkey_alloc 289 +#define TARGET_NR_pkey_free 290 +#define TARGET_NR_statx 291 +#define TARGET_NR_io_pgetevents 292 +#define TARGET_NR_rseq 293 +#define TARGET_NR_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_syscalls 443 + +#endif diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h new file mode 100644 index 0000000..9896271 --- /dev/null +++ b/linux-user/loongarch64/target_cpu.h @@ -0,0 +1,36 @@ +/* + * 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[7] = 0; + env->gpr[4] = 0; +} + +static inline void cpu_clone_regs_parent(CPULoongArchState *env, + unsigned flags) +{ +} + +static inline void cpu_set_tls(CPULoongArchState *env, target_ulong newtls) +{ + env->gpr[2] = newtls; +} + +static inline abi_ulong get_sp_from_cpustate(CPULoongArchState *state) +{ + return state->gpr[3]; +} +#endif diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h new file mode 100644 index 0000000..7c88394 --- /dev/null +++ b/linux-user/loongarch64/target_elf.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + + +#ifndef LOONGARCH_TARGET_ELF_H +#define LOONGARCH_TARGET_ELF_H +static inline const char *cpu_get_model(uint32_t eflags) +{ + return "Loongson-3A5000"; +} +#endif diff --git a/linux-user/loongarch64/target_errno_defs.h b/linux-user/loongarch64/target_errno_defs.h new file mode 100644 index 0000000..17165c1 --- /dev/null +++ b/linux-user/loongarch64/target_errno_defs.h @@ -0,0 +1,7 @@ +#ifndef LOONGARCH_TARGET_ERRNO_DEFS_H +#define LOONGARCH_TARGET_ERRNO_DEFS_H + +/* Target uses generic errno */ +#include "../generic/target_errno_defs.h" + +#endif diff --git a/linux-user/loongarch64/target_fcntl.h b/linux-user/loongarch64/target_fcntl.h new file mode 100644 index 0000000..b810293 --- /dev/null +++ b/linux-user/loongarch64/target_fcntl.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_FCNTL_H +#define LOONGARCH_TARGET_FCNTL_H + +#include "../generic/fcntl.h" + +#endif /* LOONGARCH_TARGET_FCNTL_H */ diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h new file mode 100644 index 0000000..713c26a --- /dev/null +++ b/linux-user/loongarch64/target_signal.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_SIGNAL_H +#define LOONGARCH_TARGET_SIGNAL_H + +/* this struct defines a stack used during syscall handling */ +typedef struct target_sigaltstack { + abi_long ss_sp; + abi_int ss_flags; + abi_ulong ss_size; +} target_stack_t; + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK 1 +#define TARGET_SS_DISABLE 2 + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_SIGSTKSZ 8192 + +#include "../generic/signal.h" + +#endif /* LOONGARCH_TARGET_SIGNAL_H */ diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h new file mode 100644 index 0000000..818e8d6 --- /dev/null +++ b/linux-user/loongarch64/target_structs.h @@ -0,0 +1,49 @@ +/* + * LoongArch specific structures for linux-user + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_STRUCTS_H +#define LOONGARCH_TARGET_STRUCTS_H + +struct target_ipc_perm { + abi_int __key; /* Key. */ + abi_uint uid; /* Owner's user ID. */ + abi_uint gid; /* Owner's group ID. */ + abi_uint cuid; /* Creator's user ID. */ + abi_uint cgid; /* Creator's group ID. */ + abi_uint mode; /* Read/write permission. */ + abi_ushort __seq; /* Sequence number. */ + abi_ushort __pad1; + abi_ulong __unused1; + abi_ulong __unused2; +}; + +struct target_shmid_ds { + struct target_ipc_perm shm_perm; /* operation permission struct */ + abi_long shm_segsz; /* size of segment in bytes */ + abi_ulong shm_atime; /* time of last shmat() */ + abi_ulong shm_dtime; /* time of last shmdt() */ + abi_ulong shm_ctime; /* time of last change by shmctl() */ + abi_int shm_cpid; /* pid of creator */ + abi_int shm_lpid; /* pid of last shmop */ + abi_ulong shm_nattch; /* number of current attaches */ + abi_ulong __unused1; + abi_ulong __unused2; +}; + +#define TARGET_SEMID64_DS + +struct target_semid64_ds { + struct target_ipc_perm sem_perm; + abi_ulong sem_otime; + abi_ulong sem_ctime; + abi_ulong sem_nsems; + abi_ulong __unused1; + abi_ulong __unused2; +}; + +#endif diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h new file mode 100644 index 0000000..b98ac12 --- /dev/null +++ b/linux-user/loongarch64/target_syscall.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_SYSCALL_H +#define LOONGARCH_TARGET_SYSCALL_H + +/* + * this struct defines the way the registers are stored on the + * stack during a system call. + */ + +struct target_pt_regs { + /* Saved main processor registers. */ + target_ulong regs[32]; + + /* Saved special registers. */ + target_ulong csr_crmd; + target_ulong csr_prmd; + target_ulong csr_euen; + target_ulong csr_ecfg; + target_ulong csr_estat; + target_ulong csr_era; + target_ulong csr_badvaddr; + target_ulong orig_a0; + target_ulong __last[0]; +}; + +#define UNAME_MACHINE "loongarch" +#define UNAME_MINIMUM_RELEASE "4.19.0" + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 + +#define TARGET_FORCE_SHMLBA + +static inline abi_ulong target_shmlba(CPULoongArchState *env) +{ + return 0x40000; +} + +#endif diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h new file mode 100644 index 0000000..33e74ed --- /dev/null +++ b/linux-user/loongarch64/termbits.h @@ -0,0 +1,229 @@ +#ifndef LINUX_USER_LOONGARCH_TERMBITS_H +#define LINUX_USER_LOONGARCH_TERMBITS_H + +#define TARGET_NCCS 19 + +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + +struct target_termios { + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK 0000001 +#define TARGET_BRKINT 0000002 +#define TARGET_IGNPAR 0000004 +#define TARGET_PARMRK 0000010 +#define TARGET_INPCK 0000020 +#define TARGET_ISTRIP 0000040 +#define TARGET_INLCR 0000100 +#define TARGET_IGNCR 0000200 +#define TARGET_ICRNL 0000400 +#define TARGET_IUCLC 0001000 +#define TARGET_IXON 0002000 +#define TARGET_IXANY 0004000 +#define TARGET_IXOFF 0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8 0040000 + +/* c_oflag bits */ +#define TARGET_OPOST 0000001 +#define TARGET_OLCUC 0000002 +#define TARGET_ONLCR 0000004 +#define TARGET_OCRNL 0000010 +#define TARGET_ONOCR 0000020 +#define TARGET_ONLRET 0000040 +#define TARGET_OFILL 0000100 +#define TARGET_OFDEL 0000200 +#define TARGET_NLDLY 0000400 +#define TARGET_NL0 0000000 +#define TARGET_NL1 0000400 +#define TARGET_CRDLY 0003000 +#define TARGET_CR0 0000000 +#define TARGET_CR1 0001000 +#define TARGET_CR2 0002000 +#define TARGET_CR3 0003000 +#define TARGET_TABDLY 0014000 +#define TARGET_TAB0 0000000 +#define TARGET_TAB1 0004000 +#define TARGET_TAB2 0010000 +#define TARGET_TAB3 0014000 +#define TARGET_XTABS 0014000 +#define TARGET_BSDLY 0020000 +#define TARGET_BS0 0000000 +#define TARGET_BS1 0020000 +#define TARGET_VTDLY 0040000 +#define TARGET_VT0 0000000 +#define TARGET_VT1 0040000 +#define TARGET_FFDLY 0100000 +#define TARGET_FF0 0000000 +#define TARGET_FF1 0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD 0010017 +#define TARGET_B0 0000000 /* hang up */ +#define TARGET_B50 0000001 +#define TARGET_B75 0000002 +#define TARGET_B110 0000003 +#define TARGET_B134 0000004 +#define TARGET_B150 0000005 +#define TARGET_B200 0000006 +#define TARGET_B300 0000007 +#define TARGET_B600 0000010 +#define TARGET_B1200 0000011 +#define TARGET_B1800 0000012 +#define TARGET_B2400 0000013 +#define TARGET_B4800 0000014 +#define TARGET_B9600 0000015 +#define TARGET_B19200 0000016 +#define TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE 0000060 +#define TARGET_CS5 0000000 +#define TARGET_CS6 0000020 +#define TARGET_CS7 0000040 +#define TARGET_CS8 0000060 +#define TARGET_CSTOPB 0000100 +#define TARGET_CREAD 0000200 +#define TARGET_PARENB 0000400 +#define TARGET_PARODD 0001000 +#define TARGET_HUPCL 0002000 +#define TARGET_CLOCAL 0004000 +#define TARGET_CBAUDEX 0010000 +#define TARGET_B57600 0010001 +#define TARGET_B115200 0010002 +#define TARGET_B230400 0010003 +#define TARGET_B460800 0010004 +#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ +#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ +#define TARGET_CRTSCTS 020000000000 /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG 0000001 +#define TARGET_ICANON 0000002 +#define TARGET_XCASE 0000004 +#define TARGET_ECHO 0000010 +#define TARGET_ECHOE 0000020 +#define TARGET_ECHOK 0000040 +#define TARGET_ECHONL 0000100 +#define TARGET_NOFLSH 0000200 +#define TARGET_TOSTOP 0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE 0004000 +#define TARGET_FLUSHO 0010000 +#define TARGET_PENDIN 0040000 +#define TARGET_IEXTEN 0100000 +#define TARGET_EXTPROC 0200000 + +/* c_cc character offsets */ +#define TARGET_VINTR 0 +#define TARGET_VQUIT 1 +#define TARGET_VERASE 2 +#define TARGET_VKILL 3 +#define TARGET_VEOF 4 +#define TARGET_VTIME 5 +#define TARGET_VMIN 6 +#define TARGET_VSWTC 7 +#define TARGET_VSTART 8 +#define TARGET_VSTOP 9 +#define TARGET_VSUSP 10 +#define TARGET_VEOL 11 +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE 14 +#define TARGET_VLNEXT 15 +#define TARGET_VEOL2 16 + +/* ioctls */ + +#define TARGET_TCGETS 0x5401 +#define TARGET_TCSETS 0x5402 +#define TARGET_TCSETSW 0x5403 +#define TARGET_TCSETSF 0x5404 +#define TARGET_TCGETA 0x5405 +#define TARGET_TCSETA 0x5406 +#define TARGET_TCSETAW 0x5407 +#define TARGET_TCSETAF 0x5408 +#define TARGET_TCSBRK 0x5409 +#define TARGET_TCXONC 0x540A +#define TARGET_TCFLSH 0x540B + +#define TARGET_TIOCEXCL 0x540C +#define TARGET_TIOCNXCL 0x540D +#define TARGET_TIOCSCTTY 0x540E +#define TARGET_TIOCGPGRP 0x540F +#define TARGET_TIOCSPGRP 0x5410 +#define TARGET_TIOCOUTQ 0x5411 +#define TARGET_TIOCSTI 0x5412 +#define TARGET_TIOCGWINSZ 0x5413 +#define TARGET_TIOCSWINSZ 0x5414 +#define TARGET_TIOCMGET 0x5415 +#define TARGET_TIOCMBIS 0x5416 +#define TARGET_TIOCMBIC 0x5417 +#define TARGET_TIOCMSET 0x5418 +#define TARGET_TIOCGSOFTCAR 0x5419 +#define TARGET_TIOCSSOFTCAR 0x541A +#define TARGET_FIONREAD 0x541B +#define TARGET_TIOCINQ TARGET_FIONREAD +#define TARGET_TIOCLINUX 0x541C +#define TARGET_TIOCCONS 0x541D +#define TARGET_TIOCGSERIAL 0x541E +#define TARGET_TIOCSSERIAL 0x541F +#define TARGET_TIOCPKT 0x5420 +#define TARGET_FIONBIO 0x5421 +#define TARGET_TIOCNOTTY 0x5422 +#define TARGET_TIOCSETD 0x5423 +#define TARGET_TIOCGETD 0x5424 +#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ +#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ +#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) + /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) + /* Lock/unlock Pty */ +#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) + /* Safely open the slave */ + +#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX 0x5451 +#define TARGET_FIOASYNC 0x5452 +#define TARGET_TIOCSERCONFIG 0x5453 +#define TARGET_TIOCSERGWILD 0x5454 +#define TARGET_TIOCSERSWILD 0x5455 +#define TARGET_TIOCGLCKTRMIOS 0x5456 +#define TARGET_TIOCSLCKTRMIOS 0x5457 +#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT 0x545C + /* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT 0x545D + /* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA 0 +#define TARGET_TIOCPKT_FLUSHREAD 1 +#define TARGET_TIOCPKT_FLUSHWRITE 2 +#define TARGET_TIOCPKT_STOP 4 +#define TARGET_TIOCPKT_START 8 +#define TARGET_TIOCPKT_NOSTOP 16 +#define TARGET_TIOCPKT_DOSTOP 32 + +#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +#endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index a5ce487..92e1a35 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 @@ -450,7 +450,7 @@ struct target_dirent64 { #define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */ #define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */ -#ifdef TARGET_MIPS +#if defined(TARGET_MIPS) || defined(TARGET_LOONGARCH64) #define TARGET_NSIG 128 #else #define TARGET_NSIG 64 @@ -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 */ @@ -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 Fri Aug 27 07:14:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461477 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 A289AC432BE for ; Fri, 27 Aug 2021 08:02:50 +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 35DED60EE5 for ; Fri, 27 Aug 2021 08:02:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 35DED60EE5 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]:44490 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWp7-00042N-3A for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 04:02:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53340) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5o-0001SI-1o for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:16:00 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59908 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5j-0003au-8g for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:59 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S20; Fri, 27 Aug 2021 15:15:39 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 18/19] default-configs: Add loongarch linux-user support Date: Fri, 27 Aug 2021 15:14:53 +0800 Message-Id: <1630048494-2143-19-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S20 X-Coremail-Antispam: 1UD129KBjvdXoWrur48ZrW3CF1rAF4UCrW8tFb_yoWxKrb_uF y3JF4kKFWUZryUCw10v3yFyr4rC3W8JF1rZF1DKw4xXw47Xr13t34vva1rAa4ay393urnx ZrWkArn8Cr10qjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add loongarch64 linux-user default configs file. Reviewed-by: Richard Henderson Signed-off-by: Song Gao --- 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 Fri Aug 27 07:14:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gaosong X-Patchwork-Id: 12461497 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 16632C432BE for ; Fri, 27 Aug 2021 08:04:42 +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 892D260F92 for ; Fri, 27 Aug 2021 08:04:41 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 892D260F92 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]:48812 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJWqu-00070p-KO for qemu-devel@archiver.kernel.org; Fri, 27 Aug 2021 04:04:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53342) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJW5o-0001SW-4U for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:16:00 -0400 Received: from mail.loongson.cn ([114.242.206.163]:59942 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJW5j-0003bZ-Gd for qemu-devel@nongnu.org; Fri, 27 Aug 2021 03:15:59 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxtOTvkChhno4AAA--.2304S21; Fri, 27 Aug 2021 15:15:41 +0800 (CST) From: Song Gao To: qemu-devel@nongnu.org Subject: [PATCH v3 19/19] target/loongarch: Add target build suport Date: Fri, 27 Aug 2021 15:14:54 +0800 Message-Id: <1630048494-2143-20-git-send-email-gaosong@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> References: <1630048494-2143-1-git-send-email-gaosong@loongson.cn> X-CM-TRANSID: AQAAf9AxtOTvkChhno4AAA--.2304S21 X-Coremail-Antispam: 1UD129KBjvJXoWruF4xtr1fZw4xKw4fuFyUJrb_yoW8JF48p3 y7ZryrKF48ZF9xt3s3Ja4FqFZ5Jw17Cr12qan3KFyxArsxJ3y8Z3s5trZ8XF47X3W0kFZa gFn3C345WF48Ja7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 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, chenhuacai@gmail.com, richard.henderson@linaro.org, f4bug@amsat.org, maobibo@loongson.cn, laurent@vivier.eu, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, pbonzini@redhat.com, alex.bennee@linaro.org 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 --- target/loongarch/meson.build | 18 ++++++++++++++++++ target/meson.build | 1 + 2 files changed, 19 insertions(+) create mode 100644 target/loongarch/meson.build diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build new file mode 100644 index 0000000..31f9e9f --- /dev/null +++ b/target/loongarch/meson.build @@ -0,0 +1,18 @@ +gen = decodetree.process('insns.decode') + +loongarch_ss = ss.source_set() +loongarch_ss.add(files( + 'cpu.c', +)) +loongarch_tcg_ss = ss.source_set() +loongarch_tcg_ss.add(gen) +loongarch_tcg_ss.add(files( + 'fpu_helper.c', + 'op_helper.c', + 'translate.c', +)) +loongarch_tcg_ss.add(zlib) + +loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss]) + +target_arch += {'loongarch': loongarch_ss} diff --git a/target/meson.build b/target/meson.build index 2f69402..a53a604 100644 --- a/target/meson.build +++ b/target/meson.build @@ -5,6 +5,7 @@ subdir('cris') subdir('hexagon') subdir('hppa') subdir('i386') +subdir('loongarch') subdir('m68k') subdir('microblaze') subdir('mips')