From patchwork Mon Oct 24 15:23:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 1693981 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=flygoat.com header.i=@flygoat.com header.a=rsa-sha256 header.s=fm1 header.b=o+2F6fX9; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=pNsyy8TG; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Mx1p24Pvsz23l8 for ; Tue, 25 Oct 2022 04:11:53 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1omzJ3-0003dk-Nw; Mon, 24 Oct 2022 11:24:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJ2-0003dI-PY for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:00 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJ0-0008Fk-M1 for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:00 -0400 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.west.internal (Postfix) with ESMTP id 4744D3200645; Mon, 24 Oct 2022 11:23:56 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Mon, 24 Oct 2022 11:23:56 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flygoat.com; h= cc:cc:content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; t=1666625035; x=1666711435; bh=lQ HWUYJM8thKmUr0Q+IUw7XZeSNMjQBQ0vISQ+mREWM=; b=o+2F6fX9iLYjNuX24j sN/x2FUS8ioqK5LJlGS0R9g+fo9IJzOMg2k7DvSAmx/26cW+/B4imTYD8szKMem+ 3t5hSAqAJBTCv0kVOMSFsDM/kaWsPg4EtwgYhrz7xupRBmY9HiPD7xH6Sq20n70T yvtwwu5DW0VLq/lecXAzkngugCfDcS9LJJhUE2r7VvE06ED74peqiVBVuKi7frbn 9OOVVG3SmnspUVLn79X6Lud7c1VSD49Sp3Y9Xtp9JuhBRbi6HXHwAuJsK1TxPHoj 8BHWwMDE1d7fV2MLPTyqcjJHUHPWXd0XsVpFYQkL6qQz5gWO6lPutRQ1omEa6l5Y D0zw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; t=1666625035; x=1666711435; bh=lQHWUYJM8thKm Ur0Q+IUw7XZeSNMjQBQ0vISQ+mREWM=; b=pNsyy8TG4hwFXImRIOkZXRM2GNcMS iQEjhTZ5bSpD+TsFheDUCmk2rQ5th1CmMfEJJ06KjNANhiA+6of1ONbK2f81wIWF EJNBQ7jhyYXUSDBl2X9VBPo6U2tO6Tn7KP4b8t/xFzOVbThJG+PNEkQoaNmTDi15 bMv9kDna4i0lj+9w+PZOJC9YEKpda8xdPulzluFnpsov67CIYZ5ItZZcAid+yPn3 2MpiYYeM9jK7FkLuHzQ+Nz/Myta0Apq8xNTOIZw1b0mkmFdkPgiBgR9FLpJ4j5gl lBdLNPfaIgtMbKLvd5x4K89l5aU7pleLLxHSMAjboujHwNaJQorvMYf2A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrgedtgedgkeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeflihgrgihunhcujggrnhhguceojhhirgiguhhnrdihrghn ghesfhhlhihgohgrthdrtghomheqnecuggftrfgrthhtvghrnhepfeeludefheegvdeuvd dvgeekgfdvtdettdelieeihfegtedugeekhfdvhfejfedtnecuvehluhhsthgvrhfuihii vgeptdenucfrrghrrghmpehmrghilhhfrhhomhepjhhirgiguhhnrdihrghnghesfhhlhi hgohgrthdrtghomh X-ME-Proxy: Feedback-ID: ifd894703:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 24 Oct 2022 11:23:54 -0400 (EDT) From: Jiaxun Yang To: qemu-devel@nongnu.org Cc: f4bug@amsat.org, richard.henderson@linaro.org, Jiaxun Yang Subject: [PATCH 1/6] target/mips: Introduce register access helper functions Date: Mon, 24 Oct 2022 16:23:44 +0100 Message-Id: <20221024152349.215135-2-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221024152349.215135-1-jiaxun.yang@flygoat.com> References: <20221024152349.215135-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.19; envelope-from=jiaxun.yang@flygoat.com; helo=wout3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Qemu-devel" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Introduce register access functions with value extend capability to prepare for decodetree based translation implmentation. Signed-off-by: Jiaxun Yang Reviewed-by: Richard Henderson --- target/mips/tcg/translate.c | 143 +++++++++++++++++++++++++++++++++++- target/mips/tcg/translate.h | 54 ++++++++++++++ 2 files changed, 196 insertions(+), 1 deletion(-) diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index de1511baaf..b5d595ef34 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -1196,6 +1196,17 @@ enum { MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI, }; +/* + * If an operation is being performed on less than TARGET_LONG_BITS, + * it may require the inputs to be sign- or zero-extended; which will + * depend on the exact operation being performed. + */ +typedef enum { + EXT_NONE, + EXT_SIGN, + EXT_ZERO +} DisasExtend; + /* global register indices */ TCGv cpu_gpr[32], cpu_PC; /* @@ -1221,6 +1232,18 @@ static const char regnames_LO[][4] = { "LO0", "LO1", "LO2", "LO3", }; +static TCGv ctx_temp_new(DisasContext *ctx) +{ + assert(ctx->ntemp < ARRAY_SIZE(ctx->temp)); + return ctx->temp[ctx->ntemp++] = tcg_temp_new(); +} + +static TCGv_i64 ctx_temp_new_i64(DisasContext *ctx) +{ + assert(ctx->ntemp64 < ARRAY_SIZE(ctx->temp64)); + return ctx->temp64[ctx->ntemp64++] = tcg_temp_new_i64(); +} + /* General purpose registers moves. */ void gen_load_gpr(TCGv t, int reg) { @@ -1238,6 +1261,106 @@ void gen_store_gpr(TCGv t, int reg) } } +void gen_extend(TCGv dst, TCGv src, DisasExtend src_ext) +{ + switch (src_ext) { + case EXT_NONE: + tcg_gen_mov_tl(dst, src); + return; + case EXT_SIGN: + tcg_gen_ext32s_tl(dst, src); + return; + case EXT_ZERO: + tcg_gen_ext32u_tl(dst, src); + return; + } + g_assert_not_reached(); +} + +TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend src_ext) +{ + TCGv t; + + if (reg_num == 0) { + return ctx->zero; + } + + switch (src_ext) { + case EXT_NONE: + return cpu_gpr[reg_num]; + default: + t = ctx_temp_new(ctx); + gen_extend(t, cpu_gpr[reg_num], src_ext); + return t; + } +} + +TCGv_i64 get_hilo(DisasContext *ctx, int acc) +{ + TCGv_i64 t = ctx_temp_new_i64(ctx); + /* acc must be 0 when DSP is not implemented */ + g_assert(acc == 0 || ctx->insn_flags & ASE_DSP); + tcg_gen_concat_tl_i64(t, cpu_LO[acc], cpu_HI[acc]); + + return t; +} + +TCGv dest_gpr(DisasContext *ctx, int reg_num) +{ + if (reg_num == 0) { + return ctx_temp_new(ctx); + } + return cpu_gpr[reg_num]; +} + +TCGv dest_lo(DisasContext *ctx, int acc) +{ + /* acc must be 0 when DSP is not implemented */ + g_assert(acc == 0 || ctx->insn_flags & ASE_DSP); + + return cpu_LO[acc]; +} + +TCGv dest_hi(DisasContext *ctx, int acc) +{ + /* acc must be 0 when DSP is not implemented */ + g_assert(acc == 0 || ctx->insn_flags & ASE_DSP); + + return cpu_HI[acc]; +} + +/* For 32 bit hilo pair */ +TCGv_i64 dest_hilo(DisasContext *ctx, int acc) +{ + /* acc must be 0 when DSP is not implemented */ + g_assert(acc == 0 || ctx->insn_flags & ASE_DSP); + return ctx_temp_new_i64(ctx); +} + +void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext) +{ + if (reg_num != 0) { + gen_extend(cpu_gpr[reg_num], t, dst_ext); + } +} + +void gen_set_lo(int acc, TCGv t, DisasExtend dst_ext) +{ + gen_extend(cpu_LO[acc], t, dst_ext); +} + +void gen_set_hi(int acc, TCGv t, DisasExtend dst_ext) +{ + gen_extend(cpu_HI[acc], t, dst_ext); +} + +/* For 32 bit hilo pair */ +void gen_set_hilo(int acc, TCGv_i64 t) +{ + gen_move_low32(cpu_LO[acc], t); + gen_move_high32(cpu_HI[acc], t); +} + #if defined(TARGET_MIPS64) void gen_load_gpr_hi(TCGv_i64 t, int reg) { @@ -2615,7 +2738,6 @@ static void gen_shift_imm(DisasContext *ctx, uint32_t opc, tcg_temp_free(t0); } -/* Arithmetic */ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { @@ -16031,6 +16153,12 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->base.max_insns = 2; } + ctx->ntemp = 0; + ctx->ntemp64 = 0; + memset(ctx->temp, 0, sizeof(ctx->temp)); + memset(ctx->temp64, 0, sizeof(ctx->temp)); + ctx->zero = tcg_constant_tl(0); + LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx, ctx->hflags); } @@ -16053,6 +16181,7 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) DisasContext *ctx = container_of(dcbase, DisasContext, base); int insn_bytes; int is_slot; + int i; is_slot = ctx->hflags & MIPS_HFLAG_BMASK; if (ctx->insn_flags & ISA_NANOMIPS32) { @@ -16074,6 +16203,18 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) return; } + for (i = ctx->ntemp - 1; i >= 0; --i) { + tcg_temp_free(ctx->temp[i]); + ctx->temp[i] = NULL; + ctx->ntemp--; + } + + for (i = ctx->ntemp64 - 1; i >= 0; --i) { + tcg_temp_free_i64(ctx->temp64[i]); + ctx->temp64[i] = NULL; + ctx->ntemp64--; + } + if (ctx->hflags & MIPS_HFLAG_BMASK) { if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 | MIPS_HFLAG_FBNSLOT))) { diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index 69f85841d2..980aa8682d 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -49,6 +49,11 @@ typedef struct DisasContext { bool saar; bool mi; int gi; + TCGv zero; + TCGv temp[4]; + uint8_t ntemp; + TCGv_i64 temp64[4]; + uint8_t ntemp64; } DisasContext; #define DISAS_STOP DISAS_TARGET_0 @@ -119,6 +124,17 @@ enum { OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4, }; +/* + * If an operation is being performed on less than TARGET_LONG_BITS, + * it may require the inputs to be sign- or zero-extended; which will + * depend on the exact operation being performed. + */ +typedef enum { + EXT_NONE, + EXT_SIGN, + EXT_ZERO +} DisasExtend; + #define gen_helper_0e1i(name, arg1, arg2) do { \ gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \ } while (0) @@ -150,6 +166,18 @@ void check_cp1_64bitmode(DisasContext *ctx); void check_cp1_registers(DisasContext *ctx, int regs); void check_cop1x(DisasContext *ctx); +void gen_extend(TCGv dst, TCGv src, DisasExtend src_ext); +TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend src_ext); +TCGv_i64 get_hilo(DisasContext *ctx, int acc); +TCGv dest_gpr(DisasContext *ctx, int reg_num); +TCGv dest_lo(DisasContext *ctx, int acc); +TCGv dest_hi(DisasContext *ctx, int acc); +TCGv_i64 dest_hilo(DisasContext *ctx, int acc); +void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext); +void gen_set_lo(int acc, TCGv t, DisasExtend dst_ext); +void gen_set_hi(int acc, TCGv t, DisasExtend dst_ext); +void gen_set_hilo(int acc, TCGv_i64 t); + void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset); void gen_move_low32(TCGv ret, TCGv_i64 arg); void gen_move_high32(TCGv ret, TCGv_i64 arg); @@ -231,6 +259,32 @@ bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn); static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \ { return FUNC(ctx, a, __VA_ARGS__); } +/* Instructions removed in Release 6 */ +#define TRANS_6R(NAME, FUNC, ...) \ + static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \ + { return !(ctx->insn_flags & ISA_MIPS_R6) & FUNC(ctx, a, __VA_ARGS__); } + +#if defined(TARGET_MIPS64) +#define TRANS64(NAME, FUNC, ...) \ + static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \ + { check_mips_64(ctx); return FUNC(ctx, a, __VA_ARGS__); } +#define TRANS64_6R(NAME, FUNC, ...) \ + static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \ + { if (ctx->insn_flags & ISA_MIPS_R6) return false; check_mips_64(ctx); \ + return FUNC(ctx, a, __VA_ARGS__); } +#else +#define TRANS64(NAME, FUNC, ...) \ + static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \ + { return false; } +#define TRANS64_6R(NAME, FUNC, ...) \ + static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \ + { return false; } +#endif + +#define TRANS_FLAGS(NAME, FLAGS, ...) \ + static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \ + { return (ctx->insn_flags & FLAGS) && FUNC(s, __VA_ARGS__); } + static inline bool cpu_is_bigendian(DisasContext *ctx) { return extract32(ctx->CP0_Config0, CP0C0_BE, 1); From patchwork Mon Oct 24 15:23:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 1693960 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=flygoat.com header.i=@flygoat.com header.a=rsa-sha256 header.s=fm1 header.b=jCLelnyp; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=B2NwIjms; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MwzXm6mngz23js for ; Tue, 25 Oct 2022 02:30:15 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1omzJ5-0003eG-TA; Mon, 24 Oct 2022 11:24:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJ4-0003dx-6E for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:02 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJ1-0008Ft-Hw for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:01 -0400 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.west.internal (Postfix) with ESMTP id 227683200805; Mon, 24 Oct 2022 11:23:58 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Mon, 24 Oct 2022 11:23:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flygoat.com; h= cc:cc:content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; t=1666625037; x=1666711437; bh=d+ LjkiAfgacH3tsiShIBiIkdBeIpKthkGtVUtdrd/LQ=; b=jCLelnyp6Llb45XeQQ yH6W5ArNEDKgJTLeGSYAq+mpLCJCErtkAzf4cLWLQxd+JZt6E4aSoZhpHj2chds1 nMv6NaBUWtk9KHZmn0MzgCpYzUpT8NhR2OtVK06iiwUfrlBcK9HNA1tyI8PwKkTI IXUSxCOqnQfHJSA+uaJO25nb9PX5dy1Nnwt+SNlJvXFAYDyBFuttWtgUGYxK9BRC N5OToIHSoe8bO5gOiubgmhz+kzTXSuGjNJoCJGB8hZigoDHsCYVtnQyztvF2DwD/ 4ceK4RJE6tfgEDoRq3RJxFAJ8IqtKJVZPiCDx98LkurbWHKGL3mdEUuCU8Gped3j WQoQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; t=1666625037; x=1666711437; bh=d+LjkiAfgacH3 tsiShIBiIkdBeIpKthkGtVUtdrd/LQ=; b=B2NwIjms+CGnZ3UuvWvsU1ENKkW4S DeD4LLuyvicTnanc9+auig5FLm3eVgE86H2KKw8SSJdQSWWrBZWxdNllNzc35qLC YBjqDzO2c//VIOoXhITaO3PCSfEoNs7oHuEKpS8Uru07+QYmqz9ZXfH+0ns1rdB6 SSVN4Hrq/zO3BuXguR6O6k+tE17NL+8HTUmPWmo5NjF3C/4cIExRSXiWyVdH1MCQ p0XMfdt67ibXJ3kbaVDvwM6fjGtRlYrOZQxxwamco8RTlFv/mUNvnXhnXbHmfLW8 ZoMj5c0qE1j21AVQklO3NcjPZxXbb1PmiFvMn05h2dkXiA+MhJW6ToGcQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrgedtgedgkeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeflihgrgihunhcujggrnhhguceojhhirgiguhhnrdihrghn ghesfhhlhihgohgrthdrtghomheqnecuggftrfgrthhtvghrnhepfeeludefheegvdeuvd dvgeekgfdvtdettdelieeihfegtedugeekhfdvhfejfedtnecuvehluhhsthgvrhfuihii vgeptdenucfrrghrrghmpehmrghilhhfrhhomhepjhhirgiguhhnrdihrghnghesfhhlhi hgohgrthdrtghomh X-ME-Proxy: Feedback-ID: ifd894703:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 24 Oct 2022 11:23:56 -0400 (EDT) From: Jiaxun Yang To: qemu-devel@nongnu.org Cc: f4bug@amsat.org, richard.henderson@linaro.org, Jiaxun Yang Subject: [PATCH 2/6] target/mips: Convert legacy arithmatic instructions to decodetree Date: Mon, 24 Oct 2022 16:23:45 +0100 Message-Id: <20221024152349.215135-3-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221024152349.215135-1-jiaxun.yang@flygoat.com> References: <20221024152349.215135-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.19; envelope-from=jiaxun.yang@flygoat.com; helo=wout3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Qemu-devel" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Mostly copy paste from translate.c, with some simplification based on newly introduced register access functions. Signed-off-by: Jiaxun Yang --- target/mips/tcg/insn_trans/trans_arith.c.inc | 352 +++++++++++++++++++ target/mips/tcg/legacy.decode | 62 ++++ target/mips/tcg/meson.build | 1 + target/mips/tcg/translate.c | 20 +- 4 files changed, 425 insertions(+), 10 deletions(-) create mode 100644 target/mips/tcg/insn_trans/trans_arith.c.inc create mode 100644 target/mips/tcg/legacy.decode diff --git a/target/mips/tcg/insn_trans/trans_arith.c.inc b/target/mips/tcg/insn_trans/trans_arith.c.inc new file mode 100644 index 0000000000..3de9722939 --- /dev/null +++ b/target/mips/tcg/insn_trans/trans_arith.c.inc @@ -0,0 +1,352 @@ +static bool gen_arith_notrap(DisasContext *ctx, arg_r *a, + DisasExtend ext, void (*func)(TCGv, TCGv, TCGv)) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs, ext); + TCGv src2 = get_gpr(ctx, a->rt, ext); + + func(dest, src1, src2); + gen_set_gpr(a->rd, dest, ext); + + return true; +} + +static bool gen_add(DisasContext *ctx, arg_r *a, DisasExtend ext) +{ + TCGv t0 = tcg_temp_local_new(); + TCGv t1 = get_gpr(ctx, a->rs, ext); + TCGv t2 = get_gpr(ctx, a->rt, ext); + TCGLabel *l1 = gen_new_label(); + + tcg_gen_add_tl(t0, t1, t2); + gen_extend(t0, t0, ext); + tcg_gen_xor_tl(t1, t1, t2); + tcg_gen_xor_tl(t2, t0, t2); + tcg_gen_andc_tl(t1, t2, t1); + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); + /* operands of same sign, result different sign */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + gen_store_gpr(t0, a->rd); + tcg_temp_free(t0); + + return true; +} + +static bool gen_sub(DisasContext *ctx, arg_r *a, DisasExtend ext) +{ + TCGv src1 = get_gpr(ctx, a->rs, ext); + TCGv src2 = get_gpr(ctx, a->rt, ext); + TCGv t0 = tcg_temp_local_new(); + TCGv t1 = tcg_temp_local_new(); + TCGv t2 = tcg_temp_local_new(); + TCGLabel *l1 = gen_new_label(); + + tcg_gen_sub_tl(t0, src1, src2); + gen_extend(t0, t0, ext); + tcg_gen_xor_tl(t2, src1, src2); + tcg_gen_xor_tl(t1, t0, src1); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); + tcg_temp_free(t1); + /* + * operands of different sign, first operand and the result + * of different sign + */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + gen_store_gpr(t0, a->rd); + tcg_temp_free(t0); + + return true; +} + +static bool gen_arith_imm_notrap(DisasContext *ctx, arg_i *a, DisasExtend ext, + void (*func)(TCGv, TCGv, target_long)) +{ + TCGv dest = dest_gpr(ctx, a->rt); + TCGv src1 = get_gpr(ctx, a->rs, ext); + + func(dest, src1, a->imm); + gen_set_gpr(a->rt, dest, ext); + + return true; +} + +static bool gen_add_imm(DisasContext *ctx, arg_i *a, DisasExtend ext) +{ + TCGv t0 = tcg_temp_local_new(); + TCGv t1 = get_gpr(ctx, a->rs, ext); + TCGv t2 = tcg_temp_new(); + TCGLabel *l1 = gen_new_label(); + target_ulong uimm = (target_long)a->imm; /* Sign extend to 32/64 bits */ + + gen_load_gpr(t1, a->rs); + tcg_gen_addi_tl(t0, t1, uimm); + tcg_gen_ext32s_tl(t0, t0); + + tcg_gen_xori_tl(t1, t1, ~uimm); + tcg_gen_xori_tl(t2, t0, uimm); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); + /* operands of same sign, result different sign */ + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(l1); + tcg_gen_ext32s_tl(t0, t0); + gen_store_gpr(t0, a->rt); + tcg_temp_free(t0); + + return true; +} + +#define DECLEAR_GEN_CL(suffix, arg_type) \ +static bool gen_cl_##suffix(DisasContext *ctx, arg_type * a, bool zero) \ +{ \ + TCGv dest = dest_gpr(ctx, a->rd); \ + TCGv src = get_gpr(ctx, a->rs, EXT_NONE); \ + if (!zero) { \ + tcg_gen_not_tl(dest, src); \ + } \ + tcg_gen_ext32u_tl(dest, dest); \ + tcg_gen_clzi_tl(dest, dest, TARGET_LONG_BITS); \ + tcg_gen_subi_tl(dest, dest, TARGET_LONG_BITS - 32); \ + gen_set_gpr(a->rd, dest, EXT_NONE); \ + return true; \ +} \ + +DECLEAR_GEN_CL(legacy, arg_r) +#undef DECLEAR_GEN_CL + +#ifdef TARGET_MIPS64 +#define DECLEAR_GEN_DCL(suffix, arg_type) \ +static bool gen_dcl_##suffix(DisasContext *ctx, arg_type * a, bool zero) \ +{ \ + TCGv dest = dest_gpr(ctx, a->rd); \ + TCGv src = get_gpr(ctx, a->rs, EXT_NONE); \ + if (!zero) { \ + tcg_gen_not_tl(dest, src); \ + } \ + tcg_gen_clzi_i64(dest, dest, 64); \ + gen_set_gpr(a->rd, dest, EXT_NONE); \ + return true; \ +} \ + +DECLEAR_GEN_DCL(legacy, arg_r) +#undef DECLEAR_GEN_DCL +#endif + +static bool gen_setcond(DisasContext *ctx, arg_r *a, TCGCond cond) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs, EXT_NONE); + TCGv src2 = get_gpr(ctx, a->rt, EXT_NONE); + + tcg_gen_setcond_tl(cond, dest, src1, src2); + + gen_set_gpr(a->rd, dest, EXT_NONE); + + return true; +} + +static bool gen_setcond_imm(DisasContext *ctx, arg_i *a, TCGCond cond) +{ + TCGv dest = dest_gpr(ctx, a->rt); + TCGv src1 = get_gpr(ctx, a->rs, EXT_NONE); + + tcg_gen_setcondi_tl(cond, dest, src1, a->imm); + + gen_set_gpr(a->rt, dest, EXT_NONE); + + return true; +} + +static bool gen_mult32(DisasContext *ctx, arg_r2_s *a, + void (*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) +{ + TCGv src1 = get_gpr(ctx, a->rs, EXT_NONE); + TCGv src2 = get_gpr(ctx, a->rt, EXT_NONE); + TCGv dst_lo = dest_lo(ctx, 0); + TCGv dst_hi = dest_hi(ctx, 0); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t1, src1); + tcg_gen_trunc_tl_i32(t2, src2); + + func(t1, t2, t1, t2); + + tcg_gen_ext_i32_tl(dst_lo, t1); + tcg_gen_ext_i32_tl(dst_hi, t2); + + gen_set_lo(0, dst_lo, EXT_NONE); + gen_set_hi(0, dst_hi, EXT_NONE); + + return true; +} + +#if defined(TARGET_MIPS64) +static bool gen_mult64(DisasContext *ctx, arg_r2_s *a, + void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) +{ + TCGv src1 = get_gpr(ctx, a->rs, EXT_NONE); + TCGv src2 = get_gpr(ctx, a->rt, EXT_NONE); + TCGv dst_lo = dest_lo(ctx, 0); + TCGv dst_hi = dest_hi(ctx, 0); + + func(dst_lo, dst_hi, src1, src2); + + gen_set_lo(0, dst_lo, EXT_NONE); + gen_set_hi(0, dst_hi, EXT_NONE); + + return true; +} +#endif + +static bool gen_div(DisasContext *ctx, arg_r2_s *a, DisasExtend src_ext, + DisasExtend dst_ext) +{ + TCGv temp1, temp2, zero, one, mone, min; + TCGv src1 = get_gpr(ctx, a->rs, src_ext); + TCGv src2 = get_gpr(ctx, a->rt, src_ext); + TCGv dst_lo = dest_lo(ctx, 0); + TCGv dst_hi = dest_hi(ctx, 0); + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + mone = tcg_constant_tl(-1); + min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1)); + + /* + * If overflow, set temp2 to 1, else source2. + * This produces the required result of min. + */ + tcg_gen_setcond_tl(TCG_COND_EQ, temp1, src1, min); + tcg_gen_setcond_tl(TCG_COND_EQ, temp2, src2, mone); + tcg_gen_and_tl(temp1, temp1, temp2); + tcg_gen_movcond_tl(TCG_COND_NE, temp2, temp1, zero, one, src2); + + /* + * If div by zero, set temp1 to -1 and temp2 to 1 to + * produce the required result of -1. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp1, src2, zero, mone, src1); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, src2, zero, one, src2); + + tcg_gen_div_tl(dst_lo, temp1, temp2); + tcg_gen_rem_tl(dst_hi, temp1, temp2); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); + + gen_set_lo(0, dst_lo, dst_ext); + gen_set_hi(0, dst_hi, dst_ext); + + return true; +} + +static bool gen_divu(DisasContext *ctx, arg_r2_s *a, DisasExtend src_ext, + DisasExtend dst_ext) +{ + TCGv temp1, temp2, zero, one, max; + TCGv src1 = get_gpr(ctx, a->rs, src_ext); + TCGv src2 = get_gpr(ctx, a->rt, src_ext); + TCGv dst_lo = dest_lo(ctx, 0); + TCGv dst_hi = dest_hi(ctx, 0); + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + max = tcg_constant_tl(~0); + + /* + * If div by zero, set temp1 to max and temp2 to 1 to + * produce the required result of max. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp1, src2, zero, max, src1); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, src2, zero, one, src2); + + tcg_gen_divu_tl(dst_lo, temp1, temp2); + tcg_gen_remu_tl(dst_hi, temp1, temp2); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); + + gen_set_lo(0, dst_lo, dst_ext); + gen_set_hi(0, dst_hi, dst_ext); + + return true; +} + +static bool gen_mul_addsub(DisasContext *ctx, arg_r2_s *a, DisasExtend ext, + void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) +{ + TCGv src1 = get_gpr(ctx, a->rs, ext); + TCGv src2 = get_gpr(ctx, a->rt, ext); + TCGv_i64 src3 = get_hilo(ctx, 0); + TCGv_i64 dst = dest_hilo(ctx, 0); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + switch (ext) { + case EXT_SIGN: + tcg_gen_ext_tl_i64(t2, src1); + tcg_gen_ext_tl_i64(t3, src2); + break; + case EXT_ZERO: + tcg_gen_extu_tl_i64(t2, src1); + tcg_gen_extu_tl_i64(t3, src2); + break; + default: + g_assert_not_reached(); + break; + } + + tcg_gen_mul_i64(dst, t2, t3); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); + func(dst, dst, src3); + + gen_set_hilo(0, dst); + + return true; +} + +TRANS(ADD, gen_add, EXT_SIGN) +TRANS(ADDU, gen_arith_notrap, EXT_SIGN, tcg_gen_add_tl) +TRANS_6R(ADDI, gen_add_imm, EXT_SIGN) +TRANS(ADDIU, gen_arith_imm_notrap, EXT_SIGN, tcg_gen_addi_tl) +TRANS(SUB, gen_sub, EXT_SIGN) +TRANS(SUBU, gen_arith_notrap, EXT_SIGN, tcg_gen_sub_tl) +TRANS_6R(CLO, gen_cl_legacy, false) +TRANS_6R(CLZ, gen_cl_legacy, true) +TRANS(SLT, gen_setcond, TCG_COND_LT) +TRANS(SLTU, gen_setcond, TCG_COND_LTU) +TRANS(SLTI, gen_setcond_imm, TCG_COND_LT) +TRANS(SLTIU, gen_setcond_imm, TCG_COND_LTU) +TRANS_6R(MUL, gen_arith_notrap, EXT_SIGN, tcg_gen_mul_tl) +TRANS_6R(MULT, gen_mult32, tcg_gen_muls2_i32) +TRANS_6R(MULTU, gen_mult32, tcg_gen_mulu2_i32) +TRANS_6R(DIV, gen_div, EXT_SIGN, EXT_SIGN) +TRANS_6R(DIVU, gen_divu, EXT_ZERO, EXT_SIGN) +TRANS_6R(MADD, gen_mul_addsub, EXT_SIGN, tcg_gen_add_i64) +TRANS_6R(MADDU, gen_mul_addsub, EXT_ZERO, tcg_gen_add_i64) +TRANS_6R(MSUB, gen_mul_addsub, EXT_SIGN, tcg_gen_sub_i64) +TRANS_6R(MSUBU, gen_mul_addsub, EXT_ZERO, tcg_gen_sub_i64) + +TRANS64(DADD, gen_add, EXT_NONE) +TRANS64(DADDU, gen_arith_notrap, EXT_NONE, tcg_gen_add_tl) +TRANS64_6R(DADDI, gen_add_imm, EXT_NONE) +TRANS64(DADDIU, gen_arith_imm_notrap, EXT_NONE, tcg_gen_addi_tl) +TRANS64(DSUB, gen_sub, EXT_NONE) +TRANS64(DSUBU, gen_arith_notrap, EXT_NONE, tcg_gen_sub_tl) +TRANS64_6R(DCLO, gen_dcl_legacy, false) +TRANS64_6R(DCLZ, gen_dcl_legacy, true) +TRANS64_6R(DMULT, gen_mult64, tcg_gen_muls2_i64) +TRANS64_6R(DMULTU, gen_mult64, tcg_gen_mulu2_i64) +TRANS64_6R(DDIV, gen_div, EXT_NONE, EXT_NONE) +TRANS64_6R(DDIVU, gen_divu, EXT_NONE, EXT_NONE) diff --git a/target/mips/tcg/legacy.decode b/target/mips/tcg/legacy.decode new file mode 100644 index 0000000000..d535fbe31b --- /dev/null +++ b/target/mips/tcg/legacy.decode @@ -0,0 +1,62 @@ +# MIPS I to MIPS Release 5 instructions +# +# Copyright (C) 2022 Jiaxun Yang +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# + + +# Fields: +%rd 11:5 +%rs 21:5 +%rt 16:5 + +%imms16 0:s16 + +# Argument sets: +&empty +&r rd rs rt +&r2_s rs rt +&i rt rs imm + +# Formats: +@r ................................ &r %rd %rs %rt +@r2_s ................................ &r2_s %rs %rt +@i ................................ &i %rt %rs imm=%imms16 + +# Base arithmetic instructions +ADD 000000 ...............00000100000 @r +ADDI 001000 .......................... @i # 6R +ADDIU 001001 .......................... @i +ADDU 000000 ...............00000100001 @r +CLO 011100 ...............00000100001 @r # 6Rm +CLZ 011100 ...............00000100000 @r # 6Rm +DIV 000000 ..........0000000000011010 @r2_s # 6R +DIVU 000000 ..........0000000000011011 @r2_s # 6R +MADD 011100 ..........0000000000000000 @r2_s # 6R +MADDU 011100 ..........0000000000000001 @r2_s # 6R +MSUB 011100 ..........0000000000000100 @r2_s # 6R +MSUBU 011100 ..........0000000000000101 @r2_s # 6R +MUL 011100 ...............00000000010 @r # 6R +MULT 000000 ..........0000000000011000 @r2_s # 6R +MULTU 000000 ..........0000000000011001 @r2_s # 6R +SLT 000000 ...............00000101010 @r +SLTI 001010 .......................... @i +SLTIU 001011 .......................... @i +SLTU 000000 ...............00000101011 @r +SUB 000000 ...............00000100010 @r +SUBU 000000 ...............00000100011 @r + + +DADD 000000 ...............00000101100 @r +DADDI 011000 .......................... @i # 6R +DADDIU 011001 .......................... @i +DADDU 000000 ...............00000101101 @r +DCLO 011100 ...............00000100101 @r # 6Rm +DCLZ 011100 ...............00000100100 @r # 6Rm +DDIV 000000 ..........0000000000011110 @r2_s # 6R +DDIVU 000000 ..........0000000000011111 @r2_s # 6R +DSUB 000000 ...............00000101110 @r +DSUBU 000000 ...............00000101111 @r +DMULT 000000 ..........0000000000011100 @r2_s # 6R +DMULTU 000000 ..........0000000000011101 @r2_s # 6R diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build index 7ee969ec8f..7a27fe93e0 100644 --- a/target/mips/tcg/meson.build +++ b/target/mips/tcg/meson.build @@ -1,4 +1,5 @@ gen = [ + decodetree.process('legacy.decode', extra_args: ['--static-decode=decode_isa_legacy']), decodetree.process('rel6.decode', extra_args: ['--decode=decode_isa_rel6']), decodetree.process('msa.decode', extra_args: '--decode=decode_ase_msa'), decodetree.process('tx79.decode', extra_args: '--static-decode=decode_tx79'), diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index b5d595ef34..bcb267e6bd 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -38,6 +38,9 @@ #include "fpu_helper.h" #include "translate.h" +/* Include the generated ISA decoders */ +#include "decode-legacy.c.inc" + /* * Many sysemu-only helpers are not reachable for user-only. * Define stub generators here, so that we need not either sprinkle @@ -1196,16 +1199,6 @@ enum { MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI, }; -/* - * If an operation is being performed on less than TARGET_LONG_BITS, - * it may require the inputs to be sign- or zero-extended; which will - * depend on the exact operation being performed. - */ -typedef enum { - EXT_NONE, - EXT_SIGN, - EXT_ZERO -} DisasExtend; /* global register indices */ TCGv cpu_gpr[32], cpu_PC; @@ -12261,6 +12254,9 @@ static void gen_sync(int stype) tcg_gen_mb(tcg_mo); } +/* ISA base */ +#include "insn_trans/trans_arith.c.inc" + /* ISA extensions (ASEs) */ /* MIPS16 extension to MIPS32 */ @@ -16090,6 +16086,10 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) return; } + if (decode_isa_legacy(ctx, ctx->opcode)) { + return; + } + if (decode_opc_legacy(env, ctx)) { return; } From patchwork Mon Oct 24 15:23:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 1693969 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=flygoat.com header.i=@flygoat.com header.a=rsa-sha256 header.s=fm1 header.b=VEqgT70G; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=mRO8RsyF; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Mx08425xbz23l5 for ; Tue, 25 Oct 2022 02:57:24 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1omzJF-0003ig-2a; Mon, 24 Oct 2022 11:24:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJC-0003h1-9N for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:10 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJ3-0008GY-Vx for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:10 -0400 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.west.internal (Postfix) with ESMTP id 69DAF320092D; Mon, 24 Oct 2022 11:24:00 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Mon, 24 Oct 2022 11:24:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flygoat.com; h= cc:cc:content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; t=1666625040; x=1666711440; bh=uk kVloUUCbEc+Acs8bLgu4R73ehT7czNXAO7d/GlYBg=; b=VEqgT70GzNXKYp/NGZ MjR3gB4M90cMpfk9qdRieU16zwJ7EaHF4dBDpVee1NEy+gO0OaXFcsOCOkSYkbX7 Pl1FsI21vWFXGLTuQYngNaNznNSzxYD3v53CMi6UbALIaxheu4HX2rKAcrMb/10p dmZmR/ixolVM9S5vqgXB8p/OFeDqLww1fRkUX9ZtpJPKrD0t4jIgc4zvTr75c7Td gCDZKC3Cqm/zCTuax50I2E8NrpGvV92jsYRziK2tRoMBxzigTnGbtnyB/HxcQ+S7 SD/R4pcRIXkUDqrG5d7eS6EfJ3mYDqZsKkJHeJ+qyta9XfLoX+0tPsOqzlwTp5NV IMwA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; t=1666625040; x=1666711440; bh=ukkVloUUCbEc+ Acs8bLgu4R73ehT7czNXAO7d/GlYBg=; b=mRO8RsyFh69s10ueLN4t91O2cvU3/ KlYspDbPJ9YfWkGNvN6vLBKR8RrTQ/8/RBIQgZARFxqp2v4M4lIZ/OGEM01Std9N y6JAyqCq7NRqwnqPgwO0rcfEeexCYT6XalqCSpCP3cqw5xxp+QRG7keOnIDSUncX 0S+oMLCeUYJFhswuI7uhrFs1gD0PJWjKp7Ydpmd04EvV9w9lA//RB995q1GCOMGU yrbBF+JWdsR9Lulg4VZ1pHXEfeis49/5J/MqG9rPoLlmYz08HfBfwHflC67Di9QN 9xdaN90ox1go51y1610ahyJX+5qdew8IyNtmwo+I61pfxqQhNn1IoIzLQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrgedtgedgkeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeflihgrgihunhcujggrnhhguceojhhirgiguhhnrdihrghn ghesfhhlhihgohgrthdrtghomheqnecuggftrfgrthhtvghrnhepfeeludefheegvdeuvd dvgeekgfdvtdettdelieeihfegtedugeekhfdvhfejfedtnecuvehluhhsthgvrhfuihii vgeptdenucfrrghrrghmpehmrghilhhfrhhomhepjhhirgiguhhnrdihrghnghesfhhlhi hgohgrthdrtghomh X-ME-Proxy: Feedback-ID: ifd894703:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 24 Oct 2022 11:23:58 -0400 (EDT) From: Jiaxun Yang To: qemu-devel@nongnu.org Cc: f4bug@amsat.org, richard.henderson@linaro.org, Jiaxun Yang Subject: [PATCH 3/6] tests/tcg/mips: Add mips32 arithmatic instruction test cases Date: Mon, 24 Oct 2022 16:23:46 +0100 Message-Id: <20221024152349.215135-4-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221024152349.215135-1-jiaxun.yang@flygoat.com> References: <20221024152349.215135-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.19; envelope-from=jiaxun.yang@flygoat.com; helo=wout3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Qemu-devel" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Those cases are delivered from MIPS internal architecture validation tools. Signed-off-by: Jiaxun Yang --- tests/tcg/mips/include/test_utils_32.h | 75 +++++++++++ .../tcg/mips/user/isa/mips32/arithmatic/add.c | 99 ++++++++++++++ .../mips/user/isa/mips32/arithmatic/addi.c | 70 ++++++++++ .../mips/user/isa/mips32/arithmatic/addiu.c | 90 +++++++++++++ .../mips/user/isa/mips32/arithmatic/addu.c | 125 ++++++++++++++++++ .../tcg/mips/user/isa/mips32/arithmatic/div.c | 81 ++++++++++++ .../mips/user/isa/mips32/arithmatic/divu.c | 78 +++++++++++ .../mips/user/isa/mips32/arithmatic/madd.c | 79 +++++++++++ .../mips/user/isa/mips32/arithmatic/maddu.c | 78 +++++++++++ .../mips/user/isa/mips32/arithmatic/msub.c | 78 +++++++++++ .../mips/user/isa/mips32/arithmatic/msubu.c | 78 +++++++++++ .../tcg/mips/user/isa/mips32/arithmatic/mul.c | 78 +++++++++++ .../mips/user/isa/mips32/arithmatic/mult.c | 78 +++++++++++ .../mips/user/isa/mips32/arithmatic/multu.c | 78 +++++++++++ .../tcg/mips/user/isa/mips32/arithmatic/slt.c | 61 +++++++++ .../mips/user/isa/mips32/arithmatic/slti.c | 48 +++++++ .../mips/user/isa/mips32/arithmatic/sltiu.c | 48 +++++++ .../mips/user/isa/mips32/arithmatic/sltu.c | 61 +++++++++ .../tcg/mips/user/isa/mips32/arithmatic/sub.c | 104 +++++++++++++++ .../mips/user/isa/mips32/arithmatic/subu.c | 108 +++++++++++++++ 20 files changed, 1595 insertions(+) create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/add.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/addi.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/addiu.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/addu.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/div.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/divu.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/madd.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/maddu.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/msub.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/msubu.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/mul.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/mult.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/multu.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/slt.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/slti.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/sltiu.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/sltu.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/sub.c create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/subu.c diff --git a/tests/tcg/mips/include/test_utils_32.h b/tests/tcg/mips/include/test_utils_32.h index c33990c0c5..00480e3283 100644 --- a/tests/tcg/mips/include/test_utils_32.h +++ b/tests/tcg/mips/include/test_utils_32.h @@ -29,6 +29,81 @@ #define PRINT_RESULTS 0 +#define DO_MIPS32_r(mnemonic, id, input1, input2, expect) \ +{ \ + uint32_t output; \ + uint32_t expect_val = expect; \ + __asm__ volatile ( \ + "li $t1, " #input1 "\n\t" \ + "li $t2, " #input2 "\n\t" \ + #mnemonic " $t0, $t1, $t2\n\t" \ + "sw $t0, 0(%0)\n\t" \ + : \ + : "r" (&output) \ + : "t0", "t1", "t2", "memory" \ + ); \ + check_single_insn_32(id, &pass_count, &fail_count, 1, &expect_val, &output); \ +} + +#define DO_MIPS32_i(mnemonic, id, imm, input1, expect) \ +{ \ + uint32_t output; \ + uint32_t expect_val = expect; \ + __asm__ volatile ( \ + "li $t1, " #input1 "\n\t" \ + #mnemonic " $t0, $t1, " #imm "\n\t" \ + "sw $t0, 0(%0)\n\t" \ + : \ + : "r" (&output) \ + : "t0", "t1", "memory" \ + ); \ + check_single_insn_32(id, &pass_count, &fail_count, 1, &expect_val, &output); \ +} + +#define DO_MIPS32_r2_s(mnemonic, id, hi, lo, input1, input2, expect_hi, expect_lo) \ +{ \ + uint32_t output[2]; \ + uint32_t expect_val[2] = {expect_lo, expect_hi}; \ + __asm__ volatile ( \ + ".set noreorder \n\t" \ + "li $t0, " #hi "\n\t" \ + "mthi $t0 \n\t" \ + "li $t0, " #lo "\n\t" \ + "mtlo $t0 \n\t" \ + "li $t0, " #input1 "\n\t" \ + "li $t1, " #input2 "\n\t" \ + #mnemonic " $t0, $t1 \n\t" \ + "mfhi $t0 \n\t" \ + "sw $t0, 4(%0)\n\t" \ + "mflo $t0 \n\t" \ + "sw $t0, 0(%0)\n\t" \ + ".set reorder \n\t" \ + : \ + : "r" (&output) \ + : "t0", "t1", "hi", "lo", "memory" \ + ); \ + check_single_insn_32(id, &pass_count, &fail_count, 2, expect_val, output); \ +} + +static inline void check_single_insn_32(int id, int *pass, int *fail, int cnt, + uint32_t *expect, uint32_t *actual) +{ + int i; + + if (memcmp(expect, actual, 4 * cnt) == 0) { + (*pass)++; + printf("Case %d pass:\n", id); + for (i = 0; i < cnt; i++) { + printf(" [%d]: actual: 0x%08x, expect: 0x%08x\n", i, actual[i], expect[i]); + } + } else { + (*fail)++; + printf("Case %d fail:\n", id); + for (i = 0; i < cnt; i++) { + printf(" [%d]: actual: 0x%08x, expect: 0x%08x\n", i, actual[i], expect[i]); + } + } +} static inline int32_t check_results_32(const char *instruction_name, const uint32_t test_count, diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/add.c b/tests/tcg/mips/user/isa/mips32/arithmatic/add.c new file mode 100644 index 0000000000..2e1d380c90 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/add.c @@ -0,0 +1,99 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r(add, 0, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r(add, 1, 0x00000001, 0x00000001, 0x00000002); + DO_MIPS32_r(add, 2, 0x00000002, 0x00000003, 0x00000005); + DO_MIPS32_r(add, 3, 0x00000004, 0x00000007, 0x0000000B); + DO_MIPS32_r(add, 4, 0x00000008, 0x0000000F, 0x00000017); + DO_MIPS32_r(add, 5, 0x00000010, 0x0000001F, 0x0000002F); + DO_MIPS32_r(add, 6, 0x00000020, 0x0000003F, 0x0000005F); + DO_MIPS32_r(add, 7, 0x00000040, 0x0000007F, 0x000000BF); + DO_MIPS32_r(add, 8, 0x00000080, 0x000000FF, 0x0000017F); + DO_MIPS32_r(add, 9, 0x00000100, 0x000001FF, 0x000002FF); + DO_MIPS32_r(add, 10, 0x00000200, 0x000003FF, 0x000005FF); + DO_MIPS32_r(add, 11, 0x00000400, 0x000007FF, 0x00000BFF); + DO_MIPS32_r(add, 12, 0x00000800, 0x00000FFF, 0x000017FF); + DO_MIPS32_r(add, 13, 0x00001000, 0x00001FFF, 0x00002FFF); + DO_MIPS32_r(add, 14, 0x00002000, 0x00003FFF, 0x00005FFF); + DO_MIPS32_r(add, 15, 0x00004000, 0x00007FFF, 0x0000BFFF); + DO_MIPS32_r(add, 16, 0x00008000, 0x0000FFFF, 0x00017FFF); + DO_MIPS32_r(add, 17, 0x00010000, 0x0001FFFF, 0x0002FFFF); + DO_MIPS32_r(add, 18, 0x00020000, 0x0003FFFF, 0x0005FFFF); + DO_MIPS32_r(add, 19, 0x00040000, 0x0007FFFF, 0x000BFFFF); + DO_MIPS32_r(add, 20, 0x00080000, 0x000FFFFF, 0x0017FFFF); + DO_MIPS32_r(add, 21, 0x00100000, 0x001FFFFF, 0x002FFFFF); + DO_MIPS32_r(add, 22, 0x00200000, 0x003FFFFF, 0x005FFFFF); + DO_MIPS32_r(add, 23, 0x00400000, 0x007FFFFF, 0x00BFFFFF); + DO_MIPS32_r(add, 24, 0x00800000, 0x00FFFFFF, 0x017FFFFF); + DO_MIPS32_r(add, 25, 0x01000000, 0x01FFFFFF, 0x02FFFFFF); + DO_MIPS32_r(add, 26, 0x02000000, 0x03FFFFFF, 0x05FFFFFF); + DO_MIPS32_r(add, 27, 0x04000000, 0x07FFFFFF, 0x0BFFFFFF); + DO_MIPS32_r(add, 28, 0x08000000, 0x0FFFFFFF, 0x17FFFFFF); + DO_MIPS32_r(add, 29, 0x10000000, 0x1FFFFFFF, 0x2FFFFFFF); + DO_MIPS32_r(add, 30, 0x20000000, 0x3FFFFFFF, 0x5FFFFFFF); + DO_MIPS32_r(add, 31, 0x00000000, 0x00000001, 0x00000001); + DO_MIPS32_r(add, 32, 0x80000001, 0xFFFFFFFF, 0x80000000); + DO_MIPS32_r(add, 33, 0xC0000003, 0x7FFFFFFD, 0x40000000); + DO_MIPS32_r(add, 34, 0xE0000007, 0x3FFFFFF9, 0x20000000); + DO_MIPS32_r(add, 35, 0xF000000F, 0x1FFFFFF1, 0x10000000); + DO_MIPS32_r(add, 36, 0xF800001F, 0x0FFFFFE1, 0x08000000); + DO_MIPS32_r(add, 37, 0xFC00003F, 0x07FFFFC1, 0x04000000); + DO_MIPS32_r(add, 38, 0xFE00007F, 0x03FFFF81, 0x02000000); + DO_MIPS32_r(add, 39, 0xFF0000FF, 0x01FFFF01, 0x01000000); + DO_MIPS32_r(add, 40, 0xFF8001FF, 0x00FFFE01, 0x00800000); + DO_MIPS32_r(add, 41, 0xFFC003FF, 0x007FFC01, 0x00400000); + DO_MIPS32_r(add, 42, 0xFFE007FF, 0x003FF801, 0x00200000); + DO_MIPS32_r(add, 43, 0xFFF00FFF, 0x001FF001, 0x00100000); + DO_MIPS32_r(add, 44, 0xFFF81FFF, 0x000FE001, 0x00080000); + DO_MIPS32_r(add, 45, 0xFFFC3FFF, 0x0007C001, 0x00040000); + DO_MIPS32_r(add, 46, 0xFFFE7FFF, 0x00038001, 0x00020000); + DO_MIPS32_r(add, 47, 0xFFFFFFFF, 0x00010001, 0x00010000); + DO_MIPS32_r(add, 48, 0xFFFFFFFF, 0x00018001, 0x00018000); + DO_MIPS32_r(add, 49, 0xFFFE7FFF, 0x00024001, 0x0000C000); + DO_MIPS32_r(add, 50, 0xFFFC3FFF, 0x00042001, 0x00006000); + DO_MIPS32_r(add, 51, 0xFFF81FFF, 0x00081001, 0x00003000); + DO_MIPS32_r(add, 52, 0xFFF00FFF, 0x00100801, 0x00001800); + DO_MIPS32_r(add, 53, 0xFFE007FF, 0x00200401, 0x00000C00); + DO_MIPS32_r(add, 54, 0xFFC003FF, 0x00400201, 0x00000600); + DO_MIPS32_r(add, 55, 0xFF8001FF, 0x00800101, 0x00000300); + DO_MIPS32_r(add, 56, 0xFF0000FF, 0x01000081, 0x00000180); + DO_MIPS32_r(add, 57, 0xFE00007F, 0x02000041, 0x000000C0); + DO_MIPS32_r(add, 58, 0xFC00003F, 0x04000021, 0x00000060); + DO_MIPS32_r(add, 59, 0xF800001F, 0x08000011, 0x00000030); + DO_MIPS32_r(add, 60, 0xF000000F, 0x10000009, 0x00000018); + DO_MIPS32_r(add, 61, 0xE0000007, 0x20000005, 0x0000000C); + DO_MIPS32_r(add, 62, 0xC0000003, 0x40000003, 0x00000006); + DO_MIPS32_r(add, 63, 0x00000000, 0x55555555, 0x55555555); + DO_MIPS32_r(add, 64, 0x15555555, 0x55555555, 0x6AAAAAAA); + DO_MIPS32_r(add, 65, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF); + DO_MIPS32_r(add, 66, 0xFFFFFFFF, 0x55555555, 0x55555554); + DO_MIPS32_r(add, 67, 0xAAAAAAAA, 0x00000000, 0xAAAAAAAA); + DO_MIPS32_r(add, 68, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF); + DO_MIPS32_r(add, 69, 0xAAAAAAAA, 0x2AAAAAAA, 0xD5555554); + DO_MIPS32_r(add, 70, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAA9); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/addi.c b/tests/tcg/mips/user/isa/mips32/arithmatic/addi.c new file mode 100644 index 0000000000..c032e4d9e5 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/addi.c @@ -0,0 +1,70 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_i(addi, 0, 0x0000, 0x00000000, 0x00000000); + DO_MIPS32_i(addi, 1, 0x0001, 0x00000001, 0x00000002); + DO_MIPS32_i(addi, 2, 0x0003, 0x00000002, 0x00000005); + DO_MIPS32_i(addi, 3, 0x0007, 0x00000004, 0x0000000B); + DO_MIPS32_i(addi, 4, 0x000F, 0x00000008, 0x00000017); + DO_MIPS32_i(addi, 5, 0x001F, 0x00000010, 0x0000002F); + DO_MIPS32_i(addi, 6, 0x003F, 0x00000020, 0x0000005F); + DO_MIPS32_i(addi, 7, 0x007F, 0x00000040, 0x000000BF); + DO_MIPS32_i(addi, 8, 0x00FF, 0x00000080, 0x0000017F); + DO_MIPS32_i(addi, 9, 0x01FF, 0x00000100, 0x000002FF); + DO_MIPS32_i(addi, 10, 0x03FF, 0x00000200, 0x000005FF); + DO_MIPS32_i(addi, 11, 0x07FF, 0x00000400, 0x00000BFF); + DO_MIPS32_i(addi, 12, 0x0FFF, 0x00000800, 0x000017FF); + DO_MIPS32_i(addi, 13, 0x1FFF, 0x00001000, 0x00002FFF); + DO_MIPS32_i(addi, 14, 0x3FFF, 0x00002000, 0x00005FFF); + DO_MIPS32_i(addi, 15, 0x7FFF, 0x00004000, 0x0000BFFF); + DO_MIPS32_i(addi, 16, 0xFFFF, 0x00008000, 0x00007FFF); + DO_MIPS32_i(addi, 17, 0x0001, 0x00000000, 0x00000001); + DO_MIPS32_i(addi, 18, 0xFFFF, 0x80000001, 0x80000000); + DO_MIPS32_i(addi, 19, 0xFFFD, 0xC0000003, 0xC0000000); + DO_MIPS32_i(addi, 20, 0xFFF9, 0xE0000007, 0xE0000000); + DO_MIPS32_i(addi, 21, 0xFFF1, 0xF000000F, 0xF0000000); + DO_MIPS32_i(addi, 22, 0xFFE1, 0xF800001F, 0xF8000000); + DO_MIPS32_i(addi, 23, 0xFFC1, 0xFC00003F, 0xFC000000); + DO_MIPS32_i(addi, 24, 0xFF81, 0xFE00007F, 0xFE000000); + DO_MIPS32_i(addi, 25, 0xFF01, 0xFF0000FF, 0xFF000000); + DO_MIPS32_i(addi, 26, 0xFE01, 0xFF8001FF, 0xFF800000); + DO_MIPS32_i(addi, 27, 0xFC01, 0xFFC003FF, 0xFFC00000); + DO_MIPS32_i(addi, 28, 0xF801, 0xFFE007FF, 0xFFE00000); + DO_MIPS32_i(addi, 29, 0xF001, 0xFFF00FFF, 0xFFF00000); + DO_MIPS32_i(addi, 30, 0xE001, 0xFFF81FFF, 0xFFF80000); + DO_MIPS32_i(addi, 31, 0xC001, 0xFFFC3FFF, 0xFFFC0000); + DO_MIPS32_i(addi, 32, 0x8001, 0xFFFE7FFF, 0xFFFE0000); + DO_MIPS32_i(addi, 33, 0x0001, 0xFFFFFFFF, 0x00000000); + DO_MIPS32_i(addi, 34, 0x5555, 0x00000000, 0x00005555); + DO_MIPS32_i(addi, 35, 0x5555, 0x55555555, 0x5555AAAA); + DO_MIPS32_i(addi, 36, 0x5555, 0xAAAAAAAA, 0xAAAAFFFF); + DO_MIPS32_i(addi, 37, 0x5555, 0xFFFFFFFF, 0x00005554); + DO_MIPS32_i(addi, 38, 0x0000, 0xAAAAAAAA, 0xAAAAAAAA); + DO_MIPS32_i(addi, 39, 0x5555, 0xAAAAAAAA, 0xAAAAFFFF); + DO_MIPS32_i(addi, 40, 0xAAAA, 0xAAAAAAAA, 0xAAAA5554); + DO_MIPS32_i(addi, 41, 0xFFFF, 0xAAAAAAAA, 0xAAAAAAA9); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/addiu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/addiu.c new file mode 100644 index 0000000000..cdc2ebc932 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/addiu.c @@ -0,0 +1,90 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_i(addiu, 0, 0x0000, 0x00000000, 0x00000000); + DO_MIPS32_i(addiu, 1, 0x0001, 0x00000001, 0x00000002); + DO_MIPS32_i(addiu, 2, 0x0003, 0x00000002, 0x00000005); + DO_MIPS32_i(addiu, 3, 0x0007, 0x00000004, 0x0000000B); + DO_MIPS32_i(addiu, 4, 0x000F, 0x00000008, 0x00000017); + DO_MIPS32_i(addiu, 5, 0x001F, 0x00000010, 0x0000002F); + DO_MIPS32_i(addiu, 6, 0x003F, 0x00000020, 0x0000005F); + DO_MIPS32_i(addiu, 7, 0x007F, 0x00000040, 0x000000BF); + DO_MIPS32_i(addiu, 8, 0x00FF, 0x00000080, 0x0000017F); + DO_MIPS32_i(addiu, 9, 0x01FF, 0x00000100, 0x000002FF); + DO_MIPS32_i(addiu, 10, 0x03FF, 0x00000200, 0x000005FF); + DO_MIPS32_i(addiu, 11, 0x07FF, 0x00000400, 0x00000BFF); + DO_MIPS32_i(addiu, 12, 0x0FFF, 0x00000800, 0x000017FF); + DO_MIPS32_i(addiu, 13, 0x1FFF, 0x00001000, 0x00002FFF); + DO_MIPS32_i(addiu, 14, 0x3FFF, 0x00002000, 0x00005FFF); + DO_MIPS32_i(addiu, 15, 0x7FFF, 0x00004000, 0x0000BFFF); + DO_MIPS32_i(addiu, 16, -1, 0x00008000, 0x00007FFF); + DO_MIPS32_i(addiu, 17, 0x0001, 0x00000000, 0x00000001); + DO_MIPS32_i(addiu, 18, -1, 0x80000001, 0x80000000); + DO_MIPS32_i(addiu, 19, -3, 0xC0000003, 0xC0000000); + DO_MIPS32_i(addiu, 20, -7, 0xE0000007, 0xE0000000); + DO_MIPS32_i(addiu, 21, -15, 0xF000000F, 0xF0000000); + DO_MIPS32_i(addiu, 22, -31, 0xF800001F, 0xF8000000); + DO_MIPS32_i(addiu, 23, -63, 0xFC00003F, 0xFC000000); + DO_MIPS32_i(addiu, 24, -127, 0xFE00007F, 0xFE000000); + DO_MIPS32_i(addiu, 25, -255, 0xFF0000FF, 0xFF000000); + DO_MIPS32_i(addiu, 26, -511, 0xFF8001FF, 0xFF800000); + DO_MIPS32_i(addiu, 27, -1023, 0xFFC003FF, 0xFFC00000); + DO_MIPS32_i(addiu, 28, -2047, 0xFFE007FF, 0xFFE00000); + DO_MIPS32_i(addiu, 29, -4095, 0xFFF00FFF, 0xFFF00000); + DO_MIPS32_i(addiu, 30, -8191, 0xFFF81FFF, 0xFFF80000); + DO_MIPS32_i(addiu, 31, 0xC001, 0xFFFC3FFF, 0xFFFC0000); + DO_MIPS32_i(addiu, 32, 0x8001, 0xFFFE7FFF, 0xFFFE0000); + DO_MIPS32_i(addiu, 33, 0x0001, 0xFFFFFFFF, 0x00000000); + DO_MIPS32_i(addiu, 34, 0x5555, 0x00000000, 0x00005555); + DO_MIPS32_i(addiu, 35, 0x5555, 0x55555555, 0x5555AAAA); + DO_MIPS32_i(addiu, 36, 0x5555, 0xAAAAAAAA, 0xAAAAFFFF); + DO_MIPS32_i(addiu, 37, 0x5555, 0xFFFFFFFF, 0x00005554); + DO_MIPS32_i(addiu, 38, 0x0000, 0xAAAAAAAA, 0xAAAAAAAA); + DO_MIPS32_i(addiu, 39, 0x5555, 0xAAAAAAAA, 0xAAAAFFFF); + DO_MIPS32_i(addiu, 40, 0xAAAA, 0xAAAAAAAA, 0xAAAA5554); + DO_MIPS32_i(addiu, 41, -1, 0xAAAAAAAA, 0xAAAAAAA9); + DO_MIPS32_i(addiu, 42, 0x0001, 0x7FFFFFFF, 0x80000000); + DO_MIPS32_i(addiu, 43, 0x7FFF, 0x7FFFFFFF, 0x80007FFE); + DO_MIPS32_i(addiu, 44, -1, 0x80000000, 0x7FFFFFFF); + DO_MIPS32_i(addiu, 45, 0x8000, 0x80000000, 0x7FFF8000); + DO_MIPS32_i(addiu, 46, 0x555F, 0x7FFFAAAA, 0x80000009); + DO_MIPS32_i(addiu, 47, 0xAAAA, 0x7FFF5555, 0x7FFEFFFF); + DO_MIPS32_i(addiu, 48, 0x0002, 0x7FFFFFFF, 0x80000001); + DO_MIPS32_i(addiu, 49, 0x0004, 0x7FFFFFFF, 0x80000003); + DO_MIPS32_i(addiu, 50, 0x0008, 0x7FFFFFFF, 0x80000007); + DO_MIPS32_i(addiu, 51, 0x0010, 0x7FFFFFFF, 0x8000000F); + DO_MIPS32_i(addiu, 52, 0x0020, 0x7FFFFFFF, 0x8000001F); + DO_MIPS32_i(addiu, 53, 0x0040, 0x7FFFFFFF, 0x8000003F); + DO_MIPS32_i(addiu, 54, 0x0080, 0x7FFFFFFF, 0x8000007F); + DO_MIPS32_i(addiu, 55, 0x0100, 0x7FFFFFFF, 0x800000FF); + DO_MIPS32_i(addiu, 56, 0x0200, 0x7FFFFFFF, 0x800001FF); + DO_MIPS32_i(addiu, 57, 0x0400, 0x7FFFFFFF, 0x800003FF); + DO_MIPS32_i(addiu, 58, 0x0800, 0x7FFFFFFF, 0x800007FF); + DO_MIPS32_i(addiu, 59, 0x1000, 0x7FFFFFFF, 0x80000FFF); + DO_MIPS32_i(addiu, 60, 0x2000, 0x7FFFFFFF, 0x80001FFF); + DO_MIPS32_i(addiu, 61, 0x4000, 0x7FFFFFFF, 0x80003FFF); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/addu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/addu.c new file mode 100644 index 0000000000..062999edd6 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/addu.c @@ -0,0 +1,125 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r(addu, 0, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r(addu, 1, 0x00000001, 0x00000001, 0x00000002); + DO_MIPS32_r(addu, 2, 0x00000002, 0x00000003, 0x00000005); + DO_MIPS32_r(addu, 3, 0x00000004, 0x00000007, 0x0000000B); + DO_MIPS32_r(addu, 4, 0x00000008, 0x0000000F, 0x00000017); + DO_MIPS32_r(addu, 5, 0x00000010, 0x0000001F, 0x0000002F); + DO_MIPS32_r(addu, 6, 0x00000020, 0x0000003F, 0x0000005F); + DO_MIPS32_r(addu, 7, 0x00000040, 0x0000007F, 0x000000BF); + DO_MIPS32_r(addu, 8, 0x00000080, 0x000000FF, 0x0000017F); + DO_MIPS32_r(addu, 9, 0x00000100, 0x000001FF, 0x000002FF); + DO_MIPS32_r(addu, 10, 0x00000200, 0x000003FF, 0x000005FF); + DO_MIPS32_r(addu, 11, 0x00000400, 0x000007FF, 0x00000BFF); + DO_MIPS32_r(addu, 12, 0x00000800, 0x00000FFF, 0x000017FF); + DO_MIPS32_r(addu, 13, 0x00001000, 0x00001FFF, 0x00002FFF); + DO_MIPS32_r(addu, 14, 0x00002000, 0x00003FFF, 0x00005FFF); + DO_MIPS32_r(addu, 15, 0x00004000, 0x00007FFF, 0x0000BFFF); + DO_MIPS32_r(addu, 16, 0x00008000, 0x0000FFFF, 0x00017FFF); + DO_MIPS32_r(addu, 17, 0x00010000, 0x0001FFFF, 0x0002FFFF); + DO_MIPS32_r(addu, 18, 0x00020000, 0x0003FFFF, 0x0005FFFF); + DO_MIPS32_r(addu, 19, 0x00040000, 0x0007FFFF, 0x000BFFFF); + DO_MIPS32_r(addu, 20, 0x00080000, 0x000FFFFF, 0x0017FFFF); + DO_MIPS32_r(addu, 21, 0x00100000, 0x001FFFFF, 0x002FFFFF); + DO_MIPS32_r(addu, 22, 0x00200000, 0x003FFFFF, 0x005FFFFF); + DO_MIPS32_r(addu, 23, 0x00400000, 0x007FFFFF, 0x00BFFFFF); + DO_MIPS32_r(addu, 24, 0x00800000, 0x00FFFFFF, 0x017FFFFF); + DO_MIPS32_r(addu, 25, 0x01000000, 0x01FFFFFF, 0x02FFFFFF); + DO_MIPS32_r(addu, 26, 0x02000000, 0x03FFFFFF, 0x05FFFFFF); + DO_MIPS32_r(addu, 27, 0x04000000, 0x07FFFFFF, 0x0BFFFFFF); + DO_MIPS32_r(addu, 28, 0x08000000, 0x0FFFFFFF, 0x17FFFFFF); + DO_MIPS32_r(addu, 29, 0x10000000, 0x1FFFFFFF, 0x2FFFFFFF); + DO_MIPS32_r(addu, 30, 0x20000000, 0x3FFFFFFF, 0x5FFFFFFF); + DO_MIPS32_r(addu, 31, 0x40000000, 0x7FFFFFFF, 0xBFFFFFFF); + DO_MIPS32_r(addu, 32, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF); + DO_MIPS32_r(addu, 33, 0x00000000, 0x00000001, 0x00000001); + DO_MIPS32_r(addu, 34, 0x80000001, 0xFFFFFFFF, 0x80000000); + DO_MIPS32_r(addu, 35, 0xC0000003, 0x7FFFFFFD, 0x40000000); + DO_MIPS32_r(addu, 36, 0xE0000007, 0x3FFFFFF9, 0x20000000); + DO_MIPS32_r(addu, 37, 0xF000000F, 0x1FFFFFF1, 0x10000000); + DO_MIPS32_r(addu, 38, 0xF800001F, 0x0FFFFFE1, 0x08000000); + DO_MIPS32_r(addu, 39, 0xFC00003F, 0x07FFFFC1, 0x04000000); + DO_MIPS32_r(addu, 40, 0xFE00007F, 0x03FFFF81, 0x02000000); + DO_MIPS32_r(addu, 41, 0xFF0000FF, 0x01FFFF01, 0x01000000); + DO_MIPS32_r(addu, 42, 0xFF8001FF, 0x00FFFE01, 0x00800000); + DO_MIPS32_r(addu, 43, 0xFFC003FF, 0x007FFC01, 0x00400000); + DO_MIPS32_r(addu, 44, 0xFFE007FF, 0x003FF801, 0x00200000); + DO_MIPS32_r(addu, 45, 0xFFF00FFF, 0x001FF001, 0x00100000); + DO_MIPS32_r(addu, 46, 0xFFF81FFF, 0x000FE001, 0x00080000); + DO_MIPS32_r(addu, 47, 0xFFFC3FFF, 0x0007C001, 0x00040000); + DO_MIPS32_r(addu, 48, 0xFFFE7FFF, 0x00038001, 0x00020000); + DO_MIPS32_r(addu, 49, 0xFFFFFFFF, 0x00010001, 0x00010000); + DO_MIPS32_r(addu, 50, 0xFFFFFFFF, 0x00018001, 0x00018000); + DO_MIPS32_r(addu, 51, 0xFFFE7FFF, 0x00024001, 0x0000C000); + DO_MIPS32_r(addu, 52, 0xFFFC3FFF, 0x00042001, 0x00006000); + DO_MIPS32_r(addu, 53, 0xFFF81FFF, 0x00081001, 0x00003000); + DO_MIPS32_r(addu, 54, 0xFFF00FFF, 0x00100801, 0x00001800); + DO_MIPS32_r(addu, 55, 0xFFE007FF, 0x00200401, 0x00000C00); + DO_MIPS32_r(addu, 56, 0xFFC003FF, 0x00400201, 0x00000600); + DO_MIPS32_r(addu, 57, 0xFF8001FF, 0x00800101, 0x00000300); + DO_MIPS32_r(addu, 58, 0xFF0000FF, 0x01000081, 0x00000180); + DO_MIPS32_r(addu, 59, 0xFE00007F, 0x02000041, 0x000000C0); + DO_MIPS32_r(addu, 60, 0xFC00003F, 0x04000021, 0x00000060); + DO_MIPS32_r(addu, 61, 0xF800001F, 0x08000011, 0x00000030); + DO_MIPS32_r(addu, 62, 0xF000000F, 0x10000009, 0x00000018); + DO_MIPS32_r(addu, 63, 0xE0000007, 0x20000005, 0x0000000C); + DO_MIPS32_r(addu, 64, 0xC0000003, 0x40000003, 0x00000006); + DO_MIPS32_r(addu, 65, 0x80000001, 0x80000001, 0x00000002); + DO_MIPS32_r(addu, 66, 0x00000000, 0x55555555, 0x55555555); + DO_MIPS32_r(addu, 67, 0x15555555, 0x55555555, 0x6AAAAAAA); + DO_MIPS32_r(addu, 68, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF); + DO_MIPS32_r(addu, 69, 0xFFFFFFFF, 0x55555555, 0x55555554); + DO_MIPS32_r(addu, 70, 0xAAAAAAAA, 0x00000000, 0xAAAAAAAA); + DO_MIPS32_r(addu, 71, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF); + DO_MIPS32_r(addu, 72, 0xAAAAAAAA, 0x2AAAAAAA, 0xD5555554); + DO_MIPS32_r(addu, 73, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAA9); + DO_MIPS32_r(addu, 74, 0x7FFFFFFF, 0x00000001, 0x80000000); + DO_MIPS32_r(addu, 75, 0x7FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFE); + DO_MIPS32_r(addu, 76, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF); + DO_MIPS32_r(addu, 77, 0x80000000, 0x80000000, 0x00000000); + DO_MIPS32_r(addu, 78, 0x7FFFFFFF, 0x00000001, 0x80000000); + DO_MIPS32_r(addu, 79, 0x7FFFFFFF, 0x00007FFF, 0x80007FFE); + DO_MIPS32_r(addu, 80, 0x80000000, 0x0000FFFF, 0x8000FFFF); + DO_MIPS32_r(addu, 81, 0x80000000, 0x00008000, 0x80008000); + DO_MIPS32_r(addu, 82, 0x7FFFAAAA, 0x0000555F, 0x80000009); + DO_MIPS32_r(addu, 83, 0x7FFF5555, 0x0000AAAA, 0x7FFFFFFF); + DO_MIPS32_r(addu, 84, 0x7FFFFFFF, 0x00000002, 0x80000001); + DO_MIPS32_r(addu, 85, 0x7FFFFFFF, 0x00000004, 0x80000003); + DO_MIPS32_r(addu, 86, 0x7FFFFFFF, 0x00000008, 0x80000007); + DO_MIPS32_r(addu, 87, 0x7FFFFFFF, 0x00000010, 0x8000000F); + DO_MIPS32_r(addu, 88, 0x7FFFFFFF, 0x00000020, 0x8000001F); + DO_MIPS32_r(addu, 89, 0x7FFFFFFF, 0x00000040, 0x8000003F); + DO_MIPS32_r(addu, 90, 0x7FFFFFFF, 0x00000080, 0x8000007F); + DO_MIPS32_r(addu, 91, 0x7FFFFFFF, 0x00000100, 0x800000FF); + DO_MIPS32_r(addu, 92, 0x7FFFFFFF, 0x00000200, 0x800001FF); + DO_MIPS32_r(addu, 93, 0x7FFFFFFF, 0x00000400, 0x800003FF); + DO_MIPS32_r(addu, 94, 0x7FFFFFFF, 0x00000800, 0x800007FF); + DO_MIPS32_r(addu, 95, 0x7FFFFFFF, 0x00001000, 0x80000FFF); + DO_MIPS32_r(addu, 96, 0x7FFFFFFF, 0x00002000, 0x80001FFF); + DO_MIPS32_r(addu, 97, 0x7FFFFFFF, 0x00004000, 0x80003FFF); + DO_MIPS32_r(addu, 98, 0x7FFFFFFF, 0x00001000, 0x80003FFF); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/div.c b/tests/tcg/mips/user/isa/mips32/arithmatic/div.c new file mode 100644 index 0000000000..5eafca326e --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/div.c @@ -0,0 +1,81 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r2_s(div, 0, 0, 0, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(div, 1, 0, 0, 0x80000001, 0x00000001, 0x00000000, 0x80000001); + DO_MIPS32_r2_s(div, 2, 0, 0, 0x40000002, 0x00000003, 0x00000000, 0x15555556); + DO_MIPS32_r2_s(div, 3, 0, 0, 0x20000004, 0x00000007, 0x00000001, 0x04924925); + DO_MIPS32_r2_s(div, 4, 0, 0, 0x10000008, 0x0000000F, 0x00000009, 0x01111111); + DO_MIPS32_r2_s(div, 5, 0, 0, 0x88000010, 0x0000001F, 0xFFFFFFF3, 0xFC210843); + DO_MIPS32_r2_s(div, 6, 0, 0, 0x44000020, 0x0000003F, 0x00000025, 0x01145145); + DO_MIPS32_r2_s(div, 7, 0, 0, 0x22000040, 0x0000007F, 0x00000052, 0x00448912); + DO_MIPS32_r2_s(div, 8, 0, 0, 0x11000080, 0x000000FF, 0x00000091, 0x00111111); + DO_MIPS32_r2_s(div, 9, 0, 0, 0x80800100, 0x000001FF, 0xFFFFFF11, 0xFFC02011); + DO_MIPS32_r2_s(div, 10, 0, 0, 0x40400200, 0x000003FF, 0x00000205, 0x00101405); + DO_MIPS32_r2_s(div, 11, 0, 0, 0x20200400, 0x000007FF, 0x00000081, 0x00040481); + DO_MIPS32_r2_s(div, 12, 0, 0, 0x10100800, 0x00000FFF, 0x00000910, 0x00010110); + DO_MIPS32_r2_s(div, 13, 0, 0, 0x80081000, 0x00001FFF, 0xFFFFF021, 0xFFFC0021); + DO_MIPS32_r2_s(div, 14, 0, 0, 0x40042000, 0x00003FFF, 0x00002014, 0x00010014); + DO_MIPS32_r2_s(div, 15, 0, 0, 0x20024000, 0x00007FFF, 0x00000005, 0x00004005); + DO_MIPS32_r2_s(div, 16, 0, 0, 0x10018000, 0x0000FFFF, 0x00009001, 0x00001001); + DO_MIPS32_r2_s(div, 17, 0, 0, 0x80018000, 0x0001FFFF, 0xFFFF4001, 0xFFFFC001); + DO_MIPS32_r2_s(div, 18, 0, 0, 0x40024000, 0x0003FFFF, 0x00025000, 0x00001000); + DO_MIPS32_r2_s(div, 19, 0, 0, 0x20042000, 0x0007FFFF, 0x00042400, 0x00000400); + DO_MIPS32_r2_s(div, 20, 0, 0, 0x10081000, 0x000FFFFF, 0x00081100, 0x00000100); + DO_MIPS32_r2_s(div, 21, 0, 0, 0x80100800, 0x001FFFFF, 0xFFF00401, 0xFFFFFC01); + DO_MIPS32_r2_s(div, 22, 0, 0, 0x40200400, 0x003FFFFF, 0x00200500, 0x00000100); + DO_MIPS32_r2_s(div, 23, 0, 0, 0x20400200, 0x007FFFFF, 0x00400240, 0x00000040); + DO_MIPS32_r2_s(div, 24, 0, 0, 0x10800100, 0x00FFFFFF, 0x00800110, 0x00000010); + DO_MIPS32_r2_s(div, 25, 0, 0, 0x81000080, 0x01FFFFFF, 0xFF000041, 0xFFFFFFC1); + DO_MIPS32_r2_s(div, 26, 0, 0, 0x42000040, 0x03FFFFFF, 0x02000050, 0x00000010); + DO_MIPS32_r2_s(div, 27, 0, 0, 0x24000020, 0x07FFFFFF, 0x04000024, 0x00000004); + DO_MIPS32_r2_s(div, 28, 0, 0, 0x18000010, 0x0FFFFFFF, 0x08000011, 0x00000001); + DO_MIPS32_r2_s(div, 29, 0, 0, 0x90000008, 0x1FFFFFFF, 0xF0000005, 0xFFFFFFFD); + DO_MIPS32_r2_s(div, 30, 0, 0, 0x60000004, 0x3FFFFFFF, 0x20000005, 0x00000001); + DO_MIPS32_r2_s(div, 31, 0, 0, 0x60000002, 0x7FFFFFFF, 0x60000002, 0x00000000); + DO_MIPS32_r2_s(div, 32, 0, 0, 0x90000001, 0xFFFFFFFF, 0x00000000, 0x6FFFFFFF); + DO_MIPS32_r2_s(div, 33, 0, 0, 0x00000000, 0x55555555, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(div, 34, 0, 0, 0x55555555, 0x55555555, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(div, 35, 0, 0, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF, 0xFFFFFFFF); + DO_MIPS32_r2_s(div, 36, 0, 0, 0xFFFFFFFF, 0x55555555, 0xFFFFFFFF, 0x00000000); + DO_MIPS32_r2_s(div, 37, 0, 0, 0xAAAAAAAA, 0x00000001, 0x00000000, 0xAAAAAAAA); + DO_MIPS32_r2_s(div, 38, 0, 0, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF, 0xFFFFFFFF); + DO_MIPS32_r2_s(div, 39, 0, 0, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(div, 40, 0, 0, 0xAAAAAAAA, 0xFFFFFFFF, 0x00000000, 0x55555556); + DO_MIPS32_r2_s(div, 41, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(div, 42, 0, 0, 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF, 0x00000000); + DO_MIPS32_r2_s(div, 43, 0, 0, 0x7FFFFFFF, 0xFFFFFFFF, 0x00000000, 0x80000001); + DO_MIPS32_r2_s(div, 44, 0, 0, 0x80000000, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); + DO_MIPS32_r2_s(div, 45, 0, 0, 0x80000000, 0x80000000, 0x00000000, 0x00000001); +#if 0 + /* Disabled until we find a way to disable assembler trap */ + DO_MIPS32_r2_s(div, 46, 0, 0, 0x80000000, 0xFFFFFFFF, 0x00000000, 0x80000000); +#endif + DO_MIPS32_r2_s(div, 47, 0, 0, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0x00000000); + DO_MIPS32_r2_s(div, 48, 0, 0, 0xFFFFFFFF, 0x80000000, 0xFFFFFFFF, 0x00000000); + DO_MIPS32_r2_s(div, 49, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000001); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/divu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/divu.c new file mode 100644 index 0000000000..172e8af693 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/divu.c @@ -0,0 +1,78 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r2_s(divu, 0, 0, 0, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(divu, 1, 0, 0, 0x80000001, 0x00000001, 0x00000000, 0x80000001); + DO_MIPS32_r2_s(divu, 2, 0, 0, 0x40000002, 0x00000003, 0x00000000, 0x15555556); + DO_MIPS32_r2_s(divu, 3, 0, 0, 0x20000004, 0x00000007, 0x00000001, 0x04924925); + DO_MIPS32_r2_s(divu, 4, 0, 0, 0x10000008, 0x0000000F, 0x00000009, 0x01111111); + DO_MIPS32_r2_s(divu, 5, 0, 0, 0x88000010, 0x0000001F, 0x00000016, 0x046318C6); + DO_MIPS32_r2_s(divu, 6, 0, 0, 0x44000020, 0x0000003F, 0x00000025, 0x01145145); + DO_MIPS32_r2_s(divu, 7, 0, 0, 0x22000040, 0x0000007F, 0x00000052, 0x00448912); + DO_MIPS32_r2_s(divu, 8, 0, 0, 0x11000080, 0x000000FF, 0x00000091, 0x00111111); + DO_MIPS32_r2_s(divu, 9, 0, 0, 0x80800100, 0x000001FF, 0x00000130, 0x00406030); + DO_MIPS32_r2_s(divu, 10, 0, 0, 0x40400200, 0x000003FF, 0x00000205, 0x00101405); + DO_MIPS32_r2_s(divu, 11, 0, 0, 0x20200400, 0x000007FF, 0x00000081, 0x00040481); + DO_MIPS32_r2_s(divu, 12, 0, 0, 0x10100800, 0x00000FFF, 0x00000910, 0x00010110); + DO_MIPS32_r2_s(divu, 13, 0, 0, 0x80081000, 0x00001FFF, 0x00001060, 0x00040060); + DO_MIPS32_r2_s(divu, 14, 0, 0, 0x40042000, 0x00003FFF, 0x00002014, 0x00010014); + DO_MIPS32_r2_s(divu, 15, 0, 0, 0x20024000, 0x00007FFF, 0x00000005, 0x00004005); + DO_MIPS32_r2_s(divu, 16, 0, 0, 0x10018000, 0x0000FFFF, 0x00009001, 0x00001001); + DO_MIPS32_r2_s(divu, 17, 0, 0, 0x80018000, 0x0001FFFF, 0x0001C000, 0x00004000); + DO_MIPS32_r2_s(divu, 18, 0, 0, 0x40024000, 0x0003FFFF, 0x00025000, 0x00001000); + DO_MIPS32_r2_s(divu, 19, 0, 0, 0x20042000, 0x0007FFFF, 0x00042400, 0x00000400); + DO_MIPS32_r2_s(divu, 20, 0, 0, 0x10081000, 0x000FFFFF, 0x00081100, 0x00000100); + DO_MIPS32_r2_s(divu, 21, 0, 0, 0x80100800, 0x001FFFFF, 0x00100C00, 0x00000400); + DO_MIPS32_r2_s(divu, 22, 0, 0, 0x40200400, 0x003FFFFF, 0x00200500, 0x00000100); + DO_MIPS32_r2_s(divu, 23, 0, 0, 0x20400200, 0x007FFFFF, 0x00400240, 0x00000040); + DO_MIPS32_r2_s(divu, 24, 0, 0, 0x10800100, 0x00FFFFFF, 0x00800110, 0x00000010); + DO_MIPS32_r2_s(divu, 25, 0, 0, 0x81000080, 0x01FFFFFF, 0x010000C0, 0x00000040); + DO_MIPS32_r2_s(divu, 26, 0, 0, 0x42000040, 0x03FFFFFF, 0x02000050, 0x00000010); + DO_MIPS32_r2_s(divu, 27, 0, 0, 0x24000020, 0x07FFFFFF, 0x04000024, 0x00000004); + DO_MIPS32_r2_s(divu, 28, 0, 0, 0x18000010, 0x0FFFFFFF, 0x08000011, 0x00000001); + DO_MIPS32_r2_s(divu, 29, 0, 0, 0x90000008, 0x1FFFFFFF, 0x1000000C, 0x00000004); + DO_MIPS32_r2_s(divu, 30, 0, 0, 0x60000004, 0x3FFFFFFF, 0x20000005, 0x00000001); + DO_MIPS32_r2_s(divu, 31, 0, 0, 0x60000002, 0x7FFFFFFF, 0x60000002, 0x00000000); + DO_MIPS32_r2_s(divu, 32, 0, 0, 0x90000001, 0xFFFFFFFF, 0x90000001, 0x00000000); + DO_MIPS32_r2_s(divu, 33, 0, 0, 0x00000000, 0x55555555, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(divu, 34, 0, 0, 0x55555555, 0x55555555, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(divu, 35, 0, 0, 0xAAAAAAAA, 0x55555555, 0x00000000, 0x00000002); + DO_MIPS32_r2_s(divu, 36, 0, 0, 0xFFFFFFFF, 0x55555555, 0x00000000, 0x00000003); + DO_MIPS32_r2_s(divu, 37, 0, 0, 0xAAAAAAAA, 0x00000001, 0x00000000, 0xAAAAAAAA); + DO_MIPS32_r2_s(divu, 38, 0, 0, 0xAAAAAAAA, 0x55555555, 0x00000000, 0x00000002); + DO_MIPS32_r2_s(divu, 39, 0, 0, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(divu, 40, 0, 0, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0x00000000); + DO_MIPS32_r2_s(divu, 41, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(divu, 42, 0, 0, 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF, 0x00000000); + DO_MIPS32_r2_s(divu, 43, 0, 0, 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0x00000000); + DO_MIPS32_r2_s(divu, 44, 0, 0, 0x80000000, 0x7FFFFFFF, 0x00000001, 0x00000001); + DO_MIPS32_r2_s(divu, 45, 0, 0, 0x80000000, 0x80000000, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(divu, 46, 0, 0, 0x80000000, 0xFFFFFFFF, 0x80000000, 0x00000000); + DO_MIPS32_r2_s(divu, 47, 0, 0, 0xFFFFFFFF, 0x7FFFFFFF, 0x00000001, 0x00000002); + DO_MIPS32_r2_s(divu, 48, 0, 0, 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF, 0x00000001); + DO_MIPS32_r2_s(divu, 49, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000001); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/madd.c b/tests/tcg/mips/user/isa/mips32/arithmatic/madd.c new file mode 100644 index 0000000000..7f047f76d9 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/madd.c @@ -0,0 +1,79 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r2_s(divu, 0, 0, 0, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(madd, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(madd, 1, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(madd, 2, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000000, 0x00000007); + DO_MIPS32_r2_s(madd, 3, 0x00000000, 0x00000007, 0x00000004, 0x00000007, 0x00000000, 0x00000023); + DO_MIPS32_r2_s(madd, 4, 0x00000000, 0x00000023, 0x00000008, 0x0000000F, 0x00000000, 0x0000009b); + DO_MIPS32_r2_s(madd, 5, 0x00000000, 0x0000009b, 0x00000010, 0x0000001F, 0x00000000, 0x0000028b); + DO_MIPS32_r2_s(madd, 6, 0x00000000, 0x0000028b, 0x00000020, 0x0000003F, 0x00000000, 0x00000a6b); + DO_MIPS32_r2_s(madd, 7, 0x00000000, 0x00000a6b, 0x00000040, 0x0000007F, 0x00000000, 0x00002a2b); + DO_MIPS32_r2_s(madd, 8, 0x00000000, 0x00002a2b, 0x00000080, 0x000000FF, 0x00000000, 0x0000a9ab); + DO_MIPS32_r2_s(madd, 9, 0x00000000, 0x0000a9ab, 0x00000100, 0x000001FF, 0x00000000, 0x0002a8ab); + DO_MIPS32_r2_s(madd, 10, 0x00000000, 0x0002a8ab, 0x00000200, 0x000003FF, 0x00000000, 0x000aa6ab); + DO_MIPS32_r2_s(madd, 11, 0x00000000, 0x000aa6ab, 0x00000400, 0x000007FF, 0x00000000, 0x002aa2ab); + DO_MIPS32_r2_s(madd, 12, 0x00000000, 0x002aa2ab, 0x00000800, 0x00000FFF, 0x00000000, 0x00aa9aab); + DO_MIPS32_r2_s(madd, 13, 0x00000000, 0x00aa9aab, 0x00001000, 0x00001FFF, 0x00000000, 0x02aa8aab); + DO_MIPS32_r2_s(madd, 14, 0x00000000, 0x02aa8aab, 0x00002000, 0x00003FFF, 0x00000000, 0x0aaa6aab); + DO_MIPS32_r2_s(madd, 15, 0x00000000, 0x0aaa6aab, 0x00004000, 0x00007FFF, 0x00000000, 0x2aaa2aab); + DO_MIPS32_r2_s(madd, 16, 0x00000000, 0x2aaa2aab, 0x00008000, 0x0000FFFF, 0x00000000, 0xaaa9aaab); + DO_MIPS32_r2_s(madd, 17, 0x00000000, 0xaaa9aaab, 0x00010000, 0x0001FFFF, 0x00000002, 0xaaa8aaab); + DO_MIPS32_r2_s(madd, 18, 0x00000002, 0xaaa8aaab, 0x00020000, 0x0003FFFF, 0x0000000a, 0xAAA6AAAB); + DO_MIPS32_r2_s(madd, 19, 0x0000000a, 0xAAA6AAAB, 0x00040000, 0x0007FFFF, 0x0000002A, 0xAAA2AAAB); + DO_MIPS32_r2_s(madd, 20, 0x0000002A, 0xAAA2AAAB, 0x00080000, 0x000FFFFF, 0x000000AA, 0xAA9AAAAB); + DO_MIPS32_r2_s(madd, 21, 0x000000AA, 0xAA9AAAAB, 0x00100000, 0x001FFFFF, 0x000002AA, 0xAA8AAAAB); + DO_MIPS32_r2_s(madd, 22, 0x000002AA, 0xAA8AAAAB, 0x00200000, 0x003FFFFF, 0x00000AAA, 0xAA6AAAAB); + DO_MIPS32_r2_s(madd, 23, 0x00000AAA, 0xAA6AAAAB, 0x00400000, 0x007FFFFF, 0x00002AAA, 0xAA2AAAAB); + DO_MIPS32_r2_s(madd, 24, 0x00002AAA, 0xAA2AAAAB, 0x00800000, 0x00FFFFFF, 0x0000AAAA, 0xA9AAAAAB); + DO_MIPS32_r2_s(madd, 25, 0x0000AAAA, 0xA9AAAAAB, 0x01000000, 0x01FFFFFF, 0x0002AAAA, 0xA8AAAAAB); + DO_MIPS32_r2_s(madd, 26, 0x0002AAAA, 0xA8AAAAAB, 0x02000000, 0x03FFFFFF, 0x000AAAAA, 0xA6AAAAAB); + DO_MIPS32_r2_s(madd, 27, 0x000AAAAA, 0xA6AAAAAB, 0x04000000, 0x07FFFFFF, 0x002AAAAA, 0xA2AAAAAB); + DO_MIPS32_r2_s(madd, 28, 0x002AAAAA, 0xA2AAAAAB, 0x08000000, 0x0FFFFFFF, 0x00AAAAAA, 0x9AAAAAAB); + DO_MIPS32_r2_s(madd, 29, 0x00AAAAAA, 0x9AAAAAAB, 0x10000000, 0x1FFFFFFF, 0x02AAAAAA, 0x8AAAAAAB); + DO_MIPS32_r2_s(madd, 30, 0x02AAAAAA, 0x8AAAAAAB, 0x20000000, 0x3FFFFFFF, 0x0AAAAAAA, 0x6AAAAAAB); + DO_MIPS32_r2_s(madd, 31, 0x0AAAAAAA, 0x6AAAAAAB, 0x40000000, 0x7FFFFFFF, 0x2AAAAAAA, 0x2AAAAAAB); + DO_MIPS32_r2_s(madd, 32, 0x2AAAAAAA, 0x2AAAAAAB, 0x80000000, 0xFFFFFFFF, 0x2AAAAAAA, 0xAAAAAAAB); + DO_MIPS32_r2_s(madd, 33, 0x00000000, 0x00000000, 0x00000000, 0x55555555, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(madd, 34, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0x1C71C71C, 0x38E38E39); + DO_MIPS32_r2_s(madd, 35, 0x1C71C71C, 0x38E38E39, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF, 0xAAAAAAAB); + DO_MIPS32_r2_s(madd, 36, 0xFFFFFFFF, 0xAAAAAAAB, 0xFFFFFFFF, 0x55555555, 0xFFFFFFFF, 0x55555556); + DO_MIPS32_r2_s(madd, 37, 0xFFFFFFFF, 0x55555556, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF, 0x55555556); + DO_MIPS32_r2_s(madd, 38, 0xFFFFFFFF, 0x55555556, 0xAAAAAAAA, 0x55555555, 0xe38e38e2, 0xc71c71c8); + DO_MIPS32_r2_s(madd, 39, 0xe38e38e2, 0xc71c71c8, 0xAAAAAAAA, 0xAAAAAAAA, 0xffffffff, 0xaaaaaaac); + DO_MIPS32_r2_s(madd, 40, 0xffffffff, 0xaaaaaaac, 0xAAAAAAAA, 0xFFFFFFFF, 0x00000000, 0x00000002); + DO_MIPS32_r2_s(madd, 41, 0x00000000, 0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF, 0x00000001); + DO_MIPS32_r2_s(madd, 42, 0x3FFFFFFF, 0x00000001, 0x7FFFFFFF, 0x80000000, 0xffffffff, 0x80000001); + DO_MIPS32_r2_s(madd, 43, 0xffffffff, 0x80000001, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002); + DO_MIPS32_r2_s(madd, 44, 0xFFFFFFFF, 0x00000002, 0x80000000, 0x7FFFFFFF, 0xbfffffff, 0x80000002); + DO_MIPS32_r2_s(madd, 45, 0xbfffffff, 0x80000002, 0x80000000, 0x80000000, 0xffffffff, 0x80000002); + DO_MIPS32_r2_s(madd, 46, 0xffffffff, 0x80000002, 0x80000000, 0xFFFFFFFF, 0x00000000, 0x00000002); + DO_MIPS32_r2_s(madd, 47, 0x00000000, 0x00000002, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0x80000003); + DO_MIPS32_r2_s(madd, 48, 0xFFFFFFFF, 0x80000003, 0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000003); + DO_MIPS32_r2_s(madd, 49, 0x00000000, 0x00000003, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000004); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/maddu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/maddu.c new file mode 100644 index 0000000000..8073841b33 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/maddu.c @@ -0,0 +1,78 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r2_s(maddu, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(maddu, 1, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(maddu, 2, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000000, 0x00000007); + DO_MIPS32_r2_s(maddu, 3, 0x00000000, 0x00000007, 0x00000004, 0x00000007, 0x00000000, 0x00000023); + DO_MIPS32_r2_s(maddu, 4, 0x00000000, 0x00000023, 0x00000008, 0x0000000F, 0x00000000, 0x0000009b); + DO_MIPS32_r2_s(maddu, 5, 0x00000000, 0x0000009b, 0x00000010, 0x0000001F, 0x00000000, 0x0000028b); + DO_MIPS32_r2_s(maddu, 6, 0x00000000, 0x0000028b, 0x00000020, 0x0000003F, 0x00000000, 0x00000a6b); + DO_MIPS32_r2_s(maddu, 7, 0x00000000, 0x00000a6b, 0x00000040, 0x0000007F, 0x00000000, 0x00002a2b); + DO_MIPS32_r2_s(maddu, 8, 0x00000000, 0x00002a2b, 0x00000080, 0x000000FF, 0x00000000, 0x0000a9ab); + DO_MIPS32_r2_s(maddu, 9, 0x00000000, 0x0000a9ab, 0x00000100, 0x000001FF, 0x00000000, 0x0002a8ab); + DO_MIPS32_r2_s(maddu, 10, 0x00000000, 0x0002a8ab, 0x00000200, 0x000003FF, 0x00000000, 0x000aa6ab); + DO_MIPS32_r2_s(maddu, 11, 0x00000000, 0x000aa6ab, 0x00000400, 0x000007FF, 0x00000000, 0x002aa2ab); + DO_MIPS32_r2_s(maddu, 12, 0x00000000, 0x002aa2ab, 0x00000800, 0x00000FFF, 0x00000000, 0x00aa9aab); + DO_MIPS32_r2_s(maddu, 13, 0x00000000, 0x00aa9aab, 0x00001000, 0x00001FFF, 0x00000000, 0x02aa8aab); + DO_MIPS32_r2_s(maddu, 14, 0x00000000, 0x02aa8aab, 0x00002000, 0x00003FFF, 0x00000000, 0x0aaa6aab); + DO_MIPS32_r2_s(maddu, 15, 0x00000000, 0x0aaa6aab, 0x00004000, 0x00007FFF, 0x00000000, 0x2aaa2aab); + DO_MIPS32_r2_s(maddu, 16, 0x00000000, 0x2aaa2aab, 0x00008000, 0x0000FFFF, 0x00000000, 0xaaa9aaab); + DO_MIPS32_r2_s(maddu, 17, 0x00000000, 0xaaa9aaab, 0x00010000, 0x0001FFFF, 0x00000002, 0xaaa8aaab); + DO_MIPS32_r2_s(maddu, 18, 0x00000002, 0xaaa8aaab, 0x00020000, 0x0003FFFF, 0x0000000a, 0xAAA6AAAB); + DO_MIPS32_r2_s(maddu, 19, 0x0000000a, 0xAAA6AAAB, 0x00040000, 0x0007FFFF, 0x0000002A, 0xAAA2AAAB); + DO_MIPS32_r2_s(maddu, 20, 0x0000002A, 0xAAA2AAAB, 0x00080000, 0x000FFFFF, 0x000000AA, 0xAA9AAAAB); + DO_MIPS32_r2_s(maddu, 21, 0x000000AA, 0xAA9AAAAB, 0x00100000, 0x001FFFFF, 0x000002AA, 0xAA8AAAAB); + DO_MIPS32_r2_s(maddu, 22, 0x000002AA, 0xAA8AAAAB, 0x00200000, 0x003FFFFF, 0x00000AAA, 0xAA6AAAAB); + DO_MIPS32_r2_s(maddu, 23, 0x00000AAA, 0xAA6AAAAB, 0x00400000, 0x007FFFFF, 0x00002AAA, 0xAA2AAAAB); + DO_MIPS32_r2_s(maddu, 24, 0x00002AAA, 0xAA2AAAAB, 0x00800000, 0x00FFFFFF, 0x0000AAAA, 0xA9AAAAAB); + DO_MIPS32_r2_s(maddu, 25, 0x0000AAAA, 0xA9AAAAAB, 0x01000000, 0x01FFFFFF, 0x0002AAAA, 0xA8AAAAAB); + DO_MIPS32_r2_s(maddu, 26, 0x0002AAAA, 0xA8AAAAAB, 0x02000000, 0x03FFFFFF, 0x000AAAAA, 0xA6AAAAAB); + DO_MIPS32_r2_s(maddu, 27, 0x000AAAAA, 0xA6AAAAAB, 0x04000000, 0x07FFFFFF, 0x002AAAAA, 0xA2AAAAAB); + DO_MIPS32_r2_s(maddu, 28, 0x002AAAAA, 0xA2AAAAAB, 0x08000000, 0x0FFFFFFF, 0x00AAAAAA, 0x9AAAAAAB); + DO_MIPS32_r2_s(maddu, 29, 0x00AAAAAA, 0x9AAAAAAB, 0x10000000, 0x1FFFFFFF, 0x02AAAAAA, 0x8AAAAAAB); + DO_MIPS32_r2_s(maddu, 30, 0x02AAAAAA, 0x8AAAAAAB, 0x20000000, 0x3FFFFFFF, 0x0AAAAAAA, 0x6AAAAAAB); + DO_MIPS32_r2_s(maddu, 31, 0x0AAAAAAA, 0x6AAAAAAB, 0x40000000, 0x7FFFFFFF, 0x2AAAAAAA, 0x2AAAAAAB); + DO_MIPS32_r2_s(maddu, 32, 0x2AAAAAAA, 0x2AAAAAAB, 0x80000000, 0xFFFFFFFF, 0xAAAAAAA9, 0xAAAAAAAB); + DO_MIPS32_r2_s(maddu, 33, 0x00000000, 0x00000000, 0x00000000, 0x55555555, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(maddu, 34, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0x1C71C71C, 0x38E38E39); + DO_MIPS32_r2_s(maddu, 35, 0x1C71C71C, 0x38E38E39, 0xAAAAAAAA, 0x55555555, 0x55555554, 0xaaaaaaab); + DO_MIPS32_r2_s(maddu, 36, 0x55555554, 0xaaaaaaab, 0xFFFFFFFF, 0x55555555, 0xaaaaaaa9, 0x55555556); + DO_MIPS32_r2_s(maddu, 37, 0xaaaaaaa9, 0x55555556, 0xAAAAAAAA, 0x00000000, 0xaaaaaaa9, 0x55555556); + DO_MIPS32_r2_s(maddu, 38, 0xaaaaaaa9, 0x55555556, 0xAAAAAAAA, 0x55555555, 0xe38e38e1, 0xc71c71c8); + DO_MIPS32_r2_s(maddu, 39, 0xe38e38e1, 0xc71c71c8, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555552, 0xaaaaaaac); + DO_MIPS32_r2_s(maddu, 40, 0x55555552, 0xaaaaaaac, 0xAAAAAAAA, 0xFFFFFFFF, 0xfffffffc, 0x00000002); + DO_MIPS32_r2_s(maddu, 41, 0x00000000, 0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x3fffffff, 0x00000001); + DO_MIPS32_r2_s(maddu, 42, 0x3fffffff, 0x00000001, 0x7FFFFFFF, 0x80000000, 0x7ffffffe, 0x80000001); + DO_MIPS32_r2_s(maddu, 43, 0x7ffffffe, 0x80000001, 0x7FFFFFFF, 0xFFFFFFFF, 0xfffffffd, 0x00000002); + DO_MIPS32_r2_s(maddu, 44, 0xfffffffd, 0x00000002, 0x80000000, 0x7FFFFFFF, 0x3ffffffc, 0x80000002); + DO_MIPS32_r2_s(maddu, 45, 0x3ffffffc, 0x80000002, 0x80000000, 0x80000000, 0x7ffffffc, 0x80000002); + DO_MIPS32_r2_s(maddu, 46, 0x7ffffffc, 0x80000002, 0x80000000, 0xFFFFFFFF, 0xfffffffc, 0x00000002); + DO_MIPS32_r2_s(maddu, 47, 0xfffffffc, 0x00000002, 0xFFFFFFFF, 0x7FFFFFFF, 0x7ffffffa, 0x80000003); + DO_MIPS32_r2_s(maddu, 48, 0x7ffffffa, 0x80000003, 0xFFFFFFFF, 0x80000000, 0xfffffffa, 0x00000003); + DO_MIPS32_r2_s(maddu, 49, 0xfffffffa, 0x00000003, 0xFFFFFFFF, 0xFFFFFFFF, 0xfffffff8, 0x00000004); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/msub.c b/tests/tcg/mips/user/isa/mips32/arithmatic/msub.c new file mode 100644 index 0000000000..36387cbdf8 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/msub.c @@ -0,0 +1,78 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r2_s(msub, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(msub, 1, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0xffffffff, 0xffffffff); + DO_MIPS32_r2_s(msub, 2, 0xffffffff, 0xffffffff, 0x00000002, 0x00000003, 0xffffffff, 0xfffffff9); + DO_MIPS32_r2_s(msub, 3, 0xffffffff, 0xfffffff9, 0x00000004, 0x00000007, 0xffffffff, 0xffffffdd); + DO_MIPS32_r2_s(msub, 4, 0xffffffff, 0xffffffdd, 0x00000008, 0x0000000F, 0xffffffff, 0xffffff65); + DO_MIPS32_r2_s(msub, 5, 0xffffffff, 0xffffff65, 0x00000010, 0x0000001F, 0xffffffff, 0xfffffd75); + DO_MIPS32_r2_s(msub, 6, 0xffffffff, 0xfffffd75, 0x00000020, 0x0000003F, 0xffffffff, 0xfffff595); + DO_MIPS32_r2_s(msub, 7, 0xffffffff, 0xfffff595, 0x00000040, 0x0000007F, 0xffffffff, 0xffffd5d5); + DO_MIPS32_r2_s(msub, 8, 0xffffffff, 0xffffd5d5, 0x00000080, 0x000000FF, 0xffffffff, 0xffff5655); + DO_MIPS32_r2_s(msub, 9, 0xffffffff, 0xffff5655, 0x00000100, 0x000001FF, 0xffffffff, 0xfffd5755); + DO_MIPS32_r2_s(msub, 10, 0xffffffff, 0xfffd5755, 0x00000200, 0x000003FF, 0xffffffff, 0xfff55955); + DO_MIPS32_r2_s(msub, 11, 0xffffffff, 0xfff55955, 0x00000400, 0x000007FF, 0xffffffff, 0xffd55d55); + DO_MIPS32_r2_s(msub, 12, 0xffffffff, 0xffd55d55, 0x00000800, 0x00000FFF, 0xffffffff, 0xff556555); + DO_MIPS32_r2_s(msub, 13, 0xffffffff, 0xff556555, 0x00001000, 0x00001FFF, 0xffffffff, 0xfd557555); + DO_MIPS32_r2_s(msub, 14, 0xffffffff, 0xfd557555, 0x00002000, 0x00003FFF, 0xffffffff, 0xf5559555); + DO_MIPS32_r2_s(msub, 15, 0xffffffff, 0xf5559555, 0x00004000, 0x00007FFF, 0xffffffff, 0xd555d555); + DO_MIPS32_r2_s(msub, 16, 0xffffffff, 0xd555d555, 0x00008000, 0x0000FFFF, 0xffffffff, 0x55565555); + DO_MIPS32_r2_s(msub, 17, 0xffffffff, 0x55565555, 0x00010000, 0x0001FFFF, 0xfffffffd, 0x55575555); + DO_MIPS32_r2_s(msub, 18, 0xfffffffd, 0x55575555, 0x00020000, 0x0003FFFF, 0xfffffff5, 0x55595555); + DO_MIPS32_r2_s(msub, 19, 0xfffffff5, 0x55595555, 0x00040000, 0x0007FFFF, 0xffffffd5, 0x555d5555); + DO_MIPS32_r2_s(msub, 20, 0xffffffd5, 0x555d5555, 0x00080000, 0x000FFFFF, 0xffffff55, 0x55655555); + DO_MIPS32_r2_s(msub, 21, 0xffffff55, 0x55655555, 0x00100000, 0x001FFFFF, 0xfffffd55, 0x55755555); + DO_MIPS32_r2_s(msub, 22, 0xfffffd55, 0x55755555, 0x00200000, 0x003FFFFF, 0xfffff555, 0x55955555); + DO_MIPS32_r2_s(msub, 23, 0xfffff555, 0x55955555, 0x00400000, 0x007FFFFF, 0xffffd555, 0x55d55555); + DO_MIPS32_r2_s(msub, 24, 0xffffd555, 0x55d55555, 0x00800000, 0x00FFFFFF, 0xffff5555, 0x56555555); + DO_MIPS32_r2_s(msub, 25, 0xffff5555, 0x56555555, 0x01000000, 0x01FFFFFF, 0xfffd5555, 0x57555555); + DO_MIPS32_r2_s(msub, 26, 0xfffd5555, 0x57555555, 0x02000000, 0x03FFFFFF, 0xfff55555, 0x59555555); + DO_MIPS32_r2_s(msub, 27, 0xfff55555, 0x59555555, 0x04000000, 0x07FFFFFF, 0xffd55555, 0x5d555555); + DO_MIPS32_r2_s(msub, 28, 0xffd55555, 0x5d555555, 0x08000000, 0x0FFFFFFF, 0xff555555, 0x65555555); + DO_MIPS32_r2_s(msub, 29, 0xff555555, 0x65555555, 0x10000000, 0x1FFFFFFF, 0xfd555555, 0x75555555); + DO_MIPS32_r2_s(msub, 30, 0xfd555555, 0x75555555, 0x20000000, 0x3FFFFFFF, 0xf5555555, 0x95555555); + DO_MIPS32_r2_s(msub, 31, 0xf5555555, 0x95555555, 0x40000000, 0x7FFFFFFF, 0xd5555555, 0xd5555555); + DO_MIPS32_r2_s(msub, 32, 0xd5555555, 0xd5555555, 0x80000000, 0xFFFFFFFF, 0xd5555555, 0x55555555); + DO_MIPS32_r2_s(msub, 33, 0x00000000, 0x00000000, 0x00000000, 0x55555555, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(msub, 34, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0xe38e38e3, 0xc71c71c7); + DO_MIPS32_r2_s(msub, 35, 0xe38e38e3, 0xc71c71c7, 0xAAAAAAAA, 0x55555555, 0x00000000, 0x55555555); + DO_MIPS32_r2_s(msub, 36, 0x00000000, 0x55555555, 0xFFFFFFFF, 0x55555555, 0x00000000, 0xaaaaaaaa); + DO_MIPS32_r2_s(msub, 37, 0x00000000, 0xaaaaaaaa, 0xAAAAAAAA, 0x00000000, 0x00000000, 0xaaaaaaaa); + DO_MIPS32_r2_s(msub, 38, 0x00000000, 0xaaaaaaaa, 0xAAAAAAAA, 0x55555555, 0x1c71c71d, 0x38e38e38); + DO_MIPS32_r2_s(msub, 39, 0x1c71c71d, 0x38e38e38, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000, 0x55555554); + DO_MIPS32_r2_s(msub, 40, 0x00000000, 0x55555554, 0xAAAAAAAA, 0xFFFFFFFF, 0xffffffff, 0xfffffffe); + DO_MIPS32_r2_s(msub, 41, 0x00000000, 0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0xc0000000, 0xffffffff); + DO_MIPS32_r2_s(msub, 42, 0xc0000000, 0xffffffff, 0x7FFFFFFF, 0x80000000, 0x00000000, 0x7fffffff); + DO_MIPS32_r2_s(msub, 43, 0x00000000, 0x7fffffff, 0x7FFFFFFF, 0xFFFFFFFF, 0x00000000, 0xfffffffe); + DO_MIPS32_r2_s(msub, 44, 0x00000000, 0xfffffffe, 0x80000000, 0x7FFFFFFF, 0x40000000, 0x7ffffffe); + DO_MIPS32_r2_s(msub, 45, 0x40000000, 0x7ffffffe, 0x80000000, 0x80000000, 0x00000000, 0x7ffffffe); + DO_MIPS32_r2_s(msub, 46, 0x00000000, 0x7ffffffe, 0x80000000, 0xFFFFFFFF, 0xffffffff, 0xfffffffe); + DO_MIPS32_r2_s(msub, 47, 0xffffffff, 0xfffffffe, 0xFFFFFFFF, 0x7FFFFFFF, 0x00000000, 0x7ffffffd); + DO_MIPS32_r2_s(msub, 48, 0x00000000, 0x7ffffffd, 0xFFFFFFFF, 0x80000000, 0xffffffff, 0xfffffffd); + DO_MIPS32_r2_s(msub, 49, 0xffffffff, 0xfffffffd, 0xFFFFFFFF, 0xFFFFFFFF, 0xffffffff, 0xfffffffc); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/msubu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/msubu.c new file mode 100644 index 0000000000..d20065d0b2 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/msubu.c @@ -0,0 +1,78 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r2_s(msubu, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(msubu, 1, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0xffffffff, 0xffffffff); + DO_MIPS32_r2_s(msubu, 2, 0xffffffff, 0xffffffff, 0x00000002, 0x00000003, 0xffffffff, 0xfffffff9); + DO_MIPS32_r2_s(msubu, 3, 0xffffffff, 0xfffffff9, 0x00000004, 0x00000007, 0xffffffff, 0xffffffdd); + DO_MIPS32_r2_s(msubu, 4, 0xffffffff, 0xffffffdd, 0x00000008, 0x0000000F, 0xffffffff, 0xffffff65); + DO_MIPS32_r2_s(msubu, 5, 0xffffffff, 0xffffff65, 0x00000010, 0x0000001F, 0xffffffff, 0xfffffd75); + DO_MIPS32_r2_s(msubu, 6, 0xffffffff, 0xfffffd75, 0x00000020, 0x0000003F, 0xffffffff, 0xfffff595); + DO_MIPS32_r2_s(msubu, 7, 0xffffffff, 0xfffff595, 0x00000040, 0x0000007F, 0xffffffff, 0xffffd5d5); + DO_MIPS32_r2_s(msubu, 8, 0xffffffff, 0xffffd5d5, 0x00000080, 0x000000FF, 0xffffffff, 0xffff5655); + DO_MIPS32_r2_s(msubu, 9, 0xffffffff, 0xffff5655, 0x00000100, 0x000001FF, 0xffffffff, 0xfffd5755); + DO_MIPS32_r2_s(msubu, 10, 0xffffffff, 0xfffd5755, 0x00000200, 0x000003FF, 0xffffffff, 0xfff55955); + DO_MIPS32_r2_s(msubu, 11, 0xffffffff, 0xfff55955, 0x00000400, 0x000007FF, 0xffffffff, 0xffd55d55); + DO_MIPS32_r2_s(msubu, 12, 0xffffffff, 0xffd55d55, 0x00000800, 0x00000FFF, 0xffffffff, 0xff556555); + DO_MIPS32_r2_s(msubu, 13, 0xffffffff, 0xff556555, 0x00001000, 0x00001FFF, 0xffffffff, 0xfd557555); + DO_MIPS32_r2_s(msubu, 14, 0xffffffff, 0xfd557555, 0x00002000, 0x00003FFF, 0xffffffff, 0xf5559555); + DO_MIPS32_r2_s(msubu, 15, 0xffffffff, 0xf5559555, 0x00004000, 0x00007FFF, 0xffffffff, 0xd555d555); + DO_MIPS32_r2_s(msubu, 16, 0xffffffff, 0xd555d555, 0x00008000, 0x0000FFFF, 0xffffffff, 0x55565555); + DO_MIPS32_r2_s(msubu, 17, 0xffffffff, 0x55565555, 0x00010000, 0x0001FFFF, 0xfffffffd, 0x55575555); + DO_MIPS32_r2_s(msubu, 18, 0xfffffffd, 0x55575555, 0x00020000, 0x0003FFFF, 0xfffffff5, 0x55595555); + DO_MIPS32_r2_s(msubu, 19, 0xfffffff5, 0x55595555, 0x00040000, 0x0007FFFF, 0xffffffd5, 0x555d5555); + DO_MIPS32_r2_s(msubu, 20, 0xffffffd5, 0x555d5555, 0x00080000, 0x000FFFFF, 0xffffff55, 0x55655555); + DO_MIPS32_r2_s(msubu, 21, 0xffffff55, 0x55655555, 0x00100000, 0x001FFFFF, 0xfffffd55, 0x55755555); + DO_MIPS32_r2_s(msubu, 22, 0xfffffd55, 0x55755555, 0x00200000, 0x003FFFFF, 0xfffff555, 0x55955555); + DO_MIPS32_r2_s(msubu, 23, 0xfffff555, 0x55955555, 0x00400000, 0x007FFFFF, 0xffffd555, 0x55d55555); + DO_MIPS32_r2_s(msubu, 24, 0xffffd555, 0x55d55555, 0x00800000, 0x00FFFFFF, 0xffff5555, 0x56555555); + DO_MIPS32_r2_s(msubu, 25, 0xffff5555, 0x56555555, 0x01000000, 0x01FFFFFF, 0xfffd5555, 0x57555555); + DO_MIPS32_r2_s(msubu, 26, 0xfffd5555, 0x57555555, 0x02000000, 0x03FFFFFF, 0xfff55555, 0x59555555); + DO_MIPS32_r2_s(msubu, 27, 0xfff55555, 0x59555555, 0x04000000, 0x07FFFFFF, 0xffd55555, 0x5d555555); + DO_MIPS32_r2_s(msubu, 28, 0xffd55555, 0x5d555555, 0x08000000, 0x0FFFFFFF, 0xff555555, 0x65555555); + DO_MIPS32_r2_s(msubu, 29, 0xff555555, 0x65555555, 0x10000000, 0x1FFFFFFF, 0xfd555555, 0x75555555); + DO_MIPS32_r2_s(msubu, 30, 0xfd555555, 0x75555555, 0x20000000, 0x3FFFFFFF, 0xf5555555, 0x95555555); + DO_MIPS32_r2_s(msubu, 31, 0xf5555555, 0x95555555, 0x40000000, 0x7FFFFFFF, 0xd5555555, 0xd5555555); + DO_MIPS32_r2_s(msubu, 32, 0xd5555555, 0xd5555555, 0x80000000, 0xFFFFFFFF, 0x55555556, 0x55555555); + DO_MIPS32_r2_s(msubu, 33, 0x00000000, 0x00000000, 0x00000000, 0x55555555, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(msubu, 34, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0xe38e38e3, 0xc71c71c7); + DO_MIPS32_r2_s(msubu, 35, 0xe38e38e3, 0xc71c71c7, 0xAAAAAAAA, 0x55555555, 0xaaaaaaab, 0x55555555); + DO_MIPS32_r2_s(msubu, 36, 0xaaaaaaab, 0x55555555, 0xFFFFFFFF, 0x55555555, 0x55555556, 0xaaaaaaaa); + DO_MIPS32_r2_s(msubu, 37, 0x55555556, 0xaaaaaaaa, 0xAAAAAAAA, 0x00000000, 0x55555556, 0xaaaaaaaa); + DO_MIPS32_r2_s(msubu, 38, 0x55555556, 0xaaaaaaaa, 0xAAAAAAAA, 0x55555555, 0x1c71c71e, 0x38e38e38); + DO_MIPS32_r2_s(msubu, 39, 0x1c71c71e, 0x38e38e38, 0xAAAAAAAA, 0xAAAAAAAA, 0xaaaaaaad, 0x55555554); + DO_MIPS32_r2_s(msubu, 40, 0xaaaaaaad, 0x55555554, 0xAAAAAAAA, 0xFFFFFFFF, 0x00000003, 0xfffffffe); + DO_MIPS32_r2_s(msubu, 41, 0x00000000, 0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0xc0000000, 0xffffffff); + DO_MIPS32_r2_s(msubu, 42, 0xc0000000, 0xffffffff, 0x7FFFFFFF, 0x80000000, 0x80000001, 0x7fffffff); + DO_MIPS32_r2_s(msubu, 43, 0x80000001, 0x7fffffff, 0x7FFFFFFF, 0xFFFFFFFF, 0x00000002, 0xfffffffe); + DO_MIPS32_r2_s(msubu, 44, 0x00000002, 0xfffffffe, 0x80000000, 0x7FFFFFFF, 0xc0000003, 0x7ffffffe); + DO_MIPS32_r2_s(msubu, 45, 0xc0000003, 0x7ffffffe, 0x80000000, 0x80000000, 0x80000003, 0x7ffffffe); + DO_MIPS32_r2_s(msubu, 46, 0x80000003, 0x7ffffffe, 0x80000000, 0xFFFFFFFF, 0x00000003, 0xfffffffe); + DO_MIPS32_r2_s(msubu, 47, 0x00000003, 0xfffffffe, 0xFFFFFFFF, 0x7FFFFFFF, 0x80000005, 0x7ffffffd); + DO_MIPS32_r2_s(msubu, 48, 0x80000005, 0x7ffffffd, 0xFFFFFFFF, 0x80000000, 0x00000005, 0xfffffffd); + DO_MIPS32_r2_s(msubu, 49, 0x00000005, 0xfffffffd, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0xfffffffc); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/mul.c b/tests/tcg/mips/user/isa/mips32/arithmatic/mul.c new file mode 100644 index 0000000000..ab74a14545 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/mul.c @@ -0,0 +1,78 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r(mul, 0, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r(mul, 1, 0x00000001, 0x00000001, 0x00000001); + DO_MIPS32_r(mul, 2, 0x00000002, 0x00000003, 0x00000006); + DO_MIPS32_r(mul, 3, 0x00000004, 0x00000007, 0x0000001C); + DO_MIPS32_r(mul, 4, 0x00000008, 0x0000000F, 0x00000078); + DO_MIPS32_r(mul, 5, 0x00000010, 0x0000001F, 0x000001F0); + DO_MIPS32_r(mul, 6, 0x00000020, 0x0000003F, 0x000007E0); + DO_MIPS32_r(mul, 7, 0x00000040, 0x0000007F, 0x00001FC0); + DO_MIPS32_r(mul, 8, 0x00000080, 0x000000FF, 0x00007F80); + DO_MIPS32_r(mul, 9, 0x00000100, 0x000001FF, 0x0001FF00); + DO_MIPS32_r(mul, 10, 0x00000200, 0x000003FF, 0x0007FE00); + DO_MIPS32_r(mul, 11, 0x00000400, 0x000007FF, 0x001FFC00); + DO_MIPS32_r(mul, 12, 0x00000800, 0x00000FFF, 0x007FF800); + DO_MIPS32_r(mul, 13, 0x00001000, 0x00001FFF, 0x01FFF000); + DO_MIPS32_r(mul, 14, 0x00002000, 0x00003FFF, 0x07FFE000); + DO_MIPS32_r(mul, 15, 0x00004000, 0x00007FFF, 0x1FFFC000); + DO_MIPS32_r(mul, 16, 0x00008000, 0x0000FFFF, 0x7FFF8000); + DO_MIPS32_r(mul, 17, 0x00010000, 0x0001FFFF, 0xFFFF0000); + DO_MIPS32_r(mul, 18, 0x00020000, 0x0003FFFF, 0xFFFE0000); + DO_MIPS32_r(mul, 19, 0x00040000, 0x0007FFFF, 0xFFFC0000); + DO_MIPS32_r(mul, 20, 0x00080000, 0x000FFFFF, 0xFFF80000); + DO_MIPS32_r(mul, 21, 0x00100000, 0x001FFFFF, 0xFFF00000); + DO_MIPS32_r(mul, 22, 0x00200000, 0x003FFFFF, 0xFFE00000); + DO_MIPS32_r(mul, 23, 0x00400000, 0x007FFFFF, 0xFFC00000); + DO_MIPS32_r(mul, 24, 0x00800000, 0x00FFFFFF, 0xFF800000); + DO_MIPS32_r(mul, 25, 0x01000000, 0x01FFFFFF, 0xFF000000); + DO_MIPS32_r(mul, 26, 0x02000000, 0x03FFFFFF, 0xFE000000); + DO_MIPS32_r(mul, 27, 0x04000000, 0x07FFFFFF, 0xFC000000); + DO_MIPS32_r(mul, 28, 0x08000000, 0x0FFFFFFF, 0xF8000000); + DO_MIPS32_r(mul, 29, 0x10000000, 0x1FFFFFFF, 0xF0000000); + DO_MIPS32_r(mul, 30, 0x20000000, 0x3FFFFFFF, 0xE0000000); + DO_MIPS32_r(mul, 31, 0x40000000, 0x7FFFFFFF, 0xC0000000); + DO_MIPS32_r(mul, 32, 0x80000000, 0xFFFFFFFF, 0x80000000); + DO_MIPS32_r(mul, 33, 0x00000000, 0x55555555, 0x00000000); + DO_MIPS32_r(mul, 34, 0x55555555, 0x55555555, 0x38E38E39); + DO_MIPS32_r(mul, 35, 0xAAAAAAAA, 0x55555555, 0x71C71C72); + DO_MIPS32_r(mul, 36, 0xFFFFFFFF, 0x55555555, 0xAAAAAAAB); + DO_MIPS32_r(mul, 37, 0xAAAAAAAA, 0x00000000, 0x00000000); + DO_MIPS32_r(mul, 38, 0xAAAAAAAA, 0x55555555, 0x71C71C72); + DO_MIPS32_r(mul, 39, 0xAAAAAAAA, 0xAAAAAAAA, 0xE38E38E4); + DO_MIPS32_r(mul, 40, 0xAAAAAAAA, 0xFFFFFFFF, 0x55555556); + DO_MIPS32_r(mul, 41, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000001); + DO_MIPS32_r(mul, 42, 0x7FFFFFFF, 0x80000000, 0x80000000); + DO_MIPS32_r(mul, 43, 0x7FFFFFFF, 0xFFFFFFFF, 0x80000001); + DO_MIPS32_r(mul, 44, 0x80000000, 0x7FFFFFFF, 0x80000000); + DO_MIPS32_r(mul, 45, 0x80000000, 0x80000000, 0x00000000); + DO_MIPS32_r(mul, 46, 0x80000000, 0xFFFFFFFF, 0x80000000); + DO_MIPS32_r(mul, 47, 0xFFFFFFFF, 0x7FFFFFFF, 0x80000001); + DO_MIPS32_r(mul, 48, 0xFFFFFFFF, 0x80000000, 0x80000000); + DO_MIPS32_r(mul, 49, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/mult.c b/tests/tcg/mips/user/isa/mips32/arithmatic/mult.c new file mode 100644 index 0000000000..8ac7b2c1b8 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/mult.c @@ -0,0 +1,78 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r2_s(mult, 0, 0, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(mult, 1, 0, 0, 0x00000001, 0x00000001, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(mult, 2, 0, 0, 0x00000002, 0x00000003, 0x00000000, 0x00000006); + DO_MIPS32_r2_s(mult, 3, 0, 0, 0x00000004, 0x00000007, 0x00000000, 0x0000001C); + DO_MIPS32_r2_s(mult, 4, 0, 0, 0x00000008, 0x0000000F, 0x00000000, 0x00000078); + DO_MIPS32_r2_s(mult, 5, 0, 0, 0x00000010, 0x0000001F, 0x00000000, 0x000001F0); + DO_MIPS32_r2_s(mult, 6, 0, 0, 0x00000020, 0x0000003F, 0x00000000, 0x000007E0); + DO_MIPS32_r2_s(mult, 7, 0, 0, 0x00000040, 0x0000007F, 0x00000000, 0x00001FC0); + DO_MIPS32_r2_s(mult, 8, 0, 0, 0x00000080, 0x000000FF, 0x00000000, 0x00007F80); + DO_MIPS32_r2_s(mult, 9, 0, 0, 0x00000100, 0x000001FF, 0x00000000, 0x0001FF00); + DO_MIPS32_r2_s(mult, 10, 0, 0, 0x00000200, 0x000003FF, 0x00000000, 0x0007FE00); + DO_MIPS32_r2_s(mult, 11, 0, 0, 0x00000400, 0x000007FF, 0x00000000, 0x001FFC00); + DO_MIPS32_r2_s(mult, 12, 0, 0, 0x00000800, 0x00000FFF, 0x00000000, 0x007FF800); + DO_MIPS32_r2_s(mult, 13, 0, 0, 0x00001000, 0x00001FFF, 0x00000000, 0x01FFF000); + DO_MIPS32_r2_s(mult, 14, 0, 0, 0x00002000, 0x00003FFF, 0x00000000, 0x07FFE000); + DO_MIPS32_r2_s(mult, 15, 0, 0, 0x00004000, 0x00007FFF, 0x00000000, 0x1FFFC000); + DO_MIPS32_r2_s(mult, 16, 0, 0, 0x00008000, 0x0000FFFF, 0x00000000, 0x7FFF8000); + DO_MIPS32_r2_s(mult, 17, 0, 0, 0x00010000, 0x0001FFFF, 0x00000001, 0xFFFF0000); + DO_MIPS32_r2_s(mult, 18, 0, 0, 0x00020000, 0x0003FFFF, 0x00000007, 0xFFFE0000); + DO_MIPS32_r2_s(mult, 19, 0, 0, 0x00040000, 0x0007FFFF, 0x0000001F, 0xFFFC0000); + DO_MIPS32_r2_s(mult, 20, 0, 0, 0x00080000, 0x000FFFFF, 0x0000007F, 0xFFF80000); + DO_MIPS32_r2_s(mult, 21, 0, 0, 0x00100000, 0x001FFFFF, 0x000001FF, 0xFFF00000); + DO_MIPS32_r2_s(mult, 22, 0, 0, 0x00200000, 0x003FFFFF, 0x000007FF, 0xFFE00000); + DO_MIPS32_r2_s(mult, 23, 0, 0, 0x00400000, 0x007FFFFF, 0x00001FFF, 0xFFC00000); + DO_MIPS32_r2_s(mult, 24, 0, 0, 0x00800000, 0x00FFFFFF, 0x00007FFF, 0xFF800000); + DO_MIPS32_r2_s(mult, 25, 0, 0, 0x01000000, 0x01FFFFFF, 0x0001FFFF, 0xFF000000); + DO_MIPS32_r2_s(mult, 26, 0, 0, 0x02000000, 0x03FFFFFF, 0x0007FFFF, 0xFE000000); + DO_MIPS32_r2_s(mult, 27, 0, 0, 0x04000000, 0x07FFFFFF, 0x001FFFFF, 0xFC000000); + DO_MIPS32_r2_s(mult, 28, 0, 0, 0x08000000, 0x0FFFFFFF, 0x007FFFFF, 0xF8000000); + DO_MIPS32_r2_s(mult, 29, 0, 0, 0x10000000, 0x1FFFFFFF, 0x01FFFFFF, 0xF0000000); + DO_MIPS32_r2_s(mult, 30, 0, 0, 0x20000000, 0x3FFFFFFF, 0x07FFFFFF, 0xE0000000); + DO_MIPS32_r2_s(mult, 31, 0, 0, 0x40000000, 0x7FFFFFFF, 0x1FFFFFFF, 0xC0000000); + DO_MIPS32_r2_s(mult, 32, 0, 0, 0x80000000, 0xFFFFFFFF, 0x00000000, 0x80000000); + DO_MIPS32_r2_s(mult, 33, 0, 0, 0x00000000, 0x55555555, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(mult, 34, 0, 0, 0x55555555, 0x55555555, 0x1C71C71C, 0x38E38E39); + DO_MIPS32_r2_s(mult, 35, 0, 0, 0xAAAAAAAA, 0x55555555, 0xE38E38E3, 0x71C71C72); + DO_MIPS32_r2_s(mult, 36, 0, 0, 0xFFFFFFFF, 0x55555555, 0xFFFFFFFF, 0xAAAAAAAB); + DO_MIPS32_r2_s(mult, 37, 0, 0, 0xAAAAAAAA, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(mult, 38, 0, 0, 0xAAAAAAAA, 0x55555555, 0xE38E38E3, 0x71C71C72); + DO_MIPS32_r2_s(mult, 39, 0, 0, 0xAAAAAAAA, 0xAAAAAAAA, 0x1C71C71C, 0xE38E38E4); + DO_MIPS32_r2_s(mult, 40, 0, 0, 0xAAAAAAAA, 0xFFFFFFFF, 0x00000000, 0x55555556); + DO_MIPS32_r2_s(mult, 41, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF, 0x00000001); + DO_MIPS32_r2_s(mult, 42, 0, 0, 0x7FFFFFFF, 0x80000000, 0xC0000000, 0x80000000); + DO_MIPS32_r2_s(mult, 43, 0, 0, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000001); + DO_MIPS32_r2_s(mult, 44, 0, 0, 0x80000000, 0x7FFFFFFF, 0xC0000000, 0x80000000); + DO_MIPS32_r2_s(mult, 45, 0, 0, 0x80000000, 0x80000000, 0x40000000, 0x00000000); + DO_MIPS32_r2_s(mult, 46, 0, 0, 0x80000000, 0xFFFFFFFF, 0x00000000, 0x80000000); + DO_MIPS32_r2_s(mult, 47, 0, 0, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0x80000001); + DO_MIPS32_r2_s(mult, 48, 0, 0, 0xFFFFFFFF, 0x80000000, 0x00000000, 0x80000000); + DO_MIPS32_r2_s(mult, 49, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000001); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/multu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/multu.c new file mode 100644 index 0000000000..eeafbd2d50 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/multu.c @@ -0,0 +1,78 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r2_s(multu, 0, 0, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(multu, 1, 0, 0, 0x00000001, 0x00000001, 0x00000000, 0x00000001); + DO_MIPS32_r2_s(multu, 2, 0, 0, 0x00000002, 0x00000003, 0x00000000, 0x00000006); + DO_MIPS32_r2_s(multu, 3, 0, 0, 0x00000004, 0x00000007, 0x00000000, 0x0000001C); + DO_MIPS32_r2_s(multu, 4, 0, 0, 0x00000008, 0x0000000F, 0x00000000, 0x00000078); + DO_MIPS32_r2_s(multu, 5, 0, 0, 0x00000010, 0x0000001F, 0x00000000, 0x000001F0); + DO_MIPS32_r2_s(multu, 6, 0, 0, 0x00000020, 0x0000003F, 0x00000000, 0x000007E0); + DO_MIPS32_r2_s(multu, 7, 0, 0, 0x00000040, 0x0000007F, 0x00000000, 0x00001FC0); + DO_MIPS32_r2_s(multu, 8, 0, 0, 0x00000080, 0x000000FF, 0x00000000, 0x00007F80); + DO_MIPS32_r2_s(multu, 9, 0, 0, 0x00000100, 0x000001FF, 0x00000000, 0x0001FF00); + DO_MIPS32_r2_s(multu, 10, 0, 0, 0x00000200, 0x000003FF, 0x00000000, 0x0007FE00); + DO_MIPS32_r2_s(multu, 11, 0, 0, 0x00000400, 0x000007FF, 0x00000000, 0x001FFC00); + DO_MIPS32_r2_s(multu, 12, 0, 0, 0x00000800, 0x00000FFF, 0x00000000, 0x007FF800); + DO_MIPS32_r2_s(multu, 13, 0, 0, 0x00001000, 0x00001FFF, 0x00000000, 0x01FFF000); + DO_MIPS32_r2_s(multu, 14, 0, 0, 0x00002000, 0x00003FFF, 0x00000000, 0x07FFE000); + DO_MIPS32_r2_s(multu, 15, 0, 0, 0x00004000, 0x00007FFF, 0x00000000, 0x1FFFC000); + DO_MIPS32_r2_s(multu, 16, 0, 0, 0x00008000, 0x0000FFFF, 0x00000000, 0x7FFF8000); + DO_MIPS32_r2_s(multu, 17, 0, 0, 0x00010000, 0x0001FFFF, 0x00000001, 0xFFFF0000); + DO_MIPS32_r2_s(multu, 18, 0, 0, 0x00020000, 0x0003FFFF, 0x00000007, 0xFFFE0000); + DO_MIPS32_r2_s(multu, 19, 0, 0, 0x00040000, 0x0007FFFF, 0x0000001F, 0xFFFC0000); + DO_MIPS32_r2_s(multu, 20, 0, 0, 0x00080000, 0x000FFFFF, 0x0000007F, 0xFFF80000); + DO_MIPS32_r2_s(multu, 21, 0, 0, 0x00100000, 0x001FFFFF, 0x000001FF, 0xFFF00000); + DO_MIPS32_r2_s(multu, 22, 0, 0, 0x00200000, 0x003FFFFF, 0x000007FF, 0xFFE00000); + DO_MIPS32_r2_s(multu, 23, 0, 0, 0x00400000, 0x007FFFFF, 0x00001FFF, 0xFFC00000); + DO_MIPS32_r2_s(multu, 24, 0, 0, 0x00800000, 0x00FFFFFF, 0x00007FFF, 0xFF800000); + DO_MIPS32_r2_s(multu, 25, 0, 0, 0x01000000, 0x01FFFFFF, 0x0001FFFF, 0xFF000000); + DO_MIPS32_r2_s(multu, 26, 0, 0, 0x02000000, 0x03FFFFFF, 0x0007FFFF, 0xFE000000); + DO_MIPS32_r2_s(multu, 27, 0, 0, 0x04000000, 0x07FFFFFF, 0x001FFFFF, 0xFC000000); + DO_MIPS32_r2_s(multu, 28, 0, 0, 0x08000000, 0x0FFFFFFF, 0x007FFFFF, 0xF8000000); + DO_MIPS32_r2_s(multu, 29, 0, 0, 0x10000000, 0x1FFFFFFF, 0x01FFFFFF, 0xF0000000); + DO_MIPS32_r2_s(multu, 30, 0, 0, 0x20000000, 0x3FFFFFFF, 0x07FFFFFF, 0xE0000000); + DO_MIPS32_r2_s(multu, 31, 0, 0, 0x40000000, 0x7FFFFFFF, 0x1FFFFFFF, 0xC0000000); + DO_MIPS32_r2_s(multu, 32, 0, 0, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF, 0x80000000); + DO_MIPS32_r2_s(multu, 33, 0, 0, 0x00000000, 0x55555555, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(multu, 34, 0, 0, 0x55555555, 0x55555555, 0x1C71C71C, 0x38E38E39); + DO_MIPS32_r2_s(multu, 35, 0, 0, 0xAAAAAAAA, 0x55555555, 0x38E38E38, 0x71C71C72); + DO_MIPS32_r2_s(multu, 36, 0, 0, 0xFFFFFFFF, 0x55555555, 0x55555554, 0xAAAAAAAB); + DO_MIPS32_r2_s(multu, 37, 0, 0, 0xAAAAAAAA, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r2_s(multu, 38, 0, 0, 0xAAAAAAAA, 0x55555555, 0x38E38E38, 0x71C71C72); + DO_MIPS32_r2_s(multu, 39, 0, 0, 0xAAAAAAAA, 0xAAAAAAAA, 0x71C71C70, 0xE38E38E4); + DO_MIPS32_r2_s(multu, 40, 0, 0, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAA9, 0x55555556); + DO_MIPS32_r2_s(multu, 41, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF, 0x00000001); + DO_MIPS32_r2_s(multu, 42, 0, 0, 0x7FFFFFFF, 0x80000000, 0x3FFFFFFF, 0x80000000); + DO_MIPS32_r2_s(multu, 43, 0, 0, 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFE, 0x80000001); + DO_MIPS32_r2_s(multu, 44, 0, 0, 0x80000000, 0x7FFFFFFF, 0x3FFFFFFF, 0x80000000); + DO_MIPS32_r2_s(multu, 45, 0, 0, 0x80000000, 0x80000000, 0x40000000, 0x00000000); + DO_MIPS32_r2_s(multu, 46, 0, 0, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF, 0x80000000); + DO_MIPS32_r2_s(multu, 47, 0, 0, 0xFFFFFFFF, 0x7FFFFFFF, 0x7FFFFFFE, 0x80000001); + DO_MIPS32_r2_s(multu, 48, 0, 0, 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF, 0x80000000); + DO_MIPS32_r2_s(multu, 49, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/slt.c b/tests/tcg/mips/user/isa/mips32/arithmatic/slt.c new file mode 100644 index 0000000000..74f22c365e --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/slt.c @@ -0,0 +1,61 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r(slt, 0, 0x00000000, 0x00000000, 0); + DO_MIPS32_r(slt, 1, 0x00000001, 0x00000001, 0); + DO_MIPS32_r(slt, 2, 0x00000002, 0x00000003, 1); + DO_MIPS32_r(slt, 3, 0x00000005, 0x00000007, 1); + DO_MIPS32_r(slt, 4, 0x0000000B, 0x0000000F, 1); + DO_MIPS32_r(slt, 5, 0x00000017, 0x0000001F, 1); + DO_MIPS32_r(slt, 6, 0x0000002F, 0x0000003F, 1); + DO_MIPS32_r(slt, 7, 0x0000005F, 0x0000007F, 1); + DO_MIPS32_r(slt, 8, 0x000000BF, 0x000000FF, 1); + DO_MIPS32_r(slt, 9, 0x0000017F, 0x000001FF, 1); + DO_MIPS32_r(slt, 10, 0x000002FF, 0x000003FF, 1); + DO_MIPS32_r(slt, 11, 0x000005FF, 0x000007FF, 1); + DO_MIPS32_r(slt, 12, 0x00000BFF, 0x00000FFF, 1); + DO_MIPS32_r(slt, 13, 0x000017FF, 0x00001FFF, 1); + DO_MIPS32_r(slt, 14, 0x00002FFF, 0x00003FFF, 1); + DO_MIPS32_r(slt, 15, 0x00005FFF, 0x00007FFF, 1); + DO_MIPS32_r(slt, 16, 0x0000BFFF, 0x0000FFFF, 1); + DO_MIPS32_r(slt, 17, 0x00017FFF, 0x0001FFFF, 1); + DO_MIPS32_r(slt, 18, 0x0002FFFF, 0x0003FFFF, 1); + DO_MIPS32_r(slt, 19, 0x0005FFFF, 0x0007FFFF, 1); + DO_MIPS32_r(slt, 20, 0x000BFFFF, 0x000FFFFF, 1); + DO_MIPS32_r(slt, 21, 0x0017FFFF, 0x001FFFFF, 1); + DO_MIPS32_r(slt, 22, 0x002FFFFF, 0x003FFFFF, 1); + DO_MIPS32_r(slt, 23, 0x005FFFFF, 0x007FFFFF, 1); + DO_MIPS32_r(slt, 24, 0x00BFFFFF, 0x00FFFFFF, 1); + DO_MIPS32_r(slt, 25, 0x017FFFFF, 0x01FFFFFF, 1); + DO_MIPS32_r(slt, 26, 0x02FFFFFF, 0x03FFFFFF, 1); + DO_MIPS32_r(slt, 27, 0x05FFFFFF, 0x07FFFFFF, 1); + DO_MIPS32_r(slt, 28, 0x0BFFFFFF, 0x0FFFFFFF, 1); + DO_MIPS32_r(slt, 29, 0x17FFFFFF, 0x1FFFFFFF, 1); + DO_MIPS32_r(slt, 30, 0x2FFFFFFF, 0x3FFFFFFF, 1); + DO_MIPS32_r(slt, 31, 0x5FFFFFFF, 0x7FFFFFFF, 1); + DO_MIPS32_r(slt, 32, 0xBFFFFFFF, 0xFFFFFFFF, 1); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/slti.c b/tests/tcg/mips/user/isa/mips32/arithmatic/slti.c new file mode 100644 index 0000000000..823af3e4d4 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/slti.c @@ -0,0 +1,48 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_i(slti, 0, 0x0000, 0x00000000, 0); + DO_MIPS32_i(slti, 1, 0x0001, 0x00000001, 0); + DO_MIPS32_i(slti, 2, 0x0003, 0x00000002, 1); + DO_MIPS32_i(slti, 3, 0x0007, 0x00000005, 1); + DO_MIPS32_i(slti, 4, 0x000F, 0x0000000B, 1); + DO_MIPS32_i(slti, 5, 0x001F, 0x00000017, 1); + DO_MIPS32_i(slti, 6, 0x003F, 0x0000002F, 1); + DO_MIPS32_i(slti, 7, 0x007F, 0x0000005F, 1); + DO_MIPS32_i(slti, 8, 0x00FF, 0x000000BF, 1); + DO_MIPS32_i(slti, 9, 0x01FF, 0x0000017F, 1); + DO_MIPS32_i(slti, 10, 0x03FF, 0x000002FF, 1); + DO_MIPS32_i(slti, 11, 0x07FF, 0x000005FF, 1); + DO_MIPS32_i(slti, 12, 0x0FFF, 0x00000BFF, 1); + DO_MIPS32_i(slti, 13, 0x1FFF, 0x000017FF, 1); + DO_MIPS32_i(slti, 14, 0x3FFF, 0x00002FFF, 1); + DO_MIPS32_i(slti, 15, 0x7FFF, 0x00005FFF, 1); + DO_MIPS32_i(slti, 16, 0xFFFF, 0x0000BFFF, 0); + DO_MIPS32_i(slti, 17, 0xFFFF, 0x7FFFFFFF, 0); + DO_MIPS32_i(slti, 18, 0x8000, 0x7FFFFFFF, 0); + DO_MIPS32_i(slti, 19, 0x5555, 0x00000000, 1); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/sltiu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/sltiu.c new file mode 100644 index 0000000000..5644d4d1c1 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/sltiu.c @@ -0,0 +1,48 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_i(sltiu, 0, 0x0000, 0x00000000, 0); + DO_MIPS32_i(sltiu, 1, 0x0001, 0x00000001, 0); + DO_MIPS32_i(sltiu, 2, 0x0003, 0x00000002, 1); + DO_MIPS32_i(sltiu, 3, 0x0007, 0x00000005, 1); + DO_MIPS32_i(sltiu, 4, 0x000F, 0x0000000B, 1); + DO_MIPS32_i(sltiu, 5, 0x001F, 0x00000017, 1); + DO_MIPS32_i(sltiu, 6, 0x003F, 0x0000002F, 1); + DO_MIPS32_i(sltiu, 7, 0x007F, 0x0000005F, 1); + DO_MIPS32_i(sltiu, 8, 0x00FF, 0x000000BF, 1); + DO_MIPS32_i(sltiu, 9, 0x01FF, 0x0000017F, 1); + DO_MIPS32_i(sltiu, 10, 0x03FF, 0x000002FF, 1); + DO_MIPS32_i(sltiu, 11, 0x07FF, 0x000005FF, 1); + DO_MIPS32_i(sltiu, 12, 0x0FFF, 0x00000BFF, 1); + DO_MIPS32_i(sltiu, 13, 0x1FFF, 0x000017FF, 1); + DO_MIPS32_i(sltiu, 14, 0x3FFF, 0x00002FFF, 1); + DO_MIPS32_i(sltiu, 15, 0x7FFF, 0x00005FFF, 1); + DO_MIPS32_i(sltiu, 16, 0xFFFF, 0x0000BFFF, 1); + DO_MIPS32_i(sltiu, 17, 0x5555, 0x00000000, 1); + DO_MIPS32_i(sltiu, 18, 0xFFFF, 0x7FFFFFFF, 1); + DO_MIPS32_i(sltiu, 19, 0x8000, 0x7FFFFFFF, 1); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/sltu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/sltu.c new file mode 100644 index 0000000000..bba246626e --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/sltu.c @@ -0,0 +1,61 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r(sltu, 0, 0x00000000, 0x00000000, 0); + DO_MIPS32_r(sltu, 1, 0x00000001, 0x00000001, 0); + DO_MIPS32_r(sltu, 2, 0x00000002, 0x00000003, 1); + DO_MIPS32_r(sltu, 3, 0x00000005, 0x00000007, 1); + DO_MIPS32_r(sltu, 4, 0x0000000B, 0x0000000F, 1); + DO_MIPS32_r(sltu, 5, 0x00000017, 0x0000001F, 1); + DO_MIPS32_r(sltu, 6, 0x0000002F, 0x0000003F, 1); + DO_MIPS32_r(sltu, 7, 0x0000005F, 0x0000007F, 1); + DO_MIPS32_r(sltu, 8, 0x000000BF, 0x000000FF, 1); + DO_MIPS32_r(sltu, 9, 0x0000017F, 0x000001FF, 1); + DO_MIPS32_r(sltu, 10, 0x000002FF, 0x000003FF, 1); + DO_MIPS32_r(sltu, 11, 0x000005FF, 0x000007FF, 1); + DO_MIPS32_r(sltu, 12, 0x00000BFF, 0x00000FFF, 1); + DO_MIPS32_r(sltu, 13, 0x000017FF, 0x00001FFF, 1); + DO_MIPS32_r(sltu, 14, 0x00002FFF, 0x00003FFF, 1); + DO_MIPS32_r(sltu, 15, 0x00005FFF, 0x00007FFF, 1); + DO_MIPS32_r(sltu, 16, 0x0000BFFF, 0x0000FFFF, 1); + DO_MIPS32_r(sltu, 17, 0x00017FFF, 0x0001FFFF, 1); + DO_MIPS32_r(sltu, 18, 0x0002FFFF, 0x0003FFFF, 1); + DO_MIPS32_r(sltu, 19, 0x0005FFFF, 0x0007FFFF, 1); + DO_MIPS32_r(sltu, 20, 0x000BFFFF, 0x000FFFFF, 1); + DO_MIPS32_r(sltu, 21, 0x0017FFFF, 0x001FFFFF, 1); + DO_MIPS32_r(sltu, 22, 0x002FFFFF, 0x003FFFFF, 1); + DO_MIPS32_r(sltu, 23, 0x005FFFFF, 0x007FFFFF, 1); + DO_MIPS32_r(sltu, 24, 0x00BFFFFF, 0x00FFFFFF, 1); + DO_MIPS32_r(sltu, 25, 0x017FFFFF, 0x01FFFFFF, 1); + DO_MIPS32_r(sltu, 26, 0x02FFFFFF, 0x03FFFFFF, 1); + DO_MIPS32_r(sltu, 27, 0x05FFFFFF, 0x07FFFFFF, 1); + DO_MIPS32_r(sltu, 28, 0x0BFFFFFF, 0x0FFFFFFF, 1); + DO_MIPS32_r(sltu, 29, 0x17FFFFFF, 0x1FFFFFFF, 1); + DO_MIPS32_r(sltu, 30, 0x2FFFFFFF, 0x3FFFFFFF, 1); + DO_MIPS32_r(sltu, 31, 0x5FFFFFFF, 0x7FFFFFFF, 1); + DO_MIPS32_r(sltu, 32, 0xBFFFFFFF, 0xFFFFFFFF, 1); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/sub.c b/tests/tcg/mips/user/isa/mips32/arithmatic/sub.c new file mode 100644 index 0000000000..86f747c2e7 --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/sub.c @@ -0,0 +1,104 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r(sub, 0, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r(sub, 1, 0x00000001, 0x00000001, 0x00000000); + DO_MIPS32_r(sub, 2, 0x00000002, 0x00000003, 0xFFFFFFFF); + DO_MIPS32_r(sub, 3, 0x00000004, 0x00000006, 0xFFFFFFFE); + DO_MIPS32_r(sub, 4, 0x00000008, 0x0000000C, 0xFFFFFFFC); + DO_MIPS32_r(sub, 5, 0x00000010, 0x00000018, 0xFFFFFFF8); + DO_MIPS32_r(sub, 6, 0x00000020, 0x00000030, 0xFFFFFFF0); + DO_MIPS32_r(sub, 7, 0x00000040, 0x00000060, 0xFFFFFFE0); + DO_MIPS32_r(sub, 8, 0x00000080, 0x000000C0, 0xFFFFFFC0); + DO_MIPS32_r(sub, 9, 0x00000100, 0x00000180, 0xFFFFFF80); + DO_MIPS32_r(sub, 10, 0x00000200, 0x00000300, 0xFFFFFF00); + DO_MIPS32_r(sub, 11, 0x00000400, 0x00000600, 0xFFFFFE00); + DO_MIPS32_r(sub, 12, 0x00000800, 0x00000C00, 0xFFFFFC00); + DO_MIPS32_r(sub, 13, 0x00001000, 0x00001800, 0xFFFFF800); + DO_MIPS32_r(sub, 14, 0x00002000, 0x00003000, 0xFFFFF000); + DO_MIPS32_r(sub, 15, 0x00004000, 0x00006000, 0xFFFFE000); + DO_MIPS32_r(sub, 16, 0x00008000, 0x0000C000, 0xFFFFC000); + DO_MIPS32_r(sub, 17, 0x00010000, 0x00018000, 0xFFFF8000); + DO_MIPS32_r(sub, 18, 0x00020000, 0x00030000, 0xFFFF0000); + DO_MIPS32_r(sub, 19, 0x00040000, 0x00060000, 0xFFFE0000); + DO_MIPS32_r(sub, 20, 0x00080000, 0x000C0000, 0xFFFC0000); + DO_MIPS32_r(sub, 21, 0x00100000, 0x00180000, 0xFFF80000); + DO_MIPS32_r(sub, 22, 0x00200000, 0x00300000, 0xFFF00000); + DO_MIPS32_r(sub, 23, 0x00400000, 0x00600000, 0xFFE00000); + DO_MIPS32_r(sub, 24, 0x00800000, 0x00C00000, 0xFFC00000); + DO_MIPS32_r(sub, 25, 0x01000000, 0x01800000, 0xFF800000); + DO_MIPS32_r(sub, 26, 0x02000000, 0x03000000, 0xFF000000); + DO_MIPS32_r(sub, 27, 0x04000000, 0x06000000, 0xFE000000); + DO_MIPS32_r(sub, 28, 0x08000000, 0x0C000000, 0xFC000000); + DO_MIPS32_r(sub, 29, 0x10000000, 0x18000000, 0xF8000000); + DO_MIPS32_r(sub, 30, 0x20000000, 0x30000000, 0xF0000000); + DO_MIPS32_r(sub, 31, 0x40000000, 0x60000000, 0xE0000000); + DO_MIPS32_r(sub, 32, 0x80000000, 0xC0000000, 0xC0000000); + DO_MIPS32_r(sub, 33, 0x00000000, 0x80000000, 0x80000000); + DO_MIPS32_r(sub, 34, 0x80000001, 0x80000001, 0x00000000); + DO_MIPS32_r(sub, 35, 0xC0000003, 0x40000002, 0x80000001); + DO_MIPS32_r(sub, 36, 0xE0000007, 0x20000004, 0xC0000003); + DO_MIPS32_r(sub, 37, 0xF000000F, 0x10000008, 0xE0000007); + DO_MIPS32_r(sub, 38, 0xF800001F, 0x08000010, 0xF000000F); + DO_MIPS32_r(sub, 39, 0xFC00003F, 0x04000020, 0xF800001F); + DO_MIPS32_r(sub, 40, 0xFE00007F, 0x02000040, 0xFC00003F); + DO_MIPS32_r(sub, 41, 0xFF0000FF, 0x01000080, 0xFE00007F); + DO_MIPS32_r(sub, 42, 0xFF8001FF, 0x00800100, 0xFF0000FF); + DO_MIPS32_r(sub, 43, 0xFFC003FF, 0x00400200, 0xFF8001FF); + DO_MIPS32_r(sub, 44, 0xFFE007FF, 0x00200400, 0xFFC003FF); + DO_MIPS32_r(sub, 45, 0xFFF00FFF, 0x00100800, 0xFFE007FF); + DO_MIPS32_r(sub, 46, 0xFFF81FFF, 0x00081000, 0xFFF00FFF); + DO_MIPS32_r(sub, 47, 0xFFFC3FFF, 0x00042000, 0xFFF81FFF); + DO_MIPS32_r(sub, 48, 0xFFFE7FFF, 0x00024000, 0xFFFC3FFF); + DO_MIPS32_r(sub, 49, 0xFFFFFFFF, 0x00018000, 0xFFFE7FFF); + DO_MIPS32_r(sub, 50, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF); + DO_MIPS32_r(sub, 51, 0xFFFFFFFF, 0x00018000, 0xFFFE7FFF); + DO_MIPS32_r(sub, 52, 0xFFFE7FFF, 0x0003C000, 0xFFFABFFF); + DO_MIPS32_r(sub, 53, 0xFFFC3FFF, 0x0007E000, 0xFFF45FFF); + DO_MIPS32_r(sub, 54, 0xFFF81FFF, 0x000FF000, 0xFFE82FFF); + DO_MIPS32_r(sub, 55, 0xFFF00FFF, 0x001FF800, 0xFFD017FF); + DO_MIPS32_r(sub, 56, 0xFFE007FF, 0x003FFC00, 0xFFA00BFF); + DO_MIPS32_r(sub, 57, 0xFFC003FF, 0x007FFE00, 0xFF4005FF); + DO_MIPS32_r(sub, 58, 0xFF8001FF, 0x00FFFF00, 0xFE8002FF); + DO_MIPS32_r(sub, 59, 0xFF0000FF, 0x01FFFF80, 0xFD00017F); + DO_MIPS32_r(sub, 60, 0xFE00007F, 0x03FFFFC0, 0xFA0000BF); + DO_MIPS32_r(sub, 61, 0xFC00003F, 0x07FFFFE0, 0xF400005F); + DO_MIPS32_r(sub, 62, 0xF800001F, 0x0FFFFFF0, 0xE800002F); + DO_MIPS32_r(sub, 63, 0xF000000F, 0x1FFFFFF8, 0xD0000017); + DO_MIPS32_r(sub, 64, 0xE0000007, 0x3FFFFFFC, 0xA000000B); + DO_MIPS32_r(sub, 65, 0xC0000003, 0x7FFFFFFE, 0x40000005); + DO_MIPS32_r(sub, 66, 0x80000001, 0xFFFFFFFF, 0x80000002); + DO_MIPS32_r(sub, 67, 0x00000000, 0xFFFFFFFF, 0x00000001); + DO_MIPS32_r(sub, 68, 0x00000000, 0x55555555, 0xAAAAAAAB); + DO_MIPS32_r(sub, 69, 0x55555555, 0x55555555, 0x00000000); + DO_MIPS32_r(sub, 70, 0xAAAAAAAA, 0x15555555, 0x95555555); + DO_MIPS32_r(sub, 71, 0xFFFFFFFF, 0x55555555, 0xAAAAAAAA); + DO_MIPS32_r(sub, 72, 0xAAAAAAAA, 0x00000000, 0xAAAAAAAA); + DO_MIPS32_r(sub, 73, 0xAAAAAAAA, 0x15555555, 0x95555555); + DO_MIPS32_r(sub, 74, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000); + DO_MIPS32_r(sub, 75, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAB); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/subu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/subu.c new file mode 100644 index 0000000000..fe1df6a71e --- /dev/null +++ b/tests/tcg/mips/user/isa/mips32/arithmatic/subu.c @@ -0,0 +1,108 @@ +/* + * MIPS instruction test case + * + * Copyright (c) 2022 Jiaxun Yang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include +#include + +#include "../../../../include/test_utils_32.h" + +int main(void) +{ + int ret = 0; + int pass_count = 0; + int fail_count = 0; + + DO_MIPS32_r(subu, 0, 0x00000000, 0x00000000, 0x00000000); + DO_MIPS32_r(subu, 1, 0x00000001, 0x00000001, 0x00000000); + DO_MIPS32_r(subu, 2, 0x00000002, 0x00000003, 0xFFFFFFFF); + DO_MIPS32_r(subu, 3, 0x00000004, 0x00000006, 0xFFFFFFFE); + DO_MIPS32_r(subu, 4, 0x00000008, 0x0000000C, 0xFFFFFFFC); + DO_MIPS32_r(subu, 5, 0x00000010, 0x00000018, 0xFFFFFFF8); + DO_MIPS32_r(subu, 6, 0x00000020, 0x00000030, 0xFFFFFFF0); + DO_MIPS32_r(subu, 7, 0x00000040, 0x00000060, 0xFFFFFFE0); + DO_MIPS32_r(subu, 8, 0x00000080, 0x000000C0, 0xFFFFFFC0); + DO_MIPS32_r(subu, 9, 0x00000100, 0x00000180, 0xFFFFFF80); + DO_MIPS32_r(subu, 10, 0x00000200, 0x00000300, 0xFFFFFF00); + DO_MIPS32_r(subu, 11, 0x00000400, 0x00000600, 0xFFFFFE00); + DO_MIPS32_r(subu, 12, 0x00000800, 0x00000C00, 0xFFFFFC00); + DO_MIPS32_r(subu, 13, 0x00001000, 0x00001800, 0xFFFFF800); + DO_MIPS32_r(subu, 14, 0x00002000, 0x00003000, 0xFFFFF000); + DO_MIPS32_r(subu, 15, 0x00004000, 0x00006000, 0xFFFFE000); + DO_MIPS32_r(subu, 16, 0x00008000, 0x0000C000, 0xFFFFC000); + DO_MIPS32_r(subu, 17, 0x00010000, 0x00018000, 0xFFFF8000); + DO_MIPS32_r(subu, 18, 0x00020000, 0x00030000, 0xFFFF0000); + DO_MIPS32_r(subu, 19, 0x00040000, 0x00060000, 0xFFFE0000); + DO_MIPS32_r(subu, 20, 0x00080000, 0x000C0000, 0xFFFC0000); + DO_MIPS32_r(subu, 21, 0x00100000, 0x00180000, 0xFFF80000); + DO_MIPS32_r(subu, 22, 0x00200000, 0x00300000, 0xFFF00000); + DO_MIPS32_r(subu, 23, 0x00400000, 0x00600000, 0xFFE00000); + DO_MIPS32_r(subu, 24, 0x00800000, 0x00C00000, 0xFFC00000); + DO_MIPS32_r(subu, 25, 0x01000000, 0x01800000, 0xFF800000); + DO_MIPS32_r(subu, 26, 0x02000000, 0x03000000, 0xFF000000); + DO_MIPS32_r(subu, 27, 0x04000000, 0x06000000, 0xFE000000); + DO_MIPS32_r(subu, 28, 0x08000000, 0x0C000000, 0xFC000000); + DO_MIPS32_r(subu, 29, 0x10000000, 0x18000000, 0xF8000000); + DO_MIPS32_r(subu, 30, 0x20000000, 0x30000000, 0xF0000000); + DO_MIPS32_r(subu, 31, 0x40000000, 0x60000000, 0xE0000000); + DO_MIPS32_r(subu, 32, 0x80000000, 0xC0000000, 0xC0000000); + DO_MIPS32_r(subu, 33, 0x00000000, 0x80000000, 0x80000000); + DO_MIPS32_r(subu, 34, 0x80000001, 0x80000001, 0x00000000); + DO_MIPS32_r(subu, 35, 0xC0000003, 0x40000002, 0x80000001); + DO_MIPS32_r(subu, 36, 0xE0000007, 0x20000004, 0xC0000003); + DO_MIPS32_r(subu, 37, 0xF000000F, 0x10000008, 0xE0000007); + DO_MIPS32_r(subu, 38, 0xF800001F, 0x08000010, 0xF000000F); + DO_MIPS32_r(subu, 39, 0xFC00003F, 0x04000020, 0xF800001F); + DO_MIPS32_r(subu, 40, 0xFE00007F, 0x02000040, 0xFC00003F); + DO_MIPS32_r(subu, 41, 0xFF0000FF, 0x01000080, 0xFE00007F); + DO_MIPS32_r(subu, 42, 0xFF8001FF, 0x00800100, 0xFF0000FF); + DO_MIPS32_r(subu, 43, 0xFFC003FF, 0x00400200, 0xFF8001FF); + DO_MIPS32_r(subu, 44, 0xFFE007FF, 0x00200400, 0xFFC003FF); + DO_MIPS32_r(subu, 45, 0xFFF00FFF, 0x00100800, 0xFFE007FF); + DO_MIPS32_r(subu, 46, 0xFFF81FFF, 0x00081000, 0xFFF00FFF); + DO_MIPS32_r(subu, 47, 0xFFFC3FFF, 0x00042000, 0xFFF81FFF); + DO_MIPS32_r(subu, 48, 0xFFFE7FFF, 0x00024000, 0xFFFC3FFF); + DO_MIPS32_r(subu, 49, 0xFFFFFFFF, 0x00018000, 0xFFFE7FFF); + DO_MIPS32_r(subu, 50, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF); + DO_MIPS32_r(subu, 51, 0xFFFFFFFF, 0x00018000, 0xFFFE7FFF); + DO_MIPS32_r(subu, 52, 0xFFFE7FFF, 0x0003C000, 0xFFFABFFF); + DO_MIPS32_r(subu, 53, 0xFFFC3FFF, 0x0007E000, 0xFFF45FFF); + DO_MIPS32_r(subu, 54, 0xFFF81FFF, 0x000FF000, 0xFFE82FFF); + DO_MIPS32_r(subu, 55, 0xFFF00FFF, 0x001FF800, 0xFFD017FF); + DO_MIPS32_r(subu, 56, 0xFFE007FF, 0x003FFC00, 0xFFA00BFF); + DO_MIPS32_r(subu, 57, 0xFFC003FF, 0x007FFE00, 0xFF4005FF); + DO_MIPS32_r(subu, 58, 0xFF8001FF, 0x00FFFF00, 0xFE8002FF); + DO_MIPS32_r(subu, 59, 0xFF0000FF, 0x01FFFF80, 0xFD00017F); + DO_MIPS32_r(subu, 60, 0xFE00007F, 0x03FFFFC0, 0xFA0000BF); + DO_MIPS32_r(subu, 61, 0xFC00003F, 0x07FFFFE0, 0xF400005F); + DO_MIPS32_r(subu, 62, 0xF800001F, 0x0FFFFFF0, 0xE800002F); + DO_MIPS32_r(subu, 63, 0xF000000F, 0x1FFFFFF8, 0xD0000017); + DO_MIPS32_r(subu, 64, 0xE0000007, 0x3FFFFFFC, 0xA000000B); + DO_MIPS32_r(subu, 65, 0xC0000003, 0x7FFFFFFE, 0x40000005); + DO_MIPS32_r(subu, 66, 0x80000001, 0xFFFFFFFF, 0x80000002); + DO_MIPS32_r(subu, 67, 0x00000000, 0xFFFFFFFF, 0x00000001); + DO_MIPS32_r(subu, 68, 0x00000000, 0x55555555, 0xAAAAAAAB); + DO_MIPS32_r(subu, 69, 0x55555555, 0x55555555, 0x00000000); + DO_MIPS32_r(subu, 70, 0xAAAAAAAA, 0x55555555, 0x55555555); + DO_MIPS32_r(subu, 71, 0xFFFFFFFF, 0x55555555, 0xAAAAAAAA); + DO_MIPS32_r(subu, 72, 0xAAAAAAAA, 0x00000000, 0xAAAAAAAA); + DO_MIPS32_r(subu, 73, 0xAAAAAAAA, 0x55555555, 0x55555555); + DO_MIPS32_r(subu, 74, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000); + DO_MIPS32_r(subu, 75, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAB); + DO_MIPS32_r(subu, 76, 0x7FFFFFFF, 0xFFFFFFFF, 0x80000000); + DO_MIPS32_r(subu, 77, 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF); + DO_MIPS32_r(subu, 78, 0x80000000, 0x00000001, 0x7FFFFFFF); + DO_MIPS32_r(subu, 79, 0x80000000, 0x7FFFFFFF, 0x00000001); + + printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count); + + if (fail_count) { + ret = -1; + } + + return ret; +} From patchwork Mon Oct 24 15:23:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 1693984 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=flygoat.com header.i=@flygoat.com header.a=rsa-sha256 header.s=fm1 header.b=QnAcuw7o; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=kHfi8Zvl; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Mx2Fs1NhDz23js for ; Tue, 25 Oct 2022 04:32:32 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1omzJC-0003hG-Gr; Mon, 24 Oct 2022 11:24:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJA-0003gk-Sz for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:08 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJ6-0008Gq-FX for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:08 -0400 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.west.internal (Postfix) with ESMTP id DEF1C3200900; Mon, 24 Oct 2022 11:24:02 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Mon, 24 Oct 2022 11:24:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flygoat.com; h= cc:cc:content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; t=1666625042; x=1666711442; bh=dB 23Dg1lmVTY4K9IwqHQeJHSPxvaBGn1OUb6/mWTYgg=; b=QnAcuw7opexXs2rdTO WggJvB8Bo/yPWlPsByblSqm3usIuYzK0vbCCMIBrLV5fI68RB1SypzO+ol/SaMy1 v1xz9NQPkBubMm1AL7FIYJiWg0E1qwEYJW5sA3HX+XcI1XMwhmgyVp3eoXs3QYvi x6SNmaBAmtbb0shFp04C1/kZrVNJqUaXr2OU3uHA8j4+MRRhhZ70qk2GKcJObgeJ IyfpQI0uMwV6J1VSC+0Tk6p0NejnxRfzC9IhmjZ3HpZ+yKQC3otFlh9c9P6WLwKd knD8iEFSxJZ1fGCJ+LQgHVD2oH7DnxygSef4Afru9+H8H2Gv9wKF1jaNe4+EODHd k1dg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; t=1666625042; x=1666711442; bh=dB23Dg1lmVTY4 K9IwqHQeJHSPxvaBGn1OUb6/mWTYgg=; b=kHfi8Zvl0oNC6qYDQcsrJj7TKqbqH vAbTjpFQTQ3ZrPlhz0yt7Cuam8mT5qAVYh5QvuL65rStiuP7Rirf0oPKneEzLAMW UgSNNhRpX45UA8q9BSXCeq7a+OheEc+DLuZMlThKc1YlYxSC1fW+fVhNIK3EhjJm JedX2r+KByaR4Vtr1HJgVJs96FTeuTCjowIagsiUVbcq3L8L1paA0USqu5p522mS bdIQHWRD4/as49VZtZ79o/1k1zRa3/m/2gvf5bYIcZJ/jbf/A707fBDVufFQ5wZu I+xqg4aSA7CBmYA+6UnuIcni9UUCt0GhX3l7gph0l046I2apugmm6jL2w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrgedtgedgkeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeflihgrgihunhcujggrnhhguceojhhirgiguhhnrdihrghn ghesfhhlhihgohgrthdrtghomheqnecuggftrfgrthhtvghrnhepfeeludefheegvdeuvd dvgeekgfdvtdettdelieeihfegtedugeekhfdvhfejfedtnecuvehluhhsthgvrhfuihii vgeptdenucfrrghrrghmpehmrghilhhfrhhomhepjhhirgiguhhnrdihrghnghesfhhlhi hgohgrthdrtghomh X-ME-Proxy: Feedback-ID: ifd894703:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 24 Oct 2022 11:24:01 -0400 (EDT) From: Jiaxun Yang To: qemu-devel@nongnu.org Cc: f4bug@amsat.org, richard.henderson@linaro.org, Jiaxun Yang Subject: [PATCH 4/6] target/mips: Split Loongson extention translation into standalone file Date: Mon, 24 Oct 2022 16:23:47 +0100 Message-Id: <20221024152349.215135-5-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221024152349.215135-1-jiaxun.yang@flygoat.com> References: <20221024152349.215135-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.19; envelope-from=jiaxun.yang@flygoat.com; helo=wout3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Qemu-devel" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org So we can do decodetree translation for those exts alone. Signed-off-by: Jiaxun Yang --- target/mips/tcg/loongson_translate.c | 1290 +++++++++++++++++++++ target/mips/tcg/meson.build | 1 + target/mips/tcg/translate.c | 1577 ++++---------------------- target/mips/tcg/translate.h | 6 + 4 files changed, 1493 insertions(+), 1381 deletions(-) create mode 100644 target/mips/tcg/loongson_translate.c diff --git a/target/mips/tcg/loongson_translate.c b/target/mips/tcg/loongson_translate.c new file mode 100644 index 0000000000..efeb1d6e28 --- /dev/null +++ b/target/mips/tcg/loongson_translate.c @@ -0,0 +1,1290 @@ +/* + * Loongson EXT and MMI translation routines. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This code is licensed under the LGPL v2.1 or later. + */ + +#include "qemu/osdep.h" +#include "tcg/tcg-op.h" +#include "tcg/tcg-op-gvec.h" +#include "exec/helper-gen.h" +#include "translate.h" + +enum { + OPC_CP2 = (0x12 << 26), + OPC_SPECIAL2 = (0x1C << 26), + OPC_SPECIAL3 = (0x1F << 26), + OPC_LWC2 = (0x32 << 26), + OPC_LDC2 = (0x36 << 26), + OPC_SWC2 = (0x3A << 26), + OPC_SDC2 = (0x3E << 26), +}; + +/* Special2 opcodes */ +#define MASK_2F_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F)) + +enum { + 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, +}; + +/* Special3 opcodes */ +#define MASK_2E_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F)) +enum { + /* Loongson 2E */ + OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3, + OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3, + OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3, + OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3, + OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3, + OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3, + OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3, + OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3, + OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3, + OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3, + OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3, + OPC_DMODU_G_2E = 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, +}; + +#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, +}; + +/* 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); +} + +/* 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"); + gen_reserved_instruction(ctx); + 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) +{ + 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_TEUQ | + 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_TEUQ | + 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_TEUQ | + 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_TEUQ | + 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_TEUQ | + 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_TEUQ | + 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_TEUQ | + 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_TEUQ | + 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); + if (!cpu_is_bigendian(ctx)) { + tcg_gen_xori_tl(t1, t1, 3); + } + 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); + if (cpu_is_bigendian(ctx)) { + tcg_gen_xori_tl(t1, t1, 3); + } + 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); + if (!cpu_is_bigendian(ctx)) { + tcg_gen_xori_tl(t1, t1, 7); + } + 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_TEUQ); + 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); + if (cpu_is_bigendian(ctx)) { + tcg_gen_xori_tl(t1, t1, 7); + } + 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_TEUQ); + 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"); + gen_reserved_instruction(ctx); + 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"); + gen_reserved_instruction(ctx); + break; + } + break; + default: + MIPS_INVAL("loongson_gslsq"); + gen_reserved_instruction(ctx); + 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"); + gen_reserved_instruction(ctx); + 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_TEUQ | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; +#endif + case OPC_GSLWXC1: + 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: + 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_TEUQ | + 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_TEUQ | + 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_TEUQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + default: + break; + } + + tcg_temp_free(t0); +} + +bool decode_ext_loongson2e(DisasContext *ctx, uint32_t insn) +{ + int rs, rt, rd; + uint32_t op; + + op = MASK_2E_SPECIAL3(insn); + rs = (insn >> 21) & 0x1f; + rt = (insn >> 16) & 0x1f; + rd = (insn >> 11) & 0x1f; + + switch (op) { + case OPC_DIV_G_2E: + case OPC_DIVU_G_2E: + case OPC_MOD_G_2E: + case OPC_MODU_G_2E: + case OPC_MULT_G_2E: + case OPC_MULTU_G_2E: + gen_loongson_integer(ctx, op, rd, rs, rt); + return true; +#if defined(TARGET_MIPS64) + case OPC_DDIV_G_2E: + case OPC_DDIVU_G_2E: + case OPC_DMULT_G_2E: + case OPC_DMULTU_G_2E: + case OPC_DMOD_G_2E: + case OPC_DMODU_G_2E: + gen_loongson_integer(ctx, op, rd, rs, rt); + return true; +#endif + default: + return false; + } +} + +bool decode_ext_loongson2f(DisasContext *ctx, uint32_t insn) +{ + int rs, rt, rd; + uint32_t op; + + op = MASK_2F_SPECIAL2(insn); + rs = (insn >> 21) & 0x1f; + rt = (insn >> 16) & 0x1f; + rd = (insn >> 11) & 0x1f; + + switch (op) { + case OPC_DIV_G_2F: + case OPC_DIVU_G_2F: + case OPC_MULT_G_2F: + case OPC_MULTU_G_2F: + case OPC_MOD_G_2F: + case OPC_MODU_G_2F: + gen_loongson_integer(ctx, op, rd, rs, rt); + return true; +#if defined(TARGET_MIPS64) + case OPC_DMULT_G_2F: + case OPC_DMULTU_G_2F: + case OPC_DDIV_G_2F: + case OPC_DDIVU_G_2F: + case OPC_DMOD_G_2F: + case OPC_DMODU_G_2F: + gen_loongson_integer(ctx, op, rd, rs, rt); + return true; +#endif + default: + return false; + } +} + +bool decode_ase_lext(DisasContext *ctx, uint32_t insn) +{ + int rs, rt, rd; + uint32_t op; + + op = MASK_OP_MAJOR(insn); + rs = (insn >> 21) & 0x1f; + rt = (insn >> 16) & 0x1f; + rd = (insn >> 11) & 0x1f; + + switch (op) { + case OPC_SPECIAL2: + /* LEXT inherits Loongson2F integer extensions */ + return decode_ext_loongson2f(ctx, insn); + case OPC_LWC2: + case OPC_SWC2: + gen_loongson_lswc2(ctx, rt, rs, rd); + return true; + case OPC_LDC2: + case OPC_SDC2: + gen_loongson_lsdc2(ctx, rt, rs, rd); + return true; + default: + return false; + } +} + +bool decode_ase_lmmi(DisasContext *ctx, uint32_t insn) +{ + int sa, rt, rd; + uint32_t op; + + op = MASK_OP_MAJOR(insn); + rt = (insn >> 16) & 0x1f; + rd = (insn >> 11) & 0x1f; + sa = (insn >> 6) & 0x1f; + + switch (op) { + case OPC_CP2: + gen_loongson_multimedia(ctx, sa, rd, rt); + return true; + default: + return false; + } +} diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build index 7a27fe93e0..a615cd81b6 100644 --- a/target/mips/tcg/meson.build +++ b/target/mips/tcg/meson.build @@ -14,6 +14,7 @@ mips_ss.add(files( 'fpu_helper.c', 'ldst_helper.c', 'lmmi_helper.c', + 'loongson_translate.c', 'msa_helper.c', 'msa_translate.c', 'op_helper.c', diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index bcb267e6bd..d398b2f44d 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -332,19 +332,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, @@ -373,20 +360,6 @@ enum { OPC_RDHWR = 0x3B | OPC_SPECIAL3, OPC_GINV = 0x3D | OPC_SPECIAL3, - /* Loongson 2E */ - OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3, - OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3, - OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3, - OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3, - OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3, - OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3, - OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3, - OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3, - OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3, - OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3, - 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 */ @@ -394,8 +367,7 @@ enum { 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_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 */ @@ -443,48 +415,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))) @@ -561,7 +491,6 @@ enum { 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 */ @@ -1002,103 +931,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 { @@ -3684,1163 +3516,184 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, gen_reserved_instruction(ctx); goto out; } - out: - tcg_temp_free(t0); - 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 MMI_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 MMI_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 MMI_OPC_MADD1: - acc = 1; - /* Fall through */ - case MMI_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 MMI_OPC_MADDU1: - acc = 1; - /* Fall through */ - case MMI_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"); - gen_reserved_instruction(ctx); - goto out; - } - - out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -static void gen_cl(DisasContext *ctx, uint32_t opc, - int rd, int rs) -{ - TCGv t0; - - if (rd == 0) { - /* Treat as NOP. */ - return; - } - t0 = cpu_gpr[rd]; - gen_load_gpr(t0, rs); - - switch (opc) { - case OPC_CLO: - case R6_OPC_CLO: -#if defined(TARGET_MIPS64) - case OPC_DCLO: - case R6_OPC_DCLO: -#endif - tcg_gen_not_tl(t0, t0); - break; - } - - switch (opc) { - case OPC_CLO: - case R6_OPC_CLO: - case OPC_CLZ: - case R6_OPC_CLZ: - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS); - tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32); - break; -#if defined(TARGET_MIPS64) - case OPC_DCLO: - case R6_OPC_DCLO: - case OPC_DCLZ: - case R6_OPC_DCLZ: - tcg_gen_clzi_i64(t0, t0, 64); - break; -#endif - } -} - -/* 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); -} - -/* 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"); - gen_reserved_instruction(ctx); - 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) -{ - 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_TEUQ | - 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_TEUQ | - 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_TEUQ | - 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_TEUQ | - 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_TEUQ | - 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_TEUQ | - 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_TEUQ | - 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_TEUQ | - 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); - if (!cpu_is_bigendian(ctx)) { - tcg_gen_xori_tl(t1, t1, 3); - } - 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); - if (cpu_is_bigendian(ctx)) { - tcg_gen_xori_tl(t1, t1, 3); - } - 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); - if (!cpu_is_bigendian(ctx)) { - tcg_gen_xori_tl(t1, t1, 7); - } - 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_TEUQ); - 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); - if (cpu_is_bigendian(ctx)) { - tcg_gen_xori_tl(t1, t1, 7); - } - 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_TEUQ); - 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"); - gen_reserved_instruction(ctx); - 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"); - gen_reserved_instruction(ctx); - break; - } - break; - default: - MIPS_INVAL("loongson_gslsq"); - gen_reserved_instruction(ctx); - break; - } + out: tcg_temp_free(t0); + tcg_temp_free(t1); } -/* Loongson EXT LDC2/SDC2 */ -static void gen_loongson_lsdc2(DisasContext *ctx, int rt, - int rs, int rd) +/* + * 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) { - int offset = sextract32(ctx->opcode, 3, 8); - uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode); - TCGv t0, t1; - TCGv_i32 fp0; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int acc = 0; + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); - /* Pre-conditions */ switch (opc) { - case OPC_GSLBX: - case OPC_GSLHX: - case OPC_GSLWX: - case OPC_GSLDX: - /* prefetch, implement as NOP */ - if (rt == 0) { - return; + case MMI_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_GSSBX: - case OPC_GSSHX: - case OPC_GSSWX: - case OPC_GSSDX: + case MMI_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_GSLWXC1: -#if defined(TARGET_MIPS64) - case OPC_GSLDXC1: -#endif - check_cp1_enabled(ctx); - /* prefetch, implement as NOP */ - if (rt == 0) { - return; + case MMI_OPC_MADD1: + acc = 1; + /* Fall through */ + case MMI_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_GSSWXC1: -#if defined(TARGET_MIPS64) - case OPC_GSSDXC1: -#endif - check_cp1_enabled(ctx); + case MMI_OPC_MADDU1: + acc = 1; + /* Fall through */ + case MMI_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("loongson_lsdc2"); + MIPS_INVAL("mul/madd TXx9"); gen_reserved_instruction(ctx); - return; - break; + goto out; } - t0 = tcg_temp_new(); + out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_cl(DisasContext *ctx, uint32_t opc, + int rd, int rs) +{ + TCGv t0; - gen_base_offset_addr(ctx, t0, rs, offset); - gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + if (rd == 0) { + /* Treat as NOP. */ + return; + } + t0 = cpu_gpr[rd]; + gen_load_gpr(t0, rs); 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_TEUQ | - ctx->default_tcg_memop_mask); - gen_store_gpr(t0, rt); - break; -#endif - case OPC_GSLWXC1: - 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; + case OPC_CLO: + case R6_OPC_CLO: #if defined(TARGET_MIPS64) - case OPC_GSLDXC1: - 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_TEUQ | - ctx->default_tcg_memop_mask); - gen_store_fpr64(ctx, t0, rt); - break; + case OPC_DCLO: + case R6_OPC_DCLO: #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_TEUQ | - ctx->default_tcg_memop_mask); - tcg_temp_free(t1); + tcg_gen_not_tl(t0, t0); 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); + } + + switch (opc) { + case OPC_CLO: + case R6_OPC_CLO: + case OPC_CLZ: + case R6_OPC_CLZ: + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS); + tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32); 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_TEUQ | - ctx->default_tcg_memop_mask); - tcg_temp_free(t1); + case OPC_DCLO: + case R6_OPC_DCLO: + case OPC_DCLZ: + case R6_OPC_DCLZ: + tcg_gen_clzi_i64(t0, t0, 64); break; #endif - default: - break; } - - tcg_temp_free(t0); } /* Traps */ @@ -12347,8 +11200,7 @@ static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2, gen_load_gpr(v2_t, v2); switch (op1) { - /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */ - case OPC_MULT_G_2E: + case OPC_ADDUH_QB_DSP: check_dsp_r2(ctx); switch (op2) { case OPC_ADDUH_QB: @@ -13042,11 +11894,7 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2, 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: + case OPC_ADDUH_QB_DSP: check_dsp_r2(ctx); switch (op2) { case OPC_MUL_PH: @@ -14413,15 +13261,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) case OPC_MUL: gen_arith(ctx, op1, rd, rs, rt); break; - case OPC_DIV_G_2F: - case OPC_DIVU_G_2F: - case OPC_MULT_G_2F: - case OPC_MULTU_G_2F: - case OPC_MOD_G_2F: - case OPC_MODU_G_2F: - check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT); - gen_loongson_integer(ctx, op1, rd, rs, rt); - break; case OPC_CLO: case OPC_CLZ: check_insn(ctx, ISA_MIPS_R1); @@ -14446,15 +13285,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) check_mips_64(ctx); gen_cl(ctx, op1, rd, rs); break; - case OPC_DMULT_G_2F: - case OPC_DMULTU_G_2F: - case OPC_DDIV_G_2F: - case OPC_DDIVU_G_2F: - case OPC_DMOD_G_2F: - case OPC_DMODU_G_2F: - check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT); - gen_loongson_integer(ctx, op1, rd, rs, rt); - break; #endif default: /* Invalid */ MIPS_INVAL("special2_legacy"); @@ -14587,48 +13417,33 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) op1 = MASK_SPECIAL3(ctx->opcode); switch (op1) { - case OPC_DIV_G_2E: - case OPC_DIVU_G_2E: - case OPC_MOD_G_2E: - case OPC_MODU_G_2E: - case OPC_MULT_G_2E: - case OPC_MULTU_G_2E: - /* - * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have - * the same mask and op1. - */ - if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) { - op2 = MASK_ADDUH_QB(ctx->opcode); - switch (op2) { - case OPC_ADDUH_QB: - case OPC_ADDUH_R_QB: - case OPC_ADDQH_PH: - case OPC_ADDQH_R_PH: - case OPC_ADDQH_W: - case OPC_ADDQH_R_W: - case OPC_SUBUH_QB: - case OPC_SUBUH_R_QB: - case OPC_SUBQH_PH: - case OPC_SUBQH_R_PH: - case OPC_SUBQH_W: - case OPC_SUBQH_R_W: - gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); - break; - case OPC_MUL_PH: - case OPC_MUL_S_PH: - case OPC_MULQ_S_W: - case OPC_MULQ_RS_W: - gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); - break; - default: - MIPS_INVAL("MASK ADDUH.QB"); - gen_reserved_instruction(ctx); - break; - } - } else if (ctx->insn_flags & INSN_LOONGSON2E) { - gen_loongson_integer(ctx, op1, rd, rs, rt); - } else { + case OPC_ADDUH_QB_DSP: + op2 = MASK_ADDUH_QB(ctx->opcode); + switch (op2) { + case OPC_ADDUH_QB: + case OPC_ADDUH_R_QB: + case OPC_ADDQH_PH: + case OPC_ADDQH_R_PH: + case OPC_ADDQH_W: + case OPC_ADDQH_R_W: + case OPC_SUBUH_QB: + case OPC_SUBUH_R_QB: + case OPC_SUBQH_PH: + case OPC_SUBQH_R_PH: + case OPC_SUBQH_W: + case OPC_SUBQH_R_W: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + case OPC_MUL_PH: + case OPC_MUL_S_PH: + case OPC_MULQ_S_W: + case OPC_MULQ_RS_W: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); + break; + default: + MIPS_INVAL("MASK ADDUH.QB"); gen_reserved_instruction(ctx); + break; } break; case OPC_LX_DSP: @@ -14858,15 +13673,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) } break; #if defined(TARGET_MIPS64) - case OPC_DDIV_G_2E: - case OPC_DDIVU_G_2E: - case OPC_DMULT_G_2E: - case OPC_DMULTU_G_2E: - case OPC_DMOD_G_2E: - case OPC_DMODU_G_2E: - check_insn(ctx, INSN_LOONGSON2E); - gen_loongson_integer(ctx, op1, rd, rs, rt); - break; case OPC_ABSQ_S_QH_DSP: op2 = MASK_ABSQ_S_QH(ctx->opcode); switch (op2) { @@ -15867,8 +14673,6 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) /* OPC_BC, OPC_BALC */ gen_compute_compact_branch(ctx, op, 0, 0, sextract32(ctx->opcode << 2, 0, 28)); - } else if (ctx->insn_flags & ASE_LEXT) { - gen_loongson_lswc2(ctx, rt, rs, rd); } else { /* OPC_LWC2, OPC_SWC2 */ /* COP2: Not implemented. */ @@ -15886,8 +14690,6 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) /* OPC_JIC, OPC_JIALC */ gen_compute_compact_branch(ctx, op, 0, rt, imm); } - } else if (ctx->insn_flags & ASE_LEXT) { - gen_loongson_lsdc2(ctx, rt, rs, rd); } else { /* OPC_LWC2, OPC_SWC2 */ /* COP2: Not implemented. */ @@ -15895,9 +14697,8 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) } break; case OPC_CP2: - check_insn(ctx, ASE_LMMI); - /* Note that these instructions use different fields. */ - gen_loongson_multimedia(ctx, sa, rd, rt); + MIPS_INVAL("cp2"); + gen_reserved_instruction(ctx); break; case OPC_CP3: @@ -16075,8 +14876,22 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) return; } #endif + if (cpu_supports_isa(env, INSN_LOONGSON2E) && + decode_ext_loongson2e(ctx, ctx->opcode)) { + return; + } + if (cpu_supports_isa(env, INSN_LOONGSON2F) && + decode_ext_loongson2f(ctx, ctx->opcode)) { + return; + } /* ISA extensions */ + if (cpu_supports_isa(env, ASE_LEXT) && decode_ase_lext(ctx, ctx->opcode)) { + return; + } + if (cpu_supports_isa(env, ASE_LMMI) && decode_ase_lmmi(ctx, ctx->opcode)) { + return; + } if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) { return; } diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index 980aa8682d..c5fd16e657 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -241,6 +241,12 @@ void msa_translate_init(void); void mxu_translate_init(void); bool decode_ase_mxu(DisasContext *ctx, uint32_t insn); +/* loongson */ +bool decode_ext_loongson2e(DisasContext *ctx, uint32_t insn); +bool decode_ext_loongson2f(DisasContext *ctx, uint32_t insn); +bool decode_ase_lext(DisasContext *ctx, uint32_t insn); +bool decode_ase_lmmi(DisasContext *ctx, uint32_t insn); + /* decodetree generated */ bool decode_isa_rel6(DisasContext *ctx, uint32_t insn); bool decode_ase_msa(DisasContext *ctx, uint32_t insn); From patchwork Mon Oct 24 15:23:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 1693979 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=flygoat.com header.i=@flygoat.com header.a=rsa-sha256 header.s=fm1 header.b=CUg4HRUm; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=czO//2p7; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Mx1Mt1008z23l7 for ; Tue, 25 Oct 2022 03:52:41 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1omzJD-0003hf-75; Mon, 24 Oct 2022 11:24:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJB-0003gu-JT for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:09 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJ8-0008H1-Ku for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:09 -0400 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.west.internal (Postfix) with ESMTP id 0BB923200645; Mon, 24 Oct 2022 11:24:04 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Mon, 24 Oct 2022 11:24:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flygoat.com; h= cc:cc:content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; t=1666625044; x=1666711444; bh=Jn N6ckhyHvg1hhYIM98Mcsqh5GRlzY5Jo27dbyH1B7E=; b=CUg4HRUmPaN1AbCrUH pFlw5Isrw+BqbfDHgF5SN7/plSYcWFbrEwKNtMmHOLWGGWNgfRYe0inZvp/V+pPj F7o4mfWKh7YpSOtGbRSWUydip9NmdWSfS8Iyqa+MOBcSE0RrOf1r5eeDXSVyRBUh bKY75w40fvwfwaUk5ompFgihhTYDeYMj6WQ8no66CYMeIYnnUFqtFRfzt5SCDBpF yEPOi0wNBDlXeD9NaNLEuSHNFMPrEO4HxcjMqaOF39ulPGUB+lRObnfecKFB2L6P 4thtky5tnQ0dwm920HgHWBCKRpe/+1ASyBii1ty/RQwgu6hHVubztEEspsPEtQIi /jsQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; t=1666625044; x=1666711444; bh=JnN6ckhyHvg1h hYIM98Mcsqh5GRlzY5Jo27dbyH1B7E=; b=czO//2p7u1UMfLCifTFgJfquESf2M KyNkirJpnVIkjRDX3PLi0tkJozaYnCkEt3ObvPHF2GgRG+OyfeaDmlfRyliiirQG afzE1DN4eErvP+hBo+XfRMmA8fSYVG2Z9IncKksoz0S1oD04SoCWN+brQcBk9wfr HBHmaHhplrLHT2jjj9it7hkngRwBmbg9kFTCKjgAbOdHmc5mq+Jytp3h5RKxXw6b Hhi6BWxKIcSX7vZgLsGDUjOHxJhwuF0UsqcOuGhKuenwJq4VGdgvdTcIDA3kpZrv TzzI4NbypXsGei8IcmzL9NUIWDOTFpKCJPjOMOvJowUfFlT7ym161M8KQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrgedtgedgkeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeflihgrgihunhcujggrnhhguceojhhirgiguhhnrdihrghn ghesfhhlhihgohgrthdrtghomheqnecuggftrfgrthhtvghrnhepfeeludefheegvdeuvd dvgeekgfdvtdettdelieeihfegtedugeekhfdvhfejfedtnecuvehluhhsthgvrhfuihii vgeptdenucfrrghrrghmpehmrghilhhfrhhomhepjhhirgiguhhnrdihrghnghesfhhlhi hgohgrthdrtghomh X-ME-Proxy: Feedback-ID: ifd894703:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 24 Oct 2022 11:24:03 -0400 (EDT) From: Jiaxun Yang To: qemu-devel@nongnu.org Cc: f4bug@amsat.org, richard.henderson@linaro.org, Jiaxun Yang Subject: [PATCH 5/6] target/mips: Move all tx79 instructions to decodetree Date: Mon, 24 Oct 2022 16:23:48 +0100 Message-Id: <20221024152349.215135-6-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221024152349.215135-1-jiaxun.yang@flygoat.com> References: <20221024152349.215135-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.19; envelope-from=jiaxun.yang@flygoat.com; helo=wout3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Qemu-devel" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Move MUL family instructions into decodetree. Also implement RDHWR emulation for user instructions in decodetree SQ translation. Signed-off-by: Jiaxun Yang --- target/mips/tcg/translate.c | 410 +------------------------------ target/mips/tcg/tx79.decode | 14 ++ target/mips/tcg/tx79_translate.c | 205 +++++++++++++++- 3 files changed, 219 insertions(+), 410 deletions(-) diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index d398b2f44d..c8a3f63203 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -956,82 +956,6 @@ enum { OPC_NMSUB_PS = 0x3E | OPC_CP3, }; -/* - * 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_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_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */ - MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */ - 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, -}; - - /* global register indices */ TCGv cpu_gpr[32], cpu_PC; /* @@ -3270,65 +3194,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 MMI_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 MMI_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"); - gen_reserved_instruction(ctx); - 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) { @@ -3521,138 +3386,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 MMI_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 MMI_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 MMI_OPC_MADD1: - acc = 1; - /* Fall through */ - case MMI_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 MMI_OPC_MADDU1: - acc = 1; - /* Fall through */ - case MMI_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"); - gen_reserved_instruction(ctx); - goto out; - } - - out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} - static void gen_cl(DisasContext *ctx, uint32_t opc, int rd, int rs) { @@ -12920,53 +12653,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"); - gen_reserved_instruction(ctx); - break; - } -} - static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd; @@ -13016,6 +12702,7 @@ static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx) case OPC_DDIV: case OPC_DDIVU: check_insn(ctx, ISA_MIPS3); + check_insn_opc_user_only(ctx, INSN_R5900); check_mips_64(ctx); gen_muldiv(ctx, op1, 0, rs, rt); break; @@ -13231,8 +12918,6 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) default: if (ctx->insn_flags & ISA_MIPS_R6) { decode_opc_special_r6(env, ctx); - } else if (ctx->insn_flags & INSN_R5900) { - decode_opc_special_tx79(env, ctx); } else { decode_opc_special_legacy(env, ctx); } @@ -13911,85 +13596,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) } } - -#if defined(TARGET_MIPS64) - -static void decode_mmi(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t opc = MASK_MMI(ctx->opcode); - int rs = extract32(ctx->opcode, 21, 5); - int rt = extract32(ctx->opcode, 16, 5); - int rd = extract32(ctx->opcode, 11, 5); - - switch (opc) { - case MMI_OPC_MULT1: - case MMI_OPC_MULTU1: - case MMI_OPC_MADD: - case MMI_OPC_MADDU: - case MMI_OPC_MADD1: - case MMI_OPC_MADDU1: - gen_mul_txx9(ctx, opc, rd, rs, rt); - break; - case MMI_OPC_DIV1: - case MMI_OPC_DIVU1: - gen_div1_tx79(ctx, opc, rs, rt); - break; - default: - MIPS_INVAL("TX79 MMI class"); - gen_reserved_instruction(ctx); - break; - } -} - -static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset) -{ - gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */ -} - -/* - * The TX79-specific instruction Store Quadword - * - * +--------+-------+-------+------------------------+ - * | 011111 | base | rt | offset | SQ - * +--------+-------+-------+------------------------+ - * 6 5 5 16 - * - * has the same opcode as the Read Hardware Register instruction - * - * +--------+-------+-------+-------+-------+--------+ - * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR - * +--------+-------+-------+-------+-------+--------+ - * 6 5 5 5 5 6 - * - * that is required, trapped and emulated by the Linux kernel. However, all - * RDHWR encodings yield address error exceptions on the TX79 since the SQ - * offset is odd. Therefore all valid SQ instructions can execute normally. - * In user mode, QEMU must verify the upper and lower 11 bits to distinguish - * between SQ and RDHWR, as the Linux kernel does. - */ -static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx) -{ - int base = extract32(ctx->opcode, 21, 5); - int rt = extract32(ctx->opcode, 16, 5); - int offset = extract32(ctx->opcode, 0, 16); - -#ifdef CONFIG_USER_ONLY - uint32_t op1 = MASK_SPECIAL3(ctx->opcode); - uint32_t op2 = extract32(ctx->opcode, 6, 5); - - if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) { - int rd = extract32(ctx->opcode, 11, 5); - - gen_rdhwr(ctx, rt, rd, 0); - return; - } -#endif - - gen_mmi_sq(ctx, base, rt, offset); -} - -#endif - static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd, sa; @@ -14160,12 +13766,6 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) decode_opc_special(env, ctx); break; case OPC_SPECIAL2: -#if defined(TARGET_MIPS64) - if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) { - decode_mmi(env, ctx); - break; - } -#endif if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) { if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) { gen_arith(ctx, OPC_MUL, rd, rs, rt); @@ -14177,15 +13777,7 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) decode_opc_special2_legacy(env, ctx); break; case OPC_SPECIAL3: -#if defined(TARGET_MIPS64) - if (ctx->insn_flags & INSN_R5900) { - decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */ - } else { - decode_opc_special3(env, ctx); - } -#else decode_opc_special3(env, ctx); -#endif break; case OPC_REGIMM: op1 = MASK_REGIMM(ctx->opcode); diff --git a/target/mips/tcg/tx79.decode b/target/mips/tcg/tx79.decode index 57d87a2076..8629b518bb 100644 --- a/target/mips/tcg/tx79.decode +++ b/target/mips/tcg/tx79.decode @@ -33,6 +33,20 @@ MTHI1 011100 ..... 0000000000 00000 010001 @rs MFLO1 011100 0000000000 ..... 00000 010010 @rd MTLO1 011100 ..... 0000000000 00000 010011 @rs +# MUL +# MULT/MULTU are reusing MIPS SPECIAL MAJOR_OP +MULT 000000 ..... ..... ..... 00000 011000 @rs_rt_rd +MULTU 000000 ..... ..... ..... 00000 011001 @rs_rt_rd +# Rests are using SPECIAL2 encoding +MADD 011100 ..... ..... ..... 00000 000000 @rs_rt_rd +MADDU 011100 ..... ..... ..... 00000 000001 @rs_rt_rd +MULT1 011100 ..... ..... ..... 00000 011000 @rs_rt_rd +MULTU1 011100 ..... ..... ..... 00000 011001 @rs_rt_rd +DIV1 011100 ..... ..... ..... 00000 011010 @rs_rt_rd +DIVU1 011100 ..... ..... ..... 00000 011011 @rs_rt_rd +MADD1 011100 ..... ..... ..... 00000 100000 @rs_rt_rd +MADDU1 011100 ..... ..... ..... 00000 100001 @rs_rt_rd + # MMI0 PSUBW 011100 ..... ..... ..... 00001 001000 @rs_rt_rd diff --git a/target/mips/tcg/tx79_translate.c b/target/mips/tcg/tx79_translate.c index 4e479c2d10..434a1cf13e 100644 --- a/target/mips/tcg/tx79_translate.c +++ b/target/mips/tcg/tx79_translate.c @@ -369,7 +369,7 @@ static bool trans_LQ(DisasContext *ctx, arg_i *a) return true; } -static bool trans_SQ(DisasContext *ctx, arg_i *a) +static bool gen_SQ(DisasContext *ctx, arg_i *a) { TCGv_i64 t0 = tcg_temp_new_i64(); TCGv addr = tcg_temp_new(); @@ -396,6 +396,32 @@ static bool trans_SQ(DisasContext *ctx, arg_i *a) return true; } +#define RDHWR_MASK(op) (op & 0xffe0063f) +#define OPC_RDHWR 0x7c00003b + +static bool trans_SQ(DisasContext *ctx, arg_i *a) +{ +#ifdef CONFIG_USER_ONLY + /* + * that is required, trapped and emulated by the Linux kernel. However, all + * RDHWR encodings yield address error exceptions on the TX79 since the SQ + * offset is odd. Therefore all valid SQ instructions can execute normally. + * In user mode, QEMU must verify the upper and lower 11 bits to distinguish + * between SQ and RDHWR, as the Linux kernel does. + */ + if (RDHWR_MASK(ctx->opcode) == OPC_RDHWR) { + int rd = extract32(ctx->opcode, 11, 5); + int rt = extract32(ctx->opcode, 16, 5); + int sel = extract32(ctx->opcode, 6, 3); + + gen_rdhwr(ctx, rt, rd, sel); + return true; + } +#endif + + return gen_SQ(ctx, a); +} + /* * Multiply and Divide (19 instructions) * ------------------------------------- @@ -683,3 +709,180 @@ static bool trans_PROT3W(DisasContext *ctx, arg_r *a) return true; } + +/* + * 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 bool gen_mult(DisasContext *ctx, arg_r *a, int acc, + void (*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) +{ + TCGv src1 = get_gpr(ctx, a->rs, EXT_NONE); + TCGv src2 = get_gpr(ctx, a->rt, EXT_NONE); + TCGv dst_lo = dest_lo(ctx, acc); + TCGv dst_hi = dest_hi(ctx, acc); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t1, src1); + tcg_gen_trunc_tl_i32(t2, src2); + + func(t1, t2, t1, t2); + + tcg_gen_ext_i32_tl(dst_lo, t1); + tcg_gen_ext_i32_tl(dst_hi, t2); + + gen_set_gpr(a->rd, dst_lo, EXT_NONE); + gen_set_lo(acc, dst_lo, EXT_NONE); + gen_set_hi(acc, dst_hi, EXT_NONE); + + return true; +} + +TRANS_6R(MULT, gen_mult, 0, tcg_gen_muls2_i32) +TRANS_6R(MULTU, gen_mult, 0, tcg_gen_mulu2_i32) +TRANS_6R(MULT1, gen_mult, 1, tcg_gen_muls2_i32) +TRANS_6R(MULTU1, gen_mult, 1, tcg_gen_mulu2_i32) + +static bool gen_mul_addsub(DisasContext *ctx, arg_r *a, int acc, DisasExtend ext, + void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) +{ + TCGv src1 = get_gpr(ctx, a->rs, ext); + TCGv src2 = get_gpr(ctx, a->rt, ext); + TCGv_i64 src3 = get_hilo(ctx, acc); + TCGv_i64 dst = dest_hilo(ctx, acc); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + switch (ext) { + case EXT_SIGN: + tcg_gen_ext_tl_i64(t2, src1); + tcg_gen_ext_tl_i64(t3, src2); + break; + case EXT_ZERO: + tcg_gen_extu_tl_i64(t2, src1); + tcg_gen_extu_tl_i64(t3, src2); + break; + default: + g_assert_not_reached(); + break; + } + + tcg_gen_mul_i64(dst, t2, t3); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); + func(dst, dst, src3); + + gen_set_hilo(acc, dst); + + return true; +} + +TRANS(MADD, gen_mul_addsub, 0, EXT_SIGN, tcg_gen_add_i64) +TRANS(MADDU, gen_mul_addsub, 0, EXT_ZERO, tcg_gen_add_i64) +TRANS(MADD1, gen_mul_addsub, 1, EXT_SIGN, tcg_gen_add_i64) +TRANS(MADDU1, gen_mul_addsub, 1, EXT_ZERO, tcg_gen_add_i64) + +static bool gen_div(DisasContext *ctx, arg_r *a, int acc, + DisasExtend src_ext, DisasExtend dst_ext) +{ + TCGv temp1, temp2, zero, one, mone, min; + TCGv src1 = get_gpr(ctx, a->rs, src_ext); + TCGv src2 = get_gpr(ctx, a->rt, src_ext); + TCGv dst_lo = dest_lo(ctx, acc); + TCGv dst_hi = dest_hi(ctx, acc); + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + mone = tcg_constant_tl(-1); + min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1)); + + /* + * If overflow, set temp2 to 1, else source2. + * This produces the required result of min. + */ + tcg_gen_setcond_tl(TCG_COND_EQ, temp1, src1, min); + tcg_gen_setcond_tl(TCG_COND_EQ, temp2, src2, mone); + tcg_gen_and_tl(temp1, temp1, temp2); + tcg_gen_movcond_tl(TCG_COND_NE, temp2, temp1, zero, one, src2); + + /* + * If div by zero, set temp1 to -1 and temp2 to 1 to + * produce the required result of -1. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp1, src2, zero, mone, src1); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, src2, zero, one, src2); + + tcg_gen_div_tl(dst_lo, temp1, temp2); + tcg_gen_rem_tl(dst_hi, temp1, temp2); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); + + gen_set_lo(acc, dst_lo, dst_ext); + gen_set_hi(acc, dst_hi, dst_ext); + + return true; +} + +static bool gen_divu(DisasContext *ctx, arg_r *a, int acc, + DisasExtend src_ext, DisasExtend dst_ext) +{ + TCGv temp1, temp2, zero, one, max; + TCGv src1 = get_gpr(ctx, a->rs, src_ext); + TCGv src2 = get_gpr(ctx, a->rt, src_ext); + TCGv dst_lo = dest_lo(ctx, acc); + TCGv dst_hi = dest_hi(ctx, acc); + + temp1 = tcg_temp_new(); + temp2 = tcg_temp_new(); + zero = tcg_constant_tl(0); + one = tcg_constant_tl(1); + max = tcg_constant_tl(~0); + + /* + * If div by zero, set temp1 to max and temp2 to 1 to + * produce the required result of max. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, temp1, src2, zero, max, src1); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, src2, zero, one, src2); + + tcg_gen_divu_tl(dst_lo, temp1, temp2); + tcg_gen_remu_tl(dst_hi, temp1, temp2); + + tcg_temp_free(temp1); + tcg_temp_free(temp2); + + gen_set_lo(acc, dst_lo, dst_ext); + gen_set_hi(acc, dst_hi, dst_ext); + + return true; +} + +TRANS(DIV1, gen_div, 1, EXT_SIGN, EXT_SIGN) +TRANS(DIVU1, gen_divu, 1, EXT_ZERO, EXT_SIGN) From patchwork Mon Oct 24 15:23:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 1693980 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=flygoat.com header.i=@flygoat.com header.a=rsa-sha256 header.s=fm1 header.b=V2ySNA85; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=r+Etk+U/; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Mx1bJ5CTnz23js for ; Tue, 25 Oct 2022 04:02:35 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1omzJD-0003iB-R1; Mon, 24 Oct 2022 11:24:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJC-0003hT-HL for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:10 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1omzJA-0008HS-Ph for qemu-devel@nongnu.org; Mon, 24 Oct 2022 11:24:10 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.west.internal (Postfix) with ESMTP id 63A8A320085B; Mon, 24 Oct 2022 11:24:07 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 24 Oct 2022 11:24:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flygoat.com; h= cc:cc:content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; t=1666625046; x=1666711446; bh=Ee NVEvuancGMM6mCbOQWAjOO2ICPI4+9myV2y4NytTw=; b=V2ySNA85GOFTlZQpOK C3h5eeK6CvMU5gIylSQZ/vosmGEAsioa4M0vHyFxEHf2CLnJ21xLQ8PTHMPBsLDc imoDWkrWQKWo3FF7zN97gQImi68IefugkKP6yC9Nn55olVyJcCdafIeCtki461ZF aRf4PG3RlWjy/r7QoglcMaJVVEU52BYsic03OdQJYTFEGGpxKanAVgCZ9Kp9LhFI 1u8YZ9B6bw2yxFrHhWzVruZrDV6KLuuG86SnAMQUBflyhOhD5cvwB4i5Fx57kjlp v6jPgXl6Bd2gsSBuQXldiALlts6K86qL6X8meuwLZv+vY/d+Dd7U3LS5+FqX2rQt hPTQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; t=1666625046; x=1666711446; bh=EeNVEvuancGMM 6mCbOQWAjOO2ICPI4+9myV2y4NytTw=; b=r+Etk+U/Wr3F8y+kmKsAMj4kDxE3V 1ef6fdLyQYXiFbrZbQFARYHxWfZSRY6bozvNiTWZ5/lS8CfVZ/tOvT7WPw0xakcd CO9+vA0kDQAZkqyb9Sj44irYeKnnaYYyOTKE3QUHUUspKRKk0tp+36XiZUMmzK+/ shaN5riVDP/YU5gLtr5YLQvFOcP8qft+WlDeVPLHmTQuxMJnImRMaTmbKnMKKem9 gKA+PGpe1Q/Ooo8B4VX2uhjq99dbC37Ow/IKZRfJD1xOmEhQ3iLu9TbYcO2RqnGj whJEryOBMnqAGNxbbGiDNcijphGZTIC12OoNKYGTPuFzaX5nt1obMvGGQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrgedtgedgkeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeflihgrgihunhcujggrnhhguceojhhirgiguhhnrdihrghn ghesfhhlhihgohgrthdrtghomheqnecuggftrfgrthhtvghrnhepfeeludefheegvdeuvd dvgeekgfdvtdettdelieeihfegtedugeekhfdvhfejfedtnecuvehluhhsthgvrhfuihii vgeptdenucfrrghrrghmpehmrghilhhfrhhomhepjhhirgiguhhnrdihrghnghesfhhlhi hgohgrthdrtghomh X-ME-Proxy: Feedback-ID: ifd894703:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 24 Oct 2022 11:24:05 -0400 (EDT) From: Jiaxun Yang To: qemu-devel@nongnu.org Cc: f4bug@amsat.org, richard.henderson@linaro.org, Jiaxun Yang Subject: [PATCH 6/6] target/mips: Make MXU decoder standalone Date: Mon, 24 Oct 2022 16:23:49 +0100 Message-Id: <20221024152349.215135-7-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221024152349.215135-1-jiaxun.yang@flygoat.com> References: <20221024152349.215135-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.19; envelope-from=jiaxun.yang@flygoat.com; helo=wout3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Qemu-devel" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org MXU is treated as an ISA extension for now. Signed-off-by: Jiaxun Yang --- target/mips/tcg/mxu_translate.c | 98 ++++++++++++++++++--------------- target/mips/tcg/translate.c | 13 ++--- 2 files changed, 60 insertions(+), 51 deletions(-) diff --git a/target/mips/tcg/mxu_translate.c b/target/mips/tcg/mxu_translate.c index f52244e1b2..9be37da620 100644 --- a/target/mips/tcg/mxu_translate.c +++ b/target/mips/tcg/mxu_translate.c @@ -354,6 +354,8 @@ * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017 */ +#define OPC_SPECIAL2 (0x1C << 26) + enum { OPC_MXU__POOL00 = 0x03, OPC_MXU_D16MUL = 0x08, @@ -1552,54 +1554,64 @@ bool decode_ase_mxu(DisasContext *ctx, uint32_t insn) { uint32_t opcode = extract32(insn, 0, 6); - if (opcode == OPC_MXU_S32M2I) { - gen_mxu_s32m2i(ctx); - return true; + if (MASK_OP_MAJOR(insn) != OPC_SPECIAL2) { + return false; } - if (opcode == OPC_MXU_S32I2M) { + switch (opcode) { + case OPC_MXU_S32M2I: + gen_mxu_s32m2i(ctx); + return true; + case OPC_MXU_S32I2M: gen_mxu_s32i2m(ctx); return true; - } - - { - 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); + case OPC_MXU__POOL00: + case OPC_MXU_D16MUL: + case OPC_MXU_D16MAC: + case OPC_MXU__POOL04: + case OPC_MXU_S8LDD: + case OPC_MXU__POOL16: + case OPC_MXU__POOL19: + { + 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__POOL00: + decode_opc_mxu__pool00(ctx); + break; + case OPC_MXU_D16MUL: + gen_mxu_d16mul(ctx); + break; + case OPC_MXU_D16MAC: + gen_mxu_d16mac(ctx); + break; + case OPC_MXU__POOL04: + decode_opc_mxu__pool04(ctx); + break; + case OPC_MXU_S8LDD: + gen_mxu_s8ldd(ctx); + break; + case OPC_MXU__POOL16: + decode_opc_mxu__pool16(ctx); + break; + case OPC_MXU__POOL19: + decode_opc_mxu__pool19(ctx); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + gen_reserved_instruction(ctx); + } - switch (opcode) { - case OPC_MXU__POOL00: - decode_opc_mxu__pool00(ctx); - break; - case OPC_MXU_D16MUL: - gen_mxu_d16mul(ctx); - break; - case OPC_MXU_D16MAC: - gen_mxu_d16mac(ctx); - break; - case OPC_MXU__POOL04: - decode_opc_mxu__pool04(ctx); - break; - case OPC_MXU_S8LDD: - gen_mxu_s8ldd(ctx); - break; - case OPC_MXU__POOL16: - decode_opc_mxu__pool16(ctx); - break; - case OPC_MXU__POOL19: - decode_opc_mxu__pool19(ctx); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - gen_reserved_instruction(ctx); + gen_set_label(l_exit); + tcg_temp_free(t_mxu_cr); } - - gen_set_label(l_exit); - tcg_temp_free(t_mxu_cr); + return true; + default: + return false; } - - return true; } diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index c8a3f63203..a5e89c528d 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -13766,14 +13766,6 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) decode_opc_special(env, ctx); break; case OPC_SPECIAL2: - if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) { - if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) { - gen_arith(ctx, OPC_MUL, rd, rs, rt); - } else { - decode_ase_mxu(ctx, ctx->opcode); - } - break; - } decode_opc_special2_legacy(env, ctx); break; case OPC_SPECIAL3: @@ -14484,6 +14476,11 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) if (cpu_supports_isa(env, ASE_LMMI) && decode_ase_lmmi(ctx, ctx->opcode)) { return; } + if (TARGET_LONG_BITS == 32) { + if (cpu_supports_isa(env, ASE_MXU) && decode_ase_mxu(ctx, ctx->opcode)) { + return; + } + } if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) { return; }