From patchwork Mon Nov 23 20:44:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926759 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 23AB1C2D0E4 for ; Mon, 23 Nov 2020 21:05:47 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 73A86206B5 for ; Mon, 23 Nov 2020 21:05:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WaRwQ/iU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 73A86206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:49618 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ1t-00041T-DE for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:05:45 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46340) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIhq-0000i0-Nb for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:05 -0500 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]:47002) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIhm-00018l-VO for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:01 -0500 Received: by mail-wr1-x444.google.com with SMTP id g14so4917328wrm.13 for ; Mon, 23 Nov 2020 12:44:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5Ols7j+AFzycY14iQfDkxh9tzIuV8kNY58VkxJzWR+8=; b=WaRwQ/iUWPtWfYtfrZeau21ir/yNWq8ZA4oK00JP69Y10QeVNfEptNjMIzv1fMsVqc HFNmyztBMhJrrpPgbcX4pASlUpI82V+mMgoFxMW+lQmVR1jmVDu1K8sKMLuyS8E5PrM7 Y3qOraVKGNg/E1hFdcZH7BrgCs983sKOh+TJFfT3j5vTQXOHRHOMVbVNBbSHElD0yThT LMU2k/vrdNSHmXYU5Vp7AWu8PCFS3mbGOUw2I/bpfLFX1AcHIdKc9luZHnEh12Q/Wf4V gY8r60moT0t/Qe/5596FXzI0fqvosm5VZMff6KXOdYOrTnpfLGN02jFFcJGbzEOibvTC C2hQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=5Ols7j+AFzycY14iQfDkxh9tzIuV8kNY58VkxJzWR+8=; b=LJc5Ohd3/8eTmZj9evdJCPO105ZtjHPMzfHKnsfUGAoFB+VWXjhx65oEGmVEJLH+CF VD7i9HHSuFUg1kR69oW2mjqFelV2VO+BZSxR7Q1hyfQnZszZvSfMXDf+Tu4SPCX3a4UH S9S1/tzq4PRLL9ntUa0/ZcCzd2m3B19JLpMovcNmqLc181XnNAK+AHNYdKEZe2Ai+18X OAPKxSO5b024rEX7afn4jQttnP3Hb3tlKT0gx28W78LOpcHdRS3vgr8fwuKbatSlWvK0 HiDdNVq5+A7tC1ohLXnjhhnDtxUuBvL0H+Oj9O0cTt34VjrzANYAwCh4RqfiP4Issxpg xV7A== X-Gm-Message-State: AOAM531N20G6f3eGnp4Y3hP5v9Wqs0d8rExefCrhFrF8BFMidT45J6q3 iGmpeyHpIs6l64addIJBPn1gT1r9nfk= X-Google-Smtp-Source: ABdhPJymTfom+lWr1ANpZ29uPNzo0Fw8RYP3TQkIKARy7MvpyOYQnxi1qHa5OeuRq9V8PBsFpzBl0Q== X-Received: by 2002:adf:e3c9:: with SMTP id k9mr1516798wrm.275.1606164295510; Mon, 23 Nov 2020 12:44:55 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id 90sm21450880wrl.60.2020.11.23.12.44.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:44:54 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 01/28] target/mips: Use FloatRoundMode enum for FCR31 modes conversion Date: Mon, 23 Nov 2020 21:44:21 +0100 Message-Id: <20201123204448.3260804-2-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::444; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x444.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Use the FloatRoundMode enum type introduced in commit 3dede407cc6 ("softfloat: Name rounding mode enum") instead of 'unsigned int'. Suggested-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- target/mips/internal.h | 3 ++- target/mips/fpu_helper.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/target/mips/internal.h b/target/mips/internal.h index dd8a7809b64..bbd10e9d45f 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -225,7 +225,8 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, uint32_t float_class_s(uint32_t arg, float_status *fst); uint64_t float_class_d(uint64_t arg, float_status *fst); -extern unsigned int ieee_rm[]; +extern const FloatRoundMode ieee_rm[4]; + void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask); static inline void restore_rounding_mode(CPUMIPSState *env) diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index 020b768e87b..501bd401a16 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -42,7 +42,7 @@ #define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL /* convert MIPS rounding mode in FCR31 to IEEE library */ -unsigned int ieee_rm[] = { +const FloatRoundMode ieee_rm[4] = { float_round_nearest_even, float_round_to_zero, float_round_up, From patchwork Mon Nov 23 20:44:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926741 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 6828DC2D0E4 for ; Mon, 23 Nov 2020 20:53:30 +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 CC09A206B7 for ; Mon, 23 Nov 2020 20:53:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iFp1Mltt" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CC09A206B7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:51876 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khIq0-0000yy-Mz for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 15:53:28 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46366) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIhw-0000j6-Jb for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:12 -0500 Received: from mail-wr1-x42b.google.com ([2a00:1450:4864:20::42b]:37419) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIhq-0001Al-VQ for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:04 -0500 Received: by mail-wr1-x42b.google.com with SMTP id i2so1081984wrs.4 for ; Mon, 23 Nov 2020 12:45:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MK2uHhpNIWKEQBVWTQsuDC1qbyeediSuomIIPq7aUys=; b=iFp1Mltt3KbFMhp4El2npndIs/qXLepRTI0+0lkKthro/yYUQpn8aarhi3j2aiepPt DfwWn0tNF4kVKGneEKZ38NGhtNRQTxsayyumCpiY/mhKdbdMHkqFsMdRpde4yt017uWb 0s5fUNYAsfOhxEy3rTje+WFO0TkQAMlNLbcEz/CnD7v35iXJAWnWcL7YZpflvBzKI+5r J1Z7yYbYABsgWkM96+e/OE5XTPNY50LyvNXTa1pkwhPBRDrAGDYVEf54Vva/hkYTDMsT 6VJKsyCSyO8FaVu1ggwpenb77ScRtw/qO74AVorTB2t3d7Gfs4W3KdQPCquw+DcV67cT Qg7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=MK2uHhpNIWKEQBVWTQsuDC1qbyeediSuomIIPq7aUys=; b=gEfeDUArh2qT05/1K48sZP0omRwnzuq+0djVlqIVnUAAnJmYL5GYqFJLcN0HYnYrGB 48DUvCHWhwRZvr2dD0TzAZ8SvLi1tnrOqbzOxFKi+E/AUXGpldKhHydlhvE30D1zn9Qj Ioh+VffKDn2q035MX9J0aiX9bIZev3g2IFq4O2ELOT4CBj4N+/ENl3bfvQHjCKMV3Gsx D6sHGbJnl8TDgi6SQ4A+g3MHyMJ1kx1+oGYkVdP6AfW4oj4qEDnE4tH1R1Tekl+D2yq0 PxBe1DiCtCfzvnZQtexZerpokbyon436StpZxsPNTfCAtyVOxnD9QVMJpMAyVk5pOwuw oeiQ== X-Gm-Message-State: AOAM530DEyP/RlWvzpGOr3UH+TBt8aiFVP8NuLxcRkPMISWmk5EFh15g Jp+i9lfej4uc7cpjrDCY9scLCt9vgSo= X-Google-Smtp-Source: ABdhPJwRwtpQQztVBRE8o2Z9h9uxW4XWS0IV1CYI9RtfFQQ9kLxNGCibWwkK0iGpXONkf77jtzQZiA== X-Received: by 2002:adf:fd0d:: with SMTP id e13mr1476459wrr.85.1606164300590; Mon, 23 Nov 2020 12:45:00 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id t13sm21879411wru.67.2020.11.23.12.44.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:44:59 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 02/28] target/mips: Extract FPU helpers to 'fpu_helper.h' Date: Mon, 23 Nov 2020 21:44:22 +0100 Message-Id: <20201123204448.3260804-3-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::42b; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x42b.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract FPU specific helpers from "internal.h" to "fpu_helper.h". Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201120210844.2625602-2-f4bug@amsat.org> --- target/mips/fpu_helper.h | 50 ++++++++++++++++++++++++++++++++++++++ target/mips/internal.h | 43 -------------------------------- linux-user/mips/cpu_loop.c | 1 + target/mips/fpu_helper.c | 1 + target/mips/gdbstub.c | 1 + target/mips/kvm.c | 1 + target/mips/machine.c | 1 + target/mips/msa_helper.c | 1 + target/mips/translate.c | 1 + 9 files changed, 57 insertions(+), 43 deletions(-) create mode 100644 target/mips/fpu_helper.h diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h new file mode 100644 index 00000000000..3aaee3f3430 --- /dev/null +++ b/target/mips/fpu_helper.h @@ -0,0 +1,50 @@ +/* + * Helpers for emulation of FPU-related MIPS instructions. + * + * Copyright (C) 2004-2005 Jocelyn Mayer + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "fpu/softfloat-helpers.h" +#include "cpu.h" + +extern const FloatRoundMode ieee_rm[4]; + +uint32_t float_class_s(uint32_t arg, float_status *fst); +uint64_t float_class_d(uint64_t arg, float_status *fst); + +static inline void restore_rounding_mode(CPUMIPSState *env) +{ + set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], + &env->active_fpu.fp_status); +} + +static inline void restore_flush_mode(CPUMIPSState *env) +{ + set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0, + &env->active_fpu.fp_status); +} + +static inline void restore_snan_bit_mode(CPUMIPSState *env) +{ + set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0, + &env->active_fpu.fp_status); +} + +static inline void restore_fp_status(CPUMIPSState *env) +{ + restore_rounding_mode(env); + restore_flush_mode(env); + restore_snan_bit_mode(env); +} + +static inline void restore_msa_fp_status(CPUMIPSState *env) +{ + float_status *status = &env->active_tc.msa_fp_status; + int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM; + bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0; + + set_float_rounding_mode(ieee_rm[rounding_mode], status); + set_flush_to_zero(flush_to_zero, status); + set_flush_inputs_to_zero(flush_to_zero, status); +} diff --git a/target/mips/internal.h b/target/mips/internal.h index bbd10e9d45f..7bea3af0b29 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -8,8 +8,6 @@ #ifndef MIPS_INTERNAL_H #define MIPS_INTERNAL_H -#include "fpu/softfloat-helpers.h" - /* * MMU types, the first four entries have the same layout as the * CP0C0_MT field. @@ -222,49 +220,8 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool probe, uintptr_t retaddr); /* op_helper.c */ -uint32_t float_class_s(uint32_t arg, float_status *fst); -uint64_t float_class_d(uint64_t arg, float_status *fst); - -extern const FloatRoundMode ieee_rm[4]; - void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask); -static inline void restore_rounding_mode(CPUMIPSState *env) -{ - set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], - &env->active_fpu.fp_status); -} - -static inline void restore_flush_mode(CPUMIPSState *env) -{ - set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0, - &env->active_fpu.fp_status); -} - -static inline void restore_snan_bit_mode(CPUMIPSState *env) -{ - set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0, - &env->active_fpu.fp_status); -} - -static inline void restore_fp_status(CPUMIPSState *env) -{ - restore_rounding_mode(env); - restore_flush_mode(env); - restore_snan_bit_mode(env); -} - -static inline void restore_msa_fp_status(CPUMIPSState *env) -{ - float_status *status = &env->active_tc.msa_fp_status; - int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM; - bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0; - - set_float_rounding_mode(ieee_rm[rounding_mode], status); - set_flush_to_zero(flush_to_zero, status); - set_flush_inputs_to_zero(flush_to_zero, status); -} - static inline void restore_pamask(CPUMIPSState *env) { if (env->hflags & MIPS_HFLAG_ELPA) { diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index cfe7ba5c47d..b58dbeb83d1 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -23,6 +23,7 @@ #include "cpu_loop-common.h" #include "elf.h" #include "internal.h" +#include "fpu_helper.h" # ifdef TARGET_ABI_MIPSO32 # define MIPS_SYSCALL_NUMBER_UNUSED -1 diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index 501bd401a16..7d949cd8e3a 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -31,6 +31,7 @@ #include "exec/memop.h" #include "sysemu/kvm.h" #include "fpu/softfloat.h" +#include "fpu_helper.h" /* Complex FPU operations which may need stack space. */ diff --git a/target/mips/gdbstub.c b/target/mips/gdbstub.c index e39f8d75cf0..f1c2a2cf6d6 100644 --- a/target/mips/gdbstub.c +++ b/target/mips/gdbstub.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "internal.h" #include "exec/gdbstub.h" +#include "fpu_helper.h" int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { diff --git a/target/mips/kvm.c b/target/mips/kvm.c index 72637a1e021..df47eded328 100644 --- a/target/mips/kvm.c +++ b/target/mips/kvm.c @@ -27,6 +27,7 @@ #include "kvm_mips.h" #include "exec/memattrs.h" #include "hw/boards.h" +#include "fpu_helper.h" #define DEBUG_KVM 0 diff --git a/target/mips/machine.c b/target/mips/machine.c index 5b23e3e912a..a4ea67c2980 100644 --- a/target/mips/machine.c +++ b/target/mips/machine.c @@ -2,6 +2,7 @@ #include "cpu.h" #include "internal.h" #include "migration/cpu.h" +#include "fpu_helper.h" static int cpu_post_load(void *opaque, int version_id) { diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 249f0fdad80..b89b4c44902 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -23,6 +23,7 @@ #include "exec/exec-all.h" #include "exec/helper-proto.h" #include "fpu/softfloat.h" +#include "fpu_helper.h" /* Data format min and max values */ #define DF_BITS(df) (1 << ((df) + 3)) diff --git a/target/mips/translate.c b/target/mips/translate.c index c64a1bc42e1..5ec9fd7e92a 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -39,6 +39,7 @@ #include "exec/translator.h" #include "exec/log.h" #include "qemu/qemu-print.h" +#include "fpu_helper.h" #define MIPS_DEBUG_DISAS 0 From patchwork Mon Nov 23 20:44:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926747 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 A5B2DC2D0E4 for ; Mon, 23 Nov 2020 20:57:02 +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 2AEC3206B7 for ; Mon, 23 Nov 2020 20:57:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UlzZZ2Bg" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2AEC3206B7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59346 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khItR-0004K2-4S for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 15:57:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46392) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIi2-0000lA-Rh for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:14 -0500 Received: from mail-wm1-x341.google.com ([2a00:1450:4864:20::341]:40953) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIhx-0001Cw-Me for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:14 -0500 Received: by mail-wm1-x341.google.com with SMTP id a3so721228wmb.5 for ; Mon, 23 Nov 2020 12:45:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0ph8h44c9IgmkWQLxmzuSBj3koZyAw+q+/J8qVoLDsI=; b=UlzZZ2BgjMtm4DRnjt338093bGPvNpO4mylmrgYlEErjDUrkySQ+l5qMNbLtlwUcrX Uhkw3A4mof/8RWDGYCK7o9g74Dv35pMvDP28tznCw9QT8xajYaR0JM9JQkgXEft5UVPp LxAbZOkZ8t6IgG4HOG49jIfNQqYZD7DB6KmYc5IZ7Xz55SsSkZWpE67cZLQD1qxHSf3a eh1IfMRlwKJOqbGEZTg3TSjkd3j0aIQ7QVOLKprxwRoj3emsEXnlERhTTkhZN4DimNXQ lICc9V9TVvTWUcU6OziQ2J6LrOQpsblNkIneveDXFu41DN1EtLux13b1bB+A1URxKzal ud/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=0ph8h44c9IgmkWQLxmzuSBj3koZyAw+q+/J8qVoLDsI=; b=a3coNBJT3ft3e2PIi1xXpIxOFYyDsPWuiCQX9G4+1nipZLjJ5OuSSGShby2Ud1YJNn 19o66jMiz5CuLbBnn0zQKwK/QZEjYzGjf+vSHpw57uC149DZR3mpBOeZR5PsLyBSv/04 F2DDf5/McoKg75XN6atRgNvdUIwjGqhtY0+fjRDBXHXVaJ//smblnddaDLzJWhDgh05H +RFR1vktl0lYE9A4B1rMHeNpfTCRM2Ewjfejkca+PAFQ41/z3tJ/6xPGyL+9aWNkLe4C 2AOW9Pn1NVbRoxCP8kjvCo0xjhJcHkdMrH0Q/nLRW1LIWEnCzyO4eFjNhlecxW4bWkdC 2HqQ== X-Gm-Message-State: AOAM533pIBLawgmeeSAdKDLOgyJFr5pVIf+s2evLmkf1dGK3fjNuRmwr +RbLux4sGhOwU3wZrxJnDw0YvkTefNk= X-Google-Smtp-Source: ABdhPJyBTLfFJck3OQJWqjaBPpVXQQodY+yPRwI8OllmCkvvWqqYSb3b39B1vN81xSPP08/uTfIM7g== X-Received: by 2002:a1c:6557:: with SMTP id z84mr742671wmb.144.1606164305627; Mon, 23 Nov 2020 12:45:05 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id v2sm20591284wrm.96.2020.11.23.12.45.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:04 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 03/28] target/mips: Rename msa_helper.c as mod-msa_helper.c Date: Mon, 23 Nov 2020 21:44:23 +0100 Message-Id: <20201123204448.3260804-4-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::341; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x341.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" MSA means 'MIPS SIMD Architecture' and is defined as a Module by MIPS. To keep the directory sorted, we use the 'mod' prefix for MIPS modules. Rename msa_helper.c as mod-msa_helper.c. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- target/mips/{msa_helper.c => mod-msa_helper.c} | 0 target/mips/meson.build | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) rename target/mips/{msa_helper.c => mod-msa_helper.c} (100%) diff --git a/target/mips/msa_helper.c b/target/mips/mod-msa_helper.c similarity index 100% rename from target/mips/msa_helper.c rename to target/mips/mod-msa_helper.c diff --git a/target/mips/meson.build b/target/mips/meson.build index 681a5524c0e..35dbbbf6519 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -6,8 +6,9 @@ 'gdbstub.c', 'helper.c', 'lmmi_helper.c', - 'msa_helper.c', 'op_helper.c', + 'mod-msa_helper.c', + 'translate.c', )) mips_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) From patchwork Mon Nov 23 20:44:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926749 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 8178EC2D0E4 for ; Mon, 23 Nov 2020 21:00: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 C1FEB206D5 for ; Mon, 23 Nov 2020 21:00:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="E5CwL85E" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C1FEB206D5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:38678 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khIx4-0007cv-CM for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:00:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46416) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIi5-0000pj-RX for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:17 -0500 Received: from mail-wr1-x436.google.com ([2a00:1450:4864:20::436]:33836) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIi2-0001E4-00 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:17 -0500 Received: by mail-wr1-x436.google.com with SMTP id r17so20173564wrw.1 for ; Mon, 23 Nov 2020 12:45:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NN3A70IyLtScV9bbh51zKvwmivN0fyBHf7O7ACcKdII=; b=E5CwL85EJzYm6lIkoQCri/QDtC3OeA2y7sRJsOH0N4MXJkDAdwE8nrLo+A6RpDuziQ /m6/6yuKxqeonX+Z1gS2oZeWMqCuhQcO0DH1Ez26YTu3R2vYkLU8gf5sVPNN7YV6G4Rm i6KaMhmI2+DW4c1lcIoHw4NRS2yWBTGOzQ+tNNdXbvAfH3H7HwPyIDfaEbl5EfLAZuUy skdkaLkx8losyHjCDj5eWRX1FyvCAkIpsiNSzQpivzz3UNtBwwdsaHET04G25UPT0lxn 1ShML0FCPB5LOG89EJmOVECJwqcTgHuvBSfcRDgJLdMknnjSWQSpRtJE5j/VRSew/qT8 UXTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=NN3A70IyLtScV9bbh51zKvwmivN0fyBHf7O7ACcKdII=; b=jE2Dl/2DjUV2KS8qW+jYyJLWtHXizRMYYzksclOTC+aHMF5+DUGNEXhuDvYTi3YTcJ MhrAOF15D0zxQ9SsOsQYh1l6aTikGgqrXebO3wh4WWbPNOXZ+5VB1+/R0Z+aljuwgK0v u/R+c+IrUmHJWuiza3yTTy2ubWeBgfBrAyLz/HdzBp0mWi+imNqPuKarfVgdf6IdOdit wYz6GtbqDcHQtlzsWM9YWk5NSyeak5Odmq7fZkcr+jgP462u8ewLKz85Z3wBQIgZRhfa 6eJ1EJGnBpknVSrx+NVMxuRPN3k+Pp6GQyHaIVMfiSJ4zmkW57yfSUhF7ccNJW0N7pkG 3YEg== X-Gm-Message-State: AOAM533JjI4DRB/XsAQ+8x8QiUtESvVplbzaWL25XHkt3Q2UPB0rQaLp hmBZFkbllq8zrSm9BgSBJCQxiuiyAhQ= X-Google-Smtp-Source: ABdhPJwJQJp/sUIHwqvMU6/+tWBuSx0G/F2nTyLV0Hyokwc/TtungotP5DVUdGIh2NnO0MKjWL19Gg== X-Received: by 2002:adf:e74d:: with SMTP id c13mr1534216wrn.277.1606164310443; Mon, 23 Nov 2020 12:45:10 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id f16sm869838wmh.7.2020.11.23.12.45.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:09 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 04/28] target/mips: Extract MSA helpers from op_helper.c Date: Mon, 23 Nov 2020 21:44:24 +0100 Message-Id: <20201123204448.3260804-5-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::436; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x436.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" We have ~400 lines of MSA helpers in the generic op_helper.c, move them with the other helpers in 'mod-msa_helper.c'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- target/mips/mod-msa_helper.c | 392 ++++++++++++++++++++++++++++++++++ target/mips/op_helper.c | 393 ----------------------------------- 2 files changed, 392 insertions(+), 393 deletions(-) diff --git a/target/mips/mod-msa_helper.c b/target/mips/mod-msa_helper.c index b89b4c44902..56fca86a242 100644 --- a/target/mips/mod-msa_helper.c +++ b/target/mips/mod-msa_helper.c @@ -8201,3 +8201,395 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } + +/* Data format min and max values */ +#define DF_BITS(df) (1 << ((df) + 3)) + +/* Element-by-element access macros */ +#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) + +#if !defined(CONFIG_USER_ONLY) +#define MEMOP_IDX(DF) \ + TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ + cpu_mmu_index(env, false)); +#else +#define MEMOP_IDX(DF) +#endif + +void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_BYTE) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); + pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); + pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); + pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); + pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); + pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); + pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); + pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); + pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); + pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); + pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); + pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); + pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); + pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); + pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); + pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); +#else + pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); + pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); + pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); + pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); + pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); + pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); + pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); + pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); + pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); + pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); + pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); + pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); + pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); + pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); + pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); + pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); + pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); + pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); + pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); + pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); + pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); + pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); + pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); + pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); + pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); + pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); + pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); + pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); + pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); + pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); + pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); +#else + pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); + pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); + pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); + pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); + pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); + pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); + pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); + pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); + pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); + pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); + pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); + pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); + pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); + pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); + pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); + pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); +#endif +#endif +} + +void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_HALF) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); + pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); + pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); + pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); + pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); + pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); + pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); + pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); +#else + pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); + pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); + pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); + pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); + pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); + pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); + pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); + pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF)); + pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF)); + pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF)); + pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF)); + pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF)); + pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF)); + pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF)); + pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF)); +#else + pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF)); + pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF)); + pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF)); + pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF)); + pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF)); + pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF)); + pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF)); + pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF)); +#endif +#endif +} + +void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_WORD) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); + pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); + pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); + pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); +#else + pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); + pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); + pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); + pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD)); + pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD)); + pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD)); + pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD)); +#else + pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD)); + pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD)); + pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD)); + pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD)); +#endif +#endif +} + +void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_DOUBLE) +#if !defined(CONFIG_USER_ONLY) + pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC()); + pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC()); +#else + pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE)); + pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE)); +#endif +} + +#define MSA_PAGESPAN(x) \ + ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN / 8 - 1) >= TARGET_PAGE_SIZE) + +static inline void ensure_writable_pages(CPUMIPSState *env, + target_ulong addr, + int mmu_idx, + uintptr_t retaddr) +{ + /* FIXME: Probe the actual accesses (pass and use a size) */ + if (unlikely(MSA_PAGESPAN(addr))) { + /* first page */ + probe_write(env, addr, 0, mmu_idx, retaddr); + /* second page */ + addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + probe_write(env, addr, 0, mmu_idx, retaddr); + } +} + +void helper_msa_st_b(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_BYTE) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC()); +#else + helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]); + cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]); + cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]); + cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]); + cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]); + cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]); + cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]); + cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]); + cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]); + cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]); + cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]); + cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]); + cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]); + cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]); + cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]); + cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]); +#else + cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]); + cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]); + cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]); + cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]); + cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]); + cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]); + cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]); + cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]); + cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]); + cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]); + cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]); + cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]); + cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]); + cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]); + cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]); + cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]); +#endif +#endif +} + +void helper_msa_st_h(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_HALF) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC()); +#else + helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]); + cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]); + cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]); + cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]); + cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]); + cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]); + cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]); + cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]); +#else + cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]); + cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]); + cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]); + cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]); + cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]); + cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]); + cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]); + cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]); +#endif +#endif +} + +void helper_msa_st_w(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_WORD) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[0], oi, GETPC()); + helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[1], oi, GETPC()); + helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[2], oi, GETPC()); + helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[3], oi, GETPC()); +#else + helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[0], oi, GETPC()); + helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[1], oi, GETPC()); + helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[2], oi, GETPC()); + helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[3], oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]); + cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]); + cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]); + cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]); +#else + cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]); + cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]); + cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]); + cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]); +#endif +#endif +} + +void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_DOUBLE) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) + helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC()); + helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC()); +#else + cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]); + cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]); +#endif +} diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 5184a1838be..dd09a4c714a 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -1178,399 +1178,6 @@ void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, #endif /* !CONFIG_USER_ONLY */ -/* MSA */ -/* Data format min and max values */ -#define DF_BITS(df) (1 << ((df) + 3)) - -/* Element-by-element access macros */ -#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) - -#if !defined(CONFIG_USER_ONLY) -#define MEMOP_IDX(DF) \ - TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ - cpu_mmu_index(env, false)); -#else -#define MEMOP_IDX(DF) -#endif - -void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd, - target_ulong addr) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - MEMOP_IDX(DF_BYTE) -#if !defined(CONFIG_USER_ONLY) -#if !defined(HOST_WORDS_BIGENDIAN) - pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); - pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); - pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); - pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); - pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); - pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); - pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); - pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); - pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); - pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); - pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); - pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); - pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); - pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); - pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); - pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); -#else - pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); - pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); - pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); - pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); - pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); - pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); - pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); - pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); - pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); - pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); - pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); - pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); - pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); - pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); - pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); - pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); -#endif -#else -#if !defined(HOST_WORDS_BIGENDIAN) - pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); - pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); - pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); - pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); - pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); - pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); - pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); - pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); - pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); - pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); - pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); - pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); - pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); - pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); - pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); - pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); -#else - pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); - pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); - pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); - pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); - pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); - pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); - pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); - pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); - pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); - pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); - pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); - pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); - pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); - pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); - pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); - pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); -#endif -#endif -} - -void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd, - target_ulong addr) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - MEMOP_IDX(DF_HALF) -#if !defined(CONFIG_USER_ONLY) -#if !defined(HOST_WORDS_BIGENDIAN) - pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); - pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); - pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); - pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); - pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); - pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); - pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); - pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); -#else - pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); - pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); - pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); - pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); - pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); - pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); - pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); - pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); -#endif -#else -#if !defined(HOST_WORDS_BIGENDIAN) - pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF)); - pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF)); - pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF)); - pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF)); - pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF)); - pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF)); - pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF)); - pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF)); -#else - pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF)); - pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF)); - pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF)); - pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF)); - pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF)); - pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF)); - pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF)); - pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF)); -#endif -#endif -} - -void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd, - target_ulong addr) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - MEMOP_IDX(DF_WORD) -#if !defined(CONFIG_USER_ONLY) -#if !defined(HOST_WORDS_BIGENDIAN) - pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); - pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); - pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); - pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); -#else - pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); - pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); - pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); - pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); -#endif -#else -#if !defined(HOST_WORDS_BIGENDIAN) - pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD)); - pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD)); - pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD)); - pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD)); -#else - pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD)); - pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD)); - pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD)); - pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD)); -#endif -#endif -} - -void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd, - target_ulong addr) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - MEMOP_IDX(DF_DOUBLE) -#if !defined(CONFIG_USER_ONLY) - pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC()); - pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC()); -#else - pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE)); - pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE)); -#endif -} - -#define MSA_PAGESPAN(x) \ - ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN / 8 - 1) >= TARGET_PAGE_SIZE) - -static inline void ensure_writable_pages(CPUMIPSState *env, - target_ulong addr, - int mmu_idx, - uintptr_t retaddr) -{ - /* FIXME: Probe the actual accesses (pass and use a size) */ - if (unlikely(MSA_PAGESPAN(addr))) { - /* first page */ - probe_write(env, addr, 0, mmu_idx, retaddr); - /* second page */ - addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - probe_write(env, addr, 0, mmu_idx, retaddr); - } -} - -void helper_msa_st_b(CPUMIPSState *env, uint32_t wd, - target_ulong addr) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - int mmu_idx = cpu_mmu_index(env, false); - - MEMOP_IDX(DF_BYTE) - ensure_writable_pages(env, addr, mmu_idx, GETPC()); -#if !defined(CONFIG_USER_ONLY) -#if !defined(HOST_WORDS_BIGENDIAN) - helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC()); -#else - helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC()); - helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC()); -#endif -#else -#if !defined(HOST_WORDS_BIGENDIAN) - cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]); - cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]); - cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]); - cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]); - cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]); - cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]); - cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]); - cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]); - cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]); - cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]); - cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]); - cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]); - cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]); - cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]); - cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]); - cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]); -#else - cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]); - cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]); - cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]); - cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]); - cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]); - cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]); - cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]); - cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]); - cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]); - cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]); - cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]); - cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]); - cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]); - cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]); - cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]); - cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]); -#endif -#endif -} - -void helper_msa_st_h(CPUMIPSState *env, uint32_t wd, - target_ulong addr) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - int mmu_idx = cpu_mmu_index(env, false); - - MEMOP_IDX(DF_HALF) - ensure_writable_pages(env, addr, mmu_idx, GETPC()); -#if !defined(CONFIG_USER_ONLY) -#if !defined(HOST_WORDS_BIGENDIAN) - helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC()); -#else - helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC()); - helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC()); -#endif -#else -#if !defined(HOST_WORDS_BIGENDIAN) - cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]); - cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]); - cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]); - cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]); - cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]); - cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]); - cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]); - cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]); -#else - cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]); - cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]); - cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]); - cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]); - cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]); - cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]); - cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]); - cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]); -#endif -#endif -} - -void helper_msa_st_w(CPUMIPSState *env, uint32_t wd, - target_ulong addr) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - int mmu_idx = cpu_mmu_index(env, false); - - MEMOP_IDX(DF_WORD) - ensure_writable_pages(env, addr, mmu_idx, GETPC()); -#if !defined(CONFIG_USER_ONLY) -#if !defined(HOST_WORDS_BIGENDIAN) - helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[0], oi, GETPC()); - helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[1], oi, GETPC()); - helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[2], oi, GETPC()); - helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[3], oi, GETPC()); -#else - helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[0], oi, GETPC()); - helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[1], oi, GETPC()); - helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[2], oi, GETPC()); - helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[3], oi, GETPC()); -#endif -#else -#if !defined(HOST_WORDS_BIGENDIAN) - cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]); - cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]); - cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]); - cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]); -#else - cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]); - cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]); - cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]); - cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]); -#endif -#endif -} - -void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, - target_ulong addr) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - int mmu_idx = cpu_mmu_index(env, false); - - MEMOP_IDX(DF_DOUBLE) - ensure_writable_pages(env, addr, mmu_idx, GETPC()); -#if !defined(CONFIG_USER_ONLY) - helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC()); - helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC()); -#else - cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]); - cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]); -#endif -} - void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) { #ifndef CONFIG_USER_ONLY From patchwork Mon Nov 23 20:44:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926735 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 10FA2C2D0E4 for ; Mon, 23 Nov 2020 20:50:49 +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 0E72420706 for ; Mon, 23 Nov 2020 20:50:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DwqJ/vd9" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0E72420706 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:45044 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khInO-0006Jv-Rd for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 15:50:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46452) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIi9-0000yX-W3 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:22 -0500 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]:38194) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIi5-0001HA-PX for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:21 -0500 Received: by mail-wm1-x32d.google.com with SMTP id 1so729468wme.3 for ; Mon, 23 Nov 2020 12:45:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=4LRz+2kXa1G+kvmW7hNaI1eqoy4+tVkf4TaV4Xk9Z+E=; b=DwqJ/vd9HTR11BZ3k2Id5/sLMEnOGB0vdwiaNJChvooRrISbdOWWykI+Uk7Rs3WI8i hD7DYRMsDc0gXC2RR19v12NWSkLw2wFIIVhJ7IH/4m4OtlNoT+4wAgK97AMThaZnjHTV Ao5jQdDmUo1pQGcoSs5Qw25DEycpKeuRJMAwm8jf5dmjS3hmVRpf26aVNC7xfn7hsopb OAK/FjiTdQmAy+zIMzHN2OuaV5dj9nvgbiZSsyTCADt+P43gAmaU1TdiPUhgsanEAsiD KgIANnEIUUxuduPAuI/emPW6Cuvj3PeoakRFk+/6hBjo3EXXLvK0fuMl+SznMZTVtS6l YHXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=4LRz+2kXa1G+kvmW7hNaI1eqoy4+tVkf4TaV4Xk9Z+E=; b=AfBuZHxtydzuJBYKsHlreOqX2N8s4p8xKbyyGYgRurO9flTXOrU1K3343L817fTkNN lvyWDGbiogy93v1Gvz8l7a3rySsHHX5pybj5ZTEj6vRRNms7lucpe8QKiO/wx8a5zxzj 2WrBMULPCHJFFnNGtkLv2bxxiZsf5MpKpg21LAD0ojKIJ+NhtuuFBaO6zfjT6d+l23CT C7eyQS2TGSAmkc00OEUg52+KQdvhPgUv7wGtPWA3Li3CTYOL+hH0zX3AZnpEKZtiMrsq TDlTxpHt96ZD8nS4WxEqg/hBNrfWUeL3z/4tKtnKMoUuDiMRq+A1dWt66cJ7kOLS/Vgs aHRA== X-Gm-Message-State: AOAM531ifwT7dt3ouSRZihrT/T6IAlQe2FZbPpIDZIR8doRWCVY2EEHM aMpwTpIYhlMlT5ho/F7RCHRy2cV3H/Q= X-Google-Smtp-Source: ABdhPJyVbZgM64vgFn45kXP22W9Bg36hp+F239TYZItMJYaQyMJvv7D5duz2Jm3yGvjSYRwJ7aWPlg== X-Received: by 2002:a1c:3b87:: with SMTP id i129mr760412wma.134.1606164315537; Mon, 23 Nov 2020 12:45:15 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id p21sm855263wma.41.2020.11.23.12.45.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:14 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 05/28] target/mips: Extract MSA helper definitions Date: Mon, 23 Nov 2020 21:44:25 +0100 Message-Id: <20201123204448.3260804-6-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32d; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x32d.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Keep all MSA-related code altogether. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201120210844.2625602-4-f4bug@amsat.org> --- target/mips/helper.h | 436 +----------------------------- target/mips/mod-msa_helper.h.inc | 443 +++++++++++++++++++++++++++++++ 2 files changed, 445 insertions(+), 434 deletions(-) create mode 100644 target/mips/mod-msa_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index e97655dc0eb..80eb675fa64 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -781,438 +781,6 @@ DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env) DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) -/* MIPS SIMD Architecture */ - -DEF_HELPER_3(msa_nloc_b, void, env, i32, i32) -DEF_HELPER_3(msa_nloc_h, void, env, i32, i32) -DEF_HELPER_3(msa_nloc_w, void, env, i32, i32) -DEF_HELPER_3(msa_nloc_d, void, env, i32, i32) - -DEF_HELPER_3(msa_nlzc_b, void, env, i32, i32) -DEF_HELPER_3(msa_nlzc_h, void, env, i32, i32) -DEF_HELPER_3(msa_nlzc_w, void, env, i32, i32) -DEF_HELPER_3(msa_nlzc_d, void, env, i32, i32) - -DEF_HELPER_3(msa_pcnt_b, void, env, i32, i32) -DEF_HELPER_3(msa_pcnt_h, void, env, i32, i32) -DEF_HELPER_3(msa_pcnt_w, void, env, i32, i32) -DEF_HELPER_3(msa_pcnt_d, void, env, i32, i32) - -DEF_HELPER_4(msa_binsl_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsl_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsl_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsl_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_binsr_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsr_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsr_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsr_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_bclr_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bclr_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bclr_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bclr_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_bneg_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bneg_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bneg_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bneg_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_bset_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bset_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bset_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bset_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_add_a_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_add_a_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_add_a_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_add_a_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_adds_a_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_a_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_a_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_a_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_adds_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_adds_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_addv_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_addv_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_addv_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_addv_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_hadd_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hadd_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hadd_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_hadd_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hadd_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hadd_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_ave_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_ave_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_aver_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_aver_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_ceq_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ceq_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ceq_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ceq_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_cle_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_cle_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_cle_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_cle_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_cle_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_cle_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_cle_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_cle_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_clt_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_clt_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_clt_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_clt_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_clt_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_clt_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_clt_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_clt_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_div_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_div_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_div_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_div_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_div_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_div_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_div_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_div_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_max_a_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_a_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_a_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_a_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_s_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_max_u_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_a_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_a_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_a_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_a_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_s_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_min_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_mod_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mod_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mod_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mod_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_mod_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mod_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mod_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mod_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_maddv_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_maddv_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_maddv_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_maddv_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_msubv_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_msubv_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_msubv_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_msubv_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_mulv_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mulv_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mulv_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_mulv_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_asub_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_asub_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_asub_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_asub_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_asub_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_asub_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_asub_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_asub_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_hsub_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hsub_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hsub_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_hsub_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hsub_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hsub_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_subs_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subs_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subs_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subs_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_subs_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subs_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subs_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subs_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_subsus_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subsus_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subsus_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subsus_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_subsuu_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subsuu_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subsuu_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subsuu_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_subv_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subv_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subv_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_subv_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvev_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvod_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvod_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvod_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvod_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvl_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvl_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvl_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvl_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvr_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvr_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvr_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ilvr_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_pckev_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_pckev_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_pckev_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_pckev_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_pckod_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_pckod_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_pckod_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_pckod_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_sll_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_sll_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_sll_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_sll_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_sra_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_sra_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_sra_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_sra_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_srar_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srar_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srar_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srar_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_srl_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srl_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srl_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srl_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_srlr_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srlr_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srlr_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_srlr_d, void, env, i32, i32, i32) - -DEF_HELPER_3(msa_move_v, void, env, i32, i32) - -DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) -DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) - -DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32) -DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32) - -DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) - -DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32) - -DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dotp_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dotp_s_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dotp_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dotp_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dotp_u_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpadd_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpadd_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpadd_u_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpsub_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpsub_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpsub_s_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpsub_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpsub_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_dpsub_u_d, void, env, i32, i32, i32) -DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32) - -DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) - -DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) -DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) -DEF_HELPER_2(msa_cfcmsa, tl, env, i32) - -DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fcueq_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fcult_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fcule_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fcor_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_msub_q_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32) - -DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_copy_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_copy_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32) -DEF_HELPER_4(msa_copy_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_copy_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_copy_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_insert_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_insert_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_insert_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_insert_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) - -#define MSALDST_PROTO(type) \ -DEF_HELPER_3(msa_ld_ ## type, void, env, i32, tl) \ -DEF_HELPER_3(msa_st_ ## type, void, env, i32, tl) -MSALDST_PROTO(b) -MSALDST_PROTO(h) -MSALDST_PROTO(w) -MSALDST_PROTO(d) -#undef MSALDST_PROTO - DEF_HELPER_3(cache, void, env, tl, i32) + +#include "mod-msa_helper.h.inc" diff --git a/target/mips/mod-msa_helper.h.inc b/target/mips/mod-msa_helper.h.inc new file mode 100644 index 00000000000..4963d1553a0 --- /dev/null +++ b/target/mips/mod-msa_helper.h.inc @@ -0,0 +1,443 @@ +/* + * MIPS SIMD Architecture Module (MSA) helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +DEF_HELPER_3(msa_nloc_b, void, env, i32, i32) +DEF_HELPER_3(msa_nloc_h, void, env, i32, i32) +DEF_HELPER_3(msa_nloc_w, void, env, i32, i32) +DEF_HELPER_3(msa_nloc_d, void, env, i32, i32) + +DEF_HELPER_3(msa_nlzc_b, void, env, i32, i32) +DEF_HELPER_3(msa_nlzc_h, void, env, i32, i32) +DEF_HELPER_3(msa_nlzc_w, void, env, i32, i32) +DEF_HELPER_3(msa_nlzc_d, void, env, i32, i32) + +DEF_HELPER_3(msa_pcnt_b, void, env, i32, i32) +DEF_HELPER_3(msa_pcnt_h, void, env, i32, i32) +DEF_HELPER_3(msa_pcnt_w, void, env, i32, i32) +DEF_HELPER_3(msa_pcnt_d, void, env, i32, i32) + +DEF_HELPER_4(msa_binsl_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsl_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsl_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsl_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_binsr_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsr_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsr_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsr_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_bclr_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bclr_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bclr_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bclr_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_bneg_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bneg_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bneg_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bneg_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_bset_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bset_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bset_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bset_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_add_a_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_add_a_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_add_a_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_add_a_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_adds_a_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_a_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_a_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_a_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_adds_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_adds_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_adds_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_addv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_addv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_addv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_addv_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_hadd_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_hadd_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_hadd_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_hadd_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_hadd_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_hadd_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_ave_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_ave_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_aver_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_aver_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_ceq_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ceq_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ceq_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ceq_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_cle_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_cle_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_clt_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_clt_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_div_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_div_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_max_a_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_a_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_a_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_a_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_max_u_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_a_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_a_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_a_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_a_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_min_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_mod_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_mod_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_maddv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_maddv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_maddv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_maddv_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_msubv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_msubv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_msubv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_msubv_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_mulv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mulv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mulv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mulv_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_asub_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_asub_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_asub_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_asub_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_asub_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_asub_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_asub_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_asub_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_hsub_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_hsub_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_hsub_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_hsub_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_hsub_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_hsub_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subs_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subs_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subsus_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsus_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsus_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsus_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subsuu_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsuu_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsuu_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsuu_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subv_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvev_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvod_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvod_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvod_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvod_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvl_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvl_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvl_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvl_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvr_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvr_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvr_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ilvr_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_pckev_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pckev_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pckev_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pckev_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pckod_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pckod_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pckod_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pckod_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_sll_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_sll_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_sll_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_sll_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_sra_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_sra_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_sra_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_sra_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_srar_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srar_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srar_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srar_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_srl_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srl_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srl_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srl_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_srlr_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srlr_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srlr_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_srlr_d, void, env, i32, i32, i32) + +DEF_HELPER_3(msa_move_v, void, env, i32, i32) + +DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32) + +DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_u_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_u_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_u_d, void, env, i32, i32, i32) +DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) +DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) +DEF_HELPER_2(msa_cfcmsa, tl, env, i32) + +DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcueq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcult_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcule_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcor_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_msub_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_copy_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) + +#define MSALDST_PROTO(type) \ +DEF_HELPER_3(msa_ld_ ## type, void, env, i32, tl) \ +DEF_HELPER_3(msa_st_ ## type, void, env, i32, tl) +MSALDST_PROTO(b) +MSALDST_PROTO(h) +MSALDST_PROTO(w) +MSALDST_PROTO(d) +#undef MSALDST_PROTO From patchwork Mon Nov 23 20:44:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926743 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 DD9FAC2D0E4 for ; Mon, 23 Nov 2020 20:54:57 +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 0AD47206B7 for ; Mon, 23 Nov 2020 20:54:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZAbYeISd" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0AD47206B7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:54518 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khIrP-00025L-TW for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 15:54:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46494) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIiG-0001BI-Cc for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:28 -0500 Received: from mail-wr1-x42f.google.com ([2a00:1450:4864:20::42f]:36541) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIiC-0001Ml-0d for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:28 -0500 Received: by mail-wr1-x42f.google.com with SMTP id z7so4294282wrn.3 for ; Mon, 23 Nov 2020 12:45:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=L6FwGxbIlIbktbOEAQbPDXlhz1iuhQrx2xCjj+ugYTM=; b=ZAbYeISdt8OoZCQlvPNwRz1wcLPr2rMxFIJSMyLobyu84+f7vTEDYGnPR0fWAm7gbH ROG1ls6RGROca/TC09OylSj6xQoJas94V9cS5yJ4MTdNiU+4F4m6dUp7LAb6c0Yfh+Yw ooh7Kd9c1FJMrIBCleylxS3gUkC4vd0sepf3xJkppO+C6MygN2GIvTDmyxiL/bt14f72 U+Iz3OSO5677T4vmYuiKrtnnUDssSKOmxRz802nOxVPhkKqEXgV2ZljcexwFRcD8dcBQ Vnn45mRtk2HbnrZcAXySSa7QgQhvz/KjQFoasE8HhNsLDrngtHrIxH7vbxqeSOR+o3ka kzjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=L6FwGxbIlIbktbOEAQbPDXlhz1iuhQrx2xCjj+ugYTM=; b=fI7VfiT4U7CGIEPxrt8p/n/kSTOBLD0FyHj7c7c1xBrDNb0Dg/CipARKph19ldDQda qyP1bC6fpcvVuCGh0giD7mJWvtICi1v62AcVP1O9R3fk85a82zPtPQBCN9N2q4m4idUx BMSBx50AkJWWGJUXyXNL7C3lSLXNmm1/7AQwdXIfGqpx/OAhekJapj1/RQnab3puI35F +sNfSz5PYefn7JzbYaZhPkJt4Mifp7Uv+JqvPM57KPAkQjC6VYOqLrhI51ZgmQ8/JeIQ 2bzLzy9mn8qYKnGnXjbggk3YhfsREB9pFLgo0YaQSB1/NAkUnoawuJSpwJpq3oDpXlRu 5D3g== X-Gm-Message-State: AOAM531dHxkBYh3e2tzbC4s1vlOmYtxA+/yNMd64rzR5ueyUNFuRnioU rxDPgarb9JGtIEDDk8sALFKvXqNjfr8= X-Google-Smtp-Source: ABdhPJwwjlHRqSKMxYRQ/iOr78VW8xTMGkz45tPUzVt072UHiepN5cmJdMYyfI2P7jbZnkPsnSA4qQ== X-Received: by 2002:a5d:4e09:: with SMTP id p9mr1552640wrt.345.1606164320805; Mon, 23 Nov 2020 12:45:20 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id k1sm21652700wrp.23.2020.11.23.12.45.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:19 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 06/28] target/mips: Extract MSA translation routines Date: Mon, 23 Nov 2020 21:44:26 +0100 Message-Id: <20201123204448.3260804-7-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::42f; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x42f.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract 2200 lines from the huge translate.c to a new file, 'mod-msa_translate.c.inc'. As there are too many inter-dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-5-f4bug@amsat.org> --- target/mips/translate.c | 2209 +------------------------- target/mips/mod-msa_translate.c.inc | 2218 +++++++++++++++++++++++++++ 2 files changed, 2219 insertions(+), 2208 deletions(-) create mode 100644 target/mips/mod-msa_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 5ec9fd7e92a..e174bf778e6 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -1211,239 +1211,6 @@ enum { OPC_NMSUB_PS = 0x3E | OPC_CP3, }; -/* MSA Opcodes */ -#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F)) -enum { - OPC_MSA_I8_00 = 0x00 | OPC_MSA, - OPC_MSA_I8_01 = 0x01 | OPC_MSA, - OPC_MSA_I8_02 = 0x02 | OPC_MSA, - OPC_MSA_I5_06 = 0x06 | OPC_MSA, - OPC_MSA_I5_07 = 0x07 | OPC_MSA, - OPC_MSA_BIT_09 = 0x09 | OPC_MSA, - OPC_MSA_BIT_0A = 0x0A | OPC_MSA, - OPC_MSA_3R_0D = 0x0D | OPC_MSA, - OPC_MSA_3R_0E = 0x0E | OPC_MSA, - OPC_MSA_3R_0F = 0x0F | OPC_MSA, - OPC_MSA_3R_10 = 0x10 | OPC_MSA, - OPC_MSA_3R_11 = 0x11 | OPC_MSA, - OPC_MSA_3R_12 = 0x12 | OPC_MSA, - OPC_MSA_3R_13 = 0x13 | OPC_MSA, - OPC_MSA_3R_14 = 0x14 | OPC_MSA, - OPC_MSA_3R_15 = 0x15 | OPC_MSA, - OPC_MSA_ELM = 0x19 | OPC_MSA, - OPC_MSA_3RF_1A = 0x1A | OPC_MSA, - OPC_MSA_3RF_1B = 0x1B | OPC_MSA, - OPC_MSA_3RF_1C = 0x1C | OPC_MSA, - OPC_MSA_VEC = 0x1E | OPC_MSA, - - /* MI10 instruction */ - OPC_LD_B = (0x20) | OPC_MSA, - OPC_LD_H = (0x21) | OPC_MSA, - OPC_LD_W = (0x22) | OPC_MSA, - OPC_LD_D = (0x23) | OPC_MSA, - OPC_ST_B = (0x24) | OPC_MSA, - OPC_ST_H = (0x25) | OPC_MSA, - OPC_ST_W = (0x26) | OPC_MSA, - OPC_ST_D = (0x27) | OPC_MSA, -}; - -enum { - /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */ - OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06, - OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07, - OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06, - OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06, - OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07, - OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06, - OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07, - OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06, - OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07, - OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06, - OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07, - OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07, - - /* I8 instruction */ - OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00, - OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01, - OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02, - OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00, - OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01, - OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02, - OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00, - OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01, - OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02, - OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00, - - /* VEC/2R/2RF instruction */ - OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC, - OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC, - OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC, - OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC, - OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC, - OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC, - OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC, - - OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC, - OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC, - - /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */ - OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R, - OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R, - OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R, - OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R, - - /* 2RF instruction df(bit 16) = _w, _d */ - OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF, - OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF, - OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF, - OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF, - OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF, - OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF, - OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF, - OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF, - OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF, - OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF, - OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF, - OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF, - OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF, - OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF, - OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF, - OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF, - - /* 3R instruction df(bits 22..21) = _b, _h, _w, d */ - OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D, - OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E, - OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F, - OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10, - OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11, - OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12, - OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13, - OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14, - OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15, - OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D, - OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E, - OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10, - OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11, - OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12, - OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13, - OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14, - OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15, - OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D, - OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E, - OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F, - OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10, - OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11, - OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12, - OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13, - OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14, - OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15, - OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D, - OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E, - OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F, - OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10, - OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11, - OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13, - OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14, - OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D, - OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E, - OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F, - OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10, - OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11, - OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12, - OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13, - OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14, - OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15, - OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D, - OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E, - OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F, - OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10, - OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11, - OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12, - OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13, - OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14, - OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15, - OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D, - OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E, - OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10, - OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12, - OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14, - OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15, - OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D, - OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E, - OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10, - OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12, - OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14, - OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15, - - /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */ - OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM, - OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM, - OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM, - OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM, - OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM, - OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM, - OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM, - OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM, - OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM, - - /* 3RF instruction _df(bit 21) = _w, _d */ - OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A, - OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B, - OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A, - OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B, - OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C, - OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A, - OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B, - OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C, - OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A, - OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B, - OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C, - OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A, - OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B, - OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C, - OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A, - OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B, - OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C, - OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A, - OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C, - OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A, - OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B, - OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A, - OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B, - OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A, - OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C, - OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A, - OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B, - OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C, - OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A, - OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C, - OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A, - OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B, - OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C, - OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A, - OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B, - OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C, - OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A, - OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B, - OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C, - OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A, - OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B, - - /* BIT instruction df(bits 22..16) = _B _H _W _D */ - OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09, - OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A, - OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09, - OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A, - OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09, - OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A, - OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09, - OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A, - OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09, - OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09, - OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09, - OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09, -}; - /* * @@ -2501,7 +2268,6 @@ static TCGv cpu_lladdr, cpu_llval; static TCGv_i32 hflags; static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; -static TCGv_i64 msa_wr_d[64]; #if defined(TARGET_MIPS64) /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */ @@ -2620,25 +2386,6 @@ static const char * const fregnames[] = { "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; -static const char * const msaregnames[] = { - "w0.d0", "w0.d1", "w1.d0", "w1.d1", - "w2.d0", "w2.d1", "w3.d0", "w3.d1", - "w4.d0", "w4.d1", "w5.d0", "w5.d1", - "w6.d0", "w6.d1", "w7.d0", "w7.d1", - "w8.d0", "w8.d1", "w9.d0", "w9.d1", - "w10.d0", "w10.d1", "w11.d0", "w11.d1", - "w12.d0", "w12.d1", "w13.d0", "w13.d1", - "w14.d0", "w14.d1", "w15.d0", "w15.d1", - "w16.d0", "w16.d1", "w17.d0", "w17.d1", - "w18.d0", "w18.d1", "w19.d0", "w19.d1", - "w20.d0", "w20.d1", "w21.d0", "w21.d1", - "w22.d0", "w22.d1", "w23.d0", "w23.d1", - "w24.d0", "w24.d1", "w25.d0", "w25.d1", - "w26.d0", "w26.d1", "w27.d0", "w27.d1", - "w28.d0", "w28.d1", "w29.d0", "w29.d1", - "w30.d0", "w30.d1", "w31.d0", "w31.d1", -}; - #if !defined(TARGET_MIPS64) static const char * const mxuregnames[] = { "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8", @@ -28690,1961 +28437,7 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) } } -/* MIPS SIMD Architecture (MSA) */ -static inline int check_msa_access(DisasContext *ctx) -{ - if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) && - !(ctx->hflags & MIPS_HFLAG_F64))) { - generate_exception_end(ctx, EXCP_RI); - return 0; - } - - if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) { - if (ctx->insn_flags & ASE_MSA) { - generate_exception_end(ctx, EXCP_MSADIS); - return 0; - } else { - generate_exception_end(ctx, EXCP_RI); - return 0; - } - } - return 1; -} - -static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt) -{ - /* generates tcg ops to check if any element is 0 */ - /* Note this function only works with MSA_WRLEN = 128 */ - uint64_t eval_zero_or_big = 0; - uint64_t eval_big = 0; - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - switch (df) { - case DF_BYTE: - eval_zero_or_big = 0x0101010101010101ULL; - eval_big = 0x8080808080808080ULL; - break; - case DF_HALF: - eval_zero_or_big = 0x0001000100010001ULL; - eval_big = 0x8000800080008000ULL; - break; - case DF_WORD: - eval_zero_or_big = 0x0000000100000001ULL; - eval_big = 0x8000000080000000ULL; - break; - case DF_DOUBLE: - eval_zero_or_big = 0x0000000000000001ULL; - eval_big = 0x8000000000000000ULL; - break; - } - tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big); - tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]); - tcg_gen_andi_i64(t0, t0, eval_big); - tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big); - tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]); - tcg_gen_andi_i64(t1, t1, eval_big); - tcg_gen_or_i64(t0, t0, t1); - /* if all bits are zero then all elements are not zero */ - /* if some bit is non-zero then some element is zero */ - tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0); - tcg_gen_trunc_i64_tl(tresult, t0); - tcg_temp_free_i64(t0); - tcg_temp_free_i64(t1); -} - -static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) -{ - uint8_t df = (ctx->opcode >> 21) & 0x3; - uint8_t wt = (ctx->opcode >> 16) & 0x1f; - int64_t s16 = (int16_t)ctx->opcode; - - check_msa_access(ctx); - - if (ctx->hflags & MIPS_HFLAG_BMASK) { - generate_exception_end(ctx, EXCP_RI); - return; - } - switch (op1) { - case OPC_BZ_V: - case OPC_BNZ_V: - { - TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]); - tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ? - TCG_COND_EQ : TCG_COND_NE, t0, t0, 0); - tcg_gen_trunc_i64_tl(bcond, t0); - tcg_temp_free_i64(t0); - } - break; - case OPC_BZ_B: - case OPC_BZ_H: - case OPC_BZ_W: - case OPC_BZ_D: - gen_check_zero_element(bcond, df, wt); - break; - case OPC_BNZ_B: - case OPC_BNZ_H: - case OPC_BNZ_W: - case OPC_BNZ_D: - gen_check_zero_element(bcond, df, wt); - tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0); - break; - } - - ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4; - - ctx->hflags |= MIPS_HFLAG_BC; - ctx->hflags |= MIPS_HFLAG_BDS32; -} - -static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24))) - uint8_t i8 = (ctx->opcode >> 16) & 0xff; - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - - TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 tws = tcg_const_i32(ws); - TCGv_i32 ti8 = tcg_const_i32(i8); - - switch (MASK_MSA_I8(ctx->opcode)) { - case OPC_ANDI_B: - gen_helper_msa_andi_b(cpu_env, twd, tws, ti8); - break; - case OPC_ORI_B: - gen_helper_msa_ori_b(cpu_env, twd, tws, ti8); - break; - case OPC_NORI_B: - gen_helper_msa_nori_b(cpu_env, twd, tws, ti8); - break; - case OPC_XORI_B: - gen_helper_msa_xori_b(cpu_env, twd, tws, ti8); - break; - case OPC_BMNZI_B: - gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8); - break; - case OPC_BMZI_B: - gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8); - break; - case OPC_BSELI_B: - gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8); - break; - case OPC_SHF_B: - case OPC_SHF_H: - case OPC_SHF_W: - { - uint8_t df = (ctx->opcode >> 24) & 0x3; - if (df == DF_DOUBLE) { - generate_exception_end(ctx, EXCP_RI); - } else { - TCGv_i32 tdf = tcg_const_i32(df); - gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8); - tcg_temp_free_i32(tdf); - } - } - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); - tcg_temp_free_i32(ti8); -} - -static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) - uint8_t df = (ctx->opcode >> 21) & 0x3; - int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5); - uint8_t u5 = (ctx->opcode >> 16) & 0x1f; - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - - TCGv_i32 tdf = tcg_const_i32(df); - TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 tws = tcg_const_i32(ws); - TCGv_i32 timm = tcg_temp_new_i32(); - tcg_gen_movi_i32(timm, u5); - - switch (MASK_MSA_I5(ctx->opcode)) { - case OPC_ADDVI_df: - gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_SUBVI_df: - gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_MAXI_S_df: - tcg_gen_movi_i32(timm, s5); - gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_MAXI_U_df: - gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_MINI_S_df: - tcg_gen_movi_i32(timm, s5); - gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_MINI_U_df: - gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_CEQI_df: - tcg_gen_movi_i32(timm, s5); - gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_CLTI_S_df: - tcg_gen_movi_i32(timm, s5); - gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_CLTI_U_df: - gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_CLEI_S_df: - tcg_gen_movi_i32(timm, s5); - gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_CLEI_U_df: - gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm); - break; - case OPC_LDI_df: - { - int32_t s10 = sextract32(ctx->opcode, 11, 10); - tcg_gen_movi_i32(timm, s10); - gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm); - } - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free_i32(tdf); - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); - tcg_temp_free_i32(timm); -} - -static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) - uint8_t dfm = (ctx->opcode >> 16) & 0x7f; - uint32_t df = 0, m = 0; - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - - TCGv_i32 tdf; - TCGv_i32 tm; - TCGv_i32 twd; - TCGv_i32 tws; - - if ((dfm & 0x40) == 0x00) { - m = dfm & 0x3f; - df = DF_DOUBLE; - } else if ((dfm & 0x60) == 0x40) { - m = dfm & 0x1f; - df = DF_WORD; - } else if ((dfm & 0x70) == 0x60) { - m = dfm & 0x0f; - df = DF_HALF; - } else if ((dfm & 0x78) == 0x70) { - m = dfm & 0x7; - df = DF_BYTE; - } else { - generate_exception_end(ctx, EXCP_RI); - return; - } - - tdf = tcg_const_i32(df); - tm = tcg_const_i32(m); - twd = tcg_const_i32(wd); - tws = tcg_const_i32(ws); - - switch (MASK_MSA_BIT(ctx->opcode)) { - case OPC_SLLI_df: - gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_SRAI_df: - gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_SRLI_df: - gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_BCLRI_df: - gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_BSETI_df: - gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_BNEGI_df: - gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_BINSLI_df: - gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_BINSRI_df: - gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_SAT_S_df: - gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_SAT_U_df: - gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_SRARI_df: - gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm); - break; - case OPC_SRLRI_df: - gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm); - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free_i32(tdf); - tcg_temp_free_i32(tm); - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); -} - -static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) - uint8_t df = (ctx->opcode >> 21) & 0x3; - uint8_t wt = (ctx->opcode >> 16) & 0x1f; - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - - TCGv_i32 tdf = tcg_const_i32(df); - TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 tws = tcg_const_i32(ws); - TCGv_i32 twt = tcg_const_i32(wt); - - switch (MASK_MSA_3R(ctx->opcode)) { - case OPC_BINSL_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_binsl_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_binsl_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_binsl_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_binsl_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_BINSR_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_binsr_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_binsr_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_binsr_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_binsr_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_BCLR_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_bclr_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_bclr_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_bclr_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_bclr_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_BNEG_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_bneg_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_bneg_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_bneg_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_bneg_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_BSET_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_bset_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_bset_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_bset_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_bset_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ADD_A_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_add_a_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_add_a_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_add_a_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_add_a_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ADDS_A_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ADDS_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ADDS_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ADDV_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_addv_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_addv_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_addv_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_addv_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_AVE_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_AVE_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_AVER_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_AVER_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_CEQ_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_ceq_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_ceq_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_ceq_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_ceq_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_CLE_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_CLE_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_CLT_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_CLT_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_DIV_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_div_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_div_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_div_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_div_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_DIV_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_div_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_div_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_div_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_div_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MAX_A_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_max_a_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_max_a_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_max_a_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_max_a_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MAX_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_max_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_max_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_max_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_max_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MAX_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_max_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_max_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_max_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_max_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MIN_A_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_min_a_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_min_a_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_min_a_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_min_a_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MIN_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_min_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_min_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_min_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_min_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MIN_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_min_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_min_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_min_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_min_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MOD_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MOD_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MADDV_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_maddv_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_maddv_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_maddv_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_maddv_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MSUBV_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_msubv_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_msubv_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_msubv_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_msubv_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ASUB_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ASUB_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ILVEV_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ILVOD_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ILVL_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_ILVR_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_PCKEV_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_pckev_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_pckev_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_pckev_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_pckev_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_PCKOD_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_pckod_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_pckod_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_pckod_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_pckod_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SLL_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_sll_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_sll_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_sll_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_sll_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SRA_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_sra_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_sra_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_sra_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_sra_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SRAR_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_srar_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_srar_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_srar_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_srar_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SRL_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_srl_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_srl_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_srl_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_srl_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SRLR_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_srlr_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_srlr_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_srlr_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_srlr_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SUBS_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_MULV_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_mulv_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_mulv_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_mulv_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_mulv_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SLD_df: - gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_VSHF_df: - gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_SUBV_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_subv_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_subv_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_subv_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_subv_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SUBS_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SPLAT_df: - gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_SUBSUS_U_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_SUBSUU_S_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt); - break; - case DF_HALF: - gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt); - break; - } - break; - - case OPC_DOTP_S_df: - case OPC_DOTP_U_df: - case OPC_DPADD_S_df: - case OPC_DPADD_U_df: - case OPC_DPSUB_S_df: - case OPC_HADD_S_df: - case OPC_DPSUB_U_df: - case OPC_HADD_U_df: - case OPC_HSUB_S_df: - case OPC_HSUB_U_df: - if (df == DF_BYTE) { - generate_exception_end(ctx, EXCP_RI); - break; - } - switch (MASK_MSA_3R(ctx->opcode)) { - case OPC_HADD_S_df: - switch (df) { - case DF_HALF: - gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_HADD_U_df: - switch (df) { - case DF_HALF: - gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_HSUB_S_df: - switch (df) { - case DF_HALF: - gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_HSUB_U_df: - switch (df) { - case DF_HALF: - gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_DOTP_S_df: - switch (df) { - case DF_HALF: - gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_DOTP_U_df: - switch (df) { - case DF_HALF: - gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_DPADD_S_df: - switch (df) { - case DF_HALF: - gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_DPADD_U_df: - switch (df) { - case DF_HALF: - gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_DPSUB_S_df: - switch (df) { - case DF_HALF: - gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt); - break; - } - break; - case OPC_DPSUB_U_df: - switch (df) { - case DF_HALF: - gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt); - break; - case DF_WORD: - gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt); - break; - case DF_DOUBLE: - gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt); - break; - } - break; - } - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); - tcg_temp_free_i32(twt); - tcg_temp_free_i32(tdf); -} - -static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16))) - uint8_t source = (ctx->opcode >> 11) & 0x1f; - uint8_t dest = (ctx->opcode >> 6) & 0x1f; - TCGv telm = tcg_temp_new(); - TCGv_i32 tsr = tcg_const_i32(source); - TCGv_i32 tdt = tcg_const_i32(dest); - - switch (MASK_MSA_ELM_DF3E(ctx->opcode)) { - case OPC_CTCMSA: - gen_load_gpr(telm, source); - gen_helper_msa_ctcmsa(cpu_env, telm, tdt); - break; - case OPC_CFCMSA: - gen_helper_msa_cfcmsa(telm, cpu_env, tsr); - gen_store_gpr(telm, dest); - break; - case OPC_MOVE_V: - gen_helper_msa_move_v(cpu_env, tdt, tsr); - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free(telm); - tcg_temp_free_i32(tdt); - tcg_temp_free_i32(tsr); -} - -static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, - uint32_t n) -{ -#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22))) - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - - TCGv_i32 tws = tcg_const_i32(ws); - TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 tn = tcg_const_i32(n); - TCGv_i32 tdf = tcg_const_i32(df); - - switch (MASK_MSA_ELM(ctx->opcode)) { - case OPC_SLDI_df: - gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn); - break; - case OPC_SPLATI_df: - gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn); - break; - case OPC_INSVE_df: - gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn); - break; - case OPC_COPY_S_df: - case OPC_COPY_U_df: - case OPC_INSERT_df: -#if !defined(TARGET_MIPS64) - /* Double format valid only for MIPS64 */ - if (df == DF_DOUBLE) { - generate_exception_end(ctx, EXCP_RI); - break; - } - if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) && - (df == DF_WORD)) { - generate_exception_end(ctx, EXCP_RI); - break; - } -#endif - switch (MASK_MSA_ELM(ctx->opcode)) { - case OPC_COPY_S_df: - if (likely(wd != 0)) { - switch (df) { - case DF_BYTE: - gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn); - break; - case DF_HALF: - gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn); - break; - case DF_WORD: - gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn); - break; -#if defined(TARGET_MIPS64) - case DF_DOUBLE: - gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn); - break; -#endif - default: - assert(0); - } - } - break; - case OPC_COPY_U_df: - if (likely(wd != 0)) { - switch (df) { - case DF_BYTE: - gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn); - break; - case DF_HALF: - gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn); - break; -#if defined(TARGET_MIPS64) - case DF_WORD: - gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn); - break; -#endif - default: - assert(0); - } - } - break; - case OPC_INSERT_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_insert_b(cpu_env, twd, tws, tn); - break; - case DF_HALF: - gen_helper_msa_insert_h(cpu_env, twd, tws, tn); - break; - case DF_WORD: - gen_helper_msa_insert_w(cpu_env, twd, tws, tn); - break; -#if defined(TARGET_MIPS64) - case DF_DOUBLE: - gen_helper_msa_insert_d(cpu_env, twd, tws, tn); - break; -#endif - default: - assert(0); - } - break; - } - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - } - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); - tcg_temp_free_i32(tn); - tcg_temp_free_i32(tdf); -} - -static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx) -{ - uint8_t dfn = (ctx->opcode >> 16) & 0x3f; - uint32_t df = 0, n = 0; - - if ((dfn & 0x30) == 0x00) { - n = dfn & 0x0f; - df = DF_BYTE; - } else if ((dfn & 0x38) == 0x20) { - n = dfn & 0x07; - df = DF_HALF; - } else if ((dfn & 0x3c) == 0x30) { - n = dfn & 0x03; - df = DF_WORD; - } else if ((dfn & 0x3e) == 0x38) { - n = dfn & 0x01; - df = DF_DOUBLE; - } else if (dfn == 0x3E) { - /* CTCMSA, CFCMSA, MOVE.V */ - gen_msa_elm_3e(env, ctx); - return; - } else { - generate_exception_end(ctx, EXCP_RI); - return; - } - - gen_msa_elm_df(env, ctx, df, n); -} - -static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22))) - uint8_t df = (ctx->opcode >> 21) & 0x1; - uint8_t wt = (ctx->opcode >> 16) & 0x1f; - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - - TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 tws = tcg_const_i32(ws); - TCGv_i32 twt = tcg_const_i32(wt); - TCGv_i32 tdf = tcg_temp_new_i32(); - - /* adjust df value for floating-point instruction */ - tcg_gen_movi_i32(tdf, df + 2); - - switch (MASK_MSA_3RF(ctx->opcode)) { - case OPC_FCAF_df: - gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FADD_df: - gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCUN_df: - gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSUB_df: - gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCOR_df: - gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCEQ_df: - gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FMUL_df: - gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCUNE_df: - gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCUEQ_df: - gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FDIV_df: - gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCNE_df: - gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCLT_df: - gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FMADD_df: - gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MUL_Q_df: - tcg_gen_movi_i32(tdf, df + 1); - gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCULT_df: - gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FMSUB_df: - gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MADD_Q_df: - tcg_gen_movi_i32(tdf, df + 1); - gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCLE_df: - gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MSUB_Q_df: - tcg_gen_movi_i32(tdf, df + 1); - gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FCULE_df: - gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FEXP2_df: - gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSAF_df: - gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FEXDO_df: - gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSUN_df: - gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSOR_df: - gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSEQ_df: - gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FTQ_df: - gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSUNE_df: - gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSUEQ_df: - gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSNE_df: - gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSLT_df: - gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FMIN_df: - gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MULR_Q_df: - tcg_gen_movi_i32(tdf, df + 1); - gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSULT_df: - gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FMIN_A_df: - gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MADDR_Q_df: - tcg_gen_movi_i32(tdf, df + 1); - gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSLE_df: - gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FMAX_df: - gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MSUBR_Q_df: - tcg_gen_movi_i32(tdf, df + 1); - gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FSULE_df: - gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_FMAX_A_df: - gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt); - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); - tcg_temp_free_i32(twt); - tcg_temp_free_i32(tdf); -} - -static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \ - (op & (0x7 << 18))) - uint8_t wt = (ctx->opcode >> 16) & 0x1f; - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - uint8_t df = (ctx->opcode >> 16) & 0x3; - TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 tws = tcg_const_i32(ws); - TCGv_i32 twt = tcg_const_i32(wt); - TCGv_i32 tdf = tcg_const_i32(df); - - switch (MASK_MSA_2R(ctx->opcode)) { - case OPC_FILL_df: -#if !defined(TARGET_MIPS64) - /* Double format valid only for MIPS64 */ - if (df == DF_DOUBLE) { - generate_exception_end(ctx, EXCP_RI); - break; - } -#endif - gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */ - break; - case OPC_NLOC_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_nloc_b(cpu_env, twd, tws); - break; - case DF_HALF: - gen_helper_msa_nloc_h(cpu_env, twd, tws); - break; - case DF_WORD: - gen_helper_msa_nloc_w(cpu_env, twd, tws); - break; - case DF_DOUBLE: - gen_helper_msa_nloc_d(cpu_env, twd, tws); - break; - } - break; - case OPC_NLZC_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_nlzc_b(cpu_env, twd, tws); - break; - case DF_HALF: - gen_helper_msa_nlzc_h(cpu_env, twd, tws); - break; - case DF_WORD: - gen_helper_msa_nlzc_w(cpu_env, twd, tws); - break; - case DF_DOUBLE: - gen_helper_msa_nlzc_d(cpu_env, twd, tws); - break; - } - break; - case OPC_PCNT_df: - switch (df) { - case DF_BYTE: - gen_helper_msa_pcnt_b(cpu_env, twd, tws); - break; - case DF_HALF: - gen_helper_msa_pcnt_h(cpu_env, twd, tws); - break; - case DF_WORD: - gen_helper_msa_pcnt_w(cpu_env, twd, tws); - break; - case DF_DOUBLE: - gen_helper_msa_pcnt_d(cpu_env, twd, tws); - break; - } - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); - tcg_temp_free_i32(twt); - tcg_temp_free_i32(tdf); -} - -static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \ - (op & (0xf << 17))) - uint8_t wt = (ctx->opcode >> 16) & 0x1f; - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - uint8_t df = (ctx->opcode >> 16) & 0x1; - TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 tws = tcg_const_i32(ws); - TCGv_i32 twt = tcg_const_i32(wt); - /* adjust df value for floating-point instruction */ - TCGv_i32 tdf = tcg_const_i32(df + 2); - - switch (MASK_MSA_2RF(ctx->opcode)) { - case OPC_FCLASS_df: - gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws); - break; - case OPC_FTRUNC_S_df: - gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws); - break; - case OPC_FTRUNC_U_df: - gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws); - break; - case OPC_FSQRT_df: - gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws); - break; - case OPC_FRSQRT_df: - gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws); - break; - case OPC_FRCP_df: - gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws); - break; - case OPC_FRINT_df: - gen_helper_msa_frint_df(cpu_env, tdf, twd, tws); - break; - case OPC_FLOG2_df: - gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws); - break; - case OPC_FEXUPL_df: - gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws); - break; - case OPC_FEXUPR_df: - gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws); - break; - case OPC_FFQL_df: - gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws); - break; - case OPC_FFQR_df: - gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws); - break; - case OPC_FTINT_S_df: - gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws); - break; - case OPC_FTINT_U_df: - gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws); - break; - case OPC_FFINT_S_df: - gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws); - break; - case OPC_FFINT_U_df: - gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws); - break; - } - - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); - tcg_temp_free_i32(twt); - tcg_temp_free_i32(tdf); -} - -static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx) -{ -#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21))) - uint8_t wt = (ctx->opcode >> 16) & 0x1f; - uint8_t ws = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 tws = tcg_const_i32(ws); - TCGv_i32 twt = tcg_const_i32(wt); - - switch (MASK_MSA_VEC(ctx->opcode)) { - case OPC_AND_V: - gen_helper_msa_and_v(cpu_env, twd, tws, twt); - break; - case OPC_OR_V: - gen_helper_msa_or_v(cpu_env, twd, tws, twt); - break; - case OPC_NOR_V: - gen_helper_msa_nor_v(cpu_env, twd, tws, twt); - break; - case OPC_XOR_V: - gen_helper_msa_xor_v(cpu_env, twd, tws, twt); - break; - case OPC_BMNZ_V: - gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt); - break; - case OPC_BMZ_V: - gen_helper_msa_bmz_v(cpu_env, twd, tws, twt); - break; - case OPC_BSEL_V: - gen_helper_msa_bsel_v(cpu_env, twd, tws, twt); - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free_i32(twd); - tcg_temp_free_i32(tws); - tcg_temp_free_i32(twt); -} - -static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx) -{ - switch (MASK_MSA_VEC(ctx->opcode)) { - case OPC_AND_V: - case OPC_OR_V: - case OPC_NOR_V: - case OPC_XOR_V: - case OPC_BMNZ_V: - case OPC_BMZ_V: - case OPC_BSEL_V: - gen_msa_vec_v(env, ctx); - break; - case OPC_MSA_2R: - gen_msa_2r(env, ctx); - break; - case OPC_MSA_2RF: - gen_msa_2rf(env, ctx); - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -static void gen_msa(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = ctx->opcode; - check_insn(ctx, ASE_MSA); - check_msa_access(ctx); - - switch (MASK_MSA_MINOR(opcode)) { - case OPC_MSA_I8_00: - case OPC_MSA_I8_01: - case OPC_MSA_I8_02: - gen_msa_i8(env, ctx); - break; - case OPC_MSA_I5_06: - case OPC_MSA_I5_07: - gen_msa_i5(env, ctx); - break; - case OPC_MSA_BIT_09: - case OPC_MSA_BIT_0A: - gen_msa_bit(env, ctx); - break; - case OPC_MSA_3R_0D: - case OPC_MSA_3R_0E: - case OPC_MSA_3R_0F: - case OPC_MSA_3R_10: - case OPC_MSA_3R_11: - case OPC_MSA_3R_12: - case OPC_MSA_3R_13: - case OPC_MSA_3R_14: - case OPC_MSA_3R_15: - gen_msa_3r(env, ctx); - break; - case OPC_MSA_ELM: - gen_msa_elm(env, ctx); - break; - case OPC_MSA_3RF_1A: - case OPC_MSA_3RF_1B: - case OPC_MSA_3RF_1C: - gen_msa_3rf(env, ctx); - break; - case OPC_MSA_VEC: - gen_msa_vec(env, ctx); - break; - case OPC_LD_B: - case OPC_LD_H: - case OPC_LD_W: - case OPC_LD_D: - case OPC_ST_B: - case OPC_ST_H: - case OPC_ST_W: - case OPC_ST_D: - { - int32_t s10 = sextract32(ctx->opcode, 16, 10); - uint8_t rs = (ctx->opcode >> 11) & 0x1f; - uint8_t wd = (ctx->opcode >> 6) & 0x1f; - uint8_t df = (ctx->opcode >> 0) & 0x3; - - TCGv_i32 twd = tcg_const_i32(wd); - TCGv taddr = tcg_temp_new(); - gen_base_offset_addr(ctx, taddr, rs, s10 << df); - - switch (MASK_MSA_MINOR(opcode)) { - case OPC_LD_B: - gen_helper_msa_ld_b(cpu_env, twd, taddr); - break; - case OPC_LD_H: - gen_helper_msa_ld_h(cpu_env, twd, taddr); - break; - case OPC_LD_W: - gen_helper_msa_ld_w(cpu_env, twd, taddr); - break; - case OPC_LD_D: - gen_helper_msa_ld_d(cpu_env, twd, taddr); - break; - case OPC_ST_B: - gen_helper_msa_st_b(cpu_env, twd, taddr); - break; - case OPC_ST_H: - gen_helper_msa_st_h(cpu_env, twd, taddr); - break; - case OPC_ST_W: - gen_helper_msa_st_w(cpu_env, twd, taddr); - break; - case OPC_ST_D: - gen_helper_msa_st_d(cpu_env, twd, taddr); - break; - } - - tcg_temp_free_i32(twd); - tcg_temp_free(taddr); - } - break; - default: - MIPS_INVAL("MSA instruction"); - generate_exception_end(ctx, EXCP_RI); - break; - } - -} +#include "mod-msa_translate.c.inc" static void decode_opc(CPUMIPSState *env, DisasContext *ctx) { diff --git a/target/mips/mod-msa_translate.c.inc b/target/mips/mod-msa_translate.c.inc new file mode 100644 index 00000000000..ef2f0fea0d9 --- /dev/null +++ b/target/mips/mod-msa_translate.c.inc @@ -0,0 +1,2218 @@ +/* + * MIPS SIMD Architecture Module (MSA) translation routines + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F)) +enum { + OPC_MSA_I8_00 = 0x00 | OPC_MSA, + OPC_MSA_I8_01 = 0x01 | OPC_MSA, + OPC_MSA_I8_02 = 0x02 | OPC_MSA, + OPC_MSA_I5_06 = 0x06 | OPC_MSA, + OPC_MSA_I5_07 = 0x07 | OPC_MSA, + OPC_MSA_BIT_09 = 0x09 | OPC_MSA, + OPC_MSA_BIT_0A = 0x0A | OPC_MSA, + OPC_MSA_3R_0D = 0x0D | OPC_MSA, + OPC_MSA_3R_0E = 0x0E | OPC_MSA, + OPC_MSA_3R_0F = 0x0F | OPC_MSA, + OPC_MSA_3R_10 = 0x10 | OPC_MSA, + OPC_MSA_3R_11 = 0x11 | OPC_MSA, + OPC_MSA_3R_12 = 0x12 | OPC_MSA, + OPC_MSA_3R_13 = 0x13 | OPC_MSA, + OPC_MSA_3R_14 = 0x14 | OPC_MSA, + OPC_MSA_3R_15 = 0x15 | OPC_MSA, + OPC_MSA_ELM = 0x19 | OPC_MSA, + OPC_MSA_3RF_1A = 0x1A | OPC_MSA, + OPC_MSA_3RF_1B = 0x1B | OPC_MSA, + OPC_MSA_3RF_1C = 0x1C | OPC_MSA, + OPC_MSA_VEC = 0x1E | OPC_MSA, + + /* MI10 instruction */ + OPC_LD_B = (0x20) | OPC_MSA, + OPC_LD_H = (0x21) | OPC_MSA, + OPC_LD_W = (0x22) | OPC_MSA, + OPC_LD_D = (0x23) | OPC_MSA, + OPC_ST_B = (0x24) | OPC_MSA, + OPC_ST_H = (0x25) | OPC_MSA, + OPC_ST_W = (0x26) | OPC_MSA, + OPC_ST_D = (0x27) | OPC_MSA, +}; + +enum { + /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */ + OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06, + OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07, + OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06, + OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06, + OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07, + OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06, + OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07, + OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06, + OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07, + OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06, + OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07, + OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07, + + /* I8 instruction */ + OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00, + OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01, + OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02, + OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00, + OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01, + OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02, + OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00, + OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01, + OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02, + OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00, + + /* VEC/2R/2RF instruction */ + OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC, + OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC, + OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC, + OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC, + OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC, + OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC, + OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC, + + OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC, + OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC, + + /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */ + OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R, + OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R, + OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R, + OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R, + + /* 2RF instruction df(bit 16) = _w, _d */ + OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF, + OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF, + OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF, + OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF, + OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF, + OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF, + OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF, + OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF, + OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF, + OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF, + OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF, + OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF, + OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF, + OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF, + OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF, + OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF, + + /* 3R instruction df(bits 22..21) = _b, _h, _w, d */ + OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D, + OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E, + OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F, + OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10, + OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11, + OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12, + OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13, + OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14, + OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15, + OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D, + OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E, + OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10, + OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11, + OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12, + OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13, + OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14, + OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15, + OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D, + OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E, + OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F, + OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10, + OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11, + OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12, + OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13, + OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14, + OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15, + OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D, + OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E, + OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F, + OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10, + OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11, + OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13, + OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14, + OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D, + OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E, + OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F, + OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10, + OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11, + OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12, + OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13, + OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14, + OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15, + OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D, + OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E, + OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F, + OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10, + OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11, + OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12, + OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13, + OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14, + OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15, + OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D, + OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E, + OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10, + OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12, + OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14, + OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15, + OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D, + OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E, + OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10, + OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12, + OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14, + OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15, + + /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */ + OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM, + OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM, + OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM, + OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM, + OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM, + OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM, + OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM, + OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM, + OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM, + + /* 3RF instruction _df(bit 21) = _w, _d */ + OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A, + OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B, + OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A, + OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B, + OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C, + OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A, + OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B, + OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C, + OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A, + OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B, + OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C, + OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A, + OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B, + OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C, + OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A, + OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B, + OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C, + OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A, + OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C, + OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A, + OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B, + OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A, + OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B, + OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A, + OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C, + OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A, + OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B, + OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C, + OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A, + OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C, + OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A, + OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B, + OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C, + OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A, + OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B, + OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C, + OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A, + OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B, + OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C, + OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A, + OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B, + + /* BIT instruction df(bits 22..16) = _B _H _W _D */ + OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09, + OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A, + OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09, + OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A, + OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09, + OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A, + OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09, + OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A, + OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09, + OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09, + OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09, + OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09, +}; + +static const char * const msaregnames[] = { + "w0.d0", "w0.d1", "w1.d0", "w1.d1", + "w2.d0", "w2.d1", "w3.d0", "w3.d1", + "w4.d0", "w4.d1", "w5.d0", "w5.d1", + "w6.d0", "w6.d1", "w7.d0", "w7.d1", + "w8.d0", "w8.d1", "w9.d0", "w9.d1", + "w10.d0", "w10.d1", "w11.d0", "w11.d1", + "w12.d0", "w12.d1", "w13.d0", "w13.d1", + "w14.d0", "w14.d1", "w15.d0", "w15.d1", + "w16.d0", "w16.d1", "w17.d0", "w17.d1", + "w18.d0", "w18.d1", "w19.d0", "w19.d1", + "w20.d0", "w20.d1", "w21.d0", "w21.d1", + "w22.d0", "w22.d1", "w23.d0", "w23.d1", + "w24.d0", "w24.d1", "w25.d0", "w25.d1", + "w26.d0", "w26.d1", "w27.d0", "w27.d1", + "w28.d0", "w28.d1", "w29.d0", "w29.d1", + "w30.d0", "w30.d1", "w31.d0", "w31.d1", +}; + +static TCGv_i64 msa_wr_d[64]; + +static inline int check_msa_access(DisasContext *ctx) +{ + if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) && + !(ctx->hflags & MIPS_HFLAG_F64))) { + generate_exception_end(ctx, EXCP_RI); + return 0; + } + + if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) { + if (ctx->insn_flags & ASE_MSA) { + generate_exception_end(ctx, EXCP_MSADIS); + return 0; + } else { + generate_exception_end(ctx, EXCP_RI); + return 0; + } + } + return 1; +} + +static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt) +{ + /* generates tcg ops to check if any element is 0 */ + /* Note this function only works with MSA_WRLEN = 128 */ + uint64_t eval_zero_or_big = 0; + uint64_t eval_big = 0; + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + switch (df) { + case DF_BYTE: + eval_zero_or_big = 0x0101010101010101ULL; + eval_big = 0x8080808080808080ULL; + break; + case DF_HALF: + eval_zero_or_big = 0x0001000100010001ULL; + eval_big = 0x8000800080008000ULL; + break; + case DF_WORD: + eval_zero_or_big = 0x0000000100000001ULL; + eval_big = 0x8000000080000000ULL; + break; + case DF_DOUBLE: + eval_zero_or_big = 0x0000000000000001ULL; + eval_big = 0x8000000000000000ULL; + break; + } + tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big); + tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]); + tcg_gen_andi_i64(t0, t0, eval_big); + tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big); + tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]); + tcg_gen_andi_i64(t1, t1, eval_big); + tcg_gen_or_i64(t0, t0, t1); + /* if all bits are zero then all elements are not zero */ + /* if some bit is non-zero then some element is zero */ + tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0); + tcg_gen_trunc_i64_tl(tresult, t0); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); +} + +static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) +{ + uint8_t df = (ctx->opcode >> 21) & 0x3; + uint8_t wt = (ctx->opcode >> 16) & 0x1f; + int64_t s16 = (int16_t)ctx->opcode; + + check_msa_access(ctx); + + if (ctx->hflags & MIPS_HFLAG_BMASK) { + generate_exception_end(ctx, EXCP_RI); + return; + } + switch (op1) { + case OPC_BZ_V: + case OPC_BNZ_V: + { + TCGv_i64 t0 = tcg_temp_new_i64(); + tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]); + tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ? + TCG_COND_EQ : TCG_COND_NE, t0, t0, 0); + tcg_gen_trunc_i64_tl(bcond, t0); + tcg_temp_free_i64(t0); + } + break; + case OPC_BZ_B: + case OPC_BZ_H: + case OPC_BZ_W: + case OPC_BZ_D: + gen_check_zero_element(bcond, df, wt); + break; + case OPC_BNZ_B: + case OPC_BNZ_H: + case OPC_BNZ_W: + case OPC_BNZ_D: + gen_check_zero_element(bcond, df, wt); + tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0); + break; + } + + ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4; + + ctx->hflags |= MIPS_HFLAG_BC; + ctx->hflags |= MIPS_HFLAG_BDS32; +} + +static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24))) + uint8_t i8 = (ctx->opcode >> 16) & 0xff; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 ti8 = tcg_const_i32(i8); + + switch (MASK_MSA_I8(ctx->opcode)) { + case OPC_ANDI_B: + gen_helper_msa_andi_b(cpu_env, twd, tws, ti8); + break; + case OPC_ORI_B: + gen_helper_msa_ori_b(cpu_env, twd, tws, ti8); + break; + case OPC_NORI_B: + gen_helper_msa_nori_b(cpu_env, twd, tws, ti8); + break; + case OPC_XORI_B: + gen_helper_msa_xori_b(cpu_env, twd, tws, ti8); + break; + case OPC_BMNZI_B: + gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8); + break; + case OPC_BMZI_B: + gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8); + break; + case OPC_BSELI_B: + gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8); + break; + case OPC_SHF_B: + case OPC_SHF_H: + case OPC_SHF_W: + { + uint8_t df = (ctx->opcode >> 24) & 0x3; + if (df == DF_DOUBLE) { + generate_exception_end(ctx, EXCP_RI); + } else { + TCGv_i32 tdf = tcg_const_i32(df); + gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8); + tcg_temp_free_i32(tdf); + } + } + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(ti8); +} + +static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) + uint8_t df = (ctx->opcode >> 21) & 0x3; + int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5); + uint8_t u5 = (ctx->opcode >> 16) & 0x1f; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + + TCGv_i32 tdf = tcg_const_i32(df); + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 timm = tcg_temp_new_i32(); + tcg_gen_movi_i32(timm, u5); + + switch (MASK_MSA_I5(ctx->opcode)) { + case OPC_ADDVI_df: + gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_SUBVI_df: + gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_MAXI_S_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_MAXI_U_df: + gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_MINI_S_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_MINI_U_df: + gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CEQI_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CLTI_S_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CLTI_U_df: + gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CLEI_S_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CLEI_U_df: + gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_LDI_df: + { + int32_t s10 = sextract32(ctx->opcode, 11, 10); + tcg_gen_movi_i32(timm, s10); + gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm); + } + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(tdf); + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(timm); +} + +static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) + uint8_t dfm = (ctx->opcode >> 16) & 0x7f; + uint32_t df = 0, m = 0; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + + TCGv_i32 tdf; + TCGv_i32 tm; + TCGv_i32 twd; + TCGv_i32 tws; + + if ((dfm & 0x40) == 0x00) { + m = dfm & 0x3f; + df = DF_DOUBLE; + } else if ((dfm & 0x60) == 0x40) { + m = dfm & 0x1f; + df = DF_WORD; + } else if ((dfm & 0x70) == 0x60) { + m = dfm & 0x0f; + df = DF_HALF; + } else if ((dfm & 0x78) == 0x70) { + m = dfm & 0x7; + df = DF_BYTE; + } else { + generate_exception_end(ctx, EXCP_RI); + return; + } + + tdf = tcg_const_i32(df); + tm = tcg_const_i32(m); + twd = tcg_const_i32(wd); + tws = tcg_const_i32(ws); + + switch (MASK_MSA_BIT(ctx->opcode)) { + case OPC_SLLI_df: + gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SRAI_df: + gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SRLI_df: + gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BCLRI_df: + gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BSETI_df: + gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BNEGI_df: + gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BINSLI_df: + gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BINSRI_df: + gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SAT_S_df: + gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SAT_U_df: + gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SRARI_df: + gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SRLRI_df: + gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm); + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(tdf); + tcg_temp_free_i32(tm); + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); +} + +static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) + uint8_t df = (ctx->opcode >> 21) & 0x3; + uint8_t wt = (ctx->opcode >> 16) & 0x1f; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + + TCGv_i32 tdf = tcg_const_i32(df); + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 twt = tcg_const_i32(wt); + + switch (MASK_MSA_3R(ctx->opcode)) { + case OPC_BINSL_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_binsl_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_binsl_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_binsl_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_binsl_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_BINSR_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_binsr_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_binsr_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_binsr_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_binsr_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_BCLR_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_bclr_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_bclr_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_bclr_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_bclr_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_BNEG_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_bneg_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_bneg_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_bneg_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_bneg_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_BSET_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_bset_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_bset_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_bset_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_bset_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ADD_A_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_add_a_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_add_a_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_add_a_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_add_a_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ADDS_A_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ADDS_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ADDS_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ADDV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_addv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_addv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_addv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_addv_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_AVE_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_AVE_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_AVER_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_AVER_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CEQ_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ceq_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ceq_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ceq_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ceq_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CLE_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CLE_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CLT_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CLT_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DIV_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_div_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_div_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_div_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_div_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DIV_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_div_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_div_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_div_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_div_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MAX_A_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_max_a_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_max_a_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_max_a_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_max_a_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MAX_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_max_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_max_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_max_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_max_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MAX_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_max_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_max_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_max_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_max_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MIN_A_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_min_a_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_min_a_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_min_a_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_min_a_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MIN_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_min_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_min_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_min_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_min_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MIN_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_min_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_min_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_min_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_min_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MOD_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MOD_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MADDV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_maddv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_maddv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_maddv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_maddv_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MSUBV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_msubv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_msubv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_msubv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_msubv_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ASUB_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ASUB_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ILVEV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ILVOD_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ILVL_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_ILVR_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_PCKEV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_pckev_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_pckev_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_pckev_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_pckev_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_PCKOD_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_pckod_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_pckod_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_pckod_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_pckod_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SLL_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_sll_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_sll_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_sll_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_sll_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SRA_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_sra_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_sra_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_sra_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_sra_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SRAR_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_srar_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_srar_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_srar_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_srar_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SRL_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_srl_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_srl_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_srl_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_srl_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SRLR_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_srlr_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_srlr_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_srlr_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_srlr_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SUBS_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MULV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_mulv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_mulv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_mulv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_mulv_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SLD_df: + gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_VSHF_df: + gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_SUBV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_subv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subv_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SUBS_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SPLAT_df: + gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_SUBSUS_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_SUBSUU_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt); + break; + } + break; + + case OPC_DOTP_S_df: + case OPC_DOTP_U_df: + case OPC_DPADD_S_df: + case OPC_DPADD_U_df: + case OPC_DPSUB_S_df: + case OPC_HADD_S_df: + case OPC_DPSUB_U_df: + case OPC_HADD_U_df: + case OPC_HSUB_S_df: + case OPC_HSUB_U_df: + if (df == DF_BYTE) { + generate_exception_end(ctx, EXCP_RI); + break; + } + switch (MASK_MSA_3R(ctx->opcode)) { + case OPC_HADD_S_df: + switch (df) { + case DF_HALF: + gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_HADD_U_df: + switch (df) { + case DF_HALF: + gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_HSUB_S_df: + switch (df) { + case DF_HALF: + gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_HSUB_U_df: + switch (df) { + case DF_HALF: + gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DOTP_S_df: + switch (df) { + case DF_HALF: + gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DOTP_U_df: + switch (df) { + case DF_HALF: + gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DPADD_S_df: + switch (df) { + case DF_HALF: + gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DPADD_U_df: + switch (df) { + case DF_HALF: + gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DPSUB_S_df: + switch (df) { + case DF_HALF: + gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DPSUB_U_df: + switch (df) { + case DF_HALF: + gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt); + break; + } + break; + } + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(twt); + tcg_temp_free_i32(tdf); +} + +static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16))) + uint8_t source = (ctx->opcode >> 11) & 0x1f; + uint8_t dest = (ctx->opcode >> 6) & 0x1f; + TCGv telm = tcg_temp_new(); + TCGv_i32 tsr = tcg_const_i32(source); + TCGv_i32 tdt = tcg_const_i32(dest); + + switch (MASK_MSA_ELM_DF3E(ctx->opcode)) { + case OPC_CTCMSA: + gen_load_gpr(telm, source); + gen_helper_msa_ctcmsa(cpu_env, telm, tdt); + break; + case OPC_CFCMSA: + gen_helper_msa_cfcmsa(telm, cpu_env, tsr); + gen_store_gpr(telm, dest); + break; + case OPC_MOVE_V: + gen_helper_msa_move_v(cpu_env, tdt, tsr); + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free(telm); + tcg_temp_free_i32(tdt); + tcg_temp_free_i32(tsr); +} + +static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, + uint32_t n) +{ +#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22))) + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tn = tcg_const_i32(n); + TCGv_i32 tdf = tcg_const_i32(df); + + switch (MASK_MSA_ELM(ctx->opcode)) { + case OPC_SLDI_df: + gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn); + break; + case OPC_SPLATI_df: + gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn); + break; + case OPC_INSVE_df: + gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn); + break; + case OPC_COPY_S_df: + case OPC_COPY_U_df: + case OPC_INSERT_df: +#if !defined(TARGET_MIPS64) + /* Double format valid only for MIPS64 */ + if (df == DF_DOUBLE) { + generate_exception_end(ctx, EXCP_RI); + break; + } + if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) && + (df == DF_WORD)) { + generate_exception_end(ctx, EXCP_RI); + break; + } +#endif + switch (MASK_MSA_ELM(ctx->opcode)) { + case OPC_COPY_S_df: + if (likely(wd != 0)) { + switch (df) { + case DF_BYTE: + gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn); + break; + case DF_WORD: + gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_DOUBLE: + gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } + } + break; + case OPC_COPY_U_df: + if (likely(wd != 0)) { + switch (df) { + case DF_BYTE: + gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_WORD: + gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } + } + break; + case OPC_INSERT_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_insert_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_insert_h(cpu_env, twd, tws, tn); + break; + case DF_WORD: + gen_helper_msa_insert_w(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_DOUBLE: + gen_helper_msa_insert_d(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } + break; + } + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + } + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(tn); + tcg_temp_free_i32(tdf); +} + +static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx) +{ + uint8_t dfn = (ctx->opcode >> 16) & 0x3f; + uint32_t df = 0, n = 0; + + if ((dfn & 0x30) == 0x00) { + n = dfn & 0x0f; + df = DF_BYTE; + } else if ((dfn & 0x38) == 0x20) { + n = dfn & 0x07; + df = DF_HALF; + } else if ((dfn & 0x3c) == 0x30) { + n = dfn & 0x03; + df = DF_WORD; + } else if ((dfn & 0x3e) == 0x38) { + n = dfn & 0x01; + df = DF_DOUBLE; + } else if (dfn == 0x3E) { + /* CTCMSA, CFCMSA, MOVE.V */ + gen_msa_elm_3e(env, ctx); + return; + } else { + generate_exception_end(ctx, EXCP_RI); + return; + } + + gen_msa_elm_df(env, ctx, df, n); +} + +static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22))) + uint8_t df = (ctx->opcode >> 21) & 0x1; + uint8_t wt = (ctx->opcode >> 16) & 0x1f; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 twt = tcg_const_i32(wt); + TCGv_i32 tdf = tcg_temp_new_i32(); + + /* adjust df value for floating-point instruction */ + tcg_gen_movi_i32(tdf, df + 2); + + switch (MASK_MSA_3RF(ctx->opcode)) { + case OPC_FCAF_df: + gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FADD_df: + gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCUN_df: + gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSUB_df: + gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCOR_df: + gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCEQ_df: + gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FMUL_df: + gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCUNE_df: + gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCUEQ_df: + gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FDIV_df: + gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCNE_df: + gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCLT_df: + gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FMADD_df: + gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_MUL_Q_df: + tcg_gen_movi_i32(tdf, df + 1); + gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCULT_df: + gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FMSUB_df: + gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_MADD_Q_df: + tcg_gen_movi_i32(tdf, df + 1); + gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCLE_df: + gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_MSUB_Q_df: + tcg_gen_movi_i32(tdf, df + 1); + gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FCULE_df: + gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FEXP2_df: + gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSAF_df: + gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FEXDO_df: + gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSUN_df: + gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSOR_df: + gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSEQ_df: + gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FTQ_df: + gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSUNE_df: + gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSUEQ_df: + gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSNE_df: + gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSLT_df: + gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FMIN_df: + gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_MULR_Q_df: + tcg_gen_movi_i32(tdf, df + 1); + gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSULT_df: + gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FMIN_A_df: + gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_MADDR_Q_df: + tcg_gen_movi_i32(tdf, df + 1); + gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSLE_df: + gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FMAX_df: + gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_MSUBR_Q_df: + tcg_gen_movi_i32(tdf, df + 1); + gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FSULE_df: + gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt); + break; + case OPC_FMAX_A_df: + gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt); + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(twt); + tcg_temp_free_i32(tdf); +} + +static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \ + (op & (0x7 << 18))) + uint8_t wt = (ctx->opcode >> 16) & 0x1f; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + uint8_t df = (ctx->opcode >> 16) & 0x3; + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 twt = tcg_const_i32(wt); + TCGv_i32 tdf = tcg_const_i32(df); + + switch (MASK_MSA_2R(ctx->opcode)) { + case OPC_FILL_df: +#if !defined(TARGET_MIPS64) + /* Double format valid only for MIPS64 */ + if (df == DF_DOUBLE) { + generate_exception_end(ctx, EXCP_RI); + break; + } +#endif + gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */ + break; + case OPC_NLOC_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_nloc_b(cpu_env, twd, tws); + break; + case DF_HALF: + gen_helper_msa_nloc_h(cpu_env, twd, tws); + break; + case DF_WORD: + gen_helper_msa_nloc_w(cpu_env, twd, tws); + break; + case DF_DOUBLE: + gen_helper_msa_nloc_d(cpu_env, twd, tws); + break; + } + break; + case OPC_NLZC_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_nlzc_b(cpu_env, twd, tws); + break; + case DF_HALF: + gen_helper_msa_nlzc_h(cpu_env, twd, tws); + break; + case DF_WORD: + gen_helper_msa_nlzc_w(cpu_env, twd, tws); + break; + case DF_DOUBLE: + gen_helper_msa_nlzc_d(cpu_env, twd, tws); + break; + } + break; + case OPC_PCNT_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_pcnt_b(cpu_env, twd, tws); + break; + case DF_HALF: + gen_helper_msa_pcnt_h(cpu_env, twd, tws); + break; + case DF_WORD: + gen_helper_msa_pcnt_w(cpu_env, twd, tws); + break; + case DF_DOUBLE: + gen_helper_msa_pcnt_d(cpu_env, twd, tws); + break; + } + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(twt); + tcg_temp_free_i32(tdf); +} + +static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \ + (op & (0xf << 17))) + uint8_t wt = (ctx->opcode >> 16) & 0x1f; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + uint8_t df = (ctx->opcode >> 16) & 0x1; + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 twt = tcg_const_i32(wt); + /* adjust df value for floating-point instruction */ + TCGv_i32 tdf = tcg_const_i32(df + 2); + + switch (MASK_MSA_2RF(ctx->opcode)) { + case OPC_FCLASS_df: + gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws); + break; + case OPC_FTRUNC_S_df: + gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws); + break; + case OPC_FTRUNC_U_df: + gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws); + break; + case OPC_FSQRT_df: + gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws); + break; + case OPC_FRSQRT_df: + gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws); + break; + case OPC_FRCP_df: + gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws); + break; + case OPC_FRINT_df: + gen_helper_msa_frint_df(cpu_env, tdf, twd, tws); + break; + case OPC_FLOG2_df: + gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws); + break; + case OPC_FEXUPL_df: + gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws); + break; + case OPC_FEXUPR_df: + gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws); + break; + case OPC_FFQL_df: + gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws); + break; + case OPC_FFQR_df: + gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws); + break; + case OPC_FTINT_S_df: + gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws); + break; + case OPC_FTINT_U_df: + gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws); + break; + case OPC_FFINT_S_df: + gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws); + break; + case OPC_FFINT_U_df: + gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws); + break; + } + + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(twt); + tcg_temp_free_i32(tdf); +} + +static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21))) + uint8_t wt = (ctx->opcode >> 16) & 0x1f; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 twt = tcg_const_i32(wt); + + switch (MASK_MSA_VEC(ctx->opcode)) { + case OPC_AND_V: + gen_helper_msa_and_v(cpu_env, twd, tws, twt); + break; + case OPC_OR_V: + gen_helper_msa_or_v(cpu_env, twd, tws, twt); + break; + case OPC_NOR_V: + gen_helper_msa_nor_v(cpu_env, twd, tws, twt); + break; + case OPC_XOR_V: + gen_helper_msa_xor_v(cpu_env, twd, tws, twt); + break; + case OPC_BMNZ_V: + gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt); + break; + case OPC_BMZ_V: + gen_helper_msa_bmz_v(cpu_env, twd, tws, twt); + break; + case OPC_BSEL_V: + gen_helper_msa_bsel_v(cpu_env, twd, tws, twt); + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(twt); +} + +static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx) +{ + switch (MASK_MSA_VEC(ctx->opcode)) { + case OPC_AND_V: + case OPC_OR_V: + case OPC_NOR_V: + case OPC_XOR_V: + case OPC_BMNZ_V: + case OPC_BMZ_V: + case OPC_BSEL_V: + gen_msa_vec_v(env, ctx); + break; + case OPC_MSA_2R: + gen_msa_2r(env, ctx); + break; + case OPC_MSA_2RF: + gen_msa_2rf(env, ctx); + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +static void gen_msa(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = ctx->opcode; + check_insn(ctx, ASE_MSA); + check_msa_access(ctx); + + switch (MASK_MSA_MINOR(opcode)) { + case OPC_MSA_I8_00: + case OPC_MSA_I8_01: + case OPC_MSA_I8_02: + gen_msa_i8(env, ctx); + break; + case OPC_MSA_I5_06: + case OPC_MSA_I5_07: + gen_msa_i5(env, ctx); + break; + case OPC_MSA_BIT_09: + case OPC_MSA_BIT_0A: + gen_msa_bit(env, ctx); + break; + case OPC_MSA_3R_0D: + case OPC_MSA_3R_0E: + case OPC_MSA_3R_0F: + case OPC_MSA_3R_10: + case OPC_MSA_3R_11: + case OPC_MSA_3R_12: + case OPC_MSA_3R_13: + case OPC_MSA_3R_14: + case OPC_MSA_3R_15: + gen_msa_3r(env, ctx); + break; + case OPC_MSA_ELM: + gen_msa_elm(env, ctx); + break; + case OPC_MSA_3RF_1A: + case OPC_MSA_3RF_1B: + case OPC_MSA_3RF_1C: + gen_msa_3rf(env, ctx); + break; + case OPC_MSA_VEC: + gen_msa_vec(env, ctx); + break; + case OPC_LD_B: + case OPC_LD_H: + case OPC_LD_W: + case OPC_LD_D: + case OPC_ST_B: + case OPC_ST_H: + case OPC_ST_W: + case OPC_ST_D: + { + int32_t s10 = sextract32(ctx->opcode, 16, 10); + uint8_t rs = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + uint8_t df = (ctx->opcode >> 0) & 0x3; + + TCGv_i32 twd = tcg_const_i32(wd); + TCGv taddr = tcg_temp_new(); + gen_base_offset_addr(ctx, taddr, rs, s10 << df); + + switch (MASK_MSA_MINOR(opcode)) { + case OPC_LD_B: + gen_helper_msa_ld_b(cpu_env, twd, taddr); + break; + case OPC_LD_H: + gen_helper_msa_ld_h(cpu_env, twd, taddr); + break; + case OPC_LD_W: + gen_helper_msa_ld_w(cpu_env, twd, taddr); + break; + case OPC_LD_D: + gen_helper_msa_ld_d(cpu_env, twd, taddr); + break; + case OPC_ST_B: + gen_helper_msa_st_b(cpu_env, twd, taddr); + break; + case OPC_ST_H: + gen_helper_msa_st_h(cpu_env, twd, taddr); + break; + case OPC_ST_W: + gen_helper_msa_st_w(cpu_env, twd, taddr); + break; + case OPC_ST_D: + gen_helper_msa_st_d(cpu_env, twd, taddr); + break; + } + + tcg_temp_free_i32(twd); + tcg_temp_free(taddr); + } + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} From patchwork Mon Nov 23 20:44:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926755 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 034EEC2D0E4 for ; Mon, 23 Nov 2020 21:04:34 +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 192FD206B5 for ; Mon, 23 Nov 2020 21:04:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="k0RollmF" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 192FD206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:46786 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ0h-0002p6-T2 for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:04:31 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46496) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIiG-0001C2-TC for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:28 -0500 Received: from mail-wr1-x434.google.com ([2a00:1450:4864:20::434]:42019) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIiF-0001Nu-5T for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:28 -0500 Received: by mail-wr1-x434.google.com with SMTP id l1so20093930wrb.9 for ; Mon, 23 Nov 2020 12:45:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=euDk/VwCIM7OUksohionL4dhEPJJf8PLdnfc9cMimOk=; b=k0RollmFNFEcMFYAgQDmxERkdTFH3EWECJ1gz3QSQiNXxHEUZuunbi8sc/kVnOWGoI YQZuoVSY4v6mY8hqqQU2IZdKsREpwT+YYTMgRiu8jxWeQzG2JVmme3ylUiLaQuNWotbb HoMMyQebOhlKpO5AmmsYc40qyoYsO2gs4i501iJ7Fqrg4o4Vb6fGHa8xZl0G5uLIs+9G 1G7rySqOD8O76Dzm1LHrD0KqoOdkySQo5+yp5NDy0o+eJKj4aMtXdbjZR0MRJvY8diLo 78Wk7r6A3IBJbKbFeR2is+LOzx4YG7pdnqm7xVDpjJ1LAuC0HOmpXXjZypWQ3SZo0vTF ZTNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=euDk/VwCIM7OUksohionL4dhEPJJf8PLdnfc9cMimOk=; b=Xgzm6OPCYHd218DztfPX/eARwASsX1uVHo5hZ+OpsuwhDbbGVUC+IPYlopprl0Sc/L 8KzdZB9UVR9Dx9EnbsCmz1xnp2BoitqEgcwz05pJ1t5k7oP/7gDKMUNqXjFxd+ZHN+xY DtzZ8T/JPtHcjOVpQhE22gRlJssPRe2ahzyfLBEdSjVN/EtIyeuYPty4G7S3DwN60Fwa ULb8sFI8uM8cjUoqjZWw9oH81fH8f4/1k8tGkRE2aV/TZlNkvBd+DN5XkVL5/B5A/jod FvOVl7P2JbcvPqsJlDMynZ2xaYAcEiBPoUA03qaoie+yDK1PxEuSkV6vjx/0kLXjmsmQ 8sRg== X-Gm-Message-State: AOAM532MbawNjNBfO3qSLRXaciJFFoi13sPQs8D4ZZIJJ7v9BwFcxdY1 s23NqPQD/5EvpUMUQwqn567X3rXNoEE= X-Google-Smtp-Source: ABdhPJzu8PfIM6P4hMxgBXKaAlw9mEbkVxncg0bysjEiLGFJlqIFow+OWtPZJJHuuEJM6CkLVWrYiw== X-Received: by 2002:adf:eeca:: with SMTP id a10mr1500876wrp.186.1606164325553; Mon, 23 Nov 2020 12:45:25 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id f2sm23173317wre.63.2020.11.23.12.45.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:24 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 07/28] target/mips: Rename dsp_helper.c as mod-dsp_helper.c Date: Mon, 23 Nov 2020 21:44:27 +0100 Message-Id: <20201123204448.3260804-8-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::434; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x434.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 'MIPS DSP' is defined as a Module by MIPS, rename it as mod-dsp_helper.c. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201120210844.2625602-6-f4bug@amsat.org> --- target/mips/{dsp_helper.c => mod-dsp_helper.c} | 2 ++ target/mips/meson.build | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) rename target/mips/{dsp_helper.c => mod-dsp_helper.c} (99%) diff --git a/target/mips/dsp_helper.c b/target/mips/mod-dsp_helper.c similarity index 99% rename from target/mips/dsp_helper.c rename to target/mips/mod-dsp_helper.c index 09b6e5fb15a..10a965bd20d 100644 --- a/target/mips/dsp_helper.c +++ b/target/mips/mod-dsp_helper.c @@ -15,6 +15,8 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "qemu/osdep.h" diff --git a/target/mips/meson.build b/target/mips/meson.build index 35dbbbf6519..aa6ac67df76 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -1,12 +1,12 @@ mips_ss = ss.source_set() mips_ss.add(files( 'cpu.c', - 'dsp_helper.c', 'fpu_helper.c', 'gdbstub.c', 'helper.c', 'lmmi_helper.c', 'op_helper.c', + 'mod-dsp_helper.c', 'mod-msa_helper.c', 'translate.c', From patchwork Mon Nov 23 20:44:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926763 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 C934DC388F9 for ; Mon, 23 Nov 2020 21:08:26 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2725A206B5 for ; Mon, 23 Nov 2020 21:08:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nFeQN6Fs" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2725A206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:54824 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ4T-0006OX-4a for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:08:25 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46534) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIiN-0001MC-LF for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:35 -0500 Received: from mail-wr1-x42f.google.com ([2a00:1450:4864:20::42f]:36542) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIiK-0001PL-AV for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:35 -0500 Received: by mail-wr1-x42f.google.com with SMTP id z7so4294693wrn.3 for ; Mon, 23 Nov 2020 12:45:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+EqN5qDxtEBBzxLbgFeRkbW2j1iqK+UGwCfiEIja96k=; b=nFeQN6FsFha/SIFSYi+ZlCJIZF1+t3aitAuTqX/vVsmwZkWA9eE8TZH0JvBIKMR9du g/21ggfPC4xLe3wTWXXqV4hOyhY9Isk3ZKYMh+cS7vQPxjnuJqBT6q6JwsvDwuBZDuCi RckYysA96yAfXeGbQikZfguvGwPy94zzta0BOLZIwW+Znp3LvnNbxGAY7BrlTX04zcQa zpL5MwAf4Mr1+UjKgzziKTbUevgmzqJ4riX5U31aQ+YwVftTkjIUtG1L8J7FLItDIz6P Yhyk+QhNdt/sl3XtyYqTaIah3BarrAYhFN/l+JTRs3m8HQXBEXtA17F5PKP8onKadcKa NFPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=+EqN5qDxtEBBzxLbgFeRkbW2j1iqK+UGwCfiEIja96k=; b=OjTrmnJKR4UDaybAquMgfaQBMyRJf2pLofmRYYR8ZhyKv1P7ucykaOgZMubQcDKYwb KCP6MMTBo7/ikLdc3fU5//7OTHXCSv/6Z8cPymr4Rr+Id0NuGcZnBNVo/R/uw9jPA6tS sH9ZTccCrAZDt+5CI/fVNWZ5xdrGo2cUV7j9pdH5y2RS80ubjOPDQ4GuV7DGyHhqf0wn FTbukiJ/A0bzhjGfghl1BxGzbB9vTs8G6Ggz7Posfhk4BvitUDW87OpHt60xyYtp/I1W f1pGEODfG5rzWSoKPKfK3YzKwVMzE0cA1saphgNAyxiIaS/PCe6N0qhSawsJEKyYh+x1 UOBQ== X-Gm-Message-State: AOAM531crRYIEd9L0k6fiw7snQs4TCiHfGx6AAKs3i9UGxDTRETE59Ny Crh1PVNLtEE6Kre4tPEG+9VwfrXhaYg= X-Google-Smtp-Source: ABdhPJySoOjCRzKwThpBCis/FwKVKFLuOYpqBuTqxzyxjOJluknwIYJStjvW4CNP3Z+pkXIOPDstrQ== X-Received: by 2002:adf:9b98:: with SMTP id d24mr1494737wrc.17.1606164330374; Mon, 23 Nov 2020 12:45:30 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id d134sm879570wmd.8.2020.11.23.12.45.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:29 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 08/28] target/mips: Extract DSP helper definitions Date: Mon, 23 Nov 2020 21:44:28 +0100 Message-Id: <20201123204448.3260804-9-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::42f; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x42f.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 'MIPS DSP' is defined as a Module by MIPS. Extract the helper definitions to 'mod-dsp_helper.h.inc'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-7-f4bug@amsat.org> --- target/mips/helper.h | 335 +----------------------------- target/mips/mod-dsp_helper.h.inc | 344 +++++++++++++++++++++++++++++++ 2 files changed, 345 insertions(+), 334 deletions(-) create mode 100644 target/mips/mod-dsp_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index 80eb675fa64..82f40c3b9bc 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -447,340 +447,7 @@ DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) -/*** MIPS DSP ***/ -/* DSP Arithmetic Sub-class insns */ -DEF_HELPER_FLAGS_3(addq_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(addq_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(addq_pw, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(addu_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(addu_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(addu_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(addu_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(subq_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(subq_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(subq_pw, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(subu_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(subu_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(subu_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(subu_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(addsc, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addwc, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(modsub, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_NO_RWG_SE, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_NO_RWG_SE, tl, tl) -#endif -DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, tl, env) -DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, tl, env) -DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, tl, env) -DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, tl, env) -DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, tl, env) -#endif -DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_NO_RWG_SE, - tl, i32, tl, tl) -DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_NO_RWG_SE, - tl, i32, tl, tl) -DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(precr_sra_qh_pw, - TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) -DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw, - TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) -DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(precrq_qh_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(precrq_rs_qh_pw, - TCG_CALL_NO_RWG_SE, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(precrq_pw_l, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#endif -DEF_HELPER_FLAGS_3(precrqu_s_qb_ph, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(precrqu_s_ob_qh, - TCG_CALL_NO_RWG_SE, tl, tl, tl, env) - -DEF_HELPER_FLAGS_1(preceq_pw_qhl, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceq_pw_qhr, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceq_pw_qhla, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceq_pw_qhra, TCG_CALL_NO_RWG_SE, tl, tl) -#endif -DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_1(precequ_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(precequ_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(precequ_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(precequ_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl) -#endif -DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_1(preceu_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceu_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl) -#endif - -/* DSP GPR-Based Shift Sub-class insns */ -DEF_HELPER_FLAGS_3(shll_qb, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(shll_ob, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(shll_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(shll_s_ph, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(shll_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(shll_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(shll_s_w, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(shll_pw, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(shll_s_pw, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_2(shrl_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shrl_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#endif -DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shra_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_2(shra_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shra_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#endif -DEF_HELPER_FLAGS_2(shra_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shra_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shra_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_2(shra_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shra_r_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shra_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#endif - -/* DSP Multiply Sub-class insns */ -DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, tl, tl, i32, env) -#endif -DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, i32, tl, tl, env) -DEF_HELPER_FLAGS_3(mul_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, i32, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(dmadd, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(dmaddu, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env) -DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env) -#endif - -/* DSP Bit/Manipulation Sub-class insns */ -DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl) -#endif - -/* DSP Compare-Pick Sub-class insns */ -DEF_HELPER_FLAGS_3(cmpu_eq_qb, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(cmp_eq_ph, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(cmpgu_eq_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(cmpgu_lt_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(cmpgu_le_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(cmp_eq_qh, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(pick_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(pick_ph, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#endif - -/* DSP Accumulator and DSPControl Access Sub-class insns */ -DEF_HELPER_FLAGS_3(extr_w, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(dextr_w, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(dextr_l, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(extp, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(extpdp, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(dextp, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(dextpdp, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(shilo, 0, void, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(dshilo, 0, void, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(mthlip, 0, void, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) -DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) - DEF_HELPER_3(cache, void, env, tl, i32) +#include "mod-dsp_helper.h.inc" #include "mod-msa_helper.h.inc" diff --git a/target/mips/mod-dsp_helper.h.inc b/target/mips/mod-dsp_helper.h.inc new file mode 100644 index 00000000000..83f188a697e --- /dev/null +++ b/target/mips/mod-dsp_helper.h.inc @@ -0,0 +1,344 @@ +/* + * MIPS ASE DSP instruction emulation helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* DSP Arithmetic Sub-class insns */ +DEF_HELPER_FLAGS_3(addq_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(addq_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(addq_pw, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(addu_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(addu_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(addu_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(addu_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(subq_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(subq_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(subq_pw, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(subu_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(subu_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(subu_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(subu_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(addsc, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addwc, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(modsub, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_NO_RWG_SE, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_NO_RWG_SE, tl, tl) +#endif +DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, tl, env) +DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, tl, env) +DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, tl, env) +DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, tl, env) +DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, tl, env) +#endif +DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_NO_RWG_SE, + tl, i32, tl, tl) +DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_NO_RWG_SE, + tl, i32, tl, tl) +DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(precr_sra_qh_pw, + TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw, + TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(precrq_qh_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(precrq_rs_qh_pw, + TCG_CALL_NO_RWG_SE, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(precrq_pw_l, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif +DEF_HELPER_FLAGS_3(precrqu_s_qb_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(precrqu_s_ob_qh, + TCG_CALL_NO_RWG_SE, tl, tl, tl, env) + +DEF_HELPER_FLAGS_1(preceq_pw_qhl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceq_pw_qhr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceq_pw_qhla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceq_pw_qhra, TCG_CALL_NO_RWG_SE, tl, tl) +#endif +DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_1(precequ_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl) +#endif +DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_1(preceu_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl) +#endif + +/* DSP GPR-Based Shift Sub-class insns */ +DEF_HELPER_FLAGS_3(shll_qb, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(shll_ob, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(shll_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(shll_s_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(shll_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(shll_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(shll_s_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(shll_pw, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(shll_s_pw, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(shrl_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shrl_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif +DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(shra_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif +DEF_HELPER_FLAGS_2(shra_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(shra_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif + +/* DSP Multiply Sub-class insns */ +DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_3(mul_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dmadd, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dmaddu, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env) +#endif + +/* DSP Bit/Manipulation Sub-class insns */ +DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl) +#endif + +/* DSP Compare-Pick Sub-class insns */ +DEF_HELPER_FLAGS_3(cmpu_eq_qb, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(cmp_eq_ph, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(cmpgu_eq_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(cmpgu_lt_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(cmpgu_le_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(cmp_eq_qh, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(pick_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(pick_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif + +/* DSP Accumulator and DSPControl Access Sub-class insns */ +DEF_HELPER_FLAGS_3(extr_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dextr_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_l, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(extp, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(extpdp, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dextp, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextpdp, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(shilo, 0, void, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dshilo, 0, void, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(mthlip, 0, void, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) From patchwork Mon Nov 23 20:44:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926751 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 BB649C2D0E4 for ; Mon, 23 Nov 2020 21:01:21 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D2607206D5 for ; Mon, 23 Nov 2020 21:01:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="LBzPkAY3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D2607206D5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:39320 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khIxZ-0007zr-Tc for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:01:17 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46572) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIiU-0001Xp-Gr for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:42 -0500 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]:55164) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIiQ-0001Rg-86 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:42 -0500 Received: by mail-wm1-x32d.google.com with SMTP id d142so602144wmd.4 for ; Mon, 23 Nov 2020 12:45:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AyaRjSFV8oLCfj1+p3YaEW83pkx/QYtJCkxG9FO47+U=; b=LBzPkAY3ECbDp5V3j9xF0p3GCMJVrp55NVMPXexLv4lLEsNhgL7AnGJgLL1yR7vQnr TZHqV/ooCqS5NTBzPkClS/66aM6ZZjvJW8K3zkmOWPFZlKqDcVkhmWsf1T8kJRHXuSAL EP9lhVpOyTvjtiOvmfuQmgAD7hZ+BGQ4FsDaI9UhRLOklEFlHcPzhzLnFwEzWNaOQXEq JiM1Ozu4rW9gdm7g2CsEFfmcTow8y6BgMAMvE+55EpKYICW8O5URNaAq0spmIVLILtC8 TdChTSEAif+caYm7P1Ei76HtfLgCLazHv++48TOBNrtGHlPLsps9+BDa8mqcElxOkKpC cA9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=AyaRjSFV8oLCfj1+p3YaEW83pkx/QYtJCkxG9FO47+U=; b=UfLXMqWCFxWNcxJWe92tM/ElcHP4nDpLTIGzE5u2lJn62EmYzT6+Uck7F2wCBHxO1a eaXMCKbvRkxADe2KhCbPacrhaQD5ymiaJkJeqjFo16iRMZRrx5mrdNxsARyMRLRAmly6 jkLmJCHYjOVzogG0DJTopSkOTG2Re6VNvnEPYJllMyYKGX5XgQRXXpy54qAhHDg3Qc7c uPBKNSSHijDVRz0BuHeSj5jksE4CDcJdiQ/WFmJRCwiAck1/0VKDFANS/xU+Ca9njZHm rG5XzxPTsxCnQ4zSQs0bwEigCZakVgPh5u459V1S9OAETdSRQ+vj2jDf59avAchYCsag 9Q3Q== X-Gm-Message-State: AOAM530EXG+NLLJ6waVmDRuMvfBooWC9KOW7j/jrjiCxx5qmxAcAH9XR +xNPdu31nCb7Is5QjHn6loVQwKjoIjs= X-Google-Smtp-Source: ABdhPJxVOPI/Pesu30fVsrGbqS5OEg3DWzdXZKTieUZCqSINYg3qgWHa/yMPyZ5p1/p4DNzPoC5LsQ== X-Received: by 2002:a1c:6306:: with SMTP id x6mr753483wmb.154.1606164335478; Mon, 23 Nov 2020 12:45:35 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id q12sm20740928wrx.86.2020.11.23.12.45.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:34 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 09/28] target/mips: Extract DSP translation routines Date: Mon, 23 Nov 2020 21:44:29 +0100 Message-Id: <20201123204448.3260804-10-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32d; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x32d.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract 2150 lines from the huge translate.c to a new file, 'mod-dsp_translate.c.inc'. As there are too many inter- dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201120210844.2625602-8-f4bug@amsat.org> --- target/mips/translate.c | 2150 +------------------------- target/mips/mod-dsp_translate.c.inc | 2158 +++++++++++++++++++++++++++ 2 files changed, 2162 insertions(+), 2146 deletions(-) create mode 100644 target/mips/mod-dsp_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index e174bf778e6..d1e154b1f79 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -405,35 +405,6 @@ enum { OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3, OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3, - /* MIPS DSP Load */ - OPC_LX_DSP = 0x0A | OPC_SPECIAL3, - /* MIPS DSP Arithmetic */ - OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3, - OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3, - OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3, - OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3, - /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */ - /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */ - OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3, - OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3, - /* MIPS DSP GPR-Based Shift Sub-class */ - OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3, - OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3, - /* MIPS DSP Multiply Sub-class insns */ - /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */ - /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */ - OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3, - OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3, - /* DSP Bit/Manipulation Sub-class */ - OPC_INSV_DSP = 0x0C | OPC_SPECIAL3, - OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3, - /* MIPS DSP Append Sub-class */ - OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3, - OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3, - /* MIPS DSP Accumulator and DSPControl Access Sub-class */ - OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3, - OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3, - /* EVA */ OPC_LWLE = 0x19 | OPC_SPECIAL3, OPC_LWRE = 0x1A | OPC_SPECIAL3, @@ -540,407 +511,6 @@ enum { OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM, }; -#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -/* MIPS DSP Load */ -enum { - OPC_LBUX = (0x06 << 6) | OPC_LX_DSP, - OPC_LHX = (0x04 << 6) | OPC_LX_DSP, - OPC_LWX = (0x00 << 6) | OPC_LX_DSP, - OPC_LDX = (0x08 << 6) | OPC_LX_DSP, -}; - -#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Arithmetic Sub-class */ - OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP, - OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP, - OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP, - OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP, - OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP, - OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP, - OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP, - OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP, - OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP, - OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP, - OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP, - OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP, - OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP, - OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP, - OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP, - OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP, - OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP, - OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP, - /* MIPS DSP Multiply Sub-class insns */ - OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP, - OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP, - OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP, - OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP, - OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP, - OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP, -}; - -#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E -#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Arithmetic Sub-class */ - OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP, - OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP, - OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP, - OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP, - OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP, - OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP, - OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP, - OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP, - OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP, - OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP, - OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP, - OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP, - /* MIPS DSP Multiply Sub-class insns */ - OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP, - OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP, - OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP, - OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP, -}; - -#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Arithmetic Sub-class */ - OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP, - OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP, - /* DSP Bit/Manipulation Sub-class */ - OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP, - OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP, - OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP, - OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP, -}; - -#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Arithmetic Sub-class */ - OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP, - /* DSP Compare-Pick Sub-class */ - OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP, - OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP, -}; - -#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP GPR-Based Shift Sub-class */ - OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP, - OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP, - OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP, - OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP, - OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP, - OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP, - OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP, - OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP, - OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP, - OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP, - OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP, - OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP, - OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP, -}; - -#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Multiply Sub-class insns */ - OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP, - OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP, - OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP, - OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP, - OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP, - OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP, - OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP, - OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP, - OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP, - OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP, - OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP, - OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP, -}; - -#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* DSP Bit/Manipulation Sub-class */ - OPC_INSV = (0x00 << 6) | OPC_INSV_DSP, -}; - -#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Append Sub-class */ - OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP, - OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP, - OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP, -}; - -#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Accumulator and DSPControl Access Sub-class */ - OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP, - OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP, - OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP, - OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP, - OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP, - OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP, - OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP, - OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP, - OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP, - OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP, - OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP, - OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP, - OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP, - OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP, - OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP, - OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP, - OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP, -}; - -#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Arithmetic Sub-class */ - OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP, - OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP, - OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP, - /* DSP Bit/Manipulation Sub-class */ - OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP, - OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP, - OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP, -}; - -#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Multiply Sub-class insns */ - OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP, - OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP, - OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP, - OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP, - OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP, - /* MIPS DSP Arithmetic Sub-class */ - OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP, - OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP, - OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP, - OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP, - OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP, - OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP, - OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP, - OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP, - OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP, - OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP, - OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP, - OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP, - OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP, - OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP, - OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP, - OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP, - OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP, - OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP, - OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP, - OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP, - OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP, -}; - -#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* DSP Compare-Pick Sub-class */ - OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP, - /* MIPS DSP Arithmetic Sub-class */ - OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP, - OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP, -}; - -#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* DSP Append Sub-class */ - OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP, - OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP, - OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP, - OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP, -}; - -#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Accumulator and DSPControl Access Sub-class */ - OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP, - OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP, - OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP, - OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP, -}; - -#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* DSP Bit/Manipulation Sub-class */ - OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP, -}; - -#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP Multiply Sub-class insns */ - OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP, - OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP, - OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP, -}; - -#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) -enum { - /* MIPS DSP GPR-Based Shift Sub-class */ - OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP, - OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP, - OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP, - OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP, - OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP, - OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP, - OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP, - OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP, - OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP, - OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP, - OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP, - OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP, - OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP, - OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP, - OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP, - OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP, -}; - /* Coprocessor 0 (rs field) */ #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21))) @@ -2759,42 +2329,9 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs) } } -/* - * Verify that the processor is running with DSP instructions enabled. - * This is enabled by CP0 Status register MX(24) bit. - */ -static inline void check_dsp(DisasContext *ctx) -{ - if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) { - if (ctx->insn_flags & ASE_DSP) { - generate_exception_end(ctx, EXCP_DSPDIS); - } else { - generate_exception_end(ctx, EXCP_RI); - } - } -} - -static inline void check_dsp_r2(DisasContext *ctx) -{ - if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) { - if (ctx->insn_flags & ASE_DSP) { - generate_exception_end(ctx, EXCP_DSPDIS); - } else { - generate_exception_end(ctx, EXCP_RI); - } - } -} - -static inline void check_dsp_r3(DisasContext *ctx) -{ - if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) { - if (ctx->insn_flags & ASE_DSP) { - generate_exception_end(ctx, EXCP_DSPDIS); - } else { - generate_exception_end(ctx, EXCP_RI); - } - } -} +static inline void check_dsp(DisasContext *ctx); +static inline void check_dsp_r2(DisasContext *ctx); +static inline void check_dsp_r3(DisasContext *ctx); /* * This code generates a "reserved instruction" exception if the @@ -22785,1686 +22322,7 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) #endif -/* MIPSDSP functions. */ -static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc, - int rd, int base, int offset) -{ - TCGv t0; - - check_dsp(ctx); - t0 = tcg_temp_new(); - - if (base == 0) { - gen_load_gpr(t0, offset); - } else if (offset == 0) { - gen_load_gpr(t0, base); - } else { - gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]); - } - - switch (opc) { - case OPC_LBUX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB); - gen_store_gpr(t0, rd); - break; - case OPC_LHX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW); - gen_store_gpr(t0, rd); - break; - case OPC_LWX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL); - gen_store_gpr(t0, rd); - break; -#if defined(TARGET_MIPS64) - case OPC_LDX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); - gen_store_gpr(t0, rd); - break; -#endif - } - tcg_temp_free(t0); -} - -static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2, - int ret, int v1, int v2) -{ - TCGv v1_t; - TCGv v2_t; - - if (ret == 0) { - /* Treat as NOP. */ - return; - } - - v1_t = tcg_temp_new(); - v2_t = tcg_temp_new(); - - gen_load_gpr(v1_t, v1); - gen_load_gpr(v2_t, v2); - - switch (op1) { - /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */ - case OPC_MULT_G_2E: - check_dsp_r2(ctx); - switch (op2) { - case OPC_ADDUH_QB: - gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_ADDUH_R_QB: - gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_ADDQH_PH: - gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_ADDQH_R_PH: - gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_ADDQH_W: - gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_ADDQH_R_W: - gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SUBUH_QB: - gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SUBUH_R_QB: - gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SUBQH_PH: - gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SUBQH_R_PH: - gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SUBQH_W: - gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SUBQH_R_W: - gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t); - break; - } - break; - case OPC_ABSQ_S_PH_DSP: - switch (op2) { - case OPC_ABSQ_S_QB: - check_dsp_r2(ctx); - gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env); - break; - case OPC_ABSQ_S_PH: - check_dsp(ctx); - gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env); - break; - case OPC_ABSQ_S_W: - check_dsp(ctx); - gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env); - break; - case OPC_PRECEQ_W_PHL: - check_dsp(ctx); - tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000); - tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); - break; - case OPC_PRECEQ_W_PHR: - check_dsp(ctx); - tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF); - tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16); - tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); - break; - case OPC_PRECEQU_PH_QBL: - check_dsp(ctx); - gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQU_PH_QBR: - check_dsp(ctx); - gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQU_PH_QBLA: - check_dsp(ctx); - gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQU_PH_QBRA: - check_dsp(ctx); - gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEU_PH_QBL: - check_dsp(ctx); - gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEU_PH_QBR: - check_dsp(ctx); - gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEU_PH_QBLA: - check_dsp(ctx); - gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEU_PH_QBRA: - check_dsp(ctx); - gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t); - break; - } - break; - case OPC_ADDU_QB_DSP: - switch (op2) { - case OPC_ADDQ_PH: - check_dsp(ctx); - gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDQ_S_PH: - check_dsp(ctx); - gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDQ_S_W: - check_dsp(ctx); - gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDU_QB: - check_dsp(ctx); - gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDU_S_QB: - check_dsp(ctx); - gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDU_PH: - check_dsp_r2(ctx); - gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDU_S_PH: - check_dsp_r2(ctx); - gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBQ_PH: - check_dsp(ctx); - gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBQ_S_PH: - check_dsp(ctx); - gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBQ_S_W: - check_dsp(ctx); - gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBU_QB: - check_dsp(ctx); - gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBU_S_QB: - check_dsp(ctx); - gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBU_PH: - check_dsp_r2(ctx); - gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBU_S_PH: - check_dsp_r2(ctx); - gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDSC: - check_dsp(ctx); - gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDWC: - check_dsp(ctx); - gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MODSUB: - check_dsp(ctx); - gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_RADDU_W_QB: - check_dsp(ctx); - gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t); - break; - } - break; - case OPC_CMPU_EQ_QB_DSP: - switch (op2) { - case OPC_PRECR_QB_PH: - check_dsp_r2(ctx); - gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_PRECRQ_QB_PH: - check_dsp(ctx); - gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_PRECR_SRA_PH_W: - check_dsp_r2(ctx); - { - TCGv_i32 sa_t = tcg_const_i32(v2); - gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t, - cpu_gpr[ret]); - tcg_temp_free_i32(sa_t); - break; - } - case OPC_PRECR_SRA_R_PH_W: - check_dsp_r2(ctx); - { - TCGv_i32 sa_t = tcg_const_i32(v2); - gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t, - cpu_gpr[ret]); - tcg_temp_free_i32(sa_t); - break; - } - case OPC_PRECRQ_PH_W: - check_dsp(ctx); - gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_PRECRQ_RS_PH_W: - check_dsp(ctx); - gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_PRECRQU_S_QB_PH: - check_dsp(ctx); - gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - } - break; -#ifdef TARGET_MIPS64 - case OPC_ABSQ_S_QH_DSP: - switch (op2) { - case OPC_PRECEQ_L_PWL: - check_dsp(ctx); - tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull); - break; - case OPC_PRECEQ_L_PWR: - check_dsp(ctx); - tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32); - break; - case OPC_PRECEQ_PW_QHL: - check_dsp(ctx); - gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQ_PW_QHR: - check_dsp(ctx); - gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQ_PW_QHLA: - check_dsp(ctx); - gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQ_PW_QHRA: - check_dsp(ctx); - gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQU_QH_OBL: - check_dsp(ctx); - gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQU_QH_OBR: - check_dsp(ctx); - gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQU_QH_OBLA: - check_dsp(ctx); - gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEQU_QH_OBRA: - check_dsp(ctx); - gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEU_QH_OBL: - check_dsp(ctx); - gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEU_QH_OBR: - check_dsp(ctx); - gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEU_QH_OBLA: - check_dsp(ctx); - gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t); - break; - case OPC_PRECEU_QH_OBRA: - check_dsp(ctx); - gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t); - break; - case OPC_ABSQ_S_OB: - check_dsp_r2(ctx); - gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env); - break; - case OPC_ABSQ_S_PW: - check_dsp(ctx); - gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env); - break; - case OPC_ABSQ_S_QH: - check_dsp(ctx); - gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env); - break; - } - break; - case OPC_ADDU_OB_DSP: - switch (op2) { - case OPC_RADDU_L_OB: - check_dsp(ctx); - gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t); - break; - case OPC_SUBQ_PW: - check_dsp(ctx); - gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBQ_S_PW: - check_dsp(ctx); - gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBQ_QH: - check_dsp(ctx); - gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBQ_S_QH: - check_dsp(ctx); - gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBU_OB: - check_dsp(ctx); - gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBU_S_OB: - check_dsp(ctx); - gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBU_QH: - check_dsp_r2(ctx); - gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBU_S_QH: - check_dsp_r2(ctx); - gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SUBUH_OB: - check_dsp_r2(ctx); - gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SUBUH_R_OB: - check_dsp_r2(ctx); - gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_ADDQ_PW: - check_dsp(ctx); - gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDQ_S_PW: - check_dsp(ctx); - gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDQ_QH: - check_dsp(ctx); - gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDQ_S_QH: - check_dsp(ctx); - gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDU_OB: - check_dsp(ctx); - gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDU_S_OB: - check_dsp(ctx); - gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDU_QH: - check_dsp_r2(ctx); - gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDU_S_QH: - check_dsp_r2(ctx); - gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_ADDUH_OB: - check_dsp_r2(ctx); - gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_ADDUH_R_OB: - check_dsp_r2(ctx); - gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t); - break; - } - break; - case OPC_CMPU_EQ_OB_DSP: - switch (op2) { - case OPC_PRECR_OB_QH: - check_dsp_r2(ctx); - gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_PRECR_SRA_QH_PW: - check_dsp_r2(ctx); - { - TCGv_i32 ret_t = tcg_const_i32(ret); - gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t); - tcg_temp_free_i32(ret_t); - break; - } - case OPC_PRECR_SRA_R_QH_PW: - check_dsp_r2(ctx); - { - TCGv_i32 sa_v = tcg_const_i32(ret); - gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v); - tcg_temp_free_i32(sa_v); - break; - } - case OPC_PRECRQ_OB_QH: - check_dsp(ctx); - gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_PRECRQ_PW_L: - check_dsp(ctx); - gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_PRECRQ_QH_PW: - check_dsp(ctx); - gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_PRECRQ_RS_QH_PW: - check_dsp(ctx); - gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_PRECRQU_S_OB_QH: - check_dsp(ctx); - gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - } - break; -#endif - } - - tcg_temp_free(v1_t); - tcg_temp_free(v2_t); -} - -static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc, - int ret, int v1, int v2) -{ - uint32_t op2; - TCGv t0; - TCGv v1_t; - TCGv v2_t; - - if (ret == 0) { - /* Treat as NOP. */ - return; - } - - t0 = tcg_temp_new(); - v1_t = tcg_temp_new(); - v2_t = tcg_temp_new(); - - tcg_gen_movi_tl(t0, v1); - gen_load_gpr(v1_t, v1); - gen_load_gpr(v2_t, v2); - - switch (opc) { - case OPC_SHLL_QB_DSP: - { - op2 = MASK_SHLL_QB(ctx->opcode); - switch (op2) { - case OPC_SHLL_QB: - check_dsp(ctx); - gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env); - break; - case OPC_SHLLV_QB: - check_dsp(ctx); - gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SHLL_PH: - check_dsp(ctx); - gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env); - break; - case OPC_SHLLV_PH: - check_dsp(ctx); - gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SHLL_S_PH: - check_dsp(ctx); - gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env); - break; - case OPC_SHLLV_S_PH: - check_dsp(ctx); - gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SHLL_S_W: - check_dsp(ctx); - gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env); - break; - case OPC_SHLLV_S_W: - check_dsp(ctx); - gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_SHRL_QB: - check_dsp(ctx); - gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t); - break; - case OPC_SHRLV_QB: - check_dsp(ctx); - gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SHRL_PH: - check_dsp_r2(ctx); - gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t); - break; - case OPC_SHRLV_PH: - check_dsp_r2(ctx); - gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SHRA_QB: - check_dsp_r2(ctx); - gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t); - break; - case OPC_SHRA_R_QB: - check_dsp_r2(ctx); - gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t); - break; - case OPC_SHRAV_QB: - check_dsp_r2(ctx); - gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SHRAV_R_QB: - check_dsp_r2(ctx); - gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SHRA_PH: - check_dsp(ctx); - gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t); - break; - case OPC_SHRA_R_PH: - check_dsp(ctx); - gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t); - break; - case OPC_SHRAV_PH: - check_dsp(ctx); - gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SHRAV_R_PH: - check_dsp(ctx); - gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_SHRA_R_W: - check_dsp(ctx); - gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t); - break; - case OPC_SHRAV_R_W: - check_dsp(ctx); - gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t); - break; - default: /* Invalid */ - MIPS_INVAL("MASK SHLL.QB"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - } -#ifdef TARGET_MIPS64 - case OPC_SHLL_OB_DSP: - op2 = MASK_SHLL_OB(ctx->opcode); - switch (op2) { - case OPC_SHLL_PW: - check_dsp(ctx); - gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env); - break; - case OPC_SHLLV_PW: - check_dsp(ctx); - gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env); - break; - case OPC_SHLL_S_PW: - check_dsp(ctx); - gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env); - break; - case OPC_SHLLV_S_PW: - check_dsp(ctx); - gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env); - break; - case OPC_SHLL_OB: - check_dsp(ctx); - gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env); - break; - case OPC_SHLLV_OB: - check_dsp(ctx); - gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env); - break; - case OPC_SHLL_QH: - check_dsp(ctx); - gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env); - break; - case OPC_SHLLV_QH: - check_dsp(ctx); - gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env); - break; - case OPC_SHLL_S_QH: - check_dsp(ctx); - gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env); - break; - case OPC_SHLLV_S_QH: - check_dsp(ctx); - gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env); - break; - case OPC_SHRA_OB: - check_dsp_r2(ctx); - gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0); - break; - case OPC_SHRAV_OB: - check_dsp_r2(ctx); - gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t); - break; - case OPC_SHRA_R_OB: - check_dsp_r2(ctx); - gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0); - break; - case OPC_SHRAV_R_OB: - check_dsp_r2(ctx); - gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t); - break; - case OPC_SHRA_PW: - check_dsp(ctx); - gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0); - break; - case OPC_SHRAV_PW: - check_dsp(ctx); - gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t); - break; - case OPC_SHRA_R_PW: - check_dsp(ctx); - gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0); - break; - case OPC_SHRAV_R_PW: - check_dsp(ctx); - gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t); - break; - case OPC_SHRA_QH: - check_dsp(ctx); - gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0); - break; - case OPC_SHRAV_QH: - check_dsp(ctx); - gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t); - break; - case OPC_SHRA_R_QH: - check_dsp(ctx); - gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0); - break; - case OPC_SHRAV_R_QH: - check_dsp(ctx); - gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t); - break; - case OPC_SHRL_OB: - check_dsp(ctx); - gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0); - break; - case OPC_SHRLV_OB: - check_dsp(ctx); - gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t); - break; - case OPC_SHRL_QH: - check_dsp_r2(ctx); - gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0); - break; - case OPC_SHRLV_QH: - check_dsp_r2(ctx); - gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t); - break; - default: /* Invalid */ - MIPS_INVAL("MASK SHLL.OB"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; -#endif - } - - tcg_temp_free(t0); - tcg_temp_free(v1_t); - tcg_temp_free(v2_t); -} - -static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2, - int ret, int v1, int v2, int check_ret) -{ - TCGv_i32 t0; - TCGv v1_t; - TCGv v2_t; - - if ((ret == 0) && (check_ret == 1)) { - /* Treat as NOP. */ - return; - } - - t0 = tcg_temp_new_i32(); - v1_t = tcg_temp_new(); - v2_t = tcg_temp_new(); - - tcg_gen_movi_i32(t0, ret); - gen_load_gpr(v1_t, v1); - gen_load_gpr(v2_t, v2); - - switch (op1) { - /* - * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have - * the same mask and op1. - */ - case OPC_MULT_G_2E: - check_dsp_r2(ctx); - switch (op2) { - case OPC_MUL_PH: - gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MUL_S_PH: - gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULQ_S_W: - gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULQ_RS_W: - gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - } - break; - case OPC_DPA_W_PH_DSP: - switch (op2) { - case OPC_DPAU_H_QBL: - check_dsp(ctx); - gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPAU_H_QBR: - check_dsp(ctx); - gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPSU_H_QBL: - check_dsp(ctx); - gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPSU_H_QBR: - check_dsp(ctx); - gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPAX_W_PH: - check_dsp_r2(ctx); - gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPAQ_S_W_PH: - check_dsp(ctx); - gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPAQX_S_W_PH: - check_dsp_r2(ctx); - gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPAQX_SA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPS_W_PH: - check_dsp_r2(ctx); - gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPSX_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPSQ_S_W_PH: - check_dsp(ctx); - gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPSQX_S_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPSQX_SA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_MULSAQ_S_W_PH: - check_dsp(ctx); - gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPAQ_SA_L_W: - check_dsp(ctx); - gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env); - break; - case OPC_DPSQ_SA_L_W: - check_dsp(ctx); - gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env); - break; - case OPC_MAQ_S_W_PHL: - check_dsp(ctx); - gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env); - break; - case OPC_MAQ_S_W_PHR: - check_dsp(ctx); - gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env); - break; - case OPC_MAQ_SA_W_PHL: - check_dsp(ctx); - gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env); - break; - case OPC_MAQ_SA_W_PHR: - check_dsp(ctx); - gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env); - break; - case OPC_MULSA_W_PH: - check_dsp_r2(ctx); - gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env); - break; - } - break; -#ifdef TARGET_MIPS64 - case OPC_DPAQ_W_QH_DSP: - { - int ac = ret & 0x03; - tcg_gen_movi_i32(t0, ac); - - switch (op2) { - case OPC_DMADD: - check_dsp(ctx); - gen_helper_dmadd(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DMADDU: - check_dsp(ctx); - gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DMSUB: - check_dsp(ctx); - gen_helper_dmsub(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DMSUBU: - check_dsp(ctx); - gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPA_W_QH: - check_dsp_r2(ctx); - gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPAQ_S_W_QH: - check_dsp(ctx); - gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPAQ_SA_L_PW: - check_dsp(ctx); - gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPAU_H_OBL: - check_dsp(ctx); - gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPAU_H_OBR: - check_dsp(ctx); - gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPS_W_QH: - check_dsp_r2(ctx); - gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPSQ_S_W_QH: - check_dsp(ctx); - gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPSQ_SA_L_PW: - check_dsp(ctx); - gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPSU_H_OBL: - check_dsp(ctx); - gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env); - break; - case OPC_DPSU_H_OBR: - check_dsp(ctx); - gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_S_L_PWL: - check_dsp(ctx); - gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_S_L_PWR: - check_dsp(ctx); - gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_S_W_QHLL: - check_dsp(ctx); - gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_SA_W_QHLL: - check_dsp(ctx); - gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_S_W_QHLR: - check_dsp(ctx); - gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_SA_W_QHLR: - check_dsp(ctx); - gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_S_W_QHRL: - check_dsp(ctx); - gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_SA_W_QHRL: - check_dsp(ctx); - gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_S_W_QHRR: - check_dsp(ctx); - gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MAQ_SA_W_QHRR: - check_dsp(ctx); - gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MULSAQ_S_L_PW: - check_dsp(ctx); - gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env); - break; - case OPC_MULSAQ_S_W_QH: - check_dsp(ctx); - gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env); - break; - } - } - break; -#endif - case OPC_ADDU_QB_DSP: - switch (op2) { - case OPC_MULEU_S_PH_QBL: - check_dsp(ctx); - gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULEU_S_PH_QBR: - check_dsp(ctx); - gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULQ_RS_PH: - check_dsp(ctx); - gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULEQ_S_W_PHL: - check_dsp(ctx); - gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULEQ_S_W_PHR: - check_dsp(ctx); - gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULQ_S_PH: - check_dsp_r2(ctx); - gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - } - break; -#ifdef TARGET_MIPS64 - case OPC_ADDU_OB_DSP: - switch (op2) { - case OPC_MULEQ_S_PW_QHL: - check_dsp(ctx); - gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULEQ_S_PW_QHR: - check_dsp(ctx); - gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULEU_S_QH_OBL: - check_dsp(ctx); - gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULEU_S_QH_OBR: - check_dsp(ctx); - gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_MULQ_RS_QH: - check_dsp(ctx); - gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - } - break; -#endif - } - - tcg_temp_free_i32(t0); - tcg_temp_free(v1_t); - tcg_temp_free(v2_t); -} - -static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, - int ret, int val) -{ - int16_t imm; - TCGv t0; - TCGv val_t; - - if (ret == 0) { - /* Treat as NOP. */ - return; - } - - t0 = tcg_temp_new(); - val_t = tcg_temp_new(); - gen_load_gpr(val_t, val); - - switch (op1) { - case OPC_ABSQ_S_PH_DSP: - switch (op2) { - case OPC_BITREV: - check_dsp(ctx); - gen_helper_bitrev(cpu_gpr[ret], val_t); - break; - case OPC_REPL_QB: - check_dsp(ctx); - { - target_long result; - imm = (ctx->opcode >> 16) & 0xFF; - result = (uint32_t)imm << 24 | - (uint32_t)imm << 16 | - (uint32_t)imm << 8 | - (uint32_t)imm; - result = (int32_t)result; - tcg_gen_movi_tl(cpu_gpr[ret], result); - } - break; - case OPC_REPLV_QB: - check_dsp(ctx); - tcg_gen_ext8u_tl(cpu_gpr[ret], val_t); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 8); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); - break; - case OPC_REPL_PH: - check_dsp(ctx); - { - imm = (ctx->opcode >> 16) & 0x03FF; - imm = (int16_t)(imm << 6) >> 6; - tcg_gen_movi_tl(cpu_gpr[ret], \ - (target_long)((int32_t)imm << 16 | \ - (uint16_t)imm)); - } - break; - case OPC_REPLV_PH: - check_dsp(ctx); - tcg_gen_ext16u_tl(cpu_gpr[ret], val_t); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); - break; - } - break; -#ifdef TARGET_MIPS64 - case OPC_ABSQ_S_QH_DSP: - switch (op2) { - case OPC_REPL_OB: - check_dsp(ctx); - { - target_long temp; - - imm = (ctx->opcode >> 16) & 0xFF; - temp = ((uint64_t)imm << 8) | (uint64_t)imm; - temp = (temp << 16) | temp; - temp = (temp << 32) | temp; - tcg_gen_movi_tl(cpu_gpr[ret], temp); - break; - } - case OPC_REPL_PW: - check_dsp(ctx); - { - target_long temp; - - imm = (ctx->opcode >> 16) & 0x03FF; - imm = (int16_t)(imm << 6) >> 6; - temp = ((target_long)imm << 32) \ - | ((target_long)imm & 0xFFFFFFFF); - tcg_gen_movi_tl(cpu_gpr[ret], temp); - break; - } - case OPC_REPL_QH: - check_dsp(ctx); - { - target_long temp; - - imm = (ctx->opcode >> 16) & 0x03FF; - imm = (int16_t)(imm << 6) >> 6; - - temp = ((uint64_t)(uint16_t)imm << 48) | - ((uint64_t)(uint16_t)imm << 32) | - ((uint64_t)(uint16_t)imm << 16) | - (uint64_t)(uint16_t)imm; - tcg_gen_movi_tl(cpu_gpr[ret], temp); - break; - } - case OPC_REPLV_OB: - check_dsp(ctx); - tcg_gen_ext8u_tl(cpu_gpr[ret], val_t); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 8); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - break; - case OPC_REPLV_PW: - check_dsp(ctx); - tcg_gen_ext32u_i64(cpu_gpr[ret], val_t); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - break; - case OPC_REPLV_QH: - check_dsp(ctx); - tcg_gen_ext16u_tl(cpu_gpr[ret], val_t); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - break; - } - break; -#endif - } - tcg_temp_free(t0); - tcg_temp_free(val_t); -} - -static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx, - uint32_t op1, uint32_t op2, - int ret, int v1, int v2, int check_ret) -{ - TCGv t1; - TCGv v1_t; - TCGv v2_t; - - if ((ret == 0) && (check_ret == 1)) { - /* Treat as NOP. */ - return; - } - - t1 = tcg_temp_new(); - v1_t = tcg_temp_new(); - v2_t = tcg_temp_new(); - - gen_load_gpr(v1_t, v1); - gen_load_gpr(v2_t, v2); - - switch (op1) { - case OPC_CMPU_EQ_QB_DSP: - switch (op2) { - case OPC_CMPU_EQ_QB: - check_dsp(ctx); - gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env); - break; - case OPC_CMPU_LT_QB: - check_dsp(ctx); - gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env); - break; - case OPC_CMPU_LE_QB: - check_dsp(ctx); - gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env); - break; - case OPC_CMPGU_EQ_QB: - check_dsp(ctx); - gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_CMPGU_LT_QB: - check_dsp(ctx); - gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_CMPGU_LE_QB: - check_dsp(ctx); - gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_CMPGDU_EQ_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t); - tcg_gen_mov_tl(cpu_gpr[ret], t1); - tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); - tcg_gen_shli_tl(t1, t1, 24); - tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); - break; - case OPC_CMPGDU_LT_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t); - tcg_gen_mov_tl(cpu_gpr[ret], t1); - tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); - tcg_gen_shli_tl(t1, t1, 24); - tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); - break; - case OPC_CMPGDU_LE_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_le_qb(t1, v1_t, v2_t); - tcg_gen_mov_tl(cpu_gpr[ret], t1); - tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); - tcg_gen_shli_tl(t1, t1, 24); - tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); - break; - case OPC_CMP_EQ_PH: - check_dsp(ctx); - gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env); - break; - case OPC_CMP_LT_PH: - check_dsp(ctx); - gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env); - break; - case OPC_CMP_LE_PH: - check_dsp(ctx); - gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env); - break; - case OPC_PICK_QB: - check_dsp(ctx); - gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_PICK_PH: - check_dsp(ctx); - gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_PACKRL_PH: - check_dsp(ctx); - gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t); - break; - } - break; -#ifdef TARGET_MIPS64 - case OPC_CMPU_EQ_OB_DSP: - switch (op2) { - case OPC_CMP_EQ_PW: - check_dsp(ctx); - gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env); - break; - case OPC_CMP_LT_PW: - check_dsp(ctx); - gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env); - break; - case OPC_CMP_LE_PW: - check_dsp(ctx); - gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env); - break; - case OPC_CMP_EQ_QH: - check_dsp(ctx); - gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env); - break; - case OPC_CMP_LT_QH: - check_dsp(ctx); - gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env); - break; - case OPC_CMP_LE_QH: - check_dsp(ctx); - gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env); - break; - case OPC_CMPGDU_EQ_OB: - check_dsp_r2(ctx); - gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_CMPGDU_LT_OB: - check_dsp_r2(ctx); - gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_CMPGDU_LE_OB: - check_dsp_r2(ctx); - gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_CMPGU_EQ_OB: - check_dsp(ctx); - gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_CMPGU_LT_OB: - check_dsp(ctx); - gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_CMPGU_LE_OB: - check_dsp(ctx); - gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_CMPU_EQ_OB: - check_dsp(ctx); - gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env); - break; - case OPC_CMPU_LT_OB: - check_dsp(ctx); - gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env); - break; - case OPC_CMPU_LE_OB: - check_dsp(ctx); - gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env); - break; - case OPC_PACKRL_PW: - check_dsp(ctx); - gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t); - break; - case OPC_PICK_OB: - check_dsp(ctx); - gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_PICK_PW: - check_dsp(ctx); - gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - case OPC_PICK_QH: - check_dsp(ctx); - gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); - break; - } - break; -#endif - } - - tcg_temp_free(t1); - tcg_temp_free(v1_t); - tcg_temp_free(v2_t); -} - -static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx, - uint32_t op1, int rt, int rs, int sa) -{ - TCGv t0; - - check_dsp_r2(ctx); - - if (rt == 0) { - /* Treat as NOP. */ - return; - } - - t0 = tcg_temp_new(); - gen_load_gpr(t0, rs); - - switch (op1) { - case OPC_APPEND_DSP: - switch (MASK_APPEND(ctx->opcode)) { - case OPC_APPEND: - if (sa != 0) { - tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa); - } - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - break; - case OPC_PREPEND: - if (sa != 0) { - tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]); - tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa); - tcg_gen_shli_tl(t0, t0, 32 - sa); - tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0); - } - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - break; - case OPC_BALIGN: - sa &= 3; - if (sa != 0 && sa != 2) { - tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_shri_tl(t0, t0, 8 * (4 - sa)); - tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0); - } - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - break; - default: /* Invalid */ - MIPS_INVAL("MASK APPEND"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; -#ifdef TARGET_MIPS64 - case OPC_DAPPEND_DSP: - switch (MASK_DAPPEND(ctx->opcode)) { - case OPC_DAPPEND: - if (sa != 0) { - tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa); - } - break; - case OPC_PREPENDD: - tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa); - tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa)); - tcg_gen_or_tl(cpu_gpr[rt], t0, t0); - break; - case OPC_PREPENDW: - if (sa != 0) { - tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa); - tcg_gen_shli_tl(t0, t0, 64 - sa); - tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0); - } - break; - case OPC_DBALIGN: - sa &= 7; - if (sa != 0 && sa != 2 && sa != 4) { - tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa); - tcg_gen_shri_tl(t0, t0, 8 * (8 - sa)); - tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0); - } - break; - default: /* Invalid */ - MIPS_INVAL("MASK DAPPEND"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; -#endif - } - tcg_temp_free(t0); -} - -static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, - int ret, int v1, int v2, int check_ret) - -{ - TCGv t0; - TCGv t1; - TCGv v1_t; - TCGv v2_t; - int16_t imm; - - if ((ret == 0) && (check_ret == 1)) { - /* Treat as NOP. */ - return; - } - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - v1_t = tcg_temp_new(); - v2_t = tcg_temp_new(); - - gen_load_gpr(v1_t, v1); - gen_load_gpr(v2_t, v2); - - switch (op1) { - case OPC_EXTR_W_DSP: - check_dsp(ctx); - switch (op2) { - case OPC_EXTR_W: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_EXTR_R_W: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_EXTR_RS_W: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_EXTR_S_H: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_EXTRV_S_H: - tcg_gen_movi_tl(t0, v2); - gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_EXTRV_W: - tcg_gen_movi_tl(t0, v2); - gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_EXTRV_R_W: - tcg_gen_movi_tl(t0, v2); - gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_EXTRV_RS_W: - tcg_gen_movi_tl(t0, v2); - gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_EXTP: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_EXTPV: - tcg_gen_movi_tl(t0, v2); - gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_EXTPDP: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_EXTPDPV: - tcg_gen_movi_tl(t0, v2); - gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_SHILO: - imm = (ctx->opcode >> 20) & 0x3F; - tcg_gen_movi_tl(t0, ret); - tcg_gen_movi_tl(t1, imm); - gen_helper_shilo(t0, t1, cpu_env); - break; - case OPC_SHILOV: - tcg_gen_movi_tl(t0, ret); - gen_helper_shilo(t0, v1_t, cpu_env); - break; - case OPC_MTHLIP: - tcg_gen_movi_tl(t0, ret); - gen_helper_mthlip(t0, v1_t, cpu_env); - break; - case OPC_WRDSP: - imm = (ctx->opcode >> 11) & 0x3FF; - tcg_gen_movi_tl(t0, imm); - gen_helper_wrdsp(v1_t, t0, cpu_env); - break; - case OPC_RDDSP: - imm = (ctx->opcode >> 16) & 0x03FF; - tcg_gen_movi_tl(t0, imm); - gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env); - break; - } - break; -#ifdef TARGET_MIPS64 - case OPC_DEXTR_W_DSP: - check_dsp(ctx); - switch (op2) { - case OPC_DMTHLIP: - tcg_gen_movi_tl(t0, ret); - gen_helper_dmthlip(v1_t, t0, cpu_env); - break; - case OPC_DSHILO: - { - int shift = (ctx->opcode >> 19) & 0x7F; - int ac = (ctx->opcode >> 11) & 0x03; - tcg_gen_movi_tl(t0, shift); - tcg_gen_movi_tl(t1, ac); - gen_helper_dshilo(t0, t1, cpu_env); - break; - } - case OPC_DSHILOV: - { - int ac = (ctx->opcode >> 11) & 0x03; - tcg_gen_movi_tl(t0, ac); - gen_helper_dshilo(v1_t, t0, cpu_env); - break; - } - case OPC_DEXTP: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - - gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTPV: - tcg_gen_movi_tl(t0, v2); - gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_DEXTPDP: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTPDPV: - tcg_gen_movi_tl(t0, v2); - gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_DEXTR_L: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTR_R_L: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTR_RS_L: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTR_W: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTR_R_W: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTR_RS_W: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTR_S_H: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTRV_S_H: - tcg_gen_movi_tl(t0, v2); - tcg_gen_movi_tl(t1, v1); - gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env); - break; - case OPC_DEXTRV_L: - tcg_gen_movi_tl(t0, v2); - gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_DEXTRV_R_L: - tcg_gen_movi_tl(t0, v2); - gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_DEXTRV_RS_L: - tcg_gen_movi_tl(t0, v2); - gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_DEXTRV_W: - tcg_gen_movi_tl(t0, v2); - gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_DEXTRV_R_W: - tcg_gen_movi_tl(t0, v2); - gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - case OPC_DEXTRV_RS_W: - tcg_gen_movi_tl(t0, v2); - gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env); - break; - } - break; -#endif - } - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(v1_t); - tcg_temp_free(v2_t); -} - -/* End MIPSDSP functions. */ +#include "mod-dsp_translate.c.inc" static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) { diff --git a/target/mips/mod-dsp_translate.c.inc b/target/mips/mod-dsp_translate.c.inc new file mode 100644 index 00000000000..80e3172c0be --- /dev/null +++ b/target/mips/mod-dsp_translate.c.inc @@ -0,0 +1,2158 @@ +/* + * MIPS DSP Architecture Module translation routines + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +enum { + /* MIPS DSP Load */ + OPC_LX_DSP = 0x0A | OPC_SPECIAL3, + /* MIPS DSP Arithmetic */ + OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3, + OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3, + OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3, + OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3, + /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */ + /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */ + OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3, + OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3, + /* MIPS DSP GPR-Based Shift Sub-class */ + OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3, + OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3, + /* MIPS DSP Multiply Sub-class insns */ + /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */ + /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */ + OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3, + OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3, + /* DSP Bit/Manipulation Sub-class */ + OPC_INSV_DSP = 0x0C | OPC_SPECIAL3, + OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3, + /* MIPS DSP Append Sub-class */ + OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3, + OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3, + /* MIPS DSP Accumulator and DSPControl Access Sub-class */ + OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3, + OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3, +}; + +#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +/* MIPS DSP Load */ +enum { + OPC_LBUX = (0x06 << 6) | OPC_LX_DSP, + OPC_LHX = (0x04 << 6) | OPC_LX_DSP, + OPC_LWX = (0x00 << 6) | OPC_LX_DSP, + OPC_LDX = (0x08 << 6) | OPC_LX_DSP, +}; + +#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP, + OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP, + OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP, + OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP, + OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP, + OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP, + OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP, + OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP, + OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP, + OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP, + OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP, + OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP, + OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP, + /* MIPS DSP Multiply Sub-class insns */ + OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP, + OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP, + OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP, + OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP, + OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP, + OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP, +}; + +#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E +#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP, + /* MIPS DSP Multiply Sub-class insns */ + OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP, + OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP, + OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP, + OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP, +}; + +#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP, + /* DSP Bit/Manipulation Sub-class */ + OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP, +}; + +#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP, + /* DSP Compare-Pick Sub-class */ + OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP, +}; + +#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP GPR-Based Shift Sub-class */ + OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP, + OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP, + OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP, + OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP, + OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP, + OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP, + OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP, + OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP, +}; + +#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Multiply Sub-class insns */ + OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP, + OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP, + OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP, + OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP, + OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP, + OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP, + OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP, + OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP, + OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP, +}; + +#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* DSP Bit/Manipulation Sub-class */ + OPC_INSV = (0x00 << 6) | OPC_INSV_DSP, +}; + +#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Append Sub-class */ + OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP, + OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP, + OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP, +}; + +#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Accumulator and DSPControl Access Sub-class */ + OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP, + OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP, + OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP, + OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP, + OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP, + OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP, + OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP, + OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP, + OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP, + OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP, + OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP, + OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP, + OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP, + OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP, + OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP, + OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP, + OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP, +}; + +#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP, + OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP, + /* DSP Bit/Manipulation Sub-class */ + OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP, +}; + +#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Multiply Sub-class insns */ + OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP, + OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP, + OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP, + OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP, + OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP, + /* MIPS DSP Arithmetic Sub-class */ + OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP, + OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP, + OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP, + OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP, + OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP, + OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP, + OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP, + OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP, +}; + +#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* DSP Compare-Pick Sub-class */ + OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP, + /* MIPS DSP Arithmetic Sub-class */ + OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP, +}; + +#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* DSP Append Sub-class */ + OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP, + OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP, + OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP, + OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP, +}; + +#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Accumulator and DSPControl Access Sub-class */ + OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP, + OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP, + OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP, +}; + +#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* DSP Bit/Manipulation Sub-class */ + OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP, +}; + +#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Multiply Sub-class insns */ + OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP, +}; + +#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP GPR-Based Shift Sub-class */ + OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP, + OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP, + OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP, + OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP, +}; + +/* + * Verify that the processor is running with DSP instructions enabled. + * This is enabled by CP0 Status register MX(24) bit. + */ +static inline void check_dsp(DisasContext *ctx) +{ + if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) { + if (ctx->insn_flags & ASE_DSP) { + generate_exception_end(ctx, EXCP_DSPDIS); + } else { + generate_exception_end(ctx, EXCP_RI); + } + } +} + +static inline void check_dsp_r2(DisasContext *ctx) +{ + if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) { + if (ctx->insn_flags & ASE_DSP) { + generate_exception_end(ctx, EXCP_DSPDIS); + } else { + generate_exception_end(ctx, EXCP_RI); + } + } +} + +static inline void check_dsp_r3(DisasContext *ctx) +{ + if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) { + if (ctx->insn_flags & ASE_DSP) { + generate_exception_end(ctx, EXCP_DSPDIS); + } else { + generate_exception_end(ctx, EXCP_RI); + } + } +} + +static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc, + int rd, int base, int offset) +{ + TCGv t0; + + check_dsp(ctx); + t0 = tcg_temp_new(); + + if (base == 0) { + gen_load_gpr(t0, offset); + } else if (offset == 0) { + gen_load_gpr(t0, base); + } else { + gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]); + } + + switch (opc) { + case OPC_LBUX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB); + gen_store_gpr(t0, rd); + break; + case OPC_LHX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW); + gen_store_gpr(t0, rd); + break; + case OPC_LWX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL); + gen_store_gpr(t0, rd); + break; +#if defined(TARGET_MIPS64) + case OPC_LDX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + gen_store_gpr(t0, rd); + break; +#endif + } + tcg_temp_free(t0); +} + +static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2, + int ret, int v1, int v2) +{ + TCGv v1_t; + TCGv v2_t; + + if (ret == 0) { + /* Treat as NOP. */ + return; + } + + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (op1) { + /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */ + case OPC_MULT_G_2E: + check_dsp_r2(ctx); + switch (op2) { + case OPC_ADDUH_QB: + gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDUH_R_QB: + gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQH_PH: + gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQH_R_PH: + gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQH_W: + gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQH_R_W: + gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBUH_QB: + gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBUH_R_QB: + gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBQH_PH: + gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBQH_R_PH: + gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBQH_W: + gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBQH_R_W: + gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t); + break; + } + break; + case OPC_ABSQ_S_PH_DSP: + switch (op2) { + case OPC_ABSQ_S_QB: + check_dsp_r2(ctx); + gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_ABSQ_S_PH: + check_dsp(ctx); + gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_ABSQ_S_W: + check_dsp(ctx); + gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_PRECEQ_W_PHL: + check_dsp(ctx); + tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000); + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + break; + case OPC_PRECEQ_W_PHR: + check_dsp(ctx); + tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF); + tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16); + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + break; + case OPC_PRECEQU_PH_QBL: + check_dsp(ctx); + gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_PH_QBR: + check_dsp(ctx); + gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_PH_QBLA: + check_dsp(ctx); + gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_PH_QBRA: + check_dsp(ctx); + gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_PH_QBL: + check_dsp(ctx); + gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_PH_QBR: + check_dsp(ctx); + gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_PH_QBLA: + check_dsp(ctx); + gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_PH_QBRA: + check_dsp(ctx); + gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t); + break; + } + break; + case OPC_ADDU_QB_DSP: + switch (op2) { + case OPC_ADDQ_PH: + check_dsp(ctx); + gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_S_PH: + check_dsp(ctx); + gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_S_W: + check_dsp(ctx); + gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_QB: + check_dsp(ctx); + gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_S_QB: + check_dsp(ctx); + gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_PH: + check_dsp_r2(ctx); + gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_S_PH: + check_dsp_r2(ctx); + gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_PH: + check_dsp(ctx); + gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_S_PH: + check_dsp(ctx); + gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_S_W: + check_dsp(ctx); + gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_QB: + check_dsp(ctx); + gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_S_QB: + check_dsp(ctx); + gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_PH: + check_dsp_r2(ctx); + gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_S_PH: + check_dsp_r2(ctx); + gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDSC: + check_dsp(ctx); + gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDWC: + check_dsp(ctx); + gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MODSUB: + check_dsp(ctx); + gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_RADDU_W_QB: + check_dsp(ctx); + gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t); + break; + } + break; + case OPC_CMPU_EQ_QB_DSP: + switch (op2) { + case OPC_PRECR_QB_PH: + check_dsp_r2(ctx); + gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_QB_PH: + check_dsp(ctx); + gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECR_SRA_PH_W: + check_dsp_r2(ctx); + { + TCGv_i32 sa_t = tcg_const_i32(v2); + gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t, + cpu_gpr[ret]); + tcg_temp_free_i32(sa_t); + break; + } + case OPC_PRECR_SRA_R_PH_W: + check_dsp_r2(ctx); + { + TCGv_i32 sa_t = tcg_const_i32(v2); + gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t, + cpu_gpr[ret]); + tcg_temp_free_i32(sa_t); + break; + } + case OPC_PRECRQ_PH_W: + check_dsp(ctx); + gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_RS_PH_W: + check_dsp(ctx); + gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PRECRQU_S_QB_PH: + check_dsp(ctx); + gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_ABSQ_S_QH_DSP: + switch (op2) { + case OPC_PRECEQ_L_PWL: + check_dsp(ctx); + tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull); + break; + case OPC_PRECEQ_L_PWR: + check_dsp(ctx); + tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32); + break; + case OPC_PRECEQ_PW_QHL: + check_dsp(ctx); + gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQ_PW_QHR: + check_dsp(ctx); + gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQ_PW_QHLA: + check_dsp(ctx); + gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQ_PW_QHRA: + check_dsp(ctx); + gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_QH_OBL: + check_dsp(ctx); + gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_QH_OBR: + check_dsp(ctx); + gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_QH_OBLA: + check_dsp(ctx); + gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_QH_OBRA: + check_dsp(ctx); + gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_QH_OBL: + check_dsp(ctx); + gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_QH_OBR: + check_dsp(ctx); + gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_QH_OBLA: + check_dsp(ctx); + gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_QH_OBRA: + check_dsp(ctx); + gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t); + break; + case OPC_ABSQ_S_OB: + check_dsp_r2(ctx); + gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_ABSQ_S_PW: + check_dsp(ctx); + gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_ABSQ_S_QH: + check_dsp(ctx); + gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env); + break; + } + break; + case OPC_ADDU_OB_DSP: + switch (op2) { + case OPC_RADDU_L_OB: + check_dsp(ctx); + gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t); + break; + case OPC_SUBQ_PW: + check_dsp(ctx); + gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_S_PW: + check_dsp(ctx); + gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_QH: + check_dsp(ctx); + gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_S_QH: + check_dsp(ctx); + gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_OB: + check_dsp(ctx); + gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_S_OB: + check_dsp(ctx); + gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_QH: + check_dsp_r2(ctx); + gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_S_QH: + check_dsp_r2(ctx); + gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBUH_OB: + check_dsp_r2(ctx); + gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBUH_R_OB: + check_dsp_r2(ctx); + gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQ_PW: + check_dsp(ctx); + gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_S_PW: + check_dsp(ctx); + gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_QH: + check_dsp(ctx); + gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_S_QH: + check_dsp(ctx); + gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_OB: + check_dsp(ctx); + gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_S_OB: + check_dsp(ctx); + gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_QH: + check_dsp_r2(ctx); + gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_S_QH: + check_dsp_r2(ctx); + gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDUH_OB: + check_dsp_r2(ctx); + gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDUH_R_OB: + check_dsp_r2(ctx); + gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t); + break; + } + break; + case OPC_CMPU_EQ_OB_DSP: + switch (op2) { + case OPC_PRECR_OB_QH: + check_dsp_r2(ctx); + gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECR_SRA_QH_PW: + check_dsp_r2(ctx); + { + TCGv_i32 ret_t = tcg_const_i32(ret); + gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t); + tcg_temp_free_i32(ret_t); + break; + } + case OPC_PRECR_SRA_R_QH_PW: + check_dsp_r2(ctx); + { + TCGv_i32 sa_v = tcg_const_i32(ret); + gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v); + tcg_temp_free_i32(sa_v); + break; + } + case OPC_PRECRQ_OB_QH: + check_dsp(ctx); + gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_PW_L: + check_dsp(ctx); + gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_QH_PW: + check_dsp(ctx); + gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_RS_QH_PW: + check_dsp(ctx); + gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PRECRQU_S_OB_QH: + check_dsp(ctx); + gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#endif + } + + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); +} + +static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc, + int ret, int v1, int v2) +{ + uint32_t op2; + TCGv t0; + TCGv v1_t; + TCGv v2_t; + + if (ret == 0) { + /* Treat as NOP. */ + return; + } + + t0 = tcg_temp_new(); + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + tcg_gen_movi_tl(t0, v1); + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (opc) { + case OPC_SHLL_QB_DSP: + { + op2 = MASK_SHLL_QB(ctx->opcode); + switch (op2) { + case OPC_SHLL_QB: + check_dsp(ctx); + gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env); + break; + case OPC_SHLLV_QB: + check_dsp(ctx); + gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SHLL_PH: + check_dsp(ctx); + gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env); + break; + case OPC_SHLLV_PH: + check_dsp(ctx); + gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SHLL_S_PH: + check_dsp(ctx); + gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env); + break; + case OPC_SHLLV_S_PH: + check_dsp(ctx); + gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SHLL_S_W: + check_dsp(ctx); + gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env); + break; + case OPC_SHLLV_S_W: + check_dsp(ctx); + gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SHRL_QB: + check_dsp(ctx); + gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRLV_QB: + check_dsp(ctx); + gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRL_PH: + check_dsp_r2(ctx); + gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRLV_PH: + check_dsp_r2(ctx); + gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRA_QB: + check_dsp_r2(ctx); + gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRA_R_QB: + check_dsp_r2(ctx); + gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRAV_QB: + check_dsp_r2(ctx); + gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRAV_R_QB: + check_dsp_r2(ctx); + gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRA_PH: + check_dsp(ctx); + gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRA_R_PH: + check_dsp(ctx); + gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRAV_PH: + check_dsp(ctx); + gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRAV_R_PH: + check_dsp(ctx); + gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRA_R_W: + check_dsp(ctx); + gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRAV_R_W: + check_dsp(ctx); + gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t); + break; + default: /* Invalid */ + MIPS_INVAL("MASK SHLL.QB"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + } +#ifdef TARGET_MIPS64 + case OPC_SHLL_OB_DSP: + op2 = MASK_SHLL_OB(ctx->opcode); + switch (op2) { + case OPC_SHLL_PW: + check_dsp(ctx); + gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_PW: + check_dsp(ctx); + gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHLL_S_PW: + check_dsp(ctx); + gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_S_PW: + check_dsp(ctx); + gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHLL_OB: + check_dsp(ctx); + gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_OB: + check_dsp(ctx); + gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHLL_QH: + check_dsp(ctx); + gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_QH: + check_dsp(ctx); + gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHLL_S_QH: + check_dsp(ctx); + gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_S_QH: + check_dsp(ctx); + gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHRA_OB: + check_dsp_r2(ctx); + gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_OB: + check_dsp_r2(ctx); + gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_R_OB: + check_dsp_r2(ctx); + gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_R_OB: + check_dsp_r2(ctx); + gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_PW: + check_dsp(ctx); + gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_PW: + check_dsp(ctx); + gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_R_PW: + check_dsp(ctx); + gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_R_PW: + check_dsp(ctx); + gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_QH: + check_dsp(ctx); + gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_QH: + check_dsp(ctx); + gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_R_QH: + check_dsp(ctx); + gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_R_QH: + check_dsp(ctx); + gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRL_OB: + check_dsp(ctx); + gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRLV_OB: + check_dsp(ctx); + gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRL_QH: + check_dsp_r2(ctx); + gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRLV_QH: + check_dsp_r2(ctx); + gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t); + break; + default: /* Invalid */ + MIPS_INVAL("MASK SHLL.OB"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; +#endif + } + + tcg_temp_free(t0); + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); +} + +static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2, + int ret, int v1, int v2, int check_ret) +{ + TCGv_i32 t0; + TCGv v1_t; + TCGv v2_t; + + if ((ret == 0) && (check_ret == 1)) { + /* Treat as NOP. */ + return; + } + + t0 = tcg_temp_new_i32(); + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + tcg_gen_movi_i32(t0, ret); + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (op1) { + /* + * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have + * the same mask and op1. + */ + case OPC_MULT_G_2E: + check_dsp_r2(ctx); + switch (op2) { + case OPC_MUL_PH: + gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MUL_S_PH: + gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_S_W: + gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_RS_W: + gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; + case OPC_DPA_W_PH_DSP: + switch (op2) { + case OPC_DPAU_H_QBL: + check_dsp(ctx); + gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAU_H_QBR: + check_dsp(ctx); + gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSU_H_QBL: + check_dsp(ctx); + gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSU_H_QBR: + check_dsp(ctx); + gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAX_W_PH: + check_dsp_r2(ctx); + gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAQ_S_W_PH: + check_dsp(ctx); + gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAQX_S_W_PH: + check_dsp_r2(ctx); + gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAQX_SA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPS_W_PH: + check_dsp_r2(ctx); + gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSX_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSQ_S_W_PH: + check_dsp(ctx); + gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSQX_S_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSQX_SA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MULSAQ_S_W_PH: + check_dsp(ctx); + gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAQ_SA_L_W: + check_dsp(ctx); + gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSQ_SA_L_W: + check_dsp(ctx); + gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MAQ_S_W_PHL: + check_dsp(ctx); + gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MAQ_S_W_PHR: + check_dsp(ctx); + gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MAQ_SA_W_PHL: + check_dsp(ctx); + gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MAQ_SA_W_PHR: + check_dsp(ctx); + gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MULSA_W_PH: + check_dsp_r2(ctx); + gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_DPAQ_W_QH_DSP: + { + int ac = ret & 0x03; + tcg_gen_movi_i32(t0, ac); + + switch (op2) { + case OPC_DMADD: + check_dsp(ctx); + gen_helper_dmadd(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DMADDU: + check_dsp(ctx); + gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DMSUB: + check_dsp(ctx); + gen_helper_dmsub(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DMSUBU: + check_dsp(ctx); + gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPA_W_QH: + check_dsp_r2(ctx); + gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPAQ_S_W_QH: + check_dsp(ctx); + gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPAQ_SA_L_PW: + check_dsp(ctx); + gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPAU_H_OBL: + check_dsp(ctx); + gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPAU_H_OBR: + check_dsp(ctx); + gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPS_W_QH: + check_dsp_r2(ctx); + gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPSQ_S_W_QH: + check_dsp(ctx); + gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPSQ_SA_L_PW: + check_dsp(ctx); + gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPSU_H_OBL: + check_dsp(ctx); + gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPSU_H_OBR: + check_dsp(ctx); + gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_L_PWL: + check_dsp(ctx); + gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_L_PWR: + check_dsp(ctx); + gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_W_QHLL: + check_dsp(ctx); + gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_SA_W_QHLL: + check_dsp(ctx); + gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_W_QHLR: + check_dsp(ctx); + gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_SA_W_QHLR: + check_dsp(ctx); + gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_W_QHRL: + check_dsp(ctx); + gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_SA_W_QHRL: + check_dsp(ctx); + gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_W_QHRR: + check_dsp(ctx); + gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_SA_W_QHRR: + check_dsp(ctx); + gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MULSAQ_S_L_PW: + check_dsp(ctx); + gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MULSAQ_S_W_QH: + check_dsp(ctx); + gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env); + break; + } + } + break; +#endif + case OPC_ADDU_QB_DSP: + switch (op2) { + case OPC_MULEU_S_PH_QBL: + check_dsp(ctx); + gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEU_S_PH_QBR: + check_dsp(ctx); + gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_RS_PH: + check_dsp(ctx); + gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEQ_S_W_PHL: + check_dsp(ctx); + gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEQ_S_W_PHR: + check_dsp(ctx); + gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_S_PH: + check_dsp_r2(ctx); + gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_ADDU_OB_DSP: + switch (op2) { + case OPC_MULEQ_S_PW_QHL: + check_dsp(ctx); + gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEQ_S_PW_QHR: + check_dsp(ctx); + gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEU_S_QH_OBL: + check_dsp(ctx); + gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEU_S_QH_OBR: + check_dsp(ctx); + gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_RS_QH: + check_dsp(ctx); + gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#endif + } + + tcg_temp_free_i32(t0); + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); +} + +static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, + int ret, int val) +{ + int16_t imm; + TCGv t0; + TCGv val_t; + + if (ret == 0) { + /* Treat as NOP. */ + return; + } + + t0 = tcg_temp_new(); + val_t = tcg_temp_new(); + gen_load_gpr(val_t, val); + + switch (op1) { + case OPC_ABSQ_S_PH_DSP: + switch (op2) { + case OPC_BITREV: + check_dsp(ctx); + gen_helper_bitrev(cpu_gpr[ret], val_t); + break; + case OPC_REPL_QB: + check_dsp(ctx); + { + target_long result; + imm = (ctx->opcode >> 16) & 0xFF; + result = (uint32_t)imm << 24 | + (uint32_t)imm << 16 | + (uint32_t)imm << 8 | + (uint32_t)imm; + result = (int32_t)result; + tcg_gen_movi_tl(cpu_gpr[ret], result); + } + break; + case OPC_REPLV_QB: + check_dsp(ctx); + tcg_gen_ext8u_tl(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 8); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + break; + case OPC_REPL_PH: + check_dsp(ctx); + { + imm = (ctx->opcode >> 16) & 0x03FF; + imm = (int16_t)(imm << 6) >> 6; + tcg_gen_movi_tl(cpu_gpr[ret], \ + (target_long)((int32_t)imm << 16 | \ + (uint16_t)imm)); + } + break; + case OPC_REPLV_PH: + check_dsp(ctx); + tcg_gen_ext16u_tl(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_ABSQ_S_QH_DSP: + switch (op2) { + case OPC_REPL_OB: + check_dsp(ctx); + { + target_long temp; + + imm = (ctx->opcode >> 16) & 0xFF; + temp = ((uint64_t)imm << 8) | (uint64_t)imm; + temp = (temp << 16) | temp; + temp = (temp << 32) | temp; + tcg_gen_movi_tl(cpu_gpr[ret], temp); + break; + } + case OPC_REPL_PW: + check_dsp(ctx); + { + target_long temp; + + imm = (ctx->opcode >> 16) & 0x03FF; + imm = (int16_t)(imm << 6) >> 6; + temp = ((target_long)imm << 32) \ + | ((target_long)imm & 0xFFFFFFFF); + tcg_gen_movi_tl(cpu_gpr[ret], temp); + break; + } + case OPC_REPL_QH: + check_dsp(ctx); + { + target_long temp; + + imm = (ctx->opcode >> 16) & 0x03FF; + imm = (int16_t)(imm << 6) >> 6; + + temp = ((uint64_t)(uint16_t)imm << 48) | + ((uint64_t)(uint16_t)imm << 32) | + ((uint64_t)(uint16_t)imm << 16) | + (uint64_t)(uint16_t)imm; + tcg_gen_movi_tl(cpu_gpr[ret], temp); + break; + } + case OPC_REPLV_OB: + check_dsp(ctx); + tcg_gen_ext8u_tl(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 8); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + break; + case OPC_REPLV_PW: + check_dsp(ctx); + tcg_gen_ext32u_i64(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + break; + case OPC_REPLV_QH: + check_dsp(ctx); + tcg_gen_ext16u_tl(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + break; + } + break; +#endif + } + tcg_temp_free(t0); + tcg_temp_free(val_t); +} + +static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx, + uint32_t op1, uint32_t op2, + int ret, int v1, int v2, int check_ret) +{ + TCGv t1; + TCGv v1_t; + TCGv v2_t; + + if ((ret == 0) && (check_ret == 1)) { + /* Treat as NOP. */ + return; + } + + t1 = tcg_temp_new(); + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (op1) { + case OPC_CMPU_EQ_QB_DSP: + switch (op2) { + case OPC_CMPU_EQ_QB: + check_dsp(ctx); + gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env); + break; + case OPC_CMPU_LT_QB: + check_dsp(ctx); + gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env); + break; + case OPC_CMPU_LE_QB: + check_dsp(ctx); + gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env); + break; + case OPC_CMPGU_EQ_QB: + check_dsp(ctx); + gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGU_LT_QB: + check_dsp(ctx); + gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGU_LE_QB: + check_dsp(ctx); + gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGDU_EQ_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t); + tcg_gen_mov_tl(cpu_gpr[ret], t1); + tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); + tcg_gen_shli_tl(t1, t1, 24); + tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); + break; + case OPC_CMPGDU_LT_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t); + tcg_gen_mov_tl(cpu_gpr[ret], t1); + tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); + tcg_gen_shli_tl(t1, t1, 24); + tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); + break; + case OPC_CMPGDU_LE_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_le_qb(t1, v1_t, v2_t); + tcg_gen_mov_tl(cpu_gpr[ret], t1); + tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); + tcg_gen_shli_tl(t1, t1, 24); + tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); + break; + case OPC_CMP_EQ_PH: + check_dsp(ctx); + gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LT_PH: + check_dsp(ctx); + gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LE_PH: + check_dsp(ctx); + gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env); + break; + case OPC_PICK_QB: + check_dsp(ctx); + gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PICK_PH: + check_dsp(ctx); + gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PACKRL_PH: + check_dsp(ctx); + gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_CMPU_EQ_OB_DSP: + switch (op2) { + case OPC_CMP_EQ_PW: + check_dsp(ctx); + gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LT_PW: + check_dsp(ctx); + gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LE_PW: + check_dsp(ctx); + gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_EQ_QH: + check_dsp(ctx); + gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LT_QH: + check_dsp(ctx); + gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LE_QH: + check_dsp(ctx); + gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env); + break; + case OPC_CMPGDU_EQ_OB: + check_dsp_r2(ctx); + gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_CMPGDU_LT_OB: + check_dsp_r2(ctx); + gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_CMPGDU_LE_OB: + check_dsp_r2(ctx); + gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_CMPGU_EQ_OB: + check_dsp(ctx); + gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGU_LT_OB: + check_dsp(ctx); + gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGU_LE_OB: + check_dsp(ctx); + gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPU_EQ_OB: + check_dsp(ctx); + gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env); + break; + case OPC_CMPU_LT_OB: + check_dsp(ctx); + gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env); + break; + case OPC_CMPU_LE_OB: + check_dsp(ctx); + gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env); + break; + case OPC_PACKRL_PW: + check_dsp(ctx); + gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PICK_OB: + check_dsp(ctx); + gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PICK_PW: + check_dsp(ctx); + gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PICK_QH: + check_dsp(ctx); + gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#endif + } + + tcg_temp_free(t1); + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); +} + +static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx, + uint32_t op1, int rt, int rs, int sa) +{ + TCGv t0; + + check_dsp_r2(ctx); + + if (rt == 0) { + /* Treat as NOP. */ + return; + } + + t0 = tcg_temp_new(); + gen_load_gpr(t0, rs); + + switch (op1) { + case OPC_APPEND_DSP: + switch (MASK_APPEND(ctx->opcode)) { + case OPC_APPEND: + if (sa != 0) { + tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa); + } + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + break; + case OPC_PREPEND: + if (sa != 0) { + tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]); + tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa); + tcg_gen_shli_tl(t0, t0, 32 - sa); + tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0); + } + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + break; + case OPC_BALIGN: + sa &= 3; + if (sa != 0 && sa != 2) { + tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_shri_tl(t0, t0, 8 * (4 - sa)); + tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0); + } + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + break; + default: /* Invalid */ + MIPS_INVAL("MASK APPEND"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_DAPPEND_DSP: + switch (MASK_DAPPEND(ctx->opcode)) { + case OPC_DAPPEND: + if (sa != 0) { + tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa); + } + break; + case OPC_PREPENDD: + tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa); + tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa)); + tcg_gen_or_tl(cpu_gpr[rt], t0, t0); + break; + case OPC_PREPENDW: + if (sa != 0) { + tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa); + tcg_gen_shli_tl(t0, t0, 64 - sa); + tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0); + } + break; + case OPC_DBALIGN: + sa &= 7; + if (sa != 0 && sa != 2 && sa != 4) { + tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa); + tcg_gen_shri_tl(t0, t0, 8 * (8 - sa)); + tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0); + } + break; + default: /* Invalid */ + MIPS_INVAL("MASK DAPPEND"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; +#endif + } + tcg_temp_free(t0); +} + +static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, + int ret, int v1, int v2, int check_ret) + +{ + TCGv t0; + TCGv t1; + TCGv v1_t; + TCGv v2_t; + int16_t imm; + + if ((ret == 0) && (check_ret == 1)) { + /* Treat as NOP. */ + return; + } + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (op1) { + case OPC_EXTR_W_DSP: + check_dsp(ctx); + switch (op2) { + case OPC_EXTR_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTR_R_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTR_RS_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTR_S_H: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTRV_S_H: + tcg_gen_movi_tl(t0, v2); + gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTRV_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTRV_R_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTRV_RS_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTP: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTPV: + tcg_gen_movi_tl(t0, v2); + gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTPDP: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTPDPV: + tcg_gen_movi_tl(t0, v2); + gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_SHILO: + imm = (ctx->opcode >> 20) & 0x3F; + tcg_gen_movi_tl(t0, ret); + tcg_gen_movi_tl(t1, imm); + gen_helper_shilo(t0, t1, cpu_env); + break; + case OPC_SHILOV: + tcg_gen_movi_tl(t0, ret); + gen_helper_shilo(t0, v1_t, cpu_env); + break; + case OPC_MTHLIP: + tcg_gen_movi_tl(t0, ret); + gen_helper_mthlip(t0, v1_t, cpu_env); + break; + case OPC_WRDSP: + imm = (ctx->opcode >> 11) & 0x3FF; + tcg_gen_movi_tl(t0, imm); + gen_helper_wrdsp(v1_t, t0, cpu_env); + break; + case OPC_RDDSP: + imm = (ctx->opcode >> 16) & 0x03FF; + tcg_gen_movi_tl(t0, imm); + gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_DEXTR_W_DSP: + check_dsp(ctx); + switch (op2) { + case OPC_DMTHLIP: + tcg_gen_movi_tl(t0, ret); + gen_helper_dmthlip(v1_t, t0, cpu_env); + break; + case OPC_DSHILO: + { + int shift = (ctx->opcode >> 19) & 0x7F; + int ac = (ctx->opcode >> 11) & 0x03; + tcg_gen_movi_tl(t0, shift); + tcg_gen_movi_tl(t1, ac); + gen_helper_dshilo(t0, t1, cpu_env); + break; + } + case OPC_DSHILOV: + { + int ac = (ctx->opcode >> 11) & 0x03; + tcg_gen_movi_tl(t0, ac); + gen_helper_dshilo(v1_t, t0, cpu_env); + break; + } + case OPC_DEXTP: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + + gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTPV: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTPDP: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTPDPV: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTR_L: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_R_L: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_RS_L: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_R_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_RS_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_S_H: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTRV_S_H: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTRV_L: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_R_L: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_RS_L: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_R_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_RS_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + } + break; +#endif + } + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); +} From patchwork Mon Nov 23 20:44:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926757 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 18A6CC2D0E4 for ; Mon, 23 Nov 2020 21:05:23 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7826E206B5 for ; Mon, 23 Nov 2020 21:05:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="uJjuyRPM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7826E206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48490 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ1V-0003XJ-8V for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:05:21 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46592) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIiV-0001Zg-Hv for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:43 -0500 Received: from mail-wr1-x441.google.com ([2a00:1450:4864:20::441]:36852) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIiT-0001Sj-N7 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:43 -0500 Received: by mail-wr1-x441.google.com with SMTP id z7so4295123wrn.3 for ; Mon, 23 Nov 2020 12:45:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SBIr5PT79YnRUqQgQlYRdY4YoLLnHZdi2jwadwiH97E=; b=uJjuyRPMhlFDcqqjqSZrLyWj4Np4Ae9X38Uq5vBjacQfDaUNgot4dslBKIRkhectFE XR37hbQgJqa/GBq8ag66LSWSFHvjlqhVD/dwOTHs2nUJcTC1vH5nNvG/LIrq4Qz2Xyip JZ7Eofuy6wlSppwbFxX7fF77CUkwTfiKC9F1DHCPBHxE741JFI7levdEI2kJE7W+zYVS jumduxhfnSNtTrw8eg7Qh4HNGesaplBrGQlUpPFxowMRPzGa8Qrt/8iTwWCkyTm55j6I Y2V9U1Qm8IpPt3ODD4ftK660jlswS1j0g/uwIMIrQZGttHl4x74XR6/lye24cdJI3m4p FSmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=SBIr5PT79YnRUqQgQlYRdY4YoLLnHZdi2jwadwiH97E=; b=IktaRtyYDMTbrl8bDq54mBSfivXsdHgM2Zy0VFNOnHqBRS5RPlZ6vhq9d8alViXNt4 cJI7crAcRYjlmKjvyWdjjG3wfUnJGvpNVutqkWksyyaULyt9HPdTaIbge0qq9nm+KkuM eLsKi6zDPZjvNtYweF8etrFb1bOOIuKLSaFJqmN3HVhL8OT7cdvRpFbidmXtSIm3TWX3 1XThLvz5XHQcTYo3+E7cTVLr9kfPryXDAVQuAtADfrNluWpCx4foW1w1Kn9oh18el7E6 PdfR02TnqwCDHLJAUOhDyVu5VCdBgaHzGh5dfVN6t+7rqnQFhLeJqVetsZr11YTv0LgR P6QA== X-Gm-Message-State: AOAM533YOURif9mGe9/pYjG8qkxehUITmv3y+IWSmdjNkKwNWUr0GKJY ggmIlwzLkVdEQXAsP2teNl462RA2x8Y= X-Google-Smtp-Source: ABdhPJx1CGPcw8LNQycD3mmwdTWHTs/Mqn7cF8KhqbBFwJCIPHfQiVbiXsG+nkYa3fX0VhyLDEaQUw== X-Received: by 2002:a5d:4e4c:: with SMTP id r12mr1551574wrt.348.1606164340092; Mon, 23 Nov 2020 12:45:40 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id a144sm883581wmd.47.2020.11.23.12.45.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:39 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 10/28] target/mips: Extract Multi-Threading helper definitions Date: Mon, 23 Nov 2020 21:44:30 +0100 Message-Id: <20201123204448.3260804-11-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::441; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x441.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 'MIPS MT' is defined as a Module by MIPS. Extract the helper definitions to 'mod-mt_helper.h.inc'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-9-f4bug@amsat.org> --- target/mips/helper.h | 23 +-------------------- target/mips/mod-mt_helper.h.inc | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 target/mips/mod-mt_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index 82f40c3b9bc..18366bc0345 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -179,25 +179,6 @@ DEF_HELPER_2(dmtc0_entrylo0, void, env, i64) DEF_HELPER_2(dmtc0_entrylo1, void, env, i64) #endif -/* MIPS MT functions */ -DEF_HELPER_2(mftgpr, tl, env, i32) -DEF_HELPER_2(mftlo, tl, env, i32) -DEF_HELPER_2(mfthi, tl, env, i32) -DEF_HELPER_2(mftacx, tl, env, i32) -DEF_HELPER_1(mftdsp, tl, env) -DEF_HELPER_3(mttgpr, void, env, tl, i32) -DEF_HELPER_3(mttlo, void, env, tl, i32) -DEF_HELPER_3(mtthi, void, env, tl, i32) -DEF_HELPER_3(mttacx, void, env, tl, i32) -DEF_HELPER_2(mttdsp, void, env, tl) -DEF_HELPER_0(dmt, tl) -DEF_HELPER_0(emt, tl) -DEF_HELPER_1(dvpe, tl, env) -DEF_HELPER_1(evpe, tl, env) - -/* R6 Multi-threading */ -DEF_HELPER_1(dvp, tl, env) -DEF_HELPER_1(evp, tl, env) #endif /* !CONFIG_USER_ONLY */ /* microMIPS functions */ @@ -208,9 +189,6 @@ DEF_HELPER_4(ldm, void, env, tl, tl, i32) DEF_HELPER_4(sdm, void, env, tl, tl, i32) #endif -DEF_HELPER_2(fork, void, tl, tl) -DEF_HELPER_2(yield, tl, env, tl) - /* CP1 functions */ DEF_HELPER_2(cfc1, tl, env, i32) DEF_HELPER_4(ctc1, void, env, tl, i32, i32) @@ -451,3 +429,4 @@ DEF_HELPER_3(cache, void, env, tl, i32) #include "mod-dsp_helper.h.inc" #include "mod-msa_helper.h.inc" +#include "mod-mt_helper.h.inc" diff --git a/target/mips/mod-mt_helper.h.inc b/target/mips/mod-mt_helper.h.inc new file mode 100644 index 00000000000..0db58e2a780 --- /dev/null +++ b/target/mips/mod-mt_helper.h.inc @@ -0,0 +1,36 @@ +/* + * MIPS Multi-Threading helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef CONFIG_USER_ONLY +DEF_HELPER_2(mftgpr, tl, env, i32) +DEF_HELPER_2(mftlo, tl, env, i32) +DEF_HELPER_2(mfthi, tl, env, i32) +DEF_HELPER_2(mftacx, tl, env, i32) +DEF_HELPER_1(mftdsp, tl, env) +DEF_HELPER_3(mttgpr, void, env, tl, i32) +DEF_HELPER_3(mttlo, void, env, tl, i32) +DEF_HELPER_3(mtthi, void, env, tl, i32) +DEF_HELPER_3(mttacx, void, env, tl, i32) +DEF_HELPER_2(mttdsp, void, env, tl) + +DEF_HELPER_0(dmt, tl) +DEF_HELPER_0(emt, tl) + +DEF_HELPER_1(dvpe, tl, env) +DEF_HELPER_1(evpe, tl, env) + +/* R6 Multi-threading */ +DEF_HELPER_1(dvp, tl, env) +DEF_HELPER_1(evp, tl, env) +#endif /* !CONFIG_USER_ONLY */ + +DEF_HELPER_2(fork, void, tl, tl) +DEF_HELPER_2(yield, tl, env, tl) From patchwork Mon Nov 23 20:44:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926733 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 B31DCC388F9 for ; Mon, 23 Nov 2020 20:48:57 +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 CB33020706 for ; Mon, 23 Nov 2020 20:48:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="oDeTtFds" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CB33020706 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:38862 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khIlb-0003jn-NL for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 15:48:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46638) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIid-0001o8-Pk for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:51 -0500 Received: from mail-wr1-x430.google.com ([2a00:1450:4864:20::430]:35088) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIiZ-0001Uu-LT for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:51 -0500 Received: by mail-wr1-x430.google.com with SMTP id r3so1814296wrt.2 for ; Mon, 23 Nov 2020 12:45:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nzyiJWudq9IOxyo1aoU3W3KB6JYoDKj4EfMyFYKPhtQ=; b=oDeTtFdsx60yMwLu9gMA58i02cRh8K+aH7xzWrsthM3NWmk1ZOwZlUZLn8moSSsIGB 69F7miQD3mw8tbFnLAcRze5stsb3X3SnlnstPiEp3VUWH8boFGf26F4V1dq2eFj/5RwR kMhQfBWQTIRawF+zs4A8UO3HrMMpkUp6sFOxjZiEcNvVw4bgzO7w8A6sSiP/370MWthR Vhua81vEEZZAkFH+exL1QQuYlkpFODHB5BOD5dad5DkwE1ydLU8bxSKsitACf3+CFHDg JPXO2/n+FYQw6T34R0S5cjzyOQ2JuTjdgV8uzLWs1ybxEGSuh/2jxzN2pldHMYsJGLmR 2Aew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=nzyiJWudq9IOxyo1aoU3W3KB6JYoDKj4EfMyFYKPhtQ=; b=R6u9yUaUCftzyX+Sgza2j69lk6pBe1rd6qSgPVbSObNuILSM1JKOatfRUvUb2sTLpV jNPetH9ciG46JDweJ5QxpR79WvE3h3eBrbDdOx6R17fQ8/UvCjrSmqUXGdmOSniNR7k8 QH3E90l6O5oOvCORnUiDl/ywrHQo4ibPOepgEqlDeUN9wUxyRRL7UcD0l6e/6rGQHspe K6CTtKtycsxOw+GaSujGy3eLh8bLzaiAtyMEkjXQ0NrZJSmkLTL2LTFfifH9gLhH7qdx mPXj3nFt7d9FB6rl/aK93k9+2R8F5nzBAbnWatps0IvXNHgEJGlzEfoiB00ZmBbpZT1V W3xg== X-Gm-Message-State: AOAM53050dZmOKFm0PCtvh+t+5B1S5/fEbRuRVySAUfUG3YkJwaEqBYM y06orOZHSHhfUoC1iAAGhZGBoSMjEo0= X-Google-Smtp-Source: ABdhPJzNKTfWRMXbdG45y7Lqcrw7McKJt9U0bokrqu4qdXwKxJP7T3NYY2RAO3ECV2LNkeKKViVT+w== X-Received: by 2002:a5d:51c2:: with SMTP id n2mr1577169wrv.326.1606164345033; Mon, 23 Nov 2020 12:45:45 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id y11sm770706wmj.36.2020.11.23.12.45.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:44 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 11/28] target/mips: Extract Code Compaction ASE translation routines Date: Mon, 23 Nov 2020 21:44:31 +0100 Message-Id: <20201123204448.3260804-12-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::430; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x430.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract 1200 lines from the huge translate.c to a new file, 'ase-mips16e_translate.c.inc'. As there are too many inter- dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-10-f4bug@amsat.org> --- target/mips/translate.c | 1161 +--------------------- target/mips/ase-mips16e_translate.c.inc | 1170 +++++++++++++++++++++++ 2 files changed, 1171 insertions(+), 1160 deletions(-) create mode 100644 target/mips/ase-mips16e_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index d1e154b1f79..1a329bcdede 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -13131,1167 +13131,8 @@ out: } /* ISA extensions (ASEs) */ -/* MIPS16 extension to MIPS32 */ -/* MIPS16 major opcodes */ -enum { - M16_OPC_ADDIUSP = 0x00, - M16_OPC_ADDIUPC = 0x01, - M16_OPC_B = 0x02, - M16_OPC_JAL = 0x03, - M16_OPC_BEQZ = 0x04, - M16_OPC_BNEQZ = 0x05, - M16_OPC_SHIFT = 0x06, - M16_OPC_LD = 0x07, - M16_OPC_RRIA = 0x08, - M16_OPC_ADDIU8 = 0x09, - M16_OPC_SLTI = 0x0a, - M16_OPC_SLTIU = 0x0b, - M16_OPC_I8 = 0x0c, - M16_OPC_LI = 0x0d, - M16_OPC_CMPI = 0x0e, - M16_OPC_SD = 0x0f, - M16_OPC_LB = 0x10, - M16_OPC_LH = 0x11, - M16_OPC_LWSP = 0x12, - M16_OPC_LW = 0x13, - M16_OPC_LBU = 0x14, - M16_OPC_LHU = 0x15, - M16_OPC_LWPC = 0x16, - M16_OPC_LWU = 0x17, - M16_OPC_SB = 0x18, - M16_OPC_SH = 0x19, - M16_OPC_SWSP = 0x1a, - M16_OPC_SW = 0x1b, - M16_OPC_RRR = 0x1c, - M16_OPC_RR = 0x1d, - M16_OPC_EXTEND = 0x1e, - M16_OPC_I64 = 0x1f -}; - -/* I8 funct field */ -enum { - I8_BTEQZ = 0x0, - I8_BTNEZ = 0x1, - I8_SWRASP = 0x2, - I8_ADJSP = 0x3, - I8_SVRS = 0x4, - I8_MOV32R = 0x5, - I8_MOVR32 = 0x7 -}; - -/* RRR f field */ -enum { - RRR_DADDU = 0x0, - RRR_ADDU = 0x1, - RRR_DSUBU = 0x2, - RRR_SUBU = 0x3 -}; - -/* RR funct field */ -enum { - RR_JR = 0x00, - RR_SDBBP = 0x01, - RR_SLT = 0x02, - RR_SLTU = 0x03, - RR_SLLV = 0x04, - RR_BREAK = 0x05, - RR_SRLV = 0x06, - RR_SRAV = 0x07, - RR_DSRL = 0x08, - RR_CMP = 0x0a, - RR_NEG = 0x0b, - RR_AND = 0x0c, - RR_OR = 0x0d, - RR_XOR = 0x0e, - RR_NOT = 0x0f, - RR_MFHI = 0x10, - RR_CNVT = 0x11, - RR_MFLO = 0x12, - RR_DSRA = 0x13, - RR_DSLLV = 0x14, - RR_DSRLV = 0x16, - RR_DSRAV = 0x17, - RR_MULT = 0x18, - RR_MULTU = 0x19, - RR_DIV = 0x1a, - RR_DIVU = 0x1b, - RR_DMULT = 0x1c, - RR_DMULTU = 0x1d, - RR_DDIV = 0x1e, - RR_DDIVU = 0x1f -}; - -/* I64 funct field */ -enum { - I64_LDSP = 0x0, - I64_SDSP = 0x1, - I64_SDRASP = 0x2, - I64_DADJSP = 0x3, - I64_LDPC = 0x4, - I64_DADDIU5 = 0x5, - I64_DADDIUPC = 0x6, - I64_DADDIUSP = 0x7 -}; - -/* RR ry field for CNVT */ -enum { - RR_RY_CNVT_ZEB = 0x0, - RR_RY_CNVT_ZEH = 0x1, - RR_RY_CNVT_ZEW = 0x2, - RR_RY_CNVT_SEB = 0x4, - RR_RY_CNVT_SEH = 0x5, - RR_RY_CNVT_SEW = 0x6, -}; - -static int xlat(int r) -{ - static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; - - return map[r]; -} - -static void gen_mips16_save(DisasContext *ctx, - int xsregs, int aregs, - int do_ra, int do_s0, int do_s1, - int framesize) -{ - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - TCGv t2 = tcg_temp_new(); - int args, astatic; - - switch (aregs) { - case 0: - case 1: - case 2: - case 3: - case 11: - args = 0; - break; - case 4: - case 5: - case 6: - case 7: - args = 1; - break; - case 8: - case 9: - case 10: - args = 2; - break; - case 12: - case 13: - args = 3; - break; - case 14: - args = 4; - break; - default: - generate_exception_end(ctx, EXCP_RI); - return; - } - - switch (args) { - case 4: - gen_base_offset_addr(ctx, t0, 29, 12); - gen_load_gpr(t1, 7); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - /* Fall through */ - case 3: - gen_base_offset_addr(ctx, t0, 29, 8); - gen_load_gpr(t1, 6); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - /* Fall through */ - case 2: - gen_base_offset_addr(ctx, t0, 29, 4); - gen_load_gpr(t1, 5); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - /* Fall through */ - case 1: - gen_base_offset_addr(ctx, t0, 29, 0); - gen_load_gpr(t1, 4); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - } - - gen_load_gpr(t0, 29); - -#define DECR_AND_STORE(reg) do { \ - tcg_gen_movi_tl(t2, -4); \ - gen_op_addr_add(ctx, t0, t0, t2); \ - gen_load_gpr(t1, reg); \ - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \ - } while (0) - - if (do_ra) { - DECR_AND_STORE(31); - } - - switch (xsregs) { - case 7: - DECR_AND_STORE(30); - /* Fall through */ - case 6: - DECR_AND_STORE(23); - /* Fall through */ - case 5: - DECR_AND_STORE(22); - /* Fall through */ - case 4: - DECR_AND_STORE(21); - /* Fall through */ - case 3: - DECR_AND_STORE(20); - /* Fall through */ - case 2: - DECR_AND_STORE(19); - /* Fall through */ - case 1: - DECR_AND_STORE(18); - } - - if (do_s1) { - DECR_AND_STORE(17); - } - if (do_s0) { - DECR_AND_STORE(16); - } - - switch (aregs) { - case 0: - case 4: - case 8: - case 12: - case 14: - astatic = 0; - break; - case 1: - case 5: - case 9: - case 13: - astatic = 1; - break; - case 2: - case 6: - case 10: - astatic = 2; - break; - case 3: - case 7: - astatic = 3; - break; - case 11: - astatic = 4; - break; - default: - generate_exception_end(ctx, EXCP_RI); - return; - } - - if (astatic > 0) { - DECR_AND_STORE(7); - if (astatic > 1) { - DECR_AND_STORE(6); - if (astatic > 2) { - DECR_AND_STORE(5); - if (astatic > 3) { - DECR_AND_STORE(4); - } - } - } - } -#undef DECR_AND_STORE - - tcg_gen_movi_tl(t2, -framesize); - gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2); - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); -} - -static void gen_mips16_restore(DisasContext *ctx, - int xsregs, int aregs, - int do_ra, int do_s0, int do_s1, - int framesize) -{ - int astatic; - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - TCGv t2 = tcg_temp_new(); - - tcg_gen_movi_tl(t2, framesize); - gen_op_addr_add(ctx, t0, cpu_gpr[29], t2); - -#define DECR_AND_LOAD(reg) do { \ - tcg_gen_movi_tl(t2, -4); \ - gen_op_addr_add(ctx, t0, t0, t2); \ - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \ - gen_store_gpr(t1, reg); \ - } while (0) - - if (do_ra) { - DECR_AND_LOAD(31); - } - - switch (xsregs) { - case 7: - DECR_AND_LOAD(30); - /* Fall through */ - case 6: - DECR_AND_LOAD(23); - /* Fall through */ - case 5: - DECR_AND_LOAD(22); - /* Fall through */ - case 4: - DECR_AND_LOAD(21); - /* Fall through */ - case 3: - DECR_AND_LOAD(20); - /* Fall through */ - case 2: - DECR_AND_LOAD(19); - /* Fall through */ - case 1: - DECR_AND_LOAD(18); - } - - if (do_s1) { - DECR_AND_LOAD(17); - } - if (do_s0) { - DECR_AND_LOAD(16); - } - - switch (aregs) { - case 0: - case 4: - case 8: - case 12: - case 14: - astatic = 0; - break; - case 1: - case 5: - case 9: - case 13: - astatic = 1; - break; - case 2: - case 6: - case 10: - astatic = 2; - break; - case 3: - case 7: - astatic = 3; - break; - case 11: - astatic = 4; - break; - default: - generate_exception_end(ctx, EXCP_RI); - return; - } - - if (astatic > 0) { - DECR_AND_LOAD(7); - if (astatic > 1) { - DECR_AND_LOAD(6); - if (astatic > 2) { - DECR_AND_LOAD(5); - if (astatic > 3) { - DECR_AND_LOAD(4); - } - } - } - } -#undef DECR_AND_LOAD - - tcg_gen_movi_tl(t2, framesize); - gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2); - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); -} - -static void gen_addiupc(DisasContext *ctx, int rx, int imm, - int is_64_bit, int extended) -{ - TCGv t0; - - if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { - generate_exception_end(ctx, EXCP_RI); - return; - } - - t0 = tcg_temp_new(); - - tcg_gen_movi_tl(t0, pc_relative_pc(ctx)); - tcg_gen_addi_tl(cpu_gpr[rx], t0, imm); - if (!is_64_bit) { - tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); - } - - tcg_temp_free(t0); -} - -static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base, - int16_t offset) -{ - TCGv_i32 t0 = tcg_const_i32(op); - TCGv t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t1, base, offset); - gen_helper_cache(cpu_env, t1, t0); -} - -#if defined(TARGET_MIPS64) -static void decode_i64_mips16(DisasContext *ctx, - int ry, int funct, int16_t offset, - int extended) -{ - switch (funct) { - case I64_LDSP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset = extended ? offset : offset << 3; - gen_ld(ctx, OPC_LD, ry, 29, offset); - break; - case I64_SDSP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset = extended ? offset : offset << 3; - gen_st(ctx, OPC_SD, ry, 29, offset); - break; - case I64_SDRASP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset = extended ? offset : (ctx->opcode & 0xff) << 3; - gen_st(ctx, OPC_SD, 31, 29, offset); - break; - case I64_DADJSP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset = extended ? offset : ((int8_t)ctx->opcode) << 3; - gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset); - break; - case I64_LDPC: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { - generate_exception_end(ctx, EXCP_RI); - } else { - offset = extended ? offset : offset << 3; - gen_ld(ctx, OPC_LDPC, ry, 0, offset); - } - break; - case I64_DADDIU5: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset = extended ? offset : ((int8_t)(offset << 3)) >> 3; - gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset); - break; - case I64_DADDIUPC: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset = extended ? offset : offset << 2; - gen_addiupc(ctx, ry, offset, 1, extended); - break; - case I64_DADDIUSP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset = extended ? offset : offset << 2; - gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset); - break; - } -} -#endif - -static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx) -{ - int extend = cpu_lduw_code(env, ctx->base.pc_next + 2); - int op, rx, ry, funct, sa; - int16_t imm, offset; - - ctx->opcode = (ctx->opcode << 16) | extend; - op = (ctx->opcode >> 11) & 0x1f; - sa = (ctx->opcode >> 22) & 0x1f; - funct = (ctx->opcode >> 8) & 0x7; - rx = xlat((ctx->opcode >> 8) & 0x7); - ry = xlat((ctx->opcode >> 5) & 0x7); - offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11 - | ((ctx->opcode >> 21) & 0x3f) << 5 - | (ctx->opcode & 0x1f)); - - /* - * The extended opcodes cleverly reuse the opcodes from their 16-bit - * counterparts. - */ - switch (op) { - case M16_OPC_ADDIUSP: - gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); - break; - case M16_OPC_ADDIUPC: - gen_addiupc(ctx, rx, imm, 0, 1); - break; - case M16_OPC_B: - gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_BEQZ: - gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_BNEQZ: - gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_SHIFT: - switch (ctx->opcode & 0x3) { - case 0x0: - gen_shift_imm(ctx, OPC_SLL, rx, ry, sa); - break; - case 0x1: -#if defined(TARGET_MIPS64) - check_mips_64(ctx); - gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); -#else - generate_exception_end(ctx, EXCP_RI); -#endif - break; - case 0x2: - gen_shift_imm(ctx, OPC_SRL, rx, ry, sa); - break; - case 0x3: - gen_shift_imm(ctx, OPC_SRA, rx, ry, sa); - break; - } - break; -#if defined(TARGET_MIPS64) - case M16_OPC_LD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_ld(ctx, OPC_LD, ry, rx, offset); - break; -#endif - case M16_OPC_RRIA: - imm = ctx->opcode & 0xf; - imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4; - imm = imm | ((ctx->opcode >> 16) & 0xf) << 11; - imm = (int16_t) (imm << 1) >> 1; - if ((ctx->opcode >> 4) & 0x1) { -#if defined(TARGET_MIPS64) - check_mips_64(ctx); - gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); -#else - generate_exception_end(ctx, EXCP_RI); -#endif - } else { - gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); - } - break; - case M16_OPC_ADDIU8: - gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm); - break; - case M16_OPC_SLTI: - gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm); - break; - case M16_OPC_SLTIU: - gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm); - break; - case M16_OPC_I8: - switch (funct) { - case I8_BTEQZ: - gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0); - break; - case I8_BTNEZ: - gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0); - break; - case I8_SWRASP: - gen_st(ctx, OPC_SW, 31, 29, imm); - break; - case I8_ADJSP: - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm); - break; - case I8_SVRS: - check_insn(ctx, ISA_MIPS32); - { - int xsregs = (ctx->opcode >> 24) & 0x7; - int aregs = (ctx->opcode >> 16) & 0xf; - int do_ra = (ctx->opcode >> 6) & 0x1; - int do_s0 = (ctx->opcode >> 5) & 0x1; - int do_s1 = (ctx->opcode >> 4) & 0x1; - int framesize = (((ctx->opcode >> 20) & 0xf) << 4 - | (ctx->opcode & 0xf)) << 3; - - if (ctx->opcode & (1 << 7)) { - gen_mips16_save(ctx, xsregs, aregs, - do_ra, do_s0, do_s1, - framesize); - } else { - gen_mips16_restore(ctx, xsregs, aregs, - do_ra, do_s0, do_s1, - framesize); - } - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case M16_OPC_LI: - tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm); - break; - case M16_OPC_CMPI: - tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm); - break; -#if defined(TARGET_MIPS64) - case M16_OPC_SD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_st(ctx, OPC_SD, ry, rx, offset); - break; -#endif - case M16_OPC_LB: - gen_ld(ctx, OPC_LB, ry, rx, offset); - break; - case M16_OPC_LH: - gen_ld(ctx, OPC_LH, ry, rx, offset); - break; - case M16_OPC_LWSP: - gen_ld(ctx, OPC_LW, rx, 29, offset); - break; - case M16_OPC_LW: - gen_ld(ctx, OPC_LW, ry, rx, offset); - break; - case M16_OPC_LBU: - gen_ld(ctx, OPC_LBU, ry, rx, offset); - break; - case M16_OPC_LHU: - gen_ld(ctx, OPC_LHU, ry, rx, offset); - break; - case M16_OPC_LWPC: - gen_ld(ctx, OPC_LWPC, rx, 0, offset); - break; -#if defined(TARGET_MIPS64) - case M16_OPC_LWU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_ld(ctx, OPC_LWU, ry, rx, offset); - break; -#endif - case M16_OPC_SB: - gen_st(ctx, OPC_SB, ry, rx, offset); - break; - case M16_OPC_SH: - gen_st(ctx, OPC_SH, ry, rx, offset); - break; - case M16_OPC_SWSP: - gen_st(ctx, OPC_SW, rx, 29, offset); - break; - case M16_OPC_SW: - gen_st(ctx, OPC_SW, ry, rx, offset); - break; -#if defined(TARGET_MIPS64) - case M16_OPC_I64: - decode_i64_mips16(ctx, ry, funct, offset, 1); - break; -#endif - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - - return 4; -} - -static inline bool is_uhi(int sdbbp_code) -{ -#ifdef CONFIG_USER_ONLY - return false; -#else - return semihosting_enabled() && sdbbp_code == 1; -#endif -} - -#ifdef CONFIG_USER_ONLY -/* The above should dead-code away any calls to this..*/ -static inline void gen_helper_do_semihosting(void *env) -{ - g_assert_not_reached(); -} -#endif - -static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx) -{ - int rx, ry; - int sa; - int op, cnvt_op, op1, offset; - int funct; - int n_bytes; - - op = (ctx->opcode >> 11) & 0x1f; - sa = (ctx->opcode >> 2) & 0x7; - sa = sa == 0 ? 8 : sa; - rx = xlat((ctx->opcode >> 8) & 0x7); - cnvt_op = (ctx->opcode >> 5) & 0x7; - ry = xlat((ctx->opcode >> 5) & 0x7); - op1 = offset = ctx->opcode & 0x1f; - - n_bytes = 2; - - switch (op) { - case M16_OPC_ADDIUSP: - { - int16_t imm = ((uint8_t) ctx->opcode) << 2; - - gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); - } - break; - case M16_OPC_ADDIUPC: - gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0); - break; - case M16_OPC_B: - offset = (ctx->opcode & 0x7ff) << 1; - offset = (int16_t)(offset << 4) >> 4; - gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_JAL: - offset = cpu_lduw_code(env, ctx->base.pc_next + 2); - offset = (((ctx->opcode & 0x1f) << 21) - | ((ctx->opcode >> 5) & 0x1f) << 16 - | offset) << 2; - op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL; - gen_compute_branch(ctx, op, 4, rx, ry, offset, 2); - n_bytes = 4; - break; - case M16_OPC_BEQZ: - gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, - ((int8_t)ctx->opcode) << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_BNEQZ: - gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, - ((int8_t)ctx->opcode) << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_SHIFT: - switch (ctx->opcode & 0x3) { - case 0x0: - gen_shift_imm(ctx, OPC_SLL, rx, ry, sa); - break; - case 0x1: -#if defined(TARGET_MIPS64) - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); -#else - generate_exception_end(ctx, EXCP_RI); -#endif - break; - case 0x2: - gen_shift_imm(ctx, OPC_SRL, rx, ry, sa); - break; - case 0x3: - gen_shift_imm(ctx, OPC_SRA, rx, ry, sa); - break; - } - break; -#if defined(TARGET_MIPS64) - case M16_OPC_LD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_ld(ctx, OPC_LD, ry, rx, offset << 3); - break; -#endif - case M16_OPC_RRIA: - { - int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4; - - if ((ctx->opcode >> 4) & 1) { -#if defined(TARGET_MIPS64) - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); -#else - generate_exception_end(ctx, EXCP_RI); -#endif - } else { - gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); - } - } - break; - case M16_OPC_ADDIU8: - { - int16_t imm = (int8_t) ctx->opcode; - - gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm); - } - break; - case M16_OPC_SLTI: - { - int16_t imm = (uint8_t) ctx->opcode; - gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm); - } - break; - case M16_OPC_SLTIU: - { - int16_t imm = (uint8_t) ctx->opcode; - gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm); - } - break; - case M16_OPC_I8: - { - int reg32; - - funct = (ctx->opcode >> 8) & 0x7; - switch (funct) { - case I8_BTEQZ: - gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0, - ((int8_t)ctx->opcode) << 1, 0); - break; - case I8_BTNEZ: - gen_compute_branch(ctx, OPC_BNE, 2, 24, 0, - ((int8_t)ctx->opcode) << 1, 0); - break; - case I8_SWRASP: - gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2); - break; - case I8_ADJSP: - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, - ((int8_t)ctx->opcode) << 3); - break; - case I8_SVRS: - check_insn(ctx, ISA_MIPS32); - { - int do_ra = ctx->opcode & (1 << 6); - int do_s0 = ctx->opcode & (1 << 5); - int do_s1 = ctx->opcode & (1 << 4); - int framesize = ctx->opcode & 0xf; - - if (framesize == 0) { - framesize = 128; - } else { - framesize = framesize << 3; - } - - if (ctx->opcode & (1 << 7)) { - gen_mips16_save(ctx, 0, 0, - do_ra, do_s0, do_s1, framesize); - } else { - gen_mips16_restore(ctx, 0, 0, - do_ra, do_s0, do_s1, framesize); - } - } - break; - case I8_MOV32R: - { - int rz = xlat(ctx->opcode & 0x7); - - reg32 = (((ctx->opcode >> 3) & 0x3) << 3) | - ((ctx->opcode >> 5) & 0x7); - gen_arith(ctx, OPC_ADDU, reg32, rz, 0); - } - break; - case I8_MOVR32: - reg32 = ctx->opcode & 0x1f; - gen_arith(ctx, OPC_ADDU, ry, reg32, 0); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - } - break; - case M16_OPC_LI: - { - int16_t imm = (uint8_t) ctx->opcode; - - gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm); - } - break; - case M16_OPC_CMPI: - { - int16_t imm = (uint8_t) ctx->opcode; - gen_logic_imm(ctx, OPC_XORI, 24, rx, imm); - } - break; -#if defined(TARGET_MIPS64) - case M16_OPC_SD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_st(ctx, OPC_SD, ry, rx, offset << 3); - break; -#endif - case M16_OPC_LB: - gen_ld(ctx, OPC_LB, ry, rx, offset); - break; - case M16_OPC_LH: - gen_ld(ctx, OPC_LH, ry, rx, offset << 1); - break; - case M16_OPC_LWSP: - gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2); - break; - case M16_OPC_LW: - gen_ld(ctx, OPC_LW, ry, rx, offset << 2); - break; - case M16_OPC_LBU: - gen_ld(ctx, OPC_LBU, ry, rx, offset); - break; - case M16_OPC_LHU: - gen_ld(ctx, OPC_LHU, ry, rx, offset << 1); - break; - case M16_OPC_LWPC: - gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2); - break; -#if defined(TARGET_MIPS64) - case M16_OPC_LWU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_ld(ctx, OPC_LWU, ry, rx, offset << 2); - break; -#endif - case M16_OPC_SB: - gen_st(ctx, OPC_SB, ry, rx, offset); - break; - case M16_OPC_SH: - gen_st(ctx, OPC_SH, ry, rx, offset << 1); - break; - case M16_OPC_SWSP: - gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2); - break; - case M16_OPC_SW: - gen_st(ctx, OPC_SW, ry, rx, offset << 2); - break; - case M16_OPC_RRR: - { - int rz = xlat((ctx->opcode >> 2) & 0x7); - int mips32_op; - - switch (ctx->opcode & 0x3) { - case RRR_ADDU: - mips32_op = OPC_ADDU; - break; - case RRR_SUBU: - mips32_op = OPC_SUBU; - break; -#if defined(TARGET_MIPS64) - case RRR_DADDU: - mips32_op = OPC_DADDU; - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - break; - case RRR_DSUBU: - mips32_op = OPC_DSUBU; - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - break; -#endif - default: - generate_exception_end(ctx, EXCP_RI); - goto done; - } - - gen_arith(ctx, mips32_op, rz, rx, ry); - done: - ; - } - break; - case M16_OPC_RR: - switch (op1) { - case RR_JR: - { - int nd = (ctx->opcode >> 7) & 0x1; - int link = (ctx->opcode >> 6) & 0x1; - int ra = (ctx->opcode >> 5) & 0x1; - - if (nd) { - check_insn(ctx, ISA_MIPS32); - } - - if (link) { - op = OPC_JALR; - } else { - op = OPC_JR; - } - - gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0, - (nd ? 0 : 2)); - } - break; - case RR_SDBBP: - if (is_uhi(extract32(ctx->opcode, 5, 6))) { - gen_helper_do_semihosting(cpu_env); - } else { - /* - * XXX: not clear which exception should be raised - * when in debug mode... - */ - check_insn(ctx, ISA_MIPS32); - generate_exception_end(ctx, EXCP_DBp); - } - break; - case RR_SLT: - gen_slt(ctx, OPC_SLT, 24, rx, ry); - break; - case RR_SLTU: - gen_slt(ctx, OPC_SLTU, 24, rx, ry); - break; - case RR_BREAK: - generate_exception_end(ctx, EXCP_BREAK); - break; - case RR_SLLV: - gen_shift(ctx, OPC_SLLV, ry, rx, ry); - break; - case RR_SRLV: - gen_shift(ctx, OPC_SRLV, ry, rx, ry); - break; - case RR_SRAV: - gen_shift(ctx, OPC_SRAV, ry, rx, ry); - break; -#if defined(TARGET_MIPS64) - case RR_DSRL: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa); - break; -#endif - case RR_CMP: - gen_logic(ctx, OPC_XOR, 24, rx, ry); - break; - case RR_NEG: - gen_arith(ctx, OPC_SUBU, rx, 0, ry); - break; - case RR_AND: - gen_logic(ctx, OPC_AND, rx, rx, ry); - break; - case RR_OR: - gen_logic(ctx, OPC_OR, rx, rx, ry); - break; - case RR_XOR: - gen_logic(ctx, OPC_XOR, rx, rx, ry); - break; - case RR_NOT: - gen_logic(ctx, OPC_NOR, rx, ry, 0); - break; - case RR_MFHI: - gen_HILO(ctx, OPC_MFHI, 0, rx); - break; - case RR_CNVT: - check_insn(ctx, ISA_MIPS32); - switch (cnvt_op) { - case RR_RY_CNVT_ZEB: - tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; - case RR_RY_CNVT_ZEH: - tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; - case RR_RY_CNVT_SEB: - tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; - case RR_RY_CNVT_SEH: - tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; -#if defined(TARGET_MIPS64) - case RR_RY_CNVT_ZEW: - check_insn(ctx, ISA_MIPS64); - check_mips_64(ctx); - tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; - case RR_RY_CNVT_SEW: - check_insn(ctx, ISA_MIPS64); - check_mips_64(ctx); - tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; -#endif - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case RR_MFLO: - gen_HILO(ctx, OPC_MFLO, 0, rx); - break; -#if defined(TARGET_MIPS64) - case RR_DSRA: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa); - break; - case RR_DSLLV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift(ctx, OPC_DSLLV, ry, rx, ry); - break; - case RR_DSRLV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift(ctx, OPC_DSRLV, ry, rx, ry); - break; - case RR_DSRAV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift(ctx, OPC_DSRAV, ry, rx, ry); - break; -#endif - case RR_MULT: - gen_muldiv(ctx, OPC_MULT, 0, rx, ry); - break; - case RR_MULTU: - gen_muldiv(ctx, OPC_MULTU, 0, rx, ry); - break; - case RR_DIV: - gen_muldiv(ctx, OPC_DIV, 0, rx, ry); - break; - case RR_DIVU: - gen_muldiv(ctx, OPC_DIVU, 0, rx, ry); - break; -#if defined(TARGET_MIPS64) - case RR_DMULT: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_muldiv(ctx, OPC_DMULT, 0, rx, ry); - break; - case RR_DMULTU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry); - break; - case RR_DDIV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_muldiv(ctx, OPC_DDIV, 0, rx, ry); - break; - case RR_DDIVU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry); - break; -#endif - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case M16_OPC_EXTEND: - decode_extended_mips16_opc(env, ctx); - n_bytes = 4; - break; -#if defined(TARGET_MIPS64) - case M16_OPC_I64: - funct = (ctx->opcode >> 8) & 0x7; - decode_i64_mips16(ctx, ry, funct, offset, 0); - break; -#endif - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - - return n_bytes; -} +#include "ase-mips16e_translate.c.inc" /* microMIPS extension to MIPS32/MIPS64 */ diff --git a/target/mips/ase-mips16e_translate.c.inc b/target/mips/ase-mips16e_translate.c.inc new file mode 100644 index 00000000000..11010a30bce --- /dev/null +++ b/target/mips/ase-mips16e_translate.c.inc @@ -0,0 +1,1170 @@ +/* + * MIPS16 extension (Code Compaction) ASE translation routines + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* MIPS16 major opcodes */ +enum { + M16_OPC_ADDIUSP = 0x00, + M16_OPC_ADDIUPC = 0x01, + M16_OPC_B = 0x02, + M16_OPC_JAL = 0x03, + M16_OPC_BEQZ = 0x04, + M16_OPC_BNEQZ = 0x05, + M16_OPC_SHIFT = 0x06, + M16_OPC_LD = 0x07, + M16_OPC_RRIA = 0x08, + M16_OPC_ADDIU8 = 0x09, + M16_OPC_SLTI = 0x0a, + M16_OPC_SLTIU = 0x0b, + M16_OPC_I8 = 0x0c, + M16_OPC_LI = 0x0d, + M16_OPC_CMPI = 0x0e, + M16_OPC_SD = 0x0f, + M16_OPC_LB = 0x10, + M16_OPC_LH = 0x11, + M16_OPC_LWSP = 0x12, + M16_OPC_LW = 0x13, + M16_OPC_LBU = 0x14, + M16_OPC_LHU = 0x15, + M16_OPC_LWPC = 0x16, + M16_OPC_LWU = 0x17, + M16_OPC_SB = 0x18, + M16_OPC_SH = 0x19, + M16_OPC_SWSP = 0x1a, + M16_OPC_SW = 0x1b, + M16_OPC_RRR = 0x1c, + M16_OPC_RR = 0x1d, + M16_OPC_EXTEND = 0x1e, + M16_OPC_I64 = 0x1f +}; + +/* I8 funct field */ +enum { + I8_BTEQZ = 0x0, + I8_BTNEZ = 0x1, + I8_SWRASP = 0x2, + I8_ADJSP = 0x3, + I8_SVRS = 0x4, + I8_MOV32R = 0x5, + I8_MOVR32 = 0x7 +}; + +/* RRR f field */ +enum { + RRR_DADDU = 0x0, + RRR_ADDU = 0x1, + RRR_DSUBU = 0x2, + RRR_SUBU = 0x3 +}; + +/* RR funct field */ +enum { + RR_JR = 0x00, + RR_SDBBP = 0x01, + RR_SLT = 0x02, + RR_SLTU = 0x03, + RR_SLLV = 0x04, + RR_BREAK = 0x05, + RR_SRLV = 0x06, + RR_SRAV = 0x07, + RR_DSRL = 0x08, + RR_CMP = 0x0a, + RR_NEG = 0x0b, + RR_AND = 0x0c, + RR_OR = 0x0d, + RR_XOR = 0x0e, + RR_NOT = 0x0f, + RR_MFHI = 0x10, + RR_CNVT = 0x11, + RR_MFLO = 0x12, + RR_DSRA = 0x13, + RR_DSLLV = 0x14, + RR_DSRLV = 0x16, + RR_DSRAV = 0x17, + RR_MULT = 0x18, + RR_MULTU = 0x19, + RR_DIV = 0x1a, + RR_DIVU = 0x1b, + RR_DMULT = 0x1c, + RR_DMULTU = 0x1d, + RR_DDIV = 0x1e, + RR_DDIVU = 0x1f +}; + +/* I64 funct field */ +enum { + I64_LDSP = 0x0, + I64_SDSP = 0x1, + I64_SDRASP = 0x2, + I64_DADJSP = 0x3, + I64_LDPC = 0x4, + I64_DADDIU5 = 0x5, + I64_DADDIUPC = 0x6, + I64_DADDIUSP = 0x7 +}; + +/* RR ry field for CNVT */ +enum { + RR_RY_CNVT_ZEB = 0x0, + RR_RY_CNVT_ZEH = 0x1, + RR_RY_CNVT_ZEW = 0x2, + RR_RY_CNVT_SEB = 0x4, + RR_RY_CNVT_SEH = 0x5, + RR_RY_CNVT_SEW = 0x6, +}; + +static int xlat(int r) +{ + static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; + + return map[r]; +} + +static void gen_mips16_save(DisasContext *ctx, + int xsregs, int aregs, + int do_ra, int do_s0, int do_s1, + int framesize) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + int args, astatic; + + switch (aregs) { + case 0: + case 1: + case 2: + case 3: + case 11: + args = 0; + break; + case 4: + case 5: + case 6: + case 7: + args = 1; + break; + case 8: + case 9: + case 10: + args = 2; + break; + case 12: + case 13: + args = 3; + break; + case 14: + args = 4; + break; + default: + generate_exception_end(ctx, EXCP_RI); + return; + } + + switch (args) { + case 4: + gen_base_offset_addr(ctx, t0, 29, 12); + gen_load_gpr(t1, 7); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + /* Fall through */ + case 3: + gen_base_offset_addr(ctx, t0, 29, 8); + gen_load_gpr(t1, 6); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + /* Fall through */ + case 2: + gen_base_offset_addr(ctx, t0, 29, 4); + gen_load_gpr(t1, 5); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + /* Fall through */ + case 1: + gen_base_offset_addr(ctx, t0, 29, 0); + gen_load_gpr(t1, 4); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + } + + gen_load_gpr(t0, 29); + +#define DECR_AND_STORE(reg) do { \ + tcg_gen_movi_tl(t2, -4); \ + gen_op_addr_add(ctx, t0, t0, t2); \ + gen_load_gpr(t1, reg); \ + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \ + } while (0) + + if (do_ra) { + DECR_AND_STORE(31); + } + + switch (xsregs) { + case 7: + DECR_AND_STORE(30); + /* Fall through */ + case 6: + DECR_AND_STORE(23); + /* Fall through */ + case 5: + DECR_AND_STORE(22); + /* Fall through */ + case 4: + DECR_AND_STORE(21); + /* Fall through */ + case 3: + DECR_AND_STORE(20); + /* Fall through */ + case 2: + DECR_AND_STORE(19); + /* Fall through */ + case 1: + DECR_AND_STORE(18); + } + + if (do_s1) { + DECR_AND_STORE(17); + } + if (do_s0) { + DECR_AND_STORE(16); + } + + switch (aregs) { + case 0: + case 4: + case 8: + case 12: + case 14: + astatic = 0; + break; + case 1: + case 5: + case 9: + case 13: + astatic = 1; + break; + case 2: + case 6: + case 10: + astatic = 2; + break; + case 3: + case 7: + astatic = 3; + break; + case 11: + astatic = 4; + break; + default: + generate_exception_end(ctx, EXCP_RI); + return; + } + + if (astatic > 0) { + DECR_AND_STORE(7); + if (astatic > 1) { + DECR_AND_STORE(6); + if (astatic > 2) { + DECR_AND_STORE(5); + if (astatic > 3) { + DECR_AND_STORE(4); + } + } + } + } +#undef DECR_AND_STORE + + tcg_gen_movi_tl(t2, -framesize); + gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); +} + +static void gen_mips16_restore(DisasContext *ctx, + int xsregs, int aregs, + int do_ra, int do_s0, int do_s1, + int framesize) +{ + int astatic; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + + tcg_gen_movi_tl(t2, framesize); + gen_op_addr_add(ctx, t0, cpu_gpr[29], t2); + +#define DECR_AND_LOAD(reg) do { \ + tcg_gen_movi_tl(t2, -4); \ + gen_op_addr_add(ctx, t0, t0, t2); \ + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \ + gen_store_gpr(t1, reg); \ + } while (0) + + if (do_ra) { + DECR_AND_LOAD(31); + } + + switch (xsregs) { + case 7: + DECR_AND_LOAD(30); + /* Fall through */ + case 6: + DECR_AND_LOAD(23); + /* Fall through */ + case 5: + DECR_AND_LOAD(22); + /* Fall through */ + case 4: + DECR_AND_LOAD(21); + /* Fall through */ + case 3: + DECR_AND_LOAD(20); + /* Fall through */ + case 2: + DECR_AND_LOAD(19); + /* Fall through */ + case 1: + DECR_AND_LOAD(18); + } + + if (do_s1) { + DECR_AND_LOAD(17); + } + if (do_s0) { + DECR_AND_LOAD(16); + } + + switch (aregs) { + case 0: + case 4: + case 8: + case 12: + case 14: + astatic = 0; + break; + case 1: + case 5: + case 9: + case 13: + astatic = 1; + break; + case 2: + case 6: + case 10: + astatic = 2; + break; + case 3: + case 7: + astatic = 3; + break; + case 11: + astatic = 4; + break; + default: + generate_exception_end(ctx, EXCP_RI); + return; + } + + if (astatic > 0) { + DECR_AND_LOAD(7); + if (astatic > 1) { + DECR_AND_LOAD(6); + if (astatic > 2) { + DECR_AND_LOAD(5); + if (astatic > 3) { + DECR_AND_LOAD(4); + } + } + } + } +#undef DECR_AND_LOAD + + tcg_gen_movi_tl(t2, framesize); + gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); +} + +static void gen_addiupc(DisasContext *ctx, int rx, int imm, + int is_64_bit, int extended) +{ + TCGv t0; + + if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { + generate_exception_end(ctx, EXCP_RI); + return; + } + + t0 = tcg_temp_new(); + + tcg_gen_movi_tl(t0, pc_relative_pc(ctx)); + tcg_gen_addi_tl(cpu_gpr[rx], t0, imm); + if (!is_64_bit) { + tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); + } + + tcg_temp_free(t0); +} + +static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base, + int16_t offset) +{ + TCGv_i32 t0 = tcg_const_i32(op); + TCGv t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t1, base, offset); + gen_helper_cache(cpu_env, t1, t0); +} + +#if defined(TARGET_MIPS64) +static void decode_i64_mips16(DisasContext *ctx, + int ry, int funct, int16_t offset, + int extended) +{ + switch (funct) { + case I64_LDSP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset = extended ? offset : offset << 3; + gen_ld(ctx, OPC_LD, ry, 29, offset); + break; + case I64_SDSP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset = extended ? offset : offset << 3; + gen_st(ctx, OPC_SD, ry, 29, offset); + break; + case I64_SDRASP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset = extended ? offset : (ctx->opcode & 0xff) << 3; + gen_st(ctx, OPC_SD, 31, 29, offset); + break; + case I64_DADJSP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset = extended ? offset : ((int8_t)ctx->opcode) << 3; + gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset); + break; + case I64_LDPC: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { + generate_exception_end(ctx, EXCP_RI); + } else { + offset = extended ? offset : offset << 3; + gen_ld(ctx, OPC_LDPC, ry, 0, offset); + } + break; + case I64_DADDIU5: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset = extended ? offset : ((int8_t)(offset << 3)) >> 3; + gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset); + break; + case I64_DADDIUPC: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset = extended ? offset : offset << 2; + gen_addiupc(ctx, ry, offset, 1, extended); + break; + case I64_DADDIUSP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset = extended ? offset : offset << 2; + gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset); + break; + } +} +#endif + +static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx) +{ + int extend = cpu_lduw_code(env, ctx->base.pc_next + 2); + int op, rx, ry, funct, sa; + int16_t imm, offset; + + ctx->opcode = (ctx->opcode << 16) | extend; + op = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 22) & 0x1f; + funct = (ctx->opcode >> 8) & 0x7; + rx = xlat((ctx->opcode >> 8) & 0x7); + ry = xlat((ctx->opcode >> 5) & 0x7); + offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11 + | ((ctx->opcode >> 21) & 0x3f) << 5 + | (ctx->opcode & 0x1f)); + + /* + * The extended opcodes cleverly reuse the opcodes from their 16-bit + * counterparts. + */ + switch (op) { + case M16_OPC_ADDIUSP: + gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); + break; + case M16_OPC_ADDIUPC: + gen_addiupc(ctx, rx, imm, 0, 1); + break; + case M16_OPC_B: + gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BEQZ: + gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BNEQZ: + gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_SHIFT: + switch (ctx->opcode & 0x3) { + case 0x0: + gen_shift_imm(ctx, OPC_SLL, rx, ry, sa); + break; + case 0x1: +#if defined(TARGET_MIPS64) + check_mips_64(ctx); + gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); +#else + generate_exception_end(ctx, EXCP_RI); +#endif + break; + case 0x2: + gen_shift_imm(ctx, OPC_SRL, rx, ry, sa); + break; + case 0x3: + gen_shift_imm(ctx, OPC_SRA, rx, ry, sa); + break; + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_ld(ctx, OPC_LD, ry, rx, offset); + break; +#endif + case M16_OPC_RRIA: + imm = ctx->opcode & 0xf; + imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4; + imm = imm | ((ctx->opcode >> 16) & 0xf) << 11; + imm = (int16_t) (imm << 1) >> 1; + if ((ctx->opcode >> 4) & 0x1) { +#if defined(TARGET_MIPS64) + check_mips_64(ctx); + gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); +#else + generate_exception_end(ctx, EXCP_RI); +#endif + } else { + gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); + } + break; + case M16_OPC_ADDIU8: + gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm); + break; + case M16_OPC_SLTI: + gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm); + break; + case M16_OPC_SLTIU: + gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm); + break; + case M16_OPC_I8: + switch (funct) { + case I8_BTEQZ: + gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0); + break; + case I8_BTNEZ: + gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0); + break; + case I8_SWRASP: + gen_st(ctx, OPC_SW, 31, 29, imm); + break; + case I8_ADJSP: + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm); + break; + case I8_SVRS: + check_insn(ctx, ISA_MIPS32); + { + int xsregs = (ctx->opcode >> 24) & 0x7; + int aregs = (ctx->opcode >> 16) & 0xf; + int do_ra = (ctx->opcode >> 6) & 0x1; + int do_s0 = (ctx->opcode >> 5) & 0x1; + int do_s1 = (ctx->opcode >> 4) & 0x1; + int framesize = (((ctx->opcode >> 20) & 0xf) << 4 + | (ctx->opcode & 0xf)) << 3; + + if (ctx->opcode & (1 << 7)) { + gen_mips16_save(ctx, xsregs, aregs, + do_ra, do_s0, do_s1, + framesize); + } else { + gen_mips16_restore(ctx, xsregs, aregs, + do_ra, do_s0, do_s1, + framesize); + } + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case M16_OPC_LI: + tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm); + break; + case M16_OPC_CMPI: + tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_SD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_st(ctx, OPC_SD, ry, rx, offset); + break; +#endif + case M16_OPC_LB: + gen_ld(ctx, OPC_LB, ry, rx, offset); + break; + case M16_OPC_LH: + gen_ld(ctx, OPC_LH, ry, rx, offset); + break; + case M16_OPC_LWSP: + gen_ld(ctx, OPC_LW, rx, 29, offset); + break; + case M16_OPC_LW: + gen_ld(ctx, OPC_LW, ry, rx, offset); + break; + case M16_OPC_LBU: + gen_ld(ctx, OPC_LBU, ry, rx, offset); + break; + case M16_OPC_LHU: + gen_ld(ctx, OPC_LHU, ry, rx, offset); + break; + case M16_OPC_LWPC: + gen_ld(ctx, OPC_LWPC, rx, 0, offset); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LWU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_ld(ctx, OPC_LWU, ry, rx, offset); + break; +#endif + case M16_OPC_SB: + gen_st(ctx, OPC_SB, ry, rx, offset); + break; + case M16_OPC_SH: + gen_st(ctx, OPC_SH, ry, rx, offset); + break; + case M16_OPC_SWSP: + gen_st(ctx, OPC_SW, rx, 29, offset); + break; + case M16_OPC_SW: + gen_st(ctx, OPC_SW, ry, rx, offset); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_I64: + decode_i64_mips16(ctx, ry, funct, offset, 1); + break; +#endif + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + + return 4; +} + +static inline bool is_uhi(int sdbbp_code) +{ +#ifdef CONFIG_USER_ONLY + return false; +#else + return semihosting_enabled() && sdbbp_code == 1; +#endif +} + +#ifdef CONFIG_USER_ONLY +/* The above should dead-code away any calls to this..*/ +static inline void gen_helper_do_semihosting(void *env) +{ + g_assert_not_reached(); +} +#endif + +static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx) +{ + int rx, ry; + int sa; + int op, cnvt_op, op1, offset; + int funct; + int n_bytes; + + op = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 2) & 0x7; + sa = sa == 0 ? 8 : sa; + rx = xlat((ctx->opcode >> 8) & 0x7); + cnvt_op = (ctx->opcode >> 5) & 0x7; + ry = xlat((ctx->opcode >> 5) & 0x7); + op1 = offset = ctx->opcode & 0x1f; + + n_bytes = 2; + + switch (op) { + case M16_OPC_ADDIUSP: + { + int16_t imm = ((uint8_t) ctx->opcode) << 2; + + gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); + } + break; + case M16_OPC_ADDIUPC: + gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0); + break; + case M16_OPC_B: + offset = (ctx->opcode & 0x7ff) << 1; + offset = (int16_t)(offset << 4) >> 4; + gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_JAL: + offset = cpu_lduw_code(env, ctx->base.pc_next + 2); + offset = (((ctx->opcode & 0x1f) << 21) + | ((ctx->opcode >> 5) & 0x1f) << 16 + | offset) << 2; + op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL; + gen_compute_branch(ctx, op, 4, rx, ry, offset, 2); + n_bytes = 4; + break; + case M16_OPC_BEQZ: + gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, + ((int8_t)ctx->opcode) << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BNEQZ: + gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, + ((int8_t)ctx->opcode) << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_SHIFT: + switch (ctx->opcode & 0x3) { + case 0x0: + gen_shift_imm(ctx, OPC_SLL, rx, ry, sa); + break; + case 0x1: +#if defined(TARGET_MIPS64) + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); +#else + generate_exception_end(ctx, EXCP_RI); +#endif + break; + case 0x2: + gen_shift_imm(ctx, OPC_SRL, rx, ry, sa); + break; + case 0x3: + gen_shift_imm(ctx, OPC_SRA, rx, ry, sa); + break; + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_ld(ctx, OPC_LD, ry, rx, offset << 3); + break; +#endif + case M16_OPC_RRIA: + { + int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4; + + if ((ctx->opcode >> 4) & 1) { +#if defined(TARGET_MIPS64) + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); +#else + generate_exception_end(ctx, EXCP_RI); +#endif + } else { + gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); + } + } + break; + case M16_OPC_ADDIU8: + { + int16_t imm = (int8_t) ctx->opcode; + + gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm); + } + break; + case M16_OPC_SLTI: + { + int16_t imm = (uint8_t) ctx->opcode; + gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm); + } + break; + case M16_OPC_SLTIU: + { + int16_t imm = (uint8_t) ctx->opcode; + gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm); + } + break; + case M16_OPC_I8: + { + int reg32; + + funct = (ctx->opcode >> 8) & 0x7; + switch (funct) { + case I8_BTEQZ: + gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0, + ((int8_t)ctx->opcode) << 1, 0); + break; + case I8_BTNEZ: + gen_compute_branch(ctx, OPC_BNE, 2, 24, 0, + ((int8_t)ctx->opcode) << 1, 0); + break; + case I8_SWRASP: + gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2); + break; + case I8_ADJSP: + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, + ((int8_t)ctx->opcode) << 3); + break; + case I8_SVRS: + check_insn(ctx, ISA_MIPS32); + { + int do_ra = ctx->opcode & (1 << 6); + int do_s0 = ctx->opcode & (1 << 5); + int do_s1 = ctx->opcode & (1 << 4); + int framesize = ctx->opcode & 0xf; + + if (framesize == 0) { + framesize = 128; + } else { + framesize = framesize << 3; + } + + if (ctx->opcode & (1 << 7)) { + gen_mips16_save(ctx, 0, 0, + do_ra, do_s0, do_s1, framesize); + } else { + gen_mips16_restore(ctx, 0, 0, + do_ra, do_s0, do_s1, framesize); + } + } + break; + case I8_MOV32R: + { + int rz = xlat(ctx->opcode & 0x7); + + reg32 = (((ctx->opcode >> 3) & 0x3) << 3) | + ((ctx->opcode >> 5) & 0x7); + gen_arith(ctx, OPC_ADDU, reg32, rz, 0); + } + break; + case I8_MOVR32: + reg32 = ctx->opcode & 0x1f; + gen_arith(ctx, OPC_ADDU, ry, reg32, 0); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + } + break; + case M16_OPC_LI: + { + int16_t imm = (uint8_t) ctx->opcode; + + gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm); + } + break; + case M16_OPC_CMPI: + { + int16_t imm = (uint8_t) ctx->opcode; + gen_logic_imm(ctx, OPC_XORI, 24, rx, imm); + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_SD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_st(ctx, OPC_SD, ry, rx, offset << 3); + break; +#endif + case M16_OPC_LB: + gen_ld(ctx, OPC_LB, ry, rx, offset); + break; + case M16_OPC_LH: + gen_ld(ctx, OPC_LH, ry, rx, offset << 1); + break; + case M16_OPC_LWSP: + gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2); + break; + case M16_OPC_LW: + gen_ld(ctx, OPC_LW, ry, rx, offset << 2); + break; + case M16_OPC_LBU: + gen_ld(ctx, OPC_LBU, ry, rx, offset); + break; + case M16_OPC_LHU: + gen_ld(ctx, OPC_LHU, ry, rx, offset << 1); + break; + case M16_OPC_LWPC: + gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LWU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_ld(ctx, OPC_LWU, ry, rx, offset << 2); + break; +#endif + case M16_OPC_SB: + gen_st(ctx, OPC_SB, ry, rx, offset); + break; + case M16_OPC_SH: + gen_st(ctx, OPC_SH, ry, rx, offset << 1); + break; + case M16_OPC_SWSP: + gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2); + break; + case M16_OPC_SW: + gen_st(ctx, OPC_SW, ry, rx, offset << 2); + break; + case M16_OPC_RRR: + { + int rz = xlat((ctx->opcode >> 2) & 0x7); + int mips32_op; + + switch (ctx->opcode & 0x3) { + case RRR_ADDU: + mips32_op = OPC_ADDU; + break; + case RRR_SUBU: + mips32_op = OPC_SUBU; + break; +#if defined(TARGET_MIPS64) + case RRR_DADDU: + mips32_op = OPC_DADDU; + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + break; + case RRR_DSUBU: + mips32_op = OPC_DSUBU; + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + break; +#endif + default: + generate_exception_end(ctx, EXCP_RI); + goto done; + } + + gen_arith(ctx, mips32_op, rz, rx, ry); + done: + ; + } + break; + case M16_OPC_RR: + switch (op1) { + case RR_JR: + { + int nd = (ctx->opcode >> 7) & 0x1; + int link = (ctx->opcode >> 6) & 0x1; + int ra = (ctx->opcode >> 5) & 0x1; + + if (nd) { + check_insn(ctx, ISA_MIPS32); + } + + if (link) { + op = OPC_JALR; + } else { + op = OPC_JR; + } + + gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0, + (nd ? 0 : 2)); + } + break; + case RR_SDBBP: + if (is_uhi(extract32(ctx->opcode, 5, 6))) { + gen_helper_do_semihosting(cpu_env); + } else { + /* + * XXX: not clear which exception should be raised + * when in debug mode... + */ + check_insn(ctx, ISA_MIPS32); + generate_exception_end(ctx, EXCP_DBp); + } + break; + case RR_SLT: + gen_slt(ctx, OPC_SLT, 24, rx, ry); + break; + case RR_SLTU: + gen_slt(ctx, OPC_SLTU, 24, rx, ry); + break; + case RR_BREAK: + generate_exception_end(ctx, EXCP_BREAK); + break; + case RR_SLLV: + gen_shift(ctx, OPC_SLLV, ry, rx, ry); + break; + case RR_SRLV: + gen_shift(ctx, OPC_SRLV, ry, rx, ry); + break; + case RR_SRAV: + gen_shift(ctx, OPC_SRAV, ry, rx, ry); + break; +#if defined(TARGET_MIPS64) + case RR_DSRL: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa); + break; +#endif + case RR_CMP: + gen_logic(ctx, OPC_XOR, 24, rx, ry); + break; + case RR_NEG: + gen_arith(ctx, OPC_SUBU, rx, 0, ry); + break; + case RR_AND: + gen_logic(ctx, OPC_AND, rx, rx, ry); + break; + case RR_OR: + gen_logic(ctx, OPC_OR, rx, rx, ry); + break; + case RR_XOR: + gen_logic(ctx, OPC_XOR, rx, rx, ry); + break; + case RR_NOT: + gen_logic(ctx, OPC_NOR, rx, ry, 0); + break; + case RR_MFHI: + gen_HILO(ctx, OPC_MFHI, 0, rx); + break; + case RR_CNVT: + check_insn(ctx, ISA_MIPS32); + switch (cnvt_op) { + case RR_RY_CNVT_ZEB: + tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_ZEH: + tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEB: + tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEH: + tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; +#if defined(TARGET_MIPS64) + case RR_RY_CNVT_ZEW: + check_insn(ctx, ISA_MIPS64); + check_mips_64(ctx); + tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEW: + check_insn(ctx, ISA_MIPS64); + check_mips_64(ctx); + tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; +#endif + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case RR_MFLO: + gen_HILO(ctx, OPC_MFLO, 0, rx); + break; +#if defined(TARGET_MIPS64) + case RR_DSRA: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa); + break; + case RR_DSLLV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift(ctx, OPC_DSLLV, ry, rx, ry); + break; + case RR_DSRLV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift(ctx, OPC_DSRLV, ry, rx, ry); + break; + case RR_DSRAV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift(ctx, OPC_DSRAV, ry, rx, ry); + break; +#endif + case RR_MULT: + gen_muldiv(ctx, OPC_MULT, 0, rx, ry); + break; + case RR_MULTU: + gen_muldiv(ctx, OPC_MULTU, 0, rx, ry); + break; + case RR_DIV: + gen_muldiv(ctx, OPC_DIV, 0, rx, ry); + break; + case RR_DIVU: + gen_muldiv(ctx, OPC_DIVU, 0, rx, ry); + break; +#if defined(TARGET_MIPS64) + case RR_DMULT: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DMULT, 0, rx, ry); + break; + case RR_DMULTU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry); + break; + case RR_DDIV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DDIV, 0, rx, ry); + break; + case RR_DDIVU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry); + break; +#endif + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case M16_OPC_EXTEND: + decode_extended_mips16_opc(env, ctx); + n_bytes = 4; + break; +#if defined(TARGET_MIPS64) + case M16_OPC_I64: + funct = (ctx->opcode >> 8) & 0x7; + decode_i64_mips16(ctx, ry, funct, offset, 0); + break; +#endif + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + + return n_bytes; +} From patchwork Mon Nov 23 20:44:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926739 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 16CB2C2D0E4 for ; Mon, 23 Nov 2020 20:51: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 8015920706 for ; Mon, 23 Nov 2020 20:51:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Zh/nqo8q" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8015920706 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:47674 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khIoM-0007W8-CO for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 15:51:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46658) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIif-0001qv-Jt for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:53 -0500 Received: from mail-wm1-x342.google.com ([2a00:1450:4864:20::342]:37134) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIid-0001WB-SJ for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:45:53 -0500 Received: by mail-wm1-x342.google.com with SMTP id h21so744351wmb.2 for ; Mon, 23 Nov 2020 12:45:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cmro0DZbICWkoZ0DnoHpC16jsvuCgJAkyQiwC9svvb0=; b=Zh/nqo8qtgMEX2sACstBwM9amNJUoXJg8opQAffYEsgp180fvPyobtZ9IuR1VENvX+ kPjvuQpHXHVsDEKo+TtAc7aQW5sPK9c0gI3/gzopvnjPjr/noC0frWzUssRoQqaWKhPW 9VKwEQuchLiAq1D7np7mHv3JJNXWOR5zeZrwgXBAVPerDmwNEb8WjpDRKJB8Q3jLKJ8G 00qeJnDmX+l3UIZHXpIkShN3MitPt03McIlspldjXuRO4Mwh+/HRN190dawk3Ri5QCgq vwN+rdzusUMs7m5Rmt5vweR2eyVa0msXDEGMo9Wguwy3itRoaaqIdPZz0RJkSZJ6cmk3 YzmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=cmro0DZbICWkoZ0DnoHpC16jsvuCgJAkyQiwC9svvb0=; b=HpTpioWV6eP3DJSy3u36ZtCk7xnr2WESGeNBftwwutKYHZBWkLoiA6GPD2tTNJkAmU HYxo4CVJZd6kO6kaNwsJybONGHBfkKhDmkeyI/FN5Lcn7YIA1se6yxpT3yIYaSgc4snD YGUsCK5wgEKtql+zUIxXkgU/EwZir0/5fPQtAXr/JzMImPHtncgakwEER8W/loaoi8NQ e7SDoT2udwJ1ZCPBgVJMl7UABTrBWKuykJuXgEl9Lt86uZmH9AgBOZhpkkXkfZhztP3O MNrI4ON1DaDk95onpGv40bFDaoNQQa31roqTwKEcx8AjH4gsmF3xxOBAQzLSEKvBTMI3 9f6Q== X-Gm-Message-State: AOAM531EoN02GvMwut9WLt5Aq2EwYrtV0MROAX+IoD/2CrkTMipEX0DA Bn9/tDbSGSYcPST9EwJJtrPC+tmJnq4= X-Google-Smtp-Source: ABdhPJw3Y4Fsjv6z/ddyveOtks6wH7LTgx1LMNXCvZjGkzUslDjGn692FNLnToiAmcsuZ42DK/EpDQ== X-Received: by 2002:a1c:4957:: with SMTP id w84mr751889wma.84.1606164349878; Mon, 23 Nov 2020 12:45:49 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id d8sm863531wmb.11.2020.11.23.12.45.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:49 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 12/28] target/mips: Extract the microMIPS ISA helper definitions Date: Mon, 23 Nov 2020 21:44:32 +0100 Message-Id: <20201123204448.3260804-13-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::342; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x342.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract the microMIPS ISA helper definitions to 'isa-micromips_helper.h.inc'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-11-f4bug@amsat.org> --- target/mips/helper.h | 10 ++-------- target/mips/isa-micromips_helper.h.inc | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 target/mips/isa-micromips_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index 18366bc0345..06da4c6cf68 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -181,14 +181,6 @@ DEF_HELPER_2(dmtc0_entrylo1, void, env, i64) #endif /* !CONFIG_USER_ONLY */ -/* microMIPS functions */ -DEF_HELPER_4(lwm, void, env, tl, tl, i32) -DEF_HELPER_4(swm, void, env, tl, tl, i32) -#ifdef TARGET_MIPS64 -DEF_HELPER_4(ldm, void, env, tl, tl, i32) -DEF_HELPER_4(sdm, void, env, tl, tl, i32) -#endif - /* CP1 functions */ DEF_HELPER_2(cfc1, tl, env, i32) DEF_HELPER_4(ctc1, void, env, tl, i32, i32) @@ -427,6 +419,8 @@ DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_3(cache, void, env, tl, i32) +#include "isa-micromips_helper.h.inc" + #include "mod-dsp_helper.h.inc" #include "mod-msa_helper.h.inc" #include "mod-mt_helper.h.inc" diff --git a/target/mips/isa-micromips_helper.h.inc b/target/mips/isa-micromips_helper.h.inc new file mode 100644 index 00000000000..66a764c4aac --- /dev/null +++ b/target/mips/isa-micromips_helper.h.inc @@ -0,0 +1,17 @@ +/* + * microMIPS instruction emulation helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +DEF_HELPER_4(lwm, void, env, tl, tl, i32) +DEF_HELPER_4(swm, void, env, tl, tl, i32) +#ifdef TARGET_MIPS64 +DEF_HELPER_4(ldm, void, env, tl, tl, i32) +DEF_HELPER_4(sdm, void, env, tl, tl, i32) +#endif From patchwork Mon Nov 23 20:44:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926745 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 5B558C2D0E4 for ; Mon, 23 Nov 2020 20:55:52 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 51788206B7 for ; Mon, 23 Nov 2020 20:55:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KjOqDuac" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 51788206B7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:56726 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khIsI-00035d-2w for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 15:55:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46704) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIip-0002Aj-D9 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:03 -0500 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]:35793) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIik-0001bU-Hf for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:03 -0500 Received: by mail-wm1-x32f.google.com with SMTP id w24so755792wmi.0 for ; Mon, 23 Nov 2020 12:45:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=TeepZj1tsX+d/7M2qSH82P4tr4AEnChH/VMDd3GuNzM=; b=KjOqDuacV3HYwFxmcjQhQBNwjpf96/tleUlxDALyimNsTYgXDTiFxhSvdUXEvfUdgi 7ke55bSUWVAS+XjzjoeEWOZ8TDQAe9D0z/5241ygWF77g1RRxpdGArc+G6rvf5/Rw0Et vFnNFNrQPa/MRGyuK7dCegn/sr3HBd+qk2nSaMRa53HoZ2SpiXN98HT8W+SAOSuBUeiS GkOF8xTtdN6krbbw1ytos2oYniVyLW6IZLUgjjkTONP98BKRtUQD38kK6q+969cTVSfJ O90axgIdgs4PGtl+1szeAFXwf0FCOqDXo4sDsOpdNpot6hXvftMvFZ2oWB213kjnon+W XAxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=TeepZj1tsX+d/7M2qSH82P4tr4AEnChH/VMDd3GuNzM=; b=pTQTBIn0S9QvDWLva4IEyT9pFWqgtWIqbZ0HGM4a/PRhWvKYlwjHob/K3VYC3g4SzH 8CwiR/AIgX2CZc9SuxWVFGG3gUF5TnjwGtx279twBtRNIBgbiVKkFh5wU9GcoSZ5Wz2U +dhwcUEKLw6oOdoT35tIADG90mnUEFoM5egOxxHNKBlVpyy18Pllj6xBu3nzWPTSAppC DZpIF8dboo9vmvaZFAmUjyG3166APgyXBFaN3v5snwGZe5WYdgOiJztK1xHYC/25Kq3q kk01nMwIE0gGhB5DWY9YoGQGKDlWkhgsgJWx5H0uQWPlgDcJIoxtQEacKr9pc5SkMpyF RVag== X-Gm-Message-State: AOAM5319nhaYOfDeWTqiiJyjpz1577f+Ae6hw/E3fVkWrVohhdN8sN3Z WMPwlsNXT6P30zpn0nkGHAv0d23HyOI= X-Google-Smtp-Source: ABdhPJxBmxhSrUgVBRhLM821j8BmncrMwsYrVBjGwE0RUQIBM/72j2ck5SwLMX0+BjFEmngDV6HTjw== X-Received: by 2002:a1c:3c4:: with SMTP id 187mr649886wmd.143.1606164355278; Mon, 23 Nov 2020 12:45:55 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id t13sm21883344wru.67.2020.11.23.12.45.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:54 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 13/28] target/mips: Extract the microMIPS ISA translation routines Date: Mon, 23 Nov 2020 21:44:33 +0100 Message-Id: <20201123204448.3260804-14-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32f; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x32f.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract 3300 lines from the huge translate.c to a new file, 'isa-micromips_translate.c.inc'. As there are too many inter- dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-12-f4bug@amsat.org> --- target/mips/translate.c | 3309 +------------------- target/mips/isa-micromips_translate.c.inc | 3316 +++++++++++++++++++++ 2 files changed, 3317 insertions(+), 3308 deletions(-) create mode 100644 target/mips/isa-micromips_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 1a329bcdede..5373a3f9a0a 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -13133,3314 +13133,7 @@ out: /* ISA extensions (ASEs) */ #include "ase-mips16e_translate.c.inc" - -/* microMIPS extension to MIPS32/MIPS64 */ - -/* - * microMIPS32/microMIPS64 major opcodes - * - * 1. MIPS Architecture for Programmers Volume II-B: - * The microMIPS32 Instruction Set (Revision 3.05) - * - * Table 6.2 microMIPS32 Encoding of Major Opcode Field - * - * 2. MIPS Architecture For Programmers Volume II-A: - * The MIPS64 Instruction Set (Revision 3.51) - */ - -enum { - POOL32A = 0x00, - POOL16A = 0x01, - LBU16 = 0x02, - MOVE16 = 0x03, - ADDI32 = 0x04, - R6_LUI = 0x04, - AUI = 0x04, - LBU32 = 0x05, - SB32 = 0x06, - LB32 = 0x07, - - POOL32B = 0x08, - POOL16B = 0x09, - LHU16 = 0x0a, - ANDI16 = 0x0b, - ADDIU32 = 0x0c, - LHU32 = 0x0d, - SH32 = 0x0e, - LH32 = 0x0f, - - POOL32I = 0x10, - POOL16C = 0x11, - LWSP16 = 0x12, - POOL16D = 0x13, - ORI32 = 0x14, - POOL32F = 0x15, - POOL32S = 0x16, /* MIPS64 */ - DADDIU32 = 0x17, /* MIPS64 */ - - POOL32C = 0x18, - LWGP16 = 0x19, - LW16 = 0x1a, - POOL16E = 0x1b, - XORI32 = 0x1c, - JALS32 = 0x1d, - BOVC = 0x1d, - BEQC = 0x1d, - BEQZALC = 0x1d, - ADDIUPC = 0x1e, - PCREL = 0x1e, - BNVC = 0x1f, - BNEC = 0x1f, - BNEZALC = 0x1f, - - R6_BEQZC = 0x20, - JIC = 0x20, - POOL16F = 0x21, - SB16 = 0x22, - BEQZ16 = 0x23, - BEQZC16 = 0x23, - SLTI32 = 0x24, - BEQ32 = 0x25, - BC = 0x25, - SWC132 = 0x26, - LWC132 = 0x27, - - /* 0x29 is reserved */ - RES_29 = 0x29, - R6_BNEZC = 0x28, - JIALC = 0x28, - SH16 = 0x2a, - BNEZ16 = 0x2b, - BNEZC16 = 0x2b, - SLTIU32 = 0x2c, - BNE32 = 0x2d, - BALC = 0x2d, - SDC132 = 0x2e, - LDC132 = 0x2f, - - /* 0x31 is reserved */ - RES_31 = 0x31, - BLEZALC = 0x30, - BGEZALC = 0x30, - BGEUC = 0x30, - SWSP16 = 0x32, - B16 = 0x33, - BC16 = 0x33, - ANDI32 = 0x34, - J32 = 0x35, - BGTZC = 0x35, - BLTZC = 0x35, - BLTC = 0x35, - SD32 = 0x36, /* MIPS64 */ - LD32 = 0x37, /* MIPS64 */ - - /* 0x39 is reserved */ - RES_39 = 0x39, - BGTZALC = 0x38, - BLTZALC = 0x38, - BLTUC = 0x38, - SW16 = 0x3a, - LI16 = 0x3b, - JALX32 = 0x3c, - JAL32 = 0x3d, - BLEZC = 0x3d, - BGEZC = 0x3d, - BGEC = 0x3d, - SW32 = 0x3e, - LW32 = 0x3f -}; - -/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */ -enum { - ADDIUPC_00 = 0x00, - ADDIUPC_01 = 0x01, - ADDIUPC_02 = 0x02, - ADDIUPC_03 = 0x03, - ADDIUPC_04 = 0x04, - ADDIUPC_05 = 0x05, - ADDIUPC_06 = 0x06, - ADDIUPC_07 = 0x07, - AUIPC = 0x1e, - ALUIPC = 0x1f, - LWPC_08 = 0x08, - LWPC_09 = 0x09, - LWPC_0A = 0x0A, - LWPC_0B = 0x0B, - LWPC_0C = 0x0C, - LWPC_0D = 0x0D, - LWPC_0E = 0x0E, - LWPC_0F = 0x0F, -}; - -/* POOL32A encoding of minor opcode field */ - -enum { - /* - * These opcodes are distinguished only by bits 9..6; those bits are - * what are recorded below. - */ - SLL32 = 0x0, - SRL32 = 0x1, - SRA = 0x2, - ROTR = 0x3, - SELEQZ = 0x5, - SELNEZ = 0x6, - R6_RDHWR = 0x7, - - SLLV = 0x0, - SRLV = 0x1, - SRAV = 0x2, - ROTRV = 0x3, - ADD = 0x4, - ADDU32 = 0x5, - SUB = 0x6, - SUBU32 = 0x7, - MUL = 0x8, - AND = 0x9, - OR32 = 0xa, - NOR = 0xb, - XOR32 = 0xc, - SLT = 0xd, - SLTU = 0xe, - - MOVN = 0x0, - R6_MUL = 0x0, - MOVZ = 0x1, - MUH = 0x1, - MULU = 0x2, - MUHU = 0x3, - LWXS = 0x4, - R6_DIV = 0x4, - MOD = 0x5, - R6_DIVU = 0x6, - MODU = 0x7, - - /* The following can be distinguished by their lower 6 bits. */ - BREAK32 = 0x07, - INS = 0x0c, - LSA = 0x0f, - ALIGN = 0x1f, - EXT = 0x2c, - POOL32AXF = 0x3c, - SIGRIE = 0x3f -}; - -/* POOL32AXF encoding of minor opcode field extension */ - -/* - * 1. MIPS Architecture for Programmers Volume II-B: - * The microMIPS32 Instruction Set (Revision 3.05) - * - * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field - * - * 2. MIPS Architecture for Programmers VolumeIV-e: - * The MIPS DSP Application-Specific Extension - * to the microMIPS32 Architecture (Revision 2.34) - * - * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field - */ - -enum { - /* bits 11..6 */ - TEQ = 0x00, - TGE = 0x08, - TGEU = 0x10, - TLT = 0x20, - TLTU = 0x28, - TNE = 0x30, - - MFC0 = 0x03, - MTC0 = 0x0b, - - /* begin of microMIPS32 DSP */ - - /* bits 13..12 for 0x01 */ - MFHI_ACC = 0x0, - MFLO_ACC = 0x1, - MTHI_ACC = 0x2, - MTLO_ACC = 0x3, - - /* bits 13..12 for 0x2a */ - MADD_ACC = 0x0, - MADDU_ACC = 0x1, - MSUB_ACC = 0x2, - MSUBU_ACC = 0x3, - - /* bits 13..12 for 0x32 */ - MULT_ACC = 0x0, - MULTU_ACC = 0x1, - - /* end of microMIPS32 DSP */ - - /* bits 15..12 for 0x2c */ - BITSWAP = 0x0, - SEB = 0x2, - SEH = 0x3, - CLO = 0x4, - CLZ = 0x5, - RDHWR = 0x6, - WSBH = 0x7, - MULT = 0x8, - MULTU = 0x9, - DIV = 0xa, - DIVU = 0xb, - MADD = 0xc, - MADDU = 0xd, - MSUB = 0xe, - MSUBU = 0xf, - - /* bits 15..12 for 0x34 */ - MFC2 = 0x4, - MTC2 = 0x5, - MFHC2 = 0x8, - MTHC2 = 0x9, - CFC2 = 0xc, - CTC2 = 0xd, - - /* bits 15..12 for 0x3c */ - JALR = 0x0, - JR = 0x0, /* alias */ - JALRC = 0x0, - JRC = 0x0, - JALR_HB = 0x1, - JALRC_HB = 0x1, - JALRS = 0x4, - JALRS_HB = 0x5, - - /* bits 15..12 for 0x05 */ - RDPGPR = 0xe, - WRPGPR = 0xf, - - /* bits 15..12 for 0x0d */ - TLBP = 0x0, - TLBR = 0x1, - TLBWI = 0x2, - TLBWR = 0x3, - TLBINV = 0x4, - TLBINVF = 0x5, - WAIT = 0x9, - IRET = 0xd, - DERET = 0xe, - ERET = 0xf, - - /* bits 15..12 for 0x15 */ - DMT = 0x0, - DVPE = 0x1, - EMT = 0x2, - EVPE = 0x3, - - /* bits 15..12 for 0x1d */ - DI = 0x4, - EI = 0x5, - - /* bits 15..12 for 0x2d */ - SYNC = 0x6, - SYSCALL = 0x8, - SDBBP = 0xd, - - /* bits 15..12 for 0x35 */ - MFHI32 = 0x0, - MFLO32 = 0x1, - MTHI32 = 0x2, - MTLO32 = 0x3, -}; - -/* POOL32B encoding of minor opcode field (bits 15..12) */ - -enum { - LWC2 = 0x0, - LWP = 0x1, - LDP = 0x4, - LWM32 = 0x5, - CACHE = 0x6, - LDM = 0x7, - SWC2 = 0x8, - SWP = 0x9, - SDP = 0xc, - SWM32 = 0xd, - SDM = 0xf -}; - -/* POOL32C encoding of minor opcode field (bits 15..12) */ - -enum { - LWL = 0x0, - SWL = 0x8, - LWR = 0x1, - SWR = 0x9, - PREF = 0x2, - ST_EVA = 0xa, - LL = 0x3, - SC = 0xb, - LDL = 0x4, - SDL = 0xc, - LDR = 0x5, - SDR = 0xd, - LD_EVA = 0x6, - LWU = 0xe, - LLD = 0x7, - SCD = 0xf -}; - -/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */ - -enum { - LBUE = 0x0, - LHUE = 0x1, - LWLE = 0x2, - LWRE = 0x3, - LBE = 0x4, - LHE = 0x5, - LLE = 0x6, - LWE = 0x7, -}; - -/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */ - -enum { - SWLE = 0x0, - SWRE = 0x1, - PREFE = 0x2, - CACHEE = 0x3, - SBE = 0x4, - SHE = 0x5, - SCE = 0x6, - SWE = 0x7, -}; - -/* POOL32F encoding of minor opcode field (bits 5..0) */ - -enum { - /* These are the bit 7..6 values */ - ADD_FMT = 0x0, - - SUB_FMT = 0x1, - - MUL_FMT = 0x2, - - DIV_FMT = 0x3, - - /* These are the bit 8..6 values */ - MOVN_FMT = 0x0, - RSQRT2_FMT = 0x0, - MOVF_FMT = 0x0, - RINT_FMT = 0x0, - SELNEZ_FMT = 0x0, - - MOVZ_FMT = 0x1, - LWXC1 = 0x1, - MOVT_FMT = 0x1, - CLASS_FMT = 0x1, - SELEQZ_FMT = 0x1, - - PLL_PS = 0x2, - SWXC1 = 0x2, - SEL_FMT = 0x2, - - PLU_PS = 0x3, - LDXC1 = 0x3, - - MOVN_FMT_04 = 0x4, - PUL_PS = 0x4, - SDXC1 = 0x4, - RECIP2_FMT = 0x4, - - MOVZ_FMT_05 = 0x05, - PUU_PS = 0x5, - LUXC1 = 0x5, - - CVT_PS_S = 0x6, - SUXC1 = 0x6, - ADDR_PS = 0x6, - PREFX = 0x6, - MADDF_FMT = 0x6, - - MULR_PS = 0x7, - MSUBF_FMT = 0x7, - - MADD_S = 0x01, - MADD_D = 0x09, - MADD_PS = 0x11, - ALNV_PS = 0x19, - MSUB_S = 0x21, - MSUB_D = 0x29, - MSUB_PS = 0x31, - - NMADD_S = 0x02, - NMADD_D = 0x0a, - NMADD_PS = 0x12, - NMSUB_S = 0x22, - NMSUB_D = 0x2a, - NMSUB_PS = 0x32, - - MIN_FMT = 0x3, - MAX_FMT = 0xb, - MINA_FMT = 0x23, - MAXA_FMT = 0x2b, - POOL32FXF = 0x3b, - - CABS_COND_FMT = 0x1c, /* MIPS3D */ - C_COND_FMT = 0x3c, - - CMP_CONDN_S = 0x5, - CMP_CONDN_D = 0x15 -}; - -/* POOL32Fxf encoding of minor opcode extension field */ - -enum { - CVT_L = 0x04, - RSQRT_FMT = 0x08, - FLOOR_L = 0x0c, - CVT_PW_PS = 0x1c, - CVT_W = 0x24, - SQRT_FMT = 0x28, - FLOOR_W = 0x2c, - CVT_PS_PW = 0x3c, - CFC1 = 0x40, - RECIP_FMT = 0x48, - CEIL_L = 0x4c, - CTC1 = 0x60, - CEIL_W = 0x6c, - MFC1 = 0x80, - CVT_S_PL = 0x84, - TRUNC_L = 0x8c, - MTC1 = 0xa0, - CVT_S_PU = 0xa4, - TRUNC_W = 0xac, - MFHC1 = 0xc0, - ROUND_L = 0xcc, - MTHC1 = 0xe0, - ROUND_W = 0xec, - - MOV_FMT = 0x01, - MOVF = 0x05, - ABS_FMT = 0x0d, - RSQRT1_FMT = 0x1d, - MOVT = 0x25, - NEG_FMT = 0x2d, - CVT_D = 0x4d, - RECIP1_FMT = 0x5d, - CVT_S = 0x6d -}; - -/* POOL32I encoding of minor opcode field (bits 25..21) */ - -enum { - BLTZ = 0x00, - BLTZAL = 0x01, - BGEZ = 0x02, - BGEZAL = 0x03, - BLEZ = 0x04, - BNEZC = 0x05, - BGTZ = 0x06, - BEQZC = 0x07, - TLTI = 0x08, - BC1EQZC = 0x08, - TGEI = 0x09, - BC1NEZC = 0x09, - TLTIU = 0x0a, - BC2EQZC = 0x0a, - TGEIU = 0x0b, - BC2NEZC = 0x0a, - TNEI = 0x0c, - R6_SYNCI = 0x0c, - LUI = 0x0d, - TEQI = 0x0e, - SYNCI = 0x10, - BLTZALS = 0x11, - BGEZALS = 0x13, - BC2F = 0x14, - BC2T = 0x15, - BPOSGE64 = 0x1a, - BPOSGE32 = 0x1b, - /* These overlap and are distinguished by bit16 of the instruction */ - BC1F = 0x1c, - BC1T = 0x1d, - BC1ANY2F = 0x1c, - BC1ANY2T = 0x1d, - BC1ANY4F = 0x1e, - BC1ANY4T = 0x1f -}; - -/* POOL16A encoding of minor opcode field */ - -enum { - ADDU16 = 0x0, - SUBU16 = 0x1 -}; - -/* POOL16B encoding of minor opcode field */ - -enum { - SLL16 = 0x0, - SRL16 = 0x1 -}; - -/* POOL16C encoding of minor opcode field */ - -enum { - NOT16 = 0x00, - XOR16 = 0x04, - AND16 = 0x08, - OR16 = 0x0c, - LWM16 = 0x10, - SWM16 = 0x14, - JR16 = 0x18, - JRC16 = 0x1a, - JALR16 = 0x1c, - JALR16S = 0x1e, - MFHI16 = 0x20, - MFLO16 = 0x24, - BREAK16 = 0x28, - SDBBP16 = 0x2c, - JRADDIUSP = 0x30 -}; - -/* R6 POOL16C encoding of minor opcode field (bits 0..5) */ - -enum { - R6_NOT16 = 0x00, - R6_AND16 = 0x01, - R6_LWM16 = 0x02, - R6_JRC16 = 0x03, - MOVEP = 0x04, - MOVEP_05 = 0x05, - MOVEP_06 = 0x06, - MOVEP_07 = 0x07, - R6_XOR16 = 0x08, - R6_OR16 = 0x09, - R6_SWM16 = 0x0a, - JALRC16 = 0x0b, - MOVEP_0C = 0x0c, - MOVEP_0D = 0x0d, - MOVEP_0E = 0x0e, - MOVEP_0F = 0x0f, - JRCADDIUSP = 0x13, - R6_BREAK16 = 0x1b, - R6_SDBBP16 = 0x3b -}; - -/* POOL16D encoding of minor opcode field */ - -enum { - ADDIUS5 = 0x0, - ADDIUSP = 0x1 -}; - -/* POOL16E encoding of minor opcode field */ - -enum { - ADDIUR2 = 0x0, - ADDIUR1SP = 0x1 -}; - -static int mmreg(int r) -{ - static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; - - return map[r]; -} - -/* Used for 16-bit store instructions. */ -static int mmreg2(int r) -{ - static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 }; - - return map[r]; -} - -#define uMIPS_RD(op) ((op >> 7) & 0x7) -#define uMIPS_RS(op) ((op >> 4) & 0x7) -#define uMIPS_RS2(op) uMIPS_RS(op) -#define uMIPS_RS1(op) ((op >> 1) & 0x7) -#define uMIPS_RD5(op) ((op >> 5) & 0x1f) -#define uMIPS_RS5(op) (op & 0x1f) - -/* Signed immediate */ -#define SIMM(op, start, width) \ - ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \ - << (32 - width)) \ - >> (32 - width)) -/* Zero-extended immediate */ -#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width))) - -static void gen_addiur1sp(DisasContext *ctx) -{ - int rd = mmreg(uMIPS_RD(ctx->opcode)); - - gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2); -} - -static void gen_addiur2(DisasContext *ctx) -{ - static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 }; - int rd = mmreg(uMIPS_RD(ctx->opcode)); - int rs = mmreg(uMIPS_RS(ctx->opcode)); - - gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]); -} - -static void gen_addiusp(DisasContext *ctx) -{ - int encoded = ZIMM(ctx->opcode, 1, 9); - int decoded; - - if (encoded <= 1) { - decoded = 256 + encoded; - } else if (encoded <= 255) { - decoded = encoded; - } else if (encoded <= 509) { - decoded = encoded - 512; - } else { - decoded = encoded - 768; - } - - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2); -} - -static void gen_addius5(DisasContext *ctx) -{ - int imm = SIMM(ctx->opcode, 1, 4); - int rd = (ctx->opcode >> 5) & 0x1f; - - gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm); -} - -static void gen_andi16(DisasContext *ctx) -{ - static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16, - 31, 32, 63, 64, 255, 32768, 65535 }; - int rd = mmreg(uMIPS_RD(ctx->opcode)); - int rs = mmreg(uMIPS_RS(ctx->opcode)); - int encoded = ZIMM(ctx->opcode, 0, 4); - - gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]); -} - -static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist, - int base, int16_t offset) -{ - TCGv t0, t1; - TCGv_i32 t2; - - if (ctx->hflags & MIPS_HFLAG_BMASK) { - generate_exception_end(ctx, EXCP_RI); - return; - } - - t0 = tcg_temp_new(); - - gen_base_offset_addr(ctx, t0, base, offset); - - t1 = tcg_const_tl(reglist); - t2 = tcg_const_i32(ctx->mem_idx); - - save_cpu_state(ctx, 1); - switch (opc) { - case LWM32: - gen_helper_lwm(cpu_env, t0, t1, t2); - break; - case SWM32: - gen_helper_swm(cpu_env, t0, t1, t2); - break; -#ifdef TARGET_MIPS64 - case LDM: - gen_helper_ldm(cpu_env, t0, t1, t2); - break; - case SDM: - gen_helper_sdm(cpu_env, t0, t1, t2); - break; -#endif - } - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free_i32(t2); -} - - -static void gen_pool16c_insn(DisasContext *ctx) -{ - int rd = mmreg((ctx->opcode >> 3) & 0x7); - int rs = mmreg(ctx->opcode & 0x7); - - switch (((ctx->opcode) >> 4) & 0x3f) { - case NOT16 + 0: - case NOT16 + 1: - case NOT16 + 2: - case NOT16 + 3: - gen_logic(ctx, OPC_NOR, rd, rs, 0); - break; - case XOR16 + 0: - case XOR16 + 1: - case XOR16 + 2: - case XOR16 + 3: - gen_logic(ctx, OPC_XOR, rd, rd, rs); - break; - case AND16 + 0: - case AND16 + 1: - case AND16 + 2: - case AND16 + 3: - gen_logic(ctx, OPC_AND, rd, rd, rs); - break; - case OR16 + 0: - case OR16 + 1: - case OR16 + 2: - case OR16 + 3: - gen_logic(ctx, OPC_OR, rd, rd, rs); - break; - case LWM16 + 0: - case LWM16 + 1: - case LWM16 + 2: - case LWM16 + 3: - { - static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 }; - int offset = ZIMM(ctx->opcode, 0, 4); - - gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3], - 29, offset << 2); - } - break; - case SWM16 + 0: - case SWM16 + 1: - case SWM16 + 2: - case SWM16 + 3: - { - static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 }; - int offset = ZIMM(ctx->opcode, 0, 4); - - gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3], - 29, offset << 2); - } - break; - case JR16 + 0: - case JR16 + 1: - { - int reg = ctx->opcode & 0x1f; - - gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4); - } - break; - case JRC16 + 0: - case JRC16 + 1: - { - int reg = ctx->opcode & 0x1f; - gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0); - /* - * Let normal delay slot handling in our caller take us - * to the branch target. - */ - } - break; - case JALR16 + 0: - case JALR16 + 1: - gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - break; - case JALR16S + 0: - case JALR16S + 1: - gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - break; - case MFHI16 + 0: - case MFHI16 + 1: - gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode)); - break; - case MFLO16 + 0: - case MFLO16 + 1: - gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); - break; - case BREAK16: - generate_exception_end(ctx, EXCP_BREAK); - break; - case SDBBP16: - if (is_uhi(extract32(ctx->opcode, 0, 4))) { - gen_helper_do_semihosting(cpu_env); - } else { - /* - * XXX: not clear which exception should be raised - * when in debug mode... - */ - check_insn(ctx, ISA_MIPS32); - generate_exception_end(ctx, EXCP_DBp); - } - break; - case JRADDIUSP + 0: - case JRADDIUSP + 1: - { - int imm = ZIMM(ctx->opcode, 0, 5); - gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); - /* - * Let normal delay slot handling in our caller take us - * to the branch target. - */ - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt, - int enc_rs) -{ - int rd, rs, re, rt; - static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 }; - static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 }; - static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 }; - rd = rd_enc[enc_dest]; - re = re_enc[enc_dest]; - rs = rs_rt_enc[enc_rs]; - rt = rs_rt_enc[enc_rt]; - if (rs) { - tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); - } else { - tcg_gen_movi_tl(cpu_gpr[rd], 0); - } - if (rt) { - tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]); - } else { - tcg_gen_movi_tl(cpu_gpr[re], 0); - } -} - -static void gen_pool16c_r6_insn(DisasContext *ctx) -{ - int rt = mmreg((ctx->opcode >> 7) & 0x7); - int rs = mmreg((ctx->opcode >> 4) & 0x7); - - switch (ctx->opcode & 0xf) { - case R6_NOT16: - gen_logic(ctx, OPC_NOR, rt, rs, 0); - break; - case R6_AND16: - gen_logic(ctx, OPC_AND, rt, rt, rs); - break; - case R6_LWM16: - { - int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2); - int offset = extract32(ctx->opcode, 4, 4); - gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2); - } - break; - case R6_JRC16: /* JRCADDIUSP */ - if ((ctx->opcode >> 4) & 1) { - /* JRCADDIUSP */ - int imm = extract32(ctx->opcode, 5, 5); - gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); - } else { - /* JRC16 */ - rs = extract32(ctx->opcode, 5, 5); - gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0); - } - break; - case MOVEP: - case MOVEP_05: - case MOVEP_06: - case MOVEP_07: - case MOVEP_0C: - case MOVEP_0D: - case MOVEP_0E: - case MOVEP_0F: - { - int enc_dest = uMIPS_RD(ctx->opcode); - int enc_rt = uMIPS_RS2(ctx->opcode); - int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4); - gen_movep(ctx, enc_dest, enc_rt, enc_rs); - } - break; - case R6_XOR16: - gen_logic(ctx, OPC_XOR, rt, rt, rs); - break; - case R6_OR16: - gen_logic(ctx, OPC_OR, rt, rt, rs); - break; - case R6_SWM16: - { - int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2); - int offset = extract32(ctx->opcode, 4, 4); - gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2); - } - break; - case JALRC16: /* BREAK16, SDBBP16 */ - switch (ctx->opcode & 0x3f) { - case JALRC16: - case JALRC16 + 0x20: - /* JALRC16 */ - gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f, - 31, 0, 0); - break; - case R6_BREAK16: - /* BREAK16 */ - generate_exception(ctx, EXCP_BREAK); - break; - case R6_SDBBP16: - /* SDBBP16 */ - if (is_uhi(extract32(ctx->opcode, 6, 4))) { - gen_helper_do_semihosting(cpu_env); - } else { - if (ctx->hflags & MIPS_HFLAG_SBRI) { - generate_exception(ctx, EXCP_RI); - } else { - generate_exception(ctx, EXCP_DBp); - } - } - break; - } - break; - default: - generate_exception(ctx, EXCP_RI); - break; - } -} - -static void gen_ldxs(DisasContext *ctx, int base, int index, int rd) -{ - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - gen_load_gpr(t0, base); - - if (index != 0) { - gen_load_gpr(t1, index); - tcg_gen_shli_tl(t1, t1, 2); - gen_op_addr_add(ctx, t0, t1, t0); - } - - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); - gen_store_gpr(t1, rd); - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd, - int base, int16_t offset) -{ - TCGv t0, t1; - - if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) { - generate_exception_end(ctx, EXCP_RI); - return; - } - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - - gen_base_offset_addr(ctx, t0, base, offset); - - switch (opc) { - case LWP: - if (rd == base) { - generate_exception_end(ctx, EXCP_RI); - return; - } - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); - gen_store_gpr(t1, rd); - tcg_gen_movi_tl(t1, 4); - gen_op_addr_add(ctx, t0, t0, t1); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); - gen_store_gpr(t1, rd + 1); - break; - case SWP: - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - tcg_gen_movi_tl(t1, 4); - gen_op_addr_add(ctx, t0, t0, t1); - gen_load_gpr(t1, rd + 1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - break; -#ifdef TARGET_MIPS64 - case LDP: - if (rd == base) { - generate_exception_end(ctx, EXCP_RI); - return; - } - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); - gen_store_gpr(t1, rd); - tcg_gen_movi_tl(t1, 8); - gen_op_addr_add(ctx, t0, t0, t1); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); - gen_store_gpr(t1, rd + 1); - break; - case SDP: - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); - tcg_gen_movi_tl(t1, 8); - gen_op_addr_add(ctx, t0, t0, t1); - gen_load_gpr(t1, rd + 1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); - break; -#endif - } - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -static void gen_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 gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs) -{ - int extension = (ctx->opcode >> 6) & 0x3f; - int minor = (ctx->opcode >> 12) & 0xf; - uint32_t mips32_op; - - switch (extension) { - case TEQ: - mips32_op = OPC_TEQ; - goto do_trap; - case TGE: - mips32_op = OPC_TGE; - goto do_trap; - case TGEU: - mips32_op = OPC_TGEU; - goto do_trap; - case TLT: - mips32_op = OPC_TLT; - goto do_trap; - case TLTU: - mips32_op = OPC_TLTU; - goto do_trap; - case TNE: - mips32_op = OPC_TNE; - do_trap: - gen_trap(ctx, mips32_op, rs, rt, -1); - break; -#ifndef CONFIG_USER_ONLY - case MFC0: - case MFC0 + 32: - check_cp0_enabled(ctx); - if (rt == 0) { - /* Treat as NOP. */ - break; - } - gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7); - break; - case MTC0: - case MTC0 + 32: - check_cp0_enabled(ctx); - { - TCGv t0 = tcg_temp_new(); - - gen_load_gpr(t0, rt); - gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7); - tcg_temp_free(t0); - } - break; -#endif - case 0x2a: - switch (minor & 3) { - case MADD_ACC: - gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt); - break; - case MADDU_ACC: - gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt); - break; - case MSUB_ACC: - gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt); - break; - case MSUBU_ACC: - gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x32: - switch (minor & 3) { - case MULT_ACC: - gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt); - break; - case MULTU_ACC: - gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x2c: - switch (minor) { - case BITSWAP: - check_insn(ctx, ISA_MIPS32R6); - gen_bitswap(ctx, OPC_BITSWAP, rs, rt); - break; - case SEB: - gen_bshfl(ctx, OPC_SEB, rs, rt); - break; - case SEH: - gen_bshfl(ctx, OPC_SEH, rs, rt); - break; - case CLO: - mips32_op = OPC_CLO; - goto do_cl; - case CLZ: - mips32_op = OPC_CLZ; - do_cl: - check_insn(ctx, ISA_MIPS32); - gen_cl(ctx, mips32_op, rt, rs); - break; - case RDHWR: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_rdhwr(ctx, rt, rs, 0); - break; - case WSBH: - gen_bshfl(ctx, OPC_WSBH, rs, rt); - break; - case MULT: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MULT; - goto do_mul; - case MULTU: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MULTU; - goto do_mul; - case DIV: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_DIV; - goto do_div; - case DIVU: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_DIVU; - goto do_div; - do_div: - check_insn(ctx, ISA_MIPS32); - gen_muldiv(ctx, mips32_op, 0, rs, rt); - break; - case MADD: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MADD; - goto do_mul; - case MADDU: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MADDU; - goto do_mul; - case MSUB: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MSUB; - goto do_mul; - case MSUBU: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MSUBU; - do_mul: - check_insn(ctx, ISA_MIPS32); - gen_muldiv(ctx, mips32_op, 0, rs, rt); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x34: - switch (minor) { - case MFC2: - case MTC2: - case MFHC2: - case MTHC2: - case CFC2: - case CTC2: - generate_exception_err(ctx, EXCP_CpU, 2); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x3c: - switch (minor) { - case JALR: /* JALRC */ - case JALR_HB: /* JALRC_HB */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* JALRC, JALRC_HB */ - gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0); - } else { - /* JALR, JALR_HB */ - gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - } - break; - case JALRS: - case JALRS_HB: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - break; - default: - goto pool32axf_invalid; - } - break; - case 0x05: - switch (minor) { - case RDPGPR: - check_cp0_enabled(ctx); - check_insn(ctx, ISA_MIPS32R2); - gen_load_srsgpr(rs, rt); - break; - case WRPGPR: - check_cp0_enabled(ctx); - check_insn(ctx, ISA_MIPS32R2); - gen_store_srsgpr(rs, rt); - break; - default: - goto pool32axf_invalid; - } - break; -#ifndef CONFIG_USER_ONLY - case 0x0d: - switch (minor) { - case TLBP: - mips32_op = OPC_TLBP; - goto do_cp0; - case TLBR: - mips32_op = OPC_TLBR; - goto do_cp0; - case TLBWI: - mips32_op = OPC_TLBWI; - goto do_cp0; - case TLBWR: - mips32_op = OPC_TLBWR; - goto do_cp0; - case TLBINV: - mips32_op = OPC_TLBINV; - goto do_cp0; - case TLBINVF: - mips32_op = OPC_TLBINVF; - goto do_cp0; - case WAIT: - mips32_op = OPC_WAIT; - goto do_cp0; - case DERET: - mips32_op = OPC_DERET; - goto do_cp0; - case ERET: - mips32_op = OPC_ERET; - do_cp0: - gen_cp0(env, ctx, mips32_op, rt, rs); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x1d: - switch (minor) { - case DI: - check_cp0_enabled(ctx); - { - TCGv t0 = tcg_temp_new(); - - save_cpu_state(ctx, 1); - gen_helper_di(t0, cpu_env); - gen_store_gpr(t0, rs); - /* - * Stop translation as we may have switched the execution - * mode. - */ - ctx->base.is_jmp = DISAS_STOP; - tcg_temp_free(t0); - } - break; - case EI: - check_cp0_enabled(ctx); - { - TCGv t0 = tcg_temp_new(); - - save_cpu_state(ctx, 1); - gen_helper_ei(t0, cpu_env); - gen_store_gpr(t0, rs); - /* - * DISAS_STOP isn't sufficient, we need to ensure we break out - * of translated code to check for pending interrupts. - */ - gen_save_pc(ctx->base.pc_next + 4); - ctx->base.is_jmp = DISAS_EXIT; - tcg_temp_free(t0); - } - break; - default: - goto pool32axf_invalid; - } - break; -#endif - case 0x2d: - switch (minor) { - case SYNC: - gen_sync(extract32(ctx->opcode, 16, 5)); - break; - case SYSCALL: - generate_exception_end(ctx, EXCP_SYSCALL); - break; - case SDBBP: - if (is_uhi(extract32(ctx->opcode, 16, 10))) { - gen_helper_do_semihosting(cpu_env); - } else { - check_insn(ctx, ISA_MIPS32); - if (ctx->hflags & MIPS_HFLAG_SBRI) { - generate_exception_end(ctx, EXCP_RI); - } else { - generate_exception_end(ctx, EXCP_DBp); - } - } - break; - default: - goto pool32axf_invalid; - } - break; - case 0x01: - switch (minor & 3) { - case MFHI_ACC: - gen_HILO(ctx, OPC_MFHI, minor >> 2, rs); - break; - case MFLO_ACC: - gen_HILO(ctx, OPC_MFLO, minor >> 2, rs); - break; - case MTHI_ACC: - gen_HILO(ctx, OPC_MTHI, minor >> 2, rs); - break; - case MTLO_ACC: - gen_HILO(ctx, OPC_MTLO, minor >> 2, rs); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x35: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - switch (minor) { - case MFHI32: - gen_HILO(ctx, OPC_MFHI, 0, rs); - break; - case MFLO32: - gen_HILO(ctx, OPC_MFLO, 0, rs); - break; - case MTHI32: - gen_HILO(ctx, OPC_MTHI, 0, rs); - break; - case MTLO32: - gen_HILO(ctx, OPC_MTLO, 0, rs); - break; - default: - goto pool32axf_invalid; - } - break; - default: - pool32axf_invalid: - MIPS_INVAL("pool32axf"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * Values for microMIPS fmt field. Variable-width, depending on which - * formats the instruction supports. - */ -enum { - FMT_SD_S = 0, - FMT_SD_D = 1, - - FMT_SDPS_S = 0, - FMT_SDPS_D = 1, - FMT_SDPS_PS = 2, - - FMT_SWL_S = 0, - FMT_SWL_W = 1, - FMT_SWL_L = 2, - - FMT_DWL_D = 0, - FMT_DWL_W = 1, - FMT_DWL_L = 2 -}; - -static void gen_pool32fxf(DisasContext *ctx, int rt, int rs) -{ - int extension = (ctx->opcode >> 6) & 0x3ff; - uint32_t mips32_op; - -#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc) -#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc) -#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc) - - switch (extension) { - case FLOAT_1BIT_FMT(CFC1, 0): - mips32_op = OPC_CFC1; - goto do_cp1; - case FLOAT_1BIT_FMT(CTC1, 0): - mips32_op = OPC_CTC1; - goto do_cp1; - case FLOAT_1BIT_FMT(MFC1, 0): - mips32_op = OPC_MFC1; - goto do_cp1; - case FLOAT_1BIT_FMT(MTC1, 0): - mips32_op = OPC_MTC1; - goto do_cp1; - case FLOAT_1BIT_FMT(MFHC1, 0): - mips32_op = OPC_MFHC1; - goto do_cp1; - case FLOAT_1BIT_FMT(MTHC1, 0): - mips32_op = OPC_MTHC1; - do_cp1: - gen_cp1(ctx, mips32_op, rt, rs); - break; - - /* Reciprocal square root */ - case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S): - mips32_op = OPC_RSQRT_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D): - mips32_op = OPC_RSQRT_D; - goto do_unaryfp; - - /* Square root */ - case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S): - mips32_op = OPC_SQRT_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D): - mips32_op = OPC_SQRT_D; - goto do_unaryfp; - - /* Reciprocal */ - case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S): - mips32_op = OPC_RECIP_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D): - mips32_op = OPC_RECIP_D; - goto do_unaryfp; - - /* Floor */ - case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S): - mips32_op = OPC_FLOOR_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D): - mips32_op = OPC_FLOOR_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S): - mips32_op = OPC_FLOOR_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D): - mips32_op = OPC_FLOOR_W_D; - goto do_unaryfp; - - /* Ceiling */ - case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S): - mips32_op = OPC_CEIL_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D): - mips32_op = OPC_CEIL_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S): - mips32_op = OPC_CEIL_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D): - mips32_op = OPC_CEIL_W_D; - goto do_unaryfp; - - /* Truncation */ - case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S): - mips32_op = OPC_TRUNC_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D): - mips32_op = OPC_TRUNC_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S): - mips32_op = OPC_TRUNC_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D): - mips32_op = OPC_TRUNC_W_D; - goto do_unaryfp; - - /* Round */ - case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S): - mips32_op = OPC_ROUND_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D): - mips32_op = OPC_ROUND_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S): - mips32_op = OPC_ROUND_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D): - mips32_op = OPC_ROUND_W_D; - goto do_unaryfp; - - /* Integer to floating-point conversion */ - case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S): - mips32_op = OPC_CVT_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D): - mips32_op = OPC_CVT_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S): - mips32_op = OPC_CVT_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D): - mips32_op = OPC_CVT_W_D; - goto do_unaryfp; - - /* Paired-foo conversions */ - case FLOAT_1BIT_FMT(CVT_S_PL, 0): - mips32_op = OPC_CVT_S_PL; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_S_PU, 0): - mips32_op = OPC_CVT_S_PU; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_PW_PS, 0): - mips32_op = OPC_CVT_PW_PS; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_PS_PW, 0): - mips32_op = OPC_CVT_PS_PW; - goto do_unaryfp; - - /* Floating-point moves */ - case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S): - mips32_op = OPC_MOV_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D): - mips32_op = OPC_MOV_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS): - mips32_op = OPC_MOV_PS; - goto do_unaryfp; - - /* Absolute value */ - case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S): - mips32_op = OPC_ABS_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D): - mips32_op = OPC_ABS_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS): - mips32_op = OPC_ABS_PS; - goto do_unaryfp; - - /* Negation */ - case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S): - mips32_op = OPC_NEG_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D): - mips32_op = OPC_NEG_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS): - mips32_op = OPC_NEG_PS; - goto do_unaryfp; - - /* Reciprocal square root step */ - case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S): - mips32_op = OPC_RSQRT1_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D): - mips32_op = OPC_RSQRT1_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS): - mips32_op = OPC_RSQRT1_PS; - goto do_unaryfp; - - /* Reciprocal step */ - case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S): - mips32_op = OPC_RECIP1_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D): - mips32_op = OPC_RECIP1_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS): - mips32_op = OPC_RECIP1_PS; - goto do_unaryfp; - - /* Conversions from double */ - case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S): - mips32_op = OPC_CVT_D_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W): - mips32_op = OPC_CVT_D_W; - goto do_unaryfp; - case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L): - mips32_op = OPC_CVT_D_L; - goto do_unaryfp; - - /* Conversions from single */ - case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D): - mips32_op = OPC_CVT_S_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W): - mips32_op = OPC_CVT_S_W; - goto do_unaryfp; - case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L): - mips32_op = OPC_CVT_S_L; - do_unaryfp: - gen_farith(ctx, mips32_op, -1, rs, rt, 0); - break; - - /* Conditional moves on floating-point codes */ - case COND_FLOAT_MOV(MOVT, 0): - case COND_FLOAT_MOV(MOVT, 1): - case COND_FLOAT_MOV(MOVT, 2): - case COND_FLOAT_MOV(MOVT, 3): - case COND_FLOAT_MOV(MOVT, 4): - case COND_FLOAT_MOV(MOVT, 5): - case COND_FLOAT_MOV(MOVT, 6): - case COND_FLOAT_MOV(MOVT, 7): - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1); - break; - case COND_FLOAT_MOV(MOVF, 0): - case COND_FLOAT_MOV(MOVF, 1): - case COND_FLOAT_MOV(MOVF, 2): - case COND_FLOAT_MOV(MOVF, 3): - case COND_FLOAT_MOV(MOVF, 4): - case COND_FLOAT_MOV(MOVF, 5): - case COND_FLOAT_MOV(MOVF, 6): - case COND_FLOAT_MOV(MOVF, 7): - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0); - break; - default: - MIPS_INVAL("pool32fxf"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) -{ - int32_t offset; - uint16_t insn; - int rt, rs, rd, rr; - int16_t imm; - uint32_t op, minor, minor2, mips32_op; - uint32_t cond, fmt, cc; - - insn = cpu_lduw_code(env, ctx->base.pc_next + 2); - ctx->opcode = (ctx->opcode << 16) | insn; - - rt = (ctx->opcode >> 21) & 0x1f; - rs = (ctx->opcode >> 16) & 0x1f; - rd = (ctx->opcode >> 11) & 0x1f; - rr = (ctx->opcode >> 6) & 0x1f; - imm = (int16_t) ctx->opcode; - - op = (ctx->opcode >> 26) & 0x3f; - switch (op) { - case POOL32A: - minor = ctx->opcode & 0x3f; - switch (minor) { - case 0x00: - minor = (ctx->opcode >> 6) & 0xf; - switch (minor) { - case SLL32: - mips32_op = OPC_SLL; - goto do_shifti; - case SRA: - mips32_op = OPC_SRA; - goto do_shifti; - case SRL32: - mips32_op = OPC_SRL; - goto do_shifti; - case ROTR: - mips32_op = OPC_ROTR; - do_shifti: - gen_shift_imm(ctx, mips32_op, rt, rs, rd); - break; - case SELEQZ: - check_insn(ctx, ISA_MIPS32R6); - gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt); - break; - case SELNEZ: - check_insn(ctx, ISA_MIPS32R6); - gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt); - break; - case R6_RDHWR: - check_insn(ctx, ISA_MIPS32R6); - gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); - break; - default: - goto pool32a_invalid; - } - break; - case 0x10: - minor = (ctx->opcode >> 6) & 0xf; - switch (minor) { - /* Arithmetic */ - case ADD: - mips32_op = OPC_ADD; - goto do_arith; - case ADDU32: - mips32_op = OPC_ADDU; - goto do_arith; - case SUB: - mips32_op = OPC_SUB; - goto do_arith; - case SUBU32: - mips32_op = OPC_SUBU; - goto do_arith; - case MUL: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MUL; - do_arith: - gen_arith(ctx, mips32_op, rd, rs, rt); - break; - /* Shifts */ - case SLLV: - mips32_op = OPC_SLLV; - goto do_shift; - case SRLV: - mips32_op = OPC_SRLV; - goto do_shift; - case SRAV: - mips32_op = OPC_SRAV; - goto do_shift; - case ROTRV: - mips32_op = OPC_ROTRV; - do_shift: - gen_shift(ctx, mips32_op, rd, rs, rt); - break; - /* Logical operations */ - case AND: - mips32_op = OPC_AND; - goto do_logic; - case OR32: - mips32_op = OPC_OR; - goto do_logic; - case NOR: - mips32_op = OPC_NOR; - goto do_logic; - case XOR32: - mips32_op = OPC_XOR; - do_logic: - gen_logic(ctx, mips32_op, rd, rs, rt); - break; - /* Set less than */ - case SLT: - mips32_op = OPC_SLT; - goto do_slt; - case SLTU: - mips32_op = OPC_SLTU; - do_slt: - gen_slt(ctx, mips32_op, rd, rs, rt); - break; - default: - goto pool32a_invalid; - } - break; - case 0x18: - minor = (ctx->opcode >> 6) & 0xf; - switch (minor) { - /* Conditional moves */ - case MOVN: /* MUL */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* MUL */ - gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); - } else { - /* MOVN */ - gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); - } - break; - case MOVZ: /* MUH */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* MUH */ - gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); - } else { - /* MOVZ */ - gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); - } - break; - case MULU: - check_insn(ctx, ISA_MIPS32R6); - gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); - break; - case MUHU: - check_insn(ctx, ISA_MIPS32R6); - gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); - break; - case LWXS: /* DIV */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* DIV */ - gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); - } else { - /* LWXS */ - gen_ldxs(ctx, rs, rt, rd); - } - break; - case MOD: - check_insn(ctx, ISA_MIPS32R6); - gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); - break; - case R6_DIVU: - check_insn(ctx, ISA_MIPS32R6); - gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); - break; - case MODU: - check_insn(ctx, ISA_MIPS32R6); - gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); - break; - default: - goto pool32a_invalid; - } - break; - case INS: - gen_bitops(ctx, OPC_INS, rt, rs, rr, rd); - return; - case LSA: - check_insn(ctx, ISA_MIPS32R6); - gen_lsa(ctx, OPC_LSA, rd, rs, rt, - extract32(ctx->opcode, 9, 2)); - break; - case ALIGN: - check_insn(ctx, ISA_MIPS32R6); - gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2)); - break; - case EXT: - gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd); - return; - case POOL32AXF: - gen_pool32axf(env, ctx, rt, rs); - break; - case BREAK32: - generate_exception_end(ctx, EXCP_BREAK); - break; - case SIGRIE: - check_insn(ctx, ISA_MIPS32R6); - generate_exception_end(ctx, EXCP_RI); - break; - default: - pool32a_invalid: - MIPS_INVAL("pool32a"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case POOL32B: - minor = (ctx->opcode >> 12) & 0xf; - switch (minor) { - case CACHE: - check_cp0_enabled(ctx); - if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { - gen_cache_operation(ctx, rt, rs, imm); - } - break; - case LWC2: - case SWC2: - /* COP2: Not implemented. */ - generate_exception_err(ctx, EXCP_CpU, 2); - break; -#ifdef TARGET_MIPS64 - case LDP: - case SDP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); -#endif - /* fall through */ - case LWP: - case SWP: - gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12)); - break; -#ifdef TARGET_MIPS64 - case LDM: - case SDM: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); -#endif - /* fall through */ - case LWM32: - case SWM32: - gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12)); - break; - default: - MIPS_INVAL("pool32b"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case POOL32F: - if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { - minor = ctx->opcode & 0x3f; - check_cp1_enabled(ctx); - switch (minor) { - case ALNV_PS: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_ALNV_PS; - goto do_madd; - case MADD_S: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MADD_S; - goto do_madd; - case MADD_D: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MADD_D; - goto do_madd; - case MADD_PS: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MADD_PS; - goto do_madd; - case MSUB_S: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MSUB_S; - goto do_madd; - case MSUB_D: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MSUB_D; - goto do_madd; - case MSUB_PS: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_MSUB_PS; - goto do_madd; - case NMADD_S: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_NMADD_S; - goto do_madd; - case NMADD_D: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_NMADD_D; - goto do_madd; - case NMADD_PS: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_NMADD_PS; - goto do_madd; - case NMSUB_S: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_NMSUB_S; - goto do_madd; - case NMSUB_D: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_NMSUB_D; - goto do_madd; - case NMSUB_PS: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_NMSUB_PS; - do_madd: - gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt); - break; - case CABS_COND_FMT: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - cond = (ctx->opcode >> 6) & 0xf; - cc = (ctx->opcode >> 13) & 0x7; - fmt = (ctx->opcode >> 10) & 0x3; - switch (fmt) { - case 0x0: - gen_cmpabs_s(ctx, cond, rt, rs, cc); - break; - case 0x1: - gen_cmpabs_d(ctx, cond, rt, rs, cc); - break; - case 0x2: - gen_cmpabs_ps(ctx, cond, rt, rs, cc); - break; - default: - goto pool32f_invalid; - } - break; - case C_COND_FMT: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - cond = (ctx->opcode >> 6) & 0xf; - cc = (ctx->opcode >> 13) & 0x7; - fmt = (ctx->opcode >> 10) & 0x3; - switch (fmt) { - case 0x0: - gen_cmp_s(ctx, cond, rt, rs, cc); - break; - case 0x1: - gen_cmp_d(ctx, cond, rt, rs, cc); - break; - case 0x2: - gen_cmp_ps(ctx, cond, rt, rs, cc); - break; - default: - goto pool32f_invalid; - } - break; - case CMP_CONDN_S: - check_insn(ctx, ISA_MIPS32R6); - gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); - break; - case CMP_CONDN_D: - check_insn(ctx, ISA_MIPS32R6); - gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); - break; - case POOL32FXF: - gen_pool32fxf(ctx, rt, rs); - break; - case 0x00: - /* PLL foo */ - switch ((ctx->opcode >> 6) & 0x7) { - case PLL_PS: - mips32_op = OPC_PLL_PS; - goto do_ps; - case PLU_PS: - mips32_op = OPC_PLU_PS; - goto do_ps; - case PUL_PS: - mips32_op = OPC_PUL_PS; - goto do_ps; - case PUU_PS: - mips32_op = OPC_PUU_PS; - goto do_ps; - case CVT_PS_S: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_CVT_PS_S; - do_ps: - gen_farith(ctx, mips32_op, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case MIN_FMT: - check_insn(ctx, ISA_MIPS32R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case 0x08: - /* [LS][WDU]XC1 */ - switch ((ctx->opcode >> 6) & 0x7) { - case LWXC1: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LWXC1; - goto do_ldst_cp1; - case SWXC1: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SWXC1; - goto do_ldst_cp1; - case LDXC1: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LDXC1; - goto do_ldst_cp1; - case SDXC1: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SDXC1; - goto do_ldst_cp1; - case LUXC1: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LUXC1; - goto do_ldst_cp1; - case SUXC1: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SUXC1; - do_ldst_cp1: - gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs); - break; - default: - goto pool32f_invalid; - } - break; - case MAX_FMT: - check_insn(ctx, ISA_MIPS32R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case 0x18: - /* 3D insns */ - check_insn_opc_removed(ctx, ISA_MIPS32R6); - fmt = (ctx->opcode >> 9) & 0x3; - switch ((ctx->opcode >> 6) & 0x7) { - case RSQRT2_FMT: - switch (fmt) { - case FMT_SDPS_S: - mips32_op = OPC_RSQRT2_S; - goto do_3d; - case FMT_SDPS_D: - mips32_op = OPC_RSQRT2_D; - goto do_3d; - case FMT_SDPS_PS: - mips32_op = OPC_RSQRT2_PS; - goto do_3d; - default: - goto pool32f_invalid; - } - break; - case RECIP2_FMT: - switch (fmt) { - case FMT_SDPS_S: - mips32_op = OPC_RECIP2_S; - goto do_3d; - case FMT_SDPS_D: - mips32_op = OPC_RECIP2_D; - goto do_3d; - case FMT_SDPS_PS: - mips32_op = OPC_RECIP2_PS; - goto do_3d; - default: - goto pool32f_invalid; - } - break; - case ADDR_PS: - mips32_op = OPC_ADDR_PS; - goto do_3d; - case MULR_PS: - mips32_op = OPC_MULR_PS; - do_3d: - gen_farith(ctx, mips32_op, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case 0x20: - /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/ - cc = (ctx->opcode >> 13) & 0x7; - fmt = (ctx->opcode >> 9) & 0x3; - switch ((ctx->opcode >> 6) & 0x7) { - case MOVF_FMT: /* RINT_FMT */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* RINT_FMT */ - switch (fmt) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); - break; - default: - goto pool32f_invalid; - } - } else { - /* MOVF_FMT */ - switch (fmt) { - case FMT_SDPS_S: - gen_movcf_s(ctx, rs, rt, cc, 0); - break; - case FMT_SDPS_D: - gen_movcf_d(ctx, rs, rt, cc, 0); - break; - case FMT_SDPS_PS: - check_ps(ctx); - gen_movcf_ps(ctx, rs, rt, cc, 0); - break; - default: - goto pool32f_invalid; - } - } - break; - case MOVT_FMT: /* CLASS_FMT */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* CLASS_FMT */ - switch (fmt) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); - break; - default: - goto pool32f_invalid; - } - } else { - /* MOVT_FMT */ - switch (fmt) { - case FMT_SDPS_S: - gen_movcf_s(ctx, rs, rt, cc, 1); - break; - case FMT_SDPS_D: - gen_movcf_d(ctx, rs, rt, cc, 1); - break; - case FMT_SDPS_PS: - check_ps(ctx); - gen_movcf_ps(ctx, rs, rt, cc, 1); - break; - default: - goto pool32f_invalid; - } - } - break; - case PREFX: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - break; - default: - goto pool32f_invalid; - } - break; -#define FINSN_3ARG_SDPS(prfx) \ - switch ((ctx->opcode >> 8) & 0x3) { \ - case FMT_SDPS_S: \ - mips32_op = OPC_##prfx##_S; \ - goto do_fpop; \ - case FMT_SDPS_D: \ - mips32_op = OPC_##prfx##_D; \ - goto do_fpop; \ - case FMT_SDPS_PS: \ - check_ps(ctx); \ - mips32_op = OPC_##prfx##_PS; \ - goto do_fpop; \ - default: \ - goto pool32f_invalid; \ - } - case MINA_FMT: - check_insn(ctx, ISA_MIPS32R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case MAXA_FMT: - check_insn(ctx, ISA_MIPS32R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case 0x30: - /* regular FP ops */ - switch ((ctx->opcode >> 6) & 0x3) { - case ADD_FMT: - FINSN_3ARG_SDPS(ADD); - break; - case SUB_FMT: - FINSN_3ARG_SDPS(SUB); - break; - case MUL_FMT: - FINSN_3ARG_SDPS(MUL); - break; - case DIV_FMT: - fmt = (ctx->opcode >> 8) & 0x3; - if (fmt == 1) { - mips32_op = OPC_DIV_D; - } else if (fmt == 0) { - mips32_op = OPC_DIV_S; - } else { - goto pool32f_invalid; - } - goto do_fpop; - default: - goto pool32f_invalid; - } - break; - case 0x38: - /* cmovs */ - switch ((ctx->opcode >> 6) & 0x7) { - case MOVN_FMT: /* SELEQZ_FMT */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* SELEQZ_FMT */ - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); - break; - case FMT_SDPS_D: - gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); - break; - default: - goto pool32f_invalid; - } - } else { - /* MOVN_FMT */ - FINSN_3ARG_SDPS(MOVN); - } - break; - case MOVN_FMT_04: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - FINSN_3ARG_SDPS(MOVN); - break; - case MOVZ_FMT: /* SELNEZ_FMT */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* SELNEZ_FMT */ - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); - break; - case FMT_SDPS_D: - gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); - break; - default: - goto pool32f_invalid; - } - } else { - /* MOVZ_FMT */ - FINSN_3ARG_SDPS(MOVZ); - } - break; - case MOVZ_FMT_05: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - FINSN_3ARG_SDPS(MOVZ); - break; - case SEL_FMT: - check_insn(ctx, ISA_MIPS32R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); - break; - case FMT_SDPS_D: - gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); - break; - default: - goto pool32f_invalid; - } - break; - case MADDF_FMT: - check_insn(ctx, ISA_MIPS32R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - mips32_op = OPC_MADDF_S; - goto do_fpop; - case FMT_SDPS_D: - mips32_op = OPC_MADDF_D; - goto do_fpop; - default: - goto pool32f_invalid; - } - break; - case MSUBF_FMT: - check_insn(ctx, ISA_MIPS32R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - mips32_op = OPC_MSUBF_S; - goto do_fpop; - case FMT_SDPS_D: - mips32_op = OPC_MSUBF_D; - goto do_fpop; - default: - goto pool32f_invalid; - } - break; - default: - goto pool32f_invalid; - } - break; - do_fpop: - gen_farith(ctx, mips32_op, rt, rs, rd, 0); - break; - default: - pool32f_invalid: - MIPS_INVAL("pool32f"); - generate_exception_end(ctx, EXCP_RI); - break; - } - } else { - generate_exception_err(ctx, EXCP_CpU, 1); - } - break; - case POOL32I: - minor = (ctx->opcode >> 21) & 0x1f; - switch (minor) { - case BLTZ: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4); - break; - case BLTZAL: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - break; - case BLTZALS: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - break; - case BGEZ: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4); - break; - case BGEZAL: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - break; - case BGEZALS: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - break; - case BLEZ: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4); - break; - case BGTZ: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4); - break; - - /* Traps */ - case TLTI: /* BC1EQZC */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* BC1EQZC */ - check_cp1_enabled(ctx); - gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0); - } else { - /* TLTI */ - mips32_op = OPC_TLTI; - goto do_trapi; - } - break; - case TGEI: /* BC1NEZC */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* BC1NEZC */ - check_cp1_enabled(ctx); - gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0); - } else { - /* TGEI */ - mips32_op = OPC_TGEI; - goto do_trapi; - } - break; - case TLTIU: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_TLTIU; - goto do_trapi; - case TGEIU: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_TGEIU; - goto do_trapi; - case TNEI: /* SYNCI */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* SYNCI */ - /* - * Break the TB to be able to sync copied instructions - * immediately. - */ - ctx->base.is_jmp = DISAS_STOP; - } else { - /* TNEI */ - mips32_op = OPC_TNEI; - goto do_trapi; - } - break; - case TEQI: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_TEQI; - do_trapi: - gen_trap(ctx, mips32_op, rs, -1, imm); - break; - - case BNEZC: - case BEQZC: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ, - 4, rs, 0, imm << 1, 0); - /* - * Compact branches don't have a delay slot, so just let - * the normal delay slot handling take us to the branch - * target. - */ - break; - case LUI: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_logic_imm(ctx, OPC_LUI, rs, 0, imm); - break; - case SYNCI: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - /* - * Break the TB to be able to sync copied instructions - * immediately. - */ - ctx->base.is_jmp = DISAS_STOP; - break; - case BC2F: - case BC2T: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - /* COP2: Not implemented. */ - generate_exception_err(ctx, EXCP_CpU, 2); - break; - case BC1F: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F; - goto do_cp1branch; - case BC1T: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T; - goto do_cp1branch; - case BC1ANY4F: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_BC1FANY4; - goto do_cp1mips3d; - case BC1ANY4T: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_BC1TANY4; - do_cp1mips3d: - check_cop1x(ctx); - check_insn(ctx, ASE_MIPS3D); - /* Fall through */ - do_cp1branch: - if (env->CP0_Config1 & (1 << CP0C1_FP)) { - check_cp1_enabled(ctx); - gen_compute_branch1(ctx, mips32_op, - (ctx->opcode >> 18) & 0x7, imm << 1); - } else { - generate_exception_err(ctx, EXCP_CpU, 1); - } - break; - case BPOSGE64: - case BPOSGE32: - /* MIPS DSP: not implemented */ - /* Fall through */ - default: - MIPS_INVAL("pool32i"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case POOL32C: - minor = (ctx->opcode >> 12) & 0xf; - offset = sextract32(ctx->opcode, 0, - (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12); - switch (minor) { - case LWL: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LWL; - goto do_ld_lr; - case SWL: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SWL; - goto do_st_lr; - case LWR: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LWR; - goto do_ld_lr; - case SWR: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SWR; - goto do_st_lr; -#if defined(TARGET_MIPS64) - case LDL: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LDL; - goto do_ld_lr; - case SDL: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SDL; - goto do_st_lr; - case LDR: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LDR; - goto do_ld_lr; - case SDR: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SDR; - goto do_st_lr; - case LWU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - mips32_op = OPC_LWU; - goto do_ld_lr; - case LLD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - mips32_op = OPC_LLD; - goto do_ld_lr; -#endif - case LL: - mips32_op = OPC_LL; - goto do_ld_lr; - do_ld_lr: - gen_ld(ctx, mips32_op, rt, rs, offset); - break; - do_st_lr: - gen_st(ctx, mips32_op, rt, rs, offset); - break; - case SC: - gen_st_cond(ctx, rt, rs, offset, MO_TESL, false); - break; -#if defined(TARGET_MIPS64) - case SCD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false); - break; -#endif - case LD_EVA: - if (!ctx->eva) { - MIPS_INVAL("pool32c ld-eva"); - generate_exception_end(ctx, EXCP_RI); - break; - } - check_cp0_enabled(ctx); - - minor2 = (ctx->opcode >> 9) & 0x7; - offset = sextract32(ctx->opcode, 0, 9); - switch (minor2) { - case LBUE: - mips32_op = OPC_LBUE; - goto do_ld_lr; - case LHUE: - mips32_op = OPC_LHUE; - goto do_ld_lr; - case LWLE: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LWLE; - goto do_ld_lr; - case LWRE: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_LWRE; - goto do_ld_lr; - case LBE: - mips32_op = OPC_LBE; - goto do_ld_lr; - case LHE: - mips32_op = OPC_LHE; - goto do_ld_lr; - case LLE: - mips32_op = OPC_LLE; - goto do_ld_lr; - case LWE: - mips32_op = OPC_LWE; - goto do_ld_lr; - }; - break; - case ST_EVA: - if (!ctx->eva) { - MIPS_INVAL("pool32c st-eva"); - generate_exception_end(ctx, EXCP_RI); - break; - } - check_cp0_enabled(ctx); - - minor2 = (ctx->opcode >> 9) & 0x7; - offset = sextract32(ctx->opcode, 0, 9); - switch (minor2) { - case SWLE: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SWLE; - goto do_st_lr; - case SWRE: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - mips32_op = OPC_SWRE; - goto do_st_lr; - case PREFE: - /* Treat as no-op */ - if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) { - /* hint codes 24-31 are reserved and signal RI */ - generate_exception(ctx, EXCP_RI); - } - break; - case CACHEE: - /* Treat as no-op */ - if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { - gen_cache_operation(ctx, rt, rs, offset); - } - break; - case SBE: - mips32_op = OPC_SBE; - goto do_st_lr; - case SHE: - mips32_op = OPC_SHE; - goto do_st_lr; - case SCE: - gen_st_cond(ctx, rt, rs, offset, MO_TESL, true); - break; - case SWE: - mips32_op = OPC_SWE; - goto do_st_lr; - }; - break; - case PREF: - /* Treat as no-op */ - if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) { - /* hint codes 24-31 are reserved and signal RI */ - generate_exception(ctx, EXCP_RI); - } - break; - default: - MIPS_INVAL("pool32c"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case ADDI32: /* AUI, LUI */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* AUI, LUI */ - gen_logic_imm(ctx, OPC_LUI, rt, rs, imm); - } else { - /* ADDI32 */ - mips32_op = OPC_ADDI; - goto do_addi; - } - break; - case ADDIU32: - mips32_op = OPC_ADDIU; - do_addi: - gen_arith_imm(ctx, mips32_op, rt, rs, imm); - break; - - /* Logical operations */ - case ORI32: - mips32_op = OPC_ORI; - goto do_logici; - case XORI32: - mips32_op = OPC_XORI; - goto do_logici; - case ANDI32: - mips32_op = OPC_ANDI; - do_logici: - gen_logic_imm(ctx, mips32_op, rt, rs, imm); - break; - - /* Set less than immediate */ - case SLTI32: - mips32_op = OPC_SLTI; - goto do_slti; - case SLTIU32: - mips32_op = OPC_SLTIU; - do_slti: - gen_slt_imm(ctx, mips32_op, rt, rs, imm); - break; - case JALX32: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; - gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - break; - case JALS32: /* BOVC, BEQC, BEQZALC */ - if (ctx->insn_flags & ISA_MIPS32R6) { - if (rs >= rt) { - /* BOVC */ - mips32_op = OPC_BOVC; - } else if (rs < rt && rs == 0) { - /* BEQZALC */ - mips32_op = OPC_BEQZALC; - } else { - /* BEQC */ - mips32_op = OPC_BEQC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - } else { - /* JALS32 */ - offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; - gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - } - break; - case BEQ32: /* BC */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* BC */ - gen_compute_compact_branch(ctx, OPC_BC, 0, 0, - sextract32(ctx->opcode << 1, 0, 27)); - } else { - /* BEQ32 */ - gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4); - } - break; - case BNE32: /* BALC */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* BALC */ - gen_compute_compact_branch(ctx, OPC_BALC, 0, 0, - sextract32(ctx->opcode << 1, 0, 27)); - } else { - /* BNE32 */ - gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4); - } - break; - case J32: /* BGTZC, BLTZC, BLTC */ - if (ctx->insn_flags & ISA_MIPS32R6) { - if (rs == 0 && rt != 0) { - /* BGTZC */ - mips32_op = OPC_BGTZC; - } else if (rs != 0 && rt != 0 && rs == rt) { - /* BLTZC */ - mips32_op = OPC_BLTZC; - } else { - /* BLTC */ - mips32_op = OPC_BLTC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - } else { - /* J32 */ - gen_compute_branch(ctx, OPC_J, 4, rt, rs, - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); - } - break; - case JAL32: /* BLEZC, BGEZC, BGEC */ - if (ctx->insn_flags & ISA_MIPS32R6) { - if (rs == 0 && rt != 0) { - /* BLEZC */ - mips32_op = OPC_BLEZC; - } else if (rs != 0 && rt != 0 && rs == rt) { - /* BGEZC */ - mips32_op = OPC_BGEZC; - } else { - /* BGEC */ - mips32_op = OPC_BGEC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - } else { - /* JAL32 */ - gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; - } - break; - /* Floating point (COP1) */ - case LWC132: - mips32_op = OPC_LWC1; - goto do_cop1; - case LDC132: - mips32_op = OPC_LDC1; - goto do_cop1; - case SWC132: - mips32_op = OPC_SWC1; - goto do_cop1; - case SDC132: - mips32_op = OPC_SDC1; - do_cop1: - gen_cop1_ldst(ctx, mips32_op, rt, rs, imm); - break; - case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ - if (ctx->insn_flags & ISA_MIPS32R6) { - /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ - switch ((ctx->opcode >> 16) & 0x1f) { - case ADDIUPC_00: - case ADDIUPC_01: - case ADDIUPC_02: - case ADDIUPC_03: - case ADDIUPC_04: - case ADDIUPC_05: - case ADDIUPC_06: - case ADDIUPC_07: - gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt); - break; - case AUIPC: - gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt); - break; - case ALUIPC: - gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt); - break; - case LWPC_08: - case LWPC_09: - case LWPC_0A: - case LWPC_0B: - case LWPC_0C: - case LWPC_0D: - case LWPC_0E: - case LWPC_0F: - gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt); - break; - default: - generate_exception(ctx, EXCP_RI); - break; - } - } else { - /* ADDIUPC */ - int reg = mmreg(ZIMM(ctx->opcode, 23, 3)); - offset = SIMM(ctx->opcode, 0, 23) << 2; - - gen_addiupc(ctx, reg, offset, 0, 0); - } - break; - case BNVC: /* BNEC, BNEZALC */ - check_insn(ctx, ISA_MIPS32R6); - if (rs >= rt) { - /* BNVC */ - mips32_op = OPC_BNVC; - } else if (rs < rt && rs == 0) { - /* BNEZALC */ - mips32_op = OPC_BNEZALC; - } else { - /* BNEC */ - mips32_op = OPC_BNEC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - break; - case R6_BNEZC: /* JIALC */ - check_insn(ctx, ISA_MIPS32R6); - if (rt != 0) { - /* BNEZC */ - gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0, - sextract32(ctx->opcode << 1, 0, 22)); - } else { - /* JIALC */ - gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm); - } - break; - case R6_BEQZC: /* JIC */ - check_insn(ctx, ISA_MIPS32R6); - if (rt != 0) { - /* BEQZC */ - gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0, - sextract32(ctx->opcode << 1, 0, 22)); - } else { - /* JIC */ - gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm); - } - break; - case BLEZALC: /* BGEZALC, BGEUC */ - check_insn(ctx, ISA_MIPS32R6); - if (rs == 0 && rt != 0) { - /* BLEZALC */ - mips32_op = OPC_BLEZALC; - } else if (rs != 0 && rt != 0 && rs == rt) { - /* BGEZALC */ - mips32_op = OPC_BGEZALC; - } else { - /* BGEUC */ - mips32_op = OPC_BGEUC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - break; - case BGTZALC: /* BLTZALC, BLTUC */ - check_insn(ctx, ISA_MIPS32R6); - if (rs == 0 && rt != 0) { - /* BGTZALC */ - mips32_op = OPC_BGTZALC; - } else if (rs != 0 && rt != 0 && rs == rt) { - /* BLTZALC */ - mips32_op = OPC_BLTZALC; - } else { - /* BLTUC */ - mips32_op = OPC_BLTUC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - break; - /* Loads and stores */ - case LB32: - mips32_op = OPC_LB; - goto do_ld; - case LBU32: - mips32_op = OPC_LBU; - goto do_ld; - case LH32: - mips32_op = OPC_LH; - goto do_ld; - case LHU32: - mips32_op = OPC_LHU; - goto do_ld; - case LW32: - mips32_op = OPC_LW; - goto do_ld; -#ifdef TARGET_MIPS64 - case LD32: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - mips32_op = OPC_LD; - goto do_ld; - case SD32: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - mips32_op = OPC_SD; - goto do_st; -#endif - case SB32: - mips32_op = OPC_SB; - goto do_st; - case SH32: - mips32_op = OPC_SH; - goto do_st; - case SW32: - mips32_op = OPC_SW; - goto do_st; - do_ld: - gen_ld(ctx, mips32_op, rt, rs, imm); - break; - do_st: - gen_st(ctx, mips32_op, rt, rs, imm); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t op; - - /* make sure instructions are on a halfword boundary */ - if (ctx->base.pc_next & 0x1) { - env->CP0_BadVAddr = ctx->base.pc_next; - generate_exception_end(ctx, EXCP_AdEL); - return 2; - } - - op = (ctx->opcode >> 10) & 0x3f; - /* Enforce properly-sized instructions in a delay slot */ - if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) { - switch (op & 0x7) { /* MSB-3..MSB-5 */ - case 0: - /* POOL32A, POOL32B, POOL32I, POOL32C */ - case 4: - /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */ - case 5: - /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */ - case 6: - /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */ - case 7: - /* LB32, LH32, LWC132, LDC132, LW32 */ - if (ctx->hflags & MIPS_HFLAG_BDS16) { - generate_exception_end(ctx, EXCP_RI); - return 2; - } - break; - case 1: - /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */ - case 2: - /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */ - case 3: - /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */ - if (ctx->hflags & MIPS_HFLAG_BDS32) { - generate_exception_end(ctx, EXCP_RI); - return 2; - } - break; - } - } - - switch (op) { - case POOL16A: - { - int rd = mmreg(uMIPS_RD(ctx->opcode)); - int rs1 = mmreg(uMIPS_RS1(ctx->opcode)); - int rs2 = mmreg(uMIPS_RS2(ctx->opcode)); - uint32_t opc = 0; - - switch (ctx->opcode & 0x1) { - case ADDU16: - opc = OPC_ADDU; - break; - case SUBU16: - opc = OPC_SUBU; - break; - } - if (ctx->insn_flags & ISA_MIPS32R6) { - /* - * In the Release 6, the register number location in - * the instruction encoding has changed. - */ - gen_arith(ctx, opc, rs1, rd, rs2); - } else { - gen_arith(ctx, opc, rd, rs1, rs2); - } - } - break; - case POOL16B: - { - int rd = mmreg(uMIPS_RD(ctx->opcode)); - int rs = mmreg(uMIPS_RS(ctx->opcode)); - int amount = (ctx->opcode >> 1) & 0x7; - uint32_t opc = 0; - amount = amount == 0 ? 8 : amount; - - switch (ctx->opcode & 0x1) { - case SLL16: - opc = OPC_SLL; - break; - case SRL16: - opc = OPC_SRL; - break; - } - - gen_shift_imm(ctx, opc, rd, rs, amount); - } - break; - case POOL16C: - if (ctx->insn_flags & ISA_MIPS32R6) { - gen_pool16c_r6_insn(ctx); - } else { - gen_pool16c_insn(ctx); - } - break; - case LWGP16: - { - int rd = mmreg(uMIPS_RD(ctx->opcode)); - int rb = 28; /* GP */ - int16_t offset = SIMM(ctx->opcode, 0, 7) << 2; - - gen_ld(ctx, OPC_LW, rd, rb, offset); - } - break; - case POOL16F: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - if (ctx->opcode & 1) { - generate_exception_end(ctx, EXCP_RI); - } else { - /* MOVEP */ - int enc_dest = uMIPS_RD(ctx->opcode); - int enc_rt = uMIPS_RS2(ctx->opcode); - int enc_rs = uMIPS_RS1(ctx->opcode); - gen_movep(ctx, enc_dest, enc_rt, enc_rs); - } - break; - case LBU16: - { - int rd = mmreg(uMIPS_RD(ctx->opcode)); - int rb = mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset = ZIMM(ctx->opcode, 0, 4); - offset = (offset == 0xf ? -1 : offset); - - gen_ld(ctx, OPC_LBU, rd, rb, offset); - } - break; - case LHU16: - { - int rd = mmreg(uMIPS_RD(ctx->opcode)); - int rb = mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1; - - gen_ld(ctx, OPC_LHU, rd, rb, offset); - } - break; - case LWSP16: - { - int rd = (ctx->opcode >> 5) & 0x1f; - int rb = 29; /* SP */ - int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2; - - gen_ld(ctx, OPC_LW, rd, rb, offset); - } - break; - case LW16: - { - int rd = mmreg(uMIPS_RD(ctx->opcode)); - int rb = mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2; - - gen_ld(ctx, OPC_LW, rd, rb, offset); - } - break; - case SB16: - { - int rd = mmreg2(uMIPS_RD(ctx->opcode)); - int rb = mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset = ZIMM(ctx->opcode, 0, 4); - - gen_st(ctx, OPC_SB, rd, rb, offset); - } - break; - case SH16: - { - int rd = mmreg2(uMIPS_RD(ctx->opcode)); - int rb = mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1; - - gen_st(ctx, OPC_SH, rd, rb, offset); - } - break; - case SWSP16: - { - int rd = (ctx->opcode >> 5) & 0x1f; - int rb = 29; /* SP */ - int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2; - - gen_st(ctx, OPC_SW, rd, rb, offset); - } - break; - case SW16: - { - int rd = mmreg2(uMIPS_RD(ctx->opcode)); - int rb = mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2; - - gen_st(ctx, OPC_SW, rd, rb, offset); - } - break; - case MOVE16: - { - int rd = uMIPS_RD5(ctx->opcode); - int rs = uMIPS_RS5(ctx->opcode); - - gen_arith(ctx, OPC_ADDU, rd, rs, 0); - } - break; - case ANDI16: - gen_andi16(ctx); - break; - case POOL16D: - switch (ctx->opcode & 0x1) { - case ADDIUS5: - gen_addius5(ctx); - break; - case ADDIUSP: - gen_addiusp(ctx); - break; - } - break; - case POOL16E: - switch (ctx->opcode & 0x1) { - case ADDIUR2: - gen_addiur2(ctx); - break; - case ADDIUR1SP: - gen_addiur1sp(ctx); - break; - } - break; - case B16: /* BC16 */ - gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, - sextract32(ctx->opcode, 0, 10) << 1, - (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4); - break; - case BNEZ16: /* BNEZC16 */ - case BEQZ16: /* BEQZC16 */ - gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2, - mmreg(uMIPS_RD(ctx->opcode)), - 0, sextract32(ctx->opcode, 0, 7) << 1, - (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4); - - break; - case LI16: - { - int reg = mmreg(uMIPS_RD(ctx->opcode)); - int imm = ZIMM(ctx->opcode, 0, 7); - - imm = (imm == 0x7f ? -1 : imm); - tcg_gen_movi_tl(cpu_gpr[reg], imm); - } - break; - case RES_29: - case RES_31: - case RES_39: - generate_exception_end(ctx, EXCP_RI); - break; - default: - decode_micromips32_opc(env, ctx); - return 4; - } - - return 2; -} +#include "isa-micromips_translate.c.inc" /* * diff --git a/target/mips/isa-micromips_translate.c.inc b/target/mips/isa-micromips_translate.c.inc new file mode 100644 index 00000000000..c5e2c844c4b --- /dev/null +++ b/target/mips/isa-micromips_translate.c.inc @@ -0,0 +1,3316 @@ +/* + * microMIPS translation routines + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* + * microMIPS32/microMIPS64 major opcodes + * + * 1. MIPS Architecture for Programmers Volume II-B: + * The microMIPS32 Instruction Set (Revision 3.05) + * + * Table 6.2 microMIPS32 Encoding of Major Opcode Field + * + * 2. MIPS Architecture For Programmers Volume II-A: + * The MIPS64 Instruction Set (Revision 3.51) + */ + +enum { + POOL32A = 0x00, + POOL16A = 0x01, + LBU16 = 0x02, + MOVE16 = 0x03, + ADDI32 = 0x04, + R6_LUI = 0x04, + AUI = 0x04, + LBU32 = 0x05, + SB32 = 0x06, + LB32 = 0x07, + + POOL32B = 0x08, + POOL16B = 0x09, + LHU16 = 0x0a, + ANDI16 = 0x0b, + ADDIU32 = 0x0c, + LHU32 = 0x0d, + SH32 = 0x0e, + LH32 = 0x0f, + + POOL32I = 0x10, + POOL16C = 0x11, + LWSP16 = 0x12, + POOL16D = 0x13, + ORI32 = 0x14, + POOL32F = 0x15, + POOL32S = 0x16, /* MIPS64 */ + DADDIU32 = 0x17, /* MIPS64 */ + + POOL32C = 0x18, + LWGP16 = 0x19, + LW16 = 0x1a, + POOL16E = 0x1b, + XORI32 = 0x1c, + JALS32 = 0x1d, + BOVC = 0x1d, + BEQC = 0x1d, + BEQZALC = 0x1d, + ADDIUPC = 0x1e, + PCREL = 0x1e, + BNVC = 0x1f, + BNEC = 0x1f, + BNEZALC = 0x1f, + + R6_BEQZC = 0x20, + JIC = 0x20, + POOL16F = 0x21, + SB16 = 0x22, + BEQZ16 = 0x23, + BEQZC16 = 0x23, + SLTI32 = 0x24, + BEQ32 = 0x25, + BC = 0x25, + SWC132 = 0x26, + LWC132 = 0x27, + + /* 0x29 is reserved */ + RES_29 = 0x29, + R6_BNEZC = 0x28, + JIALC = 0x28, + SH16 = 0x2a, + BNEZ16 = 0x2b, + BNEZC16 = 0x2b, + SLTIU32 = 0x2c, + BNE32 = 0x2d, + BALC = 0x2d, + SDC132 = 0x2e, + LDC132 = 0x2f, + + /* 0x31 is reserved */ + RES_31 = 0x31, + BLEZALC = 0x30, + BGEZALC = 0x30, + BGEUC = 0x30, + SWSP16 = 0x32, + B16 = 0x33, + BC16 = 0x33, + ANDI32 = 0x34, + J32 = 0x35, + BGTZC = 0x35, + BLTZC = 0x35, + BLTC = 0x35, + SD32 = 0x36, /* MIPS64 */ + LD32 = 0x37, /* MIPS64 */ + + /* 0x39 is reserved */ + RES_39 = 0x39, + BGTZALC = 0x38, + BLTZALC = 0x38, + BLTUC = 0x38, + SW16 = 0x3a, + LI16 = 0x3b, + JALX32 = 0x3c, + JAL32 = 0x3d, + BLEZC = 0x3d, + BGEZC = 0x3d, + BGEC = 0x3d, + SW32 = 0x3e, + LW32 = 0x3f +}; + +/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */ +enum { + ADDIUPC_00 = 0x00, + ADDIUPC_01 = 0x01, + ADDIUPC_02 = 0x02, + ADDIUPC_03 = 0x03, + ADDIUPC_04 = 0x04, + ADDIUPC_05 = 0x05, + ADDIUPC_06 = 0x06, + ADDIUPC_07 = 0x07, + AUIPC = 0x1e, + ALUIPC = 0x1f, + LWPC_08 = 0x08, + LWPC_09 = 0x09, + LWPC_0A = 0x0A, + LWPC_0B = 0x0B, + LWPC_0C = 0x0C, + LWPC_0D = 0x0D, + LWPC_0E = 0x0E, + LWPC_0F = 0x0F, +}; + +/* POOL32A encoding of minor opcode field */ + +enum { + /* + * These opcodes are distinguished only by bits 9..6; those bits are + * what are recorded below. + */ + SLL32 = 0x0, + SRL32 = 0x1, + SRA = 0x2, + ROTR = 0x3, + SELEQZ = 0x5, + SELNEZ = 0x6, + R6_RDHWR = 0x7, + + SLLV = 0x0, + SRLV = 0x1, + SRAV = 0x2, + ROTRV = 0x3, + ADD = 0x4, + ADDU32 = 0x5, + SUB = 0x6, + SUBU32 = 0x7, + MUL = 0x8, + AND = 0x9, + OR32 = 0xa, + NOR = 0xb, + XOR32 = 0xc, + SLT = 0xd, + SLTU = 0xe, + + MOVN = 0x0, + R6_MUL = 0x0, + MOVZ = 0x1, + MUH = 0x1, + MULU = 0x2, + MUHU = 0x3, + LWXS = 0x4, + R6_DIV = 0x4, + MOD = 0x5, + R6_DIVU = 0x6, + MODU = 0x7, + + /* The following can be distinguished by their lower 6 bits. */ + BREAK32 = 0x07, + INS = 0x0c, + LSA = 0x0f, + ALIGN = 0x1f, + EXT = 0x2c, + POOL32AXF = 0x3c, + SIGRIE = 0x3f +}; + +/* POOL32AXF encoding of minor opcode field extension */ + +/* + * 1. MIPS Architecture for Programmers Volume II-B: + * The microMIPS32 Instruction Set (Revision 3.05) + * + * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field + * + * 2. MIPS Architecture for Programmers VolumeIV-e: + * The MIPS DSP Application-Specific Extension + * to the microMIPS32 Architecture (Revision 2.34) + * + * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field + */ + +enum { + /* bits 11..6 */ + TEQ = 0x00, + TGE = 0x08, + TGEU = 0x10, + TLT = 0x20, + TLTU = 0x28, + TNE = 0x30, + + MFC0 = 0x03, + MTC0 = 0x0b, + + /* begin of microMIPS32 DSP */ + + /* bits 13..12 for 0x01 */ + MFHI_ACC = 0x0, + MFLO_ACC = 0x1, + MTHI_ACC = 0x2, + MTLO_ACC = 0x3, + + /* bits 13..12 for 0x2a */ + MADD_ACC = 0x0, + MADDU_ACC = 0x1, + MSUB_ACC = 0x2, + MSUBU_ACC = 0x3, + + /* bits 13..12 for 0x32 */ + MULT_ACC = 0x0, + MULTU_ACC = 0x1, + + /* end of microMIPS32 DSP */ + + /* bits 15..12 for 0x2c */ + BITSWAP = 0x0, + SEB = 0x2, + SEH = 0x3, + CLO = 0x4, + CLZ = 0x5, + RDHWR = 0x6, + WSBH = 0x7, + MULT = 0x8, + MULTU = 0x9, + DIV = 0xa, + DIVU = 0xb, + MADD = 0xc, + MADDU = 0xd, + MSUB = 0xe, + MSUBU = 0xf, + + /* bits 15..12 for 0x34 */ + MFC2 = 0x4, + MTC2 = 0x5, + MFHC2 = 0x8, + MTHC2 = 0x9, + CFC2 = 0xc, + CTC2 = 0xd, + + /* bits 15..12 for 0x3c */ + JALR = 0x0, + JR = 0x0, /* alias */ + JALRC = 0x0, + JRC = 0x0, + JALR_HB = 0x1, + JALRC_HB = 0x1, + JALRS = 0x4, + JALRS_HB = 0x5, + + /* bits 15..12 for 0x05 */ + RDPGPR = 0xe, + WRPGPR = 0xf, + + /* bits 15..12 for 0x0d */ + TLBP = 0x0, + TLBR = 0x1, + TLBWI = 0x2, + TLBWR = 0x3, + TLBINV = 0x4, + TLBINVF = 0x5, + WAIT = 0x9, + IRET = 0xd, + DERET = 0xe, + ERET = 0xf, + + /* bits 15..12 for 0x15 */ + DMT = 0x0, + DVPE = 0x1, + EMT = 0x2, + EVPE = 0x3, + + /* bits 15..12 for 0x1d */ + DI = 0x4, + EI = 0x5, + + /* bits 15..12 for 0x2d */ + SYNC = 0x6, + SYSCALL = 0x8, + SDBBP = 0xd, + + /* bits 15..12 for 0x35 */ + MFHI32 = 0x0, + MFLO32 = 0x1, + MTHI32 = 0x2, + MTLO32 = 0x3, +}; + +/* POOL32B encoding of minor opcode field (bits 15..12) */ + +enum { + LWC2 = 0x0, + LWP = 0x1, + LDP = 0x4, + LWM32 = 0x5, + CACHE = 0x6, + LDM = 0x7, + SWC2 = 0x8, + SWP = 0x9, + SDP = 0xc, + SWM32 = 0xd, + SDM = 0xf +}; + +/* POOL32C encoding of minor opcode field (bits 15..12) */ + +enum { + LWL = 0x0, + SWL = 0x8, + LWR = 0x1, + SWR = 0x9, + PREF = 0x2, + ST_EVA = 0xa, + LL = 0x3, + SC = 0xb, + LDL = 0x4, + SDL = 0xc, + LDR = 0x5, + SDR = 0xd, + LD_EVA = 0x6, + LWU = 0xe, + LLD = 0x7, + SCD = 0xf +}; + +/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */ + +enum { + LBUE = 0x0, + LHUE = 0x1, + LWLE = 0x2, + LWRE = 0x3, + LBE = 0x4, + LHE = 0x5, + LLE = 0x6, + LWE = 0x7, +}; + +/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */ + +enum { + SWLE = 0x0, + SWRE = 0x1, + PREFE = 0x2, + CACHEE = 0x3, + SBE = 0x4, + SHE = 0x5, + SCE = 0x6, + SWE = 0x7, +}; + +/* POOL32F encoding of minor opcode field (bits 5..0) */ + +enum { + /* These are the bit 7..6 values */ + ADD_FMT = 0x0, + + SUB_FMT = 0x1, + + MUL_FMT = 0x2, + + DIV_FMT = 0x3, + + /* These are the bit 8..6 values */ + MOVN_FMT = 0x0, + RSQRT2_FMT = 0x0, + MOVF_FMT = 0x0, + RINT_FMT = 0x0, + SELNEZ_FMT = 0x0, + + MOVZ_FMT = 0x1, + LWXC1 = 0x1, + MOVT_FMT = 0x1, + CLASS_FMT = 0x1, + SELEQZ_FMT = 0x1, + + PLL_PS = 0x2, + SWXC1 = 0x2, + SEL_FMT = 0x2, + + PLU_PS = 0x3, + LDXC1 = 0x3, + + MOVN_FMT_04 = 0x4, + PUL_PS = 0x4, + SDXC1 = 0x4, + RECIP2_FMT = 0x4, + + MOVZ_FMT_05 = 0x05, + PUU_PS = 0x5, + LUXC1 = 0x5, + + CVT_PS_S = 0x6, + SUXC1 = 0x6, + ADDR_PS = 0x6, + PREFX = 0x6, + MADDF_FMT = 0x6, + + MULR_PS = 0x7, + MSUBF_FMT = 0x7, + + MADD_S = 0x01, + MADD_D = 0x09, + MADD_PS = 0x11, + ALNV_PS = 0x19, + MSUB_S = 0x21, + MSUB_D = 0x29, + MSUB_PS = 0x31, + + NMADD_S = 0x02, + NMADD_D = 0x0a, + NMADD_PS = 0x12, + NMSUB_S = 0x22, + NMSUB_D = 0x2a, + NMSUB_PS = 0x32, + + MIN_FMT = 0x3, + MAX_FMT = 0xb, + MINA_FMT = 0x23, + MAXA_FMT = 0x2b, + POOL32FXF = 0x3b, + + CABS_COND_FMT = 0x1c, /* MIPS3D */ + C_COND_FMT = 0x3c, + + CMP_CONDN_S = 0x5, + CMP_CONDN_D = 0x15 +}; + +/* POOL32Fxf encoding of minor opcode extension field */ + +enum { + CVT_L = 0x04, + RSQRT_FMT = 0x08, + FLOOR_L = 0x0c, + CVT_PW_PS = 0x1c, + CVT_W = 0x24, + SQRT_FMT = 0x28, + FLOOR_W = 0x2c, + CVT_PS_PW = 0x3c, + CFC1 = 0x40, + RECIP_FMT = 0x48, + CEIL_L = 0x4c, + CTC1 = 0x60, + CEIL_W = 0x6c, + MFC1 = 0x80, + CVT_S_PL = 0x84, + TRUNC_L = 0x8c, + MTC1 = 0xa0, + CVT_S_PU = 0xa4, + TRUNC_W = 0xac, + MFHC1 = 0xc0, + ROUND_L = 0xcc, + MTHC1 = 0xe0, + ROUND_W = 0xec, + + MOV_FMT = 0x01, + MOVF = 0x05, + ABS_FMT = 0x0d, + RSQRT1_FMT = 0x1d, + MOVT = 0x25, + NEG_FMT = 0x2d, + CVT_D = 0x4d, + RECIP1_FMT = 0x5d, + CVT_S = 0x6d +}; + +/* POOL32I encoding of minor opcode field (bits 25..21) */ + +enum { + BLTZ = 0x00, + BLTZAL = 0x01, + BGEZ = 0x02, + BGEZAL = 0x03, + BLEZ = 0x04, + BNEZC = 0x05, + BGTZ = 0x06, + BEQZC = 0x07, + TLTI = 0x08, + BC1EQZC = 0x08, + TGEI = 0x09, + BC1NEZC = 0x09, + TLTIU = 0x0a, + BC2EQZC = 0x0a, + TGEIU = 0x0b, + BC2NEZC = 0x0a, + TNEI = 0x0c, + R6_SYNCI = 0x0c, + LUI = 0x0d, + TEQI = 0x0e, + SYNCI = 0x10, + BLTZALS = 0x11, + BGEZALS = 0x13, + BC2F = 0x14, + BC2T = 0x15, + BPOSGE64 = 0x1a, + BPOSGE32 = 0x1b, + /* These overlap and are distinguished by bit16 of the instruction */ + BC1F = 0x1c, + BC1T = 0x1d, + BC1ANY2F = 0x1c, + BC1ANY2T = 0x1d, + BC1ANY4F = 0x1e, + BC1ANY4T = 0x1f +}; + +/* POOL16A encoding of minor opcode field */ + +enum { + ADDU16 = 0x0, + SUBU16 = 0x1 +}; + +/* POOL16B encoding of minor opcode field */ + +enum { + SLL16 = 0x0, + SRL16 = 0x1 +}; + +/* POOL16C encoding of minor opcode field */ + +enum { + NOT16 = 0x00, + XOR16 = 0x04, + AND16 = 0x08, + OR16 = 0x0c, + LWM16 = 0x10, + SWM16 = 0x14, + JR16 = 0x18, + JRC16 = 0x1a, + JALR16 = 0x1c, + JALR16S = 0x1e, + MFHI16 = 0x20, + MFLO16 = 0x24, + BREAK16 = 0x28, + SDBBP16 = 0x2c, + JRADDIUSP = 0x30 +}; + +/* R6 POOL16C encoding of minor opcode field (bits 0..5) */ + +enum { + R6_NOT16 = 0x00, + R6_AND16 = 0x01, + R6_LWM16 = 0x02, + R6_JRC16 = 0x03, + MOVEP = 0x04, + MOVEP_05 = 0x05, + MOVEP_06 = 0x06, + MOVEP_07 = 0x07, + R6_XOR16 = 0x08, + R6_OR16 = 0x09, + R6_SWM16 = 0x0a, + JALRC16 = 0x0b, + MOVEP_0C = 0x0c, + MOVEP_0D = 0x0d, + MOVEP_0E = 0x0e, + MOVEP_0F = 0x0f, + JRCADDIUSP = 0x13, + R6_BREAK16 = 0x1b, + R6_SDBBP16 = 0x3b +}; + +/* POOL16D encoding of minor opcode field */ + +enum { + ADDIUS5 = 0x0, + ADDIUSP = 0x1 +}; + +/* POOL16E encoding of minor opcode field */ + +enum { + ADDIUR2 = 0x0, + ADDIUR1SP = 0x1 +}; + +static int mmreg(int r) +{ + static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; + + return map[r]; +} + +/* Used for 16-bit store instructions. */ +static int mmreg2(int r) +{ + static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 }; + + return map[r]; +} + +#define uMIPS_RD(op) ((op >> 7) & 0x7) +#define uMIPS_RS(op) ((op >> 4) & 0x7) +#define uMIPS_RS2(op) uMIPS_RS(op) +#define uMIPS_RS1(op) ((op >> 1) & 0x7) +#define uMIPS_RD5(op) ((op >> 5) & 0x1f) +#define uMIPS_RS5(op) (op & 0x1f) + +/* Signed immediate */ +#define SIMM(op, start, width) \ + ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \ + << (32 - width)) \ + >> (32 - width)) +/* Zero-extended immediate */ +#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width))) + +static void gen_addiur1sp(DisasContext *ctx) +{ + int rd = mmreg(uMIPS_RD(ctx->opcode)); + + gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2); +} + +static void gen_addiur2(DisasContext *ctx) +{ + static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 }; + int rd = mmreg(uMIPS_RD(ctx->opcode)); + int rs = mmreg(uMIPS_RS(ctx->opcode)); + + gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]); +} + +static void gen_addiusp(DisasContext *ctx) +{ + int encoded = ZIMM(ctx->opcode, 1, 9); + int decoded; + + if (encoded <= 1) { + decoded = 256 + encoded; + } else if (encoded <= 255) { + decoded = encoded; + } else if (encoded <= 509) { + decoded = encoded - 512; + } else { + decoded = encoded - 768; + } + + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2); +} + +static void gen_addius5(DisasContext *ctx) +{ + int imm = SIMM(ctx->opcode, 1, 4); + int rd = (ctx->opcode >> 5) & 0x1f; + + gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm); +} + +static void gen_andi16(DisasContext *ctx) +{ + static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16, + 31, 32, 63, 64, 255, 32768, 65535 }; + int rd = mmreg(uMIPS_RD(ctx->opcode)); + int rs = mmreg(uMIPS_RS(ctx->opcode)); + int encoded = ZIMM(ctx->opcode, 0, 4); + + gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]); +} + +static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist, + int base, int16_t offset) +{ + TCGv t0, t1; + TCGv_i32 t2; + + if (ctx->hflags & MIPS_HFLAG_BMASK) { + generate_exception_end(ctx, EXCP_RI); + return; + } + + t0 = tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, base, offset); + + t1 = tcg_const_tl(reglist); + t2 = tcg_const_i32(ctx->mem_idx); + + save_cpu_state(ctx, 1); + switch (opc) { + case LWM32: + gen_helper_lwm(cpu_env, t0, t1, t2); + break; + case SWM32: + gen_helper_swm(cpu_env, t0, t1, t2); + break; +#ifdef TARGET_MIPS64 + case LDM: + gen_helper_ldm(cpu_env, t0, t1, t2); + break; + case SDM: + gen_helper_sdm(cpu_env, t0, t1, t2); + break; +#endif + } + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free_i32(t2); +} + + +static void gen_pool16c_insn(DisasContext *ctx) +{ + int rd = mmreg((ctx->opcode >> 3) & 0x7); + int rs = mmreg(ctx->opcode & 0x7); + + switch (((ctx->opcode) >> 4) & 0x3f) { + case NOT16 + 0: + case NOT16 + 1: + case NOT16 + 2: + case NOT16 + 3: + gen_logic(ctx, OPC_NOR, rd, rs, 0); + break; + case XOR16 + 0: + case XOR16 + 1: + case XOR16 + 2: + case XOR16 + 3: + gen_logic(ctx, OPC_XOR, rd, rd, rs); + break; + case AND16 + 0: + case AND16 + 1: + case AND16 + 2: + case AND16 + 3: + gen_logic(ctx, OPC_AND, rd, rd, rs); + break; + case OR16 + 0: + case OR16 + 1: + case OR16 + 2: + case OR16 + 3: + gen_logic(ctx, OPC_OR, rd, rd, rs); + break; + case LWM16 + 0: + case LWM16 + 1: + case LWM16 + 2: + case LWM16 + 3: + { + static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 }; + int offset = ZIMM(ctx->opcode, 0, 4); + + gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3], + 29, offset << 2); + } + break; + case SWM16 + 0: + case SWM16 + 1: + case SWM16 + 2: + case SWM16 + 3: + { + static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 }; + int offset = ZIMM(ctx->opcode, 0, 4); + + gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3], + 29, offset << 2); + } + break; + case JR16 + 0: + case JR16 + 1: + { + int reg = ctx->opcode & 0x1f; + + gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4); + } + break; + case JRC16 + 0: + case JRC16 + 1: + { + int reg = ctx->opcode & 0x1f; + gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0); + /* + * Let normal delay slot handling in our caller take us + * to the branch target. + */ + } + break; + case JALR16 + 0: + case JALR16 + 1: + gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; + case JALR16S + 0: + case JALR16S + 1: + gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; + case MFHI16 + 0: + case MFHI16 + 1: + gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode)); + break; + case MFLO16 + 0: + case MFLO16 + 1: + gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); + break; + case BREAK16: + generate_exception_end(ctx, EXCP_BREAK); + break; + case SDBBP16: + if (is_uhi(extract32(ctx->opcode, 0, 4))) { + gen_helper_do_semihosting(cpu_env); + } else { + /* + * XXX: not clear which exception should be raised + * when in debug mode... + */ + check_insn(ctx, ISA_MIPS32); + generate_exception_end(ctx, EXCP_DBp); + } + break; + case JRADDIUSP + 0: + case JRADDIUSP + 1: + { + int imm = ZIMM(ctx->opcode, 0, 5); + gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); + /* + * Let normal delay slot handling in our caller take us + * to the branch target. + */ + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt, + int enc_rs) +{ + int rd, rs, re, rt; + static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 }; + static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 }; + static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 }; + rd = rd_enc[enc_dest]; + re = re_enc[enc_dest]; + rs = rs_rt_enc[enc_rs]; + rt = rs_rt_enc[enc_rt]; + if (rs) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], 0); + } + if (rt) { + tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]); + } else { + tcg_gen_movi_tl(cpu_gpr[re], 0); + } +} + +static void gen_pool16c_r6_insn(DisasContext *ctx) +{ + int rt = mmreg((ctx->opcode >> 7) & 0x7); + int rs = mmreg((ctx->opcode >> 4) & 0x7); + + switch (ctx->opcode & 0xf) { + case R6_NOT16: + gen_logic(ctx, OPC_NOR, rt, rs, 0); + break; + case R6_AND16: + gen_logic(ctx, OPC_AND, rt, rt, rs); + break; + case R6_LWM16: + { + int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2); + int offset = extract32(ctx->opcode, 4, 4); + gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2); + } + break; + case R6_JRC16: /* JRCADDIUSP */ + if ((ctx->opcode >> 4) & 1) { + /* JRCADDIUSP */ + int imm = extract32(ctx->opcode, 5, 5); + gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); + } else { + /* JRC16 */ + rs = extract32(ctx->opcode, 5, 5); + gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0); + } + break; + case MOVEP: + case MOVEP_05: + case MOVEP_06: + case MOVEP_07: + case MOVEP_0C: + case MOVEP_0D: + case MOVEP_0E: + case MOVEP_0F: + { + int enc_dest = uMIPS_RD(ctx->opcode); + int enc_rt = uMIPS_RS2(ctx->opcode); + int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4); + gen_movep(ctx, enc_dest, enc_rt, enc_rs); + } + break; + case R6_XOR16: + gen_logic(ctx, OPC_XOR, rt, rt, rs); + break; + case R6_OR16: + gen_logic(ctx, OPC_OR, rt, rt, rs); + break; + case R6_SWM16: + { + int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2); + int offset = extract32(ctx->opcode, 4, 4); + gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2); + } + break; + case JALRC16: /* BREAK16, SDBBP16 */ + switch (ctx->opcode & 0x3f) { + case JALRC16: + case JALRC16 + 0x20: + /* JALRC16 */ + gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f, + 31, 0, 0); + break; + case R6_BREAK16: + /* BREAK16 */ + generate_exception(ctx, EXCP_BREAK); + break; + case R6_SDBBP16: + /* SDBBP16 */ + if (is_uhi(extract32(ctx->opcode, 6, 4))) { + gen_helper_do_semihosting(cpu_env); + } else { + if (ctx->hflags & MIPS_HFLAG_SBRI) { + generate_exception(ctx, EXCP_RI); + } else { + generate_exception(ctx, EXCP_DBp); + } + } + break; + } + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } +} + +static void gen_ldxs(DisasContext *ctx, int base, int index, int rd) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_load_gpr(t0, base); + + if (index != 0) { + gen_load_gpr(t1, index); + tcg_gen_shli_tl(t1, t1, 2); + gen_op_addr_add(ctx, t0, t1, t0); + } + + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); + gen_store_gpr(t1, rd); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd, + int base, int16_t offset) +{ + TCGv t0, t1; + + if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) { + generate_exception_end(ctx, EXCP_RI); + return; + } + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, base, offset); + + switch (opc) { + case LWP: + if (rd == base) { + generate_exception_end(ctx, EXCP_RI); + return; + } + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); + gen_store_gpr(t1, rd); + tcg_gen_movi_tl(t1, 4); + gen_op_addr_add(ctx, t0, t0, t1); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); + gen_store_gpr(t1, rd + 1); + break; + case SWP: + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + tcg_gen_movi_tl(t1, 4); + gen_op_addr_add(ctx, t0, t0, t1); + gen_load_gpr(t1, rd + 1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + break; +#ifdef TARGET_MIPS64 + case LDP: + if (rd == base) { + generate_exception_end(ctx, EXCP_RI); + return; + } + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); + gen_store_gpr(t1, rd); + tcg_gen_movi_tl(t1, 8); + gen_op_addr_add(ctx, t0, t0, t1); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); + gen_store_gpr(t1, rd + 1); + break; + case SDP: + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_movi_tl(t1, 8); + gen_op_addr_add(ctx, t0, t0, t1); + gen_load_gpr(t1, rd + 1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); + break; +#endif + } + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_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 gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs) +{ + int extension = (ctx->opcode >> 6) & 0x3f; + int minor = (ctx->opcode >> 12) & 0xf; + uint32_t mips32_op; + + switch (extension) { + case TEQ: + mips32_op = OPC_TEQ; + goto do_trap; + case TGE: + mips32_op = OPC_TGE; + goto do_trap; + case TGEU: + mips32_op = OPC_TGEU; + goto do_trap; + case TLT: + mips32_op = OPC_TLT; + goto do_trap; + case TLTU: + mips32_op = OPC_TLTU; + goto do_trap; + case TNE: + mips32_op = OPC_TNE; + do_trap: + gen_trap(ctx, mips32_op, rs, rt, -1); + break; +#ifndef CONFIG_USER_ONLY + case MFC0: + case MFC0 + 32: + check_cp0_enabled(ctx); + if (rt == 0) { + /* Treat as NOP. */ + break; + } + gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7); + break; + case MTC0: + case MTC0 + 32: + check_cp0_enabled(ctx); + { + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7); + tcg_temp_free(t0); + } + break; +#endif + case 0x2a: + switch (minor & 3) { + case MADD_ACC: + gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt); + break; + case MADDU_ACC: + gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt); + break; + case MSUB_ACC: + gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt); + break; + case MSUBU_ACC: + gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x32: + switch (minor & 3) { + case MULT_ACC: + gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt); + break; + case MULTU_ACC: + gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x2c: + switch (minor) { + case BITSWAP: + check_insn(ctx, ISA_MIPS32R6); + gen_bitswap(ctx, OPC_BITSWAP, rs, rt); + break; + case SEB: + gen_bshfl(ctx, OPC_SEB, rs, rt); + break; + case SEH: + gen_bshfl(ctx, OPC_SEH, rs, rt); + break; + case CLO: + mips32_op = OPC_CLO; + goto do_cl; + case CLZ: + mips32_op = OPC_CLZ; + do_cl: + check_insn(ctx, ISA_MIPS32); + gen_cl(ctx, mips32_op, rt, rs); + break; + case RDHWR: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_rdhwr(ctx, rt, rs, 0); + break; + case WSBH: + gen_bshfl(ctx, OPC_WSBH, rs, rt); + break; + case MULT: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MULT; + goto do_mul; + case MULTU: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MULTU; + goto do_mul; + case DIV: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_DIV; + goto do_div; + case DIVU: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_DIVU; + goto do_div; + do_div: + check_insn(ctx, ISA_MIPS32); + gen_muldiv(ctx, mips32_op, 0, rs, rt); + break; + case MADD: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MADD; + goto do_mul; + case MADDU: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MADDU; + goto do_mul; + case MSUB: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MSUB; + goto do_mul; + case MSUBU: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MSUBU; + do_mul: + check_insn(ctx, ISA_MIPS32); + gen_muldiv(ctx, mips32_op, 0, rs, rt); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x34: + switch (minor) { + case MFC2: + case MTC2: + case MFHC2: + case MTHC2: + case CFC2: + case CTC2: + generate_exception_err(ctx, EXCP_CpU, 2); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x3c: + switch (minor) { + case JALR: /* JALRC */ + case JALR_HB: /* JALRC_HB */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* JALRC, JALRC_HB */ + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0); + } else { + /* JALR, JALR_HB */ + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + } + break; + case JALRS: + case JALRS_HB: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; + default: + goto pool32axf_invalid; + } + break; + case 0x05: + switch (minor) { + case RDPGPR: + check_cp0_enabled(ctx); + check_insn(ctx, ISA_MIPS32R2); + gen_load_srsgpr(rs, rt); + break; + case WRPGPR: + check_cp0_enabled(ctx); + check_insn(ctx, ISA_MIPS32R2); + gen_store_srsgpr(rs, rt); + break; + default: + goto pool32axf_invalid; + } + break; +#ifndef CONFIG_USER_ONLY + case 0x0d: + switch (minor) { + case TLBP: + mips32_op = OPC_TLBP; + goto do_cp0; + case TLBR: + mips32_op = OPC_TLBR; + goto do_cp0; + case TLBWI: + mips32_op = OPC_TLBWI; + goto do_cp0; + case TLBWR: + mips32_op = OPC_TLBWR; + goto do_cp0; + case TLBINV: + mips32_op = OPC_TLBINV; + goto do_cp0; + case TLBINVF: + mips32_op = OPC_TLBINVF; + goto do_cp0; + case WAIT: + mips32_op = OPC_WAIT; + goto do_cp0; + case DERET: + mips32_op = OPC_DERET; + goto do_cp0; + case ERET: + mips32_op = OPC_ERET; + do_cp0: + gen_cp0(env, ctx, mips32_op, rt, rs); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x1d: + switch (minor) { + case DI: + check_cp0_enabled(ctx); + { + TCGv t0 = tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_helper_di(t0, cpu_env); + gen_store_gpr(t0, rs); + /* + * Stop translation as we may have switched the execution + * mode. + */ + ctx->base.is_jmp = DISAS_STOP; + tcg_temp_free(t0); + } + break; + case EI: + check_cp0_enabled(ctx); + { + TCGv t0 = tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_helper_ei(t0, cpu_env); + gen_store_gpr(t0, rs); + /* + * DISAS_STOP isn't sufficient, we need to ensure we break out + * of translated code to check for pending interrupts. + */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; + tcg_temp_free(t0); + } + break; + default: + goto pool32axf_invalid; + } + break; +#endif + case 0x2d: + switch (minor) { + case SYNC: + gen_sync(extract32(ctx->opcode, 16, 5)); + break; + case SYSCALL: + generate_exception_end(ctx, EXCP_SYSCALL); + break; + case SDBBP: + if (is_uhi(extract32(ctx->opcode, 16, 10))) { + gen_helper_do_semihosting(cpu_env); + } else { + check_insn(ctx, ISA_MIPS32); + if (ctx->hflags & MIPS_HFLAG_SBRI) { + generate_exception_end(ctx, EXCP_RI); + } else { + generate_exception_end(ctx, EXCP_DBp); + } + } + break; + default: + goto pool32axf_invalid; + } + break; + case 0x01: + switch (minor & 3) { + case MFHI_ACC: + gen_HILO(ctx, OPC_MFHI, minor >> 2, rs); + break; + case MFLO_ACC: + gen_HILO(ctx, OPC_MFLO, minor >> 2, rs); + break; + case MTHI_ACC: + gen_HILO(ctx, OPC_MTHI, minor >> 2, rs); + break; + case MTLO_ACC: + gen_HILO(ctx, OPC_MTLO, minor >> 2, rs); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x35: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + switch (minor) { + case MFHI32: + gen_HILO(ctx, OPC_MFHI, 0, rs); + break; + case MFLO32: + gen_HILO(ctx, OPC_MFLO, 0, rs); + break; + case MTHI32: + gen_HILO(ctx, OPC_MTHI, 0, rs); + break; + case MTLO32: + gen_HILO(ctx, OPC_MTLO, 0, rs); + break; + default: + goto pool32axf_invalid; + } + break; + default: + pool32axf_invalid: + MIPS_INVAL("pool32axf"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * Values for microMIPS fmt field. Variable-width, depending on which + * formats the instruction supports. + */ +enum { + FMT_SD_S = 0, + FMT_SD_D = 1, + + FMT_SDPS_S = 0, + FMT_SDPS_D = 1, + FMT_SDPS_PS = 2, + + FMT_SWL_S = 0, + FMT_SWL_W = 1, + FMT_SWL_L = 2, + + FMT_DWL_D = 0, + FMT_DWL_W = 1, + FMT_DWL_L = 2 +}; + +static void gen_pool32fxf(DisasContext *ctx, int rt, int rs) +{ + int extension = (ctx->opcode >> 6) & 0x3ff; + uint32_t mips32_op; + +#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc) +#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc) +#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc) + + switch (extension) { + case FLOAT_1BIT_FMT(CFC1, 0): + mips32_op = OPC_CFC1; + goto do_cp1; + case FLOAT_1BIT_FMT(CTC1, 0): + mips32_op = OPC_CTC1; + goto do_cp1; + case FLOAT_1BIT_FMT(MFC1, 0): + mips32_op = OPC_MFC1; + goto do_cp1; + case FLOAT_1BIT_FMT(MTC1, 0): + mips32_op = OPC_MTC1; + goto do_cp1; + case FLOAT_1BIT_FMT(MFHC1, 0): + mips32_op = OPC_MFHC1; + goto do_cp1; + case FLOAT_1BIT_FMT(MTHC1, 0): + mips32_op = OPC_MTHC1; + do_cp1: + gen_cp1(ctx, mips32_op, rt, rs); + break; + + /* Reciprocal square root */ + case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S): + mips32_op = OPC_RSQRT_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D): + mips32_op = OPC_RSQRT_D; + goto do_unaryfp; + + /* Square root */ + case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S): + mips32_op = OPC_SQRT_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D): + mips32_op = OPC_SQRT_D; + goto do_unaryfp; + + /* Reciprocal */ + case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S): + mips32_op = OPC_RECIP_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D): + mips32_op = OPC_RECIP_D; + goto do_unaryfp; + + /* Floor */ + case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S): + mips32_op = OPC_FLOOR_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D): + mips32_op = OPC_FLOOR_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S): + mips32_op = OPC_FLOOR_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D): + mips32_op = OPC_FLOOR_W_D; + goto do_unaryfp; + + /* Ceiling */ + case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S): + mips32_op = OPC_CEIL_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D): + mips32_op = OPC_CEIL_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S): + mips32_op = OPC_CEIL_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D): + mips32_op = OPC_CEIL_W_D; + goto do_unaryfp; + + /* Truncation */ + case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S): + mips32_op = OPC_TRUNC_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D): + mips32_op = OPC_TRUNC_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S): + mips32_op = OPC_TRUNC_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D): + mips32_op = OPC_TRUNC_W_D; + goto do_unaryfp; + + /* Round */ + case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S): + mips32_op = OPC_ROUND_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D): + mips32_op = OPC_ROUND_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S): + mips32_op = OPC_ROUND_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D): + mips32_op = OPC_ROUND_W_D; + goto do_unaryfp; + + /* Integer to floating-point conversion */ + case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S): + mips32_op = OPC_CVT_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D): + mips32_op = OPC_CVT_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S): + mips32_op = OPC_CVT_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D): + mips32_op = OPC_CVT_W_D; + goto do_unaryfp; + + /* Paired-foo conversions */ + case FLOAT_1BIT_FMT(CVT_S_PL, 0): + mips32_op = OPC_CVT_S_PL; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_S_PU, 0): + mips32_op = OPC_CVT_S_PU; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_PW_PS, 0): + mips32_op = OPC_CVT_PW_PS; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_PS_PW, 0): + mips32_op = OPC_CVT_PS_PW; + goto do_unaryfp; + + /* Floating-point moves */ + case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S): + mips32_op = OPC_MOV_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D): + mips32_op = OPC_MOV_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS): + mips32_op = OPC_MOV_PS; + goto do_unaryfp; + + /* Absolute value */ + case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S): + mips32_op = OPC_ABS_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D): + mips32_op = OPC_ABS_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS): + mips32_op = OPC_ABS_PS; + goto do_unaryfp; + + /* Negation */ + case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S): + mips32_op = OPC_NEG_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D): + mips32_op = OPC_NEG_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS): + mips32_op = OPC_NEG_PS; + goto do_unaryfp; + + /* Reciprocal square root step */ + case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S): + mips32_op = OPC_RSQRT1_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D): + mips32_op = OPC_RSQRT1_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS): + mips32_op = OPC_RSQRT1_PS; + goto do_unaryfp; + + /* Reciprocal step */ + case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S): + mips32_op = OPC_RECIP1_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D): + mips32_op = OPC_RECIP1_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS): + mips32_op = OPC_RECIP1_PS; + goto do_unaryfp; + + /* Conversions from double */ + case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S): + mips32_op = OPC_CVT_D_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W): + mips32_op = OPC_CVT_D_W; + goto do_unaryfp; + case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L): + mips32_op = OPC_CVT_D_L; + goto do_unaryfp; + + /* Conversions from single */ + case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D): + mips32_op = OPC_CVT_S_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W): + mips32_op = OPC_CVT_S_W; + goto do_unaryfp; + case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L): + mips32_op = OPC_CVT_S_L; + do_unaryfp: + gen_farith(ctx, mips32_op, -1, rs, rt, 0); + break; + + /* Conditional moves on floating-point codes */ + case COND_FLOAT_MOV(MOVT, 0): + case COND_FLOAT_MOV(MOVT, 1): + case COND_FLOAT_MOV(MOVT, 2): + case COND_FLOAT_MOV(MOVT, 3): + case COND_FLOAT_MOV(MOVT, 4): + case COND_FLOAT_MOV(MOVT, 5): + case COND_FLOAT_MOV(MOVT, 6): + case COND_FLOAT_MOV(MOVT, 7): + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1); + break; + case COND_FLOAT_MOV(MOVF, 0): + case COND_FLOAT_MOV(MOVF, 1): + case COND_FLOAT_MOV(MOVF, 2): + case COND_FLOAT_MOV(MOVF, 3): + case COND_FLOAT_MOV(MOVF, 4): + case COND_FLOAT_MOV(MOVF, 5): + case COND_FLOAT_MOV(MOVF, 6): + case COND_FLOAT_MOV(MOVF, 7): + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0); + break; + default: + MIPS_INVAL("pool32fxf"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) +{ + int32_t offset; + uint16_t insn; + int rt, rs, rd, rr; + int16_t imm; + uint32_t op, minor, minor2, mips32_op; + uint32_t cond, fmt, cc; + + insn = cpu_lduw_code(env, ctx->base.pc_next + 2); + ctx->opcode = (ctx->opcode << 16) | insn; + + rt = (ctx->opcode >> 21) & 0x1f; + rs = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + rr = (ctx->opcode >> 6) & 0x1f; + imm = (int16_t) ctx->opcode; + + op = (ctx->opcode >> 26) & 0x3f; + switch (op) { + case POOL32A: + minor = ctx->opcode & 0x3f; + switch (minor) { + case 0x00: + minor = (ctx->opcode >> 6) & 0xf; + switch (minor) { + case SLL32: + mips32_op = OPC_SLL; + goto do_shifti; + case SRA: + mips32_op = OPC_SRA; + goto do_shifti; + case SRL32: + mips32_op = OPC_SRL; + goto do_shifti; + case ROTR: + mips32_op = OPC_ROTR; + do_shifti: + gen_shift_imm(ctx, mips32_op, rt, rs, rd); + break; + case SELEQZ: + check_insn(ctx, ISA_MIPS32R6); + gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt); + break; + case SELNEZ: + check_insn(ctx, ISA_MIPS32R6); + gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt); + break; + case R6_RDHWR: + check_insn(ctx, ISA_MIPS32R6); + gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); + break; + default: + goto pool32a_invalid; + } + break; + case 0x10: + minor = (ctx->opcode >> 6) & 0xf; + switch (minor) { + /* Arithmetic */ + case ADD: + mips32_op = OPC_ADD; + goto do_arith; + case ADDU32: + mips32_op = OPC_ADDU; + goto do_arith; + case SUB: + mips32_op = OPC_SUB; + goto do_arith; + case SUBU32: + mips32_op = OPC_SUBU; + goto do_arith; + case MUL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MUL; + do_arith: + gen_arith(ctx, mips32_op, rd, rs, rt); + break; + /* Shifts */ + case SLLV: + mips32_op = OPC_SLLV; + goto do_shift; + case SRLV: + mips32_op = OPC_SRLV; + goto do_shift; + case SRAV: + mips32_op = OPC_SRAV; + goto do_shift; + case ROTRV: + mips32_op = OPC_ROTRV; + do_shift: + gen_shift(ctx, mips32_op, rd, rs, rt); + break; + /* Logical operations */ + case AND: + mips32_op = OPC_AND; + goto do_logic; + case OR32: + mips32_op = OPC_OR; + goto do_logic; + case NOR: + mips32_op = OPC_NOR; + goto do_logic; + case XOR32: + mips32_op = OPC_XOR; + do_logic: + gen_logic(ctx, mips32_op, rd, rs, rt); + break; + /* Set less than */ + case SLT: + mips32_op = OPC_SLT; + goto do_slt; + case SLTU: + mips32_op = OPC_SLTU; + do_slt: + gen_slt(ctx, mips32_op, rd, rs, rt); + break; + default: + goto pool32a_invalid; + } + break; + case 0x18: + minor = (ctx->opcode >> 6) & 0xf; + switch (minor) { + /* Conditional moves */ + case MOVN: /* MUL */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* MUL */ + gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); + } else { + /* MOVN */ + gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); + } + break; + case MOVZ: /* MUH */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* MUH */ + gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); + } else { + /* MOVZ */ + gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); + } + break; + case MULU: + check_insn(ctx, ISA_MIPS32R6); + gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); + break; + case MUHU: + check_insn(ctx, ISA_MIPS32R6); + gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); + break; + case LWXS: /* DIV */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* DIV */ + gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); + } else { + /* LWXS */ + gen_ldxs(ctx, rs, rt, rd); + } + break; + case MOD: + check_insn(ctx, ISA_MIPS32R6); + gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); + break; + case R6_DIVU: + check_insn(ctx, ISA_MIPS32R6); + gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); + break; + case MODU: + check_insn(ctx, ISA_MIPS32R6); + gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); + break; + default: + goto pool32a_invalid; + } + break; + case INS: + gen_bitops(ctx, OPC_INS, rt, rs, rr, rd); + return; + case LSA: + check_insn(ctx, ISA_MIPS32R6); + gen_lsa(ctx, OPC_LSA, rd, rs, rt, + extract32(ctx->opcode, 9, 2)); + break; + case ALIGN: + check_insn(ctx, ISA_MIPS32R6); + gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2)); + break; + case EXT: + gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd); + return; + case POOL32AXF: + gen_pool32axf(env, ctx, rt, rs); + break; + case BREAK32: + generate_exception_end(ctx, EXCP_BREAK); + break; + case SIGRIE: + check_insn(ctx, ISA_MIPS32R6); + generate_exception_end(ctx, EXCP_RI); + break; + default: + pool32a_invalid: + MIPS_INVAL("pool32a"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case POOL32B: + minor = (ctx->opcode >> 12) & 0xf; + switch (minor) { + case CACHE: + check_cp0_enabled(ctx); + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, imm); + } + break; + case LWC2: + case SWC2: + /* COP2: Not implemented. */ + generate_exception_err(ctx, EXCP_CpU, 2); + break; +#ifdef TARGET_MIPS64 + case LDP: + case SDP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); +#endif + /* fall through */ + case LWP: + case SWP: + gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12)); + break; +#ifdef TARGET_MIPS64 + case LDM: + case SDM: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); +#endif + /* fall through */ + case LWM32: + case SWM32: + gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12)); + break; + default: + MIPS_INVAL("pool32b"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case POOL32F: + if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { + minor = ctx->opcode & 0x3f; + check_cp1_enabled(ctx); + switch (minor) { + case ALNV_PS: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_ALNV_PS; + goto do_madd; + case MADD_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MADD_S; + goto do_madd; + case MADD_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MADD_D; + goto do_madd; + case MADD_PS: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MADD_PS; + goto do_madd; + case MSUB_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MSUB_S; + goto do_madd; + case MSUB_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MSUB_D; + goto do_madd; + case MSUB_PS: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_MSUB_PS; + goto do_madd; + case NMADD_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_NMADD_S; + goto do_madd; + case NMADD_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_NMADD_D; + goto do_madd; + case NMADD_PS: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_NMADD_PS; + goto do_madd; + case NMSUB_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_NMSUB_S; + goto do_madd; + case NMSUB_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_NMSUB_D; + goto do_madd; + case NMSUB_PS: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_NMSUB_PS; + do_madd: + gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt); + break; + case CABS_COND_FMT: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + cond = (ctx->opcode >> 6) & 0xf; + cc = (ctx->opcode >> 13) & 0x7; + fmt = (ctx->opcode >> 10) & 0x3; + switch (fmt) { + case 0x0: + gen_cmpabs_s(ctx, cond, rt, rs, cc); + break; + case 0x1: + gen_cmpabs_d(ctx, cond, rt, rs, cc); + break; + case 0x2: + gen_cmpabs_ps(ctx, cond, rt, rs, cc); + break; + default: + goto pool32f_invalid; + } + break; + case C_COND_FMT: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + cond = (ctx->opcode >> 6) & 0xf; + cc = (ctx->opcode >> 13) & 0x7; + fmt = (ctx->opcode >> 10) & 0x3; + switch (fmt) { + case 0x0: + gen_cmp_s(ctx, cond, rt, rs, cc); + break; + case 0x1: + gen_cmp_d(ctx, cond, rt, rs, cc); + break; + case 0x2: + gen_cmp_ps(ctx, cond, rt, rs, cc); + break; + default: + goto pool32f_invalid; + } + break; + case CMP_CONDN_S: + check_insn(ctx, ISA_MIPS32R6); + gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); + break; + case CMP_CONDN_D: + check_insn(ctx, ISA_MIPS32R6); + gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); + break; + case POOL32FXF: + gen_pool32fxf(ctx, rt, rs); + break; + case 0x00: + /* PLL foo */ + switch ((ctx->opcode >> 6) & 0x7) { + case PLL_PS: + mips32_op = OPC_PLL_PS; + goto do_ps; + case PLU_PS: + mips32_op = OPC_PLU_PS; + goto do_ps; + case PUL_PS: + mips32_op = OPC_PUL_PS; + goto do_ps; + case PUU_PS: + mips32_op = OPC_PUU_PS; + goto do_ps; + case CVT_PS_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_CVT_PS_S; + do_ps: + gen_farith(ctx, mips32_op, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case MIN_FMT: + check_insn(ctx, ISA_MIPS32R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case 0x08: + /* [LS][WDU]XC1 */ + switch ((ctx->opcode >> 6) & 0x7) { + case LWXC1: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LWXC1; + goto do_ldst_cp1; + case SWXC1: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SWXC1; + goto do_ldst_cp1; + case LDXC1: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LDXC1; + goto do_ldst_cp1; + case SDXC1: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SDXC1; + goto do_ldst_cp1; + case LUXC1: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LUXC1; + goto do_ldst_cp1; + case SUXC1: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SUXC1; + do_ldst_cp1: + gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs); + break; + default: + goto pool32f_invalid; + } + break; + case MAX_FMT: + check_insn(ctx, ISA_MIPS32R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case 0x18: + /* 3D insns */ + check_insn_opc_removed(ctx, ISA_MIPS32R6); + fmt = (ctx->opcode >> 9) & 0x3; + switch ((ctx->opcode >> 6) & 0x7) { + case RSQRT2_FMT: + switch (fmt) { + case FMT_SDPS_S: + mips32_op = OPC_RSQRT2_S; + goto do_3d; + case FMT_SDPS_D: + mips32_op = OPC_RSQRT2_D; + goto do_3d; + case FMT_SDPS_PS: + mips32_op = OPC_RSQRT2_PS; + goto do_3d; + default: + goto pool32f_invalid; + } + break; + case RECIP2_FMT: + switch (fmt) { + case FMT_SDPS_S: + mips32_op = OPC_RECIP2_S; + goto do_3d; + case FMT_SDPS_D: + mips32_op = OPC_RECIP2_D; + goto do_3d; + case FMT_SDPS_PS: + mips32_op = OPC_RECIP2_PS; + goto do_3d; + default: + goto pool32f_invalid; + } + break; + case ADDR_PS: + mips32_op = OPC_ADDR_PS; + goto do_3d; + case MULR_PS: + mips32_op = OPC_MULR_PS; + do_3d: + gen_farith(ctx, mips32_op, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case 0x20: + /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/ + cc = (ctx->opcode >> 13) & 0x7; + fmt = (ctx->opcode >> 9) & 0x3; + switch ((ctx->opcode >> 6) & 0x7) { + case MOVF_FMT: /* RINT_FMT */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* RINT_FMT */ + switch (fmt) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); + break; + default: + goto pool32f_invalid; + } + } else { + /* MOVF_FMT */ + switch (fmt) { + case FMT_SDPS_S: + gen_movcf_s(ctx, rs, rt, cc, 0); + break; + case FMT_SDPS_D: + gen_movcf_d(ctx, rs, rt, cc, 0); + break; + case FMT_SDPS_PS: + check_ps(ctx); + gen_movcf_ps(ctx, rs, rt, cc, 0); + break; + default: + goto pool32f_invalid; + } + } + break; + case MOVT_FMT: /* CLASS_FMT */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* CLASS_FMT */ + switch (fmt) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); + break; + default: + goto pool32f_invalid; + } + } else { + /* MOVT_FMT */ + switch (fmt) { + case FMT_SDPS_S: + gen_movcf_s(ctx, rs, rt, cc, 1); + break; + case FMT_SDPS_D: + gen_movcf_d(ctx, rs, rt, cc, 1); + break; + case FMT_SDPS_PS: + check_ps(ctx); + gen_movcf_ps(ctx, rs, rt, cc, 1); + break; + default: + goto pool32f_invalid; + } + } + break; + case PREFX: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + break; + default: + goto pool32f_invalid; + } + break; +#define FINSN_3ARG_SDPS(prfx) \ + switch ((ctx->opcode >> 8) & 0x3) { \ + case FMT_SDPS_S: \ + mips32_op = OPC_##prfx##_S; \ + goto do_fpop; \ + case FMT_SDPS_D: \ + mips32_op = OPC_##prfx##_D; \ + goto do_fpop; \ + case FMT_SDPS_PS: \ + check_ps(ctx); \ + mips32_op = OPC_##prfx##_PS; \ + goto do_fpop; \ + default: \ + goto pool32f_invalid; \ + } + case MINA_FMT: + check_insn(ctx, ISA_MIPS32R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case MAXA_FMT: + check_insn(ctx, ISA_MIPS32R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case 0x30: + /* regular FP ops */ + switch ((ctx->opcode >> 6) & 0x3) { + case ADD_FMT: + FINSN_3ARG_SDPS(ADD); + break; + case SUB_FMT: + FINSN_3ARG_SDPS(SUB); + break; + case MUL_FMT: + FINSN_3ARG_SDPS(MUL); + break; + case DIV_FMT: + fmt = (ctx->opcode >> 8) & 0x3; + if (fmt == 1) { + mips32_op = OPC_DIV_D; + } else if (fmt == 0) { + mips32_op = OPC_DIV_S; + } else { + goto pool32f_invalid; + } + goto do_fpop; + default: + goto pool32f_invalid; + } + break; + case 0x38: + /* cmovs */ + switch ((ctx->opcode >> 6) & 0x7) { + case MOVN_FMT: /* SELEQZ_FMT */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* SELEQZ_FMT */ + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); + break; + case FMT_SDPS_D: + gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); + break; + default: + goto pool32f_invalid; + } + } else { + /* MOVN_FMT */ + FINSN_3ARG_SDPS(MOVN); + } + break; + case MOVN_FMT_04: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + FINSN_3ARG_SDPS(MOVN); + break; + case MOVZ_FMT: /* SELNEZ_FMT */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* SELNEZ_FMT */ + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); + break; + case FMT_SDPS_D: + gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); + break; + default: + goto pool32f_invalid; + } + } else { + /* MOVZ_FMT */ + FINSN_3ARG_SDPS(MOVZ); + } + break; + case MOVZ_FMT_05: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + FINSN_3ARG_SDPS(MOVZ); + break; + case SEL_FMT: + check_insn(ctx, ISA_MIPS32R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); + break; + case FMT_SDPS_D: + gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); + break; + default: + goto pool32f_invalid; + } + break; + case MADDF_FMT: + check_insn(ctx, ISA_MIPS32R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + mips32_op = OPC_MADDF_S; + goto do_fpop; + case FMT_SDPS_D: + mips32_op = OPC_MADDF_D; + goto do_fpop; + default: + goto pool32f_invalid; + } + break; + case MSUBF_FMT: + check_insn(ctx, ISA_MIPS32R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + mips32_op = OPC_MSUBF_S; + goto do_fpop; + case FMT_SDPS_D: + mips32_op = OPC_MSUBF_D; + goto do_fpop; + default: + goto pool32f_invalid; + } + break; + default: + goto pool32f_invalid; + } + break; + do_fpop: + gen_farith(ctx, mips32_op, rt, rs, rd, 0); + break; + default: + pool32f_invalid: + MIPS_INVAL("pool32f"); + generate_exception_end(ctx, EXCP_RI); + break; + } + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } + break; + case POOL32I: + minor = (ctx->opcode >> 21) & 0x1f; + switch (minor) { + case BLTZ: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4); + break; + case BLTZAL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; + case BLTZALS: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; + case BGEZ: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4); + break; + case BGEZAL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; + case BGEZALS: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; + case BLEZ: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4); + break; + case BGTZ: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4); + break; + + /* Traps */ + case TLTI: /* BC1EQZC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* BC1EQZC */ + check_cp1_enabled(ctx); + gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0); + } else { + /* TLTI */ + mips32_op = OPC_TLTI; + goto do_trapi; + } + break; + case TGEI: /* BC1NEZC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* BC1NEZC */ + check_cp1_enabled(ctx); + gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0); + } else { + /* TGEI */ + mips32_op = OPC_TGEI; + goto do_trapi; + } + break; + case TLTIU: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_TLTIU; + goto do_trapi; + case TGEIU: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_TGEIU; + goto do_trapi; + case TNEI: /* SYNCI */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* SYNCI */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ + ctx->base.is_jmp = DISAS_STOP; + } else { + /* TNEI */ + mips32_op = OPC_TNEI; + goto do_trapi; + } + break; + case TEQI: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_TEQI; + do_trapi: + gen_trap(ctx, mips32_op, rs, -1, imm); + break; + + case BNEZC: + case BEQZC: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ, + 4, rs, 0, imm << 1, 0); + /* + * Compact branches don't have a delay slot, so just let + * the normal delay slot handling take us to the branch + * target. + */ + break; + case LUI: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_logic_imm(ctx, OPC_LUI, rs, 0, imm); + break; + case SYNCI: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ + ctx->base.is_jmp = DISAS_STOP; + break; + case BC2F: + case BC2T: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + /* COP2: Not implemented. */ + generate_exception_err(ctx, EXCP_CpU, 2); + break; + case BC1F: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F; + goto do_cp1branch; + case BC1T: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T; + goto do_cp1branch; + case BC1ANY4F: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_BC1FANY4; + goto do_cp1mips3d; + case BC1ANY4T: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_BC1TANY4; + do_cp1mips3d: + check_cop1x(ctx); + check_insn(ctx, ASE_MIPS3D); + /* Fall through */ + do_cp1branch: + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + check_cp1_enabled(ctx); + gen_compute_branch1(ctx, mips32_op, + (ctx->opcode >> 18) & 0x7, imm << 1); + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } + break; + case BPOSGE64: + case BPOSGE32: + /* MIPS DSP: not implemented */ + /* Fall through */ + default: + MIPS_INVAL("pool32i"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case POOL32C: + minor = (ctx->opcode >> 12) & 0xf; + offset = sextract32(ctx->opcode, 0, + (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12); + switch (minor) { + case LWL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LWL; + goto do_ld_lr; + case SWL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SWL; + goto do_st_lr; + case LWR: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LWR; + goto do_ld_lr; + case SWR: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SWR; + goto do_st_lr; +#if defined(TARGET_MIPS64) + case LDL: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LDL; + goto do_ld_lr; + case SDL: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SDL; + goto do_st_lr; + case LDR: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LDR; + goto do_ld_lr; + case SDR: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SDR; + goto do_st_lr; + case LWU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + mips32_op = OPC_LWU; + goto do_ld_lr; + case LLD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + mips32_op = OPC_LLD; + goto do_ld_lr; +#endif + case LL: + mips32_op = OPC_LL; + goto do_ld_lr; + do_ld_lr: + gen_ld(ctx, mips32_op, rt, rs, offset); + break; + do_st_lr: + gen_st(ctx, mips32_op, rt, rs, offset); + break; + case SC: + gen_st_cond(ctx, rt, rs, offset, MO_TESL, false); + break; +#if defined(TARGET_MIPS64) + case SCD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false); + break; +#endif + case LD_EVA: + if (!ctx->eva) { + MIPS_INVAL("pool32c ld-eva"); + generate_exception_end(ctx, EXCP_RI); + break; + } + check_cp0_enabled(ctx); + + minor2 = (ctx->opcode >> 9) & 0x7; + offset = sextract32(ctx->opcode, 0, 9); + switch (minor2) { + case LBUE: + mips32_op = OPC_LBUE; + goto do_ld_lr; + case LHUE: + mips32_op = OPC_LHUE; + goto do_ld_lr; + case LWLE: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LWLE; + goto do_ld_lr; + case LWRE: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_LWRE; + goto do_ld_lr; + case LBE: + mips32_op = OPC_LBE; + goto do_ld_lr; + case LHE: + mips32_op = OPC_LHE; + goto do_ld_lr; + case LLE: + mips32_op = OPC_LLE; + goto do_ld_lr; + case LWE: + mips32_op = OPC_LWE; + goto do_ld_lr; + }; + break; + case ST_EVA: + if (!ctx->eva) { + MIPS_INVAL("pool32c st-eva"); + generate_exception_end(ctx, EXCP_RI); + break; + } + check_cp0_enabled(ctx); + + minor2 = (ctx->opcode >> 9) & 0x7; + offset = sextract32(ctx->opcode, 0, 9); + switch (minor2) { + case SWLE: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SWLE; + goto do_st_lr; + case SWRE: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + mips32_op = OPC_SWRE; + goto do_st_lr; + case PREFE: + /* Treat as no-op */ + if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) { + /* hint codes 24-31 are reserved and signal RI */ + generate_exception(ctx, EXCP_RI); + } + break; + case CACHEE: + /* Treat as no-op */ + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, offset); + } + break; + case SBE: + mips32_op = OPC_SBE; + goto do_st_lr; + case SHE: + mips32_op = OPC_SHE; + goto do_st_lr; + case SCE: + gen_st_cond(ctx, rt, rs, offset, MO_TESL, true); + break; + case SWE: + mips32_op = OPC_SWE; + goto do_st_lr; + }; + break; + case PREF: + /* Treat as no-op */ + if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) { + /* hint codes 24-31 are reserved and signal RI */ + generate_exception(ctx, EXCP_RI); + } + break; + default: + MIPS_INVAL("pool32c"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case ADDI32: /* AUI, LUI */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* AUI, LUI */ + gen_logic_imm(ctx, OPC_LUI, rt, rs, imm); + } else { + /* ADDI32 */ + mips32_op = OPC_ADDI; + goto do_addi; + } + break; + case ADDIU32: + mips32_op = OPC_ADDIU; + do_addi: + gen_arith_imm(ctx, mips32_op, rt, rs, imm); + break; + + /* Logical operations */ + case ORI32: + mips32_op = OPC_ORI; + goto do_logici; + case XORI32: + mips32_op = OPC_XORI; + goto do_logici; + case ANDI32: + mips32_op = OPC_ANDI; + do_logici: + gen_logic_imm(ctx, mips32_op, rt, rs, imm); + break; + + /* Set less than immediate */ + case SLTI32: + mips32_op = OPC_SLTI; + goto do_slti; + case SLTIU32: + mips32_op = OPC_SLTIU; + do_slti: + gen_slt_imm(ctx, mips32_op, rt, rs, imm); + break; + case JALX32: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; + gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; + case JALS32: /* BOVC, BEQC, BEQZALC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rs >= rt) { + /* BOVC */ + mips32_op = OPC_BOVC; + } else if (rs < rt && rs == 0) { + /* BEQZALC */ + mips32_op = OPC_BEQZALC; + } else { + /* BEQC */ + mips32_op = OPC_BEQC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + /* JALS32 */ + offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; + gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + } + break; + case BEQ32: /* BC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* BC */ + gen_compute_compact_branch(ctx, OPC_BC, 0, 0, + sextract32(ctx->opcode << 1, 0, 27)); + } else { + /* BEQ32 */ + gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4); + } + break; + case BNE32: /* BALC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* BALC */ + gen_compute_compact_branch(ctx, OPC_BALC, 0, 0, + sextract32(ctx->opcode << 1, 0, 27)); + } else { + /* BNE32 */ + gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4); + } + break; + case J32: /* BGTZC, BLTZC, BLTC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rs == 0 && rt != 0) { + /* BGTZC */ + mips32_op = OPC_BGTZC; + } else if (rs != 0 && rt != 0 && rs == rt) { + /* BLTZC */ + mips32_op = OPC_BLTZC; + } else { + /* BLTC */ + mips32_op = OPC_BLTC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + /* J32 */ + gen_compute_branch(ctx, OPC_J, 4, rt, rs, + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); + } + break; + case JAL32: /* BLEZC, BGEZC, BGEC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rs == 0 && rt != 0) { + /* BLEZC */ + mips32_op = OPC_BLEZC; + } else if (rs != 0 && rt != 0 && rs == rt) { + /* BGEZC */ + mips32_op = OPC_BGEZC; + } else { + /* BGEC */ + mips32_op = OPC_BGEC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + /* JAL32 */ + gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + } + break; + /* Floating point (COP1) */ + case LWC132: + mips32_op = OPC_LWC1; + goto do_cop1; + case LDC132: + mips32_op = OPC_LDC1; + goto do_cop1; + case SWC132: + mips32_op = OPC_SWC1; + goto do_cop1; + case SDC132: + mips32_op = OPC_SDC1; + do_cop1: + gen_cop1_ldst(ctx, mips32_op, rt, rs, imm); + break; + case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ + switch ((ctx->opcode >> 16) & 0x1f) { + case ADDIUPC_00: + case ADDIUPC_01: + case ADDIUPC_02: + case ADDIUPC_03: + case ADDIUPC_04: + case ADDIUPC_05: + case ADDIUPC_06: + case ADDIUPC_07: + gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt); + break; + case AUIPC: + gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt); + break; + case ALUIPC: + gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt); + break; + case LWPC_08: + case LWPC_09: + case LWPC_0A: + case LWPC_0B: + case LWPC_0C: + case LWPC_0D: + case LWPC_0E: + case LWPC_0F: + gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + } else { + /* ADDIUPC */ + int reg = mmreg(ZIMM(ctx->opcode, 23, 3)); + offset = SIMM(ctx->opcode, 0, 23) << 2; + + gen_addiupc(ctx, reg, offset, 0, 0); + } + break; + case BNVC: /* BNEC, BNEZALC */ + check_insn(ctx, ISA_MIPS32R6); + if (rs >= rt) { + /* BNVC */ + mips32_op = OPC_BNVC; + } else if (rs < rt && rs == 0) { + /* BNEZALC */ + mips32_op = OPC_BNEZALC; + } else { + /* BNEC */ + mips32_op = OPC_BNEC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; + case R6_BNEZC: /* JIALC */ + check_insn(ctx, ISA_MIPS32R6); + if (rt != 0) { + /* BNEZC */ + gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0, + sextract32(ctx->opcode << 1, 0, 22)); + } else { + /* JIALC */ + gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm); + } + break; + case R6_BEQZC: /* JIC */ + check_insn(ctx, ISA_MIPS32R6); + if (rt != 0) { + /* BEQZC */ + gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0, + sextract32(ctx->opcode << 1, 0, 22)); + } else { + /* JIC */ + gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm); + } + break; + case BLEZALC: /* BGEZALC, BGEUC */ + check_insn(ctx, ISA_MIPS32R6); + if (rs == 0 && rt != 0) { + /* BLEZALC */ + mips32_op = OPC_BLEZALC; + } else if (rs != 0 && rt != 0 && rs == rt) { + /* BGEZALC */ + mips32_op = OPC_BGEZALC; + } else { + /* BGEUC */ + mips32_op = OPC_BGEUC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; + case BGTZALC: /* BLTZALC, BLTUC */ + check_insn(ctx, ISA_MIPS32R6); + if (rs == 0 && rt != 0) { + /* BGTZALC */ + mips32_op = OPC_BGTZALC; + } else if (rs != 0 && rt != 0 && rs == rt) { + /* BLTZALC */ + mips32_op = OPC_BLTZALC; + } else { + /* BLTUC */ + mips32_op = OPC_BLTUC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; + /* Loads and stores */ + case LB32: + mips32_op = OPC_LB; + goto do_ld; + case LBU32: + mips32_op = OPC_LBU; + goto do_ld; + case LH32: + mips32_op = OPC_LH; + goto do_ld; + case LHU32: + mips32_op = OPC_LHU; + goto do_ld; + case LW32: + mips32_op = OPC_LW; + goto do_ld; +#ifdef TARGET_MIPS64 + case LD32: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + mips32_op = OPC_LD; + goto do_ld; + case SD32: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + mips32_op = OPC_SD; + goto do_st; +#endif + case SB32: + mips32_op = OPC_SB; + goto do_st; + case SH32: + mips32_op = OPC_SH; + goto do_st; + case SW32: + mips32_op = OPC_SW; + goto do_st; + do_ld: + gen_ld(ctx, mips32_op, rt, rs, imm); + break; + do_st: + gen_st(ctx, mips32_op, rt, rs, imm); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t op; + + /* make sure instructions are on a halfword boundary */ + if (ctx->base.pc_next & 0x1) { + env->CP0_BadVAddr = ctx->base.pc_next; + generate_exception_end(ctx, EXCP_AdEL); + return 2; + } + + op = (ctx->opcode >> 10) & 0x3f; + /* Enforce properly-sized instructions in a delay slot */ + if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) { + switch (op & 0x7) { /* MSB-3..MSB-5 */ + case 0: + /* POOL32A, POOL32B, POOL32I, POOL32C */ + case 4: + /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */ + case 5: + /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */ + case 6: + /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */ + case 7: + /* LB32, LH32, LWC132, LDC132, LW32 */ + if (ctx->hflags & MIPS_HFLAG_BDS16) { + generate_exception_end(ctx, EXCP_RI); + return 2; + } + break; + case 1: + /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */ + case 2: + /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */ + case 3: + /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */ + if (ctx->hflags & MIPS_HFLAG_BDS32) { + generate_exception_end(ctx, EXCP_RI); + return 2; + } + break; + } + } + + switch (op) { + case POOL16A: + { + int rd = mmreg(uMIPS_RD(ctx->opcode)); + int rs1 = mmreg(uMIPS_RS1(ctx->opcode)); + int rs2 = mmreg(uMIPS_RS2(ctx->opcode)); + uint32_t opc = 0; + + switch (ctx->opcode & 0x1) { + case ADDU16: + opc = OPC_ADDU; + break; + case SUBU16: + opc = OPC_SUBU; + break; + } + if (ctx->insn_flags & ISA_MIPS32R6) { + /* + * In the Release 6, the register number location in + * the instruction encoding has changed. + */ + gen_arith(ctx, opc, rs1, rd, rs2); + } else { + gen_arith(ctx, opc, rd, rs1, rs2); + } + } + break; + case POOL16B: + { + int rd = mmreg(uMIPS_RD(ctx->opcode)); + int rs = mmreg(uMIPS_RS(ctx->opcode)); + int amount = (ctx->opcode >> 1) & 0x7; + uint32_t opc = 0; + amount = amount == 0 ? 8 : amount; + + switch (ctx->opcode & 0x1) { + case SLL16: + opc = OPC_SLL; + break; + case SRL16: + opc = OPC_SRL; + break; + } + + gen_shift_imm(ctx, opc, rd, rs, amount); + } + break; + case POOL16C: + if (ctx->insn_flags & ISA_MIPS32R6) { + gen_pool16c_r6_insn(ctx); + } else { + gen_pool16c_insn(ctx); + } + break; + case LWGP16: + { + int rd = mmreg(uMIPS_RD(ctx->opcode)); + int rb = 28; /* GP */ + int16_t offset = SIMM(ctx->opcode, 0, 7) << 2; + + gen_ld(ctx, OPC_LW, rd, rb, offset); + } + break; + case POOL16F: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + if (ctx->opcode & 1) { + generate_exception_end(ctx, EXCP_RI); + } else { + /* MOVEP */ + int enc_dest = uMIPS_RD(ctx->opcode); + int enc_rt = uMIPS_RS2(ctx->opcode); + int enc_rs = uMIPS_RS1(ctx->opcode); + gen_movep(ctx, enc_dest, enc_rt, enc_rs); + } + break; + case LBU16: + { + int rd = mmreg(uMIPS_RD(ctx->opcode)); + int rb = mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset = ZIMM(ctx->opcode, 0, 4); + offset = (offset == 0xf ? -1 : offset); + + gen_ld(ctx, OPC_LBU, rd, rb, offset); + } + break; + case LHU16: + { + int rd = mmreg(uMIPS_RD(ctx->opcode)); + int rb = mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1; + + gen_ld(ctx, OPC_LHU, rd, rb, offset); + } + break; + case LWSP16: + { + int rd = (ctx->opcode >> 5) & 0x1f; + int rb = 29; /* SP */ + int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2; + + gen_ld(ctx, OPC_LW, rd, rb, offset); + } + break; + case LW16: + { + int rd = mmreg(uMIPS_RD(ctx->opcode)); + int rb = mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2; + + gen_ld(ctx, OPC_LW, rd, rb, offset); + } + break; + case SB16: + { + int rd = mmreg2(uMIPS_RD(ctx->opcode)); + int rb = mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset = ZIMM(ctx->opcode, 0, 4); + + gen_st(ctx, OPC_SB, rd, rb, offset); + } + break; + case SH16: + { + int rd = mmreg2(uMIPS_RD(ctx->opcode)); + int rb = mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1; + + gen_st(ctx, OPC_SH, rd, rb, offset); + } + break; + case SWSP16: + { + int rd = (ctx->opcode >> 5) & 0x1f; + int rb = 29; /* SP */ + int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2; + + gen_st(ctx, OPC_SW, rd, rb, offset); + } + break; + case SW16: + { + int rd = mmreg2(uMIPS_RD(ctx->opcode)); + int rb = mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2; + + gen_st(ctx, OPC_SW, rd, rb, offset); + } + break; + case MOVE16: + { + int rd = uMIPS_RD5(ctx->opcode); + int rs = uMIPS_RS5(ctx->opcode); + + gen_arith(ctx, OPC_ADDU, rd, rs, 0); + } + break; + case ANDI16: + gen_andi16(ctx); + break; + case POOL16D: + switch (ctx->opcode & 0x1) { + case ADDIUS5: + gen_addius5(ctx); + break; + case ADDIUSP: + gen_addiusp(ctx); + break; + } + break; + case POOL16E: + switch (ctx->opcode & 0x1) { + case ADDIUR2: + gen_addiur2(ctx); + break; + case ADDIUR1SP: + gen_addiur1sp(ctx); + break; + } + break; + case B16: /* BC16 */ + gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, + sextract32(ctx->opcode, 0, 10) << 1, + (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4); + break; + case BNEZ16: /* BNEZC16 */ + case BEQZ16: /* BEQZC16 */ + gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2, + mmreg(uMIPS_RD(ctx->opcode)), + 0, sextract32(ctx->opcode, 0, 7) << 1, + (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4); + + break; + case LI16: + { + int reg = mmreg(uMIPS_RD(ctx->opcode)); + int imm = ZIMM(ctx->opcode, 0, 7); + + imm = (imm == 0x7f ? -1 : imm); + tcg_gen_movi_tl(cpu_gpr[reg], imm); + } + break; + case RES_29: + case RES_31: + case RES_39: + generate_exception_end(ctx, EXCP_RI); + break; + default: + decode_micromips32_opc(env, ctx); + return 4; + } + + return 2; +} From patchwork Mon Nov 23 20:44:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926773 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 3ABD4C388F9 for ; Mon, 23 Nov 2020 21:14:07 +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 1B6AF206B5 for ; Mon, 23 Nov 2020 21:14:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tgYRmYzX" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1B6AF206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:39614 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ9w-0003WU-O5 for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:14:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46752) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIiv-0002Ld-F1 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:10 -0500 Received: from mail-wr1-x42b.google.com ([2a00:1450:4864:20::42b]:42014) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIiq-0001fy-9t for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:09 -0500 Received: by mail-wr1-x42b.google.com with SMTP id l1so20095701wrb.9 for ; Mon, 23 Nov 2020 12:46:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Z/pF7A1vx2r51xCtcQ70IuUORwKxzO04ZvJG8bbSsYo=; b=tgYRmYzXexpVJmWbGkU3xCUSTMFFaH/2EKuVpCx7+cXQeTFB+XGdRurGi5MMdmAjx8 PKrSrhz5mwQpQJ9aFrTY377eFwzOsqbPA8YQmfEMOXjQf1j0tbhZUySQQffJTO6TySGc 9kaXs9NYpnWD98PogyN1BvVDnhx98nUXQcOt2UlXh0c3wuJz8NK2Rjd4+a4x64mXNtSO nsH+gk6PiDwvdlAdi9guGWYNB5oUgxZ1V15XMJ3lvNbU8+ViNhtW6s2RH9qbe+GQKjbX vKVpOI1pXn7pcarp9Q+UnhTWVHiNSu4EetajdMpkA0kALtIEcsSKlXxgmQVZouq6jOIx ZYhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=Z/pF7A1vx2r51xCtcQ70IuUORwKxzO04ZvJG8bbSsYo=; b=Wi02vqt/h5XG9OLaSzggTRiqdpLhjNGHdZHDjhexYX+RhUKXvvqc32qE1ksfXmUdBB 0yl1xTVYVnc+NF4Ez7x1HOahJxqNo8lToWG0U5seRVA5+b9GVxrFabmnlgq7EtfC2GSB a3NRszq/tuxCBe399C6TwsknUPxy5LBHPcTdfywVnmHFFxELrb0I+IymvGxcRbcbt/jq D13C2GVscMp3CGgLLEx6ptuieFWFiP4v72FGGprt7Aa/lzkgtlm9tNaP55DfROd9HLYm PMZVMW2cnxUFUTzbafVHskiSFy4YTc/uePz1F36EFaptxXMmjRBtOOxZftMGuDMfB0v1 HUPg== X-Gm-Message-State: AOAM533p7P60IcmBw+Iaqdv9FwUqEaiuJVl+Dvao4HvxCNTC/zWbC2+R MYAficQ2aLyDlu7QFxtYuOpuoHr4ReU= X-Google-Smtp-Source: ABdhPJwJrF2l8WSqfYjNwqDwEslitWp7DgmxenlaI/tGg5QdAEABVbBIFRhj5voNpyIjkxGYuKYJIQ== X-Received: by 2002:a5d:474d:: with SMTP id o13mr1608432wrs.178.1606164360878; Mon, 23 Nov 2020 12:46:00 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id 6sm25325971wrn.72.2020.11.23.12.45.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:45:59 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 14/28] target/mips: Extract nanoMIPS ISA translation routines Date: Mon, 23 Nov 2020 21:44:34 +0100 Message-Id: <20201123204448.3260804-15-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::42b; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x42b.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract 4800 lines from the huge translate.c to a new file, 'isa-nanomips_translate.c.inc'. As there are too many inter- dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-13-f4bug@amsat.org> --- target/mips/translate.c | 4838 +-------------------- MAINTAINERS | 1 + target/mips/isa-nanomips_translate.c.inc | 4839 ++++++++++++++++++++++ 3 files changed, 4841 insertions(+), 4837 deletions(-) create mode 100644 target/mips/isa-nanomips_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 5373a3f9a0a..d6133bd7de7 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -6012,130 +6012,6 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } - -/* nanoMIPS Branches */ -static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc, - int insn_bytes, - int rs, int rt, int32_t offset) -{ - target_ulong btgt = -1; - int bcond_compute = 0; - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - /* Load needed operands */ - switch (opc) { - case OPC_BEQ: - case OPC_BNE: - /* Compare two registers */ - if (rs != rt) { - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - bcond_compute = 1; - } - btgt = ctx->base.pc_next + insn_bytes + offset; - break; - case OPC_BGEZAL: - /* Compare to zero */ - if (rs != 0) { - gen_load_gpr(t0, rs); - bcond_compute = 1; - } - btgt = ctx->base.pc_next + insn_bytes + offset; - break; - case OPC_BPOSGE32: - tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F); - bcond_compute = 1; - btgt = ctx->base.pc_next + insn_bytes + offset; - break; - case OPC_JR: - case OPC_JALR: - /* Jump to register */ - if (offset != 0 && offset != 16) { - /* - * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the - * others are reserved. - */ - MIPS_INVAL("jump hint"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - gen_load_gpr(btarget, rs); - break; - default: - MIPS_INVAL("branch/jump"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - if (bcond_compute == 0) { - /* No condition to be computed */ - switch (opc) { - case OPC_BEQ: /* rx == rx */ - /* Always take */ - ctx->hflags |= MIPS_HFLAG_B; - break; - case OPC_BGEZAL: /* 0 >= 0 */ - /* Always take and link */ - tcg_gen_movi_tl(cpu_gpr[31], - ctx->base.pc_next + insn_bytes); - ctx->hflags |= MIPS_HFLAG_B; - break; - case OPC_BNE: /* rx != rx */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8); - /* Skip the instruction in the delay slot */ - ctx->base.pc_next += 4; - goto out; - case OPC_JR: - ctx->hflags |= MIPS_HFLAG_BR; - break; - case OPC_JALR: - if (rt > 0) { - tcg_gen_movi_tl(cpu_gpr[rt], - ctx->base.pc_next + insn_bytes); - } - ctx->hflags |= MIPS_HFLAG_BR; - break; - default: - MIPS_INVAL("branch/jump"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - } else { - switch (opc) { - case OPC_BEQ: - tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); - goto not_likely; - case OPC_BNE: - tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); - goto not_likely; - case OPC_BGEZAL: - tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); - tcg_gen_movi_tl(cpu_gpr[31], - ctx->base.pc_next + insn_bytes); - goto not_likely; - case OPC_BPOSGE32: - tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32); - not_likely: - ctx->hflags |= MIPS_HFLAG_BC; - break; - default: - MIPS_INVAL("conditional branch/jump"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - } - - ctx->btarget = btgt; - - out: - if (insn_bytes == 2) { - ctx->hflags |= MIPS_HFLAG_B16; - } - tcg_temp_free(t0); - tcg_temp_free(t1); -} - - /* special3 bitfield operations */ static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt, int rs, int lsb, int msb) @@ -13134,4719 +13010,7 @@ out: #include "ase-mips16e_translate.c.inc" #include "isa-micromips_translate.c.inc" - -/* - * - * nanoMIPS opcodes - * - */ - -/* MAJOR, P16, and P32 pools opcodes */ -enum { - NM_P_ADDIU = 0x00, - NM_ADDIUPC = 0x01, - NM_MOVE_BALC = 0x02, - NM_P16_MV = 0x04, - NM_LW16 = 0x05, - NM_BC16 = 0x06, - NM_P16_SR = 0x07, - - NM_POOL32A = 0x08, - NM_P_BAL = 0x0a, - NM_P16_SHIFT = 0x0c, - NM_LWSP16 = 0x0d, - NM_BALC16 = 0x0e, - NM_P16_4X4 = 0x0f, - - NM_P_GP_W = 0x10, - NM_P_GP_BH = 0x11, - NM_P_J = 0x12, - NM_P16C = 0x14, - NM_LWGP16 = 0x15, - NM_P16_LB = 0x17, - - NM_P48I = 0x18, - NM_P16_A1 = 0x1c, - NM_LW4X4 = 0x1d, - NM_P16_LH = 0x1f, - - NM_P_U12 = 0x20, - NM_P_LS_U12 = 0x21, - NM_P_BR1 = 0x22, - NM_P16_A2 = 0x24, - NM_SW16 = 0x25, - NM_BEQZC16 = 0x26, - - NM_POOL32F = 0x28, - NM_P_LS_S9 = 0x29, - NM_P_BR2 = 0x2a, - - NM_P16_ADDU = 0x2c, - NM_SWSP16 = 0x2d, - NM_BNEZC16 = 0x2e, - NM_MOVEP = 0x2f, - - NM_POOL32S = 0x30, - NM_P_BRI = 0x32, - NM_LI16 = 0x34, - NM_SWGP16 = 0x35, - NM_P16_BR = 0x36, - - NM_P_LUI = 0x38, - NM_ANDI16 = 0x3c, - NM_SW4X4 = 0x3d, - NM_MOVEPREV = 0x3f, -}; - -/* POOL32A instruction pool */ -enum { - NM_POOL32A0 = 0x00, - NM_SPECIAL2 = 0x01, - NM_COP2_1 = 0x02, - NM_UDI = 0x03, - NM_POOL32A5 = 0x05, - NM_POOL32A7 = 0x07, -}; - -/* P.GP.W instruction pool */ -enum { - NM_ADDIUGP_W = 0x00, - NM_LWGP = 0x02, - NM_SWGP = 0x03, -}; - -/* P48I instruction pool */ -enum { - NM_LI48 = 0x00, - NM_ADDIU48 = 0x01, - NM_ADDIUGP48 = 0x02, - NM_ADDIUPC48 = 0x03, - NM_LWPC48 = 0x0b, - NM_SWPC48 = 0x0f, -}; - -/* P.U12 instruction pool */ -enum { - NM_ORI = 0x00, - NM_XORI = 0x01, - NM_ANDI = 0x02, - NM_P_SR = 0x03, - NM_SLTI = 0x04, - NM_SLTIU = 0x05, - NM_SEQI = 0x06, - NM_ADDIUNEG = 0x08, - NM_P_SHIFT = 0x0c, - NM_P_ROTX = 0x0d, - NM_P_INS = 0x0e, - NM_P_EXT = 0x0f, -}; - -/* POOL32F instruction pool */ -enum { - NM_POOL32F_0 = 0x00, - NM_POOL32F_3 = 0x03, - NM_POOL32F_5 = 0x05, -}; - -/* POOL32S instruction pool */ -enum { - NM_POOL32S_0 = 0x00, - NM_POOL32S_4 = 0x04, -}; - -/* P.LUI instruction pool */ -enum { - NM_LUI = 0x00, - NM_ALUIPC = 0x01, -}; - -/* P.GP.BH instruction pool */ -enum { - NM_LBGP = 0x00, - NM_SBGP = 0x01, - NM_LBUGP = 0x02, - NM_ADDIUGP_B = 0x03, - NM_P_GP_LH = 0x04, - NM_P_GP_SH = 0x05, - NM_P_GP_CP1 = 0x06, -}; - -/* P.LS.U12 instruction pool */ -enum { - NM_LB = 0x00, - NM_SB = 0x01, - NM_LBU = 0x02, - NM_P_PREFU12 = 0x03, - NM_LH = 0x04, - NM_SH = 0x05, - NM_LHU = 0x06, - NM_LWU = 0x07, - NM_LW = 0x08, - NM_SW = 0x09, - NM_LWC1 = 0x0a, - NM_SWC1 = 0x0b, - NM_LDC1 = 0x0e, - NM_SDC1 = 0x0f, -}; - -/* P.LS.S9 instruction pool */ -enum { - NM_P_LS_S0 = 0x00, - NM_P_LS_S1 = 0x01, - NM_P_LS_E0 = 0x02, - NM_P_LS_WM = 0x04, - NM_P_LS_UAWM = 0x05, -}; - -/* P.BAL instruction pool */ -enum { - NM_BC = 0x00, - NM_BALC = 0x01, -}; - -/* P.J instruction pool */ -enum { - NM_JALRC = 0x00, - NM_JALRC_HB = 0x01, - NM_P_BALRSC = 0x08, -}; - -/* P.BR1 instruction pool */ -enum { - NM_BEQC = 0x00, - NM_P_BR3A = 0x01, - NM_BGEC = 0x02, - NM_BGEUC = 0x03, -}; - -/* P.BR2 instruction pool */ -enum { - NM_BNEC = 0x00, - NM_BLTC = 0x02, - NM_BLTUC = 0x03, -}; - -/* P.BRI instruction pool */ -enum { - NM_BEQIC = 0x00, - NM_BBEQZC = 0x01, - NM_BGEIC = 0x02, - NM_BGEIUC = 0x03, - NM_BNEIC = 0x04, - NM_BBNEZC = 0x05, - NM_BLTIC = 0x06, - NM_BLTIUC = 0x07, -}; - -/* P16.SHIFT instruction pool */ -enum { - NM_SLL16 = 0x00, - NM_SRL16 = 0x01, -}; - -/* POOL16C instruction pool */ -enum { - NM_POOL16C_0 = 0x00, - NM_LWXS16 = 0x01, -}; - -/* P16.A1 instruction pool */ -enum { - NM_ADDIUR1SP = 0x01, -}; - -/* P16.A2 instruction pool */ -enum { - NM_ADDIUR2 = 0x00, - NM_P_ADDIURS5 = 0x01, -}; - -/* P16.ADDU instruction pool */ -enum { - NM_ADDU16 = 0x00, - NM_SUBU16 = 0x01, -}; - -/* P16.SR instruction pool */ -enum { - NM_SAVE16 = 0x00, - NM_RESTORE_JRC16 = 0x01, -}; - -/* P16.4X4 instruction pool */ -enum { - NM_ADDU4X4 = 0x00, - NM_MUL4X4 = 0x01, -}; - -/* P16.LB instruction pool */ -enum { - NM_LB16 = 0x00, - NM_SB16 = 0x01, - NM_LBU16 = 0x02, -}; - -/* P16.LH instruction pool */ -enum { - NM_LH16 = 0x00, - NM_SH16 = 0x01, - NM_LHU16 = 0x02, -}; - -/* P.RI instruction pool */ -enum { - NM_SIGRIE = 0x00, - NM_P_SYSCALL = 0x01, - NM_BREAK = 0x02, - NM_SDBBP = 0x03, -}; - -/* POOL32A0 instruction pool */ -enum { - NM_P_TRAP = 0x00, - NM_SEB = 0x01, - NM_SLLV = 0x02, - NM_MUL = 0x03, - NM_MFC0 = 0x06, - NM_MFHC0 = 0x07, - NM_SEH = 0x09, - NM_SRLV = 0x0a, - NM_MUH = 0x0b, - NM_MTC0 = 0x0e, - NM_MTHC0 = 0x0f, - NM_SRAV = 0x12, - NM_MULU = 0x13, - NM_ROTRV = 0x1a, - NM_MUHU = 0x1b, - NM_ADD = 0x22, - NM_DIV = 0x23, - NM_ADDU = 0x2a, - NM_MOD = 0x2b, - NM_SUB = 0x32, - NM_DIVU = 0x33, - NM_RDHWR = 0x38, - NM_SUBU = 0x3a, - NM_MODU = 0x3b, - NM_P_CMOVE = 0x42, - NM_FORK = 0x45, - NM_MFTR = 0x46, - NM_MFHTR = 0x47, - NM_AND = 0x4a, - NM_YIELD = 0x4d, - NM_MTTR = 0x4e, - NM_MTHTR = 0x4f, - NM_OR = 0x52, - NM_D_E_MT_VPE = 0x56, - NM_NOR = 0x5a, - NM_XOR = 0x62, - NM_SLT = 0x6a, - NM_P_SLTU = 0x72, - NM_SOV = 0x7a, -}; - -/* CRC32 instruction pool */ -enum { - NM_CRC32B = 0x00, - NM_CRC32H = 0x01, - NM_CRC32W = 0x02, - NM_CRC32CB = 0x04, - NM_CRC32CH = 0x05, - NM_CRC32CW = 0x06, -}; - -/* POOL32A5 instruction pool */ -enum { - NM_CMP_EQ_PH = 0x00, - NM_CMP_LT_PH = 0x08, - NM_CMP_LE_PH = 0x10, - NM_CMPGU_EQ_QB = 0x18, - NM_CMPGU_LT_QB = 0x20, - NM_CMPGU_LE_QB = 0x28, - NM_CMPGDU_EQ_QB = 0x30, - NM_CMPGDU_LT_QB = 0x38, - NM_CMPGDU_LE_QB = 0x40, - NM_CMPU_EQ_QB = 0x48, - NM_CMPU_LT_QB = 0x50, - NM_CMPU_LE_QB = 0x58, - NM_ADDQ_S_W = 0x60, - NM_SUBQ_S_W = 0x68, - NM_ADDSC = 0x70, - NM_ADDWC = 0x78, - - NM_ADDQ_S_PH = 0x01, - NM_ADDQH_R_PH = 0x09, - NM_ADDQH_R_W = 0x11, - NM_ADDU_S_QB = 0x19, - NM_ADDU_S_PH = 0x21, - NM_ADDUH_R_QB = 0x29, - NM_SHRAV_R_PH = 0x31, - NM_SHRAV_R_QB = 0x39, - NM_SUBQ_S_PH = 0x41, - NM_SUBQH_R_PH = 0x49, - NM_SUBQH_R_W = 0x51, - NM_SUBU_S_QB = 0x59, - NM_SUBU_S_PH = 0x61, - NM_SUBUH_R_QB = 0x69, - NM_SHLLV_S_PH = 0x71, - NM_PRECR_SRA_R_PH_W = 0x79, - - NM_MULEU_S_PH_QBL = 0x12, - NM_MULEU_S_PH_QBR = 0x1a, - NM_MULQ_RS_PH = 0x22, - NM_MULQ_S_PH = 0x2a, - NM_MULQ_RS_W = 0x32, - NM_MULQ_S_W = 0x3a, - NM_APPEND = 0x42, - NM_MODSUB = 0x52, - NM_SHRAV_R_W = 0x5a, - NM_SHRLV_PH = 0x62, - NM_SHRLV_QB = 0x6a, - NM_SHLLV_QB = 0x72, - NM_SHLLV_S_W = 0x7a, - - NM_SHILO = 0x03, - - NM_MULEQ_S_W_PHL = 0x04, - NM_MULEQ_S_W_PHR = 0x0c, - - NM_MUL_S_PH = 0x05, - NM_PRECR_QB_PH = 0x0d, - NM_PRECRQ_QB_PH = 0x15, - NM_PRECRQ_PH_W = 0x1d, - NM_PRECRQ_RS_PH_W = 0x25, - NM_PRECRQU_S_QB_PH = 0x2d, - NM_PACKRL_PH = 0x35, - NM_PICK_QB = 0x3d, - NM_PICK_PH = 0x45, - - NM_SHRA_R_W = 0x5e, - NM_SHRA_R_PH = 0x66, - NM_SHLL_S_PH = 0x76, - NM_SHLL_S_W = 0x7e, - - NM_REPL_PH = 0x07 -}; - -/* POOL32A7 instruction pool */ -enum { - NM_P_LSX = 0x00, - NM_LSA = 0x01, - NM_EXTW = 0x03, - NM_POOL32AXF = 0x07, -}; - -/* P.SR instruction pool */ -enum { - NM_PP_SR = 0x00, - NM_P_SR_F = 0x01, -}; - -/* P.SHIFT instruction pool */ -enum { - NM_P_SLL = 0x00, - NM_SRL = 0x02, - NM_SRA = 0x04, - NM_ROTR = 0x06, -}; - -/* P.ROTX instruction pool */ -enum { - NM_ROTX = 0x00, -}; - -/* P.INS instruction pool */ -enum { - NM_INS = 0x00, -}; - -/* P.EXT instruction pool */ -enum { - NM_EXT = 0x00, -}; - -/* POOL32F_0 (fmt) instruction pool */ -enum { - NM_RINT_S = 0x04, - NM_RINT_D = 0x44, - NM_ADD_S = 0x06, - NM_SELEQZ_S = 0x07, - NM_SELEQZ_D = 0x47, - NM_CLASS_S = 0x0c, - NM_CLASS_D = 0x4c, - NM_SUB_S = 0x0e, - NM_SELNEZ_S = 0x0f, - NM_SELNEZ_D = 0x4f, - NM_MUL_S = 0x16, - NM_SEL_S = 0x17, - NM_SEL_D = 0x57, - NM_DIV_S = 0x1e, - NM_ADD_D = 0x26, - NM_SUB_D = 0x2e, - NM_MUL_D = 0x36, - NM_MADDF_S = 0x37, - NM_MADDF_D = 0x77, - NM_DIV_D = 0x3e, - NM_MSUBF_S = 0x3f, - NM_MSUBF_D = 0x7f, -}; - -/* POOL32F_3 instruction pool */ -enum { - NM_MIN_FMT = 0x00, - NM_MAX_FMT = 0x01, - NM_MINA_FMT = 0x04, - NM_MAXA_FMT = 0x05, - NM_POOL32FXF = 0x07, -}; - -/* POOL32F_5 instruction pool */ -enum { - NM_CMP_CONDN_S = 0x00, - NM_CMP_CONDN_D = 0x02, -}; - -/* P.GP.LH instruction pool */ -enum { - NM_LHGP = 0x00, - NM_LHUGP = 0x01, -}; - -/* P.GP.SH instruction pool */ -enum { - NM_SHGP = 0x00, -}; - -/* P.GP.CP1 instruction pool */ -enum { - NM_LWC1GP = 0x00, - NM_SWC1GP = 0x01, - NM_LDC1GP = 0x02, - NM_SDC1GP = 0x03, -}; - -/* P.LS.S0 instruction pool */ -enum { - NM_LBS9 = 0x00, - NM_LHS9 = 0x04, - NM_LWS9 = 0x08, - NM_LDS9 = 0x0c, - - NM_SBS9 = 0x01, - NM_SHS9 = 0x05, - NM_SWS9 = 0x09, - NM_SDS9 = 0x0d, - - NM_LBUS9 = 0x02, - NM_LHUS9 = 0x06, - NM_LWC1S9 = 0x0a, - NM_LDC1S9 = 0x0e, - - NM_P_PREFS9 = 0x03, - NM_LWUS9 = 0x07, - NM_SWC1S9 = 0x0b, - NM_SDC1S9 = 0x0f, -}; - -/* P.LS.S1 instruction pool */ -enum { - NM_ASET_ACLR = 0x02, - NM_UALH = 0x04, - NM_UASH = 0x05, - NM_CACHE = 0x07, - NM_P_LL = 0x0a, - NM_P_SC = 0x0b, -}; - -/* P.LS.E0 instruction pool */ -enum { - NM_LBE = 0x00, - NM_SBE = 0x01, - NM_LBUE = 0x02, - NM_P_PREFE = 0x03, - NM_LHE = 0x04, - NM_SHE = 0x05, - NM_LHUE = 0x06, - NM_CACHEE = 0x07, - NM_LWE = 0x08, - NM_SWE = 0x09, - NM_P_LLE = 0x0a, - NM_P_SCE = 0x0b, -}; - -/* P.PREFE instruction pool */ -enum { - NM_SYNCIE = 0x00, - NM_PREFE = 0x01, -}; - -/* P.LLE instruction pool */ -enum { - NM_LLE = 0x00, - NM_LLWPE = 0x01, -}; - -/* P.SCE instruction pool */ -enum { - NM_SCE = 0x00, - NM_SCWPE = 0x01, -}; - -/* P.LS.WM instruction pool */ -enum { - NM_LWM = 0x00, - NM_SWM = 0x01, -}; - -/* P.LS.UAWM instruction pool */ -enum { - NM_UALWM = 0x00, - NM_UASWM = 0x01, -}; - -/* P.BR3A instruction pool */ -enum { - NM_BC1EQZC = 0x00, - NM_BC1NEZC = 0x01, - NM_BC2EQZC = 0x02, - NM_BC2NEZC = 0x03, - NM_BPOSGE32C = 0x04, -}; - -/* P16.RI instruction pool */ -enum { - NM_P16_SYSCALL = 0x01, - NM_BREAK16 = 0x02, - NM_SDBBP16 = 0x03, -}; - -/* POOL16C_0 instruction pool */ -enum { - NM_POOL16C_00 = 0x00, -}; - -/* P16.JRC instruction pool */ -enum { - NM_JRC = 0x00, - NM_JALRC16 = 0x01, -}; - -/* P.SYSCALL instruction pool */ -enum { - NM_SYSCALL = 0x00, - NM_HYPCALL = 0x01, -}; - -/* P.TRAP instruction pool */ -enum { - NM_TEQ = 0x00, - NM_TNE = 0x01, -}; - -/* P.CMOVE instruction pool */ -enum { - NM_MOVZ = 0x00, - NM_MOVN = 0x01, -}; - -/* POOL32Axf instruction pool */ -enum { - NM_POOL32AXF_1 = 0x01, - NM_POOL32AXF_2 = 0x02, - NM_POOL32AXF_4 = 0x04, - NM_POOL32AXF_5 = 0x05, - NM_POOL32AXF_7 = 0x07, -}; - -/* POOL32Axf_1 instruction pool */ -enum { - NM_POOL32AXF_1_0 = 0x00, - NM_POOL32AXF_1_1 = 0x01, - NM_POOL32AXF_1_3 = 0x03, - NM_POOL32AXF_1_4 = 0x04, - NM_POOL32AXF_1_5 = 0x05, - NM_POOL32AXF_1_7 = 0x07, -}; - -/* POOL32Axf_2 instruction pool */ -enum { - NM_POOL32AXF_2_0_7 = 0x00, - NM_POOL32AXF_2_8_15 = 0x01, - NM_POOL32AXF_2_16_23 = 0x02, - NM_POOL32AXF_2_24_31 = 0x03, -}; - -/* POOL32Axf_7 instruction pool */ -enum { - NM_SHRA_R_QB = 0x0, - NM_SHRL_PH = 0x1, - NM_REPL_QB = 0x2, -}; - -/* POOL32Axf_1_0 instruction pool */ -enum { - NM_MFHI = 0x0, - NM_MFLO = 0x1, - NM_MTHI = 0x2, - NM_MTLO = 0x3, -}; - -/* POOL32Axf_1_1 instruction pool */ -enum { - NM_MTHLIP = 0x0, - NM_SHILOV = 0x1, -}; - -/* POOL32Axf_1_3 instruction pool */ -enum { - NM_RDDSP = 0x0, - NM_WRDSP = 0x1, - NM_EXTP = 0x2, - NM_EXTPDP = 0x3, -}; - -/* POOL32Axf_1_4 instruction pool */ -enum { - NM_SHLL_QB = 0x0, - NM_SHRL_QB = 0x1, -}; - -/* POOL32Axf_1_5 instruction pool */ -enum { - NM_MAQ_S_W_PHR = 0x0, - NM_MAQ_S_W_PHL = 0x1, - NM_MAQ_SA_W_PHR = 0x2, - NM_MAQ_SA_W_PHL = 0x3, -}; - -/* POOL32Axf_1_7 instruction pool */ -enum { - NM_EXTR_W = 0x0, - NM_EXTR_R_W = 0x1, - NM_EXTR_RS_W = 0x2, - NM_EXTR_S_H = 0x3, -}; - -/* POOL32Axf_2_0_7 instruction pool */ -enum { - NM_DPA_W_PH = 0x0, - NM_DPAQ_S_W_PH = 0x1, - NM_DPS_W_PH = 0x2, - NM_DPSQ_S_W_PH = 0x3, - NM_BALIGN = 0x4, - NM_MADD = 0x5, - NM_MULT = 0x6, - NM_EXTRV_W = 0x7, -}; - -/* POOL32Axf_2_8_15 instruction pool */ -enum { - NM_DPAX_W_PH = 0x0, - NM_DPAQ_SA_L_W = 0x1, - NM_DPSX_W_PH = 0x2, - NM_DPSQ_SA_L_W = 0x3, - NM_MADDU = 0x5, - NM_MULTU = 0x6, - NM_EXTRV_R_W = 0x7, -}; - -/* POOL32Axf_2_16_23 instruction pool */ -enum { - NM_DPAU_H_QBL = 0x0, - NM_DPAQX_S_W_PH = 0x1, - NM_DPSU_H_QBL = 0x2, - NM_DPSQX_S_W_PH = 0x3, - NM_EXTPV = 0x4, - NM_MSUB = 0x5, - NM_MULSA_W_PH = 0x6, - NM_EXTRV_RS_W = 0x7, -}; - -/* POOL32Axf_2_24_31 instruction pool */ -enum { - NM_DPAU_H_QBR = 0x0, - NM_DPAQX_SA_W_PH = 0x1, - NM_DPSU_H_QBR = 0x2, - NM_DPSQX_SA_W_PH = 0x3, - NM_EXTPDPV = 0x4, - NM_MSUBU = 0x5, - NM_MULSAQ_S_W_PH = 0x6, - NM_EXTRV_S_H = 0x7, -}; - -/* POOL32Axf_{4, 5} instruction pool */ -enum { - NM_CLO = 0x25, - NM_CLZ = 0x2d, - - NM_TLBP = 0x01, - NM_TLBR = 0x09, - NM_TLBWI = 0x11, - NM_TLBWR = 0x19, - NM_TLBINV = 0x03, - NM_TLBINVF = 0x0b, - NM_DI = 0x23, - NM_EI = 0x2b, - NM_RDPGPR = 0x70, - NM_WRPGPR = 0x78, - NM_WAIT = 0x61, - NM_DERET = 0x71, - NM_ERETX = 0x79, - - /* nanoMIPS DSP instructions */ - NM_ABSQ_S_QB = 0x00, - NM_ABSQ_S_PH = 0x08, - NM_ABSQ_S_W = 0x10, - NM_PRECEQ_W_PHL = 0x28, - NM_PRECEQ_W_PHR = 0x30, - NM_PRECEQU_PH_QBL = 0x38, - NM_PRECEQU_PH_QBR = 0x48, - NM_PRECEU_PH_QBL = 0x58, - NM_PRECEU_PH_QBR = 0x68, - NM_PRECEQU_PH_QBLA = 0x39, - NM_PRECEQU_PH_QBRA = 0x49, - NM_PRECEU_PH_QBLA = 0x59, - NM_PRECEU_PH_QBRA = 0x69, - NM_REPLV_PH = 0x01, - NM_REPLV_QB = 0x09, - NM_BITREV = 0x18, - NM_INSV = 0x20, - NM_RADDU_W_QB = 0x78, - - NM_BITSWAP = 0x05, - NM_WSBH = 0x3d, -}; - -/* PP.SR instruction pool */ -enum { - NM_SAVE = 0x00, - NM_RESTORE = 0x02, - NM_RESTORE_JRC = 0x03, -}; - -/* P.SR.F instruction pool */ -enum { - NM_SAVEF = 0x00, - NM_RESTOREF = 0x01, -}; - -/* P16.SYSCALL instruction pool */ -enum { - NM_SYSCALL16 = 0x00, - NM_HYPCALL16 = 0x01, -}; - -/* POOL16C_00 instruction pool */ -enum { - NM_NOT16 = 0x00, - NM_XOR16 = 0x01, - NM_AND16 = 0x02, - NM_OR16 = 0x03, -}; - -/* PP.LSX and PP.LSXS instruction pool */ -enum { - NM_LBX = 0x00, - NM_LHX = 0x04, - NM_LWX = 0x08, - NM_LDX = 0x0c, - - NM_SBX = 0x01, - NM_SHX = 0x05, - NM_SWX = 0x09, - NM_SDX = 0x0d, - - NM_LBUX = 0x02, - NM_LHUX = 0x06, - NM_LWC1X = 0x0a, - NM_LDC1X = 0x0e, - - NM_LWUX = 0x07, - NM_SWC1X = 0x0b, - NM_SDC1X = 0x0f, - - NM_LHXS = 0x04, - NM_LWXS = 0x08, - NM_LDXS = 0x0c, - - NM_SHXS = 0x05, - NM_SWXS = 0x09, - NM_SDXS = 0x0d, - - NM_LHUXS = 0x06, - NM_LWC1XS = 0x0a, - NM_LDC1XS = 0x0e, - - NM_LWUXS = 0x07, - NM_SWC1XS = 0x0b, - NM_SDC1XS = 0x0f, -}; - -/* ERETx instruction pool */ -enum { - NM_ERET = 0x00, - NM_ERETNC = 0x01, -}; - -/* POOL32FxF_{0, 1} insturction pool */ -enum { - NM_CFC1 = 0x40, - NM_CTC1 = 0x60, - NM_MFC1 = 0x80, - NM_MTC1 = 0xa0, - NM_MFHC1 = 0xc0, - NM_MTHC1 = 0xe0, - - NM_CVT_S_PL = 0x84, - NM_CVT_S_PU = 0xa4, - - NM_CVT_L_S = 0x004, - NM_CVT_L_D = 0x104, - NM_CVT_W_S = 0x024, - NM_CVT_W_D = 0x124, - - NM_RSQRT_S = 0x008, - NM_RSQRT_D = 0x108, - - NM_SQRT_S = 0x028, - NM_SQRT_D = 0x128, - - NM_RECIP_S = 0x048, - NM_RECIP_D = 0x148, - - NM_FLOOR_L_S = 0x00c, - NM_FLOOR_L_D = 0x10c, - - NM_FLOOR_W_S = 0x02c, - NM_FLOOR_W_D = 0x12c, - - NM_CEIL_L_S = 0x04c, - NM_CEIL_L_D = 0x14c, - NM_CEIL_W_S = 0x06c, - NM_CEIL_W_D = 0x16c, - NM_TRUNC_L_S = 0x08c, - NM_TRUNC_L_D = 0x18c, - NM_TRUNC_W_S = 0x0ac, - NM_TRUNC_W_D = 0x1ac, - NM_ROUND_L_S = 0x0cc, - NM_ROUND_L_D = 0x1cc, - NM_ROUND_W_S = 0x0ec, - NM_ROUND_W_D = 0x1ec, - - NM_MOV_S = 0x01, - NM_MOV_D = 0x81, - NM_ABS_S = 0x0d, - NM_ABS_D = 0x8d, - NM_NEG_S = 0x2d, - NM_NEG_D = 0xad, - NM_CVT_D_S = 0x04d, - NM_CVT_D_W = 0x0cd, - NM_CVT_D_L = 0x14d, - NM_CVT_S_D = 0x06d, - NM_CVT_S_W = 0x0ed, - NM_CVT_S_L = 0x16d, -}; - -/* P.LL instruction pool */ -enum { - NM_LL = 0x00, - NM_LLWP = 0x01, -}; - -/* P.SC instruction pool */ -enum { - NM_SC = 0x00, - NM_SCWP = 0x01, -}; - -/* P.DVP instruction pool */ -enum { - NM_DVP = 0x00, - NM_EVP = 0x01, -}; - - -/* - * - * nanoMIPS decoding engine - * - */ - - -/* extraction utilities */ - -#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7) -#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7) -#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7) -#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f) -#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f) - -/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */ -static inline int decode_gpr_gpr3(int r) -{ - static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 }; - - return map[r & 0x7]; -} - -/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */ -static inline int decode_gpr_gpr3_src_store(int r) -{ - static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 }; - - return map[r & 0x7]; -} - -/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */ -static inline int decode_gpr_gpr4(int r) -{ - static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7, - 16, 17, 18, 19, 20, 21, 22, 23 }; - - return map[r & 0xf]; -} - -/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */ -static inline int decode_gpr_gpr4_zero(int r) -{ - static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7, - 16, 17, 18, 19, 20, 21, 22, 23 }; - - return map[r & 0xf]; -} - - -static void gen_adjust_sp(DisasContext *ctx, int u) -{ - gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u); -} - -static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count, - uint8_t gp, uint16_t u) -{ - int counter = 0; - TCGv va = tcg_temp_new(); - TCGv t0 = tcg_temp_new(); - - while (counter != count) { - bool use_gp = gp && (counter == count - 1); - int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f); - int this_offset = -((counter + 1) << 2); - gen_base_offset_addr(ctx, va, 29, this_offset); - gen_load_gpr(t0, this_rt); - tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx, - (MO_TEUL | ctx->default_tcg_memop_mask)); - counter++; - } - - /* adjust stack pointer */ - gen_adjust_sp(ctx, -u); - - tcg_temp_free(t0); - tcg_temp_free(va); -} - -static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count, - uint8_t gp, uint16_t u) -{ - int counter = 0; - TCGv va = tcg_temp_new(); - TCGv t0 = tcg_temp_new(); - - while (counter != count) { - bool use_gp = gp && (counter == count - 1); - int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f); - int this_offset = u - ((counter + 1) << 2); - gen_base_offset_addr(ctx, va, 29, this_offset); - tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL | - ctx->default_tcg_memop_mask); - tcg_gen_ext32s_tl(t0, t0); - gen_store_gpr(t0, this_rt); - counter++; - } - - /* adjust stack pointer */ - gen_adjust_sp(ctx, u); - - tcg_temp_free(t0); - tcg_temp_free(va); -} - -static void gen_pool16c_nanomips_insn(DisasContext *ctx) -{ - int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); - int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); - - switch (extract32(ctx->opcode, 2, 2)) { - case NM_NOT16: - gen_logic(ctx, OPC_NOR, rt, rs, 0); - break; - case NM_AND16: - gen_logic(ctx, OPC_AND, rt, rt, rs); - break; - case NM_XOR16: - gen_logic(ctx, OPC_XOR, rt, rt, rs); - break; - case NM_OR16: - gen_logic(ctx, OPC_OR, rt, rt, rs); - break; - } -} - -static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) -{ - int rt = extract32(ctx->opcode, 21, 5); - int rs = extract32(ctx->opcode, 16, 5); - int rd = extract32(ctx->opcode, 11, 5); - - switch (extract32(ctx->opcode, 3, 7)) { - case NM_P_TRAP: - switch (extract32(ctx->opcode, 10, 1)) { - case NM_TEQ: - check_nms(ctx); - gen_trap(ctx, OPC_TEQ, rs, rt, -1); - break; - case NM_TNE: - check_nms(ctx); - gen_trap(ctx, OPC_TNE, rs, rt, -1); - break; - } - break; - case NM_RDHWR: - check_nms(ctx); - gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); - break; - case NM_SEB: - check_nms(ctx); - gen_bshfl(ctx, OPC_SEB, rs, rt); - break; - case NM_SEH: - gen_bshfl(ctx, OPC_SEH, rs, rt); - break; - case NM_SLLV: - gen_shift(ctx, OPC_SLLV, rd, rt, rs); - break; - case NM_SRLV: - gen_shift(ctx, OPC_SRLV, rd, rt, rs); - break; - case NM_SRAV: - gen_shift(ctx, OPC_SRAV, rd, rt, rs); - break; - case NM_ROTRV: - gen_shift(ctx, OPC_ROTRV, rd, rt, rs); - break; - case NM_ADD: - gen_arith(ctx, OPC_ADD, rd, rs, rt); - break; - case NM_ADDU: - gen_arith(ctx, OPC_ADDU, rd, rs, rt); - break; - case NM_SUB: - check_nms(ctx); - gen_arith(ctx, OPC_SUB, rd, rs, rt); - break; - case NM_SUBU: - gen_arith(ctx, OPC_SUBU, rd, rs, rt); - break; - case NM_P_CMOVE: - switch (extract32(ctx->opcode, 10, 1)) { - case NM_MOVZ: - gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); - break; - case NM_MOVN: - gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); - break; - } - break; - case NM_AND: - gen_logic(ctx, OPC_AND, rd, rs, rt); - break; - case NM_OR: - gen_logic(ctx, OPC_OR, rd, rs, rt); - break; - case NM_NOR: - gen_logic(ctx, OPC_NOR, rd, rs, rt); - break; - case NM_XOR: - gen_logic(ctx, OPC_XOR, rd, rs, rt); - break; - case NM_SLT: - gen_slt(ctx, OPC_SLT, rd, rs, rt); - break; - case NM_P_SLTU: - if (rd == 0) { - /* P_DVP */ -#ifndef CONFIG_USER_ONLY - TCGv t0 = tcg_temp_new(); - switch (extract32(ctx->opcode, 10, 1)) { - case NM_DVP: - if (ctx->vp) { - check_cp0_enabled(ctx); - gen_helper_dvp(t0, cpu_env); - gen_store_gpr(t0, rt); - } - break; - case NM_EVP: - if (ctx->vp) { - check_cp0_enabled(ctx); - gen_helper_evp(t0, cpu_env); - gen_store_gpr(t0, rt); - } - break; - } - tcg_temp_free(t0); -#endif - } else { - gen_slt(ctx, OPC_SLTU, rd, rs, rt); - } - break; - case NM_SOV: - { - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - TCGv t2 = tcg_temp_new(); - - gen_load_gpr(t1, rs); - gen_load_gpr(t2, rt); - tcg_gen_add_tl(t0, t1, t2); - tcg_gen_ext32s_tl(t0, t0); - tcg_gen_xor_tl(t1, t1, t2); - tcg_gen_xor_tl(t2, t0, t2); - tcg_gen_andc_tl(t1, t2, t1); - - /* operands of same sign, result different sign */ - tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0); - gen_store_gpr(t0, rd); - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); - } - break; - case NM_MUL: - gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); - break; - case NM_MUH: - gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); - break; - case NM_MULU: - gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); - break; - case NM_MUHU: - gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); - break; - case NM_DIV: - gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); - break; - case NM_MOD: - gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); - break; - case NM_DIVU: - gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); - break; - case NM_MODU: - gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); - break; -#ifndef CONFIG_USER_ONLY - case NM_MFC0: - check_cp0_enabled(ctx); - if (rt == 0) { - /* Treat as NOP. */ - break; - } - gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3)); - break; - case NM_MTC0: - check_cp0_enabled(ctx); - { - TCGv t0 = tcg_temp_new(); - - gen_load_gpr(t0, rt); - gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3)); - tcg_temp_free(t0); - } - break; - case NM_D_E_MT_VPE: - { - uint8_t sc = extract32(ctx->opcode, 10, 1); - TCGv t0 = tcg_temp_new(); - - switch (sc) { - case 0: - if (rs == 1) { - /* DMT */ - check_cp0_mt(ctx); - gen_helper_dmt(t0); - gen_store_gpr(t0, rt); - } else if (rs == 0) { - /* DVPE */ - check_cp0_mt(ctx); - gen_helper_dvpe(t0, cpu_env); - gen_store_gpr(t0, rt); - } else { - generate_exception_end(ctx, EXCP_RI); - } - break; - case 1: - if (rs == 1) { - /* EMT */ - check_cp0_mt(ctx); - gen_helper_emt(t0); - gen_store_gpr(t0, rt); - } else if (rs == 0) { - /* EVPE */ - check_cp0_mt(ctx); - gen_helper_evpe(t0, cpu_env); - gen_store_gpr(t0, rt); - } else { - generate_exception_end(ctx, EXCP_RI); - } - break; - } - - tcg_temp_free(t0); - } - break; - case NM_FORK: - check_mt(ctx); - { - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - gen_load_gpr(t0, rt); - gen_load_gpr(t1, rs); - gen_helper_fork(t0, t1); - tcg_temp_free(t0); - tcg_temp_free(t1); - } - break; - case NM_MFTR: - case NM_MFHTR: - check_cp0_enabled(ctx); - if (rd == 0) { - /* Treat as NOP. */ - return; - } - gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), - extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1)); - break; - case NM_MTTR: - case NM_MTHTR: - check_cp0_enabled(ctx); - gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), - extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1)); - break; - case NM_YIELD: - check_mt(ctx); - { - TCGv t0 = tcg_temp_new(); - - gen_load_gpr(t0, rs); - gen_helper_yield(t0, cpu_env, t0); - gen_store_gpr(t0, rt); - tcg_temp_free(t0); - } - break; -#endif - default: - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* dsp */ -static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc, - int ret, int v1, int v2) -{ - TCGv_i32 t0; - TCGv v0_t; - TCGv v1_t; - - t0 = tcg_temp_new_i32(); - - v0_t = tcg_temp_new(); - v1_t = tcg_temp_new(); - - tcg_gen_movi_i32(t0, v2 >> 3); - - gen_load_gpr(v0_t, ret); - gen_load_gpr(v1_t, v1); - - switch (opc) { - case NM_MAQ_S_W_PHR: - check_dsp(ctx); - gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env); - break; - case NM_MAQ_S_W_PHL: - check_dsp(ctx); - gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env); - break; - case NM_MAQ_SA_W_PHR: - check_dsp(ctx); - gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env); - break; - case NM_MAQ_SA_W_PHL: - check_dsp(ctx); - gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free_i32(t0); - - tcg_temp_free(v0_t); - tcg_temp_free(v1_t); -} - - -static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc, - int ret, int v1, int v2) -{ - int16_t imm; - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - TCGv v0_t = tcg_temp_new(); - - gen_load_gpr(v0_t, v1); - - switch (opc) { - case NM_POOL32AXF_1_0: - check_dsp(ctx); - switch (extract32(ctx->opcode, 12, 2)) { - case NM_MFHI: - gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret); - break; - case NM_MFLO: - gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret); - break; - case NM_MTHI: - gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1); - break; - case NM_MTLO: - gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1); - break; - } - break; - case NM_POOL32AXF_1_1: - check_dsp(ctx); - switch (extract32(ctx->opcode, 12, 2)) { - case NM_MTHLIP: - tcg_gen_movi_tl(t0, v2); - gen_helper_mthlip(t0, v0_t, cpu_env); - break; - case NM_SHILOV: - tcg_gen_movi_tl(t0, v2 >> 3); - gen_helper_shilo(t0, v0_t, cpu_env); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_POOL32AXF_1_3: - check_dsp(ctx); - imm = extract32(ctx->opcode, 14, 7); - switch (extract32(ctx->opcode, 12, 2)) { - case NM_RDDSP: - tcg_gen_movi_tl(t0, imm); - gen_helper_rddsp(t0, t0, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_WRDSP: - gen_load_gpr(t0, ret); - tcg_gen_movi_tl(t1, imm); - gen_helper_wrdsp(t0, t1, cpu_env); - break; - case NM_EXTP: - tcg_gen_movi_tl(t0, v2 >> 3); - tcg_gen_movi_tl(t1, v1); - gen_helper_extp(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_EXTPDP: - tcg_gen_movi_tl(t0, v2 >> 3); - tcg_gen_movi_tl(t1, v1); - gen_helper_extpdp(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - case NM_POOL32AXF_1_4: - check_dsp(ctx); - tcg_gen_movi_tl(t0, v2 >> 2); - switch (extract32(ctx->opcode, 12, 1)) { - case NM_SHLL_QB: - gen_helper_shll_qb(t0, t0, v0_t, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_SHRL_QB: - gen_helper_shrl_qb(t0, t0, v0_t); - gen_store_gpr(t0, ret); - break; - } - break; - case NM_POOL32AXF_1_5: - opc = extract32(ctx->opcode, 12, 2); - gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2); - break; - case NM_POOL32AXF_1_7: - check_dsp(ctx); - tcg_gen_movi_tl(t0, v2 >> 3); - tcg_gen_movi_tl(t1, v1); - switch (extract32(ctx->opcode, 12, 2)) { - case NM_EXTR_W: - gen_helper_extr_w(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_EXTR_R_W: - gen_helper_extr_r_w(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_EXTR_RS_W: - gen_helper_extr_rs_w(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_EXTR_S_H: - gen_helper_extr_s_h(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(v0_t); -} - -static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc, - TCGv v0, TCGv v1, int rd) -{ - TCGv_i32 t0; - - t0 = tcg_temp_new_i32(); - - tcg_gen_movi_i32(t0, rd >> 3); - - switch (opc) { - case NM_POOL32AXF_2_0_7: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpa_w_ph(t0, v1, v0, cpu_env); - break; - case NM_DPAQ_S_W_PH: - check_dsp(ctx); - gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env); - break; - case NM_DPS_W_PH: - check_dsp_r2(ctx); - gen_helper_dps_w_ph(t0, v1, v0, cpu_env); - break; - case NM_DPSQ_S_W_PH: - check_dsp(ctx); - gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_POOL32AXF_2_8_15: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAX_W_PH: - check_dsp_r2(ctx); - gen_helper_dpax_w_ph(t0, v0, v1, cpu_env); - break; - case NM_DPAQ_SA_L_W: - check_dsp(ctx); - gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env); - break; - case NM_DPSX_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env); - break; - case NM_DPSQ_SA_L_W: - check_dsp(ctx); - gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_POOL32AXF_2_16_23: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAU_H_QBL: - check_dsp(ctx); - gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env); - break; - case NM_DPAQX_S_W_PH: - check_dsp_r2(ctx); - gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env); - break; - case NM_DPSU_H_QBL: - check_dsp(ctx); - gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env); - break; - case NM_DPSQX_S_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env); - break; - case NM_MULSA_W_PH: - check_dsp_r2(ctx); - gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_POOL32AXF_2_24_31: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAU_H_QBR: - check_dsp(ctx); - gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env); - break; - case NM_DPAQX_SA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env); - break; - case NM_DPSU_H_QBR: - check_dsp(ctx); - gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env); - break; - case NM_DPSQX_SA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env); - break; - case NM_MULSAQ_S_W_PH: - check_dsp(ctx); - gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free_i32(t0); -} - -static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc, - int rt, int rs, int rd) -{ - int ret = rt; - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - TCGv v0_t = tcg_temp_new(); - TCGv v1_t = tcg_temp_new(); - - gen_load_gpr(v0_t, rt); - gen_load_gpr(v1_t, rs); - - switch (opc) { - case NM_POOL32AXF_2_0_7: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPA_W_PH: - case NM_DPAQ_S_W_PH: - case NM_DPS_W_PH: - case NM_DPSQ_S_W_PH: - gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); - break; - case NM_BALIGN: - check_dsp_r2(ctx); - if (rt != 0) { - gen_load_gpr(t0, rs); - rd &= 3; - if (rd != 0 && rd != 2) { - tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_shri_tl(t0, t0, 8 * (4 - rd)); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - } - tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); - } - break; - case NM_MADD: - check_dsp(ctx); - { - int acc = extract32(ctx->opcode, 14, 2); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - gen_load_gpr(t0, rt); - gen_load_gpr(t1, rs); - tcg_gen_ext_tl_i64(t2, t0); - tcg_gen_ext_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_add_i64(t2, t2, t3); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - tcg_temp_free_i64(t2); - } - break; - case NM_MULT: - check_dsp(ctx); - { - int acc = extract32(ctx->opcode, 14, 2); - TCGv_i32 t2 = tcg_temp_new_i32(); - TCGv_i32 t3 = tcg_temp_new_i32(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_trunc_tl_i32(t2, t0); - tcg_gen_trunc_tl_i32(t3, t1); - tcg_gen_muls2_i32(t2, t3, t2, t3); - tcg_gen_ext_i32_tl(cpu_LO[acc], t2); - tcg_gen_ext_i32_tl(cpu_HI[acc], t3); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t3); - } - break; - case NM_EXTRV_W: - check_dsp(ctx); - gen_load_gpr(v1_t, rs); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_w(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - case NM_POOL32AXF_2_8_15: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAX_W_PH: - case NM_DPAQ_SA_L_W: - case NM_DPSX_W_PH: - case NM_DPSQ_SA_L_W: - gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); - break; - case NM_MADDU: - check_dsp(ctx); - { - int acc = extract32(ctx->opcode, 14, 2); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_extu_tl_i64(t2, t0); - tcg_gen_extu_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_add_i64(t2, t2, t3); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - tcg_temp_free_i64(t2); - } - break; - case NM_MULTU: - check_dsp(ctx); - { - int acc = extract32(ctx->opcode, 14, 2); - TCGv_i32 t2 = tcg_temp_new_i32(); - TCGv_i32 t3 = tcg_temp_new_i32(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_trunc_tl_i32(t2, t0); - tcg_gen_trunc_tl_i32(t3, t1); - tcg_gen_mulu2_i32(t2, t3, t2, t3); - tcg_gen_ext_i32_tl(cpu_LO[acc], t2); - tcg_gen_ext_i32_tl(cpu_HI[acc], t3); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t3); - } - break; - case NM_EXTRV_R_W: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_r_w(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_POOL32AXF_2_16_23: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAU_H_QBL: - case NM_DPAQX_S_W_PH: - case NM_DPSU_H_QBL: - case NM_DPSQX_S_W_PH: - case NM_MULSA_W_PH: - gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); - break; - case NM_EXTPV: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extp(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_MSUB: - check_dsp(ctx); - { - int acc = extract32(ctx->opcode, 14, 2); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_ext_tl_i64(t2, t0); - tcg_gen_ext_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_sub_i64(t2, t3, t2); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - tcg_temp_free_i64(t2); - } - break; - case NM_EXTRV_RS_W: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - case NM_POOL32AXF_2_24_31: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAU_H_QBR: - case NM_DPAQX_SA_W_PH: - case NM_DPSU_H_QBR: - case NM_DPSQX_SA_W_PH: - case NM_MULSAQ_S_W_PH: - gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); - break; - case NM_EXTPDPV: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extpdp(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_MSUBU: - check_dsp(ctx); - { - int acc = extract32(ctx->opcode, 14, 2); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_extu_tl_i64(t2, t0); - tcg_gen_extu_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_sub_i64(t2, t3, t2); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - tcg_temp_free_i64(t2); - } - break; - case NM_EXTRV_S_H: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_s_h(t0, t0, v0_t, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free(t0); - tcg_temp_free(t1); - - tcg_temp_free(v0_t); - tcg_temp_free(v1_t); -} - -static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc, - int rt, int rs) -{ - int ret = rt; - TCGv t0 = tcg_temp_new(); - TCGv v0_t = tcg_temp_new(); - - gen_load_gpr(v0_t, rs); - - switch (opc) { - case NM_ABSQ_S_QB: - check_dsp_r2(ctx); - gen_helper_absq_s_qb(v0_t, v0_t, cpu_env); - gen_store_gpr(v0_t, ret); - break; - case NM_ABSQ_S_PH: - check_dsp(ctx); - gen_helper_absq_s_ph(v0_t, v0_t, cpu_env); - gen_store_gpr(v0_t, ret); - break; - case NM_ABSQ_S_W: - check_dsp(ctx); - gen_helper_absq_s_w(v0_t, v0_t, cpu_env); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQ_W_PHL: - check_dsp(ctx); - tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000); - tcg_gen_ext32s_tl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQ_W_PHR: - check_dsp(ctx); - tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF); - tcg_gen_shli_tl(v0_t, v0_t, 16); - tcg_gen_ext32s_tl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQU_PH_QBL: - check_dsp(ctx); - gen_helper_precequ_ph_qbl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQU_PH_QBR: - check_dsp(ctx); - gen_helper_precequ_ph_qbr(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQU_PH_QBLA: - check_dsp(ctx); - gen_helper_precequ_ph_qbla(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQU_PH_QBRA: - check_dsp(ctx); - gen_helper_precequ_ph_qbra(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEU_PH_QBL: - check_dsp(ctx); - gen_helper_preceu_ph_qbl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEU_PH_QBR: - check_dsp(ctx); - gen_helper_preceu_ph_qbr(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEU_PH_QBLA: - check_dsp(ctx); - gen_helper_preceu_ph_qbla(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEU_PH_QBRA: - check_dsp(ctx); - gen_helper_preceu_ph_qbra(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_REPLV_PH: - check_dsp(ctx); - tcg_gen_ext16u_tl(v0_t, v0_t); - tcg_gen_shli_tl(t0, v0_t, 16); - tcg_gen_or_tl(v0_t, v0_t, t0); - tcg_gen_ext32s_tl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_REPLV_QB: - check_dsp(ctx); - tcg_gen_ext8u_tl(v0_t, v0_t); - tcg_gen_shli_tl(t0, v0_t, 8); - tcg_gen_or_tl(v0_t, v0_t, t0); - tcg_gen_shli_tl(t0, v0_t, 16); - tcg_gen_or_tl(v0_t, v0_t, t0); - tcg_gen_ext32s_tl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_BITREV: - check_dsp(ctx); - gen_helper_bitrev(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_INSV: - check_dsp(ctx); - { - TCGv tv0 = tcg_temp_new(); - - gen_load_gpr(tv0, rt); - gen_helper_insv(v0_t, cpu_env, v0_t, tv0); - gen_store_gpr(v0_t, ret); - tcg_temp_free(tv0); - } - break; - case NM_RADDU_W_QB: - check_dsp(ctx); - gen_helper_raddu_w_qb(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_BITSWAP: - gen_bitswap(ctx, OPC_BITSWAP, ret, rs); - break; - case NM_CLO: - check_nms(ctx); - gen_cl(ctx, OPC_CLO, ret, rs); - break; - case NM_CLZ: - check_nms(ctx); - gen_cl(ctx, OPC_CLZ, ret, rs); - break; - case NM_WSBH: - gen_bshfl(ctx, OPC_WSBH, ret, rs); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free(v0_t); - tcg_temp_free(t0); -} - -static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc, - int rt, int rs, int rd) -{ - TCGv t0 = tcg_temp_new(); - TCGv rs_t = tcg_temp_new(); - - gen_load_gpr(rs_t, rs); - - switch (opc) { - case NM_SHRA_R_QB: - check_dsp_r2(ctx); - tcg_gen_movi_tl(t0, rd >> 2); - switch (extract32(ctx->opcode, 12, 1)) { - case 0: - /* NM_SHRA_QB */ - gen_helper_shra_qb(t0, t0, rs_t); - gen_store_gpr(t0, rt); - break; - case 1: - /* NM_SHRA_R_QB */ - gen_helper_shra_r_qb(t0, t0, rs_t); - gen_store_gpr(t0, rt); - break; - } - break; - case NM_SHRL_PH: - check_dsp_r2(ctx); - tcg_gen_movi_tl(t0, rd >> 1); - gen_helper_shrl_ph(t0, t0, rs_t); - gen_store_gpr(t0, rt); - break; - case NM_REPL_QB: - check_dsp(ctx); - { - int16_t imm; - target_long result; - imm = extract32(ctx->opcode, 13, 8); - result = (uint32_t)imm << 24 | - (uint32_t)imm << 16 | - (uint32_t)imm << 8 | - (uint32_t)imm; - result = (int32_t)result; - tcg_gen_movi_tl(t0, result); - gen_store_gpr(t0, rt); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - tcg_temp_free(t0); - tcg_temp_free(rs_t); -} - - -static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) -{ - int rt = extract32(ctx->opcode, 21, 5); - int rs = extract32(ctx->opcode, 16, 5); - int rd = extract32(ctx->opcode, 11, 5); - - switch (extract32(ctx->opcode, 6, 3)) { - case NM_POOL32AXF_1: - { - int32_t op1 = extract32(ctx->opcode, 9, 3); - gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd); - } - break; - case NM_POOL32AXF_2: - { - int32_t op1 = extract32(ctx->opcode, 12, 2); - gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd); - } - break; - case NM_POOL32AXF_4: - { - int32_t op1 = extract32(ctx->opcode, 9, 7); - gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs); - } - break; - case NM_POOL32AXF_5: - switch (extract32(ctx->opcode, 9, 7)) { -#ifndef CONFIG_USER_ONLY - case NM_TLBP: - gen_cp0(env, ctx, OPC_TLBP, 0, 0); - break; - case NM_TLBR: - gen_cp0(env, ctx, OPC_TLBR, 0, 0); - break; - case NM_TLBWI: - gen_cp0(env, ctx, OPC_TLBWI, 0, 0); - break; - case NM_TLBWR: - gen_cp0(env, ctx, OPC_TLBWR, 0, 0); - break; - case NM_TLBINV: - gen_cp0(env, ctx, OPC_TLBINV, 0, 0); - break; - case NM_TLBINVF: - gen_cp0(env, ctx, OPC_TLBINVF, 0, 0); - break; - case NM_DI: - check_cp0_enabled(ctx); - { - TCGv t0 = tcg_temp_new(); - - save_cpu_state(ctx, 1); - gen_helper_di(t0, cpu_env); - gen_store_gpr(t0, rt); - /* Stop translation as we may have switched the execution mode */ - ctx->base.is_jmp = DISAS_STOP; - tcg_temp_free(t0); - } - break; - case NM_EI: - check_cp0_enabled(ctx); - { - TCGv t0 = tcg_temp_new(); - - save_cpu_state(ctx, 1); - gen_helper_ei(t0, cpu_env); - gen_store_gpr(t0, rt); - /* Stop translation as we may have switched the execution mode */ - ctx->base.is_jmp = DISAS_STOP; - tcg_temp_free(t0); - } - break; - case NM_RDPGPR: - gen_load_srsgpr(rs, rt); - break; - case NM_WRPGPR: - gen_store_srsgpr(rs, rt); - break; - case NM_WAIT: - gen_cp0(env, ctx, OPC_WAIT, 0, 0); - break; - case NM_DERET: - gen_cp0(env, ctx, OPC_DERET, 0, 0); - break; - case NM_ERETX: - gen_cp0(env, ctx, OPC_ERET, 0, 0); - break; -#endif - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_POOL32AXF_7: - { - int32_t op1 = extract32(ctx->opcode, 9, 3); - gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* Immediate Value Compact Branches */ -static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, - int rt, int32_t imm, int32_t offset) -{ - TCGCond cond = TCG_COND_ALWAYS; - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - gen_load_gpr(t0, rt); - tcg_gen_movi_tl(t1, imm); - ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); - - /* Load needed operands and calculate btarget */ - switch (opc) { - case NM_BEQIC: - if (rt == 0 && imm == 0) { - /* Unconditional branch */ - } else if (rt == 0 && imm != 0) { - /* Treat as NOP */ - goto out; - } else { - cond = TCG_COND_EQ; - } - break; - case NM_BBEQZC: - case NM_BBNEZC: - check_nms(ctx); - if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) { - generate_exception_end(ctx, EXCP_RI); - goto out; - } else if (rt == 0 && opc == NM_BBEQZC) { - /* Unconditional branch */ - } else if (rt == 0 && opc == NM_BBNEZC) { - /* Treat as NOP */ - goto out; - } else { - tcg_gen_shri_tl(t0, t0, imm); - tcg_gen_andi_tl(t0, t0, 1); - tcg_gen_movi_tl(t1, 0); - if (opc == NM_BBEQZC) { - cond = TCG_COND_EQ; - } else { - cond = TCG_COND_NE; - } - } - break; - case NM_BNEIC: - if (rt == 0 && imm == 0) { - /* Treat as NOP */ - goto out; - } else if (rt == 0 && imm != 0) { - /* Unconditional branch */ - } else { - cond = TCG_COND_NE; - } - break; - case NM_BGEIC: - if (rt == 0 && imm == 0) { - /* Unconditional branch */ - } else { - cond = TCG_COND_GE; - } - break; - case NM_BLTIC: - cond = TCG_COND_LT; - break; - case NM_BGEIUC: - if (rt == 0 && imm == 0) { - /* Unconditional branch */ - } else { - cond = TCG_COND_GEU; - } - break; - case NM_BLTIUC: - cond = TCG_COND_LTU; - break; - default: - MIPS_INVAL("Immediate Value Compact branch"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - - /* branch completion */ - clear_branch_hflags(ctx); - ctx->base.is_jmp = DISAS_NORETURN; - - if (cond == TCG_COND_ALWAYS) { - /* Uncoditional compact branch */ - gen_goto_tb(ctx, 0, ctx->btarget); - } else { - /* Conditional compact branch */ - TCGLabel *fs = gen_new_label(); - - tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs); - - gen_goto_tb(ctx, 1, ctx->btarget); - gen_set_label(fs); - - gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); - } - -out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */ -static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs, - int rt) -{ - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - /* load rs */ - gen_load_gpr(t0, rs); - - /* link */ - if (rt != 0) { - tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4); - } - - /* calculate btarget */ - tcg_gen_shli_tl(t0, t0, 1); - tcg_gen_movi_tl(t1, ctx->base.pc_next + 4); - gen_op_addr_add(ctx, btarget, t1, t0); - - /* branch completion */ - clear_branch_hflags(ctx); - ctx->base.is_jmp = DISAS_NORETURN; - - /* unconditional branch to register */ - tcg_gen_mov_tl(cpu_PC, btarget); - tcg_gen_lookup_and_goto_ptr(); - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -/* nanoMIPS Branches */ -static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc, - int rs, int rt, int32_t offset) -{ - int bcond_compute = 0; - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - /* Load needed operands and calculate btarget */ - switch (opc) { - /* compact branch */ - case OPC_BGEC: - case OPC_BLTC: - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - bcond_compute = 1; - ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); - break; - case OPC_BGEUC: - case OPC_BLTUC: - if (rs == 0 || rs == rt) { - /* OPC_BLEZALC, OPC_BGEZALC */ - /* OPC_BGTZALC, OPC_BLTZALC */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4); - } - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - bcond_compute = 1; - ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); - break; - case OPC_BC: - ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); - break; - case OPC_BEQZC: - if (rs != 0) { - /* OPC_BEQZC, OPC_BNEZC */ - gen_load_gpr(t0, rs); - bcond_compute = 1; - ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); - } else { - /* OPC_JIC, OPC_JIALC */ - TCGv tbase = tcg_temp_new(); - TCGv toffset = tcg_temp_new(); - - gen_load_gpr(tbase, rt); - tcg_gen_movi_tl(toffset, offset); - gen_op_addr_add(ctx, btarget, tbase, toffset); - tcg_temp_free(tbase); - tcg_temp_free(toffset); - } - break; - default: - MIPS_INVAL("Compact branch/jump"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - - if (bcond_compute == 0) { - /* Uncoditional compact branch */ - switch (opc) { - case OPC_BC: - gen_goto_tb(ctx, 0, ctx->btarget); - break; - default: - MIPS_INVAL("Compact branch/jump"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - } else { - /* Conditional compact branch */ - TCGLabel *fs = gen_new_label(); - - switch (opc) { - case OPC_BGEUC: - if (rs == 0 && rt != 0) { - /* OPC_BLEZALC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs); - } else if (rs != 0 && rt != 0 && rs == rt) { - /* OPC_BGEZALC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs); - } else { - /* OPC_BGEUC */ - tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs); - } - break; - case OPC_BLTUC: - if (rs == 0 && rt != 0) { - /* OPC_BGTZALC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs); - } else if (rs != 0 && rt != 0 && rs == rt) { - /* OPC_BLTZALC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs); - } else { - /* OPC_BLTUC */ - tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs); - } - break; - case OPC_BGEC: - if (rs == 0 && rt != 0) { - /* OPC_BLEZC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs); - } else if (rs != 0 && rt != 0 && rs == rt) { - /* OPC_BGEZC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs); - } else { - /* OPC_BGEC */ - tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs); - } - break; - case OPC_BLTC: - if (rs == 0 && rt != 0) { - /* OPC_BGTZC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs); - } else if (rs != 0 && rt != 0 && rs == rt) { - /* OPC_BLTZC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs); - } else { - /* OPC_BLTC */ - tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs); - } - break; - case OPC_BEQZC: - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs); - break; - default: - MIPS_INVAL("Compact conditional branch/jump"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - - /* branch completion */ - clear_branch_hflags(ctx); - ctx->base.is_jmp = DISAS_NORETURN; - - /* Generating branch here as compact branches don't have delay slot */ - gen_goto_tb(ctx, 1, ctx->btarget); - gen_set_label(fs); - - gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); - } - -out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} - - -/* nanoMIPS CP1 Branches */ -static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op, - int32_t ft, int32_t offset) -{ - target_ulong btarget; - TCGv_i64 t0 = tcg_temp_new_i64(); - - gen_load_fpr64(ctx, t0, ft); - tcg_gen_andi_i64(t0, t0, 1); - - btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); - - switch (op) { - case NM_BC1EQZC: - tcg_gen_xori_i64(t0, t0, 1); - ctx->hflags |= MIPS_HFLAG_BC; - break; - case NM_BC1NEZC: - /* t0 already set */ - ctx->hflags |= MIPS_HFLAG_BC; - break; - default: - MIPS_INVAL("cp1 cond branch"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - - tcg_gen_trunc_i64_tl(bcond, t0); - - ctx->btarget = btarget; - -out: - tcg_temp_free_i64(t0); -} - - -static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt) -{ - TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - - if ((extract32(ctx->opcode, 6, 1)) == 1) { - /* PP.LSXS instructions require shifting */ - switch (extract32(ctx->opcode, 7, 4)) { - case NM_SHXS: - check_nms(ctx); - /* fall through */ - case NM_LHXS: - case NM_LHUXS: - tcg_gen_shli_tl(t0, t0, 1); - break; - case NM_SWXS: - check_nms(ctx); - /* fall through */ - case NM_LWXS: - case NM_LWC1XS: - case NM_SWC1XS: - tcg_gen_shli_tl(t0, t0, 2); - break; - case NM_LDC1XS: - case NM_SDC1XS: - tcg_gen_shli_tl(t0, t0, 3); - break; - } - } - gen_op_addr_add(ctx, t0, t0, t1); - - switch (extract32(ctx->opcode, 7, 4)) { - case NM_LBX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_SB); - gen_store_gpr(t0, rd); - break; - case NM_LHX: - /*case NM_LHXS:*/ - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_TESW); - gen_store_gpr(t0, rd); - break; - case NM_LWX: - /*case NM_LWXS:*/ - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_TESL); - gen_store_gpr(t0, rd); - break; - case NM_LBUX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_UB); - gen_store_gpr(t0, rd); - break; - case NM_LHUX: - /*case NM_LHUXS:*/ - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_TEUW); - gen_store_gpr(t0, rd); - break; - case NM_SBX: - check_nms(ctx); - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, - MO_8); - break; - case NM_SHX: - /*case NM_SHXS:*/ - check_nms(ctx); - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, - MO_TEUW); - break; - case NM_SWX: - /*case NM_SWXS:*/ - check_nms(ctx); - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, - MO_TEUL); - break; - case NM_LWC1X: - /*case NM_LWC1XS:*/ - case NM_LDC1X: - /*case NM_LDC1XS:*/ - case NM_SWC1X: - /*case NM_SWC1XS:*/ - case NM_SDC1X: - /*case NM_SDC1XS:*/ - if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { - check_cp1_enabled(ctx); - switch (extract32(ctx->opcode, 7, 4)) { - case NM_LWC1X: - /*case NM_LWC1XS:*/ - gen_flt_ldst(ctx, OPC_LWC1, rd, t0); - break; - case NM_LDC1X: - /*case NM_LDC1XS:*/ - gen_flt_ldst(ctx, OPC_LDC1, rd, t0); - break; - case NM_SWC1X: - /*case NM_SWC1XS:*/ - gen_flt_ldst(ctx, OPC_SWC1, rd, t0); - break; - case NM_SDC1X: - /*case NM_SDC1XS:*/ - gen_flt_ldst(ctx, OPC_SDC1, rd, t0); - break; - } - } else { - generate_exception_err(ctx, EXCP_CpU, 1); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -static void gen_pool32f_nanomips_insn(DisasContext *ctx) -{ - int rt, rs, rd; - - rt = extract32(ctx->opcode, 21, 5); - rs = extract32(ctx->opcode, 16, 5); - rd = extract32(ctx->opcode, 11, 5); - - if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) { - generate_exception_end(ctx, EXCP_RI); - return; - } - check_cp1_enabled(ctx); - switch (extract32(ctx->opcode, 0, 3)) { - case NM_POOL32F_0: - switch (extract32(ctx->opcode, 3, 7)) { - case NM_RINT_S: - gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); - break; - case NM_RINT_D: - gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); - break; - case NM_CLASS_S: - gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); - break; - case NM_CLASS_D: - gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); - break; - case NM_ADD_S: - gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0); - break; - case NM_ADD_D: - gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0); - break; - case NM_SUB_S: - gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0); - break; - case NM_SUB_D: - gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0); - break; - case NM_MUL_S: - gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0); - break; - case NM_MUL_D: - gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0); - break; - case NM_DIV_S: - gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0); - break; - case NM_DIV_D: - gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0); - break; - case NM_SELEQZ_S: - gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); - break; - case NM_SELEQZ_D: - gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); - break; - case NM_SELNEZ_S: - gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); - break; - case NM_SELNEZ_D: - gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); - break; - case NM_SEL_S: - gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); - break; - case NM_SEL_D: - gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); - break; - case NM_MADDF_S: - gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0); - break; - case NM_MADDF_D: - gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0); - break; - case NM_MSUBF_S: - gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0); - break; - case NM_MSUBF_D: - gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_POOL32F_3: - switch (extract32(ctx->opcode, 3, 3)) { - case NM_MIN_FMT: - switch (extract32(ctx->opcode, 9, 1)) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0); - break; - } - break; - case NM_MAX_FMT: - switch (extract32(ctx->opcode, 9, 1)) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0); - break; - } - break; - case NM_MINA_FMT: - switch (extract32(ctx->opcode, 9, 1)) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0); - break; - } - break; - case NM_MAXA_FMT: - switch (extract32(ctx->opcode, 9, 1)) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0); - break; - } - break; - case NM_POOL32FXF: - switch (extract32(ctx->opcode, 6, 8)) { - case NM_CFC1: - gen_cp1(ctx, OPC_CFC1, rt, rs); - break; - case NM_CTC1: - gen_cp1(ctx, OPC_CTC1, rt, rs); - break; - case NM_MFC1: - gen_cp1(ctx, OPC_MFC1, rt, rs); - break; - case NM_MTC1: - gen_cp1(ctx, OPC_MTC1, rt, rs); - break; - case NM_MFHC1: - gen_cp1(ctx, OPC_MFHC1, rt, rs); - break; - case NM_MTHC1: - gen_cp1(ctx, OPC_MTHC1, rt, rs); - break; - case NM_CVT_S_PL: - gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0); - break; - case NM_CVT_S_PU: - gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0); - break; - default: - switch (extract32(ctx->opcode, 6, 9)) { - case NM_CVT_L_S: - gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0); - break; - case NM_CVT_L_D: - gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0); - break; - case NM_CVT_W_S: - gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0); - break; - case NM_CVT_W_D: - gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0); - break; - case NM_RSQRT_S: - gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0); - break; - case NM_RSQRT_D: - gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0); - break; - case NM_SQRT_S: - gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0); - break; - case NM_SQRT_D: - gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0); - break; - case NM_RECIP_S: - gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0); - break; - case NM_RECIP_D: - gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0); - break; - case NM_FLOOR_L_S: - gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0); - break; - case NM_FLOOR_L_D: - gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0); - break; - case NM_FLOOR_W_S: - gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0); - break; - case NM_FLOOR_W_D: - gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0); - break; - case NM_CEIL_L_S: - gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0); - break; - case NM_CEIL_L_D: - gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0); - break; - case NM_CEIL_W_S: - gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0); - break; - case NM_CEIL_W_D: - gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0); - break; - case NM_TRUNC_L_S: - gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0); - break; - case NM_TRUNC_L_D: - gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0); - break; - case NM_TRUNC_W_S: - gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0); - break; - case NM_TRUNC_W_D: - gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0); - break; - case NM_ROUND_L_S: - gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0); - break; - case NM_ROUND_L_D: - gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0); - break; - case NM_ROUND_W_S: - gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0); - break; - case NM_ROUND_W_D: - gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0); - break; - case NM_MOV_S: - gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0); - break; - case NM_MOV_D: - gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0); - break; - case NM_ABS_S: - gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0); - break; - case NM_ABS_D: - gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0); - break; - case NM_NEG_S: - gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0); - break; - case NM_NEG_D: - gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0); - break; - case NM_CVT_D_S: - gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0); - break; - case NM_CVT_D_W: - gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0); - break; - case NM_CVT_D_L: - gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0); - break; - case NM_CVT_S_D: - gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0); - break; - case NM_CVT_S_W: - gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0); - break; - case NM_CVT_S_L: - gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - } - break; - } - break; - case NM_POOL32F_5: - switch (extract32(ctx->opcode, 3, 3)) { - case NM_CMP_CONDN_S: - gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); - break; - case NM_CMP_CONDN_D: - gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc, - int rd, int rs, int rt) -{ - int ret = rd; - TCGv t0 = tcg_temp_new(); - TCGv v1_t = tcg_temp_new(); - TCGv v2_t = tcg_temp_new(); - - gen_load_gpr(v1_t, rs); - gen_load_gpr(v2_t, rt); - - switch (opc) { - case NM_CMP_EQ_PH: - check_dsp(ctx); - gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env); - break; - case NM_CMP_LT_PH: - check_dsp(ctx); - gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env); - break; - case NM_CMP_LE_PH: - check_dsp(ctx); - gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env); - break; - case NM_CMPU_EQ_QB: - check_dsp(ctx); - gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env); - break; - case NM_CMPU_LT_QB: - check_dsp(ctx); - gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env); - break; - case NM_CMPU_LE_QB: - check_dsp(ctx); - gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env); - break; - case NM_CMPGU_EQ_QB: - check_dsp(ctx); - gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGU_LT_QB: - check_dsp(ctx); - gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGU_LE_QB: - check_dsp(ctx); - gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGDU_EQ_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); - tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGDU_LT_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); - tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGDU_LE_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); - tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); - gen_store_gpr(v1_t, ret); - break; - case NM_PACKRL_PH: - check_dsp(ctx); - gen_helper_packrl_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_PICK_QB: - check_dsp(ctx); - gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_PICK_PH: - check_dsp(ctx); - gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_ADDQ_S_W: - check_dsp(ctx); - gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_SUBQ_S_W: - check_dsp(ctx); - gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_ADDSC: - check_dsp(ctx); - gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_ADDWC: - check_dsp(ctx); - gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_ADDQ_S_PH: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDQ_PH */ - gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDQ_S_PH */ - gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDQH_R_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDQH_PH */ - gen_helper_addqh_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDQH_R_PH */ - gen_helper_addqh_r_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDQH_R_W: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDQH_W */ - gen_helper_addqh_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDQH_R_W */ - gen_helper_addqh_r_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDU_S_QB: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDU_QB */ - gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDU_S_QB */ - gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDU_S_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDU_PH */ - gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDU_S_PH */ - gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDUH_R_QB: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDUH_QB */ - gen_helper_adduh_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDUH_R_QB */ - gen_helper_adduh_r_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SHRAV_R_PH: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SHRAV_PH */ - gen_helper_shra_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SHRAV_R_PH */ - gen_helper_shra_r_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SHRAV_R_QB: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SHRAV_QB */ - gen_helper_shra_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SHRAV_R_QB */ - gen_helper_shra_r_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBQ_S_PH: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBQ_PH */ - gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBQ_S_PH */ - gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBQH_R_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBQH_PH */ - gen_helper_subqh_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBQH_R_PH */ - gen_helper_subqh_r_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBQH_R_W: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBQH_W */ - gen_helper_subqh_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBQH_R_W */ - gen_helper_subqh_r_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBU_S_QB: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBU_QB */ - gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBU_S_QB */ - gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBU_S_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBU_PH */ - gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBU_S_PH */ - gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBUH_R_QB: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBUH_QB */ - gen_helper_subuh_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBUH_R_QB */ - gen_helper_subuh_r_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SHLLV_S_PH: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SHLLV_PH */ - gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SHLLV_S_PH */ - gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_PRECR_SRA_R_PH_W: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* PRECR_SRA_PH_W */ - { - TCGv_i32 sa_t = tcg_const_i32(rd); - gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t, - cpu_gpr[rt]); - gen_store_gpr(v1_t, rt); - tcg_temp_free_i32(sa_t); - } - break; - case 1: - /* PRECR_SRA_R_PH_W */ - { - TCGv_i32 sa_t = tcg_const_i32(rd); - gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t, - cpu_gpr[rt]); - gen_store_gpr(v1_t, rt); - tcg_temp_free_i32(sa_t); - } - break; - } - break; - case NM_MULEU_S_PH_QBL: - check_dsp(ctx); - gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULEU_S_PH_QBR: - check_dsp(ctx); - gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULQ_RS_PH: - check_dsp(ctx); - gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULQ_S_PH: - check_dsp_r2(ctx); - gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULQ_RS_W: - check_dsp_r2(ctx); - gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULQ_S_W: - check_dsp_r2(ctx); - gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_APPEND: - check_dsp_r2(ctx); - gen_load_gpr(t0, rs); - if (rd != 0) { - tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd); - } - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - break; - case NM_MODSUB: - check_dsp(ctx); - gen_helper_modsub(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_SHRAV_R_W: - check_dsp(ctx); - gen_helper_shra_r_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_SHRLV_PH: - check_dsp_r2(ctx); - gen_helper_shrl_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_SHRLV_QB: - check_dsp(ctx); - gen_helper_shrl_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_SHLLV_QB: - check_dsp(ctx); - gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_SHLLV_S_W: - check_dsp(ctx); - gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_SHILO: - check_dsp(ctx); - { - TCGv tv0 = tcg_temp_new(); - TCGv tv1 = tcg_temp_new(); - int16_t imm = extract32(ctx->opcode, 16, 7); - - tcg_gen_movi_tl(tv0, rd >> 3); - tcg_gen_movi_tl(tv1, imm); - gen_helper_shilo(tv0, tv1, cpu_env); - } - break; - case NM_MULEQ_S_W_PHL: - check_dsp(ctx); - gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULEQ_S_W_PHR: - check_dsp(ctx); - gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MUL_S_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* MUL_PH */ - gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* MUL_S_PH */ - gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_PRECR_QB_PH: - check_dsp_r2(ctx); - gen_helper_precr_qb_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_PRECRQ_QB_PH: - check_dsp(ctx); - gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_PRECRQ_PH_W: - check_dsp(ctx); - gen_helper_precrq_ph_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_PRECRQ_RS_PH_W: - check_dsp(ctx); - gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_PRECRQU_S_QB_PH: - check_dsp(ctx); - gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_SHRA_R_W: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd); - gen_helper_shra_r_w(v1_t, t0, v1_t); - gen_store_gpr(v1_t, rt); - break; - case NM_SHRA_R_PH: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 1); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SHRA_PH */ - gen_helper_shra_ph(v1_t, t0, v1_t); - gen_store_gpr(v1_t, rt); - break; - case 1: - /* SHRA_R_PH */ - gen_helper_shra_r_ph(v1_t, t0, v1_t); - gen_store_gpr(v1_t, rt); - break; - } - break; - case NM_SHLL_S_PH: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 1); - switch (extract32(ctx->opcode, 10, 2)) { - case 0: - /* SHLL_PH */ - gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env); - gen_store_gpr(v1_t, rt); - break; - case 2: - /* SHLL_S_PH */ - gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env); - gen_store_gpr(v1_t, rt); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_SHLL_S_W: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd); - gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env); - gen_store_gpr(v1_t, rt); - break; - case NM_REPL_PH: - check_dsp(ctx); - { - int16_t imm; - imm = sextract32(ctx->opcode, 11, 11); - imm = (int16_t)(imm << 6) >> 6; - if (rt != 0) { - tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm)); - } - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) -{ - uint16_t insn; - uint32_t op; - int rt, rs, rd; - int offset; - int imm; - - insn = cpu_lduw_code(env, ctx->base.pc_next + 2); - ctx->opcode = (ctx->opcode << 16) | insn; - - rt = extract32(ctx->opcode, 21, 5); - rs = extract32(ctx->opcode, 16, 5); - rd = extract32(ctx->opcode, 11, 5); - - op = extract32(ctx->opcode, 26, 6); - switch (op) { - case NM_P_ADDIU: - if (rt == 0) { - /* P.RI */ - switch (extract32(ctx->opcode, 19, 2)) { - case NM_SIGRIE: - default: - generate_exception_end(ctx, EXCP_RI); - break; - case NM_P_SYSCALL: - if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) { - generate_exception_end(ctx, EXCP_SYSCALL); - } else { - generate_exception_end(ctx, EXCP_RI); - } - break; - case NM_BREAK: - generate_exception_end(ctx, EXCP_BREAK); - break; - case NM_SDBBP: - if (is_uhi(extract32(ctx->opcode, 0, 19))) { - gen_helper_do_semihosting(cpu_env); - } else { - if (ctx->hflags & MIPS_HFLAG_SBRI) { - generate_exception_end(ctx, EXCP_RI); - } else { - generate_exception_end(ctx, EXCP_DBp); - } - } - break; - } - } else { - /* NM_ADDIU */ - imm = extract32(ctx->opcode, 0, 16); - if (rs != 0) { - tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm); - } else { - tcg_gen_movi_tl(cpu_gpr[rt], imm); - } - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - } - break; - case NM_ADDIUPC: - if (rt != 0) { - offset = sextract32(ctx->opcode, 0, 1) << 21 | - extract32(ctx->opcode, 1, 20) << 1; - target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset); - tcg_gen_movi_tl(cpu_gpr[rt], addr); - } - break; - case NM_POOL32A: - switch (ctx->opcode & 0x07) { - case NM_POOL32A0: - gen_pool32a0_nanomips_insn(env, ctx); - break; - case NM_POOL32A5: - { - int32_t op1 = extract32(ctx->opcode, 3, 7); - gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt); - } - break; - case NM_POOL32A7: - switch (extract32(ctx->opcode, 3, 3)) { - case NM_P_LSX: - gen_p_lsx(ctx, rd, rs, rt); - break; - case NM_LSA: - /* - * In nanoMIPS, the shift field directly encodes the shift - * amount, meaning that the supported shift values are in - * the range 0 to 3 (instead of 1 to 4 in MIPSR6). - */ - gen_lsa(ctx, OPC_LSA, rd, rs, rt, - extract32(ctx->opcode, 9, 2) - 1); - break; - case NM_EXTW: - gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5)); - break; - case NM_POOL32AXF: - gen_pool32axf_nanomips_insn(env, ctx); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P_GP_W: - switch (ctx->opcode & 0x03) { - case NM_ADDIUGP_W: - if (rt != 0) { - offset = extract32(ctx->opcode, 0, 21); - gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset); - } - break; - case NM_LWGP: - gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2); - break; - case NM_SWGP: - gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P48I: - { - insn = cpu_lduw_code(env, ctx->base.pc_next + 4); - target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16; - switch (extract32(ctx->opcode, 16, 5)) { - case NM_LI48: - check_nms(ctx); - if (rt != 0) { - tcg_gen_movi_tl(cpu_gpr[rt], addr_off); - } - break; - case NM_ADDIU48: - check_nms(ctx); - if (rt != 0) { - tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off); - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - } - break; - case NM_ADDIUGP48: - check_nms(ctx); - if (rt != 0) { - gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off); - } - break; - case NM_ADDIUPC48: - check_nms(ctx); - if (rt != 0) { - target_long addr = addr_add(ctx, ctx->base.pc_next + 6, - addr_off); - - tcg_gen_movi_tl(cpu_gpr[rt], addr); - } - break; - case NM_LWPC48: - check_nms(ctx); - if (rt != 0) { - TCGv t0; - t0 = tcg_temp_new(); - - target_long addr = addr_add(ctx, ctx->base.pc_next + 6, - addr_off); - - tcg_gen_movi_tl(t0, addr); - tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL); - tcg_temp_free(t0); - } - break; - case NM_SWPC48: - check_nms(ctx); - { - TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - - target_long addr = addr_add(ctx, ctx->base.pc_next + 6, - addr_off); - - tcg_gen_movi_tl(t0, addr); - gen_load_gpr(t1, rt); - - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - - tcg_temp_free(t0); - tcg_temp_free(t1); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - return 6; - } - case NM_P_U12: - switch (extract32(ctx->opcode, 12, 4)) { - case NM_ORI: - gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12)); - break; - case NM_XORI: - gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12)); - break; - case NM_ANDI: - gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12)); - break; - case NM_P_SR: - switch (extract32(ctx->opcode, 20, 1)) { - case NM_PP_SR: - switch (ctx->opcode & 3) { - case NM_SAVE: - gen_save(ctx, rt, extract32(ctx->opcode, 16, 4), - extract32(ctx->opcode, 2, 1), - extract32(ctx->opcode, 3, 9) << 3); - break; - case NM_RESTORE: - case NM_RESTORE_JRC: - gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4), - extract32(ctx->opcode, 2, 1), - extract32(ctx->opcode, 3, 9) << 3); - if ((ctx->opcode & 3) == NM_RESTORE_JRC) { - gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P_SR_F: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_SLTI: - gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12)); - break; - case NM_SLTIU: - gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12)); - break; - case NM_SEQI: - { - TCGv t0 = tcg_temp_new(); - - imm = extract32(ctx->opcode, 0, 12); - gen_load_gpr(t0, rs); - tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm); - gen_store_gpr(t0, rt); - - tcg_temp_free(t0); - } - break; - case NM_ADDIUNEG: - imm = (int16_t) extract32(ctx->opcode, 0, 12); - gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm); - break; - case NM_P_SHIFT: - { - int shift = extract32(ctx->opcode, 0, 5); - switch (extract32(ctx->opcode, 5, 4)) { - case NM_P_SLL: - if (rt == 0 && shift == 0) { - /* NOP */ - } else if (rt == 0 && shift == 3) { - /* EHB - treat as NOP */ - } else if (rt == 0 && shift == 5) { - /* PAUSE - treat as NOP */ - } else if (rt == 0 && shift == 6) { - /* SYNC */ - gen_sync(extract32(ctx->opcode, 16, 5)); - } else { - /* SLL */ - gen_shift_imm(ctx, OPC_SLL, rt, rs, - extract32(ctx->opcode, 0, 5)); - } - break; - case NM_SRL: - gen_shift_imm(ctx, OPC_SRL, rt, rs, - extract32(ctx->opcode, 0, 5)); - break; - case NM_SRA: - gen_shift_imm(ctx, OPC_SRA, rt, rs, - extract32(ctx->opcode, 0, 5)); - break; - case NM_ROTR: - gen_shift_imm(ctx, OPC_ROTR, rt, rs, - extract32(ctx->opcode, 0, 5)); - break; - } - } - break; - case NM_P_ROTX: - check_nms(ctx); - if (rt != 0) { - TCGv t0 = tcg_temp_new(); - TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5)); - TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4) - << 1); - TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1)); - - gen_load_gpr(t0, rs); - gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe); - tcg_temp_free(t0); - - tcg_temp_free_i32(shift); - tcg_temp_free_i32(shiftx); - tcg_temp_free_i32(stripe); - } - break; - case NM_P_INS: - switch (((ctx->opcode >> 10) & 2) | - (extract32(ctx->opcode, 5, 1))) { - case NM_INS: - check_nms(ctx); - gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5), - extract32(ctx->opcode, 6, 5)); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P_EXT: - switch (((ctx->opcode >> 10) & 2) | - (extract32(ctx->opcode, 5, 1))) { - case NM_EXT: - check_nms(ctx); - gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5), - extract32(ctx->opcode, 6, 5)); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_POOL32F: - gen_pool32f_nanomips_insn(ctx); - break; - case NM_POOL32S: - break; - case NM_P_LUI: - switch (extract32(ctx->opcode, 1, 1)) { - case NM_LUI: - if (rt != 0) { - tcg_gen_movi_tl(cpu_gpr[rt], - sextract32(ctx->opcode, 0, 1) << 31 | - extract32(ctx->opcode, 2, 10) << 21 | - extract32(ctx->opcode, 12, 9) << 12); - } - break; - case NM_ALUIPC: - if (rt != 0) { - offset = sextract32(ctx->opcode, 0, 1) << 31 | - extract32(ctx->opcode, 2, 10) << 21 | - extract32(ctx->opcode, 12, 9) << 12; - target_long addr; - addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset); - tcg_gen_movi_tl(cpu_gpr[rt], addr); - } - break; - } - break; - case NM_P_GP_BH: - { - uint32_t u = extract32(ctx->opcode, 0, 18); - - switch (extract32(ctx->opcode, 18, 3)) { - case NM_LBGP: - gen_ld(ctx, OPC_LB, rt, 28, u); - break; - case NM_SBGP: - gen_st(ctx, OPC_SB, rt, 28, u); - break; - case NM_LBUGP: - gen_ld(ctx, OPC_LBU, rt, 28, u); - break; - case NM_ADDIUGP_B: - if (rt != 0) { - gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u); - } - break; - case NM_P_GP_LH: - u &= ~1; - switch (ctx->opcode & 1) { - case NM_LHGP: - gen_ld(ctx, OPC_LH, rt, 28, u); - break; - case NM_LHUGP: - gen_ld(ctx, OPC_LHU, rt, 28, u); - break; - } - break; - case NM_P_GP_SH: - u &= ~1; - switch (ctx->opcode & 1) { - case NM_SHGP: - gen_st(ctx, OPC_SH, rt, 28, u); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P_GP_CP1: - u &= ~0x3; - switch (ctx->opcode & 0x3) { - case NM_LWC1GP: - gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u); - break; - case NM_LDC1GP: - gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u); - break; - case NM_SWC1GP: - gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u); - break; - case NM_SDC1GP: - gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u); - break; - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - } - break; - case NM_P_LS_U12: - { - uint32_t u = extract32(ctx->opcode, 0, 12); - - switch (extract32(ctx->opcode, 12, 4)) { - case NM_P_PREFU12: - if (rt == 31) { - /* SYNCI */ - /* - * Break the TB to be able to sync copied instructions - * immediately. - */ - ctx->base.is_jmp = DISAS_STOP; - } else { - /* PREF */ - /* Treat as NOP. */ - } - break; - case NM_LB: - gen_ld(ctx, OPC_LB, rt, rs, u); - break; - case NM_LH: - gen_ld(ctx, OPC_LH, rt, rs, u); - break; - case NM_LW: - gen_ld(ctx, OPC_LW, rt, rs, u); - break; - case NM_LBU: - gen_ld(ctx, OPC_LBU, rt, rs, u); - break; - case NM_LHU: - gen_ld(ctx, OPC_LHU, rt, rs, u); - break; - case NM_SB: - gen_st(ctx, OPC_SB, rt, rs, u); - break; - case NM_SH: - gen_st(ctx, OPC_SH, rt, rs, u); - break; - case NM_SW: - gen_st(ctx, OPC_SW, rt, rs, u); - break; - case NM_LWC1: - gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u); - break; - case NM_LDC1: - gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u); - break; - case NM_SWC1: - gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u); - break; - case NM_SDC1: - gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - } - break; - case NM_P_LS_S9: - { - int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) | - extract32(ctx->opcode, 0, 8); - - switch (extract32(ctx->opcode, 8, 3)) { - case NM_P_LS_S0: - switch (extract32(ctx->opcode, 11, 4)) { - case NM_LBS9: - gen_ld(ctx, OPC_LB, rt, rs, s); - break; - case NM_LHS9: - gen_ld(ctx, OPC_LH, rt, rs, s); - break; - case NM_LWS9: - gen_ld(ctx, OPC_LW, rt, rs, s); - break; - case NM_LBUS9: - gen_ld(ctx, OPC_LBU, rt, rs, s); - break; - case NM_LHUS9: - gen_ld(ctx, OPC_LHU, rt, rs, s); - break; - case NM_SBS9: - gen_st(ctx, OPC_SB, rt, rs, s); - break; - case NM_SHS9: - gen_st(ctx, OPC_SH, rt, rs, s); - break; - case NM_SWS9: - gen_st(ctx, OPC_SW, rt, rs, s); - break; - case NM_LWC1S9: - gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s); - break; - case NM_LDC1S9: - gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s); - break; - case NM_SWC1S9: - gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s); - break; - case NM_SDC1S9: - gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s); - break; - case NM_P_PREFS9: - if (rt == 31) { - /* SYNCI */ - /* - * Break the TB to be able to sync copied instructions - * immediately. - */ - ctx->base.is_jmp = DISAS_STOP; - } else { - /* PREF */ - /* Treat as NOP. */ - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P_LS_S1: - switch (extract32(ctx->opcode, 11, 4)) { - case NM_UALH: - case NM_UASH: - check_nms(ctx); - { - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - gen_base_offset_addr(ctx, t0, rs, s); - - switch (extract32(ctx->opcode, 11, 4)) { - case NM_UALH: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | - MO_UNALN); - gen_store_gpr(t0, rt); - break; - case NM_UASH: - gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | - MO_UNALN); - break; - } - tcg_temp_free(t0); - tcg_temp_free(t1); - } - break; - case NM_P_LL: - switch (ctx->opcode & 0x03) { - case NM_LL: - gen_ld(ctx, OPC_LL, rt, rs, s); - break; - case NM_LLWP: - check_xnp(ctx); - gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); - break; - } - break; - case NM_P_SC: - switch (ctx->opcode & 0x03) { - case NM_SC: - gen_st_cond(ctx, rt, rs, s, MO_TESL, false); - break; - case NM_SCWP: - check_xnp(ctx); - gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5), - false); - break; - } - break; - case NM_CACHE: - check_cp0_enabled(ctx); - if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { - gen_cache_operation(ctx, rt, rs, s); - } - break; - } - break; - case NM_P_LS_E0: - switch (extract32(ctx->opcode, 11, 4)) { - case NM_LBE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LBE, rt, rs, s); - break; - case NM_SBE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_st(ctx, OPC_SBE, rt, rs, s); - break; - case NM_LBUE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LBUE, rt, rs, s); - break; - case NM_P_PREFE: - if (rt == 31) { - /* case NM_SYNCIE */ - check_eva(ctx); - check_cp0_enabled(ctx); - /* - * Break the TB to be able to sync copied instructions - * immediately. - */ - ctx->base.is_jmp = DISAS_STOP; - } else { - /* case NM_PREFE */ - check_eva(ctx); - check_cp0_enabled(ctx); - /* Treat as NOP. */ - } - break; - case NM_LHE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LHE, rt, rs, s); - break; - case NM_SHE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_st(ctx, OPC_SHE, rt, rs, s); - break; - case NM_LHUE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LHUE, rt, rs, s); - break; - case NM_CACHEE: - check_nms_dl_il_sl_tl_l2c(ctx); - gen_cache_operation(ctx, rt, rs, s); - break; - case NM_LWE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LWE, rt, rs, s); - break; - case NM_SWE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_st(ctx, OPC_SWE, rt, rs, s); - break; - case NM_P_LLE: - switch (extract32(ctx->opcode, 2, 2)) { - case NM_LLE: - check_xnp(ctx); - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LLE, rt, rs, s); - break; - case NM_LLWPE: - check_xnp(ctx); - check_eva(ctx); - check_cp0_enabled(ctx); - gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P_SCE: - switch (extract32(ctx->opcode, 2, 2)) { - case NM_SCE: - check_xnp(ctx); - check_eva(ctx); - check_cp0_enabled(ctx); - gen_st_cond(ctx, rt, rs, s, MO_TESL, true); - break; - case NM_SCWPE: - check_xnp(ctx); - check_eva(ctx); - check_cp0_enabled(ctx); - gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5), - true); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - } - break; - case NM_P_LS_WM: - case NM_P_LS_UAWM: - check_nms(ctx); - { - int count = extract32(ctx->opcode, 12, 3); - int counter = 0; - - offset = sextract32(ctx->opcode, 15, 1) << 8 | - extract32(ctx->opcode, 0, 8); - TCGv va = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - MemOp memop = (extract32(ctx->opcode, 8, 3)) == - NM_P_LS_UAWM ? MO_UNALN : 0; - - count = (count == 0) ? 8 : count; - while (counter != count) { - int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10); - int this_offset = offset + (counter << 2); - - gen_base_offset_addr(ctx, va, rs, this_offset); - - switch (extract32(ctx->opcode, 11, 1)) { - case NM_LWM: - tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx, - memop | MO_TESL); - gen_store_gpr(t1, this_rt); - if ((this_rt == rs) && - (counter != (count - 1))) { - /* UNPREDICTABLE */ - } - break; - case NM_SWM: - this_rt = (rt == 0) ? 0 : this_rt; - gen_load_gpr(t1, this_rt); - tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx, - memop | MO_TEUL); - break; - } - counter++; - } - tcg_temp_free(va); - tcg_temp_free(t1); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - } - break; - case NM_MOVE_BALC: - check_nms(ctx); - { - TCGv t0 = tcg_temp_new(); - int32_t s = sextract32(ctx->opcode, 0, 1) << 21 | - extract32(ctx->opcode, 1, 20) << 1; - rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5; - rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 | - extract32(ctx->opcode, 21, 3)); - gen_load_gpr(t0, rt); - tcg_gen_mov_tl(cpu_gpr[rd], t0); - gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); - tcg_temp_free(t0); - } - break; - case NM_P_BAL: - { - int32_t s = sextract32(ctx->opcode, 0, 1) << 25 | - extract32(ctx->opcode, 1, 24) << 1; - - if ((extract32(ctx->opcode, 25, 1)) == 0) { - /* BC */ - gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s); - } else { - /* BALC */ - gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); - } - } - break; - case NM_P_J: - switch (extract32(ctx->opcode, 12, 4)) { - case NM_JALRC: - case NM_JALRC_HB: - gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0); - break; - case NM_P_BALRSC: - gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P_BR1: - { - int32_t s = sextract32(ctx->opcode, 0, 1) << 14 | - extract32(ctx->opcode, 1, 13) << 1; - switch (extract32(ctx->opcode, 14, 2)) { - case NM_BEQC: - check_nms(ctx); - gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s); - break; - case NM_P_BR3A: - s = sextract32(ctx->opcode, 0, 1) << 14 | - extract32(ctx->opcode, 1, 13) << 1; - check_cp1_enabled(ctx); - switch (extract32(ctx->opcode, 16, 5)) { - case NM_BC1EQZC: - gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s); - break; - case NM_BC1NEZC: - gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s); - break; - case NM_BPOSGE32C: - check_dsp_r3(ctx); - { - int32_t imm = extract32(ctx->opcode, 1, 13) | - extract32(ctx->opcode, 0, 1) << 13; - - gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2, - imm); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_BGEC: - if (rs == rt) { - gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s); - } else { - gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s); - } - break; - case NM_BGEUC: - if (rs == rt || rt == 0) { - gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s); - } else if (rs == 0) { - gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s); - } else { - gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s); - } - break; - } - } - break; - case NM_P_BR2: - { - int32_t s = sextract32(ctx->opcode, 0, 1) << 14 | - extract32(ctx->opcode, 1, 13) << 1; - switch (extract32(ctx->opcode, 14, 2)) { - case NM_BNEC: - check_nms(ctx); - gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s); - break; - case NM_BLTC: - if (rs != 0 && rt != 0 && rs == rt) { - /* NOP */ - ctx->hflags |= MIPS_HFLAG_FBNSLOT; - } else { - gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s); - } - break; - case NM_BLTUC: - if (rs == 0 || rs == rt) { - /* NOP */ - ctx->hflags |= MIPS_HFLAG_FBNSLOT; - } else { - gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - } - break; - case NM_P_BRI: - { - int32_t s = sextract32(ctx->opcode, 0, 1) << 11 | - extract32(ctx->opcode, 1, 10) << 1; - uint32_t u = extract32(ctx->opcode, 11, 7); - - gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3), - rt, u, s); - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - return 4; -} - -static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t op; - int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); - int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); - int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode)); - int offset; - int imm; - - /* make sure instructions are on a halfword boundary */ - if (ctx->base.pc_next & 0x1) { - TCGv tmp = tcg_const_tl(ctx->base.pc_next); - tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); - tcg_temp_free(tmp); - generate_exception_end(ctx, EXCP_AdEL); - return 2; - } - - op = extract32(ctx->opcode, 10, 6); - switch (op) { - case NM_P16_MV: - rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); - if (rt != 0) { - /* MOVE */ - rs = NANOMIPS_EXTRACT_RS5(ctx->opcode); - gen_arith(ctx, OPC_ADDU, rt, rs, 0); - } else { - /* P16.RI */ - switch (extract32(ctx->opcode, 3, 2)) { - case NM_P16_SYSCALL: - if (extract32(ctx->opcode, 2, 1) == 0) { - generate_exception_end(ctx, EXCP_SYSCALL); - } else { - generate_exception_end(ctx, EXCP_RI); - } - break; - case NM_BREAK16: - generate_exception_end(ctx, EXCP_BREAK); - break; - case NM_SDBBP16: - if (is_uhi(extract32(ctx->opcode, 0, 3))) { - gen_helper_do_semihosting(cpu_env); - } else { - if (ctx->hflags & MIPS_HFLAG_SBRI) { - generate_exception_end(ctx, EXCP_RI); - } else { - generate_exception_end(ctx, EXCP_DBp); - } - } - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - } - break; - case NM_P16_SHIFT: - { - int shift = extract32(ctx->opcode, 0, 3); - uint32_t opc = 0; - shift = (shift == 0) ? 8 : shift; - - switch (extract32(ctx->opcode, 3, 1)) { - case NM_SLL16: - opc = OPC_SLL; - break; - case NM_SRL16: - opc = OPC_SRL; - break; - } - gen_shift_imm(ctx, opc, rt, rs, shift); - } - break; - case NM_P16C: - switch (ctx->opcode & 1) { - case NM_POOL16C_0: - gen_pool16c_nanomips_insn(ctx); - break; - case NM_LWXS16: - gen_ldxs(ctx, rt, rs, rd); - break; - } - break; - case NM_P16_A1: - switch (extract32(ctx->opcode, 6, 1)) { - case NM_ADDIUR1SP: - imm = extract32(ctx->opcode, 0, 6) << 2; - gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P16_A2: - switch (extract32(ctx->opcode, 3, 1)) { - case NM_ADDIUR2: - imm = extract32(ctx->opcode, 0, 3) << 2; - gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm); - break; - case NM_P_ADDIURS5: - rt = extract32(ctx->opcode, 5, 5); - if (rt != 0) { - /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */ - imm = (sextract32(ctx->opcode, 4, 1) << 3) | - (extract32(ctx->opcode, 0, 3)); - gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm); - } - break; - } - break; - case NM_P16_ADDU: - switch (ctx->opcode & 0x1) { - case NM_ADDU16: - gen_arith(ctx, OPC_ADDU, rd, rs, rt); - break; - case NM_SUBU16: - gen_arith(ctx, OPC_SUBU, rd, rs, rt); - break; - } - break; - case NM_P16_4X4: - rt = (extract32(ctx->opcode, 9, 1) << 3) | - extract32(ctx->opcode, 5, 3); - rs = (extract32(ctx->opcode, 4, 1) << 3) | - extract32(ctx->opcode, 0, 3); - rt = decode_gpr_gpr4(rt); - rs = decode_gpr_gpr4(rs); - switch ((extract32(ctx->opcode, 7, 2) & 0x2) | - (extract32(ctx->opcode, 3, 1))) { - case NM_ADDU4X4: - check_nms(ctx); - gen_arith(ctx, OPC_ADDU, rt, rs, rt); - break; - case NM_MUL4X4: - check_nms(ctx); - gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_LI16: - { - int imm = extract32(ctx->opcode, 0, 7); - imm = (imm == 0x7f ? -1 : imm); - if (rt != 0) { - tcg_gen_movi_tl(cpu_gpr[rt], imm); - } - } - break; - case NM_ANDI16: - { - uint32_t u = extract32(ctx->opcode, 0, 4); - u = (u == 12) ? 0xff : - (u == 13) ? 0xffff : u; - gen_logic_imm(ctx, OPC_ANDI, rt, rs, u); - } - break; - case NM_P16_LB: - offset = extract32(ctx->opcode, 0, 2); - switch (extract32(ctx->opcode, 2, 2)) { - case NM_LB16: - gen_ld(ctx, OPC_LB, rt, rs, offset); - break; - case NM_SB16: - rt = decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RT3(ctx->opcode)); - gen_st(ctx, OPC_SB, rt, rs, offset); - break; - case NM_LBU16: - gen_ld(ctx, OPC_LBU, rt, rs, offset); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_P16_LH: - offset = extract32(ctx->opcode, 1, 2) << 1; - switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) { - case NM_LH16: - gen_ld(ctx, OPC_LH, rt, rs, offset); - break; - case NM_SH16: - rt = decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RT3(ctx->opcode)); - gen_st(ctx, OPC_SH, rt, rs, offset); - break; - case NM_LHU16: - gen_ld(ctx, OPC_LHU, rt, rs, offset); - break; - default: - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case NM_LW16: - offset = extract32(ctx->opcode, 0, 4) << 2; - gen_ld(ctx, OPC_LW, rt, rs, offset); - break; - case NM_LWSP16: - rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); - offset = extract32(ctx->opcode, 0, 5) << 2; - gen_ld(ctx, OPC_LW, rt, 29, offset); - break; - case NM_LW4X4: - check_nms(ctx); - rt = (extract32(ctx->opcode, 9, 1) << 3) | - extract32(ctx->opcode, 5, 3); - rs = (extract32(ctx->opcode, 4, 1) << 3) | - extract32(ctx->opcode, 0, 3); - offset = (extract32(ctx->opcode, 3, 1) << 3) | - (extract32(ctx->opcode, 8, 1) << 2); - rt = decode_gpr_gpr4(rt); - rs = decode_gpr_gpr4(rs); - gen_ld(ctx, OPC_LW, rt, rs, offset); - break; - case NM_SW4X4: - check_nms(ctx); - rt = (extract32(ctx->opcode, 9, 1) << 3) | - extract32(ctx->opcode, 5, 3); - rs = (extract32(ctx->opcode, 4, 1) << 3) | - extract32(ctx->opcode, 0, 3); - offset = (extract32(ctx->opcode, 3, 1) << 3) | - (extract32(ctx->opcode, 8, 1) << 2); - rt = decode_gpr_gpr4_zero(rt); - rs = decode_gpr_gpr4(rs); - gen_st(ctx, OPC_SW, rt, rs, offset); - break; - case NM_LWGP16: - offset = extract32(ctx->opcode, 0, 7) << 2; - gen_ld(ctx, OPC_LW, rt, 28, offset); - break; - case NM_SWSP16: - rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); - offset = extract32(ctx->opcode, 0, 5) << 2; - gen_st(ctx, OPC_SW, rt, 29, offset); - break; - case NM_SW16: - rt = decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RT3(ctx->opcode)); - rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); - offset = extract32(ctx->opcode, 0, 4) << 2; - gen_st(ctx, OPC_SW, rt, rs, offset); - break; - case NM_SWGP16: - rt = decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RT3(ctx->opcode)); - offset = extract32(ctx->opcode, 0, 7) << 2; - gen_st(ctx, OPC_SW, rt, 28, offset); - break; - case NM_BC16: - gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0, - (sextract32(ctx->opcode, 0, 1) << 10) | - (extract32(ctx->opcode, 1, 9) << 1)); - break; - case NM_BALC16: - gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0, - (sextract32(ctx->opcode, 0, 1) << 10) | - (extract32(ctx->opcode, 1, 9) << 1)); - break; - case NM_BEQZC16: - gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0, - (sextract32(ctx->opcode, 0, 1) << 7) | - (extract32(ctx->opcode, 1, 6) << 1)); - break; - case NM_BNEZC16: - gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0, - (sextract32(ctx->opcode, 0, 1) << 7) | - (extract32(ctx->opcode, 1, 6) << 1)); - break; - case NM_P16_BR: - switch (ctx->opcode & 0xf) { - case 0: - /* P16.JRC */ - switch (extract32(ctx->opcode, 4, 1)) { - case NM_JRC: - gen_compute_branch_nm(ctx, OPC_JR, 2, - extract32(ctx->opcode, 5, 5), 0, 0); - break; - case NM_JALRC16: - gen_compute_branch_nm(ctx, OPC_JALR, 2, - extract32(ctx->opcode, 5, 5), 31, 0); - break; - } - break; - default: - { - /* P16.BRI */ - uint32_t opc = extract32(ctx->opcode, 4, 3) < - extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE; - gen_compute_branch_nm(ctx, opc, 2, rs, rt, - extract32(ctx->opcode, 0, 4) << 1); - } - break; - } - break; - case NM_P16_SR: - { - int count = extract32(ctx->opcode, 0, 4); - int u = extract32(ctx->opcode, 4, 4) << 4; - - rt = 30 + extract32(ctx->opcode, 9, 1); - switch (extract32(ctx->opcode, 8, 1)) { - case NM_SAVE16: - gen_save(ctx, rt, count, 0, u); - break; - case NM_RESTORE_JRC16: - gen_restore(ctx, rt, count, 0, u); - gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); - break; - } - } - break; - case NM_MOVEP: - case NM_MOVEPREV: - check_nms(ctx); - { - static const int gpr2reg1[] = {4, 5, 6, 7}; - static const int gpr2reg2[] = {5, 6, 7, 8}; - int re; - int rd2 = extract32(ctx->opcode, 3, 1) << 1 | - extract32(ctx->opcode, 8, 1); - int r1 = gpr2reg1[rd2]; - int r2 = gpr2reg2[rd2]; - int r3 = extract32(ctx->opcode, 4, 1) << 3 | - extract32(ctx->opcode, 0, 3); - int r4 = extract32(ctx->opcode, 9, 1) << 3 | - extract32(ctx->opcode, 5, 3); - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - if (op == NM_MOVEP) { - rd = r1; - re = r2; - rs = decode_gpr_gpr4_zero(r3); - rt = decode_gpr_gpr4_zero(r4); - } else { - rd = decode_gpr_gpr4(r3); - re = decode_gpr_gpr4(r4); - rs = r1; - rt = r2; - } - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_mov_tl(cpu_gpr[rd], t0); - tcg_gen_mov_tl(cpu_gpr[re], t1); - tcg_temp_free(t0); - tcg_temp_free(t1); - } - break; - default: - return decode_nanomips_32_48_opc(env, ctx); - } - - return 2; -} - +#include "isa-nanomips_translate.c.inc" /* SmartMIPS extension to MIPS32 */ diff --git a/MAINTAINERS b/MAINTAINERS index 68bc160f41b..10e87d27eab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -244,6 +244,7 @@ K: ^Subject:.*(?i)mips MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.* +F: target/mips/isa-nanomips* Moxie TCG CPUs M: Anthony Green diff --git a/target/mips/isa-nanomips_translate.c.inc b/target/mips/isa-nanomips_translate.c.inc new file mode 100644 index 00000000000..d59a2bea9b6 --- /dev/null +++ b/target/mips/isa-nanomips_translate.c.inc @@ -0,0 +1,4839 @@ +/* + * MIPS emulation for QEMU - nanoMIPS translation routines + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* MAJOR, P16, and P32 pools opcodes */ +enum { + NM_P_ADDIU = 0x00, + NM_ADDIUPC = 0x01, + NM_MOVE_BALC = 0x02, + NM_P16_MV = 0x04, + NM_LW16 = 0x05, + NM_BC16 = 0x06, + NM_P16_SR = 0x07, + + NM_POOL32A = 0x08, + NM_P_BAL = 0x0a, + NM_P16_SHIFT = 0x0c, + NM_LWSP16 = 0x0d, + NM_BALC16 = 0x0e, + NM_P16_4X4 = 0x0f, + + NM_P_GP_W = 0x10, + NM_P_GP_BH = 0x11, + NM_P_J = 0x12, + NM_P16C = 0x14, + NM_LWGP16 = 0x15, + NM_P16_LB = 0x17, + + NM_P48I = 0x18, + NM_P16_A1 = 0x1c, + NM_LW4X4 = 0x1d, + NM_P16_LH = 0x1f, + + NM_P_U12 = 0x20, + NM_P_LS_U12 = 0x21, + NM_P_BR1 = 0x22, + NM_P16_A2 = 0x24, + NM_SW16 = 0x25, + NM_BEQZC16 = 0x26, + + NM_POOL32F = 0x28, + NM_P_LS_S9 = 0x29, + NM_P_BR2 = 0x2a, + + NM_P16_ADDU = 0x2c, + NM_SWSP16 = 0x2d, + NM_BNEZC16 = 0x2e, + NM_MOVEP = 0x2f, + + NM_POOL32S = 0x30, + NM_P_BRI = 0x32, + NM_LI16 = 0x34, + NM_SWGP16 = 0x35, + NM_P16_BR = 0x36, + + NM_P_LUI = 0x38, + NM_ANDI16 = 0x3c, + NM_SW4X4 = 0x3d, + NM_MOVEPREV = 0x3f, +}; + +/* POOL32A instruction pool */ +enum { + NM_POOL32A0 = 0x00, + NM_SPECIAL2 = 0x01, + NM_COP2_1 = 0x02, + NM_UDI = 0x03, + NM_POOL32A5 = 0x05, + NM_POOL32A7 = 0x07, +}; + +/* P.GP.W instruction pool */ +enum { + NM_ADDIUGP_W = 0x00, + NM_LWGP = 0x02, + NM_SWGP = 0x03, +}; + +/* P48I instruction pool */ +enum { + NM_LI48 = 0x00, + NM_ADDIU48 = 0x01, + NM_ADDIUGP48 = 0x02, + NM_ADDIUPC48 = 0x03, + NM_LWPC48 = 0x0b, + NM_SWPC48 = 0x0f, +}; + +/* P.U12 instruction pool */ +enum { + NM_ORI = 0x00, + NM_XORI = 0x01, + NM_ANDI = 0x02, + NM_P_SR = 0x03, + NM_SLTI = 0x04, + NM_SLTIU = 0x05, + NM_SEQI = 0x06, + NM_ADDIUNEG = 0x08, + NM_P_SHIFT = 0x0c, + NM_P_ROTX = 0x0d, + NM_P_INS = 0x0e, + NM_P_EXT = 0x0f, +}; + +/* POOL32F instruction pool */ +enum { + NM_POOL32F_0 = 0x00, + NM_POOL32F_3 = 0x03, + NM_POOL32F_5 = 0x05, +}; + +/* POOL32S instruction pool */ +enum { + NM_POOL32S_0 = 0x00, + NM_POOL32S_4 = 0x04, +}; + +/* P.LUI instruction pool */ +enum { + NM_LUI = 0x00, + NM_ALUIPC = 0x01, +}; + +/* P.GP.BH instruction pool */ +enum { + NM_LBGP = 0x00, + NM_SBGP = 0x01, + NM_LBUGP = 0x02, + NM_ADDIUGP_B = 0x03, + NM_P_GP_LH = 0x04, + NM_P_GP_SH = 0x05, + NM_P_GP_CP1 = 0x06, +}; + +/* P.LS.U12 instruction pool */ +enum { + NM_LB = 0x00, + NM_SB = 0x01, + NM_LBU = 0x02, + NM_P_PREFU12 = 0x03, + NM_LH = 0x04, + NM_SH = 0x05, + NM_LHU = 0x06, + NM_LWU = 0x07, + NM_LW = 0x08, + NM_SW = 0x09, + NM_LWC1 = 0x0a, + NM_SWC1 = 0x0b, + NM_LDC1 = 0x0e, + NM_SDC1 = 0x0f, +}; + +/* P.LS.S9 instruction pool */ +enum { + NM_P_LS_S0 = 0x00, + NM_P_LS_S1 = 0x01, + NM_P_LS_E0 = 0x02, + NM_P_LS_WM = 0x04, + NM_P_LS_UAWM = 0x05, +}; + +/* P.BAL instruction pool */ +enum { + NM_BC = 0x00, + NM_BALC = 0x01, +}; + +/* P.J instruction pool */ +enum { + NM_JALRC = 0x00, + NM_JALRC_HB = 0x01, + NM_P_BALRSC = 0x08, +}; + +/* P.BR1 instruction pool */ +enum { + NM_BEQC = 0x00, + NM_P_BR3A = 0x01, + NM_BGEC = 0x02, + NM_BGEUC = 0x03, +}; + +/* P.BR2 instruction pool */ +enum { + NM_BNEC = 0x00, + NM_BLTC = 0x02, + NM_BLTUC = 0x03, +}; + +/* P.BRI instruction pool */ +enum { + NM_BEQIC = 0x00, + NM_BBEQZC = 0x01, + NM_BGEIC = 0x02, + NM_BGEIUC = 0x03, + NM_BNEIC = 0x04, + NM_BBNEZC = 0x05, + NM_BLTIC = 0x06, + NM_BLTIUC = 0x07, +}; + +/* P16.SHIFT instruction pool */ +enum { + NM_SLL16 = 0x00, + NM_SRL16 = 0x01, +}; + +/* POOL16C instruction pool */ +enum { + NM_POOL16C_0 = 0x00, + NM_LWXS16 = 0x01, +}; + +/* P16.A1 instruction pool */ +enum { + NM_ADDIUR1SP = 0x01, +}; + +/* P16.A2 instruction pool */ +enum { + NM_ADDIUR2 = 0x00, + NM_P_ADDIURS5 = 0x01, +}; + +/* P16.ADDU instruction pool */ +enum { + NM_ADDU16 = 0x00, + NM_SUBU16 = 0x01, +}; + +/* P16.SR instruction pool */ +enum { + NM_SAVE16 = 0x00, + NM_RESTORE_JRC16 = 0x01, +}; + +/* P16.4X4 instruction pool */ +enum { + NM_ADDU4X4 = 0x00, + NM_MUL4X4 = 0x01, +}; + +/* P16.LB instruction pool */ +enum { + NM_LB16 = 0x00, + NM_SB16 = 0x01, + NM_LBU16 = 0x02, +}; + +/* P16.LH instruction pool */ +enum { + NM_LH16 = 0x00, + NM_SH16 = 0x01, + NM_LHU16 = 0x02, +}; + +/* P.RI instruction pool */ +enum { + NM_SIGRIE = 0x00, + NM_P_SYSCALL = 0x01, + NM_BREAK = 0x02, + NM_SDBBP = 0x03, +}; + +/* POOL32A0 instruction pool */ +enum { + NM_P_TRAP = 0x00, + NM_SEB = 0x01, + NM_SLLV = 0x02, + NM_MUL = 0x03, + NM_MFC0 = 0x06, + NM_MFHC0 = 0x07, + NM_SEH = 0x09, + NM_SRLV = 0x0a, + NM_MUH = 0x0b, + NM_MTC0 = 0x0e, + NM_MTHC0 = 0x0f, + NM_SRAV = 0x12, + NM_MULU = 0x13, + NM_ROTRV = 0x1a, + NM_MUHU = 0x1b, + NM_ADD = 0x22, + NM_DIV = 0x23, + NM_ADDU = 0x2a, + NM_MOD = 0x2b, + NM_SUB = 0x32, + NM_DIVU = 0x33, + NM_RDHWR = 0x38, + NM_SUBU = 0x3a, + NM_MODU = 0x3b, + NM_P_CMOVE = 0x42, + NM_FORK = 0x45, + NM_MFTR = 0x46, + NM_MFHTR = 0x47, + NM_AND = 0x4a, + NM_YIELD = 0x4d, + NM_MTTR = 0x4e, + NM_MTHTR = 0x4f, + NM_OR = 0x52, + NM_D_E_MT_VPE = 0x56, + NM_NOR = 0x5a, + NM_XOR = 0x62, + NM_SLT = 0x6a, + NM_P_SLTU = 0x72, + NM_SOV = 0x7a, +}; + +/* CRC32 instruction pool */ +enum { + NM_CRC32B = 0x00, + NM_CRC32H = 0x01, + NM_CRC32W = 0x02, + NM_CRC32CB = 0x04, + NM_CRC32CH = 0x05, + NM_CRC32CW = 0x06, +}; + +/* POOL32A5 instruction pool */ +enum { + NM_CMP_EQ_PH = 0x00, + NM_CMP_LT_PH = 0x08, + NM_CMP_LE_PH = 0x10, + NM_CMPGU_EQ_QB = 0x18, + NM_CMPGU_LT_QB = 0x20, + NM_CMPGU_LE_QB = 0x28, + NM_CMPGDU_EQ_QB = 0x30, + NM_CMPGDU_LT_QB = 0x38, + NM_CMPGDU_LE_QB = 0x40, + NM_CMPU_EQ_QB = 0x48, + NM_CMPU_LT_QB = 0x50, + NM_CMPU_LE_QB = 0x58, + NM_ADDQ_S_W = 0x60, + NM_SUBQ_S_W = 0x68, + NM_ADDSC = 0x70, + NM_ADDWC = 0x78, + + NM_ADDQ_S_PH = 0x01, + NM_ADDQH_R_PH = 0x09, + NM_ADDQH_R_W = 0x11, + NM_ADDU_S_QB = 0x19, + NM_ADDU_S_PH = 0x21, + NM_ADDUH_R_QB = 0x29, + NM_SHRAV_R_PH = 0x31, + NM_SHRAV_R_QB = 0x39, + NM_SUBQ_S_PH = 0x41, + NM_SUBQH_R_PH = 0x49, + NM_SUBQH_R_W = 0x51, + NM_SUBU_S_QB = 0x59, + NM_SUBU_S_PH = 0x61, + NM_SUBUH_R_QB = 0x69, + NM_SHLLV_S_PH = 0x71, + NM_PRECR_SRA_R_PH_W = 0x79, + + NM_MULEU_S_PH_QBL = 0x12, + NM_MULEU_S_PH_QBR = 0x1a, + NM_MULQ_RS_PH = 0x22, + NM_MULQ_S_PH = 0x2a, + NM_MULQ_RS_W = 0x32, + NM_MULQ_S_W = 0x3a, + NM_APPEND = 0x42, + NM_MODSUB = 0x52, + NM_SHRAV_R_W = 0x5a, + NM_SHRLV_PH = 0x62, + NM_SHRLV_QB = 0x6a, + NM_SHLLV_QB = 0x72, + NM_SHLLV_S_W = 0x7a, + + NM_SHILO = 0x03, + + NM_MULEQ_S_W_PHL = 0x04, + NM_MULEQ_S_W_PHR = 0x0c, + + NM_MUL_S_PH = 0x05, + NM_PRECR_QB_PH = 0x0d, + NM_PRECRQ_QB_PH = 0x15, + NM_PRECRQ_PH_W = 0x1d, + NM_PRECRQ_RS_PH_W = 0x25, + NM_PRECRQU_S_QB_PH = 0x2d, + NM_PACKRL_PH = 0x35, + NM_PICK_QB = 0x3d, + NM_PICK_PH = 0x45, + + NM_SHRA_R_W = 0x5e, + NM_SHRA_R_PH = 0x66, + NM_SHLL_S_PH = 0x76, + NM_SHLL_S_W = 0x7e, + + NM_REPL_PH = 0x07 +}; + +/* POOL32A7 instruction pool */ +enum { + NM_P_LSX = 0x00, + NM_LSA = 0x01, + NM_EXTW = 0x03, + NM_POOL32AXF = 0x07, +}; + +/* P.SR instruction pool */ +enum { + NM_PP_SR = 0x00, + NM_P_SR_F = 0x01, +}; + +/* P.SHIFT instruction pool */ +enum { + NM_P_SLL = 0x00, + NM_SRL = 0x02, + NM_SRA = 0x04, + NM_ROTR = 0x06, +}; + +/* P.ROTX instruction pool */ +enum { + NM_ROTX = 0x00, +}; + +/* P.INS instruction pool */ +enum { + NM_INS = 0x00, +}; + +/* P.EXT instruction pool */ +enum { + NM_EXT = 0x00, +}; + +/* POOL32F_0 (fmt) instruction pool */ +enum { + NM_RINT_S = 0x04, + NM_RINT_D = 0x44, + NM_ADD_S = 0x06, + NM_SELEQZ_S = 0x07, + NM_SELEQZ_D = 0x47, + NM_CLASS_S = 0x0c, + NM_CLASS_D = 0x4c, + NM_SUB_S = 0x0e, + NM_SELNEZ_S = 0x0f, + NM_SELNEZ_D = 0x4f, + NM_MUL_S = 0x16, + NM_SEL_S = 0x17, + NM_SEL_D = 0x57, + NM_DIV_S = 0x1e, + NM_ADD_D = 0x26, + NM_SUB_D = 0x2e, + NM_MUL_D = 0x36, + NM_MADDF_S = 0x37, + NM_MADDF_D = 0x77, + NM_DIV_D = 0x3e, + NM_MSUBF_S = 0x3f, + NM_MSUBF_D = 0x7f, +}; + +/* POOL32F_3 instruction pool */ +enum { + NM_MIN_FMT = 0x00, + NM_MAX_FMT = 0x01, + NM_MINA_FMT = 0x04, + NM_MAXA_FMT = 0x05, + NM_POOL32FXF = 0x07, +}; + +/* POOL32F_5 instruction pool */ +enum { + NM_CMP_CONDN_S = 0x00, + NM_CMP_CONDN_D = 0x02, +}; + +/* P.GP.LH instruction pool */ +enum { + NM_LHGP = 0x00, + NM_LHUGP = 0x01, +}; + +/* P.GP.SH instruction pool */ +enum { + NM_SHGP = 0x00, +}; + +/* P.GP.CP1 instruction pool */ +enum { + NM_LWC1GP = 0x00, + NM_SWC1GP = 0x01, + NM_LDC1GP = 0x02, + NM_SDC1GP = 0x03, +}; + +/* P.LS.S0 instruction pool */ +enum { + NM_LBS9 = 0x00, + NM_LHS9 = 0x04, + NM_LWS9 = 0x08, + NM_LDS9 = 0x0c, + + NM_SBS9 = 0x01, + NM_SHS9 = 0x05, + NM_SWS9 = 0x09, + NM_SDS9 = 0x0d, + + NM_LBUS9 = 0x02, + NM_LHUS9 = 0x06, + NM_LWC1S9 = 0x0a, + NM_LDC1S9 = 0x0e, + + NM_P_PREFS9 = 0x03, + NM_LWUS9 = 0x07, + NM_SWC1S9 = 0x0b, + NM_SDC1S9 = 0x0f, +}; + +/* P.LS.S1 instruction pool */ +enum { + NM_ASET_ACLR = 0x02, + NM_UALH = 0x04, + NM_UASH = 0x05, + NM_CACHE = 0x07, + NM_P_LL = 0x0a, + NM_P_SC = 0x0b, +}; + +/* P.LS.E0 instruction pool */ +enum { + NM_LBE = 0x00, + NM_SBE = 0x01, + NM_LBUE = 0x02, + NM_P_PREFE = 0x03, + NM_LHE = 0x04, + NM_SHE = 0x05, + NM_LHUE = 0x06, + NM_CACHEE = 0x07, + NM_LWE = 0x08, + NM_SWE = 0x09, + NM_P_LLE = 0x0a, + NM_P_SCE = 0x0b, +}; + +/* P.PREFE instruction pool */ +enum { + NM_SYNCIE = 0x00, + NM_PREFE = 0x01, +}; + +/* P.LLE instruction pool */ +enum { + NM_LLE = 0x00, + NM_LLWPE = 0x01, +}; + +/* P.SCE instruction pool */ +enum { + NM_SCE = 0x00, + NM_SCWPE = 0x01, +}; + +/* P.LS.WM instruction pool */ +enum { + NM_LWM = 0x00, + NM_SWM = 0x01, +}; + +/* P.LS.UAWM instruction pool */ +enum { + NM_UALWM = 0x00, + NM_UASWM = 0x01, +}; + +/* P.BR3A instruction pool */ +enum { + NM_BC1EQZC = 0x00, + NM_BC1NEZC = 0x01, + NM_BC2EQZC = 0x02, + NM_BC2NEZC = 0x03, + NM_BPOSGE32C = 0x04, +}; + +/* P16.RI instruction pool */ +enum { + NM_P16_SYSCALL = 0x01, + NM_BREAK16 = 0x02, + NM_SDBBP16 = 0x03, +}; + +/* POOL16C_0 instruction pool */ +enum { + NM_POOL16C_00 = 0x00, +}; + +/* P16.JRC instruction pool */ +enum { + NM_JRC = 0x00, + NM_JALRC16 = 0x01, +}; + +/* P.SYSCALL instruction pool */ +enum { + NM_SYSCALL = 0x00, + NM_HYPCALL = 0x01, +}; + +/* P.TRAP instruction pool */ +enum { + NM_TEQ = 0x00, + NM_TNE = 0x01, +}; + +/* P.CMOVE instruction pool */ +enum { + NM_MOVZ = 0x00, + NM_MOVN = 0x01, +}; + +/* POOL32Axf instruction pool */ +enum { + NM_POOL32AXF_1 = 0x01, + NM_POOL32AXF_2 = 0x02, + NM_POOL32AXF_4 = 0x04, + NM_POOL32AXF_5 = 0x05, + NM_POOL32AXF_7 = 0x07, +}; + +/* POOL32Axf_1 instruction pool */ +enum { + NM_POOL32AXF_1_0 = 0x00, + NM_POOL32AXF_1_1 = 0x01, + NM_POOL32AXF_1_3 = 0x03, + NM_POOL32AXF_1_4 = 0x04, + NM_POOL32AXF_1_5 = 0x05, + NM_POOL32AXF_1_7 = 0x07, +}; + +/* POOL32Axf_2 instruction pool */ +enum { + NM_POOL32AXF_2_0_7 = 0x00, + NM_POOL32AXF_2_8_15 = 0x01, + NM_POOL32AXF_2_16_23 = 0x02, + NM_POOL32AXF_2_24_31 = 0x03, +}; + +/* POOL32Axf_7 instruction pool */ +enum { + NM_SHRA_R_QB = 0x0, + NM_SHRL_PH = 0x1, + NM_REPL_QB = 0x2, +}; + +/* POOL32Axf_1_0 instruction pool */ +enum { + NM_MFHI = 0x0, + NM_MFLO = 0x1, + NM_MTHI = 0x2, + NM_MTLO = 0x3, +}; + +/* POOL32Axf_1_1 instruction pool */ +enum { + NM_MTHLIP = 0x0, + NM_SHILOV = 0x1, +}; + +/* POOL32Axf_1_3 instruction pool */ +enum { + NM_RDDSP = 0x0, + NM_WRDSP = 0x1, + NM_EXTP = 0x2, + NM_EXTPDP = 0x3, +}; + +/* POOL32Axf_1_4 instruction pool */ +enum { + NM_SHLL_QB = 0x0, + NM_SHRL_QB = 0x1, +}; + +/* POOL32Axf_1_5 instruction pool */ +enum { + NM_MAQ_S_W_PHR = 0x0, + NM_MAQ_S_W_PHL = 0x1, + NM_MAQ_SA_W_PHR = 0x2, + NM_MAQ_SA_W_PHL = 0x3, +}; + +/* POOL32Axf_1_7 instruction pool */ +enum { + NM_EXTR_W = 0x0, + NM_EXTR_R_W = 0x1, + NM_EXTR_RS_W = 0x2, + NM_EXTR_S_H = 0x3, +}; + +/* POOL32Axf_2_0_7 instruction pool */ +enum { + NM_DPA_W_PH = 0x0, + NM_DPAQ_S_W_PH = 0x1, + NM_DPS_W_PH = 0x2, + NM_DPSQ_S_W_PH = 0x3, + NM_BALIGN = 0x4, + NM_MADD = 0x5, + NM_MULT = 0x6, + NM_EXTRV_W = 0x7, +}; + +/* POOL32Axf_2_8_15 instruction pool */ +enum { + NM_DPAX_W_PH = 0x0, + NM_DPAQ_SA_L_W = 0x1, + NM_DPSX_W_PH = 0x2, + NM_DPSQ_SA_L_W = 0x3, + NM_MADDU = 0x5, + NM_MULTU = 0x6, + NM_EXTRV_R_W = 0x7, +}; + +/* POOL32Axf_2_16_23 instruction pool */ +enum { + NM_DPAU_H_QBL = 0x0, + NM_DPAQX_S_W_PH = 0x1, + NM_DPSU_H_QBL = 0x2, + NM_DPSQX_S_W_PH = 0x3, + NM_EXTPV = 0x4, + NM_MSUB = 0x5, + NM_MULSA_W_PH = 0x6, + NM_EXTRV_RS_W = 0x7, +}; + +/* POOL32Axf_2_24_31 instruction pool */ +enum { + NM_DPAU_H_QBR = 0x0, + NM_DPAQX_SA_W_PH = 0x1, + NM_DPSU_H_QBR = 0x2, + NM_DPSQX_SA_W_PH = 0x3, + NM_EXTPDPV = 0x4, + NM_MSUBU = 0x5, + NM_MULSAQ_S_W_PH = 0x6, + NM_EXTRV_S_H = 0x7, +}; + +/* POOL32Axf_{4, 5} instruction pool */ +enum { + NM_CLO = 0x25, + NM_CLZ = 0x2d, + + NM_TLBP = 0x01, + NM_TLBR = 0x09, + NM_TLBWI = 0x11, + NM_TLBWR = 0x19, + NM_TLBINV = 0x03, + NM_TLBINVF = 0x0b, + NM_DI = 0x23, + NM_EI = 0x2b, + NM_RDPGPR = 0x70, + NM_WRPGPR = 0x78, + NM_WAIT = 0x61, + NM_DERET = 0x71, + NM_ERETX = 0x79, + + /* nanoMIPS DSP instructions */ + NM_ABSQ_S_QB = 0x00, + NM_ABSQ_S_PH = 0x08, + NM_ABSQ_S_W = 0x10, + NM_PRECEQ_W_PHL = 0x28, + NM_PRECEQ_W_PHR = 0x30, + NM_PRECEQU_PH_QBL = 0x38, + NM_PRECEQU_PH_QBR = 0x48, + NM_PRECEU_PH_QBL = 0x58, + NM_PRECEU_PH_QBR = 0x68, + NM_PRECEQU_PH_QBLA = 0x39, + NM_PRECEQU_PH_QBRA = 0x49, + NM_PRECEU_PH_QBLA = 0x59, + NM_PRECEU_PH_QBRA = 0x69, + NM_REPLV_PH = 0x01, + NM_REPLV_QB = 0x09, + NM_BITREV = 0x18, + NM_INSV = 0x20, + NM_RADDU_W_QB = 0x78, + + NM_BITSWAP = 0x05, + NM_WSBH = 0x3d, +}; + +/* PP.SR instruction pool */ +enum { + NM_SAVE = 0x00, + NM_RESTORE = 0x02, + NM_RESTORE_JRC = 0x03, +}; + +/* P.SR.F instruction pool */ +enum { + NM_SAVEF = 0x00, + NM_RESTOREF = 0x01, +}; + +/* P16.SYSCALL instruction pool */ +enum { + NM_SYSCALL16 = 0x00, + NM_HYPCALL16 = 0x01, +}; + +/* POOL16C_00 instruction pool */ +enum { + NM_NOT16 = 0x00, + NM_XOR16 = 0x01, + NM_AND16 = 0x02, + NM_OR16 = 0x03, +}; + +/* PP.LSX and PP.LSXS instruction pool */ +enum { + NM_LBX = 0x00, + NM_LHX = 0x04, + NM_LWX = 0x08, + NM_LDX = 0x0c, + + NM_SBX = 0x01, + NM_SHX = 0x05, + NM_SWX = 0x09, + NM_SDX = 0x0d, + + NM_LBUX = 0x02, + NM_LHUX = 0x06, + NM_LWC1X = 0x0a, + NM_LDC1X = 0x0e, + + NM_LWUX = 0x07, + NM_SWC1X = 0x0b, + NM_SDC1X = 0x0f, + + NM_LHXS = 0x04, + NM_LWXS = 0x08, + NM_LDXS = 0x0c, + + NM_SHXS = 0x05, + NM_SWXS = 0x09, + NM_SDXS = 0x0d, + + NM_LHUXS = 0x06, + NM_LWC1XS = 0x0a, + NM_LDC1XS = 0x0e, + + NM_LWUXS = 0x07, + NM_SWC1XS = 0x0b, + NM_SDC1XS = 0x0f, +}; + +/* ERETx instruction pool */ +enum { + NM_ERET = 0x00, + NM_ERETNC = 0x01, +}; + +/* POOL32FxF_{0, 1} insturction pool */ +enum { + NM_CFC1 = 0x40, + NM_CTC1 = 0x60, + NM_MFC1 = 0x80, + NM_MTC1 = 0xa0, + NM_MFHC1 = 0xc0, + NM_MTHC1 = 0xe0, + + NM_CVT_S_PL = 0x84, + NM_CVT_S_PU = 0xa4, + + NM_CVT_L_S = 0x004, + NM_CVT_L_D = 0x104, + NM_CVT_W_S = 0x024, + NM_CVT_W_D = 0x124, + + NM_RSQRT_S = 0x008, + NM_RSQRT_D = 0x108, + + NM_SQRT_S = 0x028, + NM_SQRT_D = 0x128, + + NM_RECIP_S = 0x048, + NM_RECIP_D = 0x148, + + NM_FLOOR_L_S = 0x00c, + NM_FLOOR_L_D = 0x10c, + + NM_FLOOR_W_S = 0x02c, + NM_FLOOR_W_D = 0x12c, + + NM_CEIL_L_S = 0x04c, + NM_CEIL_L_D = 0x14c, + NM_CEIL_W_S = 0x06c, + NM_CEIL_W_D = 0x16c, + NM_TRUNC_L_S = 0x08c, + NM_TRUNC_L_D = 0x18c, + NM_TRUNC_W_S = 0x0ac, + NM_TRUNC_W_D = 0x1ac, + NM_ROUND_L_S = 0x0cc, + NM_ROUND_L_D = 0x1cc, + NM_ROUND_W_S = 0x0ec, + NM_ROUND_W_D = 0x1ec, + + NM_MOV_S = 0x01, + NM_MOV_D = 0x81, + NM_ABS_S = 0x0d, + NM_ABS_D = 0x8d, + NM_NEG_S = 0x2d, + NM_NEG_D = 0xad, + NM_CVT_D_S = 0x04d, + NM_CVT_D_W = 0x0cd, + NM_CVT_D_L = 0x14d, + NM_CVT_S_D = 0x06d, + NM_CVT_S_W = 0x0ed, + NM_CVT_S_L = 0x16d, +}; + +/* P.LL instruction pool */ +enum { + NM_LL = 0x00, + NM_LLWP = 0x01, +}; + +/* P.SC instruction pool */ +enum { + NM_SC = 0x00, + NM_SCWP = 0x01, +}; + +/* P.DVP instruction pool */ +enum { + NM_DVP = 0x00, + NM_EVP = 0x01, +}; + + +/* + * + * nanoMIPS decoding engine + * + */ + + +/* extraction utilities */ + +#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7) +#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7) +#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7) +#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f) +#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f) + +/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */ +static inline int decode_gpr_gpr3(int r) +{ + static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 }; + + return map[r & 0x7]; +} + +/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */ +static inline int decode_gpr_gpr3_src_store(int r) +{ + static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 }; + + return map[r & 0x7]; +} + +/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */ +static inline int decode_gpr_gpr4(int r) +{ + static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23 }; + + return map[r & 0xf]; +} + +/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */ +static inline int decode_gpr_gpr4_zero(int r) +{ + static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23 }; + + return map[r & 0xf]; +} + + +static void gen_adjust_sp(DisasContext *ctx, int u) +{ + gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u); +} + +static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count, + uint8_t gp, uint16_t u) +{ + int counter = 0; + TCGv va = tcg_temp_new(); + TCGv t0 = tcg_temp_new(); + + while (counter != count) { + bool use_gp = gp && (counter == count - 1); + int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f); + int this_offset = -((counter + 1) << 2); + gen_base_offset_addr(ctx, va, 29, this_offset); + gen_load_gpr(t0, this_rt); + tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx, + (MO_TEUL | ctx->default_tcg_memop_mask)); + counter++; + } + + /* adjust stack pointer */ + gen_adjust_sp(ctx, -u); + + tcg_temp_free(t0); + tcg_temp_free(va); +} + +static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count, + uint8_t gp, uint16_t u) +{ + int counter = 0; + TCGv va = tcg_temp_new(); + TCGv t0 = tcg_temp_new(); + + while (counter != count) { + bool use_gp = gp && (counter == count - 1); + int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f); + int this_offset = u - ((counter + 1) << 2); + gen_base_offset_addr(ctx, va, 29, this_offset); + tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + tcg_gen_ext32s_tl(t0, t0); + gen_store_gpr(t0, this_rt); + counter++; + } + + /* adjust stack pointer */ + gen_adjust_sp(ctx, u); + + tcg_temp_free(t0); + tcg_temp_free(va); +} + +static void gen_pool16c_nanomips_insn(DisasContext *ctx) +{ + int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); + int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); + + switch (extract32(ctx->opcode, 2, 2)) { + case NM_NOT16: + gen_logic(ctx, OPC_NOR, rt, rs, 0); + break; + case NM_AND16: + gen_logic(ctx, OPC_AND, rt, rt, rs); + break; + case NM_XOR16: + gen_logic(ctx, OPC_XOR, rt, rt, rs); + break; + case NM_OR16: + gen_logic(ctx, OPC_OR, rt, rt, rs); + break; + } +} + +static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) +{ + int rt = extract32(ctx->opcode, 21, 5); + int rs = extract32(ctx->opcode, 16, 5); + int rd = extract32(ctx->opcode, 11, 5); + + switch (extract32(ctx->opcode, 3, 7)) { + case NM_P_TRAP: + switch (extract32(ctx->opcode, 10, 1)) { + case NM_TEQ: + check_nms(ctx); + gen_trap(ctx, OPC_TEQ, rs, rt, -1); + break; + case NM_TNE: + check_nms(ctx); + gen_trap(ctx, OPC_TNE, rs, rt, -1); + break; + } + break; + case NM_RDHWR: + check_nms(ctx); + gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); + break; + case NM_SEB: + check_nms(ctx); + gen_bshfl(ctx, OPC_SEB, rs, rt); + break; + case NM_SEH: + gen_bshfl(ctx, OPC_SEH, rs, rt); + break; + case NM_SLLV: + gen_shift(ctx, OPC_SLLV, rd, rt, rs); + break; + case NM_SRLV: + gen_shift(ctx, OPC_SRLV, rd, rt, rs); + break; + case NM_SRAV: + gen_shift(ctx, OPC_SRAV, rd, rt, rs); + break; + case NM_ROTRV: + gen_shift(ctx, OPC_ROTRV, rd, rt, rs); + break; + case NM_ADD: + gen_arith(ctx, OPC_ADD, rd, rs, rt); + break; + case NM_ADDU: + gen_arith(ctx, OPC_ADDU, rd, rs, rt); + break; + case NM_SUB: + check_nms(ctx); + gen_arith(ctx, OPC_SUB, rd, rs, rt); + break; + case NM_SUBU: + gen_arith(ctx, OPC_SUBU, rd, rs, rt); + break; + case NM_P_CMOVE: + switch (extract32(ctx->opcode, 10, 1)) { + case NM_MOVZ: + gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); + break; + case NM_MOVN: + gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); + break; + } + break; + case NM_AND: + gen_logic(ctx, OPC_AND, rd, rs, rt); + break; + case NM_OR: + gen_logic(ctx, OPC_OR, rd, rs, rt); + break; + case NM_NOR: + gen_logic(ctx, OPC_NOR, rd, rs, rt); + break; + case NM_XOR: + gen_logic(ctx, OPC_XOR, rd, rs, rt); + break; + case NM_SLT: + gen_slt(ctx, OPC_SLT, rd, rs, rt); + break; + case NM_P_SLTU: + if (rd == 0) { + /* P_DVP */ +#ifndef CONFIG_USER_ONLY + TCGv t0 = tcg_temp_new(); + switch (extract32(ctx->opcode, 10, 1)) { + case NM_DVP: + if (ctx->vp) { + check_cp0_enabled(ctx); + gen_helper_dvp(t0, cpu_env); + gen_store_gpr(t0, rt); + } + break; + case NM_EVP: + if (ctx->vp) { + check_cp0_enabled(ctx); + gen_helper_evp(t0, cpu_env); + gen_store_gpr(t0, rt); + } + break; + } + tcg_temp_free(t0); +#endif + } else { + gen_slt(ctx, OPC_SLTU, rd, rs, rt); + } + break; + case NM_SOV: + { + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + + gen_load_gpr(t1, rs); + gen_load_gpr(t2, rt); + tcg_gen_add_tl(t0, t1, t2); + tcg_gen_ext32s_tl(t0, t0); + tcg_gen_xor_tl(t1, t1, t2); + tcg_gen_xor_tl(t2, t0, t2); + tcg_gen_andc_tl(t1, t2, t1); + + /* operands of same sign, result different sign */ + tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0); + gen_store_gpr(t0, rd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + } + break; + case NM_MUL: + gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); + break; + case NM_MUH: + gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); + break; + case NM_MULU: + gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); + break; + case NM_MUHU: + gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); + break; + case NM_DIV: + gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); + break; + case NM_MOD: + gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); + break; + case NM_DIVU: + gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); + break; + case NM_MODU: + gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); + break; +#ifndef CONFIG_USER_ONLY + case NM_MFC0: + check_cp0_enabled(ctx); + if (rt == 0) { + /* Treat as NOP. */ + break; + } + gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3)); + break; + case NM_MTC0: + check_cp0_enabled(ctx); + { + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3)); + tcg_temp_free(t0); + } + break; + case NM_D_E_MT_VPE: + { + uint8_t sc = extract32(ctx->opcode, 10, 1); + TCGv t0 = tcg_temp_new(); + + switch (sc) { + case 0: + if (rs == 1) { + /* DMT */ + check_cp0_mt(ctx); + gen_helper_dmt(t0); + gen_store_gpr(t0, rt); + } else if (rs == 0) { + /* DVPE */ + check_cp0_mt(ctx); + gen_helper_dvpe(t0, cpu_env); + gen_store_gpr(t0, rt); + } else { + generate_exception_end(ctx, EXCP_RI); + } + break; + case 1: + if (rs == 1) { + /* EMT */ + check_cp0_mt(ctx); + gen_helper_emt(t0); + gen_store_gpr(t0, rt); + } else if (rs == 0) { + /* EVPE */ + check_cp0_mt(ctx); + gen_helper_evpe(t0, cpu_env); + gen_store_gpr(t0, rt); + } else { + generate_exception_end(ctx, EXCP_RI); + } + break; + } + + tcg_temp_free(t0); + } + break; + case NM_FORK: + check_mt(ctx); + { + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + gen_helper_fork(t0, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + case NM_MFTR: + case NM_MFHTR: + check_cp0_enabled(ctx); + if (rd == 0) { + /* Treat as NOP. */ + return; + } + gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), + extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1)); + break; + case NM_MTTR: + case NM_MTHTR: + check_cp0_enabled(ctx); + gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), + extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1)); + break; + case NM_YIELD: + check_mt(ctx); + { + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_helper_yield(t0, cpu_env, t0); + gen_store_gpr(t0, rt); + tcg_temp_free(t0); + } + break; +#endif + default: + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* dsp */ +static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc, + int ret, int v1, int v2) +{ + TCGv_i32 t0; + TCGv v0_t; + TCGv v1_t; + + t0 = tcg_temp_new_i32(); + + v0_t = tcg_temp_new(); + v1_t = tcg_temp_new(); + + tcg_gen_movi_i32(t0, v2 >> 3); + + gen_load_gpr(v0_t, ret); + gen_load_gpr(v1_t, v1); + + switch (opc) { + case NM_MAQ_S_W_PHR: + check_dsp(ctx); + gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env); + break; + case NM_MAQ_S_W_PHL: + check_dsp(ctx); + gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env); + break; + case NM_MAQ_SA_W_PHR: + check_dsp(ctx); + gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env); + break; + case NM_MAQ_SA_W_PHL: + check_dsp(ctx); + gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(t0); + + tcg_temp_free(v0_t); + tcg_temp_free(v1_t); +} + + +static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc, + int ret, int v1, int v2) +{ + int16_t imm; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv v0_t = tcg_temp_new(); + + gen_load_gpr(v0_t, v1); + + switch (opc) { + case NM_POOL32AXF_1_0: + check_dsp(ctx); + switch (extract32(ctx->opcode, 12, 2)) { + case NM_MFHI: + gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret); + break; + case NM_MFLO: + gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret); + break; + case NM_MTHI: + gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1); + break; + case NM_MTLO: + gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1); + break; + } + break; + case NM_POOL32AXF_1_1: + check_dsp(ctx); + switch (extract32(ctx->opcode, 12, 2)) { + case NM_MTHLIP: + tcg_gen_movi_tl(t0, v2); + gen_helper_mthlip(t0, v0_t, cpu_env); + break; + case NM_SHILOV: + tcg_gen_movi_tl(t0, v2 >> 3); + gen_helper_shilo(t0, v0_t, cpu_env); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_POOL32AXF_1_3: + check_dsp(ctx); + imm = extract32(ctx->opcode, 14, 7); + switch (extract32(ctx->opcode, 12, 2)) { + case NM_RDDSP: + tcg_gen_movi_tl(t0, imm); + gen_helper_rddsp(t0, t0, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_WRDSP: + gen_load_gpr(t0, ret); + tcg_gen_movi_tl(t1, imm); + gen_helper_wrdsp(t0, t1, cpu_env); + break; + case NM_EXTP: + tcg_gen_movi_tl(t0, v2 >> 3); + tcg_gen_movi_tl(t1, v1); + gen_helper_extp(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_EXTPDP: + tcg_gen_movi_tl(t0, v2 >> 3); + tcg_gen_movi_tl(t1, v1); + gen_helper_extpdp(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + case NM_POOL32AXF_1_4: + check_dsp(ctx); + tcg_gen_movi_tl(t0, v2 >> 2); + switch (extract32(ctx->opcode, 12, 1)) { + case NM_SHLL_QB: + gen_helper_shll_qb(t0, t0, v0_t, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_SHRL_QB: + gen_helper_shrl_qb(t0, t0, v0_t); + gen_store_gpr(t0, ret); + break; + } + break; + case NM_POOL32AXF_1_5: + opc = extract32(ctx->opcode, 12, 2); + gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2); + break; + case NM_POOL32AXF_1_7: + check_dsp(ctx); + tcg_gen_movi_tl(t0, v2 >> 3); + tcg_gen_movi_tl(t1, v1); + switch (extract32(ctx->opcode, 12, 2)) { + case NM_EXTR_W: + gen_helper_extr_w(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_EXTR_R_W: + gen_helper_extr_r_w(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_EXTR_RS_W: + gen_helper_extr_rs_w(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_EXTR_S_H: + gen_helper_extr_s_h(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(v0_t); +} + +static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc, + TCGv v0, TCGv v1, int rd) +{ + TCGv_i32 t0; + + t0 = tcg_temp_new_i32(); + + tcg_gen_movi_i32(t0, rd >> 3); + + switch (opc) { + case NM_POOL32AXF_2_0_7: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpa_w_ph(t0, v1, v0, cpu_env); + break; + case NM_DPAQ_S_W_PH: + check_dsp(ctx); + gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env); + break; + case NM_DPS_W_PH: + check_dsp_r2(ctx); + gen_helper_dps_w_ph(t0, v1, v0, cpu_env); + break; + case NM_DPSQ_S_W_PH: + check_dsp(ctx); + gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_POOL32AXF_2_8_15: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAX_W_PH: + check_dsp_r2(ctx); + gen_helper_dpax_w_ph(t0, v0, v1, cpu_env); + break; + case NM_DPAQ_SA_L_W: + check_dsp(ctx); + gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env); + break; + case NM_DPSX_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env); + break; + case NM_DPSQ_SA_L_W: + check_dsp(ctx); + gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_POOL32AXF_2_16_23: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAU_H_QBL: + check_dsp(ctx); + gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env); + break; + case NM_DPAQX_S_W_PH: + check_dsp_r2(ctx); + gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env); + break; + case NM_DPSU_H_QBL: + check_dsp(ctx); + gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env); + break; + case NM_DPSQX_S_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env); + break; + case NM_MULSA_W_PH: + check_dsp_r2(ctx); + gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_POOL32AXF_2_24_31: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAU_H_QBR: + check_dsp(ctx); + gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env); + break; + case NM_DPAQX_SA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env); + break; + case NM_DPSU_H_QBR: + check_dsp(ctx); + gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env); + break; + case NM_DPSQX_SA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env); + break; + case NM_MULSAQ_S_W_PH: + check_dsp(ctx); + gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(t0); +} + +static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc, + int rt, int rs, int rd) +{ + int ret = rt; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv v0_t = tcg_temp_new(); + TCGv v1_t = tcg_temp_new(); + + gen_load_gpr(v0_t, rt); + gen_load_gpr(v1_t, rs); + + switch (opc) { + case NM_POOL32AXF_2_0_7: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPA_W_PH: + case NM_DPAQ_S_W_PH: + case NM_DPS_W_PH: + case NM_DPSQ_S_W_PH: + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); + break; + case NM_BALIGN: + check_dsp_r2(ctx); + if (rt != 0) { + gen_load_gpr(t0, rs); + rd &= 3; + if (rd != 0 && rd != 2) { + tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_shri_tl(t0, t0, 8 * (4 - rd)); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + } + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + } + break; + case NM_MADD: + check_dsp(ctx); + { + int acc = extract32(ctx->opcode, 14, 2); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + tcg_gen_ext_tl_i64(t2, t0); + tcg_gen_ext_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_add_i64(t2, t2, t3); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + tcg_temp_free_i64(t2); + } + break; + case NM_MULT: + check_dsp(ctx); + { + int acc = extract32(ctx->opcode, 14, 2); + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_muls2_i32(t2, t3, t2, t3); + tcg_gen_ext_i32_tl(cpu_LO[acc], t2); + tcg_gen_ext_i32_tl(cpu_HI[acc], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case NM_EXTRV_W: + check_dsp(ctx); + gen_load_gpr(v1_t, rs); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extr_w(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + case NM_POOL32AXF_2_8_15: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAX_W_PH: + case NM_DPAQ_SA_L_W: + case NM_DPSX_W_PH: + case NM_DPSQ_SA_L_W: + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); + break; + case NM_MADDU: + check_dsp(ctx); + { + int acc = extract32(ctx->opcode, 14, 2); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_extu_tl_i64(t2, t0); + tcg_gen_extu_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_add_i64(t2, t2, t3); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + tcg_temp_free_i64(t2); + } + break; + case NM_MULTU: + check_dsp(ctx); + { + int acc = extract32(ctx->opcode, 14, 2); + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_mulu2_i32(t2, t3, t2, t3); + tcg_gen_ext_i32_tl(cpu_LO[acc], t2); + tcg_gen_ext_i32_tl(cpu_HI[acc], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case NM_EXTRV_R_W: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extr_r_w(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_POOL32AXF_2_16_23: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAU_H_QBL: + case NM_DPAQX_S_W_PH: + case NM_DPSU_H_QBL: + case NM_DPSQX_S_W_PH: + case NM_MULSA_W_PH: + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); + break; + case NM_EXTPV: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extp(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_MSUB: + check_dsp(ctx); + { + int acc = extract32(ctx->opcode, 14, 2); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_ext_tl_i64(t2, t0); + tcg_gen_ext_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_sub_i64(t2, t3, t2); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + tcg_temp_free_i64(t2); + } + break; + case NM_EXTRV_RS_W: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + case NM_POOL32AXF_2_24_31: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAU_H_QBR: + case NM_DPAQX_SA_W_PH: + case NM_DPSU_H_QBR: + case NM_DPSQX_SA_W_PH: + case NM_MULSAQ_S_W_PH: + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); + break; + case NM_EXTPDPV: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extpdp(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_MSUBU: + check_dsp(ctx); + { + int acc = extract32(ctx->opcode, 14, 2); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_extu_tl_i64(t2, t0); + tcg_gen_extu_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_sub_i64(t2, t3, t2); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + tcg_temp_free_i64(t2); + } + break; + case NM_EXTRV_S_H: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extr_s_h(t0, t0, v0_t, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free(t0); + tcg_temp_free(t1); + + tcg_temp_free(v0_t); + tcg_temp_free(v1_t); +} + +static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc, + int rt, int rs) +{ + int ret = rt; + TCGv t0 = tcg_temp_new(); + TCGv v0_t = tcg_temp_new(); + + gen_load_gpr(v0_t, rs); + + switch (opc) { + case NM_ABSQ_S_QB: + check_dsp_r2(ctx); + gen_helper_absq_s_qb(v0_t, v0_t, cpu_env); + gen_store_gpr(v0_t, ret); + break; + case NM_ABSQ_S_PH: + check_dsp(ctx); + gen_helper_absq_s_ph(v0_t, v0_t, cpu_env); + gen_store_gpr(v0_t, ret); + break; + case NM_ABSQ_S_W: + check_dsp(ctx); + gen_helper_absq_s_w(v0_t, v0_t, cpu_env); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQ_W_PHL: + check_dsp(ctx); + tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000); + tcg_gen_ext32s_tl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQ_W_PHR: + check_dsp(ctx); + tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF); + tcg_gen_shli_tl(v0_t, v0_t, 16); + tcg_gen_ext32s_tl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQU_PH_QBL: + check_dsp(ctx); + gen_helper_precequ_ph_qbl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQU_PH_QBR: + check_dsp(ctx); + gen_helper_precequ_ph_qbr(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQU_PH_QBLA: + check_dsp(ctx); + gen_helper_precequ_ph_qbla(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQU_PH_QBRA: + check_dsp(ctx); + gen_helper_precequ_ph_qbra(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEU_PH_QBL: + check_dsp(ctx); + gen_helper_preceu_ph_qbl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEU_PH_QBR: + check_dsp(ctx); + gen_helper_preceu_ph_qbr(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEU_PH_QBLA: + check_dsp(ctx); + gen_helper_preceu_ph_qbla(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEU_PH_QBRA: + check_dsp(ctx); + gen_helper_preceu_ph_qbra(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_REPLV_PH: + check_dsp(ctx); + tcg_gen_ext16u_tl(v0_t, v0_t); + tcg_gen_shli_tl(t0, v0_t, 16); + tcg_gen_or_tl(v0_t, v0_t, t0); + tcg_gen_ext32s_tl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_REPLV_QB: + check_dsp(ctx); + tcg_gen_ext8u_tl(v0_t, v0_t); + tcg_gen_shli_tl(t0, v0_t, 8); + tcg_gen_or_tl(v0_t, v0_t, t0); + tcg_gen_shli_tl(t0, v0_t, 16); + tcg_gen_or_tl(v0_t, v0_t, t0); + tcg_gen_ext32s_tl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_BITREV: + check_dsp(ctx); + gen_helper_bitrev(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_INSV: + check_dsp(ctx); + { + TCGv tv0 = tcg_temp_new(); + + gen_load_gpr(tv0, rt); + gen_helper_insv(v0_t, cpu_env, v0_t, tv0); + gen_store_gpr(v0_t, ret); + tcg_temp_free(tv0); + } + break; + case NM_RADDU_W_QB: + check_dsp(ctx); + gen_helper_raddu_w_qb(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_BITSWAP: + gen_bitswap(ctx, OPC_BITSWAP, ret, rs); + break; + case NM_CLO: + check_nms(ctx); + gen_cl(ctx, OPC_CLO, ret, rs); + break; + case NM_CLZ: + check_nms(ctx); + gen_cl(ctx, OPC_CLZ, ret, rs); + break; + case NM_WSBH: + gen_bshfl(ctx, OPC_WSBH, ret, rs); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free(v0_t); + tcg_temp_free(t0); +} + +static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc, + int rt, int rs, int rd) +{ + TCGv t0 = tcg_temp_new(); + TCGv rs_t = tcg_temp_new(); + + gen_load_gpr(rs_t, rs); + + switch (opc) { + case NM_SHRA_R_QB: + check_dsp_r2(ctx); + tcg_gen_movi_tl(t0, rd >> 2); + switch (extract32(ctx->opcode, 12, 1)) { + case 0: + /* NM_SHRA_QB */ + gen_helper_shra_qb(t0, t0, rs_t); + gen_store_gpr(t0, rt); + break; + case 1: + /* NM_SHRA_R_QB */ + gen_helper_shra_r_qb(t0, t0, rs_t); + gen_store_gpr(t0, rt); + break; + } + break; + case NM_SHRL_PH: + check_dsp_r2(ctx); + tcg_gen_movi_tl(t0, rd >> 1); + gen_helper_shrl_ph(t0, t0, rs_t); + gen_store_gpr(t0, rt); + break; + case NM_REPL_QB: + check_dsp(ctx); + { + int16_t imm; + target_long result; + imm = extract32(ctx->opcode, 13, 8); + result = (uint32_t)imm << 24 | + (uint32_t)imm << 16 | + (uint32_t)imm << 8 | + (uint32_t)imm; + result = (int32_t)result; + tcg_gen_movi_tl(t0, result); + gen_store_gpr(t0, rt); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + tcg_temp_free(t0); + tcg_temp_free(rs_t); +} + + +static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) +{ + int rt = extract32(ctx->opcode, 21, 5); + int rs = extract32(ctx->opcode, 16, 5); + int rd = extract32(ctx->opcode, 11, 5); + + switch (extract32(ctx->opcode, 6, 3)) { + case NM_POOL32AXF_1: + { + int32_t op1 = extract32(ctx->opcode, 9, 3); + gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd); + } + break; + case NM_POOL32AXF_2: + { + int32_t op1 = extract32(ctx->opcode, 12, 2); + gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd); + } + break; + case NM_POOL32AXF_4: + { + int32_t op1 = extract32(ctx->opcode, 9, 7); + gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs); + } + break; + case NM_POOL32AXF_5: + switch (extract32(ctx->opcode, 9, 7)) { +#ifndef CONFIG_USER_ONLY + case NM_TLBP: + gen_cp0(env, ctx, OPC_TLBP, 0, 0); + break; + case NM_TLBR: + gen_cp0(env, ctx, OPC_TLBR, 0, 0); + break; + case NM_TLBWI: + gen_cp0(env, ctx, OPC_TLBWI, 0, 0); + break; + case NM_TLBWR: + gen_cp0(env, ctx, OPC_TLBWR, 0, 0); + break; + case NM_TLBINV: + gen_cp0(env, ctx, OPC_TLBINV, 0, 0); + break; + case NM_TLBINVF: + gen_cp0(env, ctx, OPC_TLBINVF, 0, 0); + break; + case NM_DI: + check_cp0_enabled(ctx); + { + TCGv t0 = tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_helper_di(t0, cpu_env); + gen_store_gpr(t0, rt); + /* Stop translation as we may have switched the execution mode */ + ctx->base.is_jmp = DISAS_STOP; + tcg_temp_free(t0); + } + break; + case NM_EI: + check_cp0_enabled(ctx); + { + TCGv t0 = tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_helper_ei(t0, cpu_env); + gen_store_gpr(t0, rt); + /* Stop translation as we may have switched the execution mode */ + ctx->base.is_jmp = DISAS_STOP; + tcg_temp_free(t0); + } + break; + case NM_RDPGPR: + gen_load_srsgpr(rs, rt); + break; + case NM_WRPGPR: + gen_store_srsgpr(rs, rt); + break; + case NM_WAIT: + gen_cp0(env, ctx, OPC_WAIT, 0, 0); + break; + case NM_DERET: + gen_cp0(env, ctx, OPC_DERET, 0, 0); + break; + case NM_ERETX: + gen_cp0(env, ctx, OPC_ERET, 0, 0); + break; +#endif + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_POOL32AXF_7: + { + int32_t op1 = extract32(ctx->opcode, 9, 3); + gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* nanoMIPS Branches */ +static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc, + int insn_bytes, + int rs, int rt, int32_t offset) +{ + target_ulong btgt = -1; + int bcond_compute = 0; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + /* Load needed operands */ + switch (opc) { + case OPC_BEQ: + case OPC_BNE: + /* Compare two registers */ + if (rs != rt) { + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute = 1; + } + btgt = ctx->base.pc_next + insn_bytes + offset; + break; + case OPC_BGEZAL: + /* Compare to zero */ + if (rs != 0) { + gen_load_gpr(t0, rs); + bcond_compute = 1; + } + btgt = ctx->base.pc_next + insn_bytes + offset; + break; + case OPC_BPOSGE32: + tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F); + bcond_compute = 1; + btgt = ctx->base.pc_next + insn_bytes + offset; + break; + case OPC_JR: + case OPC_JALR: + /* Jump to register */ + if (offset != 0 && offset != 16) { + /* + * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the + * others are reserved. + */ + MIPS_INVAL("jump hint"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + gen_load_gpr(btarget, rs); + break; + default: + MIPS_INVAL("branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + if (bcond_compute == 0) { + /* No condition to be computed */ + switch (opc) { + case OPC_BEQ: /* rx == rx */ + /* Always take */ + ctx->hflags |= MIPS_HFLAG_B; + break; + case OPC_BGEZAL: /* 0 >= 0 */ + /* Always take and link */ + tcg_gen_movi_tl(cpu_gpr[31], + ctx->base.pc_next + insn_bytes); + ctx->hflags |= MIPS_HFLAG_B; + break; + case OPC_BNE: /* rx != rx */ + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8); + /* Skip the instruction in the delay slot */ + ctx->base.pc_next += 4; + goto out; + case OPC_JR: + ctx->hflags |= MIPS_HFLAG_BR; + break; + case OPC_JALR: + if (rt > 0) { + tcg_gen_movi_tl(cpu_gpr[rt], + ctx->base.pc_next + insn_bytes); + } + ctx->hflags |= MIPS_HFLAG_BR; + break; + default: + MIPS_INVAL("branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + } else { + switch (opc) { + case OPC_BEQ: + tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); + goto not_likely; + case OPC_BNE: + tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); + goto not_likely; + case OPC_BGEZAL: + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); + tcg_gen_movi_tl(cpu_gpr[31], + ctx->base.pc_next + insn_bytes); + goto not_likely; + case OPC_BPOSGE32: + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32); + not_likely: + ctx->hflags |= MIPS_HFLAG_BC; + break; + default: + MIPS_INVAL("conditional branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + } + + ctx->btarget = btgt; + + out: + if (insn_bytes == 2) { + ctx->hflags |= MIPS_HFLAG_B16; + } + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* Immediate Value Compact Branches */ +static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, + int rt, int32_t imm, int32_t offset) +{ + TCGCond cond = TCG_COND_ALWAYS; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + tcg_gen_movi_tl(t1, imm); + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); + + /* Load needed operands and calculate btarget */ + switch (opc) { + case NM_BEQIC: + if (rt == 0 && imm == 0) { + /* Unconditional branch */ + } else if (rt == 0 && imm != 0) { + /* Treat as NOP */ + goto out; + } else { + cond = TCG_COND_EQ; + } + break; + case NM_BBEQZC: + case NM_BBNEZC: + check_nms(ctx); + if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) { + generate_exception_end(ctx, EXCP_RI); + goto out; + } else if (rt == 0 && opc == NM_BBEQZC) { + /* Unconditional branch */ + } else if (rt == 0 && opc == NM_BBNEZC) { + /* Treat as NOP */ + goto out; + } else { + tcg_gen_shri_tl(t0, t0, imm); + tcg_gen_andi_tl(t0, t0, 1); + tcg_gen_movi_tl(t1, 0); + if (opc == NM_BBEQZC) { + cond = TCG_COND_EQ; + } else { + cond = TCG_COND_NE; + } + } + break; + case NM_BNEIC: + if (rt == 0 && imm == 0) { + /* Treat as NOP */ + goto out; + } else if (rt == 0 && imm != 0) { + /* Unconditional branch */ + } else { + cond = TCG_COND_NE; + } + break; + case NM_BGEIC: + if (rt == 0 && imm == 0) { + /* Unconditional branch */ + } else { + cond = TCG_COND_GE; + } + break; + case NM_BLTIC: + cond = TCG_COND_LT; + break; + case NM_BGEIUC: + if (rt == 0 && imm == 0) { + /* Unconditional branch */ + } else { + cond = TCG_COND_GEU; + } + break; + case NM_BLTIUC: + cond = TCG_COND_LTU; + break; + default: + MIPS_INVAL("Immediate Value Compact branch"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + + if (cond == TCG_COND_ALWAYS) { + /* Uncoditional compact branch */ + gen_goto_tb(ctx, 0, ctx->btarget); + } else { + /* Conditional compact branch */ + TCGLabel *fs = gen_new_label(); + + tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs); + + gen_goto_tb(ctx, 1, ctx->btarget); + gen_set_label(fs); + + gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); + } + +out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */ +static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs, + int rt) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + /* load rs */ + gen_load_gpr(t0, rs); + + /* link */ + if (rt != 0) { + tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4); + } + + /* calculate btarget */ + tcg_gen_shli_tl(t0, t0, 1); + tcg_gen_movi_tl(t1, ctx->base.pc_next + 4); + gen_op_addr_add(ctx, btarget, t1, t0); + + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + + /* unconditional branch to register */ + tcg_gen_mov_tl(cpu_PC, btarget); + tcg_gen_lookup_and_goto_ptr(); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* nanoMIPS Branches */ +static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc, + int rs, int rt, int32_t offset) +{ + int bcond_compute = 0; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + /* Load needed operands and calculate btarget */ + switch (opc) { + /* compact branch */ + case OPC_BGEC: + case OPC_BLTC: + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute = 1; + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); + break; + case OPC_BGEUC: + case OPC_BLTUC: + if (rs == 0 || rs == rt) { + /* OPC_BLEZALC, OPC_BGEZALC */ + /* OPC_BGTZALC, OPC_BLTZALC */ + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4); + } + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute = 1; + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); + break; + case OPC_BC: + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); + break; + case OPC_BEQZC: + if (rs != 0) { + /* OPC_BEQZC, OPC_BNEZC */ + gen_load_gpr(t0, rs); + bcond_compute = 1; + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); + } else { + /* OPC_JIC, OPC_JIALC */ + TCGv tbase = tcg_temp_new(); + TCGv toffset = tcg_temp_new(); + + gen_load_gpr(tbase, rt); + tcg_gen_movi_tl(toffset, offset); + gen_op_addr_add(ctx, btarget, tbase, toffset); + tcg_temp_free(tbase); + tcg_temp_free(toffset); + } + break; + default: + MIPS_INVAL("Compact branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + + if (bcond_compute == 0) { + /* Uncoditional compact branch */ + switch (opc) { + case OPC_BC: + gen_goto_tb(ctx, 0, ctx->btarget); + break; + default: + MIPS_INVAL("Compact branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + } else { + /* Conditional compact branch */ + TCGLabel *fs = gen_new_label(); + + switch (opc) { + case OPC_BGEUC: + if (rs == 0 && rt != 0) { + /* OPC_BLEZALC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs); + } else if (rs != 0 && rt != 0 && rs == rt) { + /* OPC_BGEZALC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs); + } else { + /* OPC_BGEUC */ + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs); + } + break; + case OPC_BLTUC: + if (rs == 0 && rt != 0) { + /* OPC_BGTZALC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs); + } else if (rs != 0 && rt != 0 && rs == rt) { + /* OPC_BLTZALC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs); + } else { + /* OPC_BLTUC */ + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs); + } + break; + case OPC_BGEC: + if (rs == 0 && rt != 0) { + /* OPC_BLEZC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs); + } else if (rs != 0 && rt != 0 && rs == rt) { + /* OPC_BGEZC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs); + } else { + /* OPC_BGEC */ + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs); + } + break; + case OPC_BLTC: + if (rs == 0 && rt != 0) { + /* OPC_BGTZC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs); + } else if (rs != 0 && rt != 0 && rs == rt) { + /* OPC_BLTZC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs); + } else { + /* OPC_BLTC */ + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs); + } + break; + case OPC_BEQZC: + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs); + break; + default: + MIPS_INVAL("Compact conditional branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + + /* Generating branch here as compact branches don't have delay slot */ + gen_goto_tb(ctx, 1, ctx->btarget); + gen_set_label(fs); + + gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); + } + +out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + + +/* nanoMIPS CP1 Branches */ +static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op, + int32_t ft, int32_t offset) +{ + target_ulong btarget; + TCGv_i64 t0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, t0, ft); + tcg_gen_andi_i64(t0, t0, 1); + + btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); + + switch (op) { + case NM_BC1EQZC: + tcg_gen_xori_i64(t0, t0, 1); + ctx->hflags |= MIPS_HFLAG_BC; + break; + case NM_BC1NEZC: + /* t0 already set */ + ctx->hflags |= MIPS_HFLAG_BC; + break; + default: + MIPS_INVAL("cp1 cond branch"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + + tcg_gen_trunc_i64_tl(bcond, t0); + + ctx->btarget = btarget; + +out: + tcg_temp_free_i64(t0); +} + + +static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt) +{ + TCGv t0, t1; + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + + if ((extract32(ctx->opcode, 6, 1)) == 1) { + /* PP.LSXS instructions require shifting */ + switch (extract32(ctx->opcode, 7, 4)) { + case NM_SHXS: + check_nms(ctx); + /* fall through */ + case NM_LHXS: + case NM_LHUXS: + tcg_gen_shli_tl(t0, t0, 1); + break; + case NM_SWXS: + check_nms(ctx); + /* fall through */ + case NM_LWXS: + case NM_LWC1XS: + case NM_SWC1XS: + tcg_gen_shli_tl(t0, t0, 2); + break; + case NM_LDC1XS: + case NM_SDC1XS: + tcg_gen_shli_tl(t0, t0, 3); + break; + } + } + gen_op_addr_add(ctx, t0, t0, t1); + + switch (extract32(ctx->opcode, 7, 4)) { + case NM_LBX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_SB); + gen_store_gpr(t0, rd); + break; + case NM_LHX: + /*case NM_LHXS:*/ + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_TESW); + gen_store_gpr(t0, rd); + break; + case NM_LWX: + /*case NM_LWXS:*/ + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_TESL); + gen_store_gpr(t0, rd); + break; + case NM_LBUX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_UB); + gen_store_gpr(t0, rd); + break; + case NM_LHUX: + /*case NM_LHUXS:*/ + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_TEUW); + gen_store_gpr(t0, rd); + break; + case NM_SBX: + check_nms(ctx); + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, + MO_8); + break; + case NM_SHX: + /*case NM_SHXS:*/ + check_nms(ctx); + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, + MO_TEUW); + break; + case NM_SWX: + /*case NM_SWXS:*/ + check_nms(ctx); + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, + MO_TEUL); + break; + case NM_LWC1X: + /*case NM_LWC1XS:*/ + case NM_LDC1X: + /*case NM_LDC1XS:*/ + case NM_SWC1X: + /*case NM_SWC1XS:*/ + case NM_SDC1X: + /*case NM_SDC1XS:*/ + if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { + check_cp1_enabled(ctx); + switch (extract32(ctx->opcode, 7, 4)) { + case NM_LWC1X: + /*case NM_LWC1XS:*/ + gen_flt_ldst(ctx, OPC_LWC1, rd, t0); + break; + case NM_LDC1X: + /*case NM_LDC1XS:*/ + gen_flt_ldst(ctx, OPC_LDC1, rd, t0); + break; + case NM_SWC1X: + /*case NM_SWC1XS:*/ + gen_flt_ldst(ctx, OPC_SWC1, rd, t0); + break; + case NM_SDC1X: + /*case NM_SDC1XS:*/ + gen_flt_ldst(ctx, OPC_SDC1, rd, t0); + break; + } + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_pool32f_nanomips_insn(DisasContext *ctx) +{ + int rt, rs, rd; + + rt = extract32(ctx->opcode, 21, 5); + rs = extract32(ctx->opcode, 16, 5); + rd = extract32(ctx->opcode, 11, 5); + + if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) { + generate_exception_end(ctx, EXCP_RI); + return; + } + check_cp1_enabled(ctx); + switch (extract32(ctx->opcode, 0, 3)) { + case NM_POOL32F_0: + switch (extract32(ctx->opcode, 3, 7)) { + case NM_RINT_S: + gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); + break; + case NM_RINT_D: + gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); + break; + case NM_CLASS_S: + gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); + break; + case NM_CLASS_D: + gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); + break; + case NM_ADD_S: + gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0); + break; + case NM_ADD_D: + gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0); + break; + case NM_SUB_S: + gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0); + break; + case NM_SUB_D: + gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0); + break; + case NM_MUL_S: + gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0); + break; + case NM_MUL_D: + gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0); + break; + case NM_DIV_S: + gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0); + break; + case NM_DIV_D: + gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0); + break; + case NM_SELEQZ_S: + gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); + break; + case NM_SELEQZ_D: + gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); + break; + case NM_SELNEZ_S: + gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); + break; + case NM_SELNEZ_D: + gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); + break; + case NM_SEL_S: + gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); + break; + case NM_SEL_D: + gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); + break; + case NM_MADDF_S: + gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0); + break; + case NM_MADDF_D: + gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0); + break; + case NM_MSUBF_S: + gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0); + break; + case NM_MSUBF_D: + gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_POOL32F_3: + switch (extract32(ctx->opcode, 3, 3)) { + case NM_MIN_FMT: + switch (extract32(ctx->opcode, 9, 1)) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0); + break; + } + break; + case NM_MAX_FMT: + switch (extract32(ctx->opcode, 9, 1)) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0); + break; + } + break; + case NM_MINA_FMT: + switch (extract32(ctx->opcode, 9, 1)) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0); + break; + } + break; + case NM_MAXA_FMT: + switch (extract32(ctx->opcode, 9, 1)) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0); + break; + } + break; + case NM_POOL32FXF: + switch (extract32(ctx->opcode, 6, 8)) { + case NM_CFC1: + gen_cp1(ctx, OPC_CFC1, rt, rs); + break; + case NM_CTC1: + gen_cp1(ctx, OPC_CTC1, rt, rs); + break; + case NM_MFC1: + gen_cp1(ctx, OPC_MFC1, rt, rs); + break; + case NM_MTC1: + gen_cp1(ctx, OPC_MTC1, rt, rs); + break; + case NM_MFHC1: + gen_cp1(ctx, OPC_MFHC1, rt, rs); + break; + case NM_MTHC1: + gen_cp1(ctx, OPC_MTHC1, rt, rs); + break; + case NM_CVT_S_PL: + gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0); + break; + case NM_CVT_S_PU: + gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0); + break; + default: + switch (extract32(ctx->opcode, 6, 9)) { + case NM_CVT_L_S: + gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0); + break; + case NM_CVT_L_D: + gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0); + break; + case NM_CVT_W_S: + gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0); + break; + case NM_CVT_W_D: + gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0); + break; + case NM_RSQRT_S: + gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0); + break; + case NM_RSQRT_D: + gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0); + break; + case NM_SQRT_S: + gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0); + break; + case NM_SQRT_D: + gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0); + break; + case NM_RECIP_S: + gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0); + break; + case NM_RECIP_D: + gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0); + break; + case NM_FLOOR_L_S: + gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0); + break; + case NM_FLOOR_L_D: + gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0); + break; + case NM_FLOOR_W_S: + gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0); + break; + case NM_FLOOR_W_D: + gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0); + break; + case NM_CEIL_L_S: + gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0); + break; + case NM_CEIL_L_D: + gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0); + break; + case NM_CEIL_W_S: + gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0); + break; + case NM_CEIL_W_D: + gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0); + break; + case NM_TRUNC_L_S: + gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0); + break; + case NM_TRUNC_L_D: + gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0); + break; + case NM_TRUNC_W_S: + gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0); + break; + case NM_TRUNC_W_D: + gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0); + break; + case NM_ROUND_L_S: + gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0); + break; + case NM_ROUND_L_D: + gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0); + break; + case NM_ROUND_W_S: + gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0); + break; + case NM_ROUND_W_D: + gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0); + break; + case NM_MOV_S: + gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0); + break; + case NM_MOV_D: + gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0); + break; + case NM_ABS_S: + gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0); + break; + case NM_ABS_D: + gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0); + break; + case NM_NEG_S: + gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0); + break; + case NM_NEG_D: + gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0); + break; + case NM_CVT_D_S: + gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0); + break; + case NM_CVT_D_W: + gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0); + break; + case NM_CVT_D_L: + gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0); + break; + case NM_CVT_S_D: + gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0); + break; + case NM_CVT_S_W: + gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0); + break; + case NM_CVT_S_L: + gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + } + break; + } + break; + case NM_POOL32F_5: + switch (extract32(ctx->opcode, 3, 3)) { + case NM_CMP_CONDN_S: + gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); + break; + case NM_CMP_CONDN_D: + gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc, + int rd, int rs, int rt) +{ + int ret = rd; + TCGv t0 = tcg_temp_new(); + TCGv v1_t = tcg_temp_new(); + TCGv v2_t = tcg_temp_new(); + + gen_load_gpr(v1_t, rs); + gen_load_gpr(v2_t, rt); + + switch (opc) { + case NM_CMP_EQ_PH: + check_dsp(ctx); + gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env); + break; + case NM_CMP_LT_PH: + check_dsp(ctx); + gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env); + break; + case NM_CMP_LE_PH: + check_dsp(ctx); + gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env); + break; + case NM_CMPU_EQ_QB: + check_dsp(ctx); + gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env); + break; + case NM_CMPU_LT_QB: + check_dsp(ctx); + gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env); + break; + case NM_CMPU_LE_QB: + check_dsp(ctx); + gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env); + break; + case NM_CMPGU_EQ_QB: + check_dsp(ctx); + gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGU_LT_QB: + check_dsp(ctx); + gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGU_LE_QB: + check_dsp(ctx); + gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGDU_EQ_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGDU_LT_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGDU_LE_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); + gen_store_gpr(v1_t, ret); + break; + case NM_PACKRL_PH: + check_dsp(ctx); + gen_helper_packrl_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_PICK_QB: + check_dsp(ctx); + gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_PICK_PH: + check_dsp(ctx); + gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_ADDQ_S_W: + check_dsp(ctx); + gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_SUBQ_S_W: + check_dsp(ctx); + gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_ADDSC: + check_dsp(ctx); + gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_ADDWC: + check_dsp(ctx); + gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_ADDQ_S_PH: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDQ_PH */ + gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDQ_S_PH */ + gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDQH_R_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDQH_PH */ + gen_helper_addqh_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDQH_R_PH */ + gen_helper_addqh_r_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDQH_R_W: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDQH_W */ + gen_helper_addqh_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDQH_R_W */ + gen_helper_addqh_r_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDU_S_QB: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDU_QB */ + gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDU_S_QB */ + gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDU_S_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDU_PH */ + gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDU_S_PH */ + gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDUH_R_QB: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDUH_QB */ + gen_helper_adduh_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDUH_R_QB */ + gen_helper_adduh_r_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SHRAV_R_PH: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SHRAV_PH */ + gen_helper_shra_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SHRAV_R_PH */ + gen_helper_shra_r_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SHRAV_R_QB: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SHRAV_QB */ + gen_helper_shra_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SHRAV_R_QB */ + gen_helper_shra_r_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBQ_S_PH: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBQ_PH */ + gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBQ_S_PH */ + gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBQH_R_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBQH_PH */ + gen_helper_subqh_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBQH_R_PH */ + gen_helper_subqh_r_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBQH_R_W: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBQH_W */ + gen_helper_subqh_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBQH_R_W */ + gen_helper_subqh_r_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBU_S_QB: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBU_QB */ + gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBU_S_QB */ + gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBU_S_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBU_PH */ + gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBU_S_PH */ + gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBUH_R_QB: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBUH_QB */ + gen_helper_subuh_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBUH_R_QB */ + gen_helper_subuh_r_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SHLLV_S_PH: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SHLLV_PH */ + gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SHLLV_S_PH */ + gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_PRECR_SRA_R_PH_W: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* PRECR_SRA_PH_W */ + { + TCGv_i32 sa_t = tcg_const_i32(rd); + gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t, + cpu_gpr[rt]); + gen_store_gpr(v1_t, rt); + tcg_temp_free_i32(sa_t); + } + break; + case 1: + /* PRECR_SRA_R_PH_W */ + { + TCGv_i32 sa_t = tcg_const_i32(rd); + gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t, + cpu_gpr[rt]); + gen_store_gpr(v1_t, rt); + tcg_temp_free_i32(sa_t); + } + break; + } + break; + case NM_MULEU_S_PH_QBL: + check_dsp(ctx); + gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULEU_S_PH_QBR: + check_dsp(ctx); + gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULQ_RS_PH: + check_dsp(ctx); + gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULQ_S_PH: + check_dsp_r2(ctx); + gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULQ_RS_W: + check_dsp_r2(ctx); + gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULQ_S_W: + check_dsp_r2(ctx); + gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_APPEND: + check_dsp_r2(ctx); + gen_load_gpr(t0, rs); + if (rd != 0) { + tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd); + } + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + break; + case NM_MODSUB: + check_dsp(ctx); + gen_helper_modsub(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_SHRAV_R_W: + check_dsp(ctx); + gen_helper_shra_r_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_SHRLV_PH: + check_dsp_r2(ctx); + gen_helper_shrl_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_SHRLV_QB: + check_dsp(ctx); + gen_helper_shrl_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_SHLLV_QB: + check_dsp(ctx); + gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_SHLLV_S_W: + check_dsp(ctx); + gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_SHILO: + check_dsp(ctx); + { + TCGv tv0 = tcg_temp_new(); + TCGv tv1 = tcg_temp_new(); + int16_t imm = extract32(ctx->opcode, 16, 7); + + tcg_gen_movi_tl(tv0, rd >> 3); + tcg_gen_movi_tl(tv1, imm); + gen_helper_shilo(tv0, tv1, cpu_env); + } + break; + case NM_MULEQ_S_W_PHL: + check_dsp(ctx); + gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULEQ_S_W_PHR: + check_dsp(ctx); + gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MUL_S_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* MUL_PH */ + gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* MUL_S_PH */ + gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_PRECR_QB_PH: + check_dsp_r2(ctx); + gen_helper_precr_qb_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_PRECRQ_QB_PH: + check_dsp(ctx); + gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_PRECRQ_PH_W: + check_dsp(ctx); + gen_helper_precrq_ph_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_PRECRQ_RS_PH_W: + check_dsp(ctx); + gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_PRECRQU_S_QB_PH: + check_dsp(ctx); + gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_SHRA_R_W: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd); + gen_helper_shra_r_w(v1_t, t0, v1_t); + gen_store_gpr(v1_t, rt); + break; + case NM_SHRA_R_PH: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 1); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SHRA_PH */ + gen_helper_shra_ph(v1_t, t0, v1_t); + gen_store_gpr(v1_t, rt); + break; + case 1: + /* SHRA_R_PH */ + gen_helper_shra_r_ph(v1_t, t0, v1_t); + gen_store_gpr(v1_t, rt); + break; + } + break; + case NM_SHLL_S_PH: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 1); + switch (extract32(ctx->opcode, 10, 2)) { + case 0: + /* SHLL_PH */ + gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env); + gen_store_gpr(v1_t, rt); + break; + case 2: + /* SHLL_S_PH */ + gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env); + gen_store_gpr(v1_t, rt); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_SHLL_S_W: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd); + gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env); + gen_store_gpr(v1_t, rt); + break; + case NM_REPL_PH: + check_dsp(ctx); + { + int16_t imm; + imm = sextract32(ctx->opcode, 11, 11); + imm = (int16_t)(imm << 6) >> 6; + if (rt != 0) { + tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm)); + } + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) +{ + uint16_t insn; + uint32_t op; + int rt, rs, rd; + int offset; + int imm; + + insn = cpu_lduw_code(env, ctx->base.pc_next + 2); + ctx->opcode = (ctx->opcode << 16) | insn; + + rt = extract32(ctx->opcode, 21, 5); + rs = extract32(ctx->opcode, 16, 5); + rd = extract32(ctx->opcode, 11, 5); + + op = extract32(ctx->opcode, 26, 6); + switch (op) { + case NM_P_ADDIU: + if (rt == 0) { + /* P.RI */ + switch (extract32(ctx->opcode, 19, 2)) { + case NM_SIGRIE: + default: + generate_exception_end(ctx, EXCP_RI); + break; + case NM_P_SYSCALL: + if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) { + generate_exception_end(ctx, EXCP_SYSCALL); + } else { + generate_exception_end(ctx, EXCP_RI); + } + break; + case NM_BREAK: + generate_exception_end(ctx, EXCP_BREAK); + break; + case NM_SDBBP: + if (is_uhi(extract32(ctx->opcode, 0, 19))) { + gen_helper_do_semihosting(cpu_env); + } else { + if (ctx->hflags & MIPS_HFLAG_SBRI) { + generate_exception_end(ctx, EXCP_RI); + } else { + generate_exception_end(ctx, EXCP_DBp); + } + } + break; + } + } else { + /* NM_ADDIU */ + imm = extract32(ctx->opcode, 0, 16); + if (rs != 0) { + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm); + } else { + tcg_gen_movi_tl(cpu_gpr[rt], imm); + } + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + } + break; + case NM_ADDIUPC: + if (rt != 0) { + offset = sextract32(ctx->opcode, 0, 1) << 21 | + extract32(ctx->opcode, 1, 20) << 1; + target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset); + tcg_gen_movi_tl(cpu_gpr[rt], addr); + } + break; + case NM_POOL32A: + switch (ctx->opcode & 0x07) { + case NM_POOL32A0: + gen_pool32a0_nanomips_insn(env, ctx); + break; + case NM_POOL32A5: + { + int32_t op1 = extract32(ctx->opcode, 3, 7); + gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt); + } + break; + case NM_POOL32A7: + switch (extract32(ctx->opcode, 3, 3)) { + case NM_P_LSX: + gen_p_lsx(ctx, rd, rs, rt); + break; + case NM_LSA: + /* + * In nanoMIPS, the shift field directly encodes the shift + * amount, meaning that the supported shift values are in + * the range 0 to 3 (instead of 1 to 4 in MIPSR6). + */ + gen_lsa(ctx, OPC_LSA, rd, rs, rt, + extract32(ctx->opcode, 9, 2) - 1); + break; + case NM_EXTW: + gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5)); + break; + case NM_POOL32AXF: + gen_pool32axf_nanomips_insn(env, ctx); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P_GP_W: + switch (ctx->opcode & 0x03) { + case NM_ADDIUGP_W: + if (rt != 0) { + offset = extract32(ctx->opcode, 0, 21); + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset); + } + break; + case NM_LWGP: + gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2); + break; + case NM_SWGP: + gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P48I: + { + insn = cpu_lduw_code(env, ctx->base.pc_next + 4); + target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16; + switch (extract32(ctx->opcode, 16, 5)) { + case NM_LI48: + check_nms(ctx); + if (rt != 0) { + tcg_gen_movi_tl(cpu_gpr[rt], addr_off); + } + break; + case NM_ADDIU48: + check_nms(ctx); + if (rt != 0) { + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off); + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + } + break; + case NM_ADDIUGP48: + check_nms(ctx); + if (rt != 0) { + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off); + } + break; + case NM_ADDIUPC48: + check_nms(ctx); + if (rt != 0) { + target_long addr = addr_add(ctx, ctx->base.pc_next + 6, + addr_off); + + tcg_gen_movi_tl(cpu_gpr[rt], addr); + } + break; + case NM_LWPC48: + check_nms(ctx); + if (rt != 0) { + TCGv t0; + t0 = tcg_temp_new(); + + target_long addr = addr_add(ctx, ctx->base.pc_next + 6, + addr_off); + + tcg_gen_movi_tl(t0, addr); + tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL); + tcg_temp_free(t0); + } + break; + case NM_SWPC48: + check_nms(ctx); + { + TCGv t0, t1; + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + target_long addr = addr_add(ctx, ctx->base.pc_next + 6, + addr_off); + + tcg_gen_movi_tl(t0, addr); + gen_load_gpr(t1, rt); + + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + return 6; + } + case NM_P_U12: + switch (extract32(ctx->opcode, 12, 4)) { + case NM_ORI: + gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12)); + break; + case NM_XORI: + gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12)); + break; + case NM_ANDI: + gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12)); + break; + case NM_P_SR: + switch (extract32(ctx->opcode, 20, 1)) { + case NM_PP_SR: + switch (ctx->opcode & 3) { + case NM_SAVE: + gen_save(ctx, rt, extract32(ctx->opcode, 16, 4), + extract32(ctx->opcode, 2, 1), + extract32(ctx->opcode, 3, 9) << 3); + break; + case NM_RESTORE: + case NM_RESTORE_JRC: + gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4), + extract32(ctx->opcode, 2, 1), + extract32(ctx->opcode, 3, 9) << 3); + if ((ctx->opcode & 3) == NM_RESTORE_JRC) { + gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P_SR_F: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_SLTI: + gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12)); + break; + case NM_SLTIU: + gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12)); + break; + case NM_SEQI: + { + TCGv t0 = tcg_temp_new(); + + imm = extract32(ctx->opcode, 0, 12); + gen_load_gpr(t0, rs); + tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm); + gen_store_gpr(t0, rt); + + tcg_temp_free(t0); + } + break; + case NM_ADDIUNEG: + imm = (int16_t) extract32(ctx->opcode, 0, 12); + gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm); + break; + case NM_P_SHIFT: + { + int shift = extract32(ctx->opcode, 0, 5); + switch (extract32(ctx->opcode, 5, 4)) { + case NM_P_SLL: + if (rt == 0 && shift == 0) { + /* NOP */ + } else if (rt == 0 && shift == 3) { + /* EHB - treat as NOP */ + } else if (rt == 0 && shift == 5) { + /* PAUSE - treat as NOP */ + } else if (rt == 0 && shift == 6) { + /* SYNC */ + gen_sync(extract32(ctx->opcode, 16, 5)); + } else { + /* SLL */ + gen_shift_imm(ctx, OPC_SLL, rt, rs, + extract32(ctx->opcode, 0, 5)); + } + break; + case NM_SRL: + gen_shift_imm(ctx, OPC_SRL, rt, rs, + extract32(ctx->opcode, 0, 5)); + break; + case NM_SRA: + gen_shift_imm(ctx, OPC_SRA, rt, rs, + extract32(ctx->opcode, 0, 5)); + break; + case NM_ROTR: + gen_shift_imm(ctx, OPC_ROTR, rt, rs, + extract32(ctx->opcode, 0, 5)); + break; + } + } + break; + case NM_P_ROTX: + check_nms(ctx); + if (rt != 0) { + TCGv t0 = tcg_temp_new(); + TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5)); + TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4) + << 1); + TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1)); + + gen_load_gpr(t0, rs); + gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe); + tcg_temp_free(t0); + + tcg_temp_free_i32(shift); + tcg_temp_free_i32(shiftx); + tcg_temp_free_i32(stripe); + } + break; + case NM_P_INS: + switch (((ctx->opcode >> 10) & 2) | + (extract32(ctx->opcode, 5, 1))) { + case NM_INS: + check_nms(ctx); + gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5), + extract32(ctx->opcode, 6, 5)); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P_EXT: + switch (((ctx->opcode >> 10) & 2) | + (extract32(ctx->opcode, 5, 1))) { + case NM_EXT: + check_nms(ctx); + gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5), + extract32(ctx->opcode, 6, 5)); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_POOL32F: + gen_pool32f_nanomips_insn(ctx); + break; + case NM_POOL32S: + break; + case NM_P_LUI: + switch (extract32(ctx->opcode, 1, 1)) { + case NM_LUI: + if (rt != 0) { + tcg_gen_movi_tl(cpu_gpr[rt], + sextract32(ctx->opcode, 0, 1) << 31 | + extract32(ctx->opcode, 2, 10) << 21 | + extract32(ctx->opcode, 12, 9) << 12); + } + break; + case NM_ALUIPC: + if (rt != 0) { + offset = sextract32(ctx->opcode, 0, 1) << 31 | + extract32(ctx->opcode, 2, 10) << 21 | + extract32(ctx->opcode, 12, 9) << 12; + target_long addr; + addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset); + tcg_gen_movi_tl(cpu_gpr[rt], addr); + } + break; + } + break; + case NM_P_GP_BH: + { + uint32_t u = extract32(ctx->opcode, 0, 18); + + switch (extract32(ctx->opcode, 18, 3)) { + case NM_LBGP: + gen_ld(ctx, OPC_LB, rt, 28, u); + break; + case NM_SBGP: + gen_st(ctx, OPC_SB, rt, 28, u); + break; + case NM_LBUGP: + gen_ld(ctx, OPC_LBU, rt, 28, u); + break; + case NM_ADDIUGP_B: + if (rt != 0) { + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u); + } + break; + case NM_P_GP_LH: + u &= ~1; + switch (ctx->opcode & 1) { + case NM_LHGP: + gen_ld(ctx, OPC_LH, rt, 28, u); + break; + case NM_LHUGP: + gen_ld(ctx, OPC_LHU, rt, 28, u); + break; + } + break; + case NM_P_GP_SH: + u &= ~1; + switch (ctx->opcode & 1) { + case NM_SHGP: + gen_st(ctx, OPC_SH, rt, 28, u); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P_GP_CP1: + u &= ~0x3; + switch (ctx->opcode & 0x3) { + case NM_LWC1GP: + gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u); + break; + case NM_LDC1GP: + gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u); + break; + case NM_SWC1GP: + gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u); + break; + case NM_SDC1GP: + gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u); + break; + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + } + break; + case NM_P_LS_U12: + { + uint32_t u = extract32(ctx->opcode, 0, 12); + + switch (extract32(ctx->opcode, 12, 4)) { + case NM_P_PREFU12: + if (rt == 31) { + /* SYNCI */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ + ctx->base.is_jmp = DISAS_STOP; + } else { + /* PREF */ + /* Treat as NOP. */ + } + break; + case NM_LB: + gen_ld(ctx, OPC_LB, rt, rs, u); + break; + case NM_LH: + gen_ld(ctx, OPC_LH, rt, rs, u); + break; + case NM_LW: + gen_ld(ctx, OPC_LW, rt, rs, u); + break; + case NM_LBU: + gen_ld(ctx, OPC_LBU, rt, rs, u); + break; + case NM_LHU: + gen_ld(ctx, OPC_LHU, rt, rs, u); + break; + case NM_SB: + gen_st(ctx, OPC_SB, rt, rs, u); + break; + case NM_SH: + gen_st(ctx, OPC_SH, rt, rs, u); + break; + case NM_SW: + gen_st(ctx, OPC_SW, rt, rs, u); + break; + case NM_LWC1: + gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u); + break; + case NM_LDC1: + gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u); + break; + case NM_SWC1: + gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u); + break; + case NM_SDC1: + gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + } + break; + case NM_P_LS_S9: + { + int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) | + extract32(ctx->opcode, 0, 8); + + switch (extract32(ctx->opcode, 8, 3)) { + case NM_P_LS_S0: + switch (extract32(ctx->opcode, 11, 4)) { + case NM_LBS9: + gen_ld(ctx, OPC_LB, rt, rs, s); + break; + case NM_LHS9: + gen_ld(ctx, OPC_LH, rt, rs, s); + break; + case NM_LWS9: + gen_ld(ctx, OPC_LW, rt, rs, s); + break; + case NM_LBUS9: + gen_ld(ctx, OPC_LBU, rt, rs, s); + break; + case NM_LHUS9: + gen_ld(ctx, OPC_LHU, rt, rs, s); + break; + case NM_SBS9: + gen_st(ctx, OPC_SB, rt, rs, s); + break; + case NM_SHS9: + gen_st(ctx, OPC_SH, rt, rs, s); + break; + case NM_SWS9: + gen_st(ctx, OPC_SW, rt, rs, s); + break; + case NM_LWC1S9: + gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s); + break; + case NM_LDC1S9: + gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s); + break; + case NM_SWC1S9: + gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s); + break; + case NM_SDC1S9: + gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s); + break; + case NM_P_PREFS9: + if (rt == 31) { + /* SYNCI */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ + ctx->base.is_jmp = DISAS_STOP; + } else { + /* PREF */ + /* Treat as NOP. */ + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P_LS_S1: + switch (extract32(ctx->opcode, 11, 4)) { + case NM_UALH: + case NM_UASH: + check_nms(ctx); + { + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, rs, s); + + switch (extract32(ctx->opcode, 11, 4)) { + case NM_UALH: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | + MO_UNALN); + gen_store_gpr(t0, rt); + break; + case NM_UASH: + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | + MO_UNALN); + break; + } + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + case NM_P_LL: + switch (ctx->opcode & 0x03) { + case NM_LL: + gen_ld(ctx, OPC_LL, rt, rs, s); + break; + case NM_LLWP: + check_xnp(ctx); + gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); + break; + } + break; + case NM_P_SC: + switch (ctx->opcode & 0x03) { + case NM_SC: + gen_st_cond(ctx, rt, rs, s, MO_TESL, false); + break; + case NM_SCWP: + check_xnp(ctx); + gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5), + false); + break; + } + break; + case NM_CACHE: + check_cp0_enabled(ctx); + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, s); + } + break; + } + break; + case NM_P_LS_E0: + switch (extract32(ctx->opcode, 11, 4)) { + case NM_LBE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LBE, rt, rs, s); + break; + case NM_SBE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_st(ctx, OPC_SBE, rt, rs, s); + break; + case NM_LBUE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LBUE, rt, rs, s); + break; + case NM_P_PREFE: + if (rt == 31) { + /* case NM_SYNCIE */ + check_eva(ctx); + check_cp0_enabled(ctx); + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ + ctx->base.is_jmp = DISAS_STOP; + } else { + /* case NM_PREFE */ + check_eva(ctx); + check_cp0_enabled(ctx); + /* Treat as NOP. */ + } + break; + case NM_LHE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LHE, rt, rs, s); + break; + case NM_SHE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_st(ctx, OPC_SHE, rt, rs, s); + break; + case NM_LHUE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LHUE, rt, rs, s); + break; + case NM_CACHEE: + check_nms_dl_il_sl_tl_l2c(ctx); + gen_cache_operation(ctx, rt, rs, s); + break; + case NM_LWE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LWE, rt, rs, s); + break; + case NM_SWE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_st(ctx, OPC_SWE, rt, rs, s); + break; + case NM_P_LLE: + switch (extract32(ctx->opcode, 2, 2)) { + case NM_LLE: + check_xnp(ctx); + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LLE, rt, rs, s); + break; + case NM_LLWPE: + check_xnp(ctx); + check_eva(ctx); + check_cp0_enabled(ctx); + gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P_SCE: + switch (extract32(ctx->opcode, 2, 2)) { + case NM_SCE: + check_xnp(ctx); + check_eva(ctx); + check_cp0_enabled(ctx); + gen_st_cond(ctx, rt, rs, s, MO_TESL, true); + break; + case NM_SCWPE: + check_xnp(ctx); + check_eva(ctx); + check_cp0_enabled(ctx); + gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5), + true); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + } + break; + case NM_P_LS_WM: + case NM_P_LS_UAWM: + check_nms(ctx); + { + int count = extract32(ctx->opcode, 12, 3); + int counter = 0; + + offset = sextract32(ctx->opcode, 15, 1) << 8 | + extract32(ctx->opcode, 0, 8); + TCGv va = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + MemOp memop = (extract32(ctx->opcode, 8, 3)) == + NM_P_LS_UAWM ? MO_UNALN : 0; + + count = (count == 0) ? 8 : count; + while (counter != count) { + int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10); + int this_offset = offset + (counter << 2); + + gen_base_offset_addr(ctx, va, rs, this_offset); + + switch (extract32(ctx->opcode, 11, 1)) { + case NM_LWM: + tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx, + memop | MO_TESL); + gen_store_gpr(t1, this_rt); + if ((this_rt == rs) && + (counter != (count - 1))) { + /* UNPREDICTABLE */ + } + break; + case NM_SWM: + this_rt = (rt == 0) ? 0 : this_rt; + gen_load_gpr(t1, this_rt); + tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx, + memop | MO_TEUL); + break; + } + counter++; + } + tcg_temp_free(va); + tcg_temp_free(t1); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + } + break; + case NM_MOVE_BALC: + check_nms(ctx); + { + TCGv t0 = tcg_temp_new(); + int32_t s = sextract32(ctx->opcode, 0, 1) << 21 | + extract32(ctx->opcode, 1, 20) << 1; + rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5; + rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 | + extract32(ctx->opcode, 21, 3)); + gen_load_gpr(t0, rt); + tcg_gen_mov_tl(cpu_gpr[rd], t0); + gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); + tcg_temp_free(t0); + } + break; + case NM_P_BAL: + { + int32_t s = sextract32(ctx->opcode, 0, 1) << 25 | + extract32(ctx->opcode, 1, 24) << 1; + + if ((extract32(ctx->opcode, 25, 1)) == 0) { + /* BC */ + gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s); + } else { + /* BALC */ + gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); + } + } + break; + case NM_P_J: + switch (extract32(ctx->opcode, 12, 4)) { + case NM_JALRC: + case NM_JALRC_HB: + gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0); + break; + case NM_P_BALRSC: + gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P_BR1: + { + int32_t s = sextract32(ctx->opcode, 0, 1) << 14 | + extract32(ctx->opcode, 1, 13) << 1; + switch (extract32(ctx->opcode, 14, 2)) { + case NM_BEQC: + check_nms(ctx); + gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s); + break; + case NM_P_BR3A: + s = sextract32(ctx->opcode, 0, 1) << 14 | + extract32(ctx->opcode, 1, 13) << 1; + check_cp1_enabled(ctx); + switch (extract32(ctx->opcode, 16, 5)) { + case NM_BC1EQZC: + gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s); + break; + case NM_BC1NEZC: + gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s); + break; + case NM_BPOSGE32C: + check_dsp_r3(ctx); + { + int32_t imm = extract32(ctx->opcode, 1, 13) | + extract32(ctx->opcode, 0, 1) << 13; + + gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2, + imm); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_BGEC: + if (rs == rt) { + gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s); + } else { + gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s); + } + break; + case NM_BGEUC: + if (rs == rt || rt == 0) { + gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s); + } else if (rs == 0) { + gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s); + } else { + gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s); + } + break; + } + } + break; + case NM_P_BR2: + { + int32_t s = sextract32(ctx->opcode, 0, 1) << 14 | + extract32(ctx->opcode, 1, 13) << 1; + switch (extract32(ctx->opcode, 14, 2)) { + case NM_BNEC: + check_nms(ctx); + gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s); + break; + case NM_BLTC: + if (rs != 0 && rt != 0 && rs == rt) { + /* NOP */ + ctx->hflags |= MIPS_HFLAG_FBNSLOT; + } else { + gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s); + } + break; + case NM_BLTUC: + if (rs == 0 || rs == rt) { + /* NOP */ + ctx->hflags |= MIPS_HFLAG_FBNSLOT; + } else { + gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + } + break; + case NM_P_BRI: + { + int32_t s = sextract32(ctx->opcode, 0, 1) << 11 | + extract32(ctx->opcode, 1, 10) << 1; + uint32_t u = extract32(ctx->opcode, 11, 7); + + gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3), + rt, u, s); + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + return 4; +} + +static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t op; + int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); + int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); + int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode)); + int offset; + int imm; + + /* make sure instructions are on a halfword boundary */ + if (ctx->base.pc_next & 0x1) { + TCGv tmp = tcg_const_tl(ctx->base.pc_next); + tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); + tcg_temp_free(tmp); + generate_exception_end(ctx, EXCP_AdEL); + return 2; + } + + op = extract32(ctx->opcode, 10, 6); + switch (op) { + case NM_P16_MV: + rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); + if (rt != 0) { + /* MOVE */ + rs = NANOMIPS_EXTRACT_RS5(ctx->opcode); + gen_arith(ctx, OPC_ADDU, rt, rs, 0); + } else { + /* P16.RI */ + switch (extract32(ctx->opcode, 3, 2)) { + case NM_P16_SYSCALL: + if (extract32(ctx->opcode, 2, 1) == 0) { + generate_exception_end(ctx, EXCP_SYSCALL); + } else { + generate_exception_end(ctx, EXCP_RI); + } + break; + case NM_BREAK16: + generate_exception_end(ctx, EXCP_BREAK); + break; + case NM_SDBBP16: + if (is_uhi(extract32(ctx->opcode, 0, 3))) { + gen_helper_do_semihosting(cpu_env); + } else { + if (ctx->hflags & MIPS_HFLAG_SBRI) { + generate_exception_end(ctx, EXCP_RI); + } else { + generate_exception_end(ctx, EXCP_DBp); + } + } + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + } + break; + case NM_P16_SHIFT: + { + int shift = extract32(ctx->opcode, 0, 3); + uint32_t opc = 0; + shift = (shift == 0) ? 8 : shift; + + switch (extract32(ctx->opcode, 3, 1)) { + case NM_SLL16: + opc = OPC_SLL; + break; + case NM_SRL16: + opc = OPC_SRL; + break; + } + gen_shift_imm(ctx, opc, rt, rs, shift); + } + break; + case NM_P16C: + switch (ctx->opcode & 1) { + case NM_POOL16C_0: + gen_pool16c_nanomips_insn(ctx); + break; + case NM_LWXS16: + gen_ldxs(ctx, rt, rs, rd); + break; + } + break; + case NM_P16_A1: + switch (extract32(ctx->opcode, 6, 1)) { + case NM_ADDIUR1SP: + imm = extract32(ctx->opcode, 0, 6) << 2; + gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P16_A2: + switch (extract32(ctx->opcode, 3, 1)) { + case NM_ADDIUR2: + imm = extract32(ctx->opcode, 0, 3) << 2; + gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm); + break; + case NM_P_ADDIURS5: + rt = extract32(ctx->opcode, 5, 5); + if (rt != 0) { + /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */ + imm = (sextract32(ctx->opcode, 4, 1) << 3) | + (extract32(ctx->opcode, 0, 3)); + gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm); + } + break; + } + break; + case NM_P16_ADDU: + switch (ctx->opcode & 0x1) { + case NM_ADDU16: + gen_arith(ctx, OPC_ADDU, rd, rs, rt); + break; + case NM_SUBU16: + gen_arith(ctx, OPC_SUBU, rd, rs, rt); + break; + } + break; + case NM_P16_4X4: + rt = (extract32(ctx->opcode, 9, 1) << 3) | + extract32(ctx->opcode, 5, 3); + rs = (extract32(ctx->opcode, 4, 1) << 3) | + extract32(ctx->opcode, 0, 3); + rt = decode_gpr_gpr4(rt); + rs = decode_gpr_gpr4(rs); + switch ((extract32(ctx->opcode, 7, 2) & 0x2) | + (extract32(ctx->opcode, 3, 1))) { + case NM_ADDU4X4: + check_nms(ctx); + gen_arith(ctx, OPC_ADDU, rt, rs, rt); + break; + case NM_MUL4X4: + check_nms(ctx); + gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_LI16: + { + int imm = extract32(ctx->opcode, 0, 7); + imm = (imm == 0x7f ? -1 : imm); + if (rt != 0) { + tcg_gen_movi_tl(cpu_gpr[rt], imm); + } + } + break; + case NM_ANDI16: + { + uint32_t u = extract32(ctx->opcode, 0, 4); + u = (u == 12) ? 0xff : + (u == 13) ? 0xffff : u; + gen_logic_imm(ctx, OPC_ANDI, rt, rs, u); + } + break; + case NM_P16_LB: + offset = extract32(ctx->opcode, 0, 2); + switch (extract32(ctx->opcode, 2, 2)) { + case NM_LB16: + gen_ld(ctx, OPC_LB, rt, rs, offset); + break; + case NM_SB16: + rt = decode_gpr_gpr3_src_store( + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + gen_st(ctx, OPC_SB, rt, rs, offset); + break; + case NM_LBU16: + gen_ld(ctx, OPC_LBU, rt, rs, offset); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_P16_LH: + offset = extract32(ctx->opcode, 1, 2) << 1; + switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) { + case NM_LH16: + gen_ld(ctx, OPC_LH, rt, rs, offset); + break; + case NM_SH16: + rt = decode_gpr_gpr3_src_store( + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + gen_st(ctx, OPC_SH, rt, rs, offset); + break; + case NM_LHU16: + gen_ld(ctx, OPC_LHU, rt, rs, offset); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case NM_LW16: + offset = extract32(ctx->opcode, 0, 4) << 2; + gen_ld(ctx, OPC_LW, rt, rs, offset); + break; + case NM_LWSP16: + rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); + offset = extract32(ctx->opcode, 0, 5) << 2; + gen_ld(ctx, OPC_LW, rt, 29, offset); + break; + case NM_LW4X4: + check_nms(ctx); + rt = (extract32(ctx->opcode, 9, 1) << 3) | + extract32(ctx->opcode, 5, 3); + rs = (extract32(ctx->opcode, 4, 1) << 3) | + extract32(ctx->opcode, 0, 3); + offset = (extract32(ctx->opcode, 3, 1) << 3) | + (extract32(ctx->opcode, 8, 1) << 2); + rt = decode_gpr_gpr4(rt); + rs = decode_gpr_gpr4(rs); + gen_ld(ctx, OPC_LW, rt, rs, offset); + break; + case NM_SW4X4: + check_nms(ctx); + rt = (extract32(ctx->opcode, 9, 1) << 3) | + extract32(ctx->opcode, 5, 3); + rs = (extract32(ctx->opcode, 4, 1) << 3) | + extract32(ctx->opcode, 0, 3); + offset = (extract32(ctx->opcode, 3, 1) << 3) | + (extract32(ctx->opcode, 8, 1) << 2); + rt = decode_gpr_gpr4_zero(rt); + rs = decode_gpr_gpr4(rs); + gen_st(ctx, OPC_SW, rt, rs, offset); + break; + case NM_LWGP16: + offset = extract32(ctx->opcode, 0, 7) << 2; + gen_ld(ctx, OPC_LW, rt, 28, offset); + break; + case NM_SWSP16: + rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); + offset = extract32(ctx->opcode, 0, 5) << 2; + gen_st(ctx, OPC_SW, rt, 29, offset); + break; + case NM_SW16: + rt = decode_gpr_gpr3_src_store( + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); + offset = extract32(ctx->opcode, 0, 4) << 2; + gen_st(ctx, OPC_SW, rt, rs, offset); + break; + case NM_SWGP16: + rt = decode_gpr_gpr3_src_store( + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + offset = extract32(ctx->opcode, 0, 7) << 2; + gen_st(ctx, OPC_SW, rt, 28, offset); + break; + case NM_BC16: + gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0, + (sextract32(ctx->opcode, 0, 1) << 10) | + (extract32(ctx->opcode, 1, 9) << 1)); + break; + case NM_BALC16: + gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0, + (sextract32(ctx->opcode, 0, 1) << 10) | + (extract32(ctx->opcode, 1, 9) << 1)); + break; + case NM_BEQZC16: + gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0, + (sextract32(ctx->opcode, 0, 1) << 7) | + (extract32(ctx->opcode, 1, 6) << 1)); + break; + case NM_BNEZC16: + gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0, + (sextract32(ctx->opcode, 0, 1) << 7) | + (extract32(ctx->opcode, 1, 6) << 1)); + break; + case NM_P16_BR: + switch (ctx->opcode & 0xf) { + case 0: + /* P16.JRC */ + switch (extract32(ctx->opcode, 4, 1)) { + case NM_JRC: + gen_compute_branch_nm(ctx, OPC_JR, 2, + extract32(ctx->opcode, 5, 5), 0, 0); + break; + case NM_JALRC16: + gen_compute_branch_nm(ctx, OPC_JALR, 2, + extract32(ctx->opcode, 5, 5), 31, 0); + break; + } + break; + default: + { + /* P16.BRI */ + uint32_t opc = extract32(ctx->opcode, 4, 3) < + extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE; + gen_compute_branch_nm(ctx, opc, 2, rs, rt, + extract32(ctx->opcode, 0, 4) << 1); + } + break; + } + break; + case NM_P16_SR: + { + int count = extract32(ctx->opcode, 0, 4); + int u = extract32(ctx->opcode, 4, 4) << 4; + + rt = 30 + extract32(ctx->opcode, 9, 1); + switch (extract32(ctx->opcode, 8, 1)) { + case NM_SAVE16: + gen_save(ctx, rt, count, 0, u); + break; + case NM_RESTORE_JRC16: + gen_restore(ctx, rt, count, 0, u); + gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); + break; + } + } + break; + case NM_MOVEP: + case NM_MOVEPREV: + check_nms(ctx); + { + static const int gpr2reg1[] = {4, 5, 6, 7}; + static const int gpr2reg2[] = {5, 6, 7, 8}; + int re; + int rd2 = extract32(ctx->opcode, 3, 1) << 1 | + extract32(ctx->opcode, 8, 1); + int r1 = gpr2reg1[rd2]; + int r2 = gpr2reg2[rd2]; + int r3 = extract32(ctx->opcode, 4, 1) << 3 | + extract32(ctx->opcode, 0, 3); + int r4 = extract32(ctx->opcode, 9, 1) << 3 | + extract32(ctx->opcode, 5, 3); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + if (op == NM_MOVEP) { + rd = r1; + re = r2; + rs = decode_gpr_gpr4_zero(r3); + rt = decode_gpr_gpr4_zero(r4); + } else { + rd = decode_gpr_gpr4(r3); + re = decode_gpr_gpr4(r4); + rs = r1; + rt = r2; + } + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_mov_tl(cpu_gpr[rd], t0); + tcg_gen_mov_tl(cpu_gpr[re], t1); + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + default: + return decode_nanomips_32_48_opc(env, ctx); + } + + return 2; +} From patchwork Mon Nov 23 20:44:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926765 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 26966C63697 for ; Mon, 23 Nov 2020 21:10:00 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6B8B0206F9 for ; Mon, 23 Nov 2020 21:09:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XVOSvpkq" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6B8B0206F9 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59782 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ5y-0008RO-99 for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:09:58 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46754) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIiv-0002Le-Et for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:09 -0500 Received: from mail-wr1-x441.google.com ([2a00:1450:4864:20::441]:39543) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIit-0001hI-I9 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:09 -0500 Received: by mail-wr1-x441.google.com with SMTP id e7so2586865wrv.6 for ; Mon, 23 Nov 2020 12:46:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=j1Y3DPzyuheO159W9qAyN3VYs+itKBeqGyIlOMc68sk=; b=XVOSvpkqvZo/jsr4A6heTMi4YSWyXdNjOekuyLOXPLOXp15JJ2Pzl2GrrEIXM69gv3 MyAf+s+gI7cqkGWrhanj0q/S1VCKqlJ7baZdDXNvgDBJ+b9pq5S6JPnACqmPg8E5jQxO sAIvc5lFYcR1AdcVZHW2Ypdn5XNmMEHwVJ7ii8vHVgrjqkx3asNPLt/g6PWlX54ogq+i E829Y4WMw2crWQd+dKDJiz/QsuaZi90DXGR3KK+i4DXczzoqmkatVpeZ204ENU48rm59 opjwV2c638ZQTPau9+MHpaRyrn68xZaurIq4ax+RnFK9R0lRx9A1l7rc3XV96YU6VobX 5O2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=j1Y3DPzyuheO159W9qAyN3VYs+itKBeqGyIlOMc68sk=; b=rdVqRawmPp3iwohy8Pf+UWkhhyLmBxH35OmhRcxoBL/+d4WR9LvTm0E2oa2LpJjgS5 m8DUwlhXcv7SdYaEPEapjbjtwlogXjTwEI0KP5M7xUEdV2TnTg5Vv8WNsUHUnm0G8J1v BEPHu7qHp2riLNSyr74KnR89Puk9xRVLvbTNSuA9vfupczIMNXlQZb7dws+bmipz3E48 GBfBVYeCDl5qFKLqSW8edb8iGyEOlbq4dYjHhkhOyKJnaRaq1TflA8ies8GKBw7+qbz8 f9i0x0ljJxcPmkOFgLl34fLnB/6R0HQqEWfZt2v/lJw23ArJKVQ4mR+k8rfP2lSJxt2S VrFg== X-Gm-Message-State: AOAM531bPUtnpeEeSlflG2QAcy+cmPRLWIGUuPCwibgblKKgFAWIMsRl fgQkqfdwoIcuEiOTeY1I03DRQCjKapY= X-Google-Smtp-Source: ABdhPJzgNeRX9N3E1CubbtsmUgN/ii3fSWs3n685b33/1m+i6r5CNOAm1t4sAH3vVdE9w6mDW0Cm3w== X-Received: by 2002:a5d:6506:: with SMTP id x6mr1585024wru.175.1606164365838; Mon, 23 Nov 2020 12:46:05 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id l24sm15339465wrb.28.2020.11.23.12.46.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:05 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 15/28] target/mips: Extract NEC Vr54xx helpers to vendor-vr54xx_helper.c Date: Mon, 23 Nov 2020 21:44:35 +0100 Message-Id: <20201123204448.3260804-16-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::441; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x441.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract NEC Vr54xx helpers from op_helper.c to a new file: 'vendor-vr54xx_helper.c'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-14-f4bug@amsat.org> --- target/mips/op_helper.c | 118 -------------------------- target/mips/vendor-vr54xx_helper.c | 131 +++++++++++++++++++++++++++++ target/mips/meson.build | 1 + 3 files changed, 132 insertions(+), 118 deletions(-) create mode 100644 target/mips/vendor-vr54xx_helper.c diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index dd09a4c714a..a900c008b5a 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -54,124 +54,6 @@ static void raise_exception(CPUMIPSState *env, uint32_t exception) do_raise_exception(env, exception, 0); } -/* 64 bits arithmetic for 32 bits hosts */ -static inline uint64_t get_HILO(CPUMIPSState *env) -{ - return ((uint64_t)(env->active_tc.HI[0]) << 32) | - (uint32_t)env->active_tc.LO[0]; -} - -static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO) -{ - env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); - return env->active_tc.HI[0] = (int32_t)(HILO >> 32); -} - -static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO) -{ - target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); - env->active_tc.HI[0] = (int32_t)(HILO >> 32); - return tmp; -} - -/* Multiplication variants of the vr54xx. */ -target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2)); -} - -target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HI_LOT0(env, (uint64_t)get_HILO(env) + - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HIT0_LO(env, (uint64_t)get_HILO(env) + - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HI_LOT0(env, (uint64_t)get_HILO(env) - - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HIT0_LO(env, (uint64_t)get_HILO(env) - - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); -} - -target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ - return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); -} - static inline target_ulong bitswap(target_ulong v) { v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) | diff --git a/target/mips/vendor-vr54xx_helper.c b/target/mips/vendor-vr54xx_helper.c new file mode 100644 index 00000000000..d8c8f648b54 --- /dev/null +++ b/target/mips/vendor-vr54xx_helper.c @@ -0,0 +1,131 @@ +/* + * MIPS NEC Vr54xx instruction emulation helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/helper-proto.h" + +/* 64 bits arithmetic for 32 bits hosts */ +static inline uint64_t get_HILO(CPUMIPSState *env) +{ + return ((uint64_t)(env->active_tc.HI[0]) << 32) | + (uint32_t)env->active_tc.LO[0]; +} + +static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO) +{ + env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); + return env->active_tc.HI[0] = (int32_t)(HILO >> 32); +} + +static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO) +{ + target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); + env->active_tc.HI[0] = (int32_t)(HILO >> 32); + return tmp; +} + +/* Multiplication variants of the vr54xx. */ +target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2)); +} + +target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); +} + +target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); +} + +target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); +} + +target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HI_LOT0(env, (uint64_t)get_HILO(env) + + (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); +} + +target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HIT0_LO(env, (uint64_t)get_HILO(env) + + (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); +} + +target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); +} + +target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); +} + +target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HI_LOT0(env, (uint64_t)get_HILO(env) - + (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); +} + +target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HIT0_LO(env, (uint64_t)get_HILO(env) - + (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); +} + +target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); +} + +target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); +} + +target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); +} + +target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) +{ + return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); +} diff --git a/target/mips/meson.build b/target/mips/meson.build index aa6ac67df76..8cc1d0ca0f7 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -8,6 +8,7 @@ 'op_helper.c', 'mod-dsp_helper.c', 'mod-msa_helper.c', + 'vendor-vr54xx_helper.c', 'translate.c', )) From patchwork Mon Nov 23 20:44:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926761 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 2DA10C2D0E4 for ; Mon, 23 Nov 2020 21:08:02 +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 95D7C206D5 for ; Mon, 23 Nov 2020 21:08:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IeDxl9A/" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 95D7C206D5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:53188 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ44-0005gc-Bw for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:08:00 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46784) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIj4-0002Mr-NU for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:27 -0500 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]:40257) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIiz-0001iK-Mt for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:17 -0500 Received: by mail-wr1-x444.google.com with SMTP id m6so20104427wrg.7 for ; Mon, 23 Nov 2020 12:46:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=c4jJTZD8ogptt8KJFpuKBUvTjXtZDzKX+vqshTzv/Ig=; b=IeDxl9A/net7p/bDAiEoWuyWSiaYCbyRuReQy7GNau6p1zvbfZD7TGBybD39262e03 RuytwnF+8BoIMWPy+8dAA3stwbdNNVsLjO/4BMimF4UfGaaKUfVPzZSujGpaYkJ87lCV IHKcfSDys/Ugdh6frOvvFjw5bMuSbJGr4BwWnZqkp8Z5t4Ujnl/Q6ciJ12gbSFTXic85 JtP1Mum7utgQmru5Uar7Suj0eRFZbKHKWPJR5DYAs5dAztnDXCTiKDrc0Nb9hgVQnQmW yUiPzHraomQX4AEpGoiu7RW/i+wZOdahJB7VppHbXNH6EoFgiMLdOlGK//smRhGchQLz aQxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=c4jJTZD8ogptt8KJFpuKBUvTjXtZDzKX+vqshTzv/Ig=; b=pHmJD8YSH4hywr61+aXLFTtqRmVi0FV5YcJUM44s92qr3VxM8RS8hJk9dPqheF4FWM yEpbLr+th6N6ssAIbk0EY2p7gLwzTPhn9ASP1vhGJmAjmifZoAF+yaBefc7jci4hmnMO fOR56sZbfNj4dWpQoqdI5pRUgIpZv30ZCIrSuzwUJ5gZzLj0UaETOAAAvSG9wOEBBKNY ka/o4EWve9NFGTtNPoa4+vShL1lqfYPt6xxAH8kVRvPTVp4h0bNG5cwc7t/71j7YEPyi ospRugb1bUmSrwcX3crK8qJhyrGV38wRalVFqQ0twpvk5MLz3N0BNdEUh+RQeJm+Iwz7 LZZQ== X-Gm-Message-State: AOAM533f17xvchNzvHIgBvY6ruDd4cnMKTOVqJK8+FuGS/wzqSDQDeX8 DTJZVqOiplO9+wjd7YKI1rgG7aGJJUE= X-Google-Smtp-Source: ABdhPJybk1c0phz6/1h5exIJonwGQGWb61Hfm/SgAkvYl9Am/GeirtvW04xkqkd1iGgbUWNWvVEZag== X-Received: by 2002:adf:de05:: with SMTP id b5mr1496041wrm.131.1606164370583; Mon, 23 Nov 2020 12:46:10 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id o197sm865922wme.17.2020.11.23.12.46.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:10 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 16/28] target/mips: Extract NEC Vr54xx helper definitions Date: Mon, 23 Nov 2020 21:44:36 +0100 Message-Id: <20201123204448.3260804-17-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::444; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x444.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract the NEC Vr54xx helper definitions to 'vendor-vr54xx_helper.h'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-15-f4bug@amsat.org> --- target/mips/helper.h | 17 ++--------------- target/mips/vendor-vr54xx_helper.h.inc | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 target/mips/vendor-vr54xx_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index 06da4c6cf68..58c716a1480 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -20,21 +20,6 @@ DEF_HELPER_3(lld, tl, env, tl, int) #endif #endif -DEF_HELPER_3(muls, tl, env, tl, tl) -DEF_HELPER_3(mulsu, tl, env, tl, tl) -DEF_HELPER_3(macc, tl, env, tl, tl) -DEF_HELPER_3(maccu, tl, env, tl, tl) -DEF_HELPER_3(msac, tl, env, tl, tl) -DEF_HELPER_3(msacu, tl, env, tl, tl) -DEF_HELPER_3(mulhi, tl, env, tl, tl) -DEF_HELPER_3(mulhiu, tl, env, tl, tl) -DEF_HELPER_3(mulshi, tl, env, tl, tl) -DEF_HELPER_3(mulshiu, tl, env, tl, tl) -DEF_HELPER_3(macchi, tl, env, tl, tl) -DEF_HELPER_3(macchiu, tl, env, tl, tl) -DEF_HELPER_3(msachi, tl, env, tl, tl) -DEF_HELPER_3(msachiu, tl, env, tl, tl) - DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) #ifdef TARGET_MIPS64 DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) @@ -424,3 +409,5 @@ DEF_HELPER_3(cache, void, env, tl, i32) #include "mod-dsp_helper.h.inc" #include "mod-msa_helper.h.inc" #include "mod-mt_helper.h.inc" + +#include "vendor-vr54xx_helper.h.inc" diff --git a/target/mips/vendor-vr54xx_helper.h.inc b/target/mips/vendor-vr54xx_helper.h.inc new file mode 100644 index 00000000000..50b1f5b818d --- /dev/null +++ b/target/mips/vendor-vr54xx_helper.h.inc @@ -0,0 +1,24 @@ +/* + * MIPS NEC Vr54xx instruction emulation helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +DEF_HELPER_3(muls, tl, env, tl, tl) +DEF_HELPER_3(mulsu, tl, env, tl, tl) +DEF_HELPER_3(macc, tl, env, tl, tl) +DEF_HELPER_3(maccu, tl, env, tl, tl) +DEF_HELPER_3(msac, tl, env, tl, tl) +DEF_HELPER_3(msacu, tl, env, tl, tl) +DEF_HELPER_3(mulhi, tl, env, tl, tl) +DEF_HELPER_3(mulhiu, tl, env, tl, tl) +DEF_HELPER_3(mulshi, tl, env, tl, tl) +DEF_HELPER_3(mulshiu, tl, env, tl, tl) +DEF_HELPER_3(macchi, tl, env, tl, tl) +DEF_HELPER_3(macchiu, tl, env, tl, tl) +DEF_HELPER_3(msachi, tl, env, tl, tl) +DEF_HELPER_3(msachiu, tl, env, tl, tl) From patchwork Mon Nov 23 20:44:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926753 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 CE6BFC2D0E4 for ; Mon, 23 Nov 2020 21:03:55 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0C465206B5 for ; Mon, 23 Nov 2020 21:03:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Zkp360kA" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0C465206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:44828 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ05-000210-JJ for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:03:53 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46788) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIj5-0002Ms-33 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:27 -0500 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]:52761) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIj3-0001jF-8v for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:18 -0500 Received: by mail-wm1-x331.google.com with SMTP id 10so615368wml.2 for ; Mon, 23 Nov 2020 12:46:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=y0Js5XRdc4mHW1GhozQJ/l2GsYmBgybFSQVaSoieEFs=; b=Zkp360kAzVxCaILcK5NTzwIBhwhjkhLcnJOzSAEsnwxgdJAuoWTz8kSYE1F/2hL5rY uT97vpd2vQ3PZRJ3gQmmKsBy7ObVp7sR7RcO36p4Nih6P3YgqfSIrw30tm4eaR/sGnti Z5KzCazlbAJhvYCT64v0Mn1oh9TvYYKfLhxcjXBnAeHryUXSiy7j2YYiqft+MmWNVYZT W6fOx7xSY0S4ujsNsjQD1sYIQNQ04s4RL32YPb3Og6MMMY/r3ghPPjLFheTonqHwCgI8 ncYHIfKGl0eFtC48WBV+gwYY1VIE3Y/cQ0BSjDOEWDGKh3pM8S+YWNr/bnyGPRbxMKZW e5Tw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=y0Js5XRdc4mHW1GhozQJ/l2GsYmBgybFSQVaSoieEFs=; b=K3MXF2yv2AchCcjCJ3katZINFEAipNooVQvMg5hXcnZ7QPHtyH1EVLFJh+CfKdIWXx Y7uvRGE40J36iJDo6JVGjQW4lBwl0Gn/kOsrVTVrUQqdN26oH4JG7POKF3yuMxvPMGO/ I5LneORSkz9MxGbBusCM5Oiu4kSfl2s5A6rKST/1PuPOiJevBoYO9BCDbNxwdEdv1Mcj 4+lo4Lt8atCa37MZkuVM71EbRoAkdMlaAZKPxf0VqxbJgfT6uKYtOdA4EJFLCpZvTPnZ FmSiTYUy1V3esc0oe+H8spJ3gy3d7obGkCKoDo2MGFZQs2V7pf+t7rWxrdRG0hCKfEGc vaIA== X-Gm-Message-State: AOAM533yy+LA4jpeSpBpcmsZHN2jbZkvTPpQYvaRvqaKl+Yr54sEtAKB SjA5UcMkkRtqaGKZ3OyLYA+CK28e3Jw= X-Google-Smtp-Source: ABdhPJzwh0LYi3yyJti3EVYoaFYO8OfnSVFc0c4FwWGFF1CBk1g6Riu8TMA7GhokvLeAqPYSkAzndw== X-Received: by 2002:a1c:4006:: with SMTP id n6mr677685wma.135.1606164375204; Mon, 23 Nov 2020 12:46:15 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id 6sm25327322wrn.72.2020.11.23.12.46.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:14 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 17/28] target/mips: Extract NEC Vr54xx translation routines Date: Mon, 23 Nov 2020 21:44:37 +0100 Message-Id: <20201123204448.3260804-18-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::331; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x331.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract the NEC Vr54xx translation routines to 'vendor-vr54xx_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-16-f4bug@amsat.org> --- target/mips/translate.c | 86 +-------------------- target/mips/vendor-vr54xx_translate.c.inc | 93 +++++++++++++++++++++++ 2 files changed, 95 insertions(+), 84 deletions(-) create mode 100644 target/mips/vendor-vr54xx_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index d6133bd7de7..ca2e79d955a 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -295,26 +295,6 @@ enum { OPC_DLSA = 0x15 | OPC_SPECIAL, }; -/* Multiplication variants of the vr54xx. */ -#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6))) - -enum { - OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT, - OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU, - OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT, - OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU, - OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT, - OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU, - OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT, - OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU, - OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT, - OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU, - OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT, - OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU, - OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT, - OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU, -}; - /* REGIMM (rt field) opcodes */ #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16))) @@ -4546,70 +4526,6 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } -static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc, - int rd, int rs, int rt) -{ - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - - switch (opc) { - case OPC_VR54XX_MULS: - gen_helper_muls(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MULSU: - gen_helper_mulsu(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MACC: - gen_helper_macc(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MACCU: - gen_helper_maccu(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MSAC: - gen_helper_msac(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MSACU: - gen_helper_msacu(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MULHI: - gen_helper_mulhi(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MULHIU: - gen_helper_mulhiu(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MULSHI: - gen_helper_mulshi(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MULSHIU: - gen_helper_mulshiu(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MACCHI: - gen_helper_macchi(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MACCHIU: - gen_helper_macchiu(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MSACHI: - gen_helper_msachi(t0, cpu_env, t0, t1); - break; - case OPC_VR54XX_MSACHIU: - gen_helper_msachiu(t0, cpu_env, t0, t1); - break; - default: - MIPS_INVAL("mul vr54xx"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - gen_store_gpr(t0, rd); - - out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} - static void gen_cl(DisasContext *ctx, uint32_t opc, int rd, int rs) { @@ -13022,6 +12938,8 @@ out: #include "mod-dsp_translate.c.inc" +#include "vendor-vr54xx_translate.c.inc" + static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd, sa; diff --git a/target/mips/vendor-vr54xx_translate.c.inc b/target/mips/vendor-vr54xx_translate.c.inc new file mode 100644 index 00000000000..8c952a98ebc --- /dev/null +++ b/target/mips/vendor-vr54xx_translate.c.inc @@ -0,0 +1,93 @@ +/* + * MIPS NEC Vr54xx translation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* Multiplication variants of the vr54xx. */ +#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6))) + +enum { + OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT, + OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU, + OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT, + OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU, + OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT, + OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU, + OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT, + OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU, + OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT, + OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU, + OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT, + OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU, + OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT, + OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU, +}; + +static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + + switch (opc) { + case OPC_VR54XX_MULS: + gen_helper_muls(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MULSU: + gen_helper_mulsu(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MACC: + gen_helper_macc(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MACCU: + gen_helper_maccu(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MSAC: + gen_helper_msac(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MSACU: + gen_helper_msacu(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MULHI: + gen_helper_mulhi(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MULHIU: + gen_helper_mulhiu(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MULSHI: + gen_helper_mulshi(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MULSHIU: + gen_helper_mulshiu(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MACCHI: + gen_helper_macchi(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MACCHIU: + gen_helper_macchiu(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MSACHI: + gen_helper_msachi(t0, cpu_env, t0, t1); + break; + case OPC_VR54XX_MSACHIU: + gen_helper_msachiu(t0, cpu_env, t0, t1); + break; + default: + MIPS_INVAL("mul vr54xx"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + gen_store_gpr(t0, rd); + + out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} From patchwork Mon Nov 23 20:44:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926779 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 74324C2D0E4 for ; Mon, 23 Nov 2020 21:17:58 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B240A206F9 for ; Mon, 23 Nov 2020 21:17:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gvjYTmYy" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B240A206F9 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48750 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJDg-0007S3-Ig for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:17:56 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46860) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjD-0002NN-6h for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:29 -0500 Received: from mail-wr1-x429.google.com ([2a00:1450:4864:20::429]:36542) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIj9-0001kS-1y for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:24 -0500 Received: by mail-wr1-x429.google.com with SMTP id z7so4297112wrn.3 for ; Mon, 23 Nov 2020 12:46:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KNh0pIqDMIwzmpZMDW4GayC8CZVQW/Y3xdXOMEVkIms=; b=gvjYTmYyf7xM65RfbQ4mUQCdIOqOV3DiYN00YuEQMoNkxEzDv9IWVI+hFbTG3eylcl 5iPcZ0dh1O2K9elpPvxV+iVE6DR7Oe0rbsQmPzrUdwXOOvz8g0g6Xs5sz1ASnDGR5BwI A+7BY3YlWpA4uiWhCiR+NGY7GSBTEMPOh3/zZxqc5e1Krnsi8SinzOo0p3mY3J+FAxN3 vcLs4DK3xrRkKOx8rVbwtSPEraij4xCfY89eg2/jlBZWKdGLPSPNSEjn9WOrFH8WgGY1 VgfSczilrrWFydQiGb1xeHX2i4Fc82awPaN66F1dPtwczFKIe9hoq9m6Bhr1xgX0Xo2n M3ZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=KNh0pIqDMIwzmpZMDW4GayC8CZVQW/Y3xdXOMEVkIms=; b=HwKl7WgAtvEjmh0BHQSL7ieKWhfFFHejIV0uhmfbfN2ZBqAnTtgFgRd7HuX1ZNUdbK wfsgZTN+iM7sGaQk1X671X1CJ8fciTLs8FpJ6IZa07ZIz9goKfavswDjtweO5EwGFZGK DdpG+VsNyeJkxUhpvm2WTbv+83S5RY5dMJw22mEPzrdWIofYh9bjXUn2vULUqyAn1pdA T+9vjOi+ZclQ0uWD19t8WXRfdY5gFOBweervKYcwpHQ5q7u361g4hN0WhBb44S4Er9HF sru56caHDyfuUZxTbiqJUTkD++RoesX6eROFaQZIsxAySfnv86EfknjP3pr1q4kSdLPB PDAQ== X-Gm-Message-State: AOAM531+rNjQ5WdhC79xMR2C3CNFHw5N4HtEhVaipMLrZArAYdNBhSKO I7MzCLYAe5BFF7G1cJ5N76HG/K7kY1U= X-Google-Smtp-Source: ABdhPJx+M4/91DBBBPNzgZVd41UD3vMMOU0OG5OEUgyXZw4md0YoOoCLjIkJ9eKQ7JQeyMe92Dmnmg== X-Received: by 2002:adf:f852:: with SMTP id d18mr1487789wrq.232.1606164380083; Mon, 23 Nov 2020 12:46:20 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id h98sm16992027wrh.69.2020.11.23.12.46.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:19 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 18/28] target/mips: Rename lmmi_helper.c as loong-simd_helper.c Date: Mon, 23 Nov 2020 21:44:38 +0100 Message-Id: <20201123204448.3260804-19-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::429; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x429.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" The LoongMMI extension has been renamed LoongSIMD (part of the LoongISA). Rename the helper file accordingly. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-17-f4bug@amsat.org> --- target/mips/{lmmi_helper.c => vendor-loong-simd_helper.c} | 0 target/mips/meson.build | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename target/mips/{lmmi_helper.c => vendor-loong-simd_helper.c} (100%) diff --git a/target/mips/lmmi_helper.c b/target/mips/vendor-loong-simd_helper.c similarity index 100% rename from target/mips/lmmi_helper.c rename to target/mips/vendor-loong-simd_helper.c diff --git a/target/mips/meson.build b/target/mips/meson.build index 8cc1d0ca0f7..d9285ae047a 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -4,10 +4,10 @@ 'fpu_helper.c', 'gdbstub.c', 'helper.c', - 'lmmi_helper.c', 'op_helper.c', 'mod-dsp_helper.c', 'mod-msa_helper.c', + 'vendor-loong-simd_helper.c', 'vendor-vr54xx_helper.c', 'translate.c', From patchwork Mon Nov 23 20:44:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926777 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.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UPPERCASE_50_75,URIBL_BLOCKED, 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 BE624C2D0E4 for ; Mon, 23 Nov 2020 21:16:41 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 174D8206B5 for ; Mon, 23 Nov 2020 21:16:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bwAC9cBB" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 174D8206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:47330 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJCS-0006rV-2C for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:16:40 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46884) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjH-0002OA-3C for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:31 -0500 Received: from mail-wr1-x441.google.com ([2a00:1450:4864:20::441]:39544) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjC-0001lZ-Uy for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:28 -0500 Received: by mail-wr1-x441.google.com with SMTP id e7so2587824wrv.6 for ; Mon, 23 Nov 2020 12:46:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NY9o0/B9Z2rTdzQ1+aaAk/LNJykt8kQZDMeThF4Lyqo=; b=bwAC9cBB5t1UX2ohDdP85y/nCc4LbuQa/myuONv9sSd67M7QlACy2CUwEi7ZdS6G7x ZpXKdXZGFXd+3WPTpR5UfglDLyxpHqIO9xObpUy7fRmeCUJboOZuKtiMDTSGRl1Qq7XT UpadoPAQlEGE7Ekj6M1AQZNSnw+evNmixMOiceWxCdIfDyIiy76XagLEs4R36rdxFPmi IiCcZAPyXdlfmjmKUbL4lIQxqLaXhyjGMOadF+zYKV545/1NOLoEf3OE/pv2az2UAY+N ww9DIFL/5K4mfT7jg77xtBo/AxFE7L7ba2zxTUX8IrbiH8qRny7grMXuzhRudDkmDGru O9AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=NY9o0/B9Z2rTdzQ1+aaAk/LNJykt8kQZDMeThF4Lyqo=; b=i41ric44ibk9JBFVHk0S551M2ziFc0HfTBtbRpVOlPtvmGrEUToDJEx7nBxDaGMsOD 1Ky0LtgPrArYiubhaSC0gqV2IC0QGnTDzhyLKS3/852TQDBZMcyMWNgY7FxQI8qKzvvC g0/m5V5xC6XsaRpYCma5vh8m2bZI9tgwAJtZLeB8v3bXJlR9pElWIB6hRC8IHtn3HU/c Re5bzC+0zTlz6bwgrBsE5oGs51YFqNXdZ2WoRPCK3wvQYY6i/+MWXLL3Df+qLIUHmdjn NF30lltuLHT7QRrySPVKAW/Fyd8R7S8+TAkS9Cx1MUWAsfpZ7qiZlQ8a2iNk3N1EgwJn UPxg== X-Gm-Message-State: AOAM532u521Pe1/q36MpiNHrRpqN74GsI5UiE9vpoCQzfdXJU1kJUxfe 4VSUP6qRdWWwdl8XiM4m2+zxOW97D4M= X-Google-Smtp-Source: ABdhPJzxIfDefw3X2ybmMha1Ge+WRm5qZB+QUe/jB+A5LNq2u+iIIJodLDAz7pPoMjwOSDJyNaxI5Q== X-Received: by 2002:adf:dec3:: with SMTP id i3mr1541376wrn.263.1606164385108; Mon, 23 Nov 2020 12:46:25 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id r1sm14230825wra.97.2020.11.23.12.46.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:24 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 19/28] target/mips: Extract Loongson SIMD helper definitions Date: Mon, 23 Nov 2020 21:44:39 +0100 Message-Id: <20201123204448.3260804-20-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::441; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x441.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, UPPERCASE_50_75=0.008 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract the Loongson SIMD helper definitions to 'vendor-loong-simd_helper.h'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-18-f4bug@amsat.org> --- target/mips/helper.h | 60 +------------------ target/mips/vendor-loong-simd_helper.h.inc | 69 ++++++++++++++++++++++ 2 files changed, 70 insertions(+), 59 deletions(-) create mode 100644 target/mips/vendor-loong-simd_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index 58c716a1480..4de11e8209b 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -343,65 +343,6 @@ DEF_HELPER_1(rdhwr_xnp, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) -/* Loongson multimedia functions. */ -DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddb, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubb, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packushb, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pavgh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pavgb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pminub, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psraw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaddhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64) -DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) - DEF_HELPER_3(cache, void, env, tl, i32) #include "isa-micromips_helper.h.inc" @@ -411,3 +352,4 @@ DEF_HELPER_3(cache, void, env, tl, i32) #include "mod-mt_helper.h.inc" #include "vendor-vr54xx_helper.h.inc" +#include "vendor-loong-simd_helper.h.inc" diff --git a/target/mips/vendor-loong-simd_helper.h.inc b/target/mips/vendor-loong-simd_helper.h.inc new file mode 100644 index 00000000000..30e5fda66e9 --- /dev/null +++ b/target/mips/vendor-loong-simd_helper.h.inc @@ -0,0 +1,69 @@ +/* + * Loongson SIMD instruction emulation helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2011 Richard Henderson + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddb, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubb, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packushb, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pavgh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pavgb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pminub, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psraw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaddhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) From patchwork Mon Nov 23 20:44:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926767 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 BBCF0C2D0E4 for ; Mon, 23 Nov 2020 21:09:59 +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 E0952206B5 for ; Mon, 23 Nov 2020 21:09:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="so/llHmZ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E0952206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59716 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ5x-0008Pn-Pa for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:09:57 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46914) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjL-0002QU-RE for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:36 -0500 Received: from mail-wm1-x332.google.com ([2a00:1450:4864:20::332]:55924) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjI-0001mr-SN for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:35 -0500 Received: by mail-wm1-x332.google.com with SMTP id x22so602134wmc.5 for ; Mon, 23 Nov 2020 12:46:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=U7NTzUqpG+USX3MdIDzS5276z0nx/Isk7EgCIUUfDCc=; b=so/llHmZNxnEbbPTXJQue3XieQ29fczo7/R8hV9nuVMU64aLwO/kU6wCynGDJ0nyFY E2pAv3tz5icMXxDuvDLFBfuekua9tz/cfJG/yFL+psC0ihc4ltdqbmu1ACQJDFVzPx6v ONGhW3nud08eyRFYyN55tjibIH2DJ6h+j2U30SXg4kjcpg0/byZ3AmvT3PnYh3mzlsUl mSNRfE1FKxlMvSYcE+WhdGyE2QgMZLbEhmkHFJIUHe/I7Bod0Ja/OInzME9JhVqEdS5G wVPHOb4e0G1lIJBHiaedaQOht1OK/1Go5+oHB4OVQDUUDwPRCY6ZFV9RqCQxllUyLAvn cPzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=U7NTzUqpG+USX3MdIDzS5276z0nx/Isk7EgCIUUfDCc=; b=pGLGre40s8s3akuCGaT72Qenzv5jP87NLNUFxNJ53KPnm2jRaFps9dj3nyydGWsewo dNSE705C3t+NOUJRIEtGlQDDtYgc2pCCb0VE2lHtMHLP8c+vvQypkcw4yWDzP19Y6PIx 2bI9/ivsJ+4iCJQw2No0CkQHzE444v7NWK8ros2fcNwtLeKJDkIB+pK1HdbdKOqgzB4N Oq3rN94oslg07yAqMIAZKHsMB2noShGrjprJC1CAStLJZlGhXSiYGKvNA0AxcEBH/TXl FkH6F0Sl+lcEvn5GrnjXiddRh4A1CLYKfoGoYgYlkF/HRGxwI6ZOBAIBBCv8i0nDxObZ cbCQ== X-Gm-Message-State: AOAM533EMjcqbp360FhImilDEb8SydcXnY/LKGxRWB2XiKxkkw3qTgSV fIfZtNF66M8lEWOwOVqOmalMzysKdzg= X-Google-Smtp-Source: ABdhPJwpDRXIedEQH8k+it6rMY2k1t7clw3UyGqrlwxx9LM0RIA5ruVkHSYXU7IndVVUEzrY97jr1w== X-Received: by 2002:a1c:9695:: with SMTP id y143mr740023wmd.70.1606164390087; Mon, 23 Nov 2020 12:46:30 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id z17sm854447wmf.15.2020.11.23.12.46.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:29 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 20/28] target/mips: Extract Loongson SIMD translation routines Date: Mon, 23 Nov 2020 21:44:40 +0100 Message-Id: <20201123204448.3260804-21-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::332; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x332.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" LoongSIMD (formerly LoongMMI in Loongson 2E/F) is the 128-bit SIMD extension from the LoongISA. Extract ~500 lines of translation routines to 'vendor-loong-simd_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-19-f4bug@amsat.org> --- target/mips/translate.c | 483 +---------------- target/mips/vendor-loong-simd_translate.c.inc | 492 ++++++++++++++++++ 2 files changed, 493 insertions(+), 482 deletions(-) create mode 100644 target/mips/vendor-loong-simd_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index ca2e79d955a..745bf9a9dd9 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -639,103 +639,6 @@ enum { OPC_BC2NEZ = (0x0D << 21) | OPC_CP2, }; -#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F)) - -enum { - OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2, - OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2, - OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2, - OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2, - OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2, - OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2, - OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2, - OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2, - - OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2, - OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2, - OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2, - OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2, - OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2, - OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2, - OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2, - OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2, - - OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2, - OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2, - OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2, - OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2, - OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2, - OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2, - OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2, - OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2, - - OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2, - OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2, - OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2, - OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2, - OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2, - OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2, - OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2, - OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2, - - OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2, - OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2, - OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2, - OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2, - OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2, - OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2, - - OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2, - OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2, - OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2, - OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2, - OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2, - OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2, - - OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2, - OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2, - OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2, - OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2, - OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2, - OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2, - - OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2, - OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2, - OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2, - OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2, - OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2, - OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2, - - OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2, - OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2, - OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2, - OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2, - OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2, - OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2, - - OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2, - OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2, - OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2, - OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2, - OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2, - OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2, - - OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2, - OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2, - OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2, - OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2, - OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2, - OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2, - - OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2, - OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2, - OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2, - OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2, - OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2, - OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2, -}; - - #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F)) enum { @@ -4768,391 +4671,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } -/* Loongson multimedia instructions */ -static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) -{ - uint32_t opc, shift_max; - TCGv_i64 t0, t1; - TCGCond cond; - - opc = MASK_LMMI(ctx->opcode); - switch (opc) { - case OPC_ADD_CP2: - case OPC_SUB_CP2: - case OPC_DADD_CP2: - case OPC_DSUB_CP2: - t0 = tcg_temp_local_new_i64(); - t1 = tcg_temp_local_new_i64(); - break; - default: - t0 = tcg_temp_new_i64(); - t1 = tcg_temp_new_i64(); - break; - } - - check_cp1_enabled(ctx); - gen_load_fpr64(ctx, t0, rs); - gen_load_fpr64(ctx, t1, rt); - - switch (opc) { - case OPC_PADDSH: - gen_helper_paddsh(t0, t0, t1); - break; - case OPC_PADDUSH: - gen_helper_paddush(t0, t0, t1); - break; - case OPC_PADDH: - gen_helper_paddh(t0, t0, t1); - break; - case OPC_PADDW: - gen_helper_paddw(t0, t0, t1); - break; - case OPC_PADDSB: - gen_helper_paddsb(t0, t0, t1); - break; - case OPC_PADDUSB: - gen_helper_paddusb(t0, t0, t1); - break; - case OPC_PADDB: - gen_helper_paddb(t0, t0, t1); - break; - - case OPC_PSUBSH: - gen_helper_psubsh(t0, t0, t1); - break; - case OPC_PSUBUSH: - gen_helper_psubush(t0, t0, t1); - break; - case OPC_PSUBH: - gen_helper_psubh(t0, t0, t1); - break; - case OPC_PSUBW: - gen_helper_psubw(t0, t0, t1); - break; - case OPC_PSUBSB: - gen_helper_psubsb(t0, t0, t1); - break; - case OPC_PSUBUSB: - gen_helper_psubusb(t0, t0, t1); - break; - case OPC_PSUBB: - gen_helper_psubb(t0, t0, t1); - break; - - case OPC_PSHUFH: - gen_helper_pshufh(t0, t0, t1); - break; - case OPC_PACKSSWH: - gen_helper_packsswh(t0, t0, t1); - break; - case OPC_PACKSSHB: - gen_helper_packsshb(t0, t0, t1); - break; - case OPC_PACKUSHB: - gen_helper_packushb(t0, t0, t1); - break; - - case OPC_PUNPCKLHW: - gen_helper_punpcklhw(t0, t0, t1); - break; - case OPC_PUNPCKHHW: - gen_helper_punpckhhw(t0, t0, t1); - break; - case OPC_PUNPCKLBH: - gen_helper_punpcklbh(t0, t0, t1); - break; - case OPC_PUNPCKHBH: - gen_helper_punpckhbh(t0, t0, t1); - break; - case OPC_PUNPCKLWD: - gen_helper_punpcklwd(t0, t0, t1); - break; - case OPC_PUNPCKHWD: - gen_helper_punpckhwd(t0, t0, t1); - break; - - case OPC_PAVGH: - gen_helper_pavgh(t0, t0, t1); - break; - case OPC_PAVGB: - gen_helper_pavgb(t0, t0, t1); - break; - case OPC_PMAXSH: - gen_helper_pmaxsh(t0, t0, t1); - break; - case OPC_PMINSH: - gen_helper_pminsh(t0, t0, t1); - break; - case OPC_PMAXUB: - gen_helper_pmaxub(t0, t0, t1); - break; - case OPC_PMINUB: - gen_helper_pminub(t0, t0, t1); - break; - - case OPC_PCMPEQW: - gen_helper_pcmpeqw(t0, t0, t1); - break; - case OPC_PCMPGTW: - gen_helper_pcmpgtw(t0, t0, t1); - break; - case OPC_PCMPEQH: - gen_helper_pcmpeqh(t0, t0, t1); - break; - case OPC_PCMPGTH: - gen_helper_pcmpgth(t0, t0, t1); - break; - case OPC_PCMPEQB: - gen_helper_pcmpeqb(t0, t0, t1); - break; - case OPC_PCMPGTB: - gen_helper_pcmpgtb(t0, t0, t1); - break; - - case OPC_PSLLW: - gen_helper_psllw(t0, t0, t1); - break; - case OPC_PSLLH: - gen_helper_psllh(t0, t0, t1); - break; - case OPC_PSRLW: - gen_helper_psrlw(t0, t0, t1); - break; - case OPC_PSRLH: - gen_helper_psrlh(t0, t0, t1); - break; - case OPC_PSRAW: - gen_helper_psraw(t0, t0, t1); - break; - case OPC_PSRAH: - gen_helper_psrah(t0, t0, t1); - break; - - case OPC_PMULLH: - gen_helper_pmullh(t0, t0, t1); - break; - case OPC_PMULHH: - gen_helper_pmulhh(t0, t0, t1); - break; - case OPC_PMULHUH: - gen_helper_pmulhuh(t0, t0, t1); - break; - case OPC_PMADDHW: - gen_helper_pmaddhw(t0, t0, t1); - break; - - case OPC_PASUBUB: - gen_helper_pasubub(t0, t0, t1); - break; - case OPC_BIADD: - gen_helper_biadd(t0, t0); - break; - case OPC_PMOVMSKB: - gen_helper_pmovmskb(t0, t0); - break; - - case OPC_PADDD: - tcg_gen_add_i64(t0, t0, t1); - break; - case OPC_PSUBD: - tcg_gen_sub_i64(t0, t0, t1); - break; - case OPC_XOR_CP2: - tcg_gen_xor_i64(t0, t0, t1); - break; - case OPC_NOR_CP2: - tcg_gen_nor_i64(t0, t0, t1); - break; - case OPC_AND_CP2: - tcg_gen_and_i64(t0, t0, t1); - break; - case OPC_OR_CP2: - tcg_gen_or_i64(t0, t0, t1); - break; - - case OPC_PANDN: - tcg_gen_andc_i64(t0, t1, t0); - break; - - case OPC_PINSRH_0: - tcg_gen_deposit_i64(t0, t0, t1, 0, 16); - break; - case OPC_PINSRH_1: - tcg_gen_deposit_i64(t0, t0, t1, 16, 16); - break; - case OPC_PINSRH_2: - tcg_gen_deposit_i64(t0, t0, t1, 32, 16); - break; - case OPC_PINSRH_3: - tcg_gen_deposit_i64(t0, t0, t1, 48, 16); - break; - - case OPC_PEXTRH: - tcg_gen_andi_i64(t1, t1, 3); - tcg_gen_shli_i64(t1, t1, 4); - tcg_gen_shr_i64(t0, t0, t1); - tcg_gen_ext16u_i64(t0, t0); - break; - - case OPC_ADDU_CP2: - tcg_gen_add_i64(t0, t0, t1); - tcg_gen_ext32s_i64(t0, t0); - break; - case OPC_SUBU_CP2: - tcg_gen_sub_i64(t0, t0, t1); - tcg_gen_ext32s_i64(t0, t0); - break; - - case OPC_SLL_CP2: - shift_max = 32; - goto do_shift; - case OPC_SRL_CP2: - shift_max = 32; - goto do_shift; - case OPC_SRA_CP2: - shift_max = 32; - goto do_shift; - case OPC_DSLL_CP2: - shift_max = 64; - goto do_shift; - case OPC_DSRL_CP2: - shift_max = 64; - goto do_shift; - case OPC_DSRA_CP2: - shift_max = 64; - goto do_shift; - do_shift: - /* Make sure shift count isn't TCG undefined behaviour. */ - tcg_gen_andi_i64(t1, t1, shift_max - 1); - - switch (opc) { - case OPC_SLL_CP2: - case OPC_DSLL_CP2: - tcg_gen_shl_i64(t0, t0, t1); - break; - case OPC_SRA_CP2: - case OPC_DSRA_CP2: - /* - * Since SRA is UndefinedResult without sign-extended inputs, - * we can treat SRA and DSRA the same. - */ - tcg_gen_sar_i64(t0, t0, t1); - break; - case OPC_SRL_CP2: - /* We want to shift in zeros for SRL; zero-extend first. */ - tcg_gen_ext32u_i64(t0, t0); - /* FALLTHRU */ - case OPC_DSRL_CP2: - tcg_gen_shr_i64(t0, t0, t1); - break; - } - - if (shift_max == 32) { - tcg_gen_ext32s_i64(t0, t0); - } - - /* Shifts larger than MAX produce zero. */ - tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max); - tcg_gen_neg_i64(t1, t1); - tcg_gen_and_i64(t0, t0, t1); - break; - - case OPC_ADD_CP2: - case OPC_DADD_CP2: - { - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGLabel *lab = gen_new_label(); - - tcg_gen_mov_i64(t2, t0); - tcg_gen_add_i64(t0, t1, t2); - if (opc == OPC_ADD_CP2) { - tcg_gen_ext32s_i64(t0, t0); - } - tcg_gen_xor_i64(t1, t1, t2); - tcg_gen_xor_i64(t2, t2, t0); - tcg_gen_andc_i64(t1, t2, t1); - tcg_temp_free_i64(t2); - tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab); - generate_exception(ctx, EXCP_OVERFLOW); - gen_set_label(lab); - break; - } - - case OPC_SUB_CP2: - case OPC_DSUB_CP2: - { - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGLabel *lab = gen_new_label(); - - tcg_gen_mov_i64(t2, t0); - tcg_gen_sub_i64(t0, t1, t2); - if (opc == OPC_SUB_CP2) { - tcg_gen_ext32s_i64(t0, t0); - } - tcg_gen_xor_i64(t1, t1, t2); - tcg_gen_xor_i64(t2, t2, t0); - tcg_gen_and_i64(t1, t1, t2); - tcg_temp_free_i64(t2); - tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab); - generate_exception(ctx, EXCP_OVERFLOW); - gen_set_label(lab); - break; - } - - case OPC_PMULUW: - tcg_gen_ext32u_i64(t0, t0); - tcg_gen_ext32u_i64(t1, t1); - tcg_gen_mul_i64(t0, t0, t1); - break; - - case OPC_SEQU_CP2: - case OPC_SEQ_CP2: - cond = TCG_COND_EQ; - goto do_cc_cond; - break; - case OPC_SLTU_CP2: - cond = TCG_COND_LTU; - goto do_cc_cond; - break; - case OPC_SLT_CP2: - cond = TCG_COND_LT; - goto do_cc_cond; - break; - case OPC_SLEU_CP2: - cond = TCG_COND_LEU; - goto do_cc_cond; - break; - case OPC_SLE_CP2: - cond = TCG_COND_LE; - do_cc_cond: - { - int cc = (ctx->opcode >> 8) & 0x7; - TCGv_i64 t64 = tcg_temp_new_i64(); - TCGv_i32 t32 = tcg_temp_new_i32(); - - tcg_gen_setcond_i64(cond, t64, t0, t1); - tcg_gen_extrl_i64_i32(t32, t64); - tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32, - get_fp_bit(cc), 1); - - tcg_temp_free_i32(t32); - tcg_temp_free_i64(t64); - } - goto no_rd; - break; - default: - MIPS_INVAL("loongson_cp2"); - generate_exception_end(ctx, EXCP_RI); - return; - } - - gen_store_fpr64(ctx, t0, rd); - -no_rd: - tcg_temp_free_i64(t0); - tcg_temp_free_i64(t1); -} - static void gen_loongson_lswc2(DisasContext *ctx, int rt, int rs, int rd) { @@ -12939,6 +12457,7 @@ out: #include "mod-dsp_translate.c.inc" #include "vendor-vr54xx_translate.c.inc" +#include "vendor-loong-simd_translate.c.inc" static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) { diff --git a/target/mips/vendor-loong-simd_translate.c.inc b/target/mips/vendor-loong-simd_translate.c.inc new file mode 100644 index 00000000000..85b1de6c28a --- /dev/null +++ b/target/mips/vendor-loong-simd_translate.c.inc @@ -0,0 +1,492 @@ +/* + * Loongson SIMD translation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2011 Richard Henderson + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F)) + +/* Loongson multimedia instructions */ +enum { + OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2, + OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2, + OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2, + OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2, + OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2, + OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2, + OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2, + OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2, + + OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2, + OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2, + OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2, + OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2, + OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2, + OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2, + OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2, + OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2, + + OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2, + OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2, + OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2, + OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2, + OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2, + OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2, + OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2, + OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2, + + OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2, + OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2, + OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2, + OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2, + OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2, + OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2, + OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2, + OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2, + + OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2, + OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2, + OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2, + OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2, + OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2, + OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2, + + OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2, + OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2, + OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2, + OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2, + OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2, + OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2, + + OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2, + OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2, + OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2, + OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2, + OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2, + OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2, + + OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2, + OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2, + OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2, + OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2, + OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2, + OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2, + + OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2, + OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2, + OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2, + OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2, + OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2, + OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2, + + OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2, + OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2, + OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2, + OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2, + OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2, + OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2, + + OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2, + OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2, + OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2, + OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2, + OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2, + OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2, + + OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2, + OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2, + OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2, + OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2, + OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2, + OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2, +}; + +static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) +{ + uint32_t opc, shift_max; + TCGv_i64 t0, t1; + TCGCond cond; + + opc = MASK_LMMI(ctx->opcode); + switch (opc) { + case OPC_ADD_CP2: + case OPC_SUB_CP2: + case OPC_DADD_CP2: + case OPC_DSUB_CP2: + t0 = tcg_temp_local_new_i64(); + t1 = tcg_temp_local_new_i64(); + break; + default: + t0 = tcg_temp_new_i64(); + t1 = tcg_temp_new_i64(); + break; + } + + check_cp1_enabled(ctx); + gen_load_fpr64(ctx, t0, rs); + gen_load_fpr64(ctx, t1, rt); + + switch (opc) { + case OPC_PADDSH: + gen_helper_paddsh(t0, t0, t1); + break; + case OPC_PADDUSH: + gen_helper_paddush(t0, t0, t1); + break; + case OPC_PADDH: + gen_helper_paddh(t0, t0, t1); + break; + case OPC_PADDW: + gen_helper_paddw(t0, t0, t1); + break; + case OPC_PADDSB: + gen_helper_paddsb(t0, t0, t1); + break; + case OPC_PADDUSB: + gen_helper_paddusb(t0, t0, t1); + break; + case OPC_PADDB: + gen_helper_paddb(t0, t0, t1); + break; + + case OPC_PSUBSH: + gen_helper_psubsh(t0, t0, t1); + break; + case OPC_PSUBUSH: + gen_helper_psubush(t0, t0, t1); + break; + case OPC_PSUBH: + gen_helper_psubh(t0, t0, t1); + break; + case OPC_PSUBW: + gen_helper_psubw(t0, t0, t1); + break; + case OPC_PSUBSB: + gen_helper_psubsb(t0, t0, t1); + break; + case OPC_PSUBUSB: + gen_helper_psubusb(t0, t0, t1); + break; + case OPC_PSUBB: + gen_helper_psubb(t0, t0, t1); + break; + + case OPC_PSHUFH: + gen_helper_pshufh(t0, t0, t1); + break; + case OPC_PACKSSWH: + gen_helper_packsswh(t0, t0, t1); + break; + case OPC_PACKSSHB: + gen_helper_packsshb(t0, t0, t1); + break; + case OPC_PACKUSHB: + gen_helper_packushb(t0, t0, t1); + break; + + case OPC_PUNPCKLHW: + gen_helper_punpcklhw(t0, t0, t1); + break; + case OPC_PUNPCKHHW: + gen_helper_punpckhhw(t0, t0, t1); + break; + case OPC_PUNPCKLBH: + gen_helper_punpcklbh(t0, t0, t1); + break; + case OPC_PUNPCKHBH: + gen_helper_punpckhbh(t0, t0, t1); + break; + case OPC_PUNPCKLWD: + gen_helper_punpcklwd(t0, t0, t1); + break; + case OPC_PUNPCKHWD: + gen_helper_punpckhwd(t0, t0, t1); + break; + + case OPC_PAVGH: + gen_helper_pavgh(t0, t0, t1); + break; + case OPC_PAVGB: + gen_helper_pavgb(t0, t0, t1); + break; + case OPC_PMAXSH: + gen_helper_pmaxsh(t0, t0, t1); + break; + case OPC_PMINSH: + gen_helper_pminsh(t0, t0, t1); + break; + case OPC_PMAXUB: + gen_helper_pmaxub(t0, t0, t1); + break; + case OPC_PMINUB: + gen_helper_pminub(t0, t0, t1); + break; + + case OPC_PCMPEQW: + gen_helper_pcmpeqw(t0, t0, t1); + break; + case OPC_PCMPGTW: + gen_helper_pcmpgtw(t0, t0, t1); + break; + case OPC_PCMPEQH: + gen_helper_pcmpeqh(t0, t0, t1); + break; + case OPC_PCMPGTH: + gen_helper_pcmpgth(t0, t0, t1); + break; + case OPC_PCMPEQB: + gen_helper_pcmpeqb(t0, t0, t1); + break; + case OPC_PCMPGTB: + gen_helper_pcmpgtb(t0, t0, t1); + break; + + case OPC_PSLLW: + gen_helper_psllw(t0, t0, t1); + break; + case OPC_PSLLH: + gen_helper_psllh(t0, t0, t1); + break; + case OPC_PSRLW: + gen_helper_psrlw(t0, t0, t1); + break; + case OPC_PSRLH: + gen_helper_psrlh(t0, t0, t1); + break; + case OPC_PSRAW: + gen_helper_psraw(t0, t0, t1); + break; + case OPC_PSRAH: + gen_helper_psrah(t0, t0, t1); + break; + + case OPC_PMULLH: + gen_helper_pmullh(t0, t0, t1); + break; + case OPC_PMULHH: + gen_helper_pmulhh(t0, t0, t1); + break; + case OPC_PMULHUH: + gen_helper_pmulhuh(t0, t0, t1); + break; + case OPC_PMADDHW: + gen_helper_pmaddhw(t0, t0, t1); + break; + + case OPC_PASUBUB: + gen_helper_pasubub(t0, t0, t1); + break; + case OPC_BIADD: + gen_helper_biadd(t0, t0); + break; + case OPC_PMOVMSKB: + gen_helper_pmovmskb(t0, t0); + break; + + case OPC_PADDD: + tcg_gen_add_i64(t0, t0, t1); + break; + case OPC_PSUBD: + tcg_gen_sub_i64(t0, t0, t1); + break; + case OPC_XOR_CP2: + tcg_gen_xor_i64(t0, t0, t1); + break; + case OPC_NOR_CP2: + tcg_gen_nor_i64(t0, t0, t1); + break; + case OPC_AND_CP2: + tcg_gen_and_i64(t0, t0, t1); + break; + case OPC_OR_CP2: + tcg_gen_or_i64(t0, t0, t1); + break; + + case OPC_PANDN: + tcg_gen_andc_i64(t0, t1, t0); + break; + + case OPC_PINSRH_0: + tcg_gen_deposit_i64(t0, t0, t1, 0, 16); + break; + case OPC_PINSRH_1: + tcg_gen_deposit_i64(t0, t0, t1, 16, 16); + break; + case OPC_PINSRH_2: + tcg_gen_deposit_i64(t0, t0, t1, 32, 16); + break; + case OPC_PINSRH_3: + tcg_gen_deposit_i64(t0, t0, t1, 48, 16); + break; + + case OPC_PEXTRH: + tcg_gen_andi_i64(t1, t1, 3); + tcg_gen_shli_i64(t1, t1, 4); + tcg_gen_shr_i64(t0, t0, t1); + tcg_gen_ext16u_i64(t0, t0); + break; + + case OPC_ADDU_CP2: + tcg_gen_add_i64(t0, t0, t1); + tcg_gen_ext32s_i64(t0, t0); + break; + case OPC_SUBU_CP2: + tcg_gen_sub_i64(t0, t0, t1); + tcg_gen_ext32s_i64(t0, t0); + break; + + case OPC_SLL_CP2: + shift_max = 32; + goto do_shift; + case OPC_SRL_CP2: + shift_max = 32; + goto do_shift; + case OPC_SRA_CP2: + shift_max = 32; + goto do_shift; + case OPC_DSLL_CP2: + shift_max = 64; + goto do_shift; + case OPC_DSRL_CP2: + shift_max = 64; + goto do_shift; + case OPC_DSRA_CP2: + shift_max = 64; + goto do_shift; + do_shift: + /* Make sure shift count isn't TCG undefined behaviour. */ + tcg_gen_andi_i64(t1, t1, shift_max - 1); + + switch (opc) { + case OPC_SLL_CP2: + case OPC_DSLL_CP2: + tcg_gen_shl_i64(t0, t0, t1); + break; + case OPC_SRA_CP2: + case OPC_DSRA_CP2: + /* + * Since SRA is UndefinedResult without sign-extended inputs, + * we can treat SRA and DSRA the same. + */ + tcg_gen_sar_i64(t0, t0, t1); + break; + case OPC_SRL_CP2: + /* We want to shift in zeros for SRL; zero-extend first. */ + tcg_gen_ext32u_i64(t0, t0); + /* FALLTHRU */ + case OPC_DSRL_CP2: + tcg_gen_shr_i64(t0, t0, t1); + break; + } + + if (shift_max == 32) { + tcg_gen_ext32s_i64(t0, t0); + } + + /* Shifts larger than MAX produce zero. */ + tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max); + tcg_gen_neg_i64(t1, t1); + tcg_gen_and_i64(t0, t0, t1); + break; + + case OPC_ADD_CP2: + case OPC_DADD_CP2: + { + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGLabel *lab = gen_new_label(); + + tcg_gen_mov_i64(t2, t0); + tcg_gen_add_i64(t0, t1, t2); + if (opc == OPC_ADD_CP2) { + tcg_gen_ext32s_i64(t0, t0); + } + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_xor_i64(t2, t2, t0); + tcg_gen_andc_i64(t1, t2, t1); + tcg_temp_free_i64(t2); + tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab); + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(lab); + break; + } + + case OPC_SUB_CP2: + case OPC_DSUB_CP2: + { + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGLabel *lab = gen_new_label(); + + tcg_gen_mov_i64(t2, t0); + tcg_gen_sub_i64(t0, t1, t2); + if (opc == OPC_SUB_CP2) { + tcg_gen_ext32s_i64(t0, t0); + } + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_xor_i64(t2, t2, t0); + tcg_gen_and_i64(t1, t1, t2); + tcg_temp_free_i64(t2); + tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab); + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(lab); + break; + } + + case OPC_PMULUW: + tcg_gen_ext32u_i64(t0, t0); + tcg_gen_ext32u_i64(t1, t1); + tcg_gen_mul_i64(t0, t0, t1); + break; + + case OPC_SEQU_CP2: + case OPC_SEQ_CP2: + cond = TCG_COND_EQ; + goto do_cc_cond; + break; + case OPC_SLTU_CP2: + cond = TCG_COND_LTU; + goto do_cc_cond; + break; + case OPC_SLT_CP2: + cond = TCG_COND_LT; + goto do_cc_cond; + break; + case OPC_SLEU_CP2: + cond = TCG_COND_LEU; + goto do_cc_cond; + break; + case OPC_SLE_CP2: + cond = TCG_COND_LE; + do_cc_cond: + { + int cc = (ctx->opcode >> 8) & 0x7; + TCGv_i64 t64 = tcg_temp_new_i64(); + TCGv_i32 t32 = tcg_temp_new_i32(); + + tcg_gen_setcond_i64(cond, t64, t0, t1); + tcg_gen_extrl_i64_i32(t32, t64); + tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32, + get_fp_bit(cc), 1); + + tcg_temp_free_i32(t32); + tcg_temp_free_i64(t64); + } + goto no_rd; + break; + default: + MIPS_INVAL("loongson_cp2"); + generate_exception_end(ctx, EXCP_RI); + return; + } + + gen_store_fpr64(ctx, t0, rd); + +no_rd: + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); +} From patchwork Mon Nov 23 20:44:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926783 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 1BDE0C2D0E4 for ; Mon, 23 Nov 2020 21:20:02 +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 55BC3206B5 for ; Mon, 23 Nov 2020 21:20:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PqViStls" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 55BC3206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:55268 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJFg-0001kL-B5 for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:20:00 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46938) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjR-0002XY-Cj for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:41 -0500 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]:50286) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjN-0001om-Uc for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:41 -0500 Received: by mail-wm1-x333.google.com with SMTP id c198so628625wmd.0 for ; Mon, 23 Nov 2020 12:46:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wzjpmD/cVMaQhUz0TjxaCicaPXOpKMRCXqJxa9f0/F0=; b=PqViStlsyODrHDB90o69yIo57eKQSUEN/O3mPLEb/Jfp3s7NOxLyMEuQG/b+9A/bTx WhJMyGlPX6leCJvpYOtv8mluVFlFMXF9ekD8gBbnz28U8dUi3dGD3yDy5YoiFZOhZ9uH Hlt4VUFMoYhS2TefCEZzRTs3FcI1KoD0xCPJyzhpgYxNO9IO2KqfhQUX6HVmn+h7Jao0 yEQ7sCiPoLgGt9mYHa3zJzgj00yrhbssGzFO2vYqaYWBCONjn9dPIZaJQzxKnca9qWcD +f+i4iWAzYy9Mepes7omIu0CKdkJJwiHVWDDBAol2oRtig9MxAzArDxPpKY+Np8Imn/b 9DtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=wzjpmD/cVMaQhUz0TjxaCicaPXOpKMRCXqJxa9f0/F0=; b=qrv/0xFEeHA4Ayzo78iTPvie1ntZMN84qmQKL4Zs8UYwO2dAJIVdVP9Pc+L+xe4kHC ODK/iln2I6Bcr+F2g7aZ2mx+cbwiCeQaF9Cj69S1Fccx97EjqtxoTlO/9KQexRx2nA4+ bwwC2CrTtSU4AoTYfoUOG34OMoj/SxoY2AEnuzvC7p5AE0w0BK42tP4BKjUFv36d5R7F mkVZb92NmisBEbeFPAAx+jK+uA6qdY7z5Gqlp7jPrMtG4PfNlElavMSEhbLaLwvPzGIu 59mNj0jblmD+iFzp7qY8fCuwgpb7+b88gVAC95DTni5Ljn/0d93haiVZSa9Uoia8H2g6 Jltw== X-Gm-Message-State: AOAM533L44SJIa2zuYW4LHdHOKia0vRGumFEwya3koEDce8KQXuMDzxa VBTbRoW2MZOweBnQKNRejE1gI9Y+rJ0= X-Google-Smtp-Source: ABdhPJywagLuIpauFc6CBaev1IhkZyzJdSRm67zblB7d/mv9hD4UmAWEC01MLHIBO4w6hlHIYXCMrg== X-Received: by 2002:a1c:a9c4:: with SMTP id s187mr737360wme.180.1606164395071; Mon, 23 Nov 2020 12:46:35 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id c64sm758259wmd.41.2020.11.23.12.46.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:34 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 21/28] target/mips: Extract Loongson EXTensions translation routines Date: Mon, 23 Nov 2020 21:44:41 +0100 Message-Id: <20201123204448.3260804-22-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::333; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x333.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" LoongEXTs are general-purpose extensions from the LoongISA. Extract 650 lines of translation routines to 'vendor-loong-ext_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- target/mips/translate.c | 652 +----------------- target/mips/vendor-loong-ext_translate.c.inc | 665 +++++++++++++++++++ 2 files changed, 666 insertions(+), 651 deletions(-) create mode 100644 target/mips/vendor-loong-ext_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 745bf9a9dd9..90ab84c69a3 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -330,19 +330,6 @@ enum { OPC_MUL = 0x02 | OPC_SPECIAL2, OPC_MSUB = 0x04 | OPC_SPECIAL2, OPC_MSUBU = 0x05 | OPC_SPECIAL2, - /* Loongson 2F */ - OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2, - OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2, - OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2, - OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2, - OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2, - OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2, - OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2, - OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2, - OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2, - OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2, - OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2, - OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2, /* Misc */ OPC_CLZ = 0x20 | OPC_SPECIAL2, OPC_CLO = 0x21 | OPC_SPECIAL2, @@ -412,48 +399,6 @@ enum { R6_OPC_SCD = 0x27 | OPC_SPECIAL3, }; -/* Loongson EXT load/store quad word opcodes */ -#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020)) -enum { - OPC_GSLQ = 0x0020 | OPC_LWC2, - OPC_GSLQC1 = 0x8020 | OPC_LWC2, - OPC_GSSHFL = OPC_LWC2, - OPC_GSSQ = 0x0020 | OPC_SWC2, - OPC_GSSQC1 = 0x8020 | OPC_SWC2, - OPC_GSSHFS = OPC_SWC2, -}; - -/* Loongson EXT shifted load/store opcodes */ -#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f)) -enum { - OPC_GSLWLC1 = 0x4 | OPC_GSSHFL, - OPC_GSLWRC1 = 0x5 | OPC_GSSHFL, - OPC_GSLDLC1 = 0x6 | OPC_GSSHFL, - OPC_GSLDRC1 = 0x7 | OPC_GSSHFL, - OPC_GSSWLC1 = 0x4 | OPC_GSSHFS, - OPC_GSSWRC1 = 0x5 | OPC_GSSHFS, - OPC_GSSDLC1 = 0x6 | OPC_GSSHFS, - OPC_GSSDRC1 = 0x7 | OPC_GSSHFS, -}; - -/* Loongson EXT LDC2/SDC2 opcodes */ -#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7)) - -enum { - OPC_GSLBX = 0x0 | OPC_LDC2, - OPC_GSLHX = 0x1 | OPC_LDC2, - OPC_GSLWX = 0x2 | OPC_LDC2, - OPC_GSLDX = 0x3 | OPC_LDC2, - OPC_GSLWXC1 = 0x6 | OPC_LDC2, - OPC_GSLDXC1 = 0x7 | OPC_LDC2, - OPC_GSSBX = 0x0 | OPC_SDC2, - OPC_GSSHX = 0x1 | OPC_SDC2, - OPC_GSSWX = 0x2 | OPC_SDC2, - OPC_GSSDX = 0x3 | OPC_SDC2, - OPC_GSSWXC1 = 0x6 | OPC_SDC2, - OPC_GSSDXC1 = 0x7 | OPC_SDC2, -}; - /* BSHFL opcodes */ #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -4472,602 +4417,6 @@ static void gen_cl(DisasContext *ctx, uint32_t opc, } } -/* Godson integer instructions */ -static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, - int rd, int rs, int rt) -{ - TCGv t0, t1; - - if (rd == 0) { - /* Treat as NOP. */ - return; - } - - switch (opc) { - case OPC_MULT_G_2E: - case OPC_MULT_G_2F: - case OPC_MULTU_G_2E: - case OPC_MULTU_G_2F: -#if defined(TARGET_MIPS64) - case OPC_DMULT_G_2E: - case OPC_DMULT_G_2F: - case OPC_DMULTU_G_2E: - case OPC_DMULTU_G_2F: -#endif - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - break; - default: - t0 = tcg_temp_local_new(); - t1 = tcg_temp_local_new(); - break; - } - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - - switch (opc) { - case OPC_MULT_G_2E: - case OPC_MULT_G_2F: - tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); - tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); - break; - case OPC_MULTU_G_2E: - case OPC_MULTU_G_2F: - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); - tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); - break; - case OPC_DIV_G_2E: - case OPC_DIV_G_2F: - { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - TCGLabel *l3 = gen_new_label(); - tcg_gen_ext32s_tl(t0, t0); - tcg_gen_ext32s_tl(t1, t1); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); - tcg_gen_movi_tl(cpu_gpr[rd], 0); - tcg_gen_br(l3); - gen_set_label(l1); - tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); - tcg_gen_mov_tl(cpu_gpr[rd], t0); - tcg_gen_br(l3); - gen_set_label(l2); - tcg_gen_div_tl(cpu_gpr[rd], t0, t1); - tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); - gen_set_label(l3); - } - break; - case OPC_DIVU_G_2E: - case OPC_DIVU_G_2F: - { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); - tcg_gen_movi_tl(cpu_gpr[rd], 0); - tcg_gen_br(l2); - gen_set_label(l1); - tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); - tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); - gen_set_label(l2); - } - break; - case OPC_MOD_G_2E: - case OPC_MOD_G_2F: - { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - TCGLabel *l3 = gen_new_label(); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); - tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); - gen_set_label(l1); - tcg_gen_movi_tl(cpu_gpr[rd], 0); - tcg_gen_br(l3); - gen_set_label(l2); - tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); - tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); - gen_set_label(l3); - } - break; - case OPC_MODU_G_2E: - case OPC_MODU_G_2F: - { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); - tcg_gen_movi_tl(cpu_gpr[rd], 0); - tcg_gen_br(l2); - gen_set_label(l1); - tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); - tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); - gen_set_label(l2); - } - break; -#if defined(TARGET_MIPS64) - case OPC_DMULT_G_2E: - case OPC_DMULT_G_2F: - tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); - break; - case OPC_DMULTU_G_2E: - case OPC_DMULTU_G_2F: - tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); - break; - case OPC_DDIV_G_2E: - case OPC_DDIV_G_2F: - { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - TCGLabel *l3 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); - tcg_gen_movi_tl(cpu_gpr[rd], 0); - tcg_gen_br(l3); - gen_set_label(l1); - tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); - tcg_gen_mov_tl(cpu_gpr[rd], t0); - tcg_gen_br(l3); - gen_set_label(l2); - tcg_gen_div_tl(cpu_gpr[rd], t0, t1); - gen_set_label(l3); - } - break; - case OPC_DDIVU_G_2E: - case OPC_DDIVU_G_2F: - { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); - tcg_gen_movi_tl(cpu_gpr[rd], 0); - tcg_gen_br(l2); - gen_set_label(l1); - tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); - gen_set_label(l2); - } - break; - case OPC_DMOD_G_2E: - case OPC_DMOD_G_2F: - { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - TCGLabel *l3 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); - tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); - gen_set_label(l1); - tcg_gen_movi_tl(cpu_gpr[rd], 0); - tcg_gen_br(l3); - gen_set_label(l2); - tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); - gen_set_label(l3); - } - break; - case OPC_DMODU_G_2E: - case OPC_DMODU_G_2F: - { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); - tcg_gen_movi_tl(cpu_gpr[rd], 0); - tcg_gen_br(l2); - gen_set_label(l1); - tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); - gen_set_label(l2); - } - break; -#endif - } - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -static void gen_loongson_lswc2(DisasContext *ctx, int rt, - int rs, int rd) -{ - TCGv t0, t1, t2; - TCGv_i32 fp0; -#if defined(TARGET_MIPS64) - int lsq_rt1 = ctx->opcode & 0x1f; - int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4; -#endif - int shf_offset = sextract32(ctx->opcode, 6, 8); - - t0 = tcg_temp_new(); - - switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) { -#if defined(TARGET_MIPS64) - case OPC_GSLQ: - t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t0, rs, lsq_offset); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - gen_store_gpr(t1, rt); - gen_store_gpr(t0, lsq_rt1); - tcg_temp_free(t1); - break; - case OPC_GSLQC1: - check_cp1_enabled(ctx); - t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t0, rs, lsq_offset); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - gen_store_fpr64(ctx, t1, rt); - gen_store_fpr64(ctx, t0, lsq_rt1); - tcg_temp_free(t1); - break; - case OPC_GSSQ: - t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t0, rs, lsq_offset); - gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); - gen_load_gpr(t1, lsq_rt1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - tcg_temp_free(t1); - break; - case OPC_GSSQC1: - check_cp1_enabled(ctx); - t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t0, rs, lsq_offset); - gen_load_fpr64(ctx, t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); - gen_load_fpr64(ctx, t1, lsq_rt1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - tcg_temp_free(t1); - break; -#endif - case OPC_GSSHFL: - switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { - case OPC_GSLWLC1: - check_cp1_enabled(ctx); - gen_base_offset_addr(ctx, t0, rs, shf_offset); - t1 = tcg_temp_new(); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_andi_tl(t1, t0, 3); -#ifndef TARGET_WORDS_BIGENDIAN - tcg_gen_xori_tl(t1, t1, 3); -#endif - tcg_gen_shli_tl(t1, t1, 3); - tcg_gen_andi_tl(t0, t0, ~3); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); - tcg_gen_shl_tl(t0, t0, t1); - t2 = tcg_const_tl(-1); - tcg_gen_shl_tl(t2, t2, t1); - fp0 = tcg_temp_new_i32(); - gen_load_fpr32(ctx, fp0, rt); - tcg_gen_ext_i32_tl(t1, fp0); - tcg_gen_andc_tl(t1, t1, t2); - tcg_temp_free(t2); - tcg_gen_or_tl(t0, t0, t1); - tcg_temp_free(t1); -#if defined(TARGET_MIPS64) - tcg_gen_extrl_i64_i32(fp0, t0); -#else - tcg_gen_ext32s_tl(fp0, t0); -#endif - gen_store_fpr32(ctx, fp0, rt); - tcg_temp_free_i32(fp0); - break; - case OPC_GSLWRC1: - check_cp1_enabled(ctx); - gen_base_offset_addr(ctx, t0, rs, shf_offset); - t1 = tcg_temp_new(); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_andi_tl(t1, t0, 3); -#ifdef TARGET_WORDS_BIGENDIAN - tcg_gen_xori_tl(t1, t1, 3); -#endif - tcg_gen_shli_tl(t1, t1, 3); - tcg_gen_andi_tl(t0, t0, ~3); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); - tcg_gen_shr_tl(t0, t0, t1); - tcg_gen_xori_tl(t1, t1, 31); - t2 = tcg_const_tl(0xfffffffeull); - tcg_gen_shl_tl(t2, t2, t1); - fp0 = tcg_temp_new_i32(); - gen_load_fpr32(ctx, fp0, rt); - tcg_gen_ext_i32_tl(t1, fp0); - tcg_gen_and_tl(t1, t1, t2); - tcg_temp_free(t2); - tcg_gen_or_tl(t0, t0, t1); - tcg_temp_free(t1); -#if defined(TARGET_MIPS64) - tcg_gen_extrl_i64_i32(fp0, t0); -#else - tcg_gen_ext32s_tl(fp0, t0); -#endif - gen_store_fpr32(ctx, fp0, rt); - tcg_temp_free_i32(fp0); - break; -#if defined(TARGET_MIPS64) - case OPC_GSLDLC1: - check_cp1_enabled(ctx); - gen_base_offset_addr(ctx, t0, rs, shf_offset); - t1 = tcg_temp_new(); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_andi_tl(t1, t0, 7); -#ifndef TARGET_WORDS_BIGENDIAN - tcg_gen_xori_tl(t1, t1, 7); -#endif - tcg_gen_shli_tl(t1, t1, 3); - tcg_gen_andi_tl(t0, t0, ~7); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); - tcg_gen_shl_tl(t0, t0, t1); - t2 = tcg_const_tl(-1); - tcg_gen_shl_tl(t2, t2, t1); - gen_load_fpr64(ctx, t1, rt); - tcg_gen_andc_tl(t1, t1, t2); - tcg_temp_free(t2); - tcg_gen_or_tl(t0, t0, t1); - tcg_temp_free(t1); - gen_store_fpr64(ctx, t0, rt); - break; - case OPC_GSLDRC1: - check_cp1_enabled(ctx); - gen_base_offset_addr(ctx, t0, rs, shf_offset); - t1 = tcg_temp_new(); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_andi_tl(t1, t0, 7); -#ifdef TARGET_WORDS_BIGENDIAN - tcg_gen_xori_tl(t1, t1, 7); -#endif - tcg_gen_shli_tl(t1, t1, 3); - tcg_gen_andi_tl(t0, t0, ~7); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); - tcg_gen_shr_tl(t0, t0, t1); - tcg_gen_xori_tl(t1, t1, 63); - t2 = tcg_const_tl(0xfffffffffffffffeull); - tcg_gen_shl_tl(t2, t2, t1); - gen_load_fpr64(ctx, t1, rt); - tcg_gen_and_tl(t1, t1, t2); - tcg_temp_free(t2); - tcg_gen_or_tl(t0, t0, t1); - tcg_temp_free(t1); - gen_store_fpr64(ctx, t0, rt); - break; -#endif - default: - MIPS_INVAL("loongson_gsshfl"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - case OPC_GSSHFS: - switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { - case OPC_GSSWLC1: - check_cp1_enabled(ctx); - t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t0, rs, shf_offset); - fp0 = tcg_temp_new_i32(); - gen_load_fpr32(ctx, fp0, rt); - tcg_gen_ext_i32_tl(t1, fp0); - gen_helper_0e2i(swl, t1, t0, ctx->mem_idx); - tcg_temp_free_i32(fp0); - tcg_temp_free(t1); - break; - case OPC_GSSWRC1: - check_cp1_enabled(ctx); - t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t0, rs, shf_offset); - fp0 = tcg_temp_new_i32(); - gen_load_fpr32(ctx, fp0, rt); - tcg_gen_ext_i32_tl(t1, fp0); - gen_helper_0e2i(swr, t1, t0, ctx->mem_idx); - tcg_temp_free_i32(fp0); - tcg_temp_free(t1); - break; -#if defined(TARGET_MIPS64) - case OPC_GSSDLC1: - check_cp1_enabled(ctx); - t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t0, rs, shf_offset); - gen_load_fpr64(ctx, t1, rt); - gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx); - tcg_temp_free(t1); - break; - case OPC_GSSDRC1: - check_cp1_enabled(ctx); - t1 = tcg_temp_new(); - gen_base_offset_addr(ctx, t0, rs, shf_offset); - gen_load_fpr64(ctx, t1, rt); - gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx); - tcg_temp_free(t1); - break; -#endif - default: - MIPS_INVAL("loongson_gsshfs"); - generate_exception_end(ctx, EXCP_RI); - break; - } - break; - default: - MIPS_INVAL("loongson_gslsq"); - generate_exception_end(ctx, EXCP_RI); - break; - } - tcg_temp_free(t0); -} - -/* Loongson EXT LDC2/SDC2 */ -static void gen_loongson_lsdc2(DisasContext *ctx, int rt, - int rs, int rd) -{ - int offset = sextract32(ctx->opcode, 3, 8); - uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode); - TCGv t0, t1; - TCGv_i32 fp0; - - /* Pre-conditions */ - switch (opc) { - case OPC_GSLBX: - case OPC_GSLHX: - case OPC_GSLWX: - case OPC_GSLDX: - /* prefetch, implement as NOP */ - if (rt == 0) { - return; - } - break; - case OPC_GSSBX: - case OPC_GSSHX: - case OPC_GSSWX: - case OPC_GSSDX: - break; - case OPC_GSLWXC1: -#if defined(TARGET_MIPS64) - case OPC_GSLDXC1: -#endif - check_cp1_enabled(ctx); - /* prefetch, implement as NOP */ - if (rt == 0) { - return; - } - break; - case OPC_GSSWXC1: -#if defined(TARGET_MIPS64) - case OPC_GSSDXC1: -#endif - check_cp1_enabled(ctx); - break; - default: - MIPS_INVAL("loongson_lsdc2"); - generate_exception_end(ctx, EXCP_RI); - return; - break; - } - - t0 = tcg_temp_new(); - - gen_base_offset_addr(ctx, t0, rs, offset); - gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); - - switch (opc) { - case OPC_GSLBX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB); - gen_store_gpr(t0, rt); - break; - case OPC_GSLHX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | - ctx->default_tcg_memop_mask); - gen_store_gpr(t0, rt); - break; - case OPC_GSLWX: - gen_base_offset_addr(ctx, t0, rs, offset); - if (rd) { - gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); - } - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL | - ctx->default_tcg_memop_mask); - gen_store_gpr(t0, rt); - break; -#if defined(TARGET_MIPS64) - case OPC_GSLDX: - gen_base_offset_addr(ctx, t0, rs, offset); - if (rd) { - gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); - } - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - gen_store_gpr(t0, rt); - break; -#endif - case OPC_GSLWXC1: - check_cp1_enabled(ctx); - gen_base_offset_addr(ctx, t0, rs, offset); - if (rd) { - gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); - } - fp0 = tcg_temp_new_i32(); - tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL | - ctx->default_tcg_memop_mask); - gen_store_fpr32(ctx, fp0, rt); - tcg_temp_free_i32(fp0); - break; -#if defined(TARGET_MIPS64) - case OPC_GSLDXC1: - check_cp1_enabled(ctx); - gen_base_offset_addr(ctx, t0, rs, offset); - if (rd) { - gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); - } - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - gen_store_fpr64(ctx, t0, rt); - break; -#endif - case OPC_GSSBX: - t1 = tcg_temp_new(); - gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB); - tcg_temp_free(t1); - break; - case OPC_GSSHX: - t1 = tcg_temp_new(); - gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | - ctx->default_tcg_memop_mask); - tcg_temp_free(t1); - break; - case OPC_GSSWX: - t1 = tcg_temp_new(); - gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL | - ctx->default_tcg_memop_mask); - tcg_temp_free(t1); - break; -#if defined(TARGET_MIPS64) - case OPC_GSSDX: - t1 = tcg_temp_new(); - gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - tcg_temp_free(t1); - break; -#endif - case OPC_GSSWXC1: - fp0 = tcg_temp_new_i32(); - gen_load_fpr32(ctx, fp0, rt); - tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL | - ctx->default_tcg_memop_mask); - tcg_temp_free_i32(fp0); - break; -#if defined(TARGET_MIPS64) - case OPC_GSSDXC1: - t1 = tcg_temp_new(); - gen_load_fpr64(ctx, t1, rt); - tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); - tcg_temp_free(t1); - break; -#endif - default: - break; - } - - tcg_temp_free(t0); -} - /* Traps */ static void gen_trap(DisasContext *ctx, uint32_t opc, int rs, int rt, int16_t imm) @@ -12458,6 +11807,7 @@ out: #include "vendor-vr54xx_translate.c.inc" #include "vendor-loong-simd_translate.c.inc" +#include "vendor-loong-ext_translate.c.inc" static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) { diff --git a/target/mips/vendor-loong-ext_translate.c.inc b/target/mips/vendor-loong-ext_translate.c.inc new file mode 100644 index 00000000000..824a3994d16 --- /dev/null +++ b/target/mips/vendor-loong-ext_translate.c.inc @@ -0,0 +1,665 @@ +/* + * Loongson EXTensions translation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +enum { + /* Loongson 2F */ + OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2, + OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2, + OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2, + OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2, + OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2, + OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2, + OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2, + OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2, + OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2, + OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2, + OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2, + OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2, +}; + +/* Loongson EXT load/store quad word opcodes */ +#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020)) +enum { + OPC_GSLQ = 0x0020 | OPC_LWC2, + OPC_GSLQC1 = 0x8020 | OPC_LWC2, + OPC_GSSHFL = OPC_LWC2, + OPC_GSSQ = 0x0020 | OPC_SWC2, + OPC_GSSQC1 = 0x8020 | OPC_SWC2, + OPC_GSSHFS = OPC_SWC2, +}; + +/* Loongson EXT shifted load/store opcodes */ +#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f)) +enum { + OPC_GSLWLC1 = 0x4 | OPC_GSSHFL, + OPC_GSLWRC1 = 0x5 | OPC_GSSHFL, + OPC_GSLDLC1 = 0x6 | OPC_GSSHFL, + OPC_GSLDRC1 = 0x7 | OPC_GSSHFL, + OPC_GSSWLC1 = 0x4 | OPC_GSSHFS, + OPC_GSSWRC1 = 0x5 | OPC_GSSHFS, + OPC_GSSDLC1 = 0x6 | OPC_GSSHFS, + OPC_GSSDRC1 = 0x7 | OPC_GSSHFS, +}; + +/* Loongson EXT LDC2/SDC2 opcodes */ +#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7)) + +enum { + OPC_GSLBX = 0x0 | OPC_LDC2, + OPC_GSLHX = 0x1 | OPC_LDC2, + OPC_GSLWX = 0x2 | OPC_LDC2, + OPC_GSLDX = 0x3 | OPC_LDC2, + OPC_GSLWXC1 = 0x6 | OPC_LDC2, + OPC_GSLDXC1 = 0x7 | OPC_LDC2, + OPC_GSSBX = 0x0 | OPC_SDC2, + OPC_GSSHX = 0x1 | OPC_SDC2, + OPC_GSSWX = 0x2 | OPC_SDC2, + OPC_GSSDX = 0x3 | OPC_SDC2, + OPC_GSSWXC1 = 0x6 | OPC_SDC2, + OPC_GSSDXC1 = 0x7 | OPC_SDC2, +}; + +/* Godson integer instructions */ +static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) +{ + TCGv t0, t1; + + if (rd == 0) { + /* Treat as NOP. */ + return; + } + + switch (opc) { + case OPC_MULT_G_2E: + case OPC_MULT_G_2F: + case OPC_MULTU_G_2E: + case OPC_MULTU_G_2F: +#if defined(TARGET_MIPS64) + case OPC_DMULT_G_2E: + case OPC_DMULT_G_2F: + case OPC_DMULTU_G_2E: + case OPC_DMULTU_G_2F: +#endif + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + break; + default: + t0 = tcg_temp_local_new(); + t1 = tcg_temp_local_new(); + break; + } + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + + switch (opc) { + case OPC_MULT_G_2E: + case OPC_MULT_G_2F: + tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + break; + case OPC_MULTU_G_2E: + case OPC_MULTU_G_2F: + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + break; + case OPC_DIV_G_2E: + case OPC_DIV_G_2F: + { + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + TCGLabel *l3 = gen_new_label(); + tcg_gen_ext32s_tl(t0, t0); + tcg_gen_ext32s_tl(t1, t1); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rd], 0); + tcg_gen_br(l3); + gen_set_label(l1); + tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); + tcg_gen_mov_tl(cpu_gpr[rd], t0); + tcg_gen_br(l3); + gen_set_label(l2); + tcg_gen_div_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + gen_set_label(l3); + } + break; + case OPC_DIVU_G_2E: + case OPC_DIVU_G_2F: + { + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rd], 0); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + gen_set_label(l2); + } + break; + case OPC_MOD_G_2E: + case OPC_MOD_G_2F: + { + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + TCGLabel *l3 = gen_new_label(); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); + tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); + gen_set_label(l1); + tcg_gen_movi_tl(cpu_gpr[rd], 0); + tcg_gen_br(l3); + gen_set_label(l2); + tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + gen_set_label(l3); + } + break; + case OPC_MODU_G_2E: + case OPC_MODU_G_2F: + { + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rd], 0); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + gen_set_label(l2); + } + break; +#if defined(TARGET_MIPS64) + case OPC_DMULT_G_2E: + case OPC_DMULT_G_2F: + tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); + break; + case OPC_DMULTU_G_2E: + case OPC_DMULTU_G_2F: + tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); + break; + case OPC_DDIV_G_2E: + case OPC_DDIV_G_2F: + { + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + TCGLabel *l3 = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rd], 0); + tcg_gen_br(l3); + gen_set_label(l1); + tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); + tcg_gen_mov_tl(cpu_gpr[rd], t0); + tcg_gen_br(l3); + gen_set_label(l2); + tcg_gen_div_tl(cpu_gpr[rd], t0, t1); + gen_set_label(l3); + } + break; + case OPC_DDIVU_G_2E: + case OPC_DDIVU_G_2F: + { + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rd], 0); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); + gen_set_label(l2); + } + break; + case OPC_DMOD_G_2E: + case OPC_DMOD_G_2F: + { + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + TCGLabel *l3 = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); + tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); + gen_set_label(l1); + tcg_gen_movi_tl(cpu_gpr[rd], 0); + tcg_gen_br(l3); + gen_set_label(l2); + tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); + gen_set_label(l3); + } + break; + case OPC_DMODU_G_2E: + case OPC_DMODU_G_2F: + { + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rd], 0); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); + gen_set_label(l2); + } + break; +#endif + } + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_loongson_lswc2(DisasContext *ctx, int rt, + int rs, int rd) +{ + TCGv t0, t1, t2; + TCGv_i32 fp0; +#if defined(TARGET_MIPS64) + int lsq_rt1 = ctx->opcode & 0x1f; + int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4; +#endif + int shf_offset = sextract32(ctx->opcode, 6, 8); + + t0 = tcg_temp_new(); + + switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) { +#if defined(TARGET_MIPS64) + case OPC_GSLQ: + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_gpr(t1, rt); + gen_store_gpr(t0, lsq_rt1); + tcg_temp_free(t1); + break; + case OPC_GSLQC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_fpr64(ctx, t1, rt); + gen_store_fpr64(ctx, t0, lsq_rt1); + tcg_temp_free(t1); + break; + case OPC_GSSQ: + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + gen_load_gpr(t1, lsq_rt1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; + case OPC_GSSQC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + gen_load_fpr64(ctx, t1, lsq_rt1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + case OPC_GSSHFL: + switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { + case OPC_GSLWLC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 3); +#ifndef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 3); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~3); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); + tcg_gen_shl_tl(t0, t0, t1); + t2 = tcg_const_tl(-1); + tcg_gen_shl_tl(t2, t2, t1); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + tcg_gen_andc_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); +#if defined(TARGET_MIPS64) + tcg_gen_extrl_i64_i32(fp0, t0); +#else + tcg_gen_ext32s_tl(fp0, t0); +#endif + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; + case OPC_GSLWRC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 3); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 3); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~3); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); + tcg_gen_shr_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 31); + t2 = tcg_const_tl(0xfffffffeull); + tcg_gen_shl_tl(t2, t2, t1); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); +#if defined(TARGET_MIPS64) + tcg_gen_extrl_i64_i32(fp0, t0); +#else + tcg_gen_ext32s_tl(fp0, t0); +#endif + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDLC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 7); +#ifndef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 7); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~7); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_shl_tl(t0, t0, t1); + t2 = tcg_const_tl(-1); + tcg_gen_shl_tl(t2, t2, t1); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_andc_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); + gen_store_fpr64(ctx, t0, rt); + break; + case OPC_GSLDRC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 7); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 7); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~7); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_shr_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 63); + t2 = tcg_const_tl(0xfffffffffffffffeull); + tcg_gen_shl_tl(t2, t2, t1); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); + gen_store_fpr64(ctx, t0, rt); + break; +#endif + default: + MIPS_INVAL("loongson_gsshfl"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case OPC_GSSHFS: + switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { + case OPC_GSSWLC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + gen_helper_0e2i(swl, t1, t0, ctx->mem_idx); + tcg_temp_free_i32(fp0); + tcg_temp_free(t1); + break; + case OPC_GSSWRC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + gen_helper_0e2i(swr, t1, t0, ctx->mem_idx); + tcg_temp_free_i32(fp0); + tcg_temp_free(t1); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDLC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + gen_load_fpr64(ctx, t1, rt); + gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx); + tcg_temp_free(t1); + break; + case OPC_GSSDRC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + gen_load_fpr64(ctx, t1, rt); + gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx); + tcg_temp_free(t1); + break; +#endif + default: + MIPS_INVAL("loongson_gsshfs"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + default: + MIPS_INVAL("loongson_gslsq"); + generate_exception_end(ctx, EXCP_RI); + break; + } + tcg_temp_free(t0); +} + +/* Loongson EXT LDC2/SDC2 */ +static void gen_loongson_lsdc2(DisasContext *ctx, int rt, + int rs, int rd) +{ + int offset = sextract32(ctx->opcode, 3, 8); + uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode); + TCGv t0, t1; + TCGv_i32 fp0; + + /* Pre-conditions */ + switch (opc) { + case OPC_GSLBX: + case OPC_GSLHX: + case OPC_GSLWX: + case OPC_GSLDX: + /* prefetch, implement as NOP */ + if (rt == 0) { + return; + } + break; + case OPC_GSSBX: + case OPC_GSSHX: + case OPC_GSSWX: + case OPC_GSSDX: + break; + case OPC_GSLWXC1: +#if defined(TARGET_MIPS64) + case OPC_GSLDXC1: +#endif + check_cp1_enabled(ctx); + /* prefetch, implement as NOP */ + if (rt == 0) { + return; + } + break; + case OPC_GSSWXC1: +#if defined(TARGET_MIPS64) + case OPC_GSSDXC1: +#endif + check_cp1_enabled(ctx); + break; + default: + MIPS_INVAL("loongson_lsdc2"); + generate_exception_end(ctx, EXCP_RI); + return; + break; + } + + t0 = tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, rs, offset); + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + + switch (opc) { + case OPC_GSLBX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB); + gen_store_gpr(t0, rt); + break; + case OPC_GSLHX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; + case OPC_GSLWX: + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDX: + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; +#endif + case OPC_GSLWXC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + fp0 = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDXC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_fpr64(ctx, t0, rt); + break; +#endif + case OPC_GSSBX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB); + tcg_temp_free(t1); + break; + case OPC_GSSHX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; + case OPC_GSSWX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + case OPC_GSSWXC1: + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDXC1: + t1 = tcg_temp_new(); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + default: + break; + } + + tcg_temp_free(t0); +} From patchwork Mon Nov 23 20:44:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926787 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 8910BC2D0E4 for ; Mon, 23 Nov 2020 21:27:24 +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 698CE206D4 for ; Mon, 23 Nov 2020 21:27:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="U9AosNsU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 698CE206D4 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40132 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJMo-0007bO-8D for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:27:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:47010) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjb-0002bk-7H for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:52 -0500 Received: from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b]:55919) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjV-0001rN-6n for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:50 -0500 Received: by mail-wm1-x32b.google.com with SMTP id x22so602705wmc.5 for ; Mon, 23 Nov 2020 12:46:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=E3s2Q3K7NeWQ6UGFDAtWbFQn1P1j2u8IBUVAxL3DExA=; b=U9AosNsUI5PU9u/ILjTTTutfkfSyO6Bwo4nfunYPcIQvQjKyxLtFocxp0NzMPaPBLa GDwmS2B0H7XM2CoiMmuN89dMM9IycYIOCaD1/ALOTakd1VwvpcAgNRJivfg0v3pVD2Ej j7AK4eZUYc/cV3hU9xMHME0b7fuQ2KDxll9SwQssBB3KL0zqI7HDq43Wl9JzTSo+2sEf vu3ldK62wT0owvScvYplk5CgYnOsUjDSBEgcV5t2v5+j3FQRPh6whoihIrNFyyUbDkrq Yo32XUJd41KI3iuyGoaM02/37ZmsaiLaQCmt1+jREU++TJfJPNorCDh1EzhDiib3+6EP SAzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=E3s2Q3K7NeWQ6UGFDAtWbFQn1P1j2u8IBUVAxL3DExA=; b=rBwDZuY3wEgkLnpYMwn4o4O3i9GZRTfdEbLGAlt1ewrQabY8GAz/ZDRSCGygbxf9Kn sDZIgNHwm0+ZY83DQCoEAHMJ7I6oc+hX1NDS+00NBEObgDNH5S9YWaqwXQ76KPfymtvf XkJmufj7TC1ASupLc0/tnbLpidsNDkympcHvvM7N3Gu1gKOaqKFt6cwZzC5BTvdnYrxe SH/DZTI3C1r/57gHOzGpRzeEBRs5aKUoVWucnjjZ8dvfelKpZ6epqtzoU3xLJCM/SOEk SEiMxEpu/RcfXfJXp9KZ+qlF7JP55lAik4+Ma4sizlrT0Gmp8HxpbflTA1Buv8+ERYUE bUYA== X-Gm-Message-State: AOAM531tqsuksJgRWQ7lFbSui2WaH+Cb/JHbz55HnETEpRTS+Iu97Mo5 FhpXRbg5cAwtDGM5Wg3Lv+d2iTP2nxo= X-Google-Smtp-Source: ABdhPJw0IG0zj1GGMjoomHIV1sda8De7GUaE6E1DyNUAPEMujXgozybGNOkQGkMdb13f99x/9cKm1Q== X-Received: by 2002:a7b:c00b:: with SMTP id c11mr741578wmb.122.1606164400371; Mon, 23 Nov 2020 12:46:40 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id e1sm872690wmd.16.2020.11.23.12.46.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:39 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 22/28] target/mips: Extract XBurst Media eXtension Unit translation routines Date: Mon, 23 Nov 2020 21:44:42 +0100 Message-Id: <20201123204448.3260804-23-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32b; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x32b.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Media eXtension Unit is a SIMD extension from Ingenic. Extract 2900 lines from the huge translate.c to a new file, 'vendor-xburst-mxu_translate.c.inc'. As there are too many inter-dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- target/mips/translate.c | 2890 +---------------------- target/mips/vendor-mxu_translate.c.inc | 2892 ++++++++++++++++++++++++ 2 files changed, 2893 insertions(+), 2889 deletions(-) create mode 100644 target/mips/vendor-mxu_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 90ab84c69a3..7ef3bc52358 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -610,619 +610,6 @@ enum { }; -/* - * - * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET - * ============================================ - * - * - * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32 - * instructions set. It is designed to fit the needs of signal, graphical and - * video processing applications. MXU instruction set is used in Xburst family - * of microprocessors by Ingenic. - * - * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is - * the control register. - * - * - * The notation used in MXU assembler mnemonics - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Register operands: - * - * XRa, XRb, XRc, XRd - MXU registers - * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers - * - * Non-register operands: - * - * aptn1 - 1-bit accumulate add/subtract pattern - * aptn2 - 2-bit accumulate add/subtract pattern - * eptn2 - 2-bit execute add/subtract pattern - * optn2 - 2-bit operand pattern - * optn3 - 3-bit operand pattern - * sft4 - 4-bit shift amount - * strd2 - 2-bit stride amount - * - * Prefixes: - * - * Level of parallelism: Operand size: - * S - single operation at a time 32 - word - * D - two operations in parallel 16 - half word - * Q - four operations in parallel 8 - byte - * - * Operations: - * - * ADD - Add or subtract - * ADDC - Add with carry-in - * ACC - Accumulate - * ASUM - Sum together then accumulate (add or subtract) - * ASUMC - Sum together then accumulate (add or subtract) with carry-in - * AVG - Average between 2 operands - * ABD - Absolute difference - * ALN - Align data - * AND - Logical bitwise 'and' operation - * CPS - Copy sign - * EXTR - Extract bits - * I2M - Move from GPR register to MXU register - * LDD - Load data from memory to XRF - * LDI - Load data from memory to XRF (and increase the address base) - * LUI - Load unsigned immediate - * MUL - Multiply - * MULU - Unsigned multiply - * MADD - 64-bit operand add 32x32 product - * MSUB - 64-bit operand subtract 32x32 product - * MAC - Multiply and accumulate (add or subtract) - * MAD - Multiply and add or subtract - * MAX - Maximum between 2 operands - * MIN - Minimum between 2 operands - * M2I - Move from MXU register to GPR register - * MOVZ - Move if zero - * MOVN - Move if non-zero - * NOR - Logical bitwise 'nor' operation - * OR - Logical bitwise 'or' operation - * STD - Store data from XRF to memory - * SDI - Store data from XRF to memory (and increase the address base) - * SLT - Set of less than comparison - * SAD - Sum of absolute differences - * SLL - Logical shift left - * SLR - Logical shift right - * SAR - Arithmetic shift right - * SAT - Saturation - * SFL - Shuffle - * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0) - * XOR - Logical bitwise 'exclusive or' operation - * - * Suffixes: - * - * E - Expand results - * F - Fixed point multiplication - * L - Low part result - * R - Doing rounding - * V - Variable instead of immediate - * W - Combine above L and V - * - * - * The list of MXU instructions grouped by functionality - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Load/Store instructions Multiplication instructions - * ----------------------- --------------------------- - * - * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt - * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt - * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt - * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt - * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt - * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt - * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2 - * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2 - * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2 - * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2 - * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2 - * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2 - * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2 - * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd - * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd - * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2 - * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2 - * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2 - * S16SDI XRa, Rb, s10, eptn2 - * S8LDD XRa, Rb, s8, eptn3 - * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions - * S8LDI XRa, Rb, s8, eptn3 ------------------------------------- - * S8SDI XRa, Rb, s8, eptn3 - * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2 - * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd - * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2 - * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2 - * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2 - * S32CPS XRa, XRb, XRc - * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2 - * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2 - * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2 - * D16ASUM XRa, XRb, XRc, XRd, eptn2 - * S32MAX XRa, XRb, XRc D16CPS XRa, XRb, - * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc - * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc - * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2 - * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2 - * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2 - * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc - * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd - * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc - * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc - * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd - * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd - * Q8SLT XRa, XRb, XRc - * Q8SLTU XRa, XRb, XRc - * Q8MOVZ XRa, XRb, XRc Shift instructions - * Q8MOVN XRa, XRb, XRc ------------------ - * - * D32SLL XRa, XRb, XRc, XRd, sft4 - * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4 - * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4 - * D32SARL XRa, XRb, XRc, sft4 - * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb - * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb - * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb - * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb - * Q16SLL XRa, XRb, XRc, XRd, sft4 - * Q16SLR XRa, XRb, XRc, XRd, sft4 - * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4 - * ------------------------- Q16SLLV XRa, XRb, Rb - * Q16SLRV XRa, XRb, Rb - * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb - * S32ALN XRa, XRb, XRc, Rb - * S32ALNI XRa, XRb, XRc, s3 - * S32LUI XRa, s8, optn3 Move instructions - * S32EXTR XRa, XRb, Rb, bits5 ----------------- - * S32EXTRV XRa, XRb, Rs, Rt - * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb - * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb - * - * - * The opcode organization of MXU instructions - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred - * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of - * other bits up to the instruction level is as follows: - * - * bits - * 05..00 - * - * ┌─ 000000 ─ OPC_MXU_S32MADD - * ├─ 000001 ─ OPC_MXU_S32MADDU - * ├─ 000010 ─ (non-MXU OPC_MUL) - * │ - * │ 20..18 - * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX - * │ ├─ 001 ─ OPC_MXU_S32MIN - * │ ├─ 010 ─ OPC_MXU_D16MAX - * │ ├─ 011 ─ OPC_MXU_D16MIN - * │ ├─ 100 ─ OPC_MXU_Q8MAX - * │ ├─ 101 ─ OPC_MXU_Q8MIN - * │ ├─ 110 ─ OPC_MXU_Q8SLT - * │ └─ 111 ─ OPC_MXU_Q8SLTU - * ├─ 000100 ─ OPC_MXU_S32MSUB - * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18 - * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT - * │ ├─ 001 ─ OPC_MXU_D16SLT - * │ ├─ 010 ─ OPC_MXU_D16AVG - * │ ├─ 011 ─ OPC_MXU_D16AVGR - * │ ├─ 100 ─ OPC_MXU_Q8AVG - * │ ├─ 101 ─ OPC_MXU_Q8AVGR - * │ └─ 111 ─ OPC_MXU_Q8ADD - * │ - * │ 20..18 - * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS - * │ ├─ 010 ─ OPC_MXU_D16CPS - * │ ├─ 100 ─ OPC_MXU_Q8ABD - * │ └─ 110 ─ OPC_MXU_Q16SAT - * ├─ 001000 ─ OPC_MXU_D16MUL - * │ 25..24 - * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF - * │ └─ 01 ─ OPC_MXU_D16MULE - * ├─ 001010 ─ OPC_MXU_D16MAC - * ├─ 001011 ─ OPC_MXU_D16MACF - * ├─ 001100 ─ OPC_MXU_D16MADL - * ├─ 001101 ─ OPC_MXU_S16MAD - * ├─ 001110 ─ OPC_MXU_Q16ADD - * ├─ 001111 ─ OPC_MXU_D16MACE 23 - * │ ┌─ 0 ─ OPC_MXU_S32LDD - * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR - * │ - * │ 23 - * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD - * │ └─ 1 ─ OPC_MXU_S32STDR - * │ - * │ 13..10 - * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV - * │ └─ 0001 ─ OPC_MXU_S32LDDVR - * │ - * │ 13..10 - * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV - * │ └─ 0001 ─ OPC_MXU_S32STDVR - * │ - * │ 23 - * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI - * │ └─ 1 ─ OPC_MXU_S32LDIR - * │ - * │ 23 - * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI - * │ └─ 1 ─ OPC_MXU_S32SDIR - * │ - * │ 13..10 - * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV - * │ └─ 0001 ─ OPC_MXU_S32LDIVR - * │ - * │ 13..10 - * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV - * │ └─ 0001 ─ OPC_MXU_S32SDIVR - * ├─ 011000 ─ OPC_MXU_D32ADD - * │ 23..22 - * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC - * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM - * │ └─ 10 ─ OPC_MXU_D32ASUM - * ├─ 011010 ─ - * │ 23..22 - * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC - * │ ├─ 01 ─ OPC_MXU_Q16ACCM - * │ └─ 10 ─ OPC_MXU_Q16ASUM - * │ - * │ 23..22 - * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE - * │ ├─ 01 ─ OPC_MXU_D8SUM - * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC - * ├─ 011110 ─ - * ├─ 011111 ─ - * ├─ 100000 ─ (overlaps with CLZ) - * ├─ 100001 ─ (overlaps with CLO) - * ├─ 100010 ─ OPC_MXU_S8LDD - * ├─ 100011 ─ OPC_MXU_S8STD 15..14 - * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL - * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU - * │ ├─ 00 ─ OPC_MXU_S32EXTR - * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV - * │ - * │ 20..18 - * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW - * │ ├─ 001 ─ OPC_MXU_S32ALN - * │ ├─ 010 ─ OPC_MXU_S32ALNI - * │ ├─ 011 ─ OPC_MXU_S32LUI - * │ ├─ 100 ─ OPC_MXU_S32NOR - * │ ├─ 101 ─ OPC_MXU_S32AND - * │ ├─ 110 ─ OPC_MXU_S32OR - * │ └─ 111 ─ OPC_MXU_S32XOR - * │ - * │ 7..5 - * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB - * │ ├─ 001 ─ OPC_MXU_LXH - * ├─ 101001 ─ ├─ 011 ─ OPC_MXU_LXW - * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU - * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU - * ├─ 101100 ─ OPC_MXU_S16LDI - * ├─ 101101 ─ OPC_MXU_S16SDI - * ├─ 101110 ─ OPC_MXU_S32M2I - * ├─ 101111 ─ OPC_MXU_S32I2M - * ├─ 110000 ─ OPC_MXU_D32SLL - * ├─ 110001 ─ OPC_MXU_D32SLR 20..18 - * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV - * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV - * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV - * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV - * │ ├─ 100 ─ OPC_MXU_Q16SLRV - * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV - * │ - * ├─ 110111 ─ OPC_MXU_Q16SAR - * │ 23..22 - * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL - * │ └─ 01 ─ OPC_MXU_Q8MULSU - * │ - * │ 20..18 - * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ - * │ ├─ 001 ─ OPC_MXU_Q8MOVN - * │ ├─ 010 ─ OPC_MXU_D16MOVZ - * │ ├─ 011 ─ OPC_MXU_D16MOVN - * │ ├─ 100 ─ OPC_MXU_S32MOVZ - * │ └─ 101 ─ OPC_MXU_S32MOVN - * │ - * │ 23..22 - * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC - * │ └─ 10 ─ OPC_MXU_Q8MACSU - * ├─ 111011 ─ OPC_MXU_Q16SCOP - * ├─ 111100 ─ OPC_MXU_Q8MADL - * ├─ 111101 ─ OPC_MXU_S32SFL - * ├─ 111110 ─ OPC_MXU_Q8SAD - * └─ 111111 ─ (overlaps with SDBBP) - * - * - * Compiled after: - * - * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit - * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017 - */ - -enum { - OPC_MXU_S32MADD = 0x00, - OPC_MXU_S32MADDU = 0x01, - OPC__MXU_MUL = 0x02, - OPC_MXU__POOL00 = 0x03, - OPC_MXU_S32MSUB = 0x04, - OPC_MXU_S32MSUBU = 0x05, - OPC_MXU__POOL01 = 0x06, - OPC_MXU__POOL02 = 0x07, - OPC_MXU_D16MUL = 0x08, - OPC_MXU__POOL03 = 0x09, - OPC_MXU_D16MAC = 0x0A, - OPC_MXU_D16MACF = 0x0B, - OPC_MXU_D16MADL = 0x0C, - OPC_MXU_S16MAD = 0x0D, - OPC_MXU_Q16ADD = 0x0E, - OPC_MXU_D16MACE = 0x0F, - OPC_MXU__POOL04 = 0x10, - OPC_MXU__POOL05 = 0x11, - OPC_MXU__POOL06 = 0x12, - OPC_MXU__POOL07 = 0x13, - OPC_MXU__POOL08 = 0x14, - OPC_MXU__POOL09 = 0x15, - OPC_MXU__POOL10 = 0x16, - OPC_MXU__POOL11 = 0x17, - OPC_MXU_D32ADD = 0x18, - OPC_MXU__POOL12 = 0x19, - /* not assigned 0x1A */ - OPC_MXU__POOL13 = 0x1B, - OPC_MXU__POOL14 = 0x1C, - OPC_MXU_Q8ACCE = 0x1D, - /* not assigned 0x1E */ - /* not assigned 0x1F */ - /* not assigned 0x20 */ - /* not assigned 0x21 */ - OPC_MXU_S8LDD = 0x22, - OPC_MXU_S8STD = 0x23, - OPC_MXU_S8LDI = 0x24, - OPC_MXU_S8SDI = 0x25, - OPC_MXU__POOL15 = 0x26, - OPC_MXU__POOL16 = 0x27, - OPC_MXU__POOL17 = 0x28, - /* not assigned 0x29 */ - OPC_MXU_S16LDD = 0x2A, - OPC_MXU_S16STD = 0x2B, - OPC_MXU_S16LDI = 0x2C, - OPC_MXU_S16SDI = 0x2D, - OPC_MXU_S32M2I = 0x2E, - OPC_MXU_S32I2M = 0x2F, - OPC_MXU_D32SLL = 0x30, - OPC_MXU_D32SLR = 0x31, - OPC_MXU_D32SARL = 0x32, - OPC_MXU_D32SAR = 0x33, - OPC_MXU_Q16SLL = 0x34, - OPC_MXU_Q16SLR = 0x35, - OPC_MXU__POOL18 = 0x36, - OPC_MXU_Q16SAR = 0x37, - OPC_MXU__POOL19 = 0x38, - OPC_MXU__POOL20 = 0x39, - OPC_MXU__POOL21 = 0x3A, - OPC_MXU_Q16SCOP = 0x3B, - OPC_MXU_Q8MADL = 0x3C, - OPC_MXU_S32SFL = 0x3D, - OPC_MXU_Q8SAD = 0x3E, - /* not assigned 0x3F */ -}; - - -/* - * MXU pool 00 - */ -enum { - OPC_MXU_S32MAX = 0x00, - OPC_MXU_S32MIN = 0x01, - OPC_MXU_D16MAX = 0x02, - OPC_MXU_D16MIN = 0x03, - OPC_MXU_Q8MAX = 0x04, - OPC_MXU_Q8MIN = 0x05, - OPC_MXU_Q8SLT = 0x06, - OPC_MXU_Q8SLTU = 0x07, -}; - -/* - * MXU pool 01 - */ -enum { - OPC_MXU_S32SLT = 0x00, - OPC_MXU_D16SLT = 0x01, - OPC_MXU_D16AVG = 0x02, - OPC_MXU_D16AVGR = 0x03, - OPC_MXU_Q8AVG = 0x04, - OPC_MXU_Q8AVGR = 0x05, - OPC_MXU_Q8ADD = 0x07, -}; - -/* - * MXU pool 02 - */ -enum { - OPC_MXU_S32CPS = 0x00, - OPC_MXU_D16CPS = 0x02, - OPC_MXU_Q8ABD = 0x04, - OPC_MXU_Q16SAT = 0x06, -}; - -/* - * MXU pool 03 - */ -enum { - OPC_MXU_D16MULF = 0x00, - OPC_MXU_D16MULE = 0x01, -}; - -/* - * MXU pool 04 - */ -enum { - OPC_MXU_S32LDD = 0x00, - OPC_MXU_S32LDDR = 0x01, -}; - -/* - * MXU pool 05 - */ -enum { - OPC_MXU_S32STD = 0x00, - OPC_MXU_S32STDR = 0x01, -}; - -/* - * MXU pool 06 - */ -enum { - OPC_MXU_S32LDDV = 0x00, - OPC_MXU_S32LDDVR = 0x01, -}; - -/* - * MXU pool 07 - */ -enum { - OPC_MXU_S32STDV = 0x00, - OPC_MXU_S32STDVR = 0x01, -}; - -/* - * MXU pool 08 - */ -enum { - OPC_MXU_S32LDI = 0x00, - OPC_MXU_S32LDIR = 0x01, -}; - -/* - * MXU pool 09 - */ -enum { - OPC_MXU_S32SDI = 0x00, - OPC_MXU_S32SDIR = 0x01, -}; - -/* - * MXU pool 10 - */ -enum { - OPC_MXU_S32LDIV = 0x00, - OPC_MXU_S32LDIVR = 0x01, -}; - -/* - * MXU pool 11 - */ -enum { - OPC_MXU_S32SDIV = 0x00, - OPC_MXU_S32SDIVR = 0x01, -}; - -/* - * MXU pool 12 - */ -enum { - OPC_MXU_D32ACC = 0x00, - OPC_MXU_D32ACCM = 0x01, - OPC_MXU_D32ASUM = 0x02, -}; - -/* - * MXU pool 13 - */ -enum { - OPC_MXU_Q16ACC = 0x00, - OPC_MXU_Q16ACCM = 0x01, - OPC_MXU_Q16ASUM = 0x02, -}; - -/* - * MXU pool 14 - */ -enum { - OPC_MXU_Q8ADDE = 0x00, - OPC_MXU_D8SUM = 0x01, - OPC_MXU_D8SUMC = 0x02, -}; - -/* - * MXU pool 15 - */ -enum { - OPC_MXU_S32MUL = 0x00, - OPC_MXU_S32MULU = 0x01, - OPC_MXU_S32EXTR = 0x02, - OPC_MXU_S32EXTRV = 0x03, -}; - -/* - * MXU pool 16 - */ -enum { - OPC_MXU_D32SARW = 0x00, - OPC_MXU_S32ALN = 0x01, - OPC_MXU_S32ALNI = 0x02, - OPC_MXU_S32LUI = 0x03, - OPC_MXU_S32NOR = 0x04, - OPC_MXU_S32AND = 0x05, - OPC_MXU_S32OR = 0x06, - OPC_MXU_S32XOR = 0x07, -}; - -/* - * MXU pool 17 - */ -enum { - OPC_MXU_LXB = 0x00, - OPC_MXU_LXH = 0x01, - OPC_MXU_LXW = 0x03, - OPC_MXU_LXBU = 0x04, - OPC_MXU_LXHU = 0x05, -}; - -/* - * MXU pool 18 - */ -enum { - OPC_MXU_D32SLLV = 0x00, - OPC_MXU_D32SLRV = 0x01, - OPC_MXU_D32SARV = 0x03, - OPC_MXU_Q16SLLV = 0x04, - OPC_MXU_Q16SLRV = 0x05, - OPC_MXU_Q16SARV = 0x07, -}; - -/* - * MXU pool 19 - */ -enum { - OPC_MXU_Q8MUL = 0x00, - OPC_MXU_Q8MULSU = 0x01, -}; - -/* - * MXU pool 20 - */ -enum { - OPC_MXU_Q8MOVZ = 0x00, - OPC_MXU_Q8MOVN = 0x01, - OPC_MXU_D16MOVZ = 0x02, - OPC_MXU_D16MOVN = 0x03, - OPC_MXU_S32MOVZ = 0x04, - OPC_MXU_S32MOVN = 0x05, -}; - -/* - * MXU pool 21 - */ -enum { - OPC_MXU_Q8MAC = 0x00, - OPC_MXU_Q8MACSU = 0x01, -}; - /* * Overview of the TX79-specific instruction set * ============================================= @@ -1672,12 +1059,6 @@ static TCGv_i64 fpu_f64[32]; static TCGv_i64 cpu_mmr[32]; #endif -#if !defined(TARGET_MIPS64) -/* MXU registers */ -static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; -static TCGv mxu_CR; -#endif - #include "exec/gen-icount.h" #define gen_helper_0e0i(name, arg) do { \ @@ -1784,13 +1165,6 @@ static const char * const fregnames[] = { "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; -#if !defined(TARGET_MIPS64) -static const char * const mxuregnames[] = { - "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8", - "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR", -}; -#endif - #define LOG_DISAS(...) \ do { \ if (MIPS_DEBUG_DISAS) { \ @@ -1874,37 +1248,6 @@ static inline void gen_store_srsgpr(int from, int to) } } -#if !defined(TARGET_MIPS64) -/* MXU General purpose registers moves. */ -static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg) -{ - if (reg == 0) { - tcg_gen_movi_tl(t, 0); - } else if (reg <= 15) { - tcg_gen_mov_tl(t, mxu_gpr[reg - 1]); - } -} - -static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg) -{ - if (reg > 0 && reg <= 15) { - tcg_gen_mov_tl(mxu_gpr[reg - 1], t); - } -} - -/* MXU control register moves. */ -static inline void gen_load_mxu_cr(TCGv t) -{ - tcg_gen_mov_tl(t, mxu_CR); -} - -static inline void gen_store_mxu_cr(TCGv t) -{ - /* TODO: Add handling of RW rules for MXU_CR. */ - tcg_gen_mov_tl(mxu_CR, t); -} -#endif - /* Tests */ static inline void gen_save_pc(target_ulong pc) @@ -11808,6 +11151,7 @@ out: #include "vendor-vr54xx_translate.c.inc" #include "vendor-loong-simd_translate.c.inc" #include "vendor-loong-ext_translate.c.inc" +#include "vendor-mxu_translate.c.inc" static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) { @@ -12423,2238 +11767,6 @@ static void gen_mmi_pcpyud(DisasContext *ctx) #endif - -#if !defined(TARGET_MIPS64) - -/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */ -#define MXU_APTN1_A 0 -#define MXU_APTN1_S 1 - -/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */ -#define MXU_APTN2_AA 0 -#define MXU_APTN2_AS 1 -#define MXU_APTN2_SA 2 -#define MXU_APTN2_SS 3 - -/* MXU execute add/subtract 2-bit pattern 'eptn2' */ -#define MXU_EPTN2_AA 0 -#define MXU_EPTN2_AS 1 -#define MXU_EPTN2_SA 2 -#define MXU_EPTN2_SS 3 - -/* MXU operand getting pattern 'optn2' */ -#define MXU_OPTN2_PTN0 0 -#define MXU_OPTN2_PTN1 1 -#define MXU_OPTN2_PTN2 2 -#define MXU_OPTN2_PTN3 3 -/* alternative naming scheme for 'optn2' */ -#define MXU_OPTN2_WW 0 -#define MXU_OPTN2_LW 1 -#define MXU_OPTN2_HW 2 -#define MXU_OPTN2_XW 3 - -/* MXU operand getting pattern 'optn3' */ -#define MXU_OPTN3_PTN0 0 -#define MXU_OPTN3_PTN1 1 -#define MXU_OPTN3_PTN2 2 -#define MXU_OPTN3_PTN3 3 -#define MXU_OPTN3_PTN4 4 -#define MXU_OPTN3_PTN5 5 -#define MXU_OPTN3_PTN6 6 -#define MXU_OPTN3_PTN7 7 - - -/* - * S32I2M XRa, rb - Register move from GRF to XRF - */ -static void gen_mxu_s32i2m(DisasContext *ctx) -{ - TCGv t0; - uint32_t XRa, Rb; - - t0 = tcg_temp_new(); - - XRa = extract32(ctx->opcode, 6, 5); - Rb = extract32(ctx->opcode, 16, 5); - - gen_load_gpr(t0, Rb); - if (XRa <= 15) { - gen_store_mxu_gpr(t0, XRa); - } else if (XRa == 16) { - gen_store_mxu_cr(t0); - } - - tcg_temp_free(t0); -} - -/* - * S32M2I XRa, rb - Register move from XRF to GRF - */ -static void gen_mxu_s32m2i(DisasContext *ctx) -{ - TCGv t0; - uint32_t XRa, Rb; - - t0 = tcg_temp_new(); - - XRa = extract32(ctx->opcode, 6, 5); - Rb = extract32(ctx->opcode, 16, 5); - - if (XRa <= 15) { - gen_load_mxu_gpr(t0, XRa); - } else if (XRa == 16) { - gen_load_mxu_cr(t0); - } - - gen_store_gpr(t0, Rb); - - tcg_temp_free(t0); -} - -/* - * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF - */ -static void gen_mxu_s8ldd(DisasContext *ctx) -{ - TCGv t0, t1; - uint32_t XRa, Rb, s8, optn3; - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - - XRa = extract32(ctx->opcode, 6, 4); - s8 = extract32(ctx->opcode, 10, 8); - optn3 = extract32(ctx->opcode, 18, 3); - Rb = extract32(ctx->opcode, 21, 5); - - gen_load_gpr(t0, Rb); - tcg_gen_addi_tl(t0, t0, (int8_t)s8); - - switch (optn3) { - /* XRa[7:0] = tmp8 */ - case MXU_OPTN3_PTN0: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - gen_load_mxu_gpr(t0, XRa); - tcg_gen_deposit_tl(t0, t0, t1, 0, 8); - break; - /* XRa[15:8] = tmp8 */ - case MXU_OPTN3_PTN1: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - gen_load_mxu_gpr(t0, XRa); - tcg_gen_deposit_tl(t0, t0, t1, 8, 8); - break; - /* XRa[23:16] = tmp8 */ - case MXU_OPTN3_PTN2: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - gen_load_mxu_gpr(t0, XRa); - tcg_gen_deposit_tl(t0, t0, t1, 16, 8); - break; - /* XRa[31:24] = tmp8 */ - case MXU_OPTN3_PTN3: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - gen_load_mxu_gpr(t0, XRa); - tcg_gen_deposit_tl(t0, t0, t1, 24, 8); - break; - /* XRa = {8'b0, tmp8, 8'b0, tmp8} */ - case MXU_OPTN3_PTN4: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_deposit_tl(t0, t1, t1, 16, 16); - break; - /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */ - case MXU_OPTN3_PTN5: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_shli_tl(t1, t1, 8); - tcg_gen_deposit_tl(t0, t1, t1, 16, 16); - break; - /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */ - case MXU_OPTN3_PTN6: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB); - tcg_gen_mov_tl(t0, t1); - tcg_gen_andi_tl(t0, t0, 0xFF00FFFF); - tcg_gen_shli_tl(t1, t1, 16); - tcg_gen_or_tl(t0, t0, t1); - break; - /* XRa = {tmp8, tmp8, tmp8, tmp8} */ - case MXU_OPTN3_PTN7: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_deposit_tl(t1, t1, t1, 8, 8); - tcg_gen_deposit_tl(t0, t1, t1, 16, 16); - break; - } - - gen_store_mxu_gpr(t0, XRa); - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -/* - * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication - */ -static void gen_mxu_d16mul(DisasContext *ctx) -{ - TCGv t0, t1, t2, t3; - uint32_t XRa, XRb, XRc, XRd, optn2; - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - t2 = tcg_temp_new(); - t3 = tcg_temp_new(); - - XRa = extract32(ctx->opcode, 6, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRc = extract32(ctx->opcode, 14, 4); - XRd = extract32(ctx->opcode, 18, 4); - optn2 = extract32(ctx->opcode, 22, 2); - - gen_load_mxu_gpr(t1, XRb); - tcg_gen_sextract_tl(t0, t1, 0, 16); - tcg_gen_sextract_tl(t1, t1, 16, 16); - gen_load_mxu_gpr(t3, XRc); - tcg_gen_sextract_tl(t2, t3, 0, 16); - tcg_gen_sextract_tl(t3, t3, 16, 16); - - switch (optn2) { - case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */ - tcg_gen_mul_tl(t3, t1, t3); - tcg_gen_mul_tl(t2, t0, t2); - break; - case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */ - tcg_gen_mul_tl(t3, t0, t3); - tcg_gen_mul_tl(t2, t0, t2); - break; - case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */ - tcg_gen_mul_tl(t3, t1, t3); - tcg_gen_mul_tl(t2, t1, t2); - break; - case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */ - tcg_gen_mul_tl(t3, t0, t3); - tcg_gen_mul_tl(t2, t1, t2); - break; - } - gen_store_mxu_gpr(t3, XRa); - gen_store_mxu_gpr(t2, XRd); - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); - tcg_temp_free(t3); -} - -/* - * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply - * and accumulate - */ -static void gen_mxu_d16mac(DisasContext *ctx) -{ - TCGv t0, t1, t2, t3; - uint32_t XRa, XRb, XRc, XRd, optn2, aptn2; - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - t2 = tcg_temp_new(); - t3 = tcg_temp_new(); - - XRa = extract32(ctx->opcode, 6, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRc = extract32(ctx->opcode, 14, 4); - XRd = extract32(ctx->opcode, 18, 4); - optn2 = extract32(ctx->opcode, 22, 2); - aptn2 = extract32(ctx->opcode, 24, 2); - - gen_load_mxu_gpr(t1, XRb); - tcg_gen_sextract_tl(t0, t1, 0, 16); - tcg_gen_sextract_tl(t1, t1, 16, 16); - - gen_load_mxu_gpr(t3, XRc); - tcg_gen_sextract_tl(t2, t3, 0, 16); - tcg_gen_sextract_tl(t3, t3, 16, 16); - - switch (optn2) { - case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */ - tcg_gen_mul_tl(t3, t1, t3); - tcg_gen_mul_tl(t2, t0, t2); - break; - case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */ - tcg_gen_mul_tl(t3, t0, t3); - tcg_gen_mul_tl(t2, t0, t2); - break; - case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */ - tcg_gen_mul_tl(t3, t1, t3); - tcg_gen_mul_tl(t2, t1, t2); - break; - case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */ - tcg_gen_mul_tl(t3, t0, t3); - tcg_gen_mul_tl(t2, t1, t2); - break; - } - gen_load_mxu_gpr(t0, XRa); - gen_load_mxu_gpr(t1, XRd); - - switch (aptn2) { - case MXU_APTN2_AA: - tcg_gen_add_tl(t3, t0, t3); - tcg_gen_add_tl(t2, t1, t2); - break; - case MXU_APTN2_AS: - tcg_gen_add_tl(t3, t0, t3); - tcg_gen_sub_tl(t2, t1, t2); - break; - case MXU_APTN2_SA: - tcg_gen_sub_tl(t3, t0, t3); - tcg_gen_add_tl(t2, t1, t2); - break; - case MXU_APTN2_SS: - tcg_gen_sub_tl(t3, t0, t3); - tcg_gen_sub_tl(t2, t1, t2); - break; - } - gen_store_mxu_gpr(t3, XRa); - gen_store_mxu_gpr(t2, XRd); - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); - tcg_temp_free(t3); -} - -/* - * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply - * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply - */ -static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx) -{ - TCGv t0, t1, t2, t3, t4, t5, t6, t7; - uint32_t XRa, XRb, XRc, XRd, sel; - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - t2 = tcg_temp_new(); - t3 = tcg_temp_new(); - t4 = tcg_temp_new(); - t5 = tcg_temp_new(); - t6 = tcg_temp_new(); - t7 = tcg_temp_new(); - - XRa = extract32(ctx->opcode, 6, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRc = extract32(ctx->opcode, 14, 4); - XRd = extract32(ctx->opcode, 18, 4); - sel = extract32(ctx->opcode, 22, 2); - - gen_load_mxu_gpr(t3, XRb); - gen_load_mxu_gpr(t7, XRc); - - if (sel == 0x2) { - /* Q8MULSU */ - tcg_gen_ext8s_tl(t0, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8s_tl(t1, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8s_tl(t2, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8s_tl(t3, t3); - } else { - /* Q8MUL */ - tcg_gen_ext8u_tl(t0, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8u_tl(t1, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8u_tl(t2, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8u_tl(t3, t3); - } - - tcg_gen_ext8u_tl(t4, t7); - tcg_gen_shri_tl(t7, t7, 8); - tcg_gen_ext8u_tl(t5, t7); - tcg_gen_shri_tl(t7, t7, 8); - tcg_gen_ext8u_tl(t6, t7); - tcg_gen_shri_tl(t7, t7, 8); - tcg_gen_ext8u_tl(t7, t7); - - tcg_gen_mul_tl(t0, t0, t4); - tcg_gen_mul_tl(t1, t1, t5); - tcg_gen_mul_tl(t2, t2, t6); - tcg_gen_mul_tl(t3, t3, t7); - - tcg_gen_andi_tl(t0, t0, 0xFFFF); - tcg_gen_andi_tl(t1, t1, 0xFFFF); - tcg_gen_andi_tl(t2, t2, 0xFFFF); - tcg_gen_andi_tl(t3, t3, 0xFFFF); - - tcg_gen_shli_tl(t1, t1, 16); - tcg_gen_shli_tl(t3, t3, 16); - - tcg_gen_or_tl(t0, t0, t1); - tcg_gen_or_tl(t1, t2, t3); - - gen_store_mxu_gpr(t0, XRd); - gen_store_mxu_gpr(t1, XRa); - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); - tcg_temp_free(t3); - tcg_temp_free(t4); - tcg_temp_free(t5); - tcg_temp_free(t6); - tcg_temp_free(t7); -} - -/* - * S32LDD XRa, Rb, S12 - Load a word from memory to XRF - * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq. - */ -static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx) -{ - TCGv t0, t1; - uint32_t XRa, Rb, s12, sel; - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - - XRa = extract32(ctx->opcode, 6, 4); - s12 = extract32(ctx->opcode, 10, 10); - sel = extract32(ctx->opcode, 20, 1); - Rb = extract32(ctx->opcode, 21, 5); - - gen_load_gpr(t0, Rb); - - tcg_gen_movi_tl(t1, s12); - tcg_gen_shli_tl(t1, t1, 2); - if (s12 & 0x200) { - tcg_gen_ori_tl(t1, t1, 0xFFFFF000); - } - tcg_gen_add_tl(t1, t0, t1); - tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL); - - if (sel == 1) { - /* S32LDDR */ - tcg_gen_bswap32_tl(t1, t1); - } - gen_store_mxu_gpr(t1, XRa); - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - - -/* - * MXU instruction category: logic - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * S32NOR S32AND S32OR S32XOR - */ - -/* - * S32NOR XRa, XRb, XRc - * Update XRa with the result of logical bitwise 'nor' operation - * applied to the content of XRb and XRc. - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16| - * +-----------+---------+-----+-------+-------+-------+-----------+ - */ -static void gen_mxu_S32NOR(DisasContext *ctx) -{ - uint32_t pad, XRc, XRb, XRa; - - pad = extract32(ctx->opcode, 21, 5); - XRc = extract32(ctx->opcode, 14, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRa = extract32(ctx->opcode, 6, 4); - - if (unlikely(pad != 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa == 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb == 0) && (XRc == 0))) { - /* both operands zero registers -> just set destination to all 1s */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF); - } else if (unlikely(XRb == 0)) { - /* XRb zero register -> just set destination to the negation of XRc */ - tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - } else if (unlikely(XRc == 0)) { - /* XRa zero register -> just set destination to the negation of XRb */ - tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else if (unlikely(XRb == XRc)) { - /* both operands same -> just set destination to the negation of XRb */ - tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); - } -} - -/* - * S32AND XRa, XRb, XRc - * Update XRa with the result of logical bitwise 'and' operation - * applied to the content of XRb and XRc. - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16| - * +-----------+---------+-----+-------+-------+-------+-----------+ - */ -static void gen_mxu_S32AND(DisasContext *ctx) -{ - uint32_t pad, XRc, XRb, XRa; - - pad = extract32(ctx->opcode, 21, 5); - XRc = extract32(ctx->opcode, 14, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRa = extract32(ctx->opcode, 6, 4); - - if (unlikely(pad != 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa == 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb == 0) || (XRc == 0))) { - /* one of operands zero register -> just set destination to all 0s */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely(XRb == XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); - } -} - -/* - * S32OR XRa, XRb, XRc - * Update XRa with the result of logical bitwise 'or' operation - * applied to the content of XRb and XRc. - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16| - * +-----------+---------+-----+-------+-------+-------+-----------+ - */ -static void gen_mxu_S32OR(DisasContext *ctx) -{ - uint32_t pad, XRc, XRb, XRa; - - pad = extract32(ctx->opcode, 21, 5); - XRc = extract32(ctx->opcode, 14, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRa = extract32(ctx->opcode, 6, 4); - - if (unlikely(pad != 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa == 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb == 0) && (XRc == 0))) { - /* both operands zero registers -> just set destination to all 0s */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely(XRb == 0)) { - /* XRb zero register -> just set destination to the content of XRc */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - } else if (unlikely(XRc == 0)) { - /* XRc zero register -> just set destination to the content of XRb */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else if (unlikely(XRb == XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); - } -} - -/* - * S32XOR XRa, XRb, XRc - * Update XRa with the result of logical bitwise 'xor' operation - * applied to the content of XRb and XRc. - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16| - * +-----------+---------+-----+-------+-------+-------+-----------+ - */ -static void gen_mxu_S32XOR(DisasContext *ctx) -{ - uint32_t pad, XRc, XRb, XRa; - - pad = extract32(ctx->opcode, 21, 5); - XRc = extract32(ctx->opcode, 14, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRa = extract32(ctx->opcode, 6, 4); - - if (unlikely(pad != 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa == 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb == 0) && (XRc == 0))) { - /* both operands zero registers -> just set destination to all 0s */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely(XRb == 0)) { - /* XRb zero register -> just set destination to the content of XRc */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - } else if (unlikely(XRc == 0)) { - /* XRc zero register -> just set destination to the content of XRb */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else if (unlikely(XRb == XRc)) { - /* both operands same -> just set destination to all 0s */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else { - /* the most general case */ - tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); - } -} - - -/* - * MXU instruction category max/min - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * S32MAX D16MAX Q8MAX - * S32MIN D16MIN Q8MIN - */ - -/* - * S32MAX XRa, XRb, XRc - * Update XRa with the maximum of signed 32-bit integers contained - * in XRb and XRc. - * - * S32MIN XRa, XRb, XRc - * Update XRa with the minimum of signed 32-bit integers contained - * in XRb and XRc. - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00| - * +-----------+---------+-----+-------+-------+-------+-----------+ - */ -static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx) -{ - uint32_t pad, opc, XRc, XRb, XRa; - - pad = extract32(ctx->opcode, 21, 5); - opc = extract32(ctx->opcode, 18, 3); - XRc = extract32(ctx->opcode, 14, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRa = extract32(ctx->opcode, 6, 4); - - if (unlikely(pad != 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa == 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb == 0) && (XRc == 0))) { - /* both operands zero registers -> just set destination to zero */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely((XRb == 0) || (XRc == 0))) { - /* exactly one operand is zero register - find which one is not...*/ - uint32_t XRx = XRb ? XRb : XRc; - /* ...and do max/min operation with one operand 0 */ - if (opc == OPC_MXU_S32MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); - } - } else if (unlikely(XRb == XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - if (opc == OPC_MXU_S32MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], - mxu_gpr[XRc - 1]); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], - mxu_gpr[XRc - 1]); - } - } -} - -/* - * D16MAX - * Update XRa with the 16-bit-wise maximums of signed integers - * contained in XRb and XRc. - * - * D16MIN - * Update XRa with the 16-bit-wise minimums of signed integers - * contained in XRb and XRc. - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00| - * +-----------+---------+-----+-------+-------+-------+-----------+ - */ -static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) -{ - uint32_t pad, opc, XRc, XRb, XRa; - - pad = extract32(ctx->opcode, 21, 5); - opc = extract32(ctx->opcode, 18, 3); - XRc = extract32(ctx->opcode, 14, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRa = extract32(ctx->opcode, 6, 4); - - if (unlikely(pad != 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRc == 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb == 0) && (XRa == 0))) { - /* both operands zero registers -> just set destination to zero */ - tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0); - } else if (unlikely((XRb == 0) || (XRa == 0))) { - /* exactly one operand is zero register - find which one is not...*/ - uint32_t XRx = XRb ? XRb : XRc; - /* ...and do half-word-wise max/min with one operand 0 */ - TCGv_i32 t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_const_i32(0); - - /* the left half-word first */ - tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000); - if (opc == OPC_MXU_D16MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); - } - - /* the right half-word */ - tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF); - /* move half-words to the leftmost position */ - tcg_gen_shli_i32(t0, t0, 16); - /* t0 will be max/min of t0 and t1 */ - if (opc == OPC_MXU_D16MAX) { - tcg_gen_smax_i32(t0, t0, t1); - } else { - tcg_gen_smin_i32(t0, t0, t1); - } - /* return resulting half-words to its original position */ - tcg_gen_shri_i32(t0, t0, 16); - /* finally update the destination */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } else if (unlikely(XRb == XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - TCGv_i32 t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_temp_new(); - - /* the left half-word first */ - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000); - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000); - if (opc == OPC_MXU_D16MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); - } - - /* the right half-word */ - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF); - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF); - /* move half-words to the leftmost position */ - tcg_gen_shli_i32(t0, t0, 16); - tcg_gen_shli_i32(t1, t1, 16); - /* t0 will be max/min of t0 and t1 */ - if (opc == OPC_MXU_D16MAX) { - tcg_gen_smax_i32(t0, t0, t1); - } else { - tcg_gen_smin_i32(t0, t0, t1); - } - /* return resulting half-words to its original position */ - tcg_gen_shri_i32(t0, t0, 16); - /* finally update the destination */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } -} - -/* - * Q8MAX - * Update XRa with the 8-bit-wise maximums of signed integers - * contained in XRb and XRc. - * - * Q8MIN - * Update XRa with the 8-bit-wise minimums of signed integers - * contained in XRb and XRc. - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00| - * +-----------+---------+-----+-------+-------+-------+-----------+ - */ -static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx) -{ - uint32_t pad, opc, XRc, XRb, XRa; - - pad = extract32(ctx->opcode, 21, 5); - opc = extract32(ctx->opcode, 18, 3); - XRc = extract32(ctx->opcode, 14, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRa = extract32(ctx->opcode, 6, 4); - - if (unlikely(pad != 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa == 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb == 0) && (XRc == 0))) { - /* both operands zero registers -> just set destination to zero */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely((XRb == 0) || (XRc == 0))) { - /* exactly one operand is zero register - make it be the first...*/ - uint32_t XRx = XRb ? XRb : XRc; - /* ...and do byte-wise max/min with one operand 0 */ - TCGv_i32 t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_const_i32(0); - int32_t i; - - /* the leftmost byte (byte 3) first */ - tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000); - if (opc == OPC_MXU_Q8MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); - } - - /* bytes 2, 1, 0 */ - for (i = 2; i >= 0; i--) { - /* extract the byte */ - tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i)); - /* move the byte to the leftmost position */ - tcg_gen_shli_i32(t0, t0, 8 * (3 - i)); - /* t0 will be max/min of t0 and t1 */ - if (opc == OPC_MXU_Q8MAX) { - tcg_gen_smax_i32(t0, t0, t1); - } else { - tcg_gen_smin_i32(t0, t0, t1); - } - /* return resulting byte to its original position */ - tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); - /* finally update the destination */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); - } - - tcg_temp_free(t1); - tcg_temp_free(t0); - } else if (unlikely(XRb == XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - TCGv_i32 t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_temp_new(); - int32_t i; - - /* the leftmost bytes (bytes 3) first */ - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000); - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000); - if (opc == OPC_MXU_Q8MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); - } - - /* bytes 2, 1, 0 */ - for (i = 2; i >= 0; i--) { - /* extract corresponding bytes */ - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i)); - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i)); - /* move the bytes to the leftmost position */ - tcg_gen_shli_i32(t0, t0, 8 * (3 - i)); - tcg_gen_shli_i32(t1, t1, 8 * (3 - i)); - /* t0 will be max/min of t0 and t1 */ - if (opc == OPC_MXU_Q8MAX) { - tcg_gen_smax_i32(t0, t0, t1); - } else { - tcg_gen_smin_i32(t0, t0, t1); - } - /* return resulting byte to its original position */ - tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); - /* finally update the destination */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); - } - - tcg_temp_free(t1); - tcg_temp_free(t0); - } -} - - -/* - * MXU instruction category: align - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * S32ALN S32ALNI - */ - -/* - * S32ALNI XRc, XRb, XRa, optn3 - * Arrange bytes from XRb and XRc according to one of five sets of - * rules determined by optn3, and place the result in XRa. - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+-----+---+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16| - * +-----------+-----+---+-----+-------+-------+-------+-----------+ - * - */ -static void gen_mxu_S32ALNI(DisasContext *ctx) -{ - uint32_t optn3, pad, XRc, XRb, XRa; - - optn3 = extract32(ctx->opcode, 23, 3); - pad = extract32(ctx->opcode, 21, 2); - XRc = extract32(ctx->opcode, 14, 4); - XRb = extract32(ctx->opcode, 10, 4); - XRa = extract32(ctx->opcode, 6, 4); - - if (unlikely(pad != 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa == 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb == 0) && (XRc == 0))) { - /* both operands zero registers -> just set destination to all 0s */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely(XRb == 0)) { - /* XRb zero register -> just appropriatelly shift XRc into XRa */ - switch (optn3) { - case MXU_OPTN3_PTN0: - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - break; - case MXU_OPTN3_PTN1: - case MXU_OPTN3_PTN2: - case MXU_OPTN3_PTN3: - tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1], - 8 * (4 - optn3)); - break; - case MXU_OPTN3_PTN4: - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - break; - } - } else if (unlikely(XRc == 0)) { - /* XRc zero register -> just appropriatelly shift XRb into XRa */ - switch (optn3) { - case MXU_OPTN3_PTN0: - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - break; - case MXU_OPTN3_PTN1: - case MXU_OPTN3_PTN2: - case MXU_OPTN3_PTN3: - tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3); - break; - case MXU_OPTN3_PTN4: - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - break; - } - } else if (unlikely(XRb == XRc)) { - /* both operands same -> just rotation or moving from any of them */ - switch (optn3) { - case MXU_OPTN3_PTN0: - case MXU_OPTN3_PTN4: - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - break; - case MXU_OPTN3_PTN1: - case MXU_OPTN3_PTN2: - case MXU_OPTN3_PTN3: - tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3); - break; - } - } else { - /* the most general case */ - switch (optn3) { - case MXU_OPTN3_PTN0: - { - /* */ - /* XRb XRc */ - /* +---------------+ */ - /* | A B C D | E F G H */ - /* +-------+-------+ */ - /* | */ - /* XRa */ - /* */ - - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } - break; - case MXU_OPTN3_PTN1: - { - /* */ - /* XRb XRc */ - /* +-------------------+ */ - /* A | B C D E | F G H */ - /* +---------+---------+ */ - /* | */ - /* XRa */ - /* */ - - TCGv_i32 t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_temp_new(); - - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF); - tcg_gen_shli_i32(t0, t0, 8); - - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000); - tcg_gen_shri_i32(t1, t1, 24); - - tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } - break; - case MXU_OPTN3_PTN2: - { - /* */ - /* XRb XRc */ - /* +-------------------+ */ - /* A B | C D E F | G H */ - /* +---------+---------+ */ - /* | */ - /* XRa */ - /* */ - - TCGv_i32 t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_temp_new(); - - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF); - tcg_gen_shli_i32(t0, t0, 16); - - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000); - tcg_gen_shri_i32(t1, t1, 16); - - tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } - break; - case MXU_OPTN3_PTN3: - { - /* */ - /* XRb XRc */ - /* +-------------------+ */ - /* A B C | D E F G | H */ - /* +---------+---------+ */ - /* | */ - /* XRa */ - /* */ - - TCGv_i32 t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_temp_new(); - - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF); - tcg_gen_shli_i32(t0, t0, 24); - - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00); - tcg_gen_shri_i32(t1, t1, 8); - - tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } - break; - case MXU_OPTN3_PTN4: - { - /* */ - /* XRb XRc */ - /* +---------------+ */ - /* A B C D | E F G H | */ - /* +-------+-------+ */ - /* | */ - /* XRa */ - /* */ - - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - } - break; - } - } -} - - -/* - * Decoding engine for MXU - * ======================= - */ - -/* - * - * Decode MXU pool00 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00| - * +-----------+---------+-----+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 18, 3); - - switch (opcode) { - case OPC_MXU_S32MAX: - case OPC_MXU_S32MIN: - gen_mxu_S32MAX_S32MIN(ctx); - break; - case OPC_MXU_D16MAX: - case OPC_MXU_D16MIN: - gen_mxu_D16MAX_D16MIN(ctx); - break; - case OPC_MXU_Q8MAX: - case OPC_MXU_Q8MIN: - gen_mxu_Q8MAX_Q8MIN(ctx); - break; - case OPC_MXU_Q8SLT: - /* TODO: Implement emulation of Q8SLT instruction. */ - MIPS_INVAL("OPC_MXU_Q8SLT"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8SLTU: - /* TODO: Implement emulation of Q8SLTU instruction. */ - MIPS_INVAL("OPC_MXU_Q8SLTU"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool01 - * - * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01| - * +-----------+---------+-----+-------+-------+-------+-----------+ - * - * Q8ADD: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+-----+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01| - * +-----------+---+-----+-----+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 18, 3); - - switch (opcode) { - case OPC_MXU_S32SLT: - /* TODO: Implement emulation of S32SLT instruction. */ - MIPS_INVAL("OPC_MXU_S32SLT"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16SLT: - /* TODO: Implement emulation of D16SLT instruction. */ - MIPS_INVAL("OPC_MXU_D16SLT"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16AVG: - /* TODO: Implement emulation of D16AVG instruction. */ - MIPS_INVAL("OPC_MXU_D16AVG"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16AVGR: - /* TODO: Implement emulation of D16AVGR instruction. */ - MIPS_INVAL("OPC_MXU_D16AVGR"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8AVG: - /* TODO: Implement emulation of Q8AVG instruction. */ - MIPS_INVAL("OPC_MXU_Q8AVG"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8AVGR: - /* TODO: Implement emulation of Q8AVGR instruction. */ - MIPS_INVAL("OPC_MXU_Q8AVGR"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8ADD: - /* TODO: Implement emulation of Q8ADD instruction. */ - MIPS_INVAL("OPC_MXU_Q8ADD"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool02 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02| - * +-----------+---------+-----+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 18, 3); - - switch (opcode) { - case OPC_MXU_S32CPS: - /* TODO: Implement emulation of S32CPS instruction. */ - MIPS_INVAL("OPC_MXU_S32CPS"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16CPS: - /* TODO: Implement emulation of D16CPS instruction. */ - MIPS_INVAL("OPC_MXU_D16CPS"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8ABD: - /* TODO: Implement emulation of Q8ABD instruction. */ - MIPS_INVAL("OPC_MXU_Q8ABD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16SAT: - /* TODO: Implement emulation of Q16SAT instruction. */ - MIPS_INVAL("OPC_MXU_Q16SAT"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool03 - * - * D16MULF: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03| - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * - * D16MULE: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03| - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 24, 2); - - switch (opcode) { - case OPC_MXU_D16MULF: - /* TODO: Implement emulation of D16MULF instruction. */ - MIPS_INVAL("OPC_MXU_D16MULF"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16MULE: - /* TODO: Implement emulation of D16MULE instruction. */ - MIPS_INVAL("OPC_MXU_D16MULE"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool04 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-+-------------------+-------+-----------+ - * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04| - * +-----------+---------+-+-------------------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 20, 1); - - switch (opcode) { - case OPC_MXU_S32LDD: - case OPC_MXU_S32LDDR: - gen_mxu_s32ldd_s32lddr(ctx); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool05 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-+-------------------+-------+-----------+ - * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05| - * +-----------+---------+-+-------------------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 20, 1); - - switch (opcode) { - case OPC_MXU_S32STD: - /* TODO: Implement emulation of S32STD instruction. */ - MIPS_INVAL("OPC_MXU_S32STD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32STDR: - /* TODO: Implement emulation of S32STDR instruction. */ - MIPS_INVAL("OPC_MXU_S32STDR"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool06 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---+-------+-------+-----------+ - * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06| - * +-----------+---------+---------+---+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 10, 4); - - switch (opcode) { - case OPC_MXU_S32LDDV: - /* TODO: Implement emulation of S32LDDV instruction. */ - MIPS_INVAL("OPC_MXU_S32LDDV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32LDDVR: - /* TODO: Implement emulation of S32LDDVR instruction. */ - MIPS_INVAL("OPC_MXU_S32LDDVR"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool07 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---+-------+-------+-----------+ - * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07| - * +-----------+---------+---------+---+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 10, 4); - - switch (opcode) { - case OPC_MXU_S32STDV: - /* TODO: Implement emulation of S32TDV instruction. */ - MIPS_INVAL("OPC_MXU_S32TDV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32STDVR: - /* TODO: Implement emulation of S32TDVR instruction. */ - MIPS_INVAL("OPC_MXU_S32TDVR"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool08 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-+-------------------+-------+-----------+ - * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08| - * +-----------+---------+-+-------------------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 20, 1); - - switch (opcode) { - case OPC_MXU_S32LDI: - /* TODO: Implement emulation of S32LDI instruction. */ - MIPS_INVAL("OPC_MXU_S32LDI"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32LDIR: - /* TODO: Implement emulation of S32LDIR instruction. */ - MIPS_INVAL("OPC_MXU_S32LDIR"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool09 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-+-------------------+-------+-----------+ - * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09| - * +-----------+---------+-+-------------------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 5, 0); - - switch (opcode) { - case OPC_MXU_S32SDI: - /* TODO: Implement emulation of S32SDI instruction. */ - MIPS_INVAL("OPC_MXU_S32SDI"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32SDIR: - /* TODO: Implement emulation of S32SDIR instruction. */ - MIPS_INVAL("OPC_MXU_S32SDIR"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool10 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---+-------+-------+-----------+ - * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10| - * +-----------+---------+---------+---+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 5, 0); - - switch (opcode) { - case OPC_MXU_S32LDIV: - /* TODO: Implement emulation of S32LDIV instruction. */ - MIPS_INVAL("OPC_MXU_S32LDIV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32LDIVR: - /* TODO: Implement emulation of S32LDIVR instruction. */ - MIPS_INVAL("OPC_MXU_S32LDIVR"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool11 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---+-------+-------+-----------+ - * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11| - * +-----------+---------+---------+---+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 10, 4); - - switch (opcode) { - case OPC_MXU_S32SDIV: - /* TODO: Implement emulation of S32SDIV instruction. */ - MIPS_INVAL("OPC_MXU_S32SDIV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32SDIVR: - /* TODO: Implement emulation of S32SDIVR instruction. */ - MIPS_INVAL("OPC_MXU_S32SDIVR"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool12 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12| - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 22, 2); - - switch (opcode) { - case OPC_MXU_D32ACC: - /* TODO: Implement emulation of D32ACC instruction. */ - MIPS_INVAL("OPC_MXU_D32ACC"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D32ACCM: - /* TODO: Implement emulation of D32ACCM instruction. */ - MIPS_INVAL("OPC_MXU_D32ACCM"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D32ASUM: - /* TODO: Implement emulation of D32ASUM instruction. */ - MIPS_INVAL("OPC_MXU_D32ASUM"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool13 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13| - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 22, 2); - - switch (opcode) { - case OPC_MXU_Q16ACC: - /* TODO: Implement emulation of Q16ACC instruction. */ - MIPS_INVAL("OPC_MXU_Q16ACC"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16ACCM: - /* TODO: Implement emulation of Q16ACCM instruction. */ - MIPS_INVAL("OPC_MXU_Q16ACCM"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16ASUM: - /* TODO: Implement emulation of Q16ASUM instruction. */ - MIPS_INVAL("OPC_MXU_Q16ASUM"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool14 - * - * Q8ADDE, Q8ACCE: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14| - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * - * D8SUM, D8SUMC: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14| - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 22, 2); - - switch (opcode) { - case OPC_MXU_Q8ADDE: - /* TODO: Implement emulation of Q8ADDE instruction. */ - MIPS_INVAL("OPC_MXU_Q8ADDE"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D8SUM: - /* TODO: Implement emulation of D8SUM instruction. */ - MIPS_INVAL("OPC_MXU_D8SUM"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D8SUMC: - /* TODO: Implement emulation of D8SUMC instruction. */ - MIPS_INVAL("OPC_MXU_D8SUMC"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool15 - * - * S32MUL, S32MULU, S32EXTRV: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---+-------+-------+-----------+ - * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15| - * +-----------+---------+---------+---+-------+-------+-----------+ - * - * S32EXTR: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---+-------+-------+-----------+ - * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15| - * +-----------+---------+---------+---+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 14, 2); - - switch (opcode) { - case OPC_MXU_S32MUL: - /* TODO: Implement emulation of S32MUL instruction. */ - MIPS_INVAL("OPC_MXU_S32MUL"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32MULU: - /* TODO: Implement emulation of S32MULU instruction. */ - MIPS_INVAL("OPC_MXU_S32MULU"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32EXTR: - /* TODO: Implement emulation of S32EXTR instruction. */ - MIPS_INVAL("OPC_MXU_S32EXTR"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32EXTRV: - /* TODO: Implement emulation of S32EXTRV instruction. */ - MIPS_INVAL("OPC_MXU_S32EXTRV"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool16 - * - * D32SARW: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16| - * +-----------+---------+-----+-------+-------+-------+-----------+ - * - * S32ALN: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16| - * +-----------+---------+-----+-------+-------+-------+-----------+ - * - * S32ALNI: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+-----+---+-----+-------+-------+-------+-----------+ - * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16| - * +-----------+-----+---+-----+-------+-------+-------+-----------+ - * - * S32LUI: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+-----+---+-----+-------+---------------+-----------+ - * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16| - * +-----------+-----+---+-----+-------+---------------+-----------+ - * - * S32NOR, S32AND, S32OR, S32XOR: - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16| - * +-----------+---------+-----+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 18, 3); - - switch (opcode) { - case OPC_MXU_D32SARW: - /* TODO: Implement emulation of D32SARW instruction. */ - MIPS_INVAL("OPC_MXU_D32SARW"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32ALN: - /* TODO: Implement emulation of S32ALN instruction. */ - MIPS_INVAL("OPC_MXU_S32ALN"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32ALNI: - gen_mxu_S32ALNI(ctx); - break; - case OPC_MXU_S32LUI: - /* TODO: Implement emulation of S32LUI instruction. */ - MIPS_INVAL("OPC_MXU_S32LUI"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32NOR: - gen_mxu_S32NOR(ctx); - break; - case OPC_MXU_S32AND: - gen_mxu_S32AND(ctx); - break; - case OPC_MXU_S32OR: - gen_mxu_S32OR(ctx); - break; - case OPC_MXU_S32XOR: - gen_mxu_S32XOR(ctx); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool17 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---+---------+-----+-----------+ - * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15| - * +-----------+---------+---------+---+---------+-----+-----------+ - * - */ -static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 6, 2); - - switch (opcode) { - case OPC_MXU_LXW: - /* TODO: Implement emulation of LXW instruction. */ - MIPS_INVAL("OPC_MXU_LXW"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_LXH: - /* TODO: Implement emulation of LXH instruction. */ - MIPS_INVAL("OPC_MXU_LXH"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_LXHU: - /* TODO: Implement emulation of LXHU instruction. */ - MIPS_INVAL("OPC_MXU_LXHU"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_LXB: - /* TODO: Implement emulation of LXB instruction. */ - MIPS_INVAL("OPC_MXU_LXB"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_LXBU: - /* TODO: Implement emulation of LXBU instruction. */ - MIPS_INVAL("OPC_MXU_LXBU"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} -/* - * - * Decode MXU pool18 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18| - * +-----------+---------+-----+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 18, 3); - - switch (opcode) { - case OPC_MXU_D32SLLV: - /* TODO: Implement emulation of D32SLLV instruction. */ - MIPS_INVAL("OPC_MXU_D32SLLV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D32SLRV: - /* TODO: Implement emulation of D32SLRV instruction. */ - MIPS_INVAL("OPC_MXU_D32SLRV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D32SARV: - /* TODO: Implement emulation of D32SARV instruction. */ - MIPS_INVAL("OPC_MXU_D32SARV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16SLLV: - /* TODO: Implement emulation of Q16SLLV instruction. */ - MIPS_INVAL("OPC_MXU_Q16SLLV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16SLRV: - /* TODO: Implement emulation of Q16SLRV instruction. */ - MIPS_INVAL("OPC_MXU_Q16SLRV"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16SARV: - /* TODO: Implement emulation of Q16SARV instruction. */ - MIPS_INVAL("OPC_MXU_Q16SARV"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool19 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19| - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 22, 2); - - switch (opcode) { - case OPC_MXU_Q8MUL: - case OPC_MXU_Q8MULSU: - gen_mxu_q8mul_q8mulsu(ctx); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool20 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+-----+-------+-------+-------+-----------+ - * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20| - * +-----------+---------+-----+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 18, 3); - - switch (opcode) { - case OPC_MXU_Q8MOVZ: - /* TODO: Implement emulation of Q8MOVZ instruction. */ - MIPS_INVAL("OPC_MXU_Q8MOVZ"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8MOVN: - /* TODO: Implement emulation of Q8MOVN instruction. */ - MIPS_INVAL("OPC_MXU_Q8MOVN"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16MOVZ: - /* TODO: Implement emulation of D16MOVZ instruction. */ - MIPS_INVAL("OPC_MXU_D16MOVZ"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16MOVN: - /* TODO: Implement emulation of D16MOVN instruction. */ - MIPS_INVAL("OPC_MXU_D16MOVN"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32MOVZ: - /* TODO: Implement emulation of S32MOVZ instruction. */ - MIPS_INVAL("OPC_MXU_S32MOVZ"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32MOVN: - /* TODO: Implement emulation of S32MOVN instruction. */ - MIPS_INVAL("OPC_MXU_S32MOVN"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - -/* - * - * Decode MXU pool21 - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21| - * +-----------+---+---+-------+-------+-------+-------+-----------+ - * - */ -static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opcode = extract32(ctx->opcode, 22, 2); - - switch (opcode) { - case OPC_MXU_Q8MAC: - /* TODO: Implement emulation of Q8MAC instruction. */ - MIPS_INVAL("OPC_MXU_Q8MAC"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8MACSU: - /* TODO: Implement emulation of Q8MACSU instruction. */ - MIPS_INVAL("OPC_MXU_Q8MACSU"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - - -/* - * Main MXU decoding function - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------------------------------------+-----------+ - * | SPECIAL2 | |x x x x x x| - * +-----------+---------------------------------------+-----------+ - * - */ -static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx) -{ - /* - * TODO: Investigate necessity of including handling of - * CLZ, CLO, SDBB in this function, as they belong to - * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs. - */ - uint32_t opcode = extract32(ctx->opcode, 0, 6); - - if (opcode == OPC__MXU_MUL) { - uint32_t rs, rt, rd, op1; - - rs = extract32(ctx->opcode, 21, 5); - rt = extract32(ctx->opcode, 16, 5); - rd = extract32(ctx->opcode, 11, 5); - op1 = MASK_SPECIAL2(ctx->opcode); - - gen_arith(ctx, op1, rd, rs, rt); - - return; - } - - if (opcode == OPC_MXU_S32M2I) { - gen_mxu_s32m2i(ctx); - return; - } - - if (opcode == OPC_MXU_S32I2M) { - gen_mxu_s32i2m(ctx); - return; - } - - { - TCGv t_mxu_cr = tcg_temp_new(); - TCGLabel *l_exit = gen_new_label(); - - gen_load_mxu_cr(t_mxu_cr); - tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN); - tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit); - - switch (opcode) { - case OPC_MXU_S32MADD: - /* TODO: Implement emulation of S32MADD instruction. */ - MIPS_INVAL("OPC_MXU_S32MADD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32MADDU: - /* TODO: Implement emulation of S32MADDU instruction. */ - MIPS_INVAL("OPC_MXU_S32MADDU"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU__POOL00: - decode_opc_mxu__pool00(env, ctx); - break; - case OPC_MXU_S32MSUB: - /* TODO: Implement emulation of S32MSUB instruction. */ - MIPS_INVAL("OPC_MXU_S32MSUB"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32MSUBU: - /* TODO: Implement emulation of S32MSUBU instruction. */ - MIPS_INVAL("OPC_MXU_S32MSUBU"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU__POOL01: - decode_opc_mxu__pool01(env, ctx); - break; - case OPC_MXU__POOL02: - decode_opc_mxu__pool02(env, ctx); - break; - case OPC_MXU_D16MUL: - gen_mxu_d16mul(ctx); - break; - case OPC_MXU__POOL03: - decode_opc_mxu__pool03(env, ctx); - break; - case OPC_MXU_D16MAC: - gen_mxu_d16mac(ctx); - break; - case OPC_MXU_D16MACF: - /* TODO: Implement emulation of D16MACF instruction. */ - MIPS_INVAL("OPC_MXU_D16MACF"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16MADL: - /* TODO: Implement emulation of D16MADL instruction. */ - MIPS_INVAL("OPC_MXU_D16MADL"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S16MAD: - /* TODO: Implement emulation of S16MAD instruction. */ - MIPS_INVAL("OPC_MXU_S16MAD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16ADD: - /* TODO: Implement emulation of Q16ADD instruction. */ - MIPS_INVAL("OPC_MXU_Q16ADD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D16MACE: - /* TODO: Implement emulation of D16MACE instruction. */ - MIPS_INVAL("OPC_MXU_D16MACE"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU__POOL04: - decode_opc_mxu__pool04(env, ctx); - break; - case OPC_MXU__POOL05: - decode_opc_mxu__pool05(env, ctx); - break; - case OPC_MXU__POOL06: - decode_opc_mxu__pool06(env, ctx); - break; - case OPC_MXU__POOL07: - decode_opc_mxu__pool07(env, ctx); - break; - case OPC_MXU__POOL08: - decode_opc_mxu__pool08(env, ctx); - break; - case OPC_MXU__POOL09: - decode_opc_mxu__pool09(env, ctx); - break; - case OPC_MXU__POOL10: - decode_opc_mxu__pool10(env, ctx); - break; - case OPC_MXU__POOL11: - decode_opc_mxu__pool11(env, ctx); - break; - case OPC_MXU_D32ADD: - /* TODO: Implement emulation of D32ADD instruction. */ - MIPS_INVAL("OPC_MXU_D32ADD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU__POOL12: - decode_opc_mxu__pool12(env, ctx); - break; - case OPC_MXU__POOL13: - decode_opc_mxu__pool13(env, ctx); - break; - case OPC_MXU__POOL14: - decode_opc_mxu__pool14(env, ctx); - break; - case OPC_MXU_Q8ACCE: - /* TODO: Implement emulation of Q8ACCE instruction. */ - MIPS_INVAL("OPC_MXU_Q8ACCE"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S8LDD: - gen_mxu_s8ldd(ctx); - break; - case OPC_MXU_S8STD: - /* TODO: Implement emulation of S8STD instruction. */ - MIPS_INVAL("OPC_MXU_S8STD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S8LDI: - /* TODO: Implement emulation of S8LDI instruction. */ - MIPS_INVAL("OPC_MXU_S8LDI"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S8SDI: - /* TODO: Implement emulation of S8SDI instruction. */ - MIPS_INVAL("OPC_MXU_S8SDI"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU__POOL15: - decode_opc_mxu__pool15(env, ctx); - break; - case OPC_MXU__POOL16: - decode_opc_mxu__pool16(env, ctx); - break; - case OPC_MXU__POOL17: - decode_opc_mxu__pool17(env, ctx); - break; - case OPC_MXU_S16LDD: - /* TODO: Implement emulation of S16LDD instruction. */ - MIPS_INVAL("OPC_MXU_S16LDD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S16STD: - /* TODO: Implement emulation of S16STD instruction. */ - MIPS_INVAL("OPC_MXU_S16STD"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S16LDI: - /* TODO: Implement emulation of S16LDI instruction. */ - MIPS_INVAL("OPC_MXU_S16LDI"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S16SDI: - /* TODO: Implement emulation of S16SDI instruction. */ - MIPS_INVAL("OPC_MXU_S16SDI"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D32SLL: - /* TODO: Implement emulation of D32SLL instruction. */ - MIPS_INVAL("OPC_MXU_D32SLL"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D32SLR: - /* TODO: Implement emulation of D32SLR instruction. */ - MIPS_INVAL("OPC_MXU_D32SLR"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D32SARL: - /* TODO: Implement emulation of D32SARL instruction. */ - MIPS_INVAL("OPC_MXU_D32SARL"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_D32SAR: - /* TODO: Implement emulation of D32SAR instruction. */ - MIPS_INVAL("OPC_MXU_D32SAR"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16SLL: - /* TODO: Implement emulation of Q16SLL instruction. */ - MIPS_INVAL("OPC_MXU_Q16SLL"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q16SLR: - /* TODO: Implement emulation of Q16SLR instruction. */ - MIPS_INVAL("OPC_MXU_Q16SLR"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU__POOL18: - decode_opc_mxu__pool18(env, ctx); - break; - case OPC_MXU_Q16SAR: - /* TODO: Implement emulation of Q16SAR instruction. */ - MIPS_INVAL("OPC_MXU_Q16SAR"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU__POOL19: - decode_opc_mxu__pool19(env, ctx); - break; - case OPC_MXU__POOL20: - decode_opc_mxu__pool20(env, ctx); - break; - case OPC_MXU__POOL21: - decode_opc_mxu__pool21(env, ctx); - break; - case OPC_MXU_Q16SCOP: - /* TODO: Implement emulation of Q16SCOP instruction. */ - MIPS_INVAL("OPC_MXU_Q16SCOP"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8MADL: - /* TODO: Implement emulation of Q8MADL instruction. */ - MIPS_INVAL("OPC_MXU_Q8MADL"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_S32SFL: - /* TODO: Implement emulation of S32SFL instruction. */ - MIPS_INVAL("OPC_MXU_S32SFL"); - generate_exception_end(ctx, EXCP_RI); - break; - case OPC_MXU_Q8SAD: - /* TODO: Implement emulation of Q8SAD instruction. */ - MIPS_INVAL("OPC_MXU_Q8SAD"); - generate_exception_end(ctx, EXCP_RI); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - generate_exception_end(ctx, EXCP_RI); - } - - gen_set_label(l_exit); - tcg_temp_free(t_mxu_cr); - } -} - -#endif /* !defined(TARGET_MIPS64) */ - - static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd; diff --git a/target/mips/vendor-mxu_translate.c.inc b/target/mips/vendor-mxu_translate.c.inc new file mode 100644 index 00000000000..21c5e45efac --- /dev/null +++ b/target/mips/vendor-mxu_translate.c.inc @@ -0,0 +1,2892 @@ +/* + * Ingenic XBurst Media eXtension Unit (MXU) translation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * Datasheet: + * + * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit + * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017 + * + * + * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET + * ============================================ + * + * + * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32 + * instructions set. It is designed to fit the needs of signal, graphical and + * video processing applications. MXU instruction set is used in Xburst family + * of microprocessors by Ingenic. + * + * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is + * the control register. + * + * + * The notation used in MXU assembler mnemonics + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Register operands: + * + * XRa, XRb, XRc, XRd - MXU registers + * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers + * + * Non-register operands: + * + * aptn1 - 1-bit accumulate add/subtract pattern + * aptn2 - 2-bit accumulate add/subtract pattern + * eptn2 - 2-bit execute add/subtract pattern + * optn2 - 2-bit operand pattern + * optn3 - 3-bit operand pattern + * sft4 - 4-bit shift amount + * strd2 - 2-bit stride amount + * + * Prefixes: + * + * Level of parallelism: Operand size: + * S - single operation at a time 32 - word + * D - two operations in parallel 16 - half word + * Q - four operations in parallel 8 - byte + * + * Operations: + * + * ADD - Add or subtract + * ADDC - Add with carry-in + * ACC - Accumulate + * ASUM - Sum together then accumulate (add or subtract) + * ASUMC - Sum together then accumulate (add or subtract) with carry-in + * AVG - Average between 2 operands + * ABD - Absolute difference + * ALN - Align data + * AND - Logical bitwise 'and' operation + * CPS - Copy sign + * EXTR - Extract bits + * I2M - Move from GPR register to MXU register + * LDD - Load data from memory to XRF + * LDI - Load data from memory to XRF (and increase the address base) + * LUI - Load unsigned immediate + * MUL - Multiply + * MULU - Unsigned multiply + * MADD - 64-bit operand add 32x32 product + * MSUB - 64-bit operand subtract 32x32 product + * MAC - Multiply and accumulate (add or subtract) + * MAD - Multiply and add or subtract + * MAX - Maximum between 2 operands + * MIN - Minimum between 2 operands + * M2I - Move from MXU register to GPR register + * MOVZ - Move if zero + * MOVN - Move if non-zero + * NOR - Logical bitwise 'nor' operation + * OR - Logical bitwise 'or' operation + * STD - Store data from XRF to memory + * SDI - Store data from XRF to memory (and increase the address base) + * SLT - Set of less than comparison + * SAD - Sum of absolute differences + * SLL - Logical shift left + * SLR - Logical shift right + * SAR - Arithmetic shift right + * SAT - Saturation + * SFL - Shuffle + * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0) + * XOR - Logical bitwise 'exclusive or' operation + * + * Suffixes: + * + * E - Expand results + * F - Fixed point multiplication + * L - Low part result + * R - Doing rounding + * V - Variable instead of immediate + * W - Combine above L and V + * + * + * The list of MXU instructions grouped by functionality + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Load/Store instructions Multiplication instructions + * ----------------------- --------------------------- + * + * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt + * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt + * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt + * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt + * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt + * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt + * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2 + * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2 + * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2 + * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 + * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2 + * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2 + * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2 + * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2 + * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd + * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd + * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2 + * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2 + * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2 + * S16SDI XRa, Rb, s10, eptn2 + * S8LDD XRa, Rb, s8, eptn3 + * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions + * S8LDI XRa, Rb, s8, eptn3 ------------------------------------- + * S8SDI XRa, Rb, s8, eptn3 + * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2 + * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd + * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2 + * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2 + * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2 + * S32CPS XRa, XRb, XRc + * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2 + * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2 + * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2 + * D16ASUM XRa, XRb, XRc, XRd, eptn2 + * S32MAX XRa, XRb, XRc D16CPS XRa, XRb, + * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc + * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc + * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2 + * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2 + * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2 + * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc + * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd + * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc + * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc + * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd + * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd + * Q8SLT XRa, XRb, XRc + * Q8SLTU XRa, XRb, XRc + * Q8MOVZ XRa, XRb, XRc Shift instructions + * Q8MOVN XRa, XRb, XRc ------------------ + * + * D32SLL XRa, XRb, XRc, XRd, sft4 + * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4 + * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4 + * D32SARL XRa, XRb, XRc, sft4 + * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb + * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb + * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb + * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb + * Q16SLL XRa, XRb, XRc, XRd, sft4 + * Q16SLR XRa, XRb, XRc, XRd, sft4 + * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4 + * ------------------------- Q16SLLV XRa, XRb, Rb + * Q16SLRV XRa, XRb, Rb + * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb + * S32ALN XRa, XRb, XRc, Rb + * S32ALNI XRa, XRb, XRc, s3 + * S32LUI XRa, s8, optn3 Move instructions + * S32EXTR XRa, XRb, Rb, bits5 ----------------- + * S32EXTRV XRa, XRb, Rs, Rt + * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb + * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb + * + * + * The opcode organization of MXU instructions + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred + * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of + * other bits up to the instruction level is as follows: + * + * bits + * 05..00 + * + * ┌─ 000000 ─ OPC_MXU_S32MADD + * ├─ 000001 ─ OPC_MXU_S32MADDU + * ├─ 000010 ─ (non-MXU OPC_MUL) + * │ + * │ 20..18 + * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX + * │ ├─ 001 ─ OPC_MXU_S32MIN + * │ ├─ 010 ─ OPC_MXU_D16MAX + * │ ├─ 011 ─ OPC_MXU_D16MIN + * │ ├─ 100 ─ OPC_MXU_Q8MAX + * │ ├─ 101 ─ OPC_MXU_Q8MIN + * │ ├─ 110 ─ OPC_MXU_Q8SLT + * │ └─ 111 ─ OPC_MXU_Q8SLTU + * ├─ 000100 ─ OPC_MXU_S32MSUB + * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18 + * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT + * │ ├─ 001 ─ OPC_MXU_D16SLT + * │ ├─ 010 ─ OPC_MXU_D16AVG + * │ ├─ 011 ─ OPC_MXU_D16AVGR + * │ ├─ 100 ─ OPC_MXU_Q8AVG + * │ ├─ 101 ─ OPC_MXU_Q8AVGR + * │ └─ 111 ─ OPC_MXU_Q8ADD + * │ + * │ 20..18 + * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS + * │ ├─ 010 ─ OPC_MXU_D16CPS + * │ ├─ 100 ─ OPC_MXU_Q8ABD + * │ └─ 110 ─ OPC_MXU_Q16SAT + * ├─ 001000 ─ OPC_MXU_D16MUL + * │ 25..24 + * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF + * │ └─ 01 ─ OPC_MXU_D16MULE + * ├─ 001010 ─ OPC_MXU_D16MAC + * ├─ 001011 ─ OPC_MXU_D16MACF + * ├─ 001100 ─ OPC_MXU_D16MADL + * ├─ 001101 ─ OPC_MXU_S16MAD + * ├─ 001110 ─ OPC_MXU_Q16ADD + * ├─ 001111 ─ OPC_MXU_D16MACE 23 + * │ ┌─ 0 ─ OPC_MXU_S32LDD + * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR + * │ + * │ 23 + * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD + * │ └─ 1 ─ OPC_MXU_S32STDR + * │ + * │ 13..10 + * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV + * │ └─ 0001 ─ OPC_MXU_S32LDDVR + * │ + * │ 13..10 + * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV + * │ └─ 0001 ─ OPC_MXU_S32STDVR + * │ + * │ 23 + * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI + * │ └─ 1 ─ OPC_MXU_S32LDIR + * │ + * │ 23 + * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI + * │ └─ 1 ─ OPC_MXU_S32SDIR + * │ + * │ 13..10 + * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV + * │ └─ 0001 ─ OPC_MXU_S32LDIVR + * │ + * │ 13..10 + * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV + * │ └─ 0001 ─ OPC_MXU_S32SDIVR + * ├─ 011000 ─ OPC_MXU_D32ADD + * │ 23..22 + * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC + * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM + * │ └─ 10 ─ OPC_MXU_D32ASUM + * ├─ 011010 ─ + * │ 23..22 + * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC + * │ ├─ 01 ─ OPC_MXU_Q16ACCM + * │ └─ 10 ─ OPC_MXU_Q16ASUM + * │ + * │ 23..22 + * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE + * │ ├─ 01 ─ OPC_MXU_D8SUM + * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC + * ├─ 011110 ─ + * ├─ 011111 ─ + * ├─ 100000 ─ (overlaps with CLZ) + * ├─ 100001 ─ (overlaps with CLO) + * ├─ 100010 ─ OPC_MXU_S8LDD + * ├─ 100011 ─ OPC_MXU_S8STD 15..14 + * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL + * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU + * │ ├─ 00 ─ OPC_MXU_S32EXTR + * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV + * │ + * │ 20..18 + * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW + * │ ├─ 001 ─ OPC_MXU_S32ALN + * │ ├─ 010 ─ OPC_MXU_S32ALNI + * │ ├─ 011 ─ OPC_MXU_S32LUI + * │ ├─ 100 ─ OPC_MXU_S32NOR + * │ ├─ 101 ─ OPC_MXU_S32AND + * │ ├─ 110 ─ OPC_MXU_S32OR + * │ └─ 111 ─ OPC_MXU_S32XOR + * │ + * │ 7..5 + * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB + * │ ├─ 001 ─ OPC_MXU_LXH + * ├─ 101001 ─ ├─ 011 ─ OPC_MXU_LXW + * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU + * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU + * ├─ 101100 ─ OPC_MXU_S16LDI + * ├─ 101101 ─ OPC_MXU_S16SDI + * ├─ 101110 ─ OPC_MXU_S32M2I + * ├─ 101111 ─ OPC_MXU_S32I2M + * ├─ 110000 ─ OPC_MXU_D32SLL + * ├─ 110001 ─ OPC_MXU_D32SLR 20..18 + * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV + * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV + * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV + * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV + * │ ├─ 100 ─ OPC_MXU_Q16SLRV + * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV + * │ + * ├─ 110111 ─ OPC_MXU_Q16SAR + * │ 23..22 + * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL + * │ └─ 01 ─ OPC_MXU_Q8MULSU + * │ + * │ 20..18 + * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ + * │ ├─ 001 ─ OPC_MXU_Q8MOVN + * │ ├─ 010 ─ OPC_MXU_D16MOVZ + * │ ├─ 011 ─ OPC_MXU_D16MOVN + * │ ├─ 100 ─ OPC_MXU_S32MOVZ + * │ └─ 101 ─ OPC_MXU_S32MOVN + * │ + * │ 23..22 + * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC + * │ └─ 10 ─ OPC_MXU_Q8MACSU + * ├─ 111011 ─ OPC_MXU_Q16SCOP + * ├─ 111100 ─ OPC_MXU_Q8MADL + * ├─ 111101 ─ OPC_MXU_S32SFL + * ├─ 111110 ─ OPC_MXU_Q8SAD + * └─ 111111 ─ (overlaps with SDBBP) + */ + +enum { + OPC_MXU_S32MADD = 0x00, + OPC_MXU_S32MADDU = 0x01, + OPC__MXU_MUL = 0x02, + OPC_MXU__POOL00 = 0x03, + OPC_MXU_S32MSUB = 0x04, + OPC_MXU_S32MSUBU = 0x05, + OPC_MXU__POOL01 = 0x06, + OPC_MXU__POOL02 = 0x07, + OPC_MXU_D16MUL = 0x08, + OPC_MXU__POOL03 = 0x09, + OPC_MXU_D16MAC = 0x0A, + OPC_MXU_D16MACF = 0x0B, + OPC_MXU_D16MADL = 0x0C, + OPC_MXU_S16MAD = 0x0D, + OPC_MXU_Q16ADD = 0x0E, + OPC_MXU_D16MACE = 0x0F, + OPC_MXU__POOL04 = 0x10, + OPC_MXU__POOL05 = 0x11, + OPC_MXU__POOL06 = 0x12, + OPC_MXU__POOL07 = 0x13, + OPC_MXU__POOL08 = 0x14, + OPC_MXU__POOL09 = 0x15, + OPC_MXU__POOL10 = 0x16, + OPC_MXU__POOL11 = 0x17, + OPC_MXU_D32ADD = 0x18, + OPC_MXU__POOL12 = 0x19, + /* not assigned 0x1A */ + OPC_MXU__POOL13 = 0x1B, + OPC_MXU__POOL14 = 0x1C, + OPC_MXU_Q8ACCE = 0x1D, + /* not assigned 0x1E */ + /* not assigned 0x1F */ + /* not assigned 0x20 */ + /* not assigned 0x21 */ + OPC_MXU_S8LDD = 0x22, + OPC_MXU_S8STD = 0x23, + OPC_MXU_S8LDI = 0x24, + OPC_MXU_S8SDI = 0x25, + OPC_MXU__POOL15 = 0x26, + OPC_MXU__POOL16 = 0x27, + OPC_MXU__POOL17 = 0x28, + /* not assigned 0x29 */ + OPC_MXU_S16LDD = 0x2A, + OPC_MXU_S16STD = 0x2B, + OPC_MXU_S16LDI = 0x2C, + OPC_MXU_S16SDI = 0x2D, + OPC_MXU_S32M2I = 0x2E, + OPC_MXU_S32I2M = 0x2F, + OPC_MXU_D32SLL = 0x30, + OPC_MXU_D32SLR = 0x31, + OPC_MXU_D32SARL = 0x32, + OPC_MXU_D32SAR = 0x33, + OPC_MXU_Q16SLL = 0x34, + OPC_MXU_Q16SLR = 0x35, + OPC_MXU__POOL18 = 0x36, + OPC_MXU_Q16SAR = 0x37, + OPC_MXU__POOL19 = 0x38, + OPC_MXU__POOL20 = 0x39, + OPC_MXU__POOL21 = 0x3A, + OPC_MXU_Q16SCOP = 0x3B, + OPC_MXU_Q8MADL = 0x3C, + OPC_MXU_S32SFL = 0x3D, + OPC_MXU_Q8SAD = 0x3E, + /* not assigned 0x3F */ +}; + + +/* + * MXU pool 00 + */ +enum { + OPC_MXU_S32MAX = 0x00, + OPC_MXU_S32MIN = 0x01, + OPC_MXU_D16MAX = 0x02, + OPC_MXU_D16MIN = 0x03, + OPC_MXU_Q8MAX = 0x04, + OPC_MXU_Q8MIN = 0x05, + OPC_MXU_Q8SLT = 0x06, + OPC_MXU_Q8SLTU = 0x07, +}; + +/* + * MXU pool 01 + */ +enum { + OPC_MXU_S32SLT = 0x00, + OPC_MXU_D16SLT = 0x01, + OPC_MXU_D16AVG = 0x02, + OPC_MXU_D16AVGR = 0x03, + OPC_MXU_Q8AVG = 0x04, + OPC_MXU_Q8AVGR = 0x05, + OPC_MXU_Q8ADD = 0x07, +}; + +/* + * MXU pool 02 + */ +enum { + OPC_MXU_S32CPS = 0x00, + OPC_MXU_D16CPS = 0x02, + OPC_MXU_Q8ABD = 0x04, + OPC_MXU_Q16SAT = 0x06, +}; + +/* + * MXU pool 03 + */ +enum { + OPC_MXU_D16MULF = 0x00, + OPC_MXU_D16MULE = 0x01, +}; + +/* + * MXU pool 04 + */ +enum { + OPC_MXU_S32LDD = 0x00, + OPC_MXU_S32LDDR = 0x01, +}; + +/* + * MXU pool 05 + */ +enum { + OPC_MXU_S32STD = 0x00, + OPC_MXU_S32STDR = 0x01, +}; + +/* + * MXU pool 06 + */ +enum { + OPC_MXU_S32LDDV = 0x00, + OPC_MXU_S32LDDVR = 0x01, +}; + +/* + * MXU pool 07 + */ +enum { + OPC_MXU_S32STDV = 0x00, + OPC_MXU_S32STDVR = 0x01, +}; + +/* + * MXU pool 08 + */ +enum { + OPC_MXU_S32LDI = 0x00, + OPC_MXU_S32LDIR = 0x01, +}; + +/* + * MXU pool 09 + */ +enum { + OPC_MXU_S32SDI = 0x00, + OPC_MXU_S32SDIR = 0x01, +}; + +/* + * MXU pool 10 + */ +enum { + OPC_MXU_S32LDIV = 0x00, + OPC_MXU_S32LDIVR = 0x01, +}; + +/* + * MXU pool 11 + */ +enum { + OPC_MXU_S32SDIV = 0x00, + OPC_MXU_S32SDIVR = 0x01, +}; + +/* + * MXU pool 12 + */ +enum { + OPC_MXU_D32ACC = 0x00, + OPC_MXU_D32ACCM = 0x01, + OPC_MXU_D32ASUM = 0x02, +}; + +/* + * MXU pool 13 + */ +enum { + OPC_MXU_Q16ACC = 0x00, + OPC_MXU_Q16ACCM = 0x01, + OPC_MXU_Q16ASUM = 0x02, +}; + +/* + * MXU pool 14 + */ +enum { + OPC_MXU_Q8ADDE = 0x00, + OPC_MXU_D8SUM = 0x01, + OPC_MXU_D8SUMC = 0x02, +}; + +/* + * MXU pool 15 + */ +enum { + OPC_MXU_S32MUL = 0x00, + OPC_MXU_S32MULU = 0x01, + OPC_MXU_S32EXTR = 0x02, + OPC_MXU_S32EXTRV = 0x03, +}; + +/* + * MXU pool 16 + */ +enum { + OPC_MXU_D32SARW = 0x00, + OPC_MXU_S32ALN = 0x01, + OPC_MXU_S32ALNI = 0x02, + OPC_MXU_S32LUI = 0x03, + OPC_MXU_S32NOR = 0x04, + OPC_MXU_S32AND = 0x05, + OPC_MXU_S32OR = 0x06, + OPC_MXU_S32XOR = 0x07, +}; + +/* + * MXU pool 17 + */ +enum { + OPC_MXU_LXB = 0x00, + OPC_MXU_LXH = 0x01, + OPC_MXU_LXW = 0x03, + OPC_MXU_LXBU = 0x04, + OPC_MXU_LXHU = 0x05, +}; + +/* + * MXU pool 18 + */ +enum { + OPC_MXU_D32SLLV = 0x00, + OPC_MXU_D32SLRV = 0x01, + OPC_MXU_D32SARV = 0x03, + OPC_MXU_Q16SLLV = 0x04, + OPC_MXU_Q16SLRV = 0x05, + OPC_MXU_Q16SARV = 0x07, +}; + +/* + * MXU pool 19 + */ +enum { + OPC_MXU_Q8MUL = 0x00, + OPC_MXU_Q8MULSU = 0x01, +}; + +/* + * MXU pool 20 + */ +enum { + OPC_MXU_Q8MOVZ = 0x00, + OPC_MXU_Q8MOVN = 0x01, + OPC_MXU_D16MOVZ = 0x02, + OPC_MXU_D16MOVN = 0x03, + OPC_MXU_S32MOVZ = 0x04, + OPC_MXU_S32MOVN = 0x05, +}; + +/* + * MXU pool 21 + */ +enum { + OPC_MXU_Q8MAC = 0x00, + OPC_MXU_Q8MACSU = 0x01, +}; + +#if !defined(TARGET_MIPS64) + +/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */ +#define MXU_APTN1_A 0 +#define MXU_APTN1_S 1 + +/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */ +#define MXU_APTN2_AA 0 +#define MXU_APTN2_AS 1 +#define MXU_APTN2_SA 2 +#define MXU_APTN2_SS 3 + +/* MXU execute add/subtract 2-bit pattern 'eptn2' */ +#define MXU_EPTN2_AA 0 +#define MXU_EPTN2_AS 1 +#define MXU_EPTN2_SA 2 +#define MXU_EPTN2_SS 3 + +/* MXU operand getting pattern 'optn2' */ +#define MXU_OPTN2_PTN0 0 +#define MXU_OPTN2_PTN1 1 +#define MXU_OPTN2_PTN2 2 +#define MXU_OPTN2_PTN3 3 +/* alternative naming scheme for 'optn2' */ +#define MXU_OPTN2_WW 0 +#define MXU_OPTN2_LW 1 +#define MXU_OPTN2_HW 2 +#define MXU_OPTN2_XW 3 + +/* MXU operand getting pattern 'optn3' */ +#define MXU_OPTN3_PTN0 0 +#define MXU_OPTN3_PTN1 1 +#define MXU_OPTN3_PTN2 2 +#define MXU_OPTN3_PTN3 3 +#define MXU_OPTN3_PTN4 4 +#define MXU_OPTN3_PTN5 5 +#define MXU_OPTN3_PTN6 6 +#define MXU_OPTN3_PTN7 7 + + +static const char * const mxuregnames[] = { + "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8", + "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR", +}; + +static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; +static TCGv mxu_CR; + + +/* MXU General purpose registers moves. */ +static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg) +{ + if (reg == 0) { + tcg_gen_movi_tl(t, 0); + } else if (reg <= 15) { + tcg_gen_mov_tl(t, mxu_gpr[reg - 1]); + } +} + +static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg) +{ + if (reg > 0 && reg <= 15) { + tcg_gen_mov_tl(mxu_gpr[reg - 1], t); + } +} + +/* MXU control register moves. */ +static inline void gen_load_mxu_cr(TCGv t) +{ + tcg_gen_mov_tl(t, mxu_CR); +} + +static inline void gen_store_mxu_cr(TCGv t) +{ + /* TODO: Add handling of RW rules for MXU_CR. */ + tcg_gen_mov_tl(mxu_CR, t); +} + + +/* + * S32I2M XRa, rb - Register move from GRF to XRF + */ +static void gen_mxu_s32i2m(DisasContext *ctx) +{ + TCGv t0; + uint32_t XRa, Rb; + + t0 = tcg_temp_new(); + + XRa = extract32(ctx->opcode, 6, 5); + Rb = extract32(ctx->opcode, 16, 5); + + gen_load_gpr(t0, Rb); + if (XRa <= 15) { + gen_store_mxu_gpr(t0, XRa); + } else if (XRa == 16) { + gen_store_mxu_cr(t0); + } + + tcg_temp_free(t0); +} + +/* + * S32M2I XRa, rb - Register move from XRF to GRF + */ +static void gen_mxu_s32m2i(DisasContext *ctx) +{ + TCGv t0; + uint32_t XRa, Rb; + + t0 = tcg_temp_new(); + + XRa = extract32(ctx->opcode, 6, 5); + Rb = extract32(ctx->opcode, 16, 5); + + if (XRa <= 15) { + gen_load_mxu_gpr(t0, XRa); + } else if (XRa == 16) { + gen_load_mxu_cr(t0); + } + + gen_store_gpr(t0, Rb); + + tcg_temp_free(t0); +} + +/* + * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF + */ +static void gen_mxu_s8ldd(DisasContext *ctx) +{ + TCGv t0, t1; + uint32_t XRa, Rb, s8, optn3; + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + XRa = extract32(ctx->opcode, 6, 4); + s8 = extract32(ctx->opcode, 10, 8); + optn3 = extract32(ctx->opcode, 18, 3); + Rb = extract32(ctx->opcode, 21, 5); + + gen_load_gpr(t0, Rb); + tcg_gen_addi_tl(t0, t0, (int8_t)s8); + + switch (optn3) { + /* XRa[7:0] = tmp8 */ + case MXU_OPTN3_PTN0: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + gen_load_mxu_gpr(t0, XRa); + tcg_gen_deposit_tl(t0, t0, t1, 0, 8); + break; + /* XRa[15:8] = tmp8 */ + case MXU_OPTN3_PTN1: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + gen_load_mxu_gpr(t0, XRa); + tcg_gen_deposit_tl(t0, t0, t1, 8, 8); + break; + /* XRa[23:16] = tmp8 */ + case MXU_OPTN3_PTN2: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + gen_load_mxu_gpr(t0, XRa); + tcg_gen_deposit_tl(t0, t0, t1, 16, 8); + break; + /* XRa[31:24] = tmp8 */ + case MXU_OPTN3_PTN3: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + gen_load_mxu_gpr(t0, XRa); + tcg_gen_deposit_tl(t0, t0, t1, 24, 8); + break; + /* XRa = {8'b0, tmp8, 8'b0, tmp8} */ + case MXU_OPTN3_PTN4: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_deposit_tl(t0, t1, t1, 16, 16); + break; + /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */ + case MXU_OPTN3_PTN5: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_shli_tl(t1, t1, 8); + tcg_gen_deposit_tl(t0, t1, t1, 16, 16); + break; + /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */ + case MXU_OPTN3_PTN6: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB); + tcg_gen_mov_tl(t0, t1); + tcg_gen_andi_tl(t0, t0, 0xFF00FFFF); + tcg_gen_shli_tl(t1, t1, 16); + tcg_gen_or_tl(t0, t0, t1); + break; + /* XRa = {tmp8, tmp8, tmp8, tmp8} */ + case MXU_OPTN3_PTN7: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_deposit_tl(t1, t1, t1, 8, 8); + tcg_gen_deposit_tl(t0, t1, t1, 16, 16); + break; + } + + gen_store_mxu_gpr(t0, XRa); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* + * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication + */ +static void gen_mxu_d16mul(DisasContext *ctx) +{ + TCGv t0, t1, t2, t3; + uint32_t XRa, XRb, XRc, XRd, optn2; + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + t2 = tcg_temp_new(); + t3 = tcg_temp_new(); + + XRa = extract32(ctx->opcode, 6, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRc = extract32(ctx->opcode, 14, 4); + XRd = extract32(ctx->opcode, 18, 4); + optn2 = extract32(ctx->opcode, 22, 2); + + gen_load_mxu_gpr(t1, XRb); + tcg_gen_sextract_tl(t0, t1, 0, 16); + tcg_gen_sextract_tl(t1, t1, 16, 16); + gen_load_mxu_gpr(t3, XRc); + tcg_gen_sextract_tl(t2, t3, 0, 16); + tcg_gen_sextract_tl(t3, t3, 16, 16); + + switch (optn2) { + case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */ + tcg_gen_mul_tl(t3, t1, t3); + tcg_gen_mul_tl(t2, t0, t2); + break; + case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */ + tcg_gen_mul_tl(t3, t0, t3); + tcg_gen_mul_tl(t2, t0, t2); + break; + case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */ + tcg_gen_mul_tl(t3, t1, t3); + tcg_gen_mul_tl(t2, t1, t2); + break; + case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */ + tcg_gen_mul_tl(t3, t0, t3); + tcg_gen_mul_tl(t2, t1, t2); + break; + } + gen_store_mxu_gpr(t3, XRa); + gen_store_mxu_gpr(t2, XRd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_temp_free(t3); +} + +/* + * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply + * and accumulate + */ +static void gen_mxu_d16mac(DisasContext *ctx) +{ + TCGv t0, t1, t2, t3; + uint32_t XRa, XRb, XRc, XRd, optn2, aptn2; + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + t2 = tcg_temp_new(); + t3 = tcg_temp_new(); + + XRa = extract32(ctx->opcode, 6, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRc = extract32(ctx->opcode, 14, 4); + XRd = extract32(ctx->opcode, 18, 4); + optn2 = extract32(ctx->opcode, 22, 2); + aptn2 = extract32(ctx->opcode, 24, 2); + + gen_load_mxu_gpr(t1, XRb); + tcg_gen_sextract_tl(t0, t1, 0, 16); + tcg_gen_sextract_tl(t1, t1, 16, 16); + + gen_load_mxu_gpr(t3, XRc); + tcg_gen_sextract_tl(t2, t3, 0, 16); + tcg_gen_sextract_tl(t3, t3, 16, 16); + + switch (optn2) { + case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */ + tcg_gen_mul_tl(t3, t1, t3); + tcg_gen_mul_tl(t2, t0, t2); + break; + case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */ + tcg_gen_mul_tl(t3, t0, t3); + tcg_gen_mul_tl(t2, t0, t2); + break; + case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */ + tcg_gen_mul_tl(t3, t1, t3); + tcg_gen_mul_tl(t2, t1, t2); + break; + case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */ + tcg_gen_mul_tl(t3, t0, t3); + tcg_gen_mul_tl(t2, t1, t2); + break; + } + gen_load_mxu_gpr(t0, XRa); + gen_load_mxu_gpr(t1, XRd); + + switch (aptn2) { + case MXU_APTN2_AA: + tcg_gen_add_tl(t3, t0, t3); + tcg_gen_add_tl(t2, t1, t2); + break; + case MXU_APTN2_AS: + tcg_gen_add_tl(t3, t0, t3); + tcg_gen_sub_tl(t2, t1, t2); + break; + case MXU_APTN2_SA: + tcg_gen_sub_tl(t3, t0, t3); + tcg_gen_add_tl(t2, t1, t2); + break; + case MXU_APTN2_SS: + tcg_gen_sub_tl(t3, t0, t3); + tcg_gen_sub_tl(t2, t1, t2); + break; + } + gen_store_mxu_gpr(t3, XRa); + gen_store_mxu_gpr(t2, XRd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_temp_free(t3); +} + +/* + * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply + * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply + */ +static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx) +{ + TCGv t0, t1, t2, t3, t4, t5, t6, t7; + uint32_t XRa, XRb, XRc, XRd, sel; + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + t2 = tcg_temp_new(); + t3 = tcg_temp_new(); + t4 = tcg_temp_new(); + t5 = tcg_temp_new(); + t6 = tcg_temp_new(); + t7 = tcg_temp_new(); + + XRa = extract32(ctx->opcode, 6, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRc = extract32(ctx->opcode, 14, 4); + XRd = extract32(ctx->opcode, 18, 4); + sel = extract32(ctx->opcode, 22, 2); + + gen_load_mxu_gpr(t3, XRb); + gen_load_mxu_gpr(t7, XRc); + + if (sel == 0x2) { + /* Q8MULSU */ + tcg_gen_ext8s_tl(t0, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8s_tl(t1, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8s_tl(t2, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8s_tl(t3, t3); + } else { + /* Q8MUL */ + tcg_gen_ext8u_tl(t0, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8u_tl(t1, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8u_tl(t2, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8u_tl(t3, t3); + } + + tcg_gen_ext8u_tl(t4, t7); + tcg_gen_shri_tl(t7, t7, 8); + tcg_gen_ext8u_tl(t5, t7); + tcg_gen_shri_tl(t7, t7, 8); + tcg_gen_ext8u_tl(t6, t7); + tcg_gen_shri_tl(t7, t7, 8); + tcg_gen_ext8u_tl(t7, t7); + + tcg_gen_mul_tl(t0, t0, t4); + tcg_gen_mul_tl(t1, t1, t5); + tcg_gen_mul_tl(t2, t2, t6); + tcg_gen_mul_tl(t3, t3, t7); + + tcg_gen_andi_tl(t0, t0, 0xFFFF); + tcg_gen_andi_tl(t1, t1, 0xFFFF); + tcg_gen_andi_tl(t2, t2, 0xFFFF); + tcg_gen_andi_tl(t3, t3, 0xFFFF); + + tcg_gen_shli_tl(t1, t1, 16); + tcg_gen_shli_tl(t3, t3, 16); + + tcg_gen_or_tl(t0, t0, t1); + tcg_gen_or_tl(t1, t2, t3); + + gen_store_mxu_gpr(t0, XRd); + gen_store_mxu_gpr(t1, XRa); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_temp_free(t3); + tcg_temp_free(t4); + tcg_temp_free(t5); + tcg_temp_free(t6); + tcg_temp_free(t7); +} + +/* + * S32LDD XRa, Rb, S12 - Load a word from memory to XRF + * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq. + */ +static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx) +{ + TCGv t0, t1; + uint32_t XRa, Rb, s12, sel; + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + XRa = extract32(ctx->opcode, 6, 4); + s12 = extract32(ctx->opcode, 10, 10); + sel = extract32(ctx->opcode, 20, 1); + Rb = extract32(ctx->opcode, 21, 5); + + gen_load_gpr(t0, Rb); + + tcg_gen_movi_tl(t1, s12); + tcg_gen_shli_tl(t1, t1, 2); + if (s12 & 0x200) { + tcg_gen_ori_tl(t1, t1, 0xFFFFF000); + } + tcg_gen_add_tl(t1, t0, t1); + tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL); + + if (sel == 1) { + /* S32LDDR */ + tcg_gen_bswap32_tl(t1, t1); + } + gen_store_mxu_gpr(t1, XRa); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + + +/* + * MXU instruction category: logic + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * S32NOR S32AND S32OR S32XOR + */ + +/* + * S32NOR XRa, XRb, XRc + * Update XRa with the result of logical bitwise 'nor' operation + * applied to the content of XRb and XRc. + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16| + * +-----------+---------+-----+-------+-------+-------+-----------+ + */ +static void gen_mxu_S32NOR(DisasContext *ctx) +{ + uint32_t pad, XRc, XRb, XRa; + + pad = extract32(ctx->opcode, 21, 5); + XRc = extract32(ctx->opcode, 14, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRa = extract32(ctx->opcode, 6, 4); + + if (unlikely(pad != 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa == 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb == 0) && (XRc == 0))) { + /* both operands zero registers -> just set destination to all 1s */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF); + } else if (unlikely(XRb == 0)) { + /* XRb zero register -> just set destination to the negation of XRc */ + tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + } else if (unlikely(XRc == 0)) { + /* XRa zero register -> just set destination to the negation of XRb */ + tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else if (unlikely(XRb == XRc)) { + /* both operands same -> just set destination to the negation of XRb */ + tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); + } +} + +/* + * S32AND XRa, XRb, XRc + * Update XRa with the result of logical bitwise 'and' operation + * applied to the content of XRb and XRc. + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16| + * +-----------+---------+-----+-------+-------+-------+-----------+ + */ +static void gen_mxu_S32AND(DisasContext *ctx) +{ + uint32_t pad, XRc, XRb, XRa; + + pad = extract32(ctx->opcode, 21, 5); + XRc = extract32(ctx->opcode, 14, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRa = extract32(ctx->opcode, 6, 4); + + if (unlikely(pad != 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa == 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb == 0) || (XRc == 0))) { + /* one of operands zero register -> just set destination to all 0s */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely(XRb == XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); + } +} + +/* + * S32OR XRa, XRb, XRc + * Update XRa with the result of logical bitwise 'or' operation + * applied to the content of XRb and XRc. + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16| + * +-----------+---------+-----+-------+-------+-------+-----------+ + */ +static void gen_mxu_S32OR(DisasContext *ctx) +{ + uint32_t pad, XRc, XRb, XRa; + + pad = extract32(ctx->opcode, 21, 5); + XRc = extract32(ctx->opcode, 14, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRa = extract32(ctx->opcode, 6, 4); + + if (unlikely(pad != 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa == 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb == 0) && (XRc == 0))) { + /* both operands zero registers -> just set destination to all 0s */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely(XRb == 0)) { + /* XRb zero register -> just set destination to the content of XRc */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + } else if (unlikely(XRc == 0)) { + /* XRc zero register -> just set destination to the content of XRb */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else if (unlikely(XRb == XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); + } +} + +/* + * S32XOR XRa, XRb, XRc + * Update XRa with the result of logical bitwise 'xor' operation + * applied to the content of XRb and XRc. + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16| + * +-----------+---------+-----+-------+-------+-------+-----------+ + */ +static void gen_mxu_S32XOR(DisasContext *ctx) +{ + uint32_t pad, XRc, XRb, XRa; + + pad = extract32(ctx->opcode, 21, 5); + XRc = extract32(ctx->opcode, 14, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRa = extract32(ctx->opcode, 6, 4); + + if (unlikely(pad != 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa == 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb == 0) && (XRc == 0))) { + /* both operands zero registers -> just set destination to all 0s */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely(XRb == 0)) { + /* XRb zero register -> just set destination to the content of XRc */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + } else if (unlikely(XRc == 0)) { + /* XRc zero register -> just set destination to the content of XRb */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else if (unlikely(XRb == XRc)) { + /* both operands same -> just set destination to all 0s */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else { + /* the most general case */ + tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); + } +} + + +/* + * MXU instruction category max/min + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * S32MAX D16MAX Q8MAX + * S32MIN D16MIN Q8MIN + */ + +/* + * S32MAX XRa, XRb, XRc + * Update XRa with the maximum of signed 32-bit integers contained + * in XRb and XRc. + * + * S32MIN XRa, XRb, XRc + * Update XRa with the minimum of signed 32-bit integers contained + * in XRb and XRc. + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00| + * +-----------+---------+-----+-------+-------+-------+-----------+ + */ +static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx) +{ + uint32_t pad, opc, XRc, XRb, XRa; + + pad = extract32(ctx->opcode, 21, 5); + opc = extract32(ctx->opcode, 18, 3); + XRc = extract32(ctx->opcode, 14, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRa = extract32(ctx->opcode, 6, 4); + + if (unlikely(pad != 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa == 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb == 0) && (XRc == 0))) { + /* both operands zero registers -> just set destination to zero */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely((XRb == 0) || (XRc == 0))) { + /* exactly one operand is zero register - find which one is not...*/ + uint32_t XRx = XRb ? XRb : XRc; + /* ...and do max/min operation with one operand 0 */ + if (opc == OPC_MXU_S32MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); + } + } else if (unlikely(XRb == XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + if (opc == OPC_MXU_S32MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], + mxu_gpr[XRc - 1]); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], + mxu_gpr[XRc - 1]); + } + } +} + +/* + * D16MAX + * Update XRa with the 16-bit-wise maximums of signed integers + * contained in XRb and XRc. + * + * D16MIN + * Update XRa with the 16-bit-wise minimums of signed integers + * contained in XRb and XRc. + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00| + * +-----------+---------+-----+-------+-------+-------+-----------+ + */ +static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) +{ + uint32_t pad, opc, XRc, XRb, XRa; + + pad = extract32(ctx->opcode, 21, 5); + opc = extract32(ctx->opcode, 18, 3); + XRc = extract32(ctx->opcode, 14, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRa = extract32(ctx->opcode, 6, 4); + + if (unlikely(pad != 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRc == 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb == 0) && (XRa == 0))) { + /* both operands zero registers -> just set destination to zero */ + tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0); + } else if (unlikely((XRb == 0) || (XRa == 0))) { + /* exactly one operand is zero register - find which one is not...*/ + uint32_t XRx = XRb ? XRb : XRc; + /* ...and do half-word-wise max/min with one operand 0 */ + TCGv_i32 t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_const_i32(0); + + /* the left half-word first */ + tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000); + if (opc == OPC_MXU_D16MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); + } + + /* the right half-word */ + tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF); + /* move half-words to the leftmost position */ + tcg_gen_shli_i32(t0, t0, 16); + /* t0 will be max/min of t0 and t1 */ + if (opc == OPC_MXU_D16MAX) { + tcg_gen_smax_i32(t0, t0, t1); + } else { + tcg_gen_smin_i32(t0, t0, t1); + } + /* return resulting half-words to its original position */ + tcg_gen_shri_i32(t0, t0, 16); + /* finally update the destination */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } else if (unlikely(XRb == XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + TCGv_i32 t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_temp_new(); + + /* the left half-word first */ + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000); + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000); + if (opc == OPC_MXU_D16MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); + } + + /* the right half-word */ + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF); + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF); + /* move half-words to the leftmost position */ + tcg_gen_shli_i32(t0, t0, 16); + tcg_gen_shli_i32(t1, t1, 16); + /* t0 will be max/min of t0 and t1 */ + if (opc == OPC_MXU_D16MAX) { + tcg_gen_smax_i32(t0, t0, t1); + } else { + tcg_gen_smin_i32(t0, t0, t1); + } + /* return resulting half-words to its original position */ + tcg_gen_shri_i32(t0, t0, 16); + /* finally update the destination */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } +} + +/* + * Q8MAX + * Update XRa with the 8-bit-wise maximums of signed integers + * contained in XRb and XRc. + * + * Q8MIN + * Update XRa with the 8-bit-wise minimums of signed integers + * contained in XRb and XRc. + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00| + * +-----------+---------+-----+-------+-------+-------+-----------+ + */ +static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx) +{ + uint32_t pad, opc, XRc, XRb, XRa; + + pad = extract32(ctx->opcode, 21, 5); + opc = extract32(ctx->opcode, 18, 3); + XRc = extract32(ctx->opcode, 14, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRa = extract32(ctx->opcode, 6, 4); + + if (unlikely(pad != 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa == 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb == 0) && (XRc == 0))) { + /* both operands zero registers -> just set destination to zero */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely((XRb == 0) || (XRc == 0))) { + /* exactly one operand is zero register - make it be the first...*/ + uint32_t XRx = XRb ? XRb : XRc; + /* ...and do byte-wise max/min with one operand 0 */ + TCGv_i32 t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_const_i32(0); + int32_t i; + + /* the leftmost byte (byte 3) first */ + tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000); + if (opc == OPC_MXU_Q8MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); + } + + /* bytes 2, 1, 0 */ + for (i = 2; i >= 0; i--) { + /* extract the byte */ + tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i)); + /* move the byte to the leftmost position */ + tcg_gen_shli_i32(t0, t0, 8 * (3 - i)); + /* t0 will be max/min of t0 and t1 */ + if (opc == OPC_MXU_Q8MAX) { + tcg_gen_smax_i32(t0, t0, t1); + } else { + tcg_gen_smin_i32(t0, t0, t1); + } + /* return resulting byte to its original position */ + tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); + /* finally update the destination */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); + } + + tcg_temp_free(t1); + tcg_temp_free(t0); + } else if (unlikely(XRb == XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + TCGv_i32 t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_temp_new(); + int32_t i; + + /* the leftmost bytes (bytes 3) first */ + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000); + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000); + if (opc == OPC_MXU_Q8MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); + } + + /* bytes 2, 1, 0 */ + for (i = 2; i >= 0; i--) { + /* extract corresponding bytes */ + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i)); + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i)); + /* move the bytes to the leftmost position */ + tcg_gen_shli_i32(t0, t0, 8 * (3 - i)); + tcg_gen_shli_i32(t1, t1, 8 * (3 - i)); + /* t0 will be max/min of t0 and t1 */ + if (opc == OPC_MXU_Q8MAX) { + tcg_gen_smax_i32(t0, t0, t1); + } else { + tcg_gen_smin_i32(t0, t0, t1); + } + /* return resulting byte to its original position */ + tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); + /* finally update the destination */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); + } + + tcg_temp_free(t1); + tcg_temp_free(t0); + } +} + + +/* + * MXU instruction category: align + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * S32ALN S32ALNI + */ + +/* + * S32ALNI XRc, XRb, XRa, optn3 + * Arrange bytes from XRb and XRc according to one of five sets of + * rules determined by optn3, and place the result in XRa. + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+-----+---+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16| + * +-----------+-----+---+-----+-------+-------+-------+-----------+ + * + */ +static void gen_mxu_S32ALNI(DisasContext *ctx) +{ + uint32_t optn3, pad, XRc, XRb, XRa; + + optn3 = extract32(ctx->opcode, 23, 3); + pad = extract32(ctx->opcode, 21, 2); + XRc = extract32(ctx->opcode, 14, 4); + XRb = extract32(ctx->opcode, 10, 4); + XRa = extract32(ctx->opcode, 6, 4); + + if (unlikely(pad != 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa == 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb == 0) && (XRc == 0))) { + /* both operands zero registers -> just set destination to all 0s */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely(XRb == 0)) { + /* XRb zero register -> just appropriatelly shift XRc into XRa */ + switch (optn3) { + case MXU_OPTN3_PTN0: + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + break; + case MXU_OPTN3_PTN1: + case MXU_OPTN3_PTN2: + case MXU_OPTN3_PTN3: + tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1], + 8 * (4 - optn3)); + break; + case MXU_OPTN3_PTN4: + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + break; + } + } else if (unlikely(XRc == 0)) { + /* XRc zero register -> just appropriatelly shift XRb into XRa */ + switch (optn3) { + case MXU_OPTN3_PTN0: + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + break; + case MXU_OPTN3_PTN1: + case MXU_OPTN3_PTN2: + case MXU_OPTN3_PTN3: + tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3); + break; + case MXU_OPTN3_PTN4: + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + break; + } + } else if (unlikely(XRb == XRc)) { + /* both operands same -> just rotation or moving from any of them */ + switch (optn3) { + case MXU_OPTN3_PTN0: + case MXU_OPTN3_PTN4: + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + break; + case MXU_OPTN3_PTN1: + case MXU_OPTN3_PTN2: + case MXU_OPTN3_PTN3: + tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3); + break; + } + } else { + /* the most general case */ + switch (optn3) { + case MXU_OPTN3_PTN0: + { + /* */ + /* XRb XRc */ + /* +---------------+ */ + /* | A B C D | E F G H */ + /* +-------+-------+ */ + /* | */ + /* XRa */ + /* */ + + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } + break; + case MXU_OPTN3_PTN1: + { + /* */ + /* XRb XRc */ + /* +-------------------+ */ + /* A | B C D E | F G H */ + /* +---------+---------+ */ + /* | */ + /* XRa */ + /* */ + + TCGv_i32 t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_temp_new(); + + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF); + tcg_gen_shli_i32(t0, t0, 8); + + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000); + tcg_gen_shri_i32(t1, t1, 24); + + tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } + break; + case MXU_OPTN3_PTN2: + { + /* */ + /* XRb XRc */ + /* +-------------------+ */ + /* A B | C D E F | G H */ + /* +---------+---------+ */ + /* | */ + /* XRa */ + /* */ + + TCGv_i32 t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_temp_new(); + + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF); + tcg_gen_shli_i32(t0, t0, 16); + + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000); + tcg_gen_shri_i32(t1, t1, 16); + + tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } + break; + case MXU_OPTN3_PTN3: + { + /* */ + /* XRb XRc */ + /* +-------------------+ */ + /* A B C | D E F G | H */ + /* +---------+---------+ */ + /* | */ + /* XRa */ + /* */ + + TCGv_i32 t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_temp_new(); + + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF); + tcg_gen_shli_i32(t0, t0, 24); + + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00); + tcg_gen_shri_i32(t1, t1, 8); + + tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } + break; + case MXU_OPTN3_PTN4: + { + /* */ + /* XRb XRc */ + /* +---------------+ */ + /* A B C D | E F G H | */ + /* +-------+-------+ */ + /* | */ + /* XRa */ + /* */ + + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + } + break; + } + } +} + + +/* + * Decoding engine for MXU + * ======================= + */ + +/* + * + * Decode MXU pool00 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00| + * +-----------+---------+-----+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 18, 3); + + switch (opcode) { + case OPC_MXU_S32MAX: + case OPC_MXU_S32MIN: + gen_mxu_S32MAX_S32MIN(ctx); + break; + case OPC_MXU_D16MAX: + case OPC_MXU_D16MIN: + gen_mxu_D16MAX_D16MIN(ctx); + break; + case OPC_MXU_Q8MAX: + case OPC_MXU_Q8MIN: + gen_mxu_Q8MAX_Q8MIN(ctx); + break; + case OPC_MXU_Q8SLT: + /* TODO: Implement emulation of Q8SLT instruction. */ + MIPS_INVAL("OPC_MXU_Q8SLT"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8SLTU: + /* TODO: Implement emulation of Q8SLTU instruction. */ + MIPS_INVAL("OPC_MXU_Q8SLTU"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool01 + * + * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01| + * +-----------+---------+-----+-------+-------+-------+-----------+ + * + * Q8ADD: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+-----+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01| + * +-----------+---+-----+-----+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 18, 3); + + switch (opcode) { + case OPC_MXU_S32SLT: + /* TODO: Implement emulation of S32SLT instruction. */ + MIPS_INVAL("OPC_MXU_S32SLT"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16SLT: + /* TODO: Implement emulation of D16SLT instruction. */ + MIPS_INVAL("OPC_MXU_D16SLT"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16AVG: + /* TODO: Implement emulation of D16AVG instruction. */ + MIPS_INVAL("OPC_MXU_D16AVG"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16AVGR: + /* TODO: Implement emulation of D16AVGR instruction. */ + MIPS_INVAL("OPC_MXU_D16AVGR"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8AVG: + /* TODO: Implement emulation of Q8AVG instruction. */ + MIPS_INVAL("OPC_MXU_Q8AVG"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8AVGR: + /* TODO: Implement emulation of Q8AVGR instruction. */ + MIPS_INVAL("OPC_MXU_Q8AVGR"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8ADD: + /* TODO: Implement emulation of Q8ADD instruction. */ + MIPS_INVAL("OPC_MXU_Q8ADD"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool02 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02| + * +-----------+---------+-----+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 18, 3); + + switch (opcode) { + case OPC_MXU_S32CPS: + /* TODO: Implement emulation of S32CPS instruction. */ + MIPS_INVAL("OPC_MXU_S32CPS"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16CPS: + /* TODO: Implement emulation of D16CPS instruction. */ + MIPS_INVAL("OPC_MXU_D16CPS"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8ABD: + /* TODO: Implement emulation of Q8ABD instruction. */ + MIPS_INVAL("OPC_MXU_Q8ABD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16SAT: + /* TODO: Implement emulation of Q16SAT instruction. */ + MIPS_INVAL("OPC_MXU_Q16SAT"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool03 + * + * D16MULF: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03| + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * + * D16MULE: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03| + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 24, 2); + + switch (opcode) { + case OPC_MXU_D16MULF: + /* TODO: Implement emulation of D16MULF instruction. */ + MIPS_INVAL("OPC_MXU_D16MULF"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16MULE: + /* TODO: Implement emulation of D16MULE instruction. */ + MIPS_INVAL("OPC_MXU_D16MULE"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool04 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-+-------------------+-------+-----------+ + * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04| + * +-----------+---------+-+-------------------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 20, 1); + + switch (opcode) { + case OPC_MXU_S32LDD: + case OPC_MXU_S32LDDR: + gen_mxu_s32ldd_s32lddr(ctx); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool05 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-+-------------------+-------+-----------+ + * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05| + * +-----------+---------+-+-------------------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 20, 1); + + switch (opcode) { + case OPC_MXU_S32STD: + /* TODO: Implement emulation of S32STD instruction. */ + MIPS_INVAL("OPC_MXU_S32STD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32STDR: + /* TODO: Implement emulation of S32STDR instruction. */ + MIPS_INVAL("OPC_MXU_S32STDR"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool06 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---+-------+-------+-----------+ + * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06| + * +-----------+---------+---------+---+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 10, 4); + + switch (opcode) { + case OPC_MXU_S32LDDV: + /* TODO: Implement emulation of S32LDDV instruction. */ + MIPS_INVAL("OPC_MXU_S32LDDV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32LDDVR: + /* TODO: Implement emulation of S32LDDVR instruction. */ + MIPS_INVAL("OPC_MXU_S32LDDVR"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool07 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---+-------+-------+-----------+ + * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07| + * +-----------+---------+---------+---+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 10, 4); + + switch (opcode) { + case OPC_MXU_S32STDV: + /* TODO: Implement emulation of S32TDV instruction. */ + MIPS_INVAL("OPC_MXU_S32TDV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32STDVR: + /* TODO: Implement emulation of S32TDVR instruction. */ + MIPS_INVAL("OPC_MXU_S32TDVR"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool08 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-+-------------------+-------+-----------+ + * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08| + * +-----------+---------+-+-------------------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 20, 1); + + switch (opcode) { + case OPC_MXU_S32LDI: + /* TODO: Implement emulation of S32LDI instruction. */ + MIPS_INVAL("OPC_MXU_S32LDI"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32LDIR: + /* TODO: Implement emulation of S32LDIR instruction. */ + MIPS_INVAL("OPC_MXU_S32LDIR"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool09 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-+-------------------+-------+-----------+ + * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09| + * +-----------+---------+-+-------------------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 5, 0); + + switch (opcode) { + case OPC_MXU_S32SDI: + /* TODO: Implement emulation of S32SDI instruction. */ + MIPS_INVAL("OPC_MXU_S32SDI"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32SDIR: + /* TODO: Implement emulation of S32SDIR instruction. */ + MIPS_INVAL("OPC_MXU_S32SDIR"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool10 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---+-------+-------+-----------+ + * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10| + * +-----------+---------+---------+---+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 5, 0); + + switch (opcode) { + case OPC_MXU_S32LDIV: + /* TODO: Implement emulation of S32LDIV instruction. */ + MIPS_INVAL("OPC_MXU_S32LDIV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32LDIVR: + /* TODO: Implement emulation of S32LDIVR instruction. */ + MIPS_INVAL("OPC_MXU_S32LDIVR"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool11 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---+-------+-------+-----------+ + * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11| + * +-----------+---------+---------+---+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 10, 4); + + switch (opcode) { + case OPC_MXU_S32SDIV: + /* TODO: Implement emulation of S32SDIV instruction. */ + MIPS_INVAL("OPC_MXU_S32SDIV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32SDIVR: + /* TODO: Implement emulation of S32SDIVR instruction. */ + MIPS_INVAL("OPC_MXU_S32SDIVR"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool12 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12| + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 22, 2); + + switch (opcode) { + case OPC_MXU_D32ACC: + /* TODO: Implement emulation of D32ACC instruction. */ + MIPS_INVAL("OPC_MXU_D32ACC"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D32ACCM: + /* TODO: Implement emulation of D32ACCM instruction. */ + MIPS_INVAL("OPC_MXU_D32ACCM"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D32ASUM: + /* TODO: Implement emulation of D32ASUM instruction. */ + MIPS_INVAL("OPC_MXU_D32ASUM"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool13 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13| + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 22, 2); + + switch (opcode) { + case OPC_MXU_Q16ACC: + /* TODO: Implement emulation of Q16ACC instruction. */ + MIPS_INVAL("OPC_MXU_Q16ACC"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16ACCM: + /* TODO: Implement emulation of Q16ACCM instruction. */ + MIPS_INVAL("OPC_MXU_Q16ACCM"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16ASUM: + /* TODO: Implement emulation of Q16ASUM instruction. */ + MIPS_INVAL("OPC_MXU_Q16ASUM"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool14 + * + * Q8ADDE, Q8ACCE: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14| + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * + * D8SUM, D8SUMC: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14| + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 22, 2); + + switch (opcode) { + case OPC_MXU_Q8ADDE: + /* TODO: Implement emulation of Q8ADDE instruction. */ + MIPS_INVAL("OPC_MXU_Q8ADDE"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D8SUM: + /* TODO: Implement emulation of D8SUM instruction. */ + MIPS_INVAL("OPC_MXU_D8SUM"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D8SUMC: + /* TODO: Implement emulation of D8SUMC instruction. */ + MIPS_INVAL("OPC_MXU_D8SUMC"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool15 + * + * S32MUL, S32MULU, S32EXTRV: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---+-------+-------+-----------+ + * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15| + * +-----------+---------+---------+---+-------+-------+-----------+ + * + * S32EXTR: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---+-------+-------+-----------+ + * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15| + * +-----------+---------+---------+---+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 14, 2); + + switch (opcode) { + case OPC_MXU_S32MUL: + /* TODO: Implement emulation of S32MUL instruction. */ + MIPS_INVAL("OPC_MXU_S32MUL"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32MULU: + /* TODO: Implement emulation of S32MULU instruction. */ + MIPS_INVAL("OPC_MXU_S32MULU"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32EXTR: + /* TODO: Implement emulation of S32EXTR instruction. */ + MIPS_INVAL("OPC_MXU_S32EXTR"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32EXTRV: + /* TODO: Implement emulation of S32EXTRV instruction. */ + MIPS_INVAL("OPC_MXU_S32EXTRV"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool16 + * + * D32SARW: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16| + * +-----------+---------+-----+-------+-------+-------+-----------+ + * + * S32ALN: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16| + * +-----------+---------+-----+-------+-------+-------+-----------+ + * + * S32ALNI: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+-----+---+-----+-------+-------+-------+-----------+ + * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16| + * +-----------+-----+---+-----+-------+-------+-------+-----------+ + * + * S32LUI: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+-----+---+-----+-------+---------------+-----------+ + * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16| + * +-----------+-----+---+-----+-------+---------------+-----------+ + * + * S32NOR, S32AND, S32OR, S32XOR: + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16| + * +-----------+---------+-----+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 18, 3); + + switch (opcode) { + case OPC_MXU_D32SARW: + /* TODO: Implement emulation of D32SARW instruction. */ + MIPS_INVAL("OPC_MXU_D32SARW"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32ALN: + /* TODO: Implement emulation of S32ALN instruction. */ + MIPS_INVAL("OPC_MXU_S32ALN"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32ALNI: + gen_mxu_S32ALNI(ctx); + break; + case OPC_MXU_S32LUI: + /* TODO: Implement emulation of S32LUI instruction. */ + MIPS_INVAL("OPC_MXU_S32LUI"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32NOR: + gen_mxu_S32NOR(ctx); + break; + case OPC_MXU_S32AND: + gen_mxu_S32AND(ctx); + break; + case OPC_MXU_S32OR: + gen_mxu_S32OR(ctx); + break; + case OPC_MXU_S32XOR: + gen_mxu_S32XOR(ctx); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool17 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---+---------+-----+-----------+ + * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15| + * +-----------+---------+---------+---+---------+-----+-----------+ + * + */ +static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 6, 2); + + switch (opcode) { + case OPC_MXU_LXW: + /* TODO: Implement emulation of LXW instruction. */ + MIPS_INVAL("OPC_MXU_LXW"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_LXH: + /* TODO: Implement emulation of LXH instruction. */ + MIPS_INVAL("OPC_MXU_LXH"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_LXHU: + /* TODO: Implement emulation of LXHU instruction. */ + MIPS_INVAL("OPC_MXU_LXHU"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_LXB: + /* TODO: Implement emulation of LXB instruction. */ + MIPS_INVAL("OPC_MXU_LXB"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_LXBU: + /* TODO: Implement emulation of LXBU instruction. */ + MIPS_INVAL("OPC_MXU_LXBU"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} +/* + * + * Decode MXU pool18 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18| + * +-----------+---------+-----+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 18, 3); + + switch (opcode) { + case OPC_MXU_D32SLLV: + /* TODO: Implement emulation of D32SLLV instruction. */ + MIPS_INVAL("OPC_MXU_D32SLLV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D32SLRV: + /* TODO: Implement emulation of D32SLRV instruction. */ + MIPS_INVAL("OPC_MXU_D32SLRV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D32SARV: + /* TODO: Implement emulation of D32SARV instruction. */ + MIPS_INVAL("OPC_MXU_D32SARV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16SLLV: + /* TODO: Implement emulation of Q16SLLV instruction. */ + MIPS_INVAL("OPC_MXU_Q16SLLV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16SLRV: + /* TODO: Implement emulation of Q16SLRV instruction. */ + MIPS_INVAL("OPC_MXU_Q16SLRV"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16SARV: + /* TODO: Implement emulation of Q16SARV instruction. */ + MIPS_INVAL("OPC_MXU_Q16SARV"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool19 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19| + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 22, 2); + + switch (opcode) { + case OPC_MXU_Q8MUL: + case OPC_MXU_Q8MULSU: + gen_mxu_q8mul_q8mulsu(ctx); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool20 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+-----+-------+-------+-------+-----------+ + * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20| + * +-----------+---------+-----+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 18, 3); + + switch (opcode) { + case OPC_MXU_Q8MOVZ: + /* TODO: Implement emulation of Q8MOVZ instruction. */ + MIPS_INVAL("OPC_MXU_Q8MOVZ"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8MOVN: + /* TODO: Implement emulation of Q8MOVN instruction. */ + MIPS_INVAL("OPC_MXU_Q8MOVN"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16MOVZ: + /* TODO: Implement emulation of D16MOVZ instruction. */ + MIPS_INVAL("OPC_MXU_D16MOVZ"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16MOVN: + /* TODO: Implement emulation of D16MOVN instruction. */ + MIPS_INVAL("OPC_MXU_D16MOVN"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32MOVZ: + /* TODO: Implement emulation of S32MOVZ instruction. */ + MIPS_INVAL("OPC_MXU_S32MOVZ"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32MOVN: + /* TODO: Implement emulation of S32MOVN instruction. */ + MIPS_INVAL("OPC_MXU_S32MOVN"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +/* + * + * Decode MXU pool21 + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21| + * +-----------+---+---+-------+-------+-------+-------+-----------+ + * + */ +static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t opcode = extract32(ctx->opcode, 22, 2); + + switch (opcode) { + case OPC_MXU_Q8MAC: + /* TODO: Implement emulation of Q8MAC instruction. */ + MIPS_INVAL("OPC_MXU_Q8MAC"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8MACSU: + /* TODO: Implement emulation of Q8MACSU instruction. */ + MIPS_INVAL("OPC_MXU_Q8MACSU"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + + +/* + * Main MXU decoding function + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------------------------------------+-----------+ + * | SPECIAL2 | |x x x x x x| + * +-----------+---------------------------------------+-----------+ + * + */ +static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx) +{ + /* + * TODO: Investigate necessity of including handling of + * CLZ, CLO, SDBB in this function, as they belong to + * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs. + */ + uint32_t opcode = extract32(ctx->opcode, 0, 6); + + if (opcode == OPC__MXU_MUL) { + uint32_t rs, rt, rd, op1; + + rs = extract32(ctx->opcode, 21, 5); + rt = extract32(ctx->opcode, 16, 5); + rd = extract32(ctx->opcode, 11, 5); + op1 = MASK_SPECIAL2(ctx->opcode); + + gen_arith(ctx, op1, rd, rs, rt); + + return; + } + + if (opcode == OPC_MXU_S32M2I) { + gen_mxu_s32m2i(ctx); + return; + } + + if (opcode == OPC_MXU_S32I2M) { + gen_mxu_s32i2m(ctx); + return; + } + + { + TCGv t_mxu_cr = tcg_temp_new(); + TCGLabel *l_exit = gen_new_label(); + + gen_load_mxu_cr(t_mxu_cr); + tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN); + tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit); + + switch (opcode) { + case OPC_MXU_S32MADD: + /* TODO: Implement emulation of S32MADD instruction. */ + MIPS_INVAL("OPC_MXU_S32MADD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32MADDU: + /* TODO: Implement emulation of S32MADDU instruction. */ + MIPS_INVAL("OPC_MXU_S32MADDU"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU__POOL00: + decode_opc_mxu__pool00(env, ctx); + break; + case OPC_MXU_S32MSUB: + /* TODO: Implement emulation of S32MSUB instruction. */ + MIPS_INVAL("OPC_MXU_S32MSUB"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32MSUBU: + /* TODO: Implement emulation of S32MSUBU instruction. */ + MIPS_INVAL("OPC_MXU_S32MSUBU"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU__POOL01: + decode_opc_mxu__pool01(env, ctx); + break; + case OPC_MXU__POOL02: + decode_opc_mxu__pool02(env, ctx); + break; + case OPC_MXU_D16MUL: + gen_mxu_d16mul(ctx); + break; + case OPC_MXU__POOL03: + decode_opc_mxu__pool03(env, ctx); + break; + case OPC_MXU_D16MAC: + gen_mxu_d16mac(ctx); + break; + case OPC_MXU_D16MACF: + /* TODO: Implement emulation of D16MACF instruction. */ + MIPS_INVAL("OPC_MXU_D16MACF"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16MADL: + /* TODO: Implement emulation of D16MADL instruction. */ + MIPS_INVAL("OPC_MXU_D16MADL"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S16MAD: + /* TODO: Implement emulation of S16MAD instruction. */ + MIPS_INVAL("OPC_MXU_S16MAD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16ADD: + /* TODO: Implement emulation of Q16ADD instruction. */ + MIPS_INVAL("OPC_MXU_Q16ADD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D16MACE: + /* TODO: Implement emulation of D16MACE instruction. */ + MIPS_INVAL("OPC_MXU_D16MACE"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU__POOL04: + decode_opc_mxu__pool04(env, ctx); + break; + case OPC_MXU__POOL05: + decode_opc_mxu__pool05(env, ctx); + break; + case OPC_MXU__POOL06: + decode_opc_mxu__pool06(env, ctx); + break; + case OPC_MXU__POOL07: + decode_opc_mxu__pool07(env, ctx); + break; + case OPC_MXU__POOL08: + decode_opc_mxu__pool08(env, ctx); + break; + case OPC_MXU__POOL09: + decode_opc_mxu__pool09(env, ctx); + break; + case OPC_MXU__POOL10: + decode_opc_mxu__pool10(env, ctx); + break; + case OPC_MXU__POOL11: + decode_opc_mxu__pool11(env, ctx); + break; + case OPC_MXU_D32ADD: + /* TODO: Implement emulation of D32ADD instruction. */ + MIPS_INVAL("OPC_MXU_D32ADD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU__POOL12: + decode_opc_mxu__pool12(env, ctx); + break; + case OPC_MXU__POOL13: + decode_opc_mxu__pool13(env, ctx); + break; + case OPC_MXU__POOL14: + decode_opc_mxu__pool14(env, ctx); + break; + case OPC_MXU_Q8ACCE: + /* TODO: Implement emulation of Q8ACCE instruction. */ + MIPS_INVAL("OPC_MXU_Q8ACCE"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S8LDD: + gen_mxu_s8ldd(ctx); + break; + case OPC_MXU_S8STD: + /* TODO: Implement emulation of S8STD instruction. */ + MIPS_INVAL("OPC_MXU_S8STD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S8LDI: + /* TODO: Implement emulation of S8LDI instruction. */ + MIPS_INVAL("OPC_MXU_S8LDI"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S8SDI: + /* TODO: Implement emulation of S8SDI instruction. */ + MIPS_INVAL("OPC_MXU_S8SDI"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU__POOL15: + decode_opc_mxu__pool15(env, ctx); + break; + case OPC_MXU__POOL16: + decode_opc_mxu__pool16(env, ctx); + break; + case OPC_MXU__POOL17: + decode_opc_mxu__pool17(env, ctx); + break; + case OPC_MXU_S16LDD: + /* TODO: Implement emulation of S16LDD instruction. */ + MIPS_INVAL("OPC_MXU_S16LDD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S16STD: + /* TODO: Implement emulation of S16STD instruction. */ + MIPS_INVAL("OPC_MXU_S16STD"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S16LDI: + /* TODO: Implement emulation of S16LDI instruction. */ + MIPS_INVAL("OPC_MXU_S16LDI"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S16SDI: + /* TODO: Implement emulation of S16SDI instruction. */ + MIPS_INVAL("OPC_MXU_S16SDI"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D32SLL: + /* TODO: Implement emulation of D32SLL instruction. */ + MIPS_INVAL("OPC_MXU_D32SLL"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D32SLR: + /* TODO: Implement emulation of D32SLR instruction. */ + MIPS_INVAL("OPC_MXU_D32SLR"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D32SARL: + /* TODO: Implement emulation of D32SARL instruction. */ + MIPS_INVAL("OPC_MXU_D32SARL"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_D32SAR: + /* TODO: Implement emulation of D32SAR instruction. */ + MIPS_INVAL("OPC_MXU_D32SAR"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16SLL: + /* TODO: Implement emulation of Q16SLL instruction. */ + MIPS_INVAL("OPC_MXU_Q16SLL"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q16SLR: + /* TODO: Implement emulation of Q16SLR instruction. */ + MIPS_INVAL("OPC_MXU_Q16SLR"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU__POOL18: + decode_opc_mxu__pool18(env, ctx); + break; + case OPC_MXU_Q16SAR: + /* TODO: Implement emulation of Q16SAR instruction. */ + MIPS_INVAL("OPC_MXU_Q16SAR"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU__POOL19: + decode_opc_mxu__pool19(env, ctx); + break; + case OPC_MXU__POOL20: + decode_opc_mxu__pool20(env, ctx); + break; + case OPC_MXU__POOL21: + decode_opc_mxu__pool21(env, ctx); + break; + case OPC_MXU_Q16SCOP: + /* TODO: Implement emulation of Q16SCOP instruction. */ + MIPS_INVAL("OPC_MXU_Q16SCOP"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8MADL: + /* TODO: Implement emulation of Q8MADL instruction. */ + MIPS_INVAL("OPC_MXU_Q8MADL"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_S32SFL: + /* TODO: Implement emulation of S32SFL instruction. */ + MIPS_INVAL("OPC_MXU_S32SFL"); + generate_exception_end(ctx, EXCP_RI); + break; + case OPC_MXU_Q8SAD: + /* TODO: Implement emulation of Q8SAD instruction. */ + MIPS_INVAL("OPC_MXU_Q8SAD"); + generate_exception_end(ctx, EXCP_RI); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + generate_exception_end(ctx, EXCP_RI); + } + + gen_set_label(l_exit); + tcg_temp_free(t_mxu_cr); + } +} + +#endif /* !defined(TARGET_MIPS64) */ + + From patchwork Mon Nov 23 20:44:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926785 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,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 35BA6C388F9 for ; Mon, 23 Nov 2020 21:24:45 +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 6BB14206D4 for ; Mon, 23 Nov 2020 21:24:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="o2Sbqkaj" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6BB14206D4 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:34528 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJKF-00055w-0m for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:24:43 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46974) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjY-0002aT-Oy for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:48 -0500 Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]:52763) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjX-0001rj-2b for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:48 -0500 Received: by mail-wm1-x330.google.com with SMTP id 10so616891wml.2 for ; Mon, 23 Nov 2020 12:46:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JBBGafkMt7OMjeY7K8PjAZiYEpVm5oWHr+U5UNLGJTw=; b=o2SbqkajeYgQUNK+AeItP+rjgc/xJuRIKReY//Tk7dLViPGogwuG0eUiwzHHtQSiQJ ErOD95tiLJmVwstu6FJvtr6HYHMd1axOaXZWUoWGJ3FNi2kf8QW0jnOTyN1UZzLfxLEK 9RxpuAgLEKFs/BD8rdKa91Mi207334+ll306DPlKArzc9XTN4wHEc/uRnVo6TE9cMZ7J g+4VJADdypAE34jo4vNjSLMziUQXnXVqQjPxvCIICnzx7slIuSt3Fkqk+RjpiQXCkRiq 3h7LJXCBmhi+fdh42cKoI85GooKXmBWz7SnpDCDWEiLzRBXb6QVWWw6151VCYiS7V55O E9hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=JBBGafkMt7OMjeY7K8PjAZiYEpVm5oWHr+U5UNLGJTw=; b=ZP+cJrOgAYEpan1gm+1YGKMr4srs0bSKV3f2heTZr9snQfA7003d2bgb7LyQiMfvdc orBVEAPS6upfHqeiGh0NbpIn5cIyxm03jWCBG89JJCF1Nl81paIaDtvh0AJiwuJjXGBp 0La+xBbd2UbELJsnj1wyZTN4gFZp2ffxwYheVZpoxyuiz7gVREgdYJm915ZClfj+laOf ckbWAV26pFsbbayuC+D2e7ovm9809pqLoUWHWQ7TF2NGmYUsCqj5Sux57hsLNPL+JSUn hrGnOlnicG7a2ypJXdekxEgN1hj10XkyHe165fBcfohdbJD9xIGL/ldYswt21NPCPCEF BbDQ== X-Gm-Message-State: AOAM531Ymic8mq/3xB6Xlk7lqd2ooGCtN/gMCr26dJ/Jsa9m6yWTnLvV WlLvY19nKTj7pqw5/f1q5NsOxNJBmUY= X-Google-Smtp-Source: ABdhPJy1pJsfuE75oITUGgqwnA/AtEdVtKsLwSV08xUZO2jhl1CX8efs9+9W2y71T4VSF597zkLZqQ== X-Received: by 2002:a1c:7fd7:: with SMTP id a206mr720611wmd.135.1606164405227; Mon, 23 Nov 2020 12:46:45 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id w11sm827049wmg.36.2020.11.23.12.46.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:44 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 23/28] target/mips: Make pipeline 1 multiply opcodes generic Date: Mon, 23 Nov 2020 21:44:43 +0100 Message-Id: <20201123204448.3260804-24-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::330; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x330.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Special2 multiply opcodes are not specific to Toshiba TX79, and are not part of its multimedia extension. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-22-f4bug@amsat.org> --- target/mips/translate.c | 75 +++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/target/mips/translate.c b/target/mips/translate.c index 7ef3bc52358..8854d284d33 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -330,6 +330,19 @@ enum { OPC_MUL = 0x02 | OPC_SPECIAL2, OPC_MSUB = 0x04 | OPC_SPECIAL2, OPC_MSUBU = 0x05 | OPC_SPECIAL2, + + /* Multiply Instructions for Pipeline 1 */ + OPC_MFHI1 = 0x10 | OPC_SPECIAL2, + OPC_MTHI1 = 0x11 | OPC_SPECIAL2, + OPC_MFLO1 = 0x12 | OPC_SPECIAL2, + OPC_MTLO1 = 0x13 | OPC_SPECIAL2, + OPC_MULT1 = 0x18 | OPC_SPECIAL2, + OPC_MULTU1 = 0x19 | OPC_SPECIAL2, + OPC_DIV1 = 0x1A | OPC_SPECIAL2, + OPC_DIVU1 = 0x1B | OPC_SPECIAL2, + OPC_MADD1 = 0x20 | OPC_SPECIAL2, + OPC_MADDU1 = 0x21 | OPC_SPECIAL2, + /* Misc */ OPC_CLZ = 0x20 | OPC_SPECIAL2, OPC_CLO = 0x21 | OPC_SPECIAL2, @@ -836,21 +849,9 @@ enum { #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F)) enum { - MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */ - MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */ MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI, MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI, MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI, - MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */ - MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */ - MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */ - MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */ - MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */ - MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */ - MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */ - MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */ - MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI, - MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI, MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI, MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI, MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI, @@ -2952,26 +2953,26 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, /* Copy GPR to and from TX79 HI1/LO1 register. */ static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg) { - if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) { + if (reg == 0 && (opc == OPC_MFHI1 || opc == OPC_MFLO1)) { /* Treat as NOP. */ return; } switch (opc) { - case MMI_OPC_MFHI1: + case OPC_MFHI1: tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]); break; - case MMI_OPC_MFLO1: + case OPC_MFLO1: tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]); break; - case MMI_OPC_MTHI1: + case OPC_MTHI1: if (reg != 0) { tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]); } else { tcg_gen_movi_tl(cpu_HI[1], 0); } break; - case MMI_OPC_MTLO1: + case OPC_MTLO1: if (reg != 0) { tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]); } else { @@ -3346,7 +3347,7 @@ static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) gen_load_gpr(t1, rt); switch (opc) { - case MMI_OPC_DIV1: + case OPC_DIV1: { TCGv t2 = tcg_temp_new(); TCGv t3 = tcg_temp_new(); @@ -3367,7 +3368,7 @@ static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) tcg_temp_free(t2); } break; - case MMI_OPC_DIVU1: + case OPC_DIVU1: { TCGv t2 = tcg_const_tl(0); TCGv t3 = tcg_const_tl(1); @@ -3622,7 +3623,7 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, gen_load_gpr(t1, rt); switch (opc) { - case MMI_OPC_MULT1: + case OPC_MULT1: acc = 1; /* Fall through */ case OPC_MULT: @@ -3641,7 +3642,7 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, tcg_temp_free_i32(t3); } break; - case MMI_OPC_MULTU1: + case OPC_MULTU1: acc = 1; /* Fall through */ case OPC_MULTU: @@ -3660,10 +3661,10 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, tcg_temp_free_i32(t3); } break; - case MMI_OPC_MADD1: + case OPC_MADD1: acc = 1; /* Fall through */ - case MMI_OPC_MADD: + case OPC_MADD: { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); @@ -3682,10 +3683,10 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, tcg_temp_free_i64(t2); } break; - case MMI_OPC_MADDU1: + case OPC_MADDU1: acc = 1; /* Fall through */ - case MMI_OPC_MADDU: + case OPC_MADDU: { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); @@ -12644,24 +12645,24 @@ static void decode_mmi(CPUMIPSState *env, DisasContext *ctx) case MMI_OPC_CLASS_MMI3: decode_mmi3(env, ctx); break; - case MMI_OPC_MULT1: - case MMI_OPC_MULTU1: - case MMI_OPC_MADD: - case MMI_OPC_MADDU: - case MMI_OPC_MADD1: - case MMI_OPC_MADDU1: + case OPC_MULT1: + case OPC_MULTU1: + case OPC_MADD: + case OPC_MADDU: + case OPC_MADD1: + case OPC_MADDU1: gen_mul_txx9(ctx, opc, rd, rs, rt); break; - case MMI_OPC_DIV1: - case MMI_OPC_DIVU1: + case OPC_DIV1: + case OPC_DIVU1: gen_div1_tx79(ctx, opc, rs, rt); break; - case MMI_OPC_MTLO1: - case MMI_OPC_MTHI1: + case OPC_MTLO1: + case OPC_MTHI1: gen_HILO1_tx79(ctx, opc, rs); break; - case MMI_OPC_MFLO1: - case MMI_OPC_MFHI1: + case OPC_MFLO1: + case OPC_MFHI1: gen_HILO1_tx79(ctx, opc, rd); break; case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */ From patchwork Mon Nov 23 20:44:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926789 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 643D3C388F9 for ; Mon, 23 Nov 2020 21:32:30 +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 500EF206FB for ; Mon, 23 Nov 2020 21:32:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iR75VgMn" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 500EF206FB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:45630 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJRj-0001gP-KD for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:32:27 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:47044) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjf-0002cq-Ko for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:56 -0500 Received: from mail-wr1-x436.google.com ([2a00:1450:4864:20::436]:39192) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjc-0001u6-Ou for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:46:55 -0500 Received: by mail-wr1-x436.google.com with SMTP id e7so2589160wrv.6 for ; Mon, 23 Nov 2020 12:46:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KTXQ6BcNfHASdBhaYccCTSzBtWV71744MD3MDy4TE8I=; b=iR75VgMnmhWY6aOzU4mODlzDRXPPWHoyYArhX+grHFXEh3HyxEajbtCCoaiPjQ1W/W Ft7q3UZOX73h9aQIeNF2vO23nc775phxfczrid5PCV/sXdll1wa9h+ZXfpwn9y3RpSoH SLRTJ/Eq785QmTesYFnSKnD2KM87OYh6IO9vHUQnA8CbJ+uTpUz62L2IKzoM4Rs7G5U2 VEubx4XY1TNZsN5iHBxX786n1zjivwger1YWuQw1oWErrY5UmDldqHJLgb+Uj4Sc0SJd i5cSD0pL4WrYdX7SXgvF/kW0D871XvQPuryFsPwRaa95oMfJttHe9KtPOyCPpjk1Hz7V kjxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=KTXQ6BcNfHASdBhaYccCTSzBtWV71744MD3MDy4TE8I=; b=fMwOzuXMdVegh9gY2wVPt/w5RV7Kx905mk9NKFhMx542wCgUYDUQxOgxlKji+aVS0A 96mwNrYOckDNosH7FiJkCJZzzLPbw3eFNiJc9oANnCZGLroLLK5uhoApdwJumZ5w4FG8 NCjI/89ROsV1EQOD1PiEPx6NgaYys2bg4TDzjI5HxqxRzlMzqpdWwIRi4LDQgH/Ovvwb 8g52j407Na4bcqRTjIsQllBLKmBUlCXjyFEqivK5qkdcbdogVg833Cvi4hymZyJafRQ7 +cbmkBaKl73FkYl/y3iW8v6uocUK5hD4ljEAJ9IlXsQrTSv74LveRlj5VBMjB05ufcQB WEqQ== X-Gm-Message-State: AOAM5338JptuiS95yPNxEndde8jzjee2hNObv73i25EgtHhZTFs6u7S4 CA0mBBr8R7mBsz/+D9zEpXijCUZtWYE= X-Google-Smtp-Source: ABdhPJw3PgCxb4uNzae76ari8GRmtgVxkdRvedH7UbJlU9vS0MCNrDnSxv6A5hTYlU5SwlLrv6k98g== X-Received: by 2002:adf:ed04:: with SMTP id a4mr1606360wro.172.1606164410492; Mon, 23 Nov 2020 12:46:50 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id c187sm1035610wmd.23.2020.11.23.12.46.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:49 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 24/28] target/mips: Extract Toshiba TXx9 translation routines Date: Mon, 23 Nov 2020 21:44:44 +0100 Message-Id: <20201123204448.3260804-25-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::436; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x436.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract 300 lines of the Toshiba TX19/TX39/TX49/TX79 translation routines to 'vendor-tx_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-23-f4bug@amsat.org> --- target/mips/translate.c | 302 +----------------------- target/mips/vendor-tx_translate.c.inc | 315 ++++++++++++++++++++++++++ 2 files changed, 316 insertions(+), 301 deletions(-) create mode 100644 target/mips/vendor-tx_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 8854d284d33..a4558c21d3f 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -633,31 +633,6 @@ enum { * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit * or sixteen 8-bit paths. * - * Reference: - * - * The Toshiba TX System RISC TX79 Core Architecture manual, - * https://wiki.qemu.org/File:C790.pdf - * - * Three-Operand Multiply and Multiply-Add (4 instructions) - * -------------------------------------------------------- - * MADD [rd,] rs, rt Multiply/Add - * MADDU [rd,] rs, rt Multiply/Add Unsigned - * MULT [rd,] rs, rt Multiply (3-operand) - * MULTU [rd,] rs, rt Multiply Unsigned (3-operand) - * - * Multiply Instructions for Pipeline 1 (10 instructions) - * ------------------------------------------------------ - * MULT1 [rd,] rs, rt Multiply Pipeline 1 - * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1 - * DIV1 rs, rt Divide Pipeline 1 - * DIVU1 rs, rt Divide Unsigned Pipeline 1 - * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1 - * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1 - * MFHI1 rd Move From HI1 Register - * MFLO1 rd Move From LO1 Register - * MTHI1 rs Move To HI1 Register - * MTLO1 rs Move To LO1 Register - * * Arithmetic (19 instructions) * ---------------------------- * PADDB rd, rs, rt Parallel Add Byte @@ -2949,44 +2924,6 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } -#if defined(TARGET_MIPS64) -/* Copy GPR to and from TX79 HI1/LO1 register. */ -static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg) -{ - if (reg == 0 && (opc == OPC_MFHI1 || opc == OPC_MFLO1)) { - /* Treat as NOP. */ - return; - } - - switch (opc) { - case OPC_MFHI1: - tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]); - break; - case OPC_MFLO1: - tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]); - break; - case OPC_MTHI1: - if (reg != 0) { - tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]); - } else { - tcg_gen_movi_tl(cpu_HI[1], 0); - } - break; - case OPC_MTLO1: - if (reg != 0) { - tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]); - } else { - tcg_gen_movi_tl(cpu_LO[1], 0); - } - break; - default: - MIPS_INVAL("mfthilo1 TX79"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} -#endif - /* Arithmetic on HI/LO registers */ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) { @@ -3335,65 +3272,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t1); } -#if defined(TARGET_MIPS64) -static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) -{ - TCGv t0, t1; - - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - - switch (opc) { - case OPC_DIV1: - { - TCGv t2 = tcg_temp_new(); - TCGv t3 = tcg_temp_new(); - tcg_gen_ext32s_tl(t0, t0); - tcg_gen_ext32s_tl(t1, t1); - tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); - tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); - tcg_gen_and_tl(t2, t2, t3); - tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); - tcg_gen_or_tl(t2, t2, t3); - tcg_gen_movi_tl(t3, 0); - tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); - tcg_gen_div_tl(cpu_LO[1], t0, t1); - tcg_gen_rem_tl(cpu_HI[1], t0, t1); - tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]); - tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]); - tcg_temp_free(t3); - tcg_temp_free(t2); - } - break; - case OPC_DIVU1: - { - TCGv t2 = tcg_const_tl(0); - TCGv t3 = tcg_const_tl(1); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); - tcg_gen_divu_tl(cpu_LO[1], t0, t1); - tcg_gen_remu_tl(cpu_HI[1], t0, t1); - tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]); - tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]); - tcg_temp_free(t3); - tcg_temp_free(t2); - } - break; - default: - MIPS_INVAL("div1 TX79"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} -#endif - static void gen_muldiv(DisasContext *ctx, uint32_t opc, int acc, int rs, int rt) { @@ -3586,138 +3464,6 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } -/* - * These MULT[U] and MADD[U] instructions implemented in for example - * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core - * architectures are special three-operand variants with the syntax - * - * MULT[U][1] rd, rs, rt - * - * such that - * - * (rd, LO, HI) <- rs * rt - * - * and - * - * MADD[U][1] rd, rs, rt - * - * such that - * - * (rd, LO, HI) <- (LO, HI) + rs * rt - * - * where the low-order 32-bits of the result is placed into both the - * GPR rd and the special register LO. The high-order 32-bits of the - * result is placed into the special register HI. - * - * If the GPR rd is omitted in assembly language, it is taken to be 0, - * which is the zero register that always reads as 0. - */ -static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, - int rd, int rs, int rt) -{ - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - int acc = 0; - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - - switch (opc) { - case OPC_MULT1: - acc = 1; - /* Fall through */ - case OPC_MULT: - { - TCGv_i32 t2 = tcg_temp_new_i32(); - TCGv_i32 t3 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t2, t0); - tcg_gen_trunc_tl_i32(t3, t1); - tcg_gen_muls2_i32(t2, t3, t2, t3); - if (rd) { - tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); - } - tcg_gen_ext_i32_tl(cpu_LO[acc], t2); - tcg_gen_ext_i32_tl(cpu_HI[acc], t3); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t3); - } - break; - case OPC_MULTU1: - acc = 1; - /* Fall through */ - case OPC_MULTU: - { - TCGv_i32 t2 = tcg_temp_new_i32(); - TCGv_i32 t3 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t2, t0); - tcg_gen_trunc_tl_i32(t3, t1); - tcg_gen_mulu2_i32(t2, t3, t2, t3); - if (rd) { - tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); - } - tcg_gen_ext_i32_tl(cpu_LO[acc], t2); - tcg_gen_ext_i32_tl(cpu_HI[acc], t3); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t3); - } - break; - case OPC_MADD1: - acc = 1; - /* Fall through */ - case OPC_MADD: - { - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - tcg_gen_ext_tl_i64(t2, t0); - tcg_gen_ext_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_add_i64(t2, t2, t3); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - if (rd) { - gen_move_low32(cpu_gpr[rd], t2); - } - tcg_temp_free_i64(t2); - } - break; - case OPC_MADDU1: - acc = 1; - /* Fall through */ - case OPC_MADDU: - { - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i64 t3 = tcg_temp_new_i64(); - - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_extu_tl_i64(t2, t0); - tcg_gen_extu_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_add_i64(t2, t2, t3); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - if (rd) { - gen_move_low32(cpu_gpr[rd], t2); - } - tcg_temp_free_i64(t2); - } - break; - default: - MIPS_INVAL("mul/madd TXx9"); - generate_exception_end(ctx, EXCP_RI); - goto out; - } - - out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} - static void gen_cl(DisasContext *ctx, uint32_t opc, int rd, int rs) { @@ -11150,6 +10896,7 @@ out: #include "mod-dsp_translate.c.inc" #include "vendor-vr54xx_translate.c.inc" +#include "vendor-tx_translate.c.inc" #include "vendor-loong-simd_translate.c.inc" #include "vendor-loong-ext_translate.c.inc" #include "vendor-mxu_translate.c.inc" @@ -11268,53 +11015,6 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) } } -static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx) -{ - int rs = extract32(ctx->opcode, 21, 5); - int rt = extract32(ctx->opcode, 16, 5); - int rd = extract32(ctx->opcode, 11, 5); - uint32_t op1 = MASK_SPECIAL(ctx->opcode); - - switch (op1) { - case OPC_MOVN: /* Conditional move */ - case OPC_MOVZ: - gen_cond_move(ctx, op1, rd, rs, rt); - break; - case OPC_MFHI: /* Move from HI/LO */ - case OPC_MFLO: - gen_HILO(ctx, op1, 0, rd); - break; - case OPC_MTHI: - case OPC_MTLO: /* Move to HI/LO */ - gen_HILO(ctx, op1, 0, rs); - break; - case OPC_MULT: - case OPC_MULTU: - gen_mul_txx9(ctx, op1, rd, rs, rt); - break; - case OPC_DIV: - case OPC_DIVU: - gen_muldiv(ctx, op1, 0, rs, rt); - break; -#if defined(TARGET_MIPS64) - case OPC_DMULT: - case OPC_DMULTU: - case OPC_DDIV: - case OPC_DDIVU: - check_insn_opc_user_only(ctx, INSN_R5900); - gen_muldiv(ctx, op1, 0, rs, rt); - break; -#endif - case OPC_JR: - gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4); - break; - default: /* Invalid */ - MIPS_INVAL("special_tx79"); - generate_exception_end(ctx, EXCP_RI); - break; - } -} - static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd, sa; diff --git a/target/mips/vendor-tx_translate.c.inc b/target/mips/vendor-tx_translate.c.inc new file mode 100644 index 00000000000..1d157743bd4 --- /dev/null +++ b/target/mips/vendor-tx_translate.c.inc @@ -0,0 +1,315 @@ +/* + * Toshiba TX instruction translation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * Overview of the TX79-specific instruction set + * ============================================= + * + * Reference: + * + * The Toshiba TX System RISC TX79 Core Architecture manual, + * https://wiki.qemu.org/File:C790.pdf + * + * Three-Operand Multiply and Multiply-Add (4 instructions) + * -------------------------------------------------------- + * MADD [rd,] rs, rt Multiply/Add + * MADDU [rd,] rs, rt Multiply/Add Unsigned + * MULT [rd,] rs, rt Multiply (3-operand) + * MULTU [rd,] rs, rt Multiply Unsigned (3-operand) + * + * Multiply Instructions for Pipeline 1 (10 instructions) + * ------------------------------------------------------ + * MULT1 [rd,] rs, rt Multiply Pipeline 1 + * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1 + * DIV1 rs, rt Divide Pipeline 1 + * DIVU1 rs, rt Divide Unsigned Pipeline 1 + * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1 + * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1 + * MFHI1 rd Move From HI1 Register + * MFLO1 rd Move From LO1 Register + * MTHI1 rs Move To HI1 Register + * MTLO1 rs Move To LO1 Register + * + */ + +#if defined(TARGET_MIPS64) + +/* Copy GPR to and from TX79 HI1/LO1 register. */ +static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg) +{ + if (reg == 0 && (opc == OPC_MFHI1 || opc == OPC_MFLO1)) { + /* Treat as NOP. */ + return; + } + + switch (opc) { + case OPC_MFHI1: + tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]); + break; + case OPC_MFLO1: + tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]); + break; + case OPC_MTHI1: + if (reg != 0) { + tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]); + } else { + tcg_gen_movi_tl(cpu_HI[1], 0); + } + break; + case OPC_MTLO1: + if (reg != 0) { + tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]); + } else { + tcg_gen_movi_tl(cpu_LO[1], 0); + } + break; + default: + MIPS_INVAL("mfthilo1 TX79"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) +{ + TCGv t0, t1; + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + + switch (opc) { + case OPC_DIV1: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_ext32s_tl(t0, t0); + tcg_gen_ext32s_tl(t1, t1); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_div_tl(cpu_LO[1], t0, t1); + tcg_gen_rem_tl(cpu_HI[1], t0, t1); + tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]); + tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_DIVU1: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_divu_tl(cpu_LO[1], t0, t1); + tcg_gen_remu_tl(cpu_HI[1], t0, t1); + tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]); + tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + default: + MIPS_INVAL("div1 TX79"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} +#endif + +/* + * These MULT[U] and MADD[U] instructions implemented in for example + * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core + * architectures are special three-operand variants with the syntax + * + * MULT[U][1] rd, rs, rt + * + * such that + * + * (rd, LO, HI) <- rs * rt + * + * and + * + * MADD[U][1] rd, rs, rt + * + * such that + * + * (rd, LO, HI) <- (LO, HI) + rs * rt + * + * where the low-order 32-bits of the result is placed into both the + * GPR rd and the special register LO. The high-order 32-bits of the + * result is placed into the special register HI. + * + * If the GPR rd is omitted in assembly language, it is taken to be 0, + * which is the zero register that always reads as 0. + */ +static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int acc = 0; + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + + switch (opc) { + case OPC_MULT1: + acc = 1; + /* Fall through */ + case OPC_MULT: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_muls2_i32(t2, t3, t2, t3); + if (rd) { + tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); + } + tcg_gen_ext_i32_tl(cpu_LO[acc], t2); + tcg_gen_ext_i32_tl(cpu_HI[acc], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case OPC_MULTU1: + acc = 1; + /* Fall through */ + case OPC_MULTU: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_mulu2_i32(t2, t3, t2, t3); + if (rd) { + tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); + } + tcg_gen_ext_i32_tl(cpu_LO[acc], t2); + tcg_gen_ext_i32_tl(cpu_HI[acc], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case OPC_MADD1: + acc = 1; + /* Fall through */ + case OPC_MADD: + { + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_ext_tl_i64(t2, t0); + tcg_gen_ext_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_add_i64(t2, t2, t3); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + if (rd) { + gen_move_low32(cpu_gpr[rd], t2); + } + tcg_temp_free_i64(t2); + } + break; + case OPC_MADDU1: + acc = 1; + /* Fall through */ + case OPC_MADDU: + { + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_extu_tl_i64(t2, t0); + tcg_gen_extu_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_add_i64(t2, t2, t3); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + if (rd) { + gen_move_low32(cpu_gpr[rd], t2); + } + tcg_temp_free_i64(t2); + } + break; + default: + MIPS_INVAL("mul/madd TXx9"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + + out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx) +{ + int rs = extract32(ctx->opcode, 21, 5); + int rt = extract32(ctx->opcode, 16, 5); + int rd = extract32(ctx->opcode, 11, 5); + uint32_t op1 = MASK_SPECIAL(ctx->opcode); + + switch (op1) { + case OPC_MOVN: /* Conditional move */ + case OPC_MOVZ: + gen_cond_move(ctx, op1, rd, rs, rt); + break; + case OPC_MFHI: /* Move from HI/LO */ + case OPC_MFLO: + gen_HILO(ctx, op1, 0, rd); + break; + case OPC_MTHI: + case OPC_MTLO: /* Move to HI/LO */ + gen_HILO(ctx, op1, 0, rs); + break; + case OPC_MULT: + case OPC_MULTU: + gen_mul_txx9(ctx, op1, rd, rs, rt); + break; + case OPC_DIV: + case OPC_DIVU: + gen_muldiv(ctx, op1, 0, rs, rt); + break; +#if defined(TARGET_MIPS64) + case OPC_DMULT: + case OPC_DMULTU: + case OPC_DDIV: + case OPC_DDIVU: + check_insn_opc_user_only(ctx, INSN_R5900); + gen_muldiv(ctx, op1, 0, rs, rt); + break; +#endif + case OPC_JR: + gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4); + break; + default: /* Invalid */ + MIPS_INVAL("special_tx79"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} From patchwork Mon Nov 23 20:44:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926769 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 50C51C2D0E4 for ; Mon, 23 Nov 2020 21:11: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 8450F206B5 for ; Mon, 23 Nov 2020 21:11:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SPcJpkY/" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8450F206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:35216 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ7l-0001cy-DY for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:11:49 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:47098) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjm-0002lp-PP for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:47:02 -0500 Received: from mail-wr1-x433.google.com ([2a00:1450:4864:20::433]:36556) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIji-0001wS-9y for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:47:02 -0500 Received: by mail-wr1-x433.google.com with SMTP id z7so4298976wrn.3 for ; Mon, 23 Nov 2020 12:46:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=I14tN5Tu2ItVYLYMh5ZnvfOf/d6+vwKeGkpRqnrfWo0=; b=SPcJpkY/XbHgg1f/EQsRUiCQiTAfiVKXzYyh1BmaaVTJXbFN+OIR5V4ccNONvnyfdM VUypCqzJETkAHrhIS5aXjihrIGnSMWY59SUzHacOAFjsLYvsL9Oo4oLVldRGT76Z1aw8 HJ1LqhDzWhtIlzp8aqNSCJFbYQoE6jxBA0z7S8ca7ok794VawoISoQfL8mkysEk9l691 G5tjR1/yVyCSxnawMfCPbN56uqtgueE1/8NxXPqecCHvbgQy9KzRL7QEs2FC3IEbfz21 zdYsTMZbaXg9OJGnHGIM4m77bbf0BtrvmqHDLTJnH988zDvVtv3usxPxkYcjWU84n94M NEkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=I14tN5Tu2ItVYLYMh5ZnvfOf/d6+vwKeGkpRqnrfWo0=; b=VOkR4tzvu1i8hILcKca8huGite+kPAhtMhzoq6ljWOMLL2A9dfyvR3WUXh2uLJU3gn tBkHTRhvFrYKy/j7vc7i3R9Xq84UO/n0z99aXPxNxjuzUApEsssY8PNz89kJoTsWPHw/ rjGCOOx0fuwzxmlXbzmeCrR+VbFOZcBcHSqWFn3ZBOg957YA7rYtcxwkmo2IQkOPCK3i piPcuaTFol3r/HVTt3qvJMpuS6X9zmmGsrCcuW2edOdOjnR+dlkBomT+KycRb91vAzlC sUtTVTVvMeLa+DbbNEr91iJedPeNHeC+FF9b/N4x+nfpnA0CZ0IB+MKLf8VmJETbCnNv 12lQ== X-Gm-Message-State: AOAM530oqp7Yx7P6uWCUz9R/AVieg6oCI5C2cB9z+c7n6BjowryLd3yg PSZUFNL/yTLutuH/qPLSXMHQX4mYgjI= X-Google-Smtp-Source: ABdhPJxUX7RlAWc/MxU4WRJygWNRKDSc4o4cYoFY4rSKS28918ecOW85wenFhMtQPoCFTpwJ31r+iQ== X-Received: by 2002:a5d:5651:: with SMTP id j17mr1522097wrw.221.1606164415439; Mon, 23 Nov 2020 12:46:55 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id y2sm22319134wrn.31.2020.11.23.12.46.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:54 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 25/28] target/mips: Extract Toshiba TX79 multimedia translation routines Date: Mon, 23 Nov 2020 21:44:45 +0100 Message-Id: <20201123204448.3260804-26-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::433; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x433.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Extract 600 lines of the the Toshiba TX79 multimedia translation routines to 'vendor-tx-mmi_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- target/mips/translate.c | 568 +-------------------- target/mips/vendor-tx-mmi_translate.c.inc | 573 ++++++++++++++++++++++ 2 files changed, 574 insertions(+), 567 deletions(-) create mode 100644 target/mips/vendor-tx-mmi_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index a4558c21d3f..e95c1e666aa 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -622,405 +622,6 @@ enum { OPC_NMSUB_PS = 0x3E | OPC_CP3, }; - -/* - * Overview of the TX79-specific instruction set - * ============================================= - * - * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits - * are only used by the specific quadword (128-bit) LQ/SQ load/store - * instructions and certain multimedia instructions (MMIs). These MMIs - * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit - * or sixteen 8-bit paths. - * - * Arithmetic (19 instructions) - * ---------------------------- - * PADDB rd, rs, rt Parallel Add Byte - * PSUBB rd, rs, rt Parallel Subtract Byte - * PADDH rd, rs, rt Parallel Add Halfword - * PSUBH rd, rs, rt Parallel Subtract Halfword - * PADDW rd, rs, rt Parallel Add Word - * PSUBW rd, rs, rt Parallel Subtract Word - * PADSBH rd, rs, rt Parallel Add/Subtract Halfword - * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte - * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte - * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword - * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword - * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word - * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word - * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte - * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte - * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword - * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword - * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word - * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word - * - * Min/Max (4 instructions) - * ------------------------ - * PMAXH rd, rs, rt Parallel Maximum Halfword - * PMINH rd, rs, rt Parallel Minimum Halfword - * PMAXW rd, rs, rt Parallel Maximum Word - * PMINW rd, rs, rt Parallel Minimum Word - * - * Absolute (2 instructions) - * ------------------------- - * PABSH rd, rt Parallel Absolute Halfword - * PABSW rd, rt Parallel Absolute Word - * - * Logical (4 instructions) - * ------------------------ - * PAND rd, rs, rt Parallel AND - * POR rd, rs, rt Parallel OR - * PXOR rd, rs, rt Parallel XOR - * PNOR rd, rs, rt Parallel NOR - * - * Shift (9 instructions) - * ---------------------- - * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword - * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword - * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword - * PSLLW rd, rt, sa Parallel Shift Left Logical Word - * PSRLW rd, rt, sa Parallel Shift Right Logical Word - * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word - * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word - * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word - * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word - * - * Compare (6 instructions) - * ------------------------ - * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte - * PCEQB rd, rs, rt Parallel Compare for Equal Byte - * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword - * PCEQH rd, rs, rt Parallel Compare for Equal Halfword - * PCGTW rd, rs, rt Parallel Compare for Greater Than Word - * PCEQW rd, rs, rt Parallel Compare for Equal Word - * - * LZC (1 instruction) - * ------------------- - * PLZCW rd, rs Parallel Leading Zero or One Count Word - * - * Quadword Load and Store (2 instructions) - * ---------------------------------------- - * LQ rt, offset(base) Load Quadword - * SQ rt, offset(base) Store Quadword - * - * Multiply and Divide (19 instructions) - * ------------------------------------- - * PMULTW rd, rs, rt Parallel Multiply Word - * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word - * PDIVW rs, rt Parallel Divide Word - * PDIVUW rs, rt Parallel Divide Unsigned Word - * PMADDW rd, rs, rt Parallel Multiply-Add Word - * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word - * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word - * PMULTH rd, rs, rt Parallel Multiply Halfword - * PMADDH rd, rs, rt Parallel Multiply-Add Halfword - * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword - * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword - * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword - * PDIVBW rs, rt Parallel Divide Broadcast Word - * PMFHI rd Parallel Move From HI Register - * PMFLO rd Parallel Move From LO Register - * PMTHI rs Parallel Move To HI Register - * PMTLO rs Parallel Move To LO Register - * PMFHL rd Parallel Move From HI/LO Register - * PMTHL rs Parallel Move To HI/LO Register - * - * Pack/Extend (11 instructions) - * ----------------------------- - * PPAC5 rd, rt Parallel Pack to 5 bits - * PPACB rd, rs, rt Parallel Pack to Byte - * PPACH rd, rs, rt Parallel Pack to Halfword - * PPACW rd, rs, rt Parallel Pack to Word - * PEXT5 rd, rt Parallel Extend Upper from 5 bits - * PEXTUB rd, rs, rt Parallel Extend Upper from Byte - * PEXTLB rd, rs, rt Parallel Extend Lower from Byte - * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword - * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword - * PEXTUW rd, rs, rt Parallel Extend Upper from Word - * PEXTLW rd, rs, rt Parallel Extend Lower from Word - * - * Others (16 instructions) - * ------------------------ - * PCPYH rd, rt Parallel Copy Halfword - * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword - * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword - * PREVH rd, rt Parallel Reverse Halfword - * PINTH rd, rs, rt Parallel Interleave Halfword - * PINTEH rd, rs, rt Parallel Interleave Even Halfword - * PEXEH rd, rt Parallel Exchange Even Halfword - * PEXCH rd, rt Parallel Exchange Center Halfword - * PEXEW rd, rt Parallel Exchange Even Word - * PEXCW rd, rt Parallel Exchange Center Word - * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable - * MFSA rd Move from Shift Amount Register - * MTSA rs Move to Shift Amount Register - * MTSAB rs, immediate Move Byte Count to Shift Amount Register - * MTSAH rs, immediate Move Halfword Count to Shift Amount Register - * PROT3W rd, rt Parallel Rotate 3 Words - * - * MMI (MultiMedia Instruction) encodings - * ====================================== - * - * MMI instructions encoding table keys: - * - * * This code is reserved for future use. An attempt to execute it - * causes a Reserved Instruction exception. - * % This code indicates an instruction class. The instruction word - * must be further decoded by examining additional tables that show - * the values for other instruction fields. - * # This code is reserved for the unsupported instructions DMULT, - * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt - * to execute it causes a Reserved Instruction exception. - * - * MMI instructions encoded by opcode field (MMI, LQ, SQ): - * - * 31 26 0 - * +--------+----------------------------------------+ - * | opcode | | - * +--------+----------------------------------------+ - * - * opcode bits 28..26 - * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 - * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 - * -------+-------+-------+-------+-------+-------+-------+-------+------- - * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ - * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI - * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL - * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ - * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU - * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE - * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD - * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD - */ - -enum { - MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */ - MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */ - MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */ -}; - -/* - * MMI instructions with opcode field = MMI: - * - * 31 26 5 0 - * +--------+-------------------------------+--------+ - * | MMI | |function| - * +--------+-------------------------------+--------+ - * - * function bits 2..0 - * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 - * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 - * -------+-------+-------+-------+-------+-------+-------+-------+------- - * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | * - * 1 001 | MMI0% | MMI2% | * | * | * | * | * | * - * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | * - * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | * - * 4 100 | MADD1 | MADDU1| * | * | * | * | * | * - * 5 101 | MMI1% | MMI3% | * | * | * | * | * | * - * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH - * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW - */ - -#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F)) -enum { - MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI, - MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI, - MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI, - MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI, - MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI, - MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI, - MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI, - MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI, - MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI, - MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI, - MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI, - MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI, - MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI, -}; - -/* - * MMI instructions with opcode field = MMI and bits 5..0 = MMI0: - * - * 31 26 10 6 5 0 - * +--------+----------------------+--------+--------+ - * | MMI | |function| MMI0 | - * +--------+----------------------+--------+--------+ - * - * function bits 7..6 - * bits | 0 | 1 | 2 | 3 - * 10..8 | 00 | 01 | 10 | 11 - * -------+-------+-------+-------+------- - * 0 000 | PADDW | PSUBW | PCGTW | PMAXW - * 1 001 | PADDH | PSUBH | PCGTH | PMAXH - * 2 010 | PADDB | PSUBB | PCGTB | * - * 3 011 | * | * | * | * - * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW - * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH - * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB - * 7 111 | * | * | PEXT5 | PPAC5 - */ - -#define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF)) -enum { - MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0, - MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0, -}; - -/* - * MMI instructions with opcode field = MMI and bits 5..0 = MMI1: - * - * 31 26 10 6 5 0 - * +--------+----------------------+--------+--------+ - * | MMI | |function| MMI1 | - * +--------+----------------------+--------+--------+ - * - * function bits 7..6 - * bits | 0 | 1 | 2 | 3 - * 10..8 | 00 | 01 | 10 | 11 - * -------+-------+-------+-------+------- - * 0 000 | * | PABSW | PCEQW | PMINW - * 1 001 | PADSBH| PABSH | PCEQH | PMINH - * 2 010 | * | * | PCEQB | * - * 3 011 | * | * | * | * - * 4 100 | PADDUW| PSUBUW| PEXTUW| * - * 5 101 | PADDUH| PSUBUH| PEXTUH| * - * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV - * 7 111 | * | * | * | * - */ - -#define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF)) -enum { - MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1, - MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1, -}; - -/* - * MMI instructions with opcode field = MMI and bits 5..0 = MMI2: - * - * 31 26 10 6 5 0 - * +--------+----------------------+--------+--------+ - * | MMI | |function| MMI2 | - * +--------+----------------------+--------+--------+ - * - * function bits 7..6 - * bits | 0 | 1 | 2 | 3 - * 10..8 | 00 | 01 | 10 | 11 - * -------+-------+-------+-------+------- - * 0 000 | PMADDW| * | PSLLVW| PSRLVW - * 1 001 | PMSUBW| * | * | * - * 2 010 | PMFHI | PMFLO | PINTH | * - * 3 011 | PMULTW| PDIVW | PCPYLD| * - * 4 100 | PMADDH| PHMADH| PAND | PXOR - * 5 101 | PMSUBH| PHMSBH| * | * - * 6 110 | * | * | PEXEH | PREVH - * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W - */ - -#define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF)) -enum { - MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2, - MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2, -}; - -/* - * MMI instructions with opcode field = MMI and bits 5..0 = MMI3: - * - * 31 26 10 6 5 0 - * +--------+----------------------+--------+--------+ - * | MMI | |function| MMI3 | - * +--------+----------------------+--------+--------+ - * - * function bits 7..6 - * bits | 0 | 1 | 2 | 3 - * 10..8 | 00 | 01 | 10 | 11 - * -------+-------+-------+-------+------- - * 0 000 |PMADDUW| * | * | PSRAVW - * 1 001 | * | * | * | * - * 2 010 | PMTHI | PMTLO | PINTEH| * - * 3 011 |PMULTUW| PDIVUW| PCPYUD| * - * 4 100 | * | * | POR | PNOR - * 5 101 | * | * | * | * - * 6 110 | * | * | PEXCH | PCPYH - * 7 111 | * | * | PEXCW | * - */ - -#define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF)) -enum { - MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3, - MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3, -}; - /* global register indices */ static TCGv cpu_gpr[32], cpu_PC; static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; @@ -1030,11 +631,6 @@ static TCGv_i32 hflags; static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; -#if defined(TARGET_MIPS64) -/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */ -static TCGv_i64 cpu_mmr[32]; -#endif - #include "exec/gen-icount.h" #define gen_helper_0e0i(name, arg) do { \ @@ -10897,6 +10493,7 @@ out: #include "vendor-vr54xx_translate.c.inc" #include "vendor-tx_translate.c.inc" +#include "vendor-tx-mmi_translate.c.inc" #include "vendor-loong-simd_translate.c.inc" #include "vendor-loong-ext_translate.c.inc" #include "vendor-mxu_translate.c.inc" @@ -11305,169 +10902,6 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) } } - -#if defined(TARGET_MIPS64) - -/* - * - * MMI (MultiMedia Interface) ASE instructions - * =========================================== - */ - -/* - * MMI instructions category: data communication - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH - * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W - * PCPYUD PEXEH PEXTLW PPACW - * PEXEW PEXTUB - * PEXTUH - * PEXTUW - */ - -/* - * PCPYH rd, rt - * - * Parallel Copy Halfword - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---------+---------+-----------+ - * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 | - * +-----------+---------+---------+---------+---------+-----------+ - */ -static void gen_mmi_pcpyh(DisasContext *ctx) -{ - uint32_t pd, rt, rd; - uint32_t opcode; - - opcode = ctx->opcode; - - pd = extract32(opcode, 21, 5); - rt = extract32(opcode, 16, 5); - rd = extract32(opcode, 11, 5); - - if (unlikely(pd != 0)) { - generate_exception_end(ctx, EXCP_RI); - } else if (rd == 0) { - /* nop */ - } else if (rt == 0) { - tcg_gen_movi_i64(cpu_gpr[rd], 0); - tcg_gen_movi_i64(cpu_mmr[rd], 0); - } else { - TCGv_i64 t0 = tcg_temp_new(); - TCGv_i64 t1 = tcg_temp_new(); - uint64_t mask = (1ULL << 16) - 1; - - tcg_gen_andi_i64(t0, cpu_gpr[rt], mask); - tcg_gen_movi_i64(t1, 0); - tcg_gen_or_i64(t1, t0, t1); - tcg_gen_shli_i64(t0, t0, 16); - tcg_gen_or_i64(t1, t0, t1); - tcg_gen_shli_i64(t0, t0, 16); - tcg_gen_or_i64(t1, t0, t1); - tcg_gen_shli_i64(t0, t0, 16); - tcg_gen_or_i64(t1, t0, t1); - - tcg_gen_mov_i64(cpu_gpr[rd], t1); - - tcg_gen_andi_i64(t0, cpu_mmr[rt], mask); - tcg_gen_movi_i64(t1, 0); - tcg_gen_or_i64(t1, t0, t1); - tcg_gen_shli_i64(t0, t0, 16); - tcg_gen_or_i64(t1, t0, t1); - tcg_gen_shli_i64(t0, t0, 16); - tcg_gen_or_i64(t1, t0, t1); - tcg_gen_shli_i64(t0, t0, 16); - tcg_gen_or_i64(t1, t0, t1); - - tcg_gen_mov_i64(cpu_mmr[rd], t1); - - tcg_temp_free(t0); - tcg_temp_free(t1); - } -} - -/* - * PCPYLD rd, rs, rt - * - * Parallel Copy Lower Doubleword - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---------+---------+-----------+ - * | MMI | rs | rt | rd | PCPYLD | MMI2 | - * +-----------+---------+---------+---------+---------+-----------+ - */ -static void gen_mmi_pcpyld(DisasContext *ctx) -{ - uint32_t rs, rt, rd; - uint32_t opcode; - - opcode = ctx->opcode; - - rs = extract32(opcode, 21, 5); - rt = extract32(opcode, 16, 5); - rd = extract32(opcode, 11, 5); - - if (rd == 0) { - /* nop */ - } else { - if (rs == 0) { - tcg_gen_movi_i64(cpu_mmr[rd], 0); - } else { - tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]); - } - if (rt == 0) { - tcg_gen_movi_i64(cpu_gpr[rd], 0); - } else { - if (rd != rt) { - tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]); - } - } - } -} - -/* - * PCPYUD rd, rs, rt - * - * Parallel Copy Upper Doubleword - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------+---------+---------+---------+---------+-----------+ - * | MMI | rs | rt | rd | PCPYUD | MMI3 | - * +-----------+---------+---------+---------+---------+-----------+ - */ -static void gen_mmi_pcpyud(DisasContext *ctx) -{ - uint32_t rs, rt, rd; - uint32_t opcode; - - opcode = ctx->opcode; - - rs = extract32(opcode, 21, 5); - rt = extract32(opcode, 16, 5); - rd = extract32(opcode, 11, 5); - - if (rd == 0) { - /* nop */ - } else { - if (rs == 0) { - tcg_gen_movi_i64(cpu_gpr[rd], 0); - } else { - tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]); - } - if (rt == 0) { - tcg_gen_movi_i64(cpu_mmr[rd], 0); - } else { - if (rd != rt) { - tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]); - } - } - } -} - -#endif - static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd; diff --git a/target/mips/vendor-tx-mmi_translate.c.inc b/target/mips/vendor-tx-mmi_translate.c.inc new file mode 100644 index 00000000000..84118cc5df3 --- /dev/null +++ b/target/mips/vendor-tx-mmi_translate.c.inc @@ -0,0 +1,573 @@ +#if defined(TARGET_MIPS64) +/* + * Toshiba TX MultiMedia Instruction translation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits + * are only used by the specific quadword (128-bit) LQ/SQ load/store + * instructions and certain multimedia instructions (MMIs). These MMIs + * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit + * or sixteen 8-bit paths. + * + * Reference: + * + * The Toshiba TX System RISC TX79 Core Architecture manual, + * https://wiki.qemu.org/File:C790.pdf + * + * Arithmetic (19 instructions) + * ---------------------------- + * PADDB rd, rs, rt Parallel Add Byte + * PSUBB rd, rs, rt Parallel Subtract Byte + * PADDH rd, rs, rt Parallel Add Halfword + * PSUBH rd, rs, rt Parallel Subtract Halfword + * PADDW rd, rs, rt Parallel Add Word + * PSUBW rd, rs, rt Parallel Subtract Word + * PADSBH rd, rs, rt Parallel Add/Subtract Halfword + * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte + * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte + * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword + * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword + * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word + * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word + * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte + * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte + * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword + * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword + * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word + * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word + * + * Min/Max (4 instructions) + * ------------------------ + * PMAXH rd, rs, rt Parallel Maximum Halfword + * PMINH rd, rs, rt Parallel Minimum Halfword + * PMAXW rd, rs, rt Parallel Maximum Word + * PMINW rd, rs, rt Parallel Minimum Word + * + * Absolute (2 instructions) + * ------------------------- + * PABSH rd, rt Parallel Absolute Halfword + * PABSW rd, rt Parallel Absolute Word + * + * Logical (4 instructions) + * ------------------------ + * PAND rd, rs, rt Parallel AND + * POR rd, rs, rt Parallel OR + * PXOR rd, rs, rt Parallel XOR + * PNOR rd, rs, rt Parallel NOR + * + * Shift (9 instructions) + * ---------------------- + * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword + * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword + * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword + * PSLLW rd, rt, sa Parallel Shift Left Logical Word + * PSRLW rd, rt, sa Parallel Shift Right Logical Word + * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word + * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word + * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word + * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word + * + * Compare (6 instructions) + * ------------------------ + * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte + * PCEQB rd, rs, rt Parallel Compare for Equal Byte + * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword + * PCEQH rd, rs, rt Parallel Compare for Equal Halfword + * PCGTW rd, rs, rt Parallel Compare for Greater Than Word + * PCEQW rd, rs, rt Parallel Compare for Equal Word + * + * LZC (1 instruction) + * ------------------- + * PLZCW rd, rs Parallel Leading Zero or One Count Word + * + * Quadword Load and Store (2 instructions) + * ---------------------------------------- + * LQ rt, offset(base) Load Quadword + * SQ rt, offset(base) Store Quadword + * + * Multiply and Divide (19 instructions) + * ------------------------------------- + * PMULTW rd, rs, rt Parallel Multiply Word + * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word + * PDIVW rs, rt Parallel Divide Word + * PDIVUW rs, rt Parallel Divide Unsigned Word + * PMADDW rd, rs, rt Parallel Multiply-Add Word + * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word + * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word + * PMULTH rd, rs, rt Parallel Multiply Halfword + * PMADDH rd, rs, rt Parallel Multiply-Add Halfword + * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword + * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword + * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword + * PDIVBW rs, rt Parallel Divide Broadcast Word + * PMFHI rd Parallel Move From HI Register + * PMFLO rd Parallel Move From LO Register + * PMTHI rs Parallel Move To HI Register + * PMTLO rs Parallel Move To LO Register + * PMFHL rd Parallel Move From HI/LO Register + * PMTHL rs Parallel Move To HI/LO Register + * + * Pack/Extend (11 instructions) + * ----------------------------- + * PPAC5 rd, rt Parallel Pack to 5 bits + * PPACB rd, rs, rt Parallel Pack to Byte + * PPACH rd, rs, rt Parallel Pack to Halfword + * PPACW rd, rs, rt Parallel Pack to Word + * PEXT5 rd, rt Parallel Extend Upper from 5 bits + * PEXTUB rd, rs, rt Parallel Extend Upper from Byte + * PEXTLB rd, rs, rt Parallel Extend Lower from Byte + * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword + * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword + * PEXTUW rd, rs, rt Parallel Extend Upper from Word + * PEXTLW rd, rs, rt Parallel Extend Lower from Word + * + * Others (16 instructions) + * ------------------------ + * PCPYH rd, rt Parallel Copy Halfword + * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword + * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword + * PREVH rd, rt Parallel Reverse Halfword + * PINTH rd, rs, rt Parallel Interleave Halfword + * PINTEH rd, rs, rt Parallel Interleave Even Halfword + * PEXEH rd, rt Parallel Exchange Even Halfword + * PEXCH rd, rt Parallel Exchange Center Halfword + * PEXEW rd, rt Parallel Exchange Even Word + * PEXCW rd, rt Parallel Exchange Center Word + * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable + * MFSA rd Move from Shift Amount Register + * MTSA rs Move to Shift Amount Register + * MTSAB rs, immediate Move Byte Count to Shift Amount Register + * MTSAH rs, immediate Move Halfword Count to Shift Amount Register + * PROT3W rd, rt Parallel Rotate 3 Words + * + * MMI (MultiMedia Instruction) encodings + * ====================================== + * + * MMI instructions encoding table keys: + * + * * This code is reserved for future use. An attempt to execute it + * causes a Reserved Instruction exception. + * % This code indicates an instruction class. The instruction word + * must be further decoded by examining additional tables that show + * the values for other instruction fields. + * # This code is reserved for the unsupported instructions DMULT, + * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt + * to execute it causes a Reserved Instruction exception. + * + * MMI instructions encoded by opcode field (MMI, LQ, SQ): + * + * 31 26 0 + * +--------+----------------------------------------+ + * | opcode | | + * +--------+----------------------------------------+ + * + * opcode bits 28..26 + * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 + * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 + * -------+-------+-------+-------+-------+-------+-------+-------+------- + * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ + * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI + * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL + * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ + * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU + * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE + * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD + * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD + */ + +enum { + MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */ + MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */ + MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */ +}; + +/* + * MMI instructions with opcode field = MMI: + * + * 31 26 5 0 + * +--------+-------------------------------+--------+ + * | MMI | |function| + * +--------+-------------------------------+--------+ + * + * function bits 2..0 + * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 + * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 + * -------+-------+-------+-------+-------+-------+-------+-------+------- + * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | * + * 1 001 | MMI0% | MMI2% | * | * | * | * | * | * + * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | * + * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | * + * 4 100 | MADD1 | MADDU1| * | * | * | * | * | * + * 5 101 | MMI1% | MMI3% | * | * | * | * | * | * + * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH + * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW + */ + +#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F)) +enum { + MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI, + MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI, + MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI, + MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI, + MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI, + MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI, + MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI, + MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI, + MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI, + MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI, + MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI, + MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI, + MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI, +}; + +/* + * MMI instructions with opcode field = MMI and bits 5..0 = MMI0: + * + * 31 26 10 6 5 0 + * +--------+----------------------+--------+--------+ + * | MMI | |function| MMI0 | + * +--------+----------------------+--------+--------+ + * + * function bits 7..6 + * bits | 0 | 1 | 2 | 3 + * 10..8 | 00 | 01 | 10 | 11 + * -------+-------+-------+-------+------- + * 0 000 | PADDW | PSUBW | PCGTW | PMAXW + * 1 001 | PADDH | PSUBH | PCGTH | PMAXH + * 2 010 | PADDB | PSUBB | PCGTB | * + * 3 011 | * | * | * | * + * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW + * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH + * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB + * 7 111 | * | * | PEXT5 | PPAC5 + */ + +#define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF)) +enum { + MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0, + MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0, +}; + +/* + * MMI instructions with opcode field = MMI and bits 5..0 = MMI1: + * + * 31 26 10 6 5 0 + * +--------+----------------------+--------+--------+ + * | MMI | |function| MMI1 | + * +--------+----------------------+--------+--------+ + * + * function bits 7..6 + * bits | 0 | 1 | 2 | 3 + * 10..8 | 00 | 01 | 10 | 11 + * -------+-------+-------+-------+------- + * 0 000 | * | PABSW | PCEQW | PMINW + * 1 001 | PADSBH| PABSH | PCEQH | PMINH + * 2 010 | * | * | PCEQB | * + * 3 011 | * | * | * | * + * 4 100 | PADDUW| PSUBUW| PEXTUW| * + * 5 101 | PADDUH| PSUBUH| PEXTUH| * + * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV + * 7 111 | * | * | * | * + */ + +#define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF)) +enum { + MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1, + MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1, +}; + +/* + * MMI instructions with opcode field = MMI and bits 5..0 = MMI2: + * + * 31 26 10 6 5 0 + * +--------+----------------------+--------+--------+ + * | MMI | |function| MMI2 | + * +--------+----------------------+--------+--------+ + * + * function bits 7..6 + * bits | 0 | 1 | 2 | 3 + * 10..8 | 00 | 01 | 10 | 11 + * -------+-------+-------+-------+------- + * 0 000 | PMADDW| * | PSLLVW| PSRLVW + * 1 001 | PMSUBW| * | * | * + * 2 010 | PMFHI | PMFLO | PINTH | * + * 3 011 | PMULTW| PDIVW | PCPYLD| * + * 4 100 | PMADDH| PHMADH| PAND | PXOR + * 5 101 | PMSUBH| PHMSBH| * | * + * 6 110 | * | * | PEXEH | PREVH + * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W + */ + +#define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF)) +enum { + MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2, + MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2, +}; + +/* + * MMI instructions with opcode field = MMI and bits 5..0 = MMI3: + * + * 31 26 10 6 5 0 + * +--------+----------------------+--------+--------+ + * | MMI | |function| MMI3 | + * +--------+----------------------+--------+--------+ + * + * function bits 7..6 + * bits | 0 | 1 | 2 | 3 + * 10..8 | 00 | 01 | 10 | 11 + * -------+-------+-------+-------+------- + * 0 000 |PMADDUW| * | * | PSRAVW + * 1 001 | * | * | * | * + * 2 010 | PMTHI | PMTLO | PINTEH| * + * 3 011 |PMULTUW| PDIVUW| PCPYUD| * + * 4 100 | * | * | POR | PNOR + * 5 101 | * | * | * | * + * 6 110 | * | * | PEXCH | PCPYH + * 7 111 | * | * | PEXCW | * + */ + +#define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF)) +enum { + MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3, + MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3, +}; + +/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */ +static TCGv_i64 cpu_mmr[32]; + +/* + * + * MMI (MultiMedia Interface) ASE instructions + * =========================================== + */ + +/* + * MMI instructions category: data communication + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH + * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W + * PCPYUD PEXEH PEXTLW PPACW + * PEXEW PEXTUB + * PEXTUH + * PEXTUW + */ + +/* + * PCPYH rd, rt + * + * Parallel Copy Halfword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyh(DisasContext *ctx) +{ + uint32_t pd, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + pd = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (unlikely(pd != 0)) { + generate_exception_end(ctx, EXCP_RI); + } else if (rd == 0) { + /* nop */ + } else if (rt == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + TCGv_i64 t0 = tcg_temp_new(); + TCGv_i64 t1 = tcg_temp_new(); + uint64_t mask = (1ULL << 16) - 1; + + tcg_gen_andi_i64(t0, cpu_gpr[rt], mask); + tcg_gen_movi_i64(t1, 0); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + + tcg_gen_mov_i64(cpu_gpr[rd], t1); + + tcg_gen_andi_i64(t0, cpu_mmr[rt], mask); + tcg_gen_movi_i64(t1, 0); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + + tcg_gen_mov_i64(cpu_mmr[rd], t1); + + tcg_temp_free(t0); + tcg_temp_free(t1); + } +} + +/* + * PCPYLD rd, rs, rt + * + * Parallel Copy Lower Doubleword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI | rs | rt | rd | PCPYLD | MMI2 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyld(DisasContext *ctx) +{ + uint32_t rs, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + rs = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (rd == 0) { + /* nop */ + } else { + if (rs == 0) { + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]); + } + if (rt == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + } else { + if (rd != rt) { + tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]); + } + } + } +} + +/* + * PCPYUD rd, rs, rt + * + * Parallel Copy Upper Doubleword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI | rs | rt | rd | PCPYUD | MMI3 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyud(DisasContext *ctx) +{ + uint32_t rs, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + rs = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (rd == 0) { + /* nop */ + } else { + if (rs == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + } else { + tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]); + } + if (rt == 0) { + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + if (rd != rt) { + tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]); + } + } + } +} + +#endif From patchwork Mon Nov 23 20:44:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926771 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 E9371C2D0E4 for ; Mon, 23 Nov 2020 21:12:54 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 43980206F9 for ; Mon, 23 Nov 2020 21:12:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RIbvTJfR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 43980206F9 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:38168 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJ8n-0002rh-8w for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:12:53 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:47102) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjn-0002nU-Ek for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:47:03 -0500 Received: from mail-wr1-x443.google.com ([2a00:1450:4864:20::443]:32862) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjl-0001xd-Qr for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:47:03 -0500 Received: by mail-wr1-x443.google.com with SMTP id u12so20185500wrt.0 for ; Mon, 23 Nov 2020 12:47:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=sTFpJW58XZ2N3GcSvdqnh8S3DT54Pmk8KnHBCRTI0vQ=; b=RIbvTJfR3ywqs/D7FIrlCRH3BHF1yUV8z/SnP3C6ikiZ0GDklbmIjwbnEQslsrGb7G 6ME4IADdc1mXd17r+UAk4WyOQaK+ehKkpALag601167IiszYzanNyGNsaAV6Uv/4a7EF 4d2QGJFX0erCjPihXRfEFO8HAt21jkRkuPC2SVI+SRLVvbFp90PBPqd7ZUNE3cjowAQ+ ITpWO1fMsht/LUlR2qcKKZUm/tyLy+M5DmKUH/kxk/ByuszP7uZIWhjnYhYH2nbi7n9H Y1mpth8WX9OZp8WfLrk9z254YRCHR2DOdTohiMLVUMscGD0hcIBqT0684b6y+WzahME0 sIHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=sTFpJW58XZ2N3GcSvdqnh8S3DT54Pmk8KnHBCRTI0vQ=; b=XN+J8CndIbf9qJpp731Ce+9tknalD19sxFFCu85dz2aZkRxgo/SdSutDEoQamy0kKT Q9/4r7ciRhF4QYXDfAmFRmqSyRnXQKePhTWhISI+5n810HCEecfz8qFOyWS53Yh3zAVQ NaEMGLsOMMQZqaBZCz4TS1fvvmY3zBfS6XvG4xstO7jFSnH7JP5v8m3skfZj2stSaf9W QAAnjgTC7bB5JFoNky3CK5XijB05Ytuo4UDJbGik3CxwzOFj9cHVMhg9/j/oDDg++nUq uXavoo5J635s9t/6+DoCNsCdTOvISs/mGDvK19L2unHm61tXxzFHRDO2TQQaAbwbwhmF NKAQ== X-Gm-Message-State: AOAM533GH+uOXt2+v+H+IpUkfDIp4kB4tE8XUX/kQuvuswpmCQCAOvnS /owVOcZjssb0CLaDcMIewK0kekEpRJ0= X-Google-Smtp-Source: ABdhPJxK900Cdw6eRolrggEBV2XkAITvpYUxBvCq0j1KMxqMmbaMroLZv32tqQdSJRYLPg/hM0KJNg== X-Received: by 2002:a05:6000:c7:: with SMTP id q7mr1492704wrx.137.1606164420142; Mon, 23 Nov 2020 12:47:00 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id j8sm21331543wrx.11.2020.11.23.12.46.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:46:59 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 26/28] MAINTAINERS: Add entry for MIPS Loongson TCG Date: Mon, 23 Nov 2020 21:44:46 +0100 Message-Id: <20201123204448.3260804-27-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::443; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-x443.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add an entry for the TCG core related to Loongson. Signed-off-by: Philippe Mathieu-Daudé --- Adding Huacai and Jiaxun in case they want to be notified of changes, patch conditional to their individual approval. --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 10e87d27eab..0f49b997f2e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -241,6 +241,13 @@ F: include/hw/timer/mips_gictimer.h F: tests/tcg/mips/ K: ^Subject:.*(?i)mips +MIPS TCG CPUs (Loongson) +M: Philippe Mathieu-Daudé +R: Huacai Chen +R: Jiaxun Yang +S: Odd Fixes +F: target/mips/vendor-loong* + MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.* From patchwork Mon Nov 23 20:44:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926781 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 BA69CC2D0E4 for ; Mon, 23 Nov 2020 21:19:44 +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 099AC206B5 for ; Mon, 23 Nov 2020 21:19:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pkA91Fv3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 099AC206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:53938 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJFO-0001Bw-VH for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:19:43 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:47124) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjs-0002xF-1N for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:47:08 -0500 Received: from mail-wm1-x335.google.com ([2a00:1450:4864:20::335]:40747) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjq-0001zv-K3 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:47:07 -0500 Received: by mail-wm1-x335.google.com with SMTP id a3so727373wmb.5 for ; Mon, 23 Nov 2020 12:47:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9WfXx5bwoQ1bGvwty9bUUX0gx83YLXHNHesMImFdU98=; b=pkA91Fv3xv409n9qJ9dpK0VQlV3LBcuxQB7mCot5EQIMk/oqUAWSbzjdiejdOOgmDG uglGf9tPfh/LSLq6V2fxgUqegO+ePhrm9tKuzPI+iKGhRzjg2/S9ZzXO0VldsM859K0W oDGo62v+Pc24liXNAi1aWHdNort3lxV11GahsT+i78bNe4XASpNxc5+R177Mk3lhhqat 4eId0VsCKRCBovKXVp/0lCyti1HYpo96nnVWUQhZftdBiL6UTF94K3zdg0vRxb0okuyh VisKqSaSZztFj6apz8ta27xly/N0zuxRyK6KwhtrnadWgeRrMY4M0yrpLcHhypEU/WAz /C5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=9WfXx5bwoQ1bGvwty9bUUX0gx83YLXHNHesMImFdU98=; b=dwkgEjYY4WaOSBMP8BVEt4CAJiKNHgZCDh7s9oqjXyPbk8hDhzteL5UTi7DK7I3Hek Ol+rnhczx0KuMmhTFXMFhUU7GVlVcFPUNFXx1jg/cMW2b8Yldbk8bD4BD12nuyliPQ2C r6scrED+0vuCCKTxy4PalwWkZED6c/WA/+vmdze7kO3q8o0TpOkawyTD7dh9O9/QvMk+ y1B3YXsuCjgGbNmTCNnidpLh0D4qKbd0EpMJAhdwQwz3AUyIjI5MKHnzn7F35P9HJckc U4h7iJHeeC5ai+5iTj1/o2D6GV/B+2x6FqFU+UKxR/cSQVgouIWyMj4+O6X9Ca1mrYDH p0sw== X-Gm-Message-State: AOAM532+xBPHCKCCBIMbZvBTWMWHFsn8Oj1lEgQdSTFSaCPfzCHsbXxl pKW6cMLWezdl6x4JyrGb8CPYq4xSscI= X-Google-Smtp-Source: ABdhPJxprXwZBsCRV8Ns0+jHBbHMeTqCm1GHR/0ko0wi5GicI2e8u2I21Z7ht2dyPnacJCCz6WvWjg== X-Received: by 2002:a05:600c:290a:: with SMTP id i10mr706151wmd.187.1606164425048; Mon, 23 Nov 2020 12:47:05 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id u203sm815879wme.32.2020.11.23.12.47.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:47:04 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 27/28] MAINTAINERS: Add entry for MIPS Ingenic Xburst TCG Date: Mon, 23 Nov 2020 21:44:47 +0100 Message-Id: <20201123204448.3260804-28-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::335; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x335.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add an entry for the TCG core related to Ingenic Xburst. Signed-off-by: Philippe Mathieu-Daudé --- Adding Craig Janeczek in case he wants to be notified of changes, patch conditional to his approval. --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0f49b997f2e..976d23508c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -248,6 +248,12 @@ R: Jiaxun Yang S: Odd Fixes F: target/mips/vendor-loong* +MIPS TCG CPUs (Ingenic Xburst) +M: Philippe Mathieu-Daudé +R: Craig Janeczek +S: Odd Fixes +F: target/mips/vendor-xburst* + MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.* From patchwork Mon Nov 23 20:44:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 11926775 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.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 52A0EC388F9 for ; Mon, 23 Nov 2020 21:15:52 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B1E6D206B5 for ; Mon, 23 Nov 2020 21:15:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hDfcBBQR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B1E6D206B5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=amsat.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:44608 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1khJBe-0005hd-5v for qemu-devel@archiver.kernel.org; Mon, 23 Nov 2020 16:15:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:47162) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1khIjx-00034m-T7 for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:47:17 -0500 Received: from mail-wm1-x341.google.com ([2a00:1450:4864:20::341]:39847) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1khIjv-00020v-QL for qemu-devel@nongnu.org; Mon, 23 Nov 2020 15:47:13 -0500 Received: by mail-wm1-x341.google.com with SMTP id s13so733887wmh.4 for ; Mon, 23 Nov 2020 12:47:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qKnuSsMcPcENLKBNnohxCclJvsUgxb6ZminldHfrSRI=; b=hDfcBBQR8dayGQHjOcgdZNgSvfsUYeQ8BSljhsqEpVZGAQJBj24E5n9lgheMbTReq5 mioHCk5YGzwt83Vq+VwbtrOvFqV8uaTW1JxQueUwtIXX/2TLD0isaqMI13R3OARf6+fu 8zF7twoZdUcWvyao8uLuEUIR+Kw43blaDbX59zRS2zpsQ4QRKIloueEbB60V+sMhZ6SU vR55LHETB4o8/+O0DT3NqI0PV7busZZg03U7e5k4jJfpM7clrDyZNDcrOKVyBrbOwI/C pd8lCDt6i1mjx2sMiZfU57sbt2IPzAvuFDsg0mNAEoCZFOGfhTnFO75Z03w3Db/D4Dqw WTxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=qKnuSsMcPcENLKBNnohxCclJvsUgxb6ZminldHfrSRI=; b=k+S8Xyo90CJkb5t3ryHk8x/6O6OAew79WITklOlJv2l4IzpilQWcrSvKzbDdzKqINX 3UArFS/bOGhj4MTWkl+6D/EJJfdRPKCSHBD4JFJpOhxxUQUkjpGLOnhqK5SROaM6wDvc +HxUt36uwpSVi014cJzSLDYOAyeKCkxAb/jEJMKEq+/p+ZYwz4tHUAAjU1CSGOfAF1fu G4Smi32V9XYO1naoBYxJJ51ygi7vQuRBn3c6ZpHq3kVe4XVTQ3oZLufV7LKTY4k+Md0L 0/usE3tGToq766MRP9ViOgrbO/lDQtvHACLj0sDSz3FX1hf2+LB7YMeQO9uYennOnwLp SR/A== X-Gm-Message-State: AOAM531bIZ6PJRNWh7PT79VtcfKfs2z8JELTZGk2dkSTN3uHY2xwUGUI H6+OpYzncg0HUywpoZdiMuPunsrJ84s= X-Google-Smtp-Source: ABdhPJx2Q16tyKADDf28Q7fJo0Yd8NafXX3YqRfXfWwUSxnxHiJj2zRm3z0JsaS4l1UqxlDWpiC+DA== X-Received: by 2002:a1c:9ad3:: with SMTP id c202mr691669wme.43.1606164430077; Mon, 23 Nov 2020 12:47:10 -0800 (PST) Received: from x1w.redhat.com (111.red-88-21-205.staticip.rima-tde.net. [88.21.205.111]) by smtp.gmail.com with ESMTPSA id f17sm920931wmh.10.2020.11.23.12.47.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Nov 2020 12:47:09 -0800 (PST) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Subject: [PATCH v2 28/28] MAINTAINERS: Add entry for MIPS Toshiba TCG Date: Mon, 23 Nov 2020 21:44:48 +0100 Message-Id: <20201123204448.3260804-29-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201123204448.3260804-1-f4bug@amsat.org> References: <20201123204448.3260804-1-f4bug@amsat.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::341; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-x341.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add an entry for the TCG core related to Toshiba TXx9. Signed-off-by: Philippe Mathieu-Daudé --- Adding Fredrik Noring in case he wants to be notified of changes, patch conditional to his approval. --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 976d23508c8..7b70cd9a799 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -254,6 +254,12 @@ R: Craig Janeczek S: Odd Fixes F: target/mips/vendor-xburst* +MIPS TCG CPUs (Toshiba TX) +M: Philippe Mathieu-Daudé +R: Fredrik Noring +S: Odd Fixes +F: target/mips/vendor-tx* + MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.*