From nobody Wed Nov 19 03:02:57 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.46 as permitted sender) client-ip=209.85.128.46; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f46.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.46 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1614193105; cv=none; d=zohomail.com; s=zohoarc; b=evqdAiTR1gn9YpuUIzHtPDybNtBOGQbkfDyu+ipjLyIlucLVGV/f2akKEJRz/G7yQwea6aAPcbD4hDW9R1ykiVSITn6JtALzO+SIerrCUJyae2ZbtcHjVAzm2cbOzLK2GN0Sy8pBUYJD1/PoeZx0ma6Ib59JpJgMjtypvMbmYFE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1614193105; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ECdywSb5KoBbihi9gSeHYreiO+a92VyaR8UVhCjE+nI=; b=EoeZPRq/jzynO3XFFtTG7n6EUAWzEjVz/jNRrnqtBAv2Yj19el55fEGcjml+WwkigWlD1RxBAYW9MgXk1GNqsIYCHhroubIf0Yi9Mhwq804SNnDeA38MULH6RwfWfgAIZBJQcH5CwvHmSZ320HzyFxj9ptNJuE9vsb+WfzNAswY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.46 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) by mx.zohomail.com with SMTPS id 161419310552375.63152300836714; Wed, 24 Feb 2021 10:58:25 -0800 (PST) Received: by mail-wm1-f46.google.com with SMTP id i9so2383845wml.0 for ; Wed, 24 Feb 2021 10:58:24 -0800 (PST) Return-Path: Return-Path: Received: from x1w.redhat.com (68.red-83-57-175.dynamicip.rima-tde.net. [83.57.175.68]) by smtp.gmail.com with ESMTPSA id 7sm5048718wmi.27.2021.02.24.10.58.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Feb 2021 10:58:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ECdywSb5KoBbihi9gSeHYreiO+a92VyaR8UVhCjE+nI=; b=Nv6hggEeHVQGEwHXZM81zDjojtHwP1HJaqn/J+xBwXqU+2QqYjGgwMgrUeL5WShM2q fxznlNouJP76qxKudDk31Vqr9xmoU6tPwn91KPnq/KuOkv6/y+8R1zzuDtR+TvVyoFNd kqIL+v4v9lSwXkMetMFKY+uvGVDiHiPWcTe3vxAxwAooAPLLvp7CA23xniuOVUl8NN/r 1azb8M09L+RZiauIVmkvOpSZ2uYSsmHs1jyCEmuVpoemLszvPj8mZAG/pfrghdhfsmok AdH1yzGxxyMUt7efARjDSaa/r7vSNVtW7WLL0ihsGvcufPfOlCVBvqs/7jRl5Xex0sT+ 6F5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=ECdywSb5KoBbihi9gSeHYreiO+a92VyaR8UVhCjE+nI=; b=lcu1ssk0W04yYeu3rz1a6rDxBgFrh/1OwDd8XpYqaZfPInvll+1Xr6qFpapjvjVrlw +Ssv5Fd0R0l6eZ7FHVq1/IS2Q/8tb6oHH5WYR73DzjELFKZRO6+0GL0xwNLAcOd53QZ1 RwylFSIjqMITbWG7u65fn1B9xPTEtEAtSNcRV7544ntH1ai4ICyTp5QxCZ43j0ZlobvW XT/sZjWcgJcITHTfIeCpwGAY4uDZpB+RdzWj0RMH3qiQWkjXVmzAxsdZBdep7PIuFrD2 dxIPo2A9u4rh/s7PM5xnjzLx7DrzigfwSpYGAIG3lLFp0zLQXs2MEnVCJfPqriyCzXMT HZ9Q== X-Gm-Message-State: AOAM530FsVUlrhUEQ7oWB5WAJEWKJVvtlQ6DpecG8JSWnmCKO/s2VHSv 89YSeFg/Rj4xhvq+PplzCXU= X-Google-Smtp-Source: ABdhPJx6XZBxgN1hZHtFvMIEwTvhCMoVkiUolz25rhHYezTuXsLH9bWOmIyYklJzUfgFxPWLrrMHnA== X-Received: by 2002:a1c:7e4e:: with SMTP id z75mr5068841wmc.168.1614193102581; Wed, 24 Feb 2021 10:58:22 -0800 (PST) Sender: =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: Craig Janeczek , Jiaxun Yang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aleksandar Rikalo , Richard Henderson , Aurelien Jarno Subject: [PATCH v4 12/12] target/mips: Extract MXU code to new mxu_translate.c file Date: Wed, 24 Feb 2021 19:57:06 +0100 Message-Id: <20210224185706.3293058-13-f4bug@amsat.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210224185706.3293058-1-f4bug@amsat.org> References: <20210224185706.3293058-1-f4bug@amsat.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) Extract 1600+ lines from the big translate.c into a new file. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- target/mips/mxu_translate.c | 1609 +++++++++++++++++++++++++++++++++++ target/mips/translate.c | 1605 ---------------------------------- target/mips/meson.build | 4 + 3 files changed, 1613 insertions(+), 1605 deletions(-) create mode 100644 target/mips/mxu_translate.c diff --git a/target/mips/mxu_translate.c b/target/mips/mxu_translate.c new file mode 100644 index 00000000000..afc008eeeef --- /dev/null +++ b/target/mips/mxu_translate.c @@ -0,0 +1,1609 @@ +/* + * Ingenic XBurst Media eXtension Unit (MXU) translation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * Datasheet: + * + * "XBurst=C2=AE Instruction Set Architecture MIPS eXtension/enhanced Un= it + * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2,= 2017 + */ + +#include "qemu/osdep.h" +#include "tcg/tcg-op.h" +#include "exec/helper-gen.h" +#include "translate.h" + +/* + * + * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET + * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + * + * + * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MI= PS32 + * instructions set. It is designed to fit the needs of signal, graphical = and + * video processing applications. MXU instruction set is used in Xburst fa= mily + * of microprocessors by Ingenic. + * + * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X1= 6 is + * the control register. + * + * + * The notation used in MXU assembler mnemonics + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Register operands: + * + * XRa, XRb, XRc, XRd - MXU registers + * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers + * + * Non-register operands: + * + * aptn1 - 1-bit accumulate add/subtract pattern + * aptn2 - 2-bit accumulate add/subtract pattern + * eptn2 - 2-bit execute add/subtract pattern + * optn2 - 2-bit operand pattern + * optn3 - 3-bit operand pattern + * sft4 - 4-bit shift amount + * strd2 - 2-bit stride amount + * + * Prefixes: + * + * Level of parallelism: Operand size: + * S - single operation at a time 32 - word + * D - two operations in parallel 16 - half word + * Q - four operations in parallel 8 - byte + * + * Operations: + * + * ADD - Add or subtract + * ADDC - Add with carry-in + * ACC - Accumulate + * ASUM - Sum together then accumulate (add or subtract) + * ASUMC - Sum together then accumulate (add or subtract) with carry-in + * AVG - Average between 2 operands + * ABD - Absolute difference + * ALN - Align data + * AND - Logical bitwise 'and' operation + * CPS - Copy sign + * EXTR - Extract bits + * I2M - Move from GPR register to MXU register + * LDD - Load data from memory to XRF + * LDI - Load data from memory to XRF (and increase the address base) + * LUI - Load unsigned immediate + * MUL - Multiply + * MULU - Unsigned multiply + * MADD - 64-bit operand add 32x32 product + * MSUB - 64-bit operand subtract 32x32 product + * MAC - Multiply and accumulate (add or subtract) + * MAD - Multiply and add or subtract + * MAX - Maximum between 2 operands + * MIN - Minimum between 2 operands + * M2I - Move from MXU register to GPR register + * MOVZ - Move if zero + * MOVN - Move if non-zero + * NOR - Logical bitwise 'nor' operation + * OR - Logical bitwise 'or' operation + * STD - Store data from XRF to memory + * SDI - Store data from XRF to memory (and increase the address base) + * SLT - Set of less than comparison + * SAD - Sum of absolute differences + * SLL - Logical shift left + * SLR - Logical shift right + * SAR - Arithmetic shift right + * SAT - Saturation + * SFL - Shuffle + * SCOP - Calculate x=E2=80=99s scope (-1, means x<0; 0, means x=3D=3D0= ; 1, means x>0) + * XOR - Logical bitwise 'exclusive or' operation + * + * Suffixes: + * + * E - Expand results + * F - Fixed point multiplication + * L - Low part result + * R - Doing rounding + * V - Variable instead of immediate + * W - Combine above L and V + * + * + * The list of MXU instructions grouped by functionality + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Load/Store instructions Multiplication instructions + * ----------------------- --------------------------- + * + * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt + * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt + * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt + * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt + * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt + * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt + * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2 + * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2 + * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2 + * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, op= tn2 + * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, o= ptn2 + * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, o= ptn2 + * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, o= ptn2 + * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, op= tn2 + * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd + * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd + * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2 + * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2 + * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2 + * S16SDI XRa, Rb, s10, eptn2 + * S8LDD XRa, Rb, s8, eptn3 + * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions + * S8LDI XRa, Rb, s8, eptn3 ------------------------------------- + * S8SDI XRa, Rb, s8, eptn3 + * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2 + * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd + * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2 + * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2 + * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2 + * S32CPS XRa, XRb, XRc + * Q16ADD XRa, XRb, XRc, XRd, eptn2, op= tn2 + * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2 + * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2 + * D16ASUM XRa, XRb, XRc, XRd, eptn2 + * S32MAX XRa, XRb, XRc D16CPS XRa, XRb, + * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc + * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc + * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2 + * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2 + * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2 + * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc + * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd + * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc + * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc + * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd + * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd + * Q8SLT XRa, XRb, XRc + * Q8SLTU XRa, XRb, XRc + * Q8MOVZ XRa, XRb, XRc Shift instructions + * Q8MOVN XRa, XRb, XRc ------------------ + * + * D32SLL XRa, XRb, XRc, XRd, sft4 + * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4 + * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4 + * D32SARL XRa, XRb, XRc, sft4 + * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb + * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb + * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb + * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb + * Q16SLL XRa, XRb, XRc, XRd, sft4 + * Q16SLR XRa, XRb, XRc, XRd, sft4 + * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4 + * ------------------------- Q16SLLV XRa, XRb, Rb + * Q16SLRV XRa, XRb, Rb + * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb + * S32ALN XRa, XRb, XRc, Rb + * S32ALNI XRa, XRb, XRc, s3 + * S32LUI XRa, s8, optn3 Move instructions + * S32EXTR XRa, XRb, Rb, bits5 ----------------- + * S32EXTRV XRa, XRb, Rs, Rt + * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb + * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb + * + * + * The opcode organization of MXU instructions + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred + * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning = of + * other bits up to the instruction level is as follows: + * + * bits + * 05..00 + * + * =E2=94=8C=E2=94=80 000000 =E2=94=80 OPC_MXU_S32MADD + * =E2=94=9C=E2=94=80 000001 =E2=94=80 OPC_MXU_S32MADDU + * =E2=94=9C=E2=94=80 000010 =E2=94=80 (non-MXU = OPC_MUL) + * =E2=94=82 + * =E2=94=82 20..18 + * =E2=94=9C=E2=94=80 000011 =E2=94=80 OPC_MXU__POOL00 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_S32MAX + * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_S32MIN + * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_D16MAX + * =E2=94=82 =E2=94=9C=E2=94=80 011 = =E2=94=80 OPC_MXU_D16MIN + * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_Q8MAX + * =E2=94=82 =E2=94=9C=E2=94=80 101 = =E2=94=80 OPC_MXU_Q8MIN + * =E2=94=82 =E2=94=9C=E2=94=80 110 = =E2=94=80 OPC_MXU_Q8SLT + * =E2=94=82 =E2=94=94=E2=94=80 111 = =E2=94=80 OPC_MXU_Q8SLTU + * =E2=94=9C=E2=94=80 000100 =E2=94=80 OPC_MXU_S32MSUB + * =E2=94=9C=E2=94=80 000101 =E2=94=80 OPC_MXU_S32MSUBU 20..18 + * =E2=94=9C=E2=94=80 000110 =E2=94=80 OPC_MXU__POOL01 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_S32SLT + * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_D16SLT + * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_D16AVG + * =E2=94=82 =E2=94=9C=E2=94=80 011 = =E2=94=80 OPC_MXU_D16AVGR + * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_Q8AVG + * =E2=94=82 =E2=94=9C=E2=94=80 101 = =E2=94=80 OPC_MXU_Q8AVGR + * =E2=94=82 =E2=94=94=E2=94=80 111 = =E2=94=80 OPC_MXU_Q8ADD + * =E2=94=82 + * =E2=94=82 20..18 + * =E2=94=9C=E2=94=80 000111 =E2=94=80 OPC_MXU__POOL02 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_S32CPS + * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_D16CPS + * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_Q8ABD + * =E2=94=82 =E2=94=94=E2=94=80 110 = =E2=94=80 OPC_MXU_Q16SAT + * =E2=94=9C=E2=94=80 001000 =E2=94=80 OPC_MXU_D16MUL + * =E2=94=82 25..24 + * =E2=94=9C=E2=94=80 001001 =E2=94=80 OPC_MXU__POOL03 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_D16MULF + * =E2=94=82 =E2=94=94=E2=94=80 01 =E2= =94=80 OPC_MXU_D16MULE + * =E2=94=9C=E2=94=80 001010 =E2=94=80 OPC_MXU_D16MAC + * =E2=94=9C=E2=94=80 001011 =E2=94=80 OPC_MXU_D16MACF + * =E2=94=9C=E2=94=80 001100 =E2=94=80 OPC_MXU_D16MADL + * =E2=94=9C=E2=94=80 001101 =E2=94=80 OPC_MXU_S16MAD + * =E2=94=9C=E2=94=80 001110 =E2=94=80 OPC_MXU_Q16ADD + * =E2=94=9C=E2=94=80 001111 =E2=94=80 OPC_MXU_D16MACE 23 + * =E2=94=82 =E2=94=8C=E2=94=80 0 =E2= =94=80 OPC_MXU_S32LDD + * =E2=94=9C=E2=94=80 010000 =E2=94=80 OPC_MXU__POOL04 =E2=94=80= =E2=94=B4=E2=94=80 1 =E2=94=80 OPC_MXU_S32LDDR + * =E2=94=82 + * =E2=94=82 23 + * =E2=94=9C=E2=94=80 010001 =E2=94=80 OPC_MXU__POOL05 =E2=94=80= =E2=94=AC=E2=94=80 0 =E2=94=80 OPC_MXU_S32STD + * =E2=94=82 =E2=94=94=E2=94=80 1 =E2= =94=80 OPC_MXU_S32STDR + * =E2=94=82 + * =E2=94=82 13..10 + * =E2=94=9C=E2=94=80 010010 =E2=94=80 OPC_MXU__POOL06 =E2=94=80= =E2=94=AC=E2=94=80 0000 =E2=94=80 OPC_MXU_S32LDDV + * =E2=94=82 =E2=94=94=E2=94=80 0001 = =E2=94=80 OPC_MXU_S32LDDVR + * =E2=94=82 + * =E2=94=82 13..10 + * =E2=94=9C=E2=94=80 010011 =E2=94=80 OPC_MXU__POOL07 =E2=94=80= =E2=94=AC=E2=94=80 0000 =E2=94=80 OPC_MXU_S32STDV + * =E2=94=82 =E2=94=94=E2=94=80 0001 = =E2=94=80 OPC_MXU_S32STDVR + * =E2=94=82 + * =E2=94=82 23 + * =E2=94=9C=E2=94=80 010100 =E2=94=80 OPC_MXU__POOL08 =E2=94=80= =E2=94=AC=E2=94=80 0 =E2=94=80 OPC_MXU_S32LDI + * =E2=94=82 =E2=94=94=E2=94=80 1 =E2= =94=80 OPC_MXU_S32LDIR + * =E2=94=82 + * =E2=94=82 23 + * =E2=94=9C=E2=94=80 010101 =E2=94=80 OPC_MXU__POOL09 =E2=94=80= =E2=94=AC=E2=94=80 0 =E2=94=80 OPC_MXU_S32SDI + * =E2=94=82 =E2=94=94=E2=94=80 1 =E2= =94=80 OPC_MXU_S32SDIR + * =E2=94=82 + * =E2=94=82 13..10 + * =E2=94=9C=E2=94=80 010110 =E2=94=80 OPC_MXU__POOL10 =E2=94=80= =E2=94=AC=E2=94=80 0000 =E2=94=80 OPC_MXU_S32LDIV + * =E2=94=82 =E2=94=94=E2=94=80 0001 = =E2=94=80 OPC_MXU_S32LDIVR + * =E2=94=82 + * =E2=94=82 13..10 + * =E2=94=9C=E2=94=80 010111 =E2=94=80 OPC_MXU__POOL11 =E2=94=80= =E2=94=AC=E2=94=80 0000 =E2=94=80 OPC_MXU_S32SDIV + * =E2=94=82 =E2=94=94=E2=94=80 0001 = =E2=94=80 OPC_MXU_S32SDIVR + * =E2=94=9C=E2=94=80 011000 =E2=94=80 OPC_MXU_D32ADD + * =E2=94=82 23..22 + * MXU =E2=94=9C=E2=94=80 011001 =E2=94=80 OPC_MXU__POOL12 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_D32ACC + * opcodes =E2=94=80=E2=94=A4 =E2=94=9C=E2=94= =80 01 =E2=94=80 OPC_MXU_D32ACCM + * =E2=94=82 =E2=94=94=E2=94=80 10 =E2= =94=80 OPC_MXU_D32ASUM + * =E2=94=9C=E2=94=80 011010 =E2=94=80 + * =E2=94=82 23..22 + * =E2=94=9C=E2=94=80 011011 =E2=94=80 OPC_MXU__POOL13 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_Q16ACC + * =E2=94=82 =E2=94=9C=E2=94=80 01 =E2= =94=80 OPC_MXU_Q16ACCM + * =E2=94=82 =E2=94=94=E2=94=80 10 =E2= =94=80 OPC_MXU_Q16ASUM + * =E2=94=82 + * =E2=94=82 23..22 + * =E2=94=9C=E2=94=80 011100 =E2=94=80 OPC_MXU__POOL14 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_Q8ADDE + * =E2=94=82 =E2=94=9C=E2=94=80 01 =E2= =94=80 OPC_MXU_D8SUM + * =E2=94=9C=E2=94=80 011101 =E2=94=80 OPC_MXU_Q8ACCE =E2=94=94= =E2=94=80 10 =E2=94=80 OPC_MXU_D8SUMC + * =E2=94=9C=E2=94=80 011110 =E2=94=80 + * =E2=94=9C=E2=94=80 011111 =E2=94=80 + * =E2=94=9C=E2=94=80 100000 =E2=94=80 (overlaps= with CLZ) + * =E2=94=9C=E2=94=80 100001 =E2=94=80 (overlaps= with CLO) + * =E2=94=9C=E2=94=80 100010 =E2=94=80 OPC_MXU_S8LDD + * =E2=94=9C=E2=94=80 100011 =E2=94=80 OPC_MXU_S8STD 15..14 + * =E2=94=9C=E2=94=80 100100 =E2=94=80 OPC_MXU_S8LDI =E2=94=8C= =E2=94=80 00 =E2=94=80 OPC_MXU_S32MUL + * =E2=94=9C=E2=94=80 100101 =E2=94=80 OPC_MXU_S8SDI =E2=94=9C= =E2=94=80 00 =E2=94=80 OPC_MXU_S32MULU + * =E2=94=82 =E2=94=9C=E2=94=80 00 =E2= =94=80 OPC_MXU_S32EXTR + * =E2=94=9C=E2=94=80 100110 =E2=94=80 OPC_MXU__POOL15 =E2=94=80= =E2=94=B4=E2=94=80 00 =E2=94=80 OPC_MXU_S32EXTRV + * =E2=94=82 + * =E2=94=82 20..18 + * =E2=94=9C=E2=94=80 100111 =E2=94=80 OPC_MXU__POOL16 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_D32SARW + * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_S32ALN + * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_S32ALNI + * =E2=94=82 =E2=94=9C=E2=94=80 011 = =E2=94=80 OPC_MXU_S32LUI + * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_S32NOR + * =E2=94=82 =E2=94=9C=E2=94=80 101 = =E2=94=80 OPC_MXU_S32AND + * =E2=94=82 =E2=94=9C=E2=94=80 110 = =E2=94=80 OPC_MXU_S32OR + * =E2=94=82 =E2=94=94=E2=94=80 111 = =E2=94=80 OPC_MXU_S32XOR + * =E2=94=82 + * =E2=94=82 7..5 + * =E2=94=9C=E2=94=80 101000 =E2=94=80 OPC_MXU__POOL17 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_LXB + * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_LXH + * =E2=94=9C=E2=94=80 101001 =E2=94=80 =E2=94=9C= =E2=94=80 011 =E2=94=80 OPC_MXU_LXW + * =E2=94=9C=E2=94=80 101010 =E2=94=80 OPC_MXU_S16LDD =E2=94=9C= =E2=94=80 100 =E2=94=80 OPC_MXU_LXBU + * =E2=94=9C=E2=94=80 101011 =E2=94=80 OPC_MXU_S16STD =E2=94=94= =E2=94=80 101 =E2=94=80 OPC_MXU_LXHU + * =E2=94=9C=E2=94=80 101100 =E2=94=80 OPC_MXU_S16LDI + * =E2=94=9C=E2=94=80 101101 =E2=94=80 OPC_MXU_S16SDI + * =E2=94=9C=E2=94=80 101110 =E2=94=80 OPC_MXU_S32M2I + * =E2=94=9C=E2=94=80 101111 =E2=94=80 OPC_MXU_S32I2M + * =E2=94=9C=E2=94=80 110000 =E2=94=80 OPC_MXU_D32SLL + * =E2=94=9C=E2=94=80 110001 =E2=94=80 OPC_MXU_D32SLR 20..18 + * =E2=94=9C=E2=94=80 110010 =E2=94=80 OPC_MXU_D32SARL =E2=94=8C= =E2=94=80 000 =E2=94=80 OPC_MXU_D32SLLV + * =E2=94=9C=E2=94=80 110011 =E2=94=80 OPC_MXU_D32SAR =E2=94=9C= =E2=94=80 001 =E2=94=80 OPC_MXU_D32SLRV + * =E2=94=9C=E2=94=80 110100 =E2=94=80 OPC_MXU_Q16SLL =E2=94=9C= =E2=94=80 010 =E2=94=80 OPC_MXU_D32SARV + * =E2=94=9C=E2=94=80 110101 =E2=94=80 OPC_MXU_Q16SLR =E2=94=9C= =E2=94=80 011 =E2=94=80 OPC_MXU_Q16SLLV + * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_Q16SLRV + * =E2=94=9C=E2=94=80 110110 =E2=94=80 OPC_MXU__POOL18 =E2=94=80= =E2=94=B4=E2=94=80 101 =E2=94=80 OPC_MXU_Q16SARV + * =E2=94=82 + * =E2=94=9C=E2=94=80 110111 =E2=94=80 OPC_MXU_Q16SAR + * =E2=94=82 23..22 + * =E2=94=9C=E2=94=80 111000 =E2=94=80 OPC_MXU__POOL19 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_Q8MUL + * =E2=94=82 =E2=94=94=E2=94=80 01 =E2= =94=80 OPC_MXU_Q8MULSU + * =E2=94=82 + * =E2=94=82 20..18 + * =E2=94=9C=E2=94=80 111001 =E2=94=80 OPC_MXU__POOL20 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_Q8MOVZ + * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_Q8MOVN + * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_D16MOVZ + * =E2=94=82 =E2=94=9C=E2=94=80 011 = =E2=94=80 OPC_MXU_D16MOVN + * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_S32MOVZ + * =E2=94=82 =E2=94=94=E2=94=80 101 = =E2=94=80 OPC_MXU_S32MOVN + * =E2=94=82 + * =E2=94=82 23..22 + * =E2=94=9C=E2=94=80 111010 =E2=94=80 OPC_MXU__POOL21 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_Q8MAC + * =E2=94=82 =E2=94=94=E2=94=80 10 =E2= =94=80 OPC_MXU_Q8MACSU + * =E2=94=9C=E2=94=80 111011 =E2=94=80 OPC_MXU_Q16SCOP + * =E2=94=9C=E2=94=80 111100 =E2=94=80 OPC_MXU_Q8MADL + * =E2=94=9C=E2=94=80 111101 =E2=94=80 OPC_MXU_S32SFL + * =E2=94=9C=E2=94=80 111110 =E2=94=80 OPC_MXU_Q8SAD + * =E2=94=94=E2=94=80 111111 =E2=94=80 (overlaps= with SDBBP) + * + * + * Compiled after: + * + * "XBurst=C2=AE Instruction Set Architecture MIPS eXtension/enhanced Un= it + * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2,= 2017 + */ + +enum { + OPC_MXU__POOL00 =3D 0x03, + OPC_MXU_D16MUL =3D 0x08, + OPC_MXU_D16MAC =3D 0x0A, + OPC_MXU__POOL04 =3D 0x10, + OPC_MXU_S8LDD =3D 0x22, + OPC_MXU__POOL16 =3D 0x27, + OPC_MXU_S32M2I =3D 0x2E, + OPC_MXU_S32I2M =3D 0x2F, + OPC_MXU__POOL19 =3D 0x38, +}; + + +/* + * MXU pool 00 + */ +enum { + OPC_MXU_S32MAX =3D 0x00, + OPC_MXU_S32MIN =3D 0x01, + OPC_MXU_D16MAX =3D 0x02, + OPC_MXU_D16MIN =3D 0x03, + OPC_MXU_Q8MAX =3D 0x04, + OPC_MXU_Q8MIN =3D 0x05, +}; + +/* + * MXU pool 04 + */ +enum { + OPC_MXU_S32LDD =3D 0x00, + OPC_MXU_S32LDDR =3D 0x01, +}; + +/* + * MXU pool 16 + */ +enum { + OPC_MXU_S32ALNI =3D 0x02, + OPC_MXU_S32NOR =3D 0x04, + OPC_MXU_S32AND =3D 0x05, + OPC_MXU_S32OR =3D 0x06, + OPC_MXU_S32XOR =3D 0x07, +}; + +/* + * MXU pool 19 + */ +enum { + OPC_MXU_Q8MUL =3D 0x00, + OPC_MXU_Q8MULSU =3D 0x01, +}; + +/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */ +#define MXU_APTN1_A 0 +#define MXU_APTN1_S 1 + +/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */ +#define MXU_APTN2_AA 0 +#define MXU_APTN2_AS 1 +#define MXU_APTN2_SA 2 +#define MXU_APTN2_SS 3 + +/* MXU execute add/subtract 2-bit pattern 'eptn2' */ +#define MXU_EPTN2_AA 0 +#define MXU_EPTN2_AS 1 +#define MXU_EPTN2_SA 2 +#define MXU_EPTN2_SS 3 + +/* MXU operand getting pattern 'optn2' */ +#define MXU_OPTN2_PTN0 0 +#define MXU_OPTN2_PTN1 1 +#define MXU_OPTN2_PTN2 2 +#define MXU_OPTN2_PTN3 3 +/* alternative naming scheme for 'optn2' */ +#define MXU_OPTN2_WW 0 +#define MXU_OPTN2_LW 1 +#define MXU_OPTN2_HW 2 +#define MXU_OPTN2_XW 3 + +/* MXU operand getting pattern 'optn3' */ +#define MXU_OPTN3_PTN0 0 +#define MXU_OPTN3_PTN1 1 +#define MXU_OPTN3_PTN2 2 +#define MXU_OPTN3_PTN3 3 +#define MXU_OPTN3_PTN4 4 +#define MXU_OPTN3_PTN5 5 +#define MXU_OPTN3_PTN6 6 +#define MXU_OPTN3_PTN7 7 + +/* MXU registers */ +static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; +static TCGv mxu_CR; + +static const char * const mxuregnames[] =3D { + "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8", + "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR", +}; + +void mxu_translate_init(void) +{ + for (unsigned i =3D 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) { + mxu_gpr[i] =3D tcg_global_mem_new(cpu_env, + offsetof(CPUMIPSState, active_tc.m= xu_gpr[i]), + mxuregnames[i]); + } + + mxu_CR =3D tcg_global_mem_new(cpu_env, + offsetof(CPUMIPSState, active_tc.mxu_cr), + mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]); +} + +/* MXU General purpose registers moves. */ +static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg) +{ + if (reg =3D=3D 0) { + tcg_gen_movi_tl(t, 0); + } else if (reg <=3D 15) { + tcg_gen_mov_tl(t, mxu_gpr[reg - 1]); + } +} + +static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg) +{ + if (reg > 0 && reg <=3D 15) { + tcg_gen_mov_tl(mxu_gpr[reg - 1], t); + } +} + +/* MXU control register moves. */ +static inline void gen_load_mxu_cr(TCGv t) +{ + tcg_gen_mov_tl(t, mxu_CR); +} + +static inline void gen_store_mxu_cr(TCGv t) +{ + /* TODO: Add handling of RW rules for MXU_CR. */ + tcg_gen_mov_tl(mxu_CR, t); +} + +/* + * S32I2M XRa, rb - Register move from GRF to XRF + */ +static void gen_mxu_s32i2m(DisasContext *ctx) +{ + TCGv t0; + uint32_t XRa, Rb; + + t0 =3D tcg_temp_new(); + + XRa =3D extract32(ctx->opcode, 6, 5); + Rb =3D extract32(ctx->opcode, 16, 5); + + gen_load_gpr(t0, Rb); + if (XRa <=3D 15) { + gen_store_mxu_gpr(t0, XRa); + } else if (XRa =3D=3D 16) { + gen_store_mxu_cr(t0); + } + + tcg_temp_free(t0); +} + +/* + * S32M2I XRa, rb - Register move from XRF to GRF + */ +static void gen_mxu_s32m2i(DisasContext *ctx) +{ + TCGv t0; + uint32_t XRa, Rb; + + t0 =3D tcg_temp_new(); + + XRa =3D extract32(ctx->opcode, 6, 5); + Rb =3D extract32(ctx->opcode, 16, 5); + + if (XRa <=3D 15) { + gen_load_mxu_gpr(t0, XRa); + } else if (XRa =3D=3D 16) { + gen_load_mxu_cr(t0); + } + + gen_store_gpr(t0, Rb); + + tcg_temp_free(t0); +} + +/* + * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF + */ +static void gen_mxu_s8ldd(DisasContext *ctx) +{ + TCGv t0, t1; + uint32_t XRa, Rb, s8, optn3; + + t0 =3D tcg_temp_new(); + t1 =3D tcg_temp_new(); + + XRa =3D extract32(ctx->opcode, 6, 4); + s8 =3D extract32(ctx->opcode, 10, 8); + optn3 =3D extract32(ctx->opcode, 18, 3); + Rb =3D extract32(ctx->opcode, 21, 5); + + gen_load_gpr(t0, Rb); + tcg_gen_addi_tl(t0, t0, (int8_t)s8); + + switch (optn3) { + /* XRa[7:0] =3D tmp8 */ + case MXU_OPTN3_PTN0: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + gen_load_mxu_gpr(t0, XRa); + tcg_gen_deposit_tl(t0, t0, t1, 0, 8); + break; + /* XRa[15:8] =3D tmp8 */ + case MXU_OPTN3_PTN1: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + gen_load_mxu_gpr(t0, XRa); + tcg_gen_deposit_tl(t0, t0, t1, 8, 8); + break; + /* XRa[23:16] =3D tmp8 */ + case MXU_OPTN3_PTN2: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + gen_load_mxu_gpr(t0, XRa); + tcg_gen_deposit_tl(t0, t0, t1, 16, 8); + break; + /* XRa[31:24] =3D tmp8 */ + case MXU_OPTN3_PTN3: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + gen_load_mxu_gpr(t0, XRa); + tcg_gen_deposit_tl(t0, t0, t1, 24, 8); + break; + /* XRa =3D {8'b0, tmp8, 8'b0, tmp8} */ + case MXU_OPTN3_PTN4: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_deposit_tl(t0, t1, t1, 16, 16); + break; + /* XRa =3D {tmp8, 8'b0, tmp8, 8'b0} */ + case MXU_OPTN3_PTN5: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_shli_tl(t1, t1, 8); + tcg_gen_deposit_tl(t0, t1, t1, 16, 16); + break; + /* XRa =3D {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */ + case MXU_OPTN3_PTN6: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB); + tcg_gen_mov_tl(t0, t1); + tcg_gen_andi_tl(t0, t0, 0xFF00FFFF); + tcg_gen_shli_tl(t1, t1, 16); + tcg_gen_or_tl(t0, t0, t1); + break; + /* XRa =3D {tmp8, tmp8, tmp8, tmp8} */ + case MXU_OPTN3_PTN7: + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_deposit_tl(t1, t1, t1, 8, 8); + tcg_gen_deposit_tl(t0, t1, t1, 16, 16); + break; + } + + gen_store_mxu_gpr(t0, XRa); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* + * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication + */ +static void gen_mxu_d16mul(DisasContext *ctx) +{ + TCGv t0, t1, t2, t3; + uint32_t XRa, XRb, XRc, XRd, optn2; + + t0 =3D tcg_temp_new(); + t1 =3D tcg_temp_new(); + t2 =3D tcg_temp_new(); + t3 =3D tcg_temp_new(); + + XRa =3D extract32(ctx->opcode, 6, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRc =3D extract32(ctx->opcode, 14, 4); + XRd =3D extract32(ctx->opcode, 18, 4); + optn2 =3D extract32(ctx->opcode, 22, 2); + + gen_load_mxu_gpr(t1, XRb); + tcg_gen_sextract_tl(t0, t1, 0, 16); + tcg_gen_sextract_tl(t1, t1, 16, 16); + gen_load_mxu_gpr(t3, XRc); + tcg_gen_sextract_tl(t2, t3, 0, 16); + tcg_gen_sextract_tl(t3, t3, 16, 16); + + switch (optn2) { + case MXU_OPTN2_WW: /* XRB.H*XRC.H =3D=3D lop, XRB.L*XRC.L =3D=3D rop */ + tcg_gen_mul_tl(t3, t1, t3); + tcg_gen_mul_tl(t2, t0, t2); + break; + case MXU_OPTN2_LW: /* XRB.L*XRC.H =3D=3D lop, XRB.L*XRC.L =3D=3D rop */ + tcg_gen_mul_tl(t3, t0, t3); + tcg_gen_mul_tl(t2, t0, t2); + break; + case MXU_OPTN2_HW: /* XRB.H*XRC.H =3D=3D lop, XRB.H*XRC.L =3D=3D rop */ + tcg_gen_mul_tl(t3, t1, t3); + tcg_gen_mul_tl(t2, t1, t2); + break; + case MXU_OPTN2_XW: /* XRB.L*XRC.H =3D=3D lop, XRB.H*XRC.L =3D=3D rop */ + tcg_gen_mul_tl(t3, t0, t3); + tcg_gen_mul_tl(t2, t1, t2); + break; + } + gen_store_mxu_gpr(t3, XRa); + gen_store_mxu_gpr(t2, XRd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_temp_free(t3); +} + +/* + * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply + * and accumulate + */ +static void gen_mxu_d16mac(DisasContext *ctx) +{ + TCGv t0, t1, t2, t3; + uint32_t XRa, XRb, XRc, XRd, optn2, aptn2; + + t0 =3D tcg_temp_new(); + t1 =3D tcg_temp_new(); + t2 =3D tcg_temp_new(); + t3 =3D tcg_temp_new(); + + XRa =3D extract32(ctx->opcode, 6, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRc =3D extract32(ctx->opcode, 14, 4); + XRd =3D extract32(ctx->opcode, 18, 4); + optn2 =3D extract32(ctx->opcode, 22, 2); + aptn2 =3D extract32(ctx->opcode, 24, 2); + + gen_load_mxu_gpr(t1, XRb); + tcg_gen_sextract_tl(t0, t1, 0, 16); + tcg_gen_sextract_tl(t1, t1, 16, 16); + + gen_load_mxu_gpr(t3, XRc); + tcg_gen_sextract_tl(t2, t3, 0, 16); + tcg_gen_sextract_tl(t3, t3, 16, 16); + + switch (optn2) { + case MXU_OPTN2_WW: /* XRB.H*XRC.H =3D=3D lop, XRB.L*XRC.L =3D=3D rop */ + tcg_gen_mul_tl(t3, t1, t3); + tcg_gen_mul_tl(t2, t0, t2); + break; + case MXU_OPTN2_LW: /* XRB.L*XRC.H =3D=3D lop, XRB.L*XRC.L =3D=3D rop */ + tcg_gen_mul_tl(t3, t0, t3); + tcg_gen_mul_tl(t2, t0, t2); + break; + case MXU_OPTN2_HW: /* XRB.H*XRC.H =3D=3D lop, XRB.H*XRC.L =3D=3D rop */ + tcg_gen_mul_tl(t3, t1, t3); + tcg_gen_mul_tl(t2, t1, t2); + break; + case MXU_OPTN2_XW: /* XRB.L*XRC.H =3D=3D lop, XRB.H*XRC.L =3D=3D rop */ + tcg_gen_mul_tl(t3, t0, t3); + tcg_gen_mul_tl(t2, t1, t2); + break; + } + gen_load_mxu_gpr(t0, XRa); + gen_load_mxu_gpr(t1, XRd); + + switch (aptn2) { + case MXU_APTN2_AA: + tcg_gen_add_tl(t3, t0, t3); + tcg_gen_add_tl(t2, t1, t2); + break; + case MXU_APTN2_AS: + tcg_gen_add_tl(t3, t0, t3); + tcg_gen_sub_tl(t2, t1, t2); + break; + case MXU_APTN2_SA: + tcg_gen_sub_tl(t3, t0, t3); + tcg_gen_add_tl(t2, t1, t2); + break; + case MXU_APTN2_SS: + tcg_gen_sub_tl(t3, t0, t3); + tcg_gen_sub_tl(t2, t1, t2); + break; + } + gen_store_mxu_gpr(t3, XRa); + gen_store_mxu_gpr(t2, XRd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_temp_free(t3); +} + +/* + * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply + * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply + */ +static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx) +{ + TCGv t0, t1, t2, t3, t4, t5, t6, t7; + uint32_t XRa, XRb, XRc, XRd, sel; + + t0 =3D tcg_temp_new(); + t1 =3D tcg_temp_new(); + t2 =3D tcg_temp_new(); + t3 =3D tcg_temp_new(); + t4 =3D tcg_temp_new(); + t5 =3D tcg_temp_new(); + t6 =3D tcg_temp_new(); + t7 =3D tcg_temp_new(); + + XRa =3D extract32(ctx->opcode, 6, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRc =3D extract32(ctx->opcode, 14, 4); + XRd =3D extract32(ctx->opcode, 18, 4); + sel =3D extract32(ctx->opcode, 22, 2); + + gen_load_mxu_gpr(t3, XRb); + gen_load_mxu_gpr(t7, XRc); + + if (sel =3D=3D 0x2) { + /* Q8MULSU */ + tcg_gen_ext8s_tl(t0, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8s_tl(t1, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8s_tl(t2, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8s_tl(t3, t3); + } else { + /* Q8MUL */ + tcg_gen_ext8u_tl(t0, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8u_tl(t1, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8u_tl(t2, t3); + tcg_gen_shri_tl(t3, t3, 8); + tcg_gen_ext8u_tl(t3, t3); + } + + tcg_gen_ext8u_tl(t4, t7); + tcg_gen_shri_tl(t7, t7, 8); + tcg_gen_ext8u_tl(t5, t7); + tcg_gen_shri_tl(t7, t7, 8); + tcg_gen_ext8u_tl(t6, t7); + tcg_gen_shri_tl(t7, t7, 8); + tcg_gen_ext8u_tl(t7, t7); + + tcg_gen_mul_tl(t0, t0, t4); + tcg_gen_mul_tl(t1, t1, t5); + tcg_gen_mul_tl(t2, t2, t6); + tcg_gen_mul_tl(t3, t3, t7); + + tcg_gen_andi_tl(t0, t0, 0xFFFF); + tcg_gen_andi_tl(t1, t1, 0xFFFF); + tcg_gen_andi_tl(t2, t2, 0xFFFF); + tcg_gen_andi_tl(t3, t3, 0xFFFF); + + tcg_gen_shli_tl(t1, t1, 16); + tcg_gen_shli_tl(t3, t3, 16); + + tcg_gen_or_tl(t0, t0, t1); + tcg_gen_or_tl(t1, t2, t3); + + gen_store_mxu_gpr(t0, XRd); + gen_store_mxu_gpr(t1, XRa); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_temp_free(t3); + tcg_temp_free(t4); + tcg_temp_free(t5); + tcg_temp_free(t6); + tcg_temp_free(t7); +} + +/* + * S32LDD XRa, Rb, S12 - Load a word from memory to XRF + * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte se= q. + */ +static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx) +{ + TCGv t0, t1; + uint32_t XRa, Rb, s12, sel; + + t0 =3D tcg_temp_new(); + t1 =3D tcg_temp_new(); + + XRa =3D extract32(ctx->opcode, 6, 4); + s12 =3D extract32(ctx->opcode, 10, 10); + sel =3D extract32(ctx->opcode, 20, 1); + Rb =3D extract32(ctx->opcode, 21, 5); + + gen_load_gpr(t0, Rb); + + tcg_gen_movi_tl(t1, s12); + tcg_gen_shli_tl(t1, t1, 2); + if (s12 & 0x200) { + tcg_gen_ori_tl(t1, t1, 0xFFFFF000); + } + tcg_gen_add_tl(t1, t0, t1); + tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL); + + if (sel =3D=3D 1) { + /* S32LDDR */ + tcg_gen_bswap32_tl(t1, t1); + } + gen_store_mxu_gpr(t1, XRa); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + + +/* + * MXU instruction category: logic + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * S32NOR S32AND S32OR S32XOR + */ + +/* + * S32NOR XRa, XRb, XRc + * Update XRa with the result of logical bitwise 'nor' operation + * applied to the content of XRb and XRc. + */ +static void gen_mxu_S32NOR(DisasContext *ctx) +{ + uint32_t pad, XRc, XRb, XRa; + + pad =3D extract32(ctx->opcode, 21, 5); + XRc =3D extract32(ctx->opcode, 14, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRa =3D extract32(ctx->opcode, 6, 4); + + if (unlikely(pad !=3D 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa =3D=3D 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { + /* both operands zero registers -> just set destination to all 1s = */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF); + } else if (unlikely(XRb =3D=3D 0)) { + /* XRb zero register -> just set destination to the negation of XR= c */ + tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + } else if (unlikely(XRc =3D=3D 0)) { + /* XRa zero register -> just set destination to the negation of XR= b */ + tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else if (unlikely(XRb =3D=3D XRc)) { + /* both operands same -> just set destination to the negation of X= Rb */ + tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - = 1]); + } +} + +/* + * S32AND XRa, XRb, XRc + * Update XRa with the result of logical bitwise 'and' operation + * applied to the content of XRb and XRc. + */ +static void gen_mxu_S32AND(DisasContext *ctx) +{ + uint32_t pad, XRc, XRb, XRa; + + pad =3D extract32(ctx->opcode, 21, 5); + XRc =3D extract32(ctx->opcode, 14, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRa =3D extract32(ctx->opcode, 6, 4); + + if (unlikely(pad !=3D 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa =3D=3D 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb =3D=3D 0) || (XRc =3D=3D 0))) { + /* one of operands zero register -> just set destination to all 0s= */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely(XRb =3D=3D XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - = 1]); + } +} + +/* + * S32OR XRa, XRb, XRc + * Update XRa with the result of logical bitwise 'or' operation + * applied to the content of XRb and XRc. + */ +static void gen_mxu_S32OR(DisasContext *ctx) +{ + uint32_t pad, XRc, XRb, XRa; + + pad =3D extract32(ctx->opcode, 21, 5); + XRc =3D extract32(ctx->opcode, 14, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRa =3D extract32(ctx->opcode, 6, 4); + + if (unlikely(pad !=3D 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa =3D=3D 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { + /* both operands zero registers -> just set destination to all 0s = */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely(XRb =3D=3D 0)) { + /* XRb zero register -> just set destination to the content of XRc= */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + } else if (unlikely(XRc =3D=3D 0)) { + /* XRc zero register -> just set destination to the content of XRb= */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else if (unlikely(XRb =3D=3D XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1= ]); + } +} + +/* + * S32XOR XRa, XRb, XRc + * Update XRa with the result of logical bitwise 'xor' operation + * applied to the content of XRb and XRc. + */ +static void gen_mxu_S32XOR(DisasContext *ctx) +{ + uint32_t pad, XRc, XRb, XRa; + + pad =3D extract32(ctx->opcode, 21, 5); + XRc =3D extract32(ctx->opcode, 14, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRa =3D extract32(ctx->opcode, 6, 4); + + if (unlikely(pad !=3D 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa =3D=3D 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { + /* both operands zero registers -> just set destination to all 0s = */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely(XRb =3D=3D 0)) { + /* XRb zero register -> just set destination to the content of XRc= */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + } else if (unlikely(XRc =3D=3D 0)) { + /* XRc zero register -> just set destination to the content of XRb= */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else if (unlikely(XRb =3D=3D XRc)) { + /* both operands same -> just set destination to all 0s */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else { + /* the most general case */ + tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - = 1]); + } +} + + +/* + * MXU instruction category max/min + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * S32MAX D16MAX Q8MAX + * S32MIN D16MIN Q8MIN + */ + +/* + * S32MAX XRa, XRb, XRc + * Update XRa with the maximum of signed 32-bit integers contained + * in XRb and XRc. + * + * S32MIN XRa, XRb, XRc + * Update XRa with the minimum of signed 32-bit integers contained + * in XRb and XRc. + */ +static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx) +{ + uint32_t pad, opc, XRc, XRb, XRa; + + pad =3D extract32(ctx->opcode, 21, 5); + opc =3D extract32(ctx->opcode, 18, 3); + XRc =3D extract32(ctx->opcode, 14, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRa =3D extract32(ctx->opcode, 6, 4); + + if (unlikely(pad !=3D 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa =3D=3D 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { + /* both operands zero registers -> just set destination to zero */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely((XRb =3D=3D 0) || (XRc =3D=3D 0))) { + /* exactly one operand is zero register - find which one is not...= */ + uint32_t XRx =3D XRb ? XRb : XRc; + /* ...and do max/min operation with one operand 0 */ + if (opc =3D=3D OPC_MXU_S32MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); + } + } else if (unlikely(XRb =3D=3D XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + if (opc =3D=3D OPC_MXU_S32MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], + mxu_gpr[XRc - 1]); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], + mxu_gpr[XRc - 1]); + } + } +} + +/* + * D16MAX + * Update XRa with the 16-bit-wise maximums of signed integers + * contained in XRb and XRc. + * + * D16MIN + * Update XRa with the 16-bit-wise minimums of signed integers + * contained in XRb and XRc. + */ +static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) +{ + uint32_t pad, opc, XRc, XRb, XRa; + + pad =3D extract32(ctx->opcode, 21, 5); + opc =3D extract32(ctx->opcode, 18, 3); + XRc =3D extract32(ctx->opcode, 14, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRa =3D extract32(ctx->opcode, 6, 4); + + if (unlikely(pad !=3D 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRc =3D=3D 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb =3D=3D 0) && (XRa =3D=3D 0))) { + /* both operands zero registers -> just set destination to zero */ + tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0); + } else if (unlikely((XRb =3D=3D 0) || (XRa =3D=3D 0))) { + /* exactly one operand is zero register - find which one is not...= */ + uint32_t XRx =3D XRb ? XRb : XRc; + /* ...and do half-word-wise max/min with one operand 0 */ + TCGv_i32 t0 =3D tcg_temp_new(); + TCGv_i32 t1 =3D tcg_const_i32(0); + + /* the left half-word first */ + tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000); + if (opc =3D=3D OPC_MXU_D16MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); + } + + /* the right half-word */ + tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF); + /* move half-words to the leftmost position */ + tcg_gen_shli_i32(t0, t0, 16); + /* t0 will be max/min of t0 and t1 */ + if (opc =3D=3D OPC_MXU_D16MAX) { + tcg_gen_smax_i32(t0, t0, t1); + } else { + tcg_gen_smin_i32(t0, t0, t1); + } + /* return resulting half-words to its original position */ + tcg_gen_shri_i32(t0, t0, 16); + /* finally update the destination */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } else if (unlikely(XRb =3D=3D XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + TCGv_i32 t0 =3D tcg_temp_new(); + TCGv_i32 t1 =3D tcg_temp_new(); + + /* the left half-word first */ + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000); + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000); + if (opc =3D=3D OPC_MXU_D16MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); + } + + /* the right half-word */ + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF); + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF); + /* move half-words to the leftmost position */ + tcg_gen_shli_i32(t0, t0, 16); + tcg_gen_shli_i32(t1, t1, 16); + /* t0 will be max/min of t0 and t1 */ + if (opc =3D=3D OPC_MXU_D16MAX) { + tcg_gen_smax_i32(t0, t0, t1); + } else { + tcg_gen_smin_i32(t0, t0, t1); + } + /* return resulting half-words to its original position */ + tcg_gen_shri_i32(t0, t0, 16); + /* finally update the destination */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } +} + +/* + * Q8MAX + * Update XRa with the 8-bit-wise maximums of signed integers + * contained in XRb and XRc. + * + * Q8MIN + * Update XRa with the 8-bit-wise minimums of signed integers + * contained in XRb and XRc. + */ +static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx) +{ + uint32_t pad, opc, XRc, XRb, XRa; + + pad =3D extract32(ctx->opcode, 21, 5); + opc =3D extract32(ctx->opcode, 18, 3); + XRc =3D extract32(ctx->opcode, 14, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRa =3D extract32(ctx->opcode, 6, 4); + + if (unlikely(pad !=3D 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa =3D=3D 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { + /* both operands zero registers -> just set destination to zero */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely((XRb =3D=3D 0) || (XRc =3D=3D 0))) { + /* exactly one operand is zero register - make it be the first...*/ + uint32_t XRx =3D XRb ? XRb : XRc; + /* ...and do byte-wise max/min with one operand 0 */ + TCGv_i32 t0 =3D tcg_temp_new(); + TCGv_i32 t1 =3D tcg_const_i32(0); + int32_t i; + + /* the leftmost byte (byte 3) first */ + tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000); + if (opc =3D=3D OPC_MXU_Q8MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); + } + + /* bytes 2, 1, 0 */ + for (i =3D 2; i >=3D 0; i--) { + /* extract the byte */ + tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i)); + /* move the byte to the leftmost position */ + tcg_gen_shli_i32(t0, t0, 8 * (3 - i)); + /* t0 will be max/min of t0 and t1 */ + if (opc =3D=3D OPC_MXU_Q8MAX) { + tcg_gen_smax_i32(t0, t0, t1); + } else { + tcg_gen_smin_i32(t0, t0, t1); + } + /* return resulting byte to its original position */ + tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); + /* finally update the destination */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); + } + + tcg_temp_free(t1); + tcg_temp_free(t0); + } else if (unlikely(XRb =3D=3D XRc)) { + /* both operands same -> just set destination to one of them */ + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } else { + /* the most general case */ + TCGv_i32 t0 =3D tcg_temp_new(); + TCGv_i32 t1 =3D tcg_temp_new(); + int32_t i; + + /* the leftmost bytes (bytes 3) first */ + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000); + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000); + if (opc =3D=3D OPC_MXU_Q8MAX) { + tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); + } else { + tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); + } + + /* bytes 2, 1, 0 */ + for (i =3D 2; i >=3D 0; i--) { + /* extract corresponding bytes */ + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i)); + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i)); + /* move the bytes to the leftmost position */ + tcg_gen_shli_i32(t0, t0, 8 * (3 - i)); + tcg_gen_shli_i32(t1, t1, 8 * (3 - i)); + /* t0 will be max/min of t0 and t1 */ + if (opc =3D=3D OPC_MXU_Q8MAX) { + tcg_gen_smax_i32(t0, t0, t1); + } else { + tcg_gen_smin_i32(t0, t0, t1); + } + /* return resulting byte to its original position */ + tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); + /* finally update the destination */ + tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); + } + + tcg_temp_free(t1); + tcg_temp_free(t0); + } +} + + +/* + * MXU instruction category: align + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * S32ALN S32ALNI + */ + +/* + * S32ALNI XRc, XRb, XRa, optn3 + * Arrange bytes from XRb and XRc according to one of five sets of + * rules determined by optn3, and place the result in XRa. + */ +static void gen_mxu_S32ALNI(DisasContext *ctx) +{ + uint32_t optn3, pad, XRc, XRb, XRa; + + optn3 =3D extract32(ctx->opcode, 23, 3); + pad =3D extract32(ctx->opcode, 21, 2); + XRc =3D extract32(ctx->opcode, 14, 4); + XRb =3D extract32(ctx->opcode, 10, 4); + XRa =3D extract32(ctx->opcode, 6, 4); + + if (unlikely(pad !=3D 0)) { + /* opcode padding incorrect -> do nothing */ + } else if (unlikely(XRa =3D=3D 0)) { + /* destination is zero register -> do nothing */ + } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { + /* both operands zero registers -> just set destination to all 0s = */ + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + } else if (unlikely(XRb =3D=3D 0)) { + /* XRb zero register -> just appropriatelly shift XRc into XRa */ + switch (optn3) { + case MXU_OPTN3_PTN0: + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + break; + case MXU_OPTN3_PTN1: + case MXU_OPTN3_PTN2: + case MXU_OPTN3_PTN3: + tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1], + 8 * (4 - optn3)); + break; + case MXU_OPTN3_PTN4: + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + break; + } + } else if (unlikely(XRc =3D=3D 0)) { + /* XRc zero register -> just appropriatelly shift XRb into XRa */ + switch (optn3) { + case MXU_OPTN3_PTN0: + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + break; + case MXU_OPTN3_PTN1: + case MXU_OPTN3_PTN2: + case MXU_OPTN3_PTN3: + tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3= ); + break; + case MXU_OPTN3_PTN4: + tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); + break; + } + } else if (unlikely(XRb =3D=3D XRc)) { + /* both operands same -> just rotation or moving from any of them = */ + switch (optn3) { + case MXU_OPTN3_PTN0: + case MXU_OPTN3_PTN4: + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + break; + case MXU_OPTN3_PTN1: + case MXU_OPTN3_PTN2: + case MXU_OPTN3_PTN3: + tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn= 3); + break; + } + } else { + /* the most general case */ + switch (optn3) { + case MXU_OPTN3_PTN0: + { + /* */ + /* XRb XRc */ + /* +---------------+ */ + /* | A B C D | E F G H */ + /* +-------+-------+ */ + /* | */ + /* XRa */ + /* */ + + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); + } + break; + case MXU_OPTN3_PTN1: + { + /* */ + /* XRb XRc */ + /* +-------------------+ */ + /* A | B C D E | F G H */ + /* +---------+---------+ */ + /* | */ + /* XRa */ + /* */ + + TCGv_i32 t0 =3D tcg_temp_new(); + TCGv_i32 t1 =3D tcg_temp_new(); + + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF); + tcg_gen_shli_i32(t0, t0, 8); + + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000); + tcg_gen_shri_i32(t1, t1, 24); + + tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } + break; + case MXU_OPTN3_PTN2: + { + /* */ + /* XRb XRc */ + /* +-------------------+ */ + /* A B | C D E F | G H */ + /* +---------+---------+ */ + /* | */ + /* XRa */ + /* */ + + TCGv_i32 t0 =3D tcg_temp_new(); + TCGv_i32 t1 =3D tcg_temp_new(); + + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF); + tcg_gen_shli_i32(t0, t0, 16); + + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000); + tcg_gen_shri_i32(t1, t1, 16); + + tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } + break; + case MXU_OPTN3_PTN3: + { + /* */ + /* XRb XRc */ + /* +-------------------+ */ + /* A B C | D E F G | H */ + /* +---------+---------+ */ + /* | */ + /* XRa */ + /* */ + + TCGv_i32 t0 =3D tcg_temp_new(); + TCGv_i32 t1 =3D tcg_temp_new(); + + tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF); + tcg_gen_shli_i32(t0, t0, 24); + + tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00); + tcg_gen_shri_i32(t1, t1, 8); + + tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); + + tcg_temp_free(t1); + tcg_temp_free(t0); + } + break; + case MXU_OPTN3_PTN4: + { + /* */ + /* XRb XRc */ + /* +---------------+ */ + /* A B C D | E F G H | */ + /* +-------+-------+ */ + /* | */ + /* XRa */ + /* */ + + tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); + } + break; + } + } +} + + +/* + * Decoding engine for MXU + * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + */ + +static void decode_opc_mxu__pool00(DisasContext *ctx) +{ + uint32_t opcode =3D extract32(ctx->opcode, 18, 3); + + switch (opcode) { + case OPC_MXU_S32MAX: + case OPC_MXU_S32MIN: + gen_mxu_S32MAX_S32MIN(ctx); + break; + case OPC_MXU_D16MAX: + case OPC_MXU_D16MIN: + gen_mxu_D16MAX_D16MIN(ctx); + break; + case OPC_MXU_Q8MAX: + case OPC_MXU_Q8MIN: + gen_mxu_Q8MAX_Q8MIN(ctx); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + gen_reserved_instruction(ctx); + break; + } +} + +static void decode_opc_mxu__pool04(DisasContext *ctx) +{ + uint32_t opcode =3D extract32(ctx->opcode, 20, 1); + + switch (opcode) { + case OPC_MXU_S32LDD: + case OPC_MXU_S32LDDR: + gen_mxu_s32ldd_s32lddr(ctx); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + gen_reserved_instruction(ctx); + break; + } +} + +static void decode_opc_mxu__pool16(DisasContext *ctx) +{ + uint32_t opcode =3D extract32(ctx->opcode, 18, 3); + + switch (opcode) { + case OPC_MXU_S32ALNI: + gen_mxu_S32ALNI(ctx); + break; + case OPC_MXU_S32NOR: + gen_mxu_S32NOR(ctx); + break; + case OPC_MXU_S32AND: + gen_mxu_S32AND(ctx); + break; + case OPC_MXU_S32OR: + gen_mxu_S32OR(ctx); + break; + case OPC_MXU_S32XOR: + gen_mxu_S32XOR(ctx); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + gen_reserved_instruction(ctx); + break; + } +} + +static void decode_opc_mxu__pool19(DisasContext *ctx) +{ + uint32_t opcode =3D extract32(ctx->opcode, 22, 2); + + switch (opcode) { + case OPC_MXU_Q8MUL: + case OPC_MXU_Q8MULSU: + gen_mxu_q8mul_q8mulsu(ctx); + break; + default: + MIPS_INVAL("decode_opc_mxu"); + gen_reserved_instruction(ctx); + break; + } +} + +bool decode_ase_mxu(DisasContext *ctx, uint32_t insn) +{ + uint32_t opcode =3D extract32(insn, 0, 6); + + if (opcode =3D=3D OPC_MXU_S32M2I) { + gen_mxu_s32m2i(ctx); + return true; + } + + if (opcode =3D=3D OPC_MXU_S32I2M) { + gen_mxu_s32i2m(ctx); + return true; + } + + { + TCGv t_mxu_cr =3D tcg_temp_new(); + TCGLabel *l_exit =3D 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); + } + + gen_set_label(l_exit); + tcg_temp_free(t_mxu_cr); + } + + return true; +} diff --git a/target/mips/translate.c b/target/mips/translate.c index da6825c2fec..64e0baf11b7 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -1129,392 +1129,6 @@ enum { OPC_NMSUB_PS =3D 0x3E | OPC_CP3, }; =20 -/* - * - * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET - * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - * - * - * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MI= PS32 - * instructions set. It is designed to fit the needs of signal, graphical = and - * video processing applications. MXU instruction set is used in Xburst fa= mily - * of microprocessors by Ingenic. - * - * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X1= 6 is - * the control register. - * - * - * The notation used in MXU assembler mnemonics - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Register operands: - * - * XRa, XRb, XRc, XRd - MXU registers - * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers - * - * Non-register operands: - * - * aptn1 - 1-bit accumulate add/subtract pattern - * aptn2 - 2-bit accumulate add/subtract pattern - * eptn2 - 2-bit execute add/subtract pattern - * optn2 - 2-bit operand pattern - * optn3 - 3-bit operand pattern - * sft4 - 4-bit shift amount - * strd2 - 2-bit stride amount - * - * Prefixes: - * - * Level of parallelism: Operand size: - * S - single operation at a time 32 - word - * D - two operations in parallel 16 - half word - * Q - four operations in parallel 8 - byte - * - * Operations: - * - * ADD - Add or subtract - * ADDC - Add with carry-in - * ACC - Accumulate - * ASUM - Sum together then accumulate (add or subtract) - * ASUMC - Sum together then accumulate (add or subtract) with carry-in - * AVG - Average between 2 operands - * ABD - Absolute difference - * ALN - Align data - * AND - Logical bitwise 'and' operation - * CPS - Copy sign - * EXTR - Extract bits - * I2M - Move from GPR register to MXU register - * LDD - Load data from memory to XRF - * LDI - Load data from memory to XRF (and increase the address base) - * LUI - Load unsigned immediate - * MUL - Multiply - * MULU - Unsigned multiply - * MADD - 64-bit operand add 32x32 product - * MSUB - 64-bit operand subtract 32x32 product - * MAC - Multiply and accumulate (add or subtract) - * MAD - Multiply and add or subtract - * MAX - Maximum between 2 operands - * MIN - Minimum between 2 operands - * M2I - Move from MXU register to GPR register - * MOVZ - Move if zero - * MOVN - Move if non-zero - * NOR - Logical bitwise 'nor' operation - * OR - Logical bitwise 'or' operation - * STD - Store data from XRF to memory - * SDI - Store data from XRF to memory (and increase the address base) - * SLT - Set of less than comparison - * SAD - Sum of absolute differences - * SLL - Logical shift left - * SLR - Logical shift right - * SAR - Arithmetic shift right - * SAT - Saturation - * SFL - Shuffle - * SCOP - Calculate x=E2=80=99s scope (-1, means x<0; 0, means x=3D=3D0= ; 1, means x>0) - * XOR - Logical bitwise 'exclusive or' operation - * - * Suffixes: - * - * E - Expand results - * F - Fixed point multiplication - * L - Low part result - * R - Doing rounding - * V - Variable instead of immediate - * W - Combine above L and V - * - * - * The list of MXU instructions grouped by functionality - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Load/Store instructions Multiplication instructions - * ----------------------- --------------------------- - * - * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt - * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt - * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt - * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt - * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt - * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt - * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2 - * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2 - * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2 - * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, op= tn2 - * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, o= ptn2 - * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, o= ptn2 - * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, o= ptn2 - * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, op= tn2 - * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd - * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd - * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2 - * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2 - * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2 - * S16SDI XRa, Rb, s10, eptn2 - * S8LDD XRa, Rb, s8, eptn3 - * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions - * S8LDI XRa, Rb, s8, eptn3 ------------------------------------- - * S8SDI XRa, Rb, s8, eptn3 - * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2 - * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd - * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2 - * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2 - * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2 - * S32CPS XRa, XRb, XRc - * Q16ADD XRa, XRb, XRc, XRd, eptn2, op= tn2 - * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2 - * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2 - * D16ASUM XRa, XRb, XRc, XRd, eptn2 - * S32MAX XRa, XRb, XRc D16CPS XRa, XRb, - * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc - * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc - * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2 - * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2 - * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2 - * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc - * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd - * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc - * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc - * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd - * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd - * Q8SLT XRa, XRb, XRc - * Q8SLTU XRa, XRb, XRc - * Q8MOVZ XRa, XRb, XRc Shift instructions - * Q8MOVN XRa, XRb, XRc ------------------ - * - * D32SLL XRa, XRb, XRc, XRd, sft4 - * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4 - * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4 - * D32SARL XRa, XRb, XRc, sft4 - * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb - * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb - * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb - * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb - * Q16SLL XRa, XRb, XRc, XRd, sft4 - * Q16SLR XRa, XRb, XRc, XRd, sft4 - * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4 - * ------------------------- Q16SLLV XRa, XRb, Rb - * Q16SLRV XRa, XRb, Rb - * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb - * S32ALN XRa, XRb, XRc, Rb - * S32ALNI XRa, XRb, XRc, s3 - * S32LUI XRa, s8, optn3 Move instructions - * S32EXTR XRa, XRb, Rb, bits5 ----------------- - * S32EXTRV XRa, XRb, Rs, Rt - * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb - * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb - * - * - * The opcode organization of MXU instructions - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred - * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning = of - * other bits up to the instruction level is as follows: - * - * bits - * 05..00 - * - * =E2=94=8C=E2=94=80 000000 =E2=94=80 OPC_MXU_S32MADD - * =E2=94=9C=E2=94=80 000001 =E2=94=80 OPC_MXU_S32MADDU - * =E2=94=9C=E2=94=80 000010 =E2=94=80 (non-MXU = OPC_MUL) - * =E2=94=82 - * =E2=94=82 20..18 - * =E2=94=9C=E2=94=80 000011 =E2=94=80 OPC_MXU__POOL00 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_S32MAX - * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_S32MIN - * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_D16MAX - * =E2=94=82 =E2=94=9C=E2=94=80 011 = =E2=94=80 OPC_MXU_D16MIN - * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_Q8MAX - * =E2=94=82 =E2=94=9C=E2=94=80 101 = =E2=94=80 OPC_MXU_Q8MIN - * =E2=94=82 =E2=94=9C=E2=94=80 110 = =E2=94=80 OPC_MXU_Q8SLT - * =E2=94=82 =E2=94=94=E2=94=80 111 = =E2=94=80 OPC_MXU_Q8SLTU - * =E2=94=9C=E2=94=80 000100 =E2=94=80 OPC_MXU_S32MSUB - * =E2=94=9C=E2=94=80 000101 =E2=94=80 OPC_MXU_S32MSUBU 20..18 - * =E2=94=9C=E2=94=80 000110 =E2=94=80 OPC_MXU__POOL01 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_S32SLT - * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_D16SLT - * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_D16AVG - * =E2=94=82 =E2=94=9C=E2=94=80 011 = =E2=94=80 OPC_MXU_D16AVGR - * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_Q8AVG - * =E2=94=82 =E2=94=9C=E2=94=80 101 = =E2=94=80 OPC_MXU_Q8AVGR - * =E2=94=82 =E2=94=94=E2=94=80 111 = =E2=94=80 OPC_MXU_Q8ADD - * =E2=94=82 - * =E2=94=82 20..18 - * =E2=94=9C=E2=94=80 000111 =E2=94=80 OPC_MXU__POOL02 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_S32CPS - * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_D16CPS - * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_Q8ABD - * =E2=94=82 =E2=94=94=E2=94=80 110 = =E2=94=80 OPC_MXU_Q16SAT - * =E2=94=9C=E2=94=80 001000 =E2=94=80 OPC_MXU_D16MUL - * =E2=94=82 25..24 - * =E2=94=9C=E2=94=80 001001 =E2=94=80 OPC_MXU__POOL03 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_D16MULF - * =E2=94=82 =E2=94=94=E2=94=80 01 =E2= =94=80 OPC_MXU_D16MULE - * =E2=94=9C=E2=94=80 001010 =E2=94=80 OPC_MXU_D16MAC - * =E2=94=9C=E2=94=80 001011 =E2=94=80 OPC_MXU_D16MACF - * =E2=94=9C=E2=94=80 001100 =E2=94=80 OPC_MXU_D16MADL - * =E2=94=9C=E2=94=80 001101 =E2=94=80 OPC_MXU_S16MAD - * =E2=94=9C=E2=94=80 001110 =E2=94=80 OPC_MXU_Q16ADD - * =E2=94=9C=E2=94=80 001111 =E2=94=80 OPC_MXU_D16MACE 23 - * =E2=94=82 =E2=94=8C=E2=94=80 0 =E2= =94=80 OPC_MXU_S32LDD - * =E2=94=9C=E2=94=80 010000 =E2=94=80 OPC_MXU__POOL04 =E2=94=80= =E2=94=B4=E2=94=80 1 =E2=94=80 OPC_MXU_S32LDDR - * =E2=94=82 - * =E2=94=82 23 - * =E2=94=9C=E2=94=80 010001 =E2=94=80 OPC_MXU__POOL05 =E2=94=80= =E2=94=AC=E2=94=80 0 =E2=94=80 OPC_MXU_S32STD - * =E2=94=82 =E2=94=94=E2=94=80 1 =E2= =94=80 OPC_MXU_S32STDR - * =E2=94=82 - * =E2=94=82 13..10 - * =E2=94=9C=E2=94=80 010010 =E2=94=80 OPC_MXU__POOL06 =E2=94=80= =E2=94=AC=E2=94=80 0000 =E2=94=80 OPC_MXU_S32LDDV - * =E2=94=82 =E2=94=94=E2=94=80 0001 = =E2=94=80 OPC_MXU_S32LDDVR - * =E2=94=82 - * =E2=94=82 13..10 - * =E2=94=9C=E2=94=80 010011 =E2=94=80 OPC_MXU__POOL07 =E2=94=80= =E2=94=AC=E2=94=80 0000 =E2=94=80 OPC_MXU_S32STDV - * =E2=94=82 =E2=94=94=E2=94=80 0001 = =E2=94=80 OPC_MXU_S32STDVR - * =E2=94=82 - * =E2=94=82 23 - * =E2=94=9C=E2=94=80 010100 =E2=94=80 OPC_MXU__POOL08 =E2=94=80= =E2=94=AC=E2=94=80 0 =E2=94=80 OPC_MXU_S32LDI - * =E2=94=82 =E2=94=94=E2=94=80 1 =E2= =94=80 OPC_MXU_S32LDIR - * =E2=94=82 - * =E2=94=82 23 - * =E2=94=9C=E2=94=80 010101 =E2=94=80 OPC_MXU__POOL09 =E2=94=80= =E2=94=AC=E2=94=80 0 =E2=94=80 OPC_MXU_S32SDI - * =E2=94=82 =E2=94=94=E2=94=80 1 =E2= =94=80 OPC_MXU_S32SDIR - * =E2=94=82 - * =E2=94=82 13..10 - * =E2=94=9C=E2=94=80 010110 =E2=94=80 OPC_MXU__POOL10 =E2=94=80= =E2=94=AC=E2=94=80 0000 =E2=94=80 OPC_MXU_S32LDIV - * =E2=94=82 =E2=94=94=E2=94=80 0001 = =E2=94=80 OPC_MXU_S32LDIVR - * =E2=94=82 - * =E2=94=82 13..10 - * =E2=94=9C=E2=94=80 010111 =E2=94=80 OPC_MXU__POOL11 =E2=94=80= =E2=94=AC=E2=94=80 0000 =E2=94=80 OPC_MXU_S32SDIV - * =E2=94=82 =E2=94=94=E2=94=80 0001 = =E2=94=80 OPC_MXU_S32SDIVR - * =E2=94=9C=E2=94=80 011000 =E2=94=80 OPC_MXU_D32ADD - * =E2=94=82 23..22 - * MXU =E2=94=9C=E2=94=80 011001 =E2=94=80 OPC_MXU__POOL12 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_D32ACC - * opcodes =E2=94=80=E2=94=A4 =E2=94=9C=E2=94= =80 01 =E2=94=80 OPC_MXU_D32ACCM - * =E2=94=82 =E2=94=94=E2=94=80 10 =E2= =94=80 OPC_MXU_D32ASUM - * =E2=94=9C=E2=94=80 011010 =E2=94=80 - * =E2=94=82 23..22 - * =E2=94=9C=E2=94=80 011011 =E2=94=80 OPC_MXU__POOL13 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_Q16ACC - * =E2=94=82 =E2=94=9C=E2=94=80 01 =E2= =94=80 OPC_MXU_Q16ACCM - * =E2=94=82 =E2=94=94=E2=94=80 10 =E2= =94=80 OPC_MXU_Q16ASUM - * =E2=94=82 - * =E2=94=82 23..22 - * =E2=94=9C=E2=94=80 011100 =E2=94=80 OPC_MXU__POOL14 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_Q8ADDE - * =E2=94=82 =E2=94=9C=E2=94=80 01 =E2= =94=80 OPC_MXU_D8SUM - * =E2=94=9C=E2=94=80 011101 =E2=94=80 OPC_MXU_Q8ACCE =E2=94=94= =E2=94=80 10 =E2=94=80 OPC_MXU_D8SUMC - * =E2=94=9C=E2=94=80 011110 =E2=94=80 - * =E2=94=9C=E2=94=80 011111 =E2=94=80 - * =E2=94=9C=E2=94=80 100000 =E2=94=80 (overlaps= with CLZ) - * =E2=94=9C=E2=94=80 100001 =E2=94=80 (overlaps= with CLO) - * =E2=94=9C=E2=94=80 100010 =E2=94=80 OPC_MXU_S8LDD - * =E2=94=9C=E2=94=80 100011 =E2=94=80 OPC_MXU_S8STD 15..14 - * =E2=94=9C=E2=94=80 100100 =E2=94=80 OPC_MXU_S8LDI =E2=94=8C= =E2=94=80 00 =E2=94=80 OPC_MXU_S32MUL - * =E2=94=9C=E2=94=80 100101 =E2=94=80 OPC_MXU_S8SDI =E2=94=9C= =E2=94=80 00 =E2=94=80 OPC_MXU_S32MULU - * =E2=94=82 =E2=94=9C=E2=94=80 00 =E2= =94=80 OPC_MXU_S32EXTR - * =E2=94=9C=E2=94=80 100110 =E2=94=80 OPC_MXU__POOL15 =E2=94=80= =E2=94=B4=E2=94=80 00 =E2=94=80 OPC_MXU_S32EXTRV - * =E2=94=82 - * =E2=94=82 20..18 - * =E2=94=9C=E2=94=80 100111 =E2=94=80 OPC_MXU__POOL16 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_D32SARW - * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_S32ALN - * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_S32ALNI - * =E2=94=82 =E2=94=9C=E2=94=80 011 = =E2=94=80 OPC_MXU_S32LUI - * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_S32NOR - * =E2=94=82 =E2=94=9C=E2=94=80 101 = =E2=94=80 OPC_MXU_S32AND - * =E2=94=82 =E2=94=9C=E2=94=80 110 = =E2=94=80 OPC_MXU_S32OR - * =E2=94=82 =E2=94=94=E2=94=80 111 = =E2=94=80 OPC_MXU_S32XOR - * =E2=94=82 - * =E2=94=82 7..5 - * =E2=94=9C=E2=94=80 101000 =E2=94=80 OPC_MXU__POOL17 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_LXB - * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_LXH - * =E2=94=9C=E2=94=80 101001 =E2=94=80 =E2=94=9C= =E2=94=80 011 =E2=94=80 OPC_MXU_LXW - * =E2=94=9C=E2=94=80 101010 =E2=94=80 OPC_MXU_S16LDD =E2=94=9C= =E2=94=80 100 =E2=94=80 OPC_MXU_LXBU - * =E2=94=9C=E2=94=80 101011 =E2=94=80 OPC_MXU_S16STD =E2=94=94= =E2=94=80 101 =E2=94=80 OPC_MXU_LXHU - * =E2=94=9C=E2=94=80 101100 =E2=94=80 OPC_MXU_S16LDI - * =E2=94=9C=E2=94=80 101101 =E2=94=80 OPC_MXU_S16SDI - * =E2=94=9C=E2=94=80 101110 =E2=94=80 OPC_MXU_S32M2I - * =E2=94=9C=E2=94=80 101111 =E2=94=80 OPC_MXU_S32I2M - * =E2=94=9C=E2=94=80 110000 =E2=94=80 OPC_MXU_D32SLL - * =E2=94=9C=E2=94=80 110001 =E2=94=80 OPC_MXU_D32SLR 20..18 - * =E2=94=9C=E2=94=80 110010 =E2=94=80 OPC_MXU_D32SARL =E2=94=8C= =E2=94=80 000 =E2=94=80 OPC_MXU_D32SLLV - * =E2=94=9C=E2=94=80 110011 =E2=94=80 OPC_MXU_D32SAR =E2=94=9C= =E2=94=80 001 =E2=94=80 OPC_MXU_D32SLRV - * =E2=94=9C=E2=94=80 110100 =E2=94=80 OPC_MXU_Q16SLL =E2=94=9C= =E2=94=80 010 =E2=94=80 OPC_MXU_D32SARV - * =E2=94=9C=E2=94=80 110101 =E2=94=80 OPC_MXU_Q16SLR =E2=94=9C= =E2=94=80 011 =E2=94=80 OPC_MXU_Q16SLLV - * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_Q16SLRV - * =E2=94=9C=E2=94=80 110110 =E2=94=80 OPC_MXU__POOL18 =E2=94=80= =E2=94=B4=E2=94=80 101 =E2=94=80 OPC_MXU_Q16SARV - * =E2=94=82 - * =E2=94=9C=E2=94=80 110111 =E2=94=80 OPC_MXU_Q16SAR - * =E2=94=82 23..22 - * =E2=94=9C=E2=94=80 111000 =E2=94=80 OPC_MXU__POOL19 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_Q8MUL - * =E2=94=82 =E2=94=94=E2=94=80 01 =E2= =94=80 OPC_MXU_Q8MULSU - * =E2=94=82 - * =E2=94=82 20..18 - * =E2=94=9C=E2=94=80 111001 =E2=94=80 OPC_MXU__POOL20 =E2=94=80= =E2=94=AC=E2=94=80 000 =E2=94=80 OPC_MXU_Q8MOVZ - * =E2=94=82 =E2=94=9C=E2=94=80 001 = =E2=94=80 OPC_MXU_Q8MOVN - * =E2=94=82 =E2=94=9C=E2=94=80 010 = =E2=94=80 OPC_MXU_D16MOVZ - * =E2=94=82 =E2=94=9C=E2=94=80 011 = =E2=94=80 OPC_MXU_D16MOVN - * =E2=94=82 =E2=94=9C=E2=94=80 100 = =E2=94=80 OPC_MXU_S32MOVZ - * =E2=94=82 =E2=94=94=E2=94=80 101 = =E2=94=80 OPC_MXU_S32MOVN - * =E2=94=82 - * =E2=94=82 23..22 - * =E2=94=9C=E2=94=80 111010 =E2=94=80 OPC_MXU__POOL21 =E2=94=80= =E2=94=AC=E2=94=80 00 =E2=94=80 OPC_MXU_Q8MAC - * =E2=94=82 =E2=94=94=E2=94=80 10 =E2= =94=80 OPC_MXU_Q8MACSU - * =E2=94=9C=E2=94=80 111011 =E2=94=80 OPC_MXU_Q16SCOP - * =E2=94=9C=E2=94=80 111100 =E2=94=80 OPC_MXU_Q8MADL - * =E2=94=9C=E2=94=80 111101 =E2=94=80 OPC_MXU_S32SFL - * =E2=94=9C=E2=94=80 111110 =E2=94=80 OPC_MXU_Q8SAD - * =E2=94=94=E2=94=80 111111 =E2=94=80 (overlaps= with SDBBP) - * - * - * Compiled after: - * - * "XBurst=C2=AE Instruction Set Architecture MIPS eXtension/enhanced Un= it - * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2,= 2017 - */ - -enum { - OPC_MXU__POOL00 =3D 0x03, - OPC_MXU_D16MUL =3D 0x08, - OPC_MXU_D16MAC =3D 0x0A, - OPC_MXU__POOL04 =3D 0x10, - OPC_MXU_S8LDD =3D 0x22, - OPC_MXU__POOL16 =3D 0x27, - OPC_MXU_S32M2I =3D 0x2E, - OPC_MXU_S32I2M =3D 0x2F, - OPC_MXU__POOL19 =3D 0x38, -}; - - -/* - * MXU pool 00 - */ -enum { - OPC_MXU_S32MAX =3D 0x00, - OPC_MXU_S32MIN =3D 0x01, - OPC_MXU_D16MAX =3D 0x02, - OPC_MXU_D16MIN =3D 0x03, - OPC_MXU_Q8MAX =3D 0x04, - OPC_MXU_Q8MIN =3D 0x05, -}; - -/* - * MXU pool 04 - */ -enum { - OPC_MXU_S32LDD =3D 0x00, - OPC_MXU_S32LDDR =3D 0x01, -}; - -/* - * MXU pool 16 - */ -enum { - OPC_MXU_S32ALNI =3D 0x02, - OPC_MXU_S32NOR =3D 0x04, - OPC_MXU_S32AND =3D 0x05, - OPC_MXU_S32OR =3D 0x06, - OPC_MXU_S32XOR =3D 0x07, -}; - -/* - * MXU pool 19 - */ -enum { - OPC_MXU_Q8MUL =3D 0x00, - OPC_MXU_Q8MULSU =3D 0x01, -}; - /* * Overview of the TX79-specific instruction set * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D @@ -1965,12 +1579,6 @@ static TCGv_i32 hflags; TCGv_i32 fpu_fcr0, fpu_fcr31; TCGv_i64 fpu_f64[32]; =20 -#if !defined(TARGET_MIPS64) -/* MXU registers */ -static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; -static TCGv mxu_CR; -#endif - #include "exec/gen-icount.h" =20 #define gen_helper_0e0i(name, arg) do { \ @@ -2040,26 +1648,6 @@ static const char * const fregnames[] =3D { "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; =20 -#if !defined(TARGET_MIPS64) -static const char * const mxuregnames[] =3D { - "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8", - "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR", -}; - -void mxu_translate_init(void) -{ - for (unsigned i =3D 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) { - mxu_gpr[i] =3D tcg_global_mem_new(cpu_env, - offsetof(CPUMIPSState, active_tc.m= xu_gpr[i]), - mxuregnames[i]); - } - - mxu_CR =3D tcg_global_mem_new(cpu_env, - offsetof(CPUMIPSState, active_tc.mxu_cr), - mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]); -} -#endif /* !TARGET_MIPS64 */ - /* General purpose registers moves. */ void gen_load_gpr(TCGv t, int reg) { @@ -2143,38 +1731,6 @@ static inline void gen_store_srsgpr(int from, int to) } } =20 -#if !defined(TARGET_MIPS64) -/* MXU General purpose registers moves. */ -static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg) -{ - if (reg =3D=3D 0) { - tcg_gen_movi_tl(t, 0); - } else if (reg <=3D 15) { - tcg_gen_mov_tl(t, mxu_gpr[reg - 1]); - } -} - -static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg) -{ - if (reg > 0 && reg <=3D 15) { - tcg_gen_mov_tl(mxu_gpr[reg - 1], t); - } -} - -/* MXU control register moves. */ -static inline void gen_load_mxu_cr(TCGv t) -{ - tcg_gen_mov_tl(t, mxu_CR); -} - -static inline void gen_store_mxu_cr(TCGv t) -{ - /* TODO: Add handling of RW rules for MXU_CR. */ - tcg_gen_mov_tl(mxu_CR, t); -} -#endif - - /* Tests */ static inline void gen_save_pc(target_ulong pc) { @@ -24690,1167 +24246,6 @@ static void gen_mmi_pcpyud(DisasContext *ctx) =20 #endif =20 - -#if !defined(TARGET_MIPS64) - -/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */ -#define MXU_APTN1_A 0 -#define MXU_APTN1_S 1 - -/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */ -#define MXU_APTN2_AA 0 -#define MXU_APTN2_AS 1 -#define MXU_APTN2_SA 2 -#define MXU_APTN2_SS 3 - -/* MXU execute add/subtract 2-bit pattern 'eptn2' */ -#define MXU_EPTN2_AA 0 -#define MXU_EPTN2_AS 1 -#define MXU_EPTN2_SA 2 -#define MXU_EPTN2_SS 3 - -/* MXU operand getting pattern 'optn2' */ -#define MXU_OPTN2_PTN0 0 -#define MXU_OPTN2_PTN1 1 -#define MXU_OPTN2_PTN2 2 -#define MXU_OPTN2_PTN3 3 -/* alternative naming scheme for 'optn2' */ -#define MXU_OPTN2_WW 0 -#define MXU_OPTN2_LW 1 -#define MXU_OPTN2_HW 2 -#define MXU_OPTN2_XW 3 - -/* MXU operand getting pattern 'optn3' */ -#define MXU_OPTN3_PTN0 0 -#define MXU_OPTN3_PTN1 1 -#define MXU_OPTN3_PTN2 2 -#define MXU_OPTN3_PTN3 3 -#define MXU_OPTN3_PTN4 4 -#define MXU_OPTN3_PTN5 5 -#define MXU_OPTN3_PTN6 6 -#define MXU_OPTN3_PTN7 7 - - -/* - * S32I2M XRa, rb - Register move from GRF to XRF - */ -static void gen_mxu_s32i2m(DisasContext *ctx) -{ - TCGv t0; - uint32_t XRa, Rb; - - t0 =3D tcg_temp_new(); - - XRa =3D extract32(ctx->opcode, 6, 5); - Rb =3D extract32(ctx->opcode, 16, 5); - - gen_load_gpr(t0, Rb); - if (XRa <=3D 15) { - gen_store_mxu_gpr(t0, XRa); - } else if (XRa =3D=3D 16) { - gen_store_mxu_cr(t0); - } - - tcg_temp_free(t0); -} - -/* - * S32M2I XRa, rb - Register move from XRF to GRF - */ -static void gen_mxu_s32m2i(DisasContext *ctx) -{ - TCGv t0; - uint32_t XRa, Rb; - - t0 =3D tcg_temp_new(); - - XRa =3D extract32(ctx->opcode, 6, 5); - Rb =3D extract32(ctx->opcode, 16, 5); - - if (XRa <=3D 15) { - gen_load_mxu_gpr(t0, XRa); - } else if (XRa =3D=3D 16) { - gen_load_mxu_cr(t0); - } - - gen_store_gpr(t0, Rb); - - tcg_temp_free(t0); -} - -/* - * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF - */ -static void gen_mxu_s8ldd(DisasContext *ctx) -{ - TCGv t0, t1; - uint32_t XRa, Rb, s8, optn3; - - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); - - XRa =3D extract32(ctx->opcode, 6, 4); - s8 =3D extract32(ctx->opcode, 10, 8); - optn3 =3D extract32(ctx->opcode, 18, 3); - Rb =3D extract32(ctx->opcode, 21, 5); - - gen_load_gpr(t0, Rb); - tcg_gen_addi_tl(t0, t0, (int8_t)s8); - - switch (optn3) { - /* XRa[7:0] =3D tmp8 */ - case MXU_OPTN3_PTN0: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - gen_load_mxu_gpr(t0, XRa); - tcg_gen_deposit_tl(t0, t0, t1, 0, 8); - break; - /* XRa[15:8] =3D tmp8 */ - case MXU_OPTN3_PTN1: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - gen_load_mxu_gpr(t0, XRa); - tcg_gen_deposit_tl(t0, t0, t1, 8, 8); - break; - /* XRa[23:16] =3D tmp8 */ - case MXU_OPTN3_PTN2: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - gen_load_mxu_gpr(t0, XRa); - tcg_gen_deposit_tl(t0, t0, t1, 16, 8); - break; - /* XRa[31:24] =3D tmp8 */ - case MXU_OPTN3_PTN3: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - gen_load_mxu_gpr(t0, XRa); - tcg_gen_deposit_tl(t0, t0, t1, 24, 8); - break; - /* XRa =3D {8'b0, tmp8, 8'b0, tmp8} */ - case MXU_OPTN3_PTN4: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_deposit_tl(t0, t1, t1, 16, 16); - break; - /* XRa =3D {tmp8, 8'b0, tmp8, 8'b0} */ - case MXU_OPTN3_PTN5: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_shli_tl(t1, t1, 8); - tcg_gen_deposit_tl(t0, t1, t1, 16, 16); - break; - /* XRa =3D {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */ - case MXU_OPTN3_PTN6: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB); - tcg_gen_mov_tl(t0, t1); - tcg_gen_andi_tl(t0, t0, 0xFF00FFFF); - tcg_gen_shli_tl(t1, t1, 16); - tcg_gen_or_tl(t0, t0, t1); - break; - /* XRa =3D {tmp8, tmp8, tmp8, tmp8} */ - case MXU_OPTN3_PTN7: - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); - tcg_gen_deposit_tl(t1, t1, t1, 8, 8); - tcg_gen_deposit_tl(t0, t1, t1, 16, 16); - break; - } - - gen_store_mxu_gpr(t0, XRa); - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -/* - * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication - */ -static void gen_mxu_d16mul(DisasContext *ctx) -{ - TCGv t0, t1, t2, t3; - uint32_t XRa, XRb, XRc, XRd, optn2; - - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); - t2 =3D tcg_temp_new(); - t3 =3D tcg_temp_new(); - - XRa =3D extract32(ctx->opcode, 6, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRc =3D extract32(ctx->opcode, 14, 4); - XRd =3D extract32(ctx->opcode, 18, 4); - optn2 =3D extract32(ctx->opcode, 22, 2); - - gen_load_mxu_gpr(t1, XRb); - tcg_gen_sextract_tl(t0, t1, 0, 16); - tcg_gen_sextract_tl(t1, t1, 16, 16); - gen_load_mxu_gpr(t3, XRc); - tcg_gen_sextract_tl(t2, t3, 0, 16); - tcg_gen_sextract_tl(t3, t3, 16, 16); - - switch (optn2) { - case MXU_OPTN2_WW: /* XRB.H*XRC.H =3D=3D lop, XRB.L*XRC.L =3D=3D rop */ - tcg_gen_mul_tl(t3, t1, t3); - tcg_gen_mul_tl(t2, t0, t2); - break; - case MXU_OPTN2_LW: /* XRB.L*XRC.H =3D=3D lop, XRB.L*XRC.L =3D=3D rop */ - tcg_gen_mul_tl(t3, t0, t3); - tcg_gen_mul_tl(t2, t0, t2); - break; - case MXU_OPTN2_HW: /* XRB.H*XRC.H =3D=3D lop, XRB.H*XRC.L =3D=3D rop */ - tcg_gen_mul_tl(t3, t1, t3); - tcg_gen_mul_tl(t2, t1, t2); - break; - case MXU_OPTN2_XW: /* XRB.L*XRC.H =3D=3D lop, XRB.H*XRC.L =3D=3D rop */ - tcg_gen_mul_tl(t3, t0, t3); - tcg_gen_mul_tl(t2, t1, t2); - break; - } - gen_store_mxu_gpr(t3, XRa); - gen_store_mxu_gpr(t2, XRd); - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); - tcg_temp_free(t3); -} - -/* - * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply - * and accumulate - */ -static void gen_mxu_d16mac(DisasContext *ctx) -{ - TCGv t0, t1, t2, t3; - uint32_t XRa, XRb, XRc, XRd, optn2, aptn2; - - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); - t2 =3D tcg_temp_new(); - t3 =3D tcg_temp_new(); - - XRa =3D extract32(ctx->opcode, 6, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRc =3D extract32(ctx->opcode, 14, 4); - XRd =3D extract32(ctx->opcode, 18, 4); - optn2 =3D extract32(ctx->opcode, 22, 2); - aptn2 =3D extract32(ctx->opcode, 24, 2); - - gen_load_mxu_gpr(t1, XRb); - tcg_gen_sextract_tl(t0, t1, 0, 16); - tcg_gen_sextract_tl(t1, t1, 16, 16); - - gen_load_mxu_gpr(t3, XRc); - tcg_gen_sextract_tl(t2, t3, 0, 16); - tcg_gen_sextract_tl(t3, t3, 16, 16); - - switch (optn2) { - case MXU_OPTN2_WW: /* XRB.H*XRC.H =3D=3D lop, XRB.L*XRC.L =3D=3D rop */ - tcg_gen_mul_tl(t3, t1, t3); - tcg_gen_mul_tl(t2, t0, t2); - break; - case MXU_OPTN2_LW: /* XRB.L*XRC.H =3D=3D lop, XRB.L*XRC.L =3D=3D rop */ - tcg_gen_mul_tl(t3, t0, t3); - tcg_gen_mul_tl(t2, t0, t2); - break; - case MXU_OPTN2_HW: /* XRB.H*XRC.H =3D=3D lop, XRB.H*XRC.L =3D=3D rop */ - tcg_gen_mul_tl(t3, t1, t3); - tcg_gen_mul_tl(t2, t1, t2); - break; - case MXU_OPTN2_XW: /* XRB.L*XRC.H =3D=3D lop, XRB.H*XRC.L =3D=3D rop */ - tcg_gen_mul_tl(t3, t0, t3); - tcg_gen_mul_tl(t2, t1, t2); - break; - } - gen_load_mxu_gpr(t0, XRa); - gen_load_mxu_gpr(t1, XRd); - - switch (aptn2) { - case MXU_APTN2_AA: - tcg_gen_add_tl(t3, t0, t3); - tcg_gen_add_tl(t2, t1, t2); - break; - case MXU_APTN2_AS: - tcg_gen_add_tl(t3, t0, t3); - tcg_gen_sub_tl(t2, t1, t2); - break; - case MXU_APTN2_SA: - tcg_gen_sub_tl(t3, t0, t3); - tcg_gen_add_tl(t2, t1, t2); - break; - case MXU_APTN2_SS: - tcg_gen_sub_tl(t3, t0, t3); - tcg_gen_sub_tl(t2, t1, t2); - break; - } - gen_store_mxu_gpr(t3, XRa); - gen_store_mxu_gpr(t2, XRd); - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); - tcg_temp_free(t3); -} - -/* - * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply - * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply - */ -static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx) -{ - TCGv t0, t1, t2, t3, t4, t5, t6, t7; - uint32_t XRa, XRb, XRc, XRd, sel; - - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); - t2 =3D tcg_temp_new(); - t3 =3D tcg_temp_new(); - t4 =3D tcg_temp_new(); - t5 =3D tcg_temp_new(); - t6 =3D tcg_temp_new(); - t7 =3D tcg_temp_new(); - - XRa =3D extract32(ctx->opcode, 6, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRc =3D extract32(ctx->opcode, 14, 4); - XRd =3D extract32(ctx->opcode, 18, 4); - sel =3D extract32(ctx->opcode, 22, 2); - - gen_load_mxu_gpr(t3, XRb); - gen_load_mxu_gpr(t7, XRc); - - if (sel =3D=3D 0x2) { - /* Q8MULSU */ - tcg_gen_ext8s_tl(t0, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8s_tl(t1, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8s_tl(t2, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8s_tl(t3, t3); - } else { - /* Q8MUL */ - tcg_gen_ext8u_tl(t0, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8u_tl(t1, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8u_tl(t2, t3); - tcg_gen_shri_tl(t3, t3, 8); - tcg_gen_ext8u_tl(t3, t3); - } - - tcg_gen_ext8u_tl(t4, t7); - tcg_gen_shri_tl(t7, t7, 8); - tcg_gen_ext8u_tl(t5, t7); - tcg_gen_shri_tl(t7, t7, 8); - tcg_gen_ext8u_tl(t6, t7); - tcg_gen_shri_tl(t7, t7, 8); - tcg_gen_ext8u_tl(t7, t7); - - tcg_gen_mul_tl(t0, t0, t4); - tcg_gen_mul_tl(t1, t1, t5); - tcg_gen_mul_tl(t2, t2, t6); - tcg_gen_mul_tl(t3, t3, t7); - - tcg_gen_andi_tl(t0, t0, 0xFFFF); - tcg_gen_andi_tl(t1, t1, 0xFFFF); - tcg_gen_andi_tl(t2, t2, 0xFFFF); - tcg_gen_andi_tl(t3, t3, 0xFFFF); - - tcg_gen_shli_tl(t1, t1, 16); - tcg_gen_shli_tl(t3, t3, 16); - - tcg_gen_or_tl(t0, t0, t1); - tcg_gen_or_tl(t1, t2, t3); - - gen_store_mxu_gpr(t0, XRd); - gen_store_mxu_gpr(t1, XRa); - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); - tcg_temp_free(t3); - tcg_temp_free(t4); - tcg_temp_free(t5); - tcg_temp_free(t6); - tcg_temp_free(t7); -} - -/* - * S32LDD XRa, Rb, S12 - Load a word from memory to XRF - * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte se= q. - */ -static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx) -{ - TCGv t0, t1; - uint32_t XRa, Rb, s12, sel; - - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); - - XRa =3D extract32(ctx->opcode, 6, 4); - s12 =3D extract32(ctx->opcode, 10, 10); - sel =3D extract32(ctx->opcode, 20, 1); - Rb =3D extract32(ctx->opcode, 21, 5); - - gen_load_gpr(t0, Rb); - - tcg_gen_movi_tl(t1, s12); - tcg_gen_shli_tl(t1, t1, 2); - if (s12 & 0x200) { - tcg_gen_ori_tl(t1, t1, 0xFFFFF000); - } - tcg_gen_add_tl(t1, t0, t1); - tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL); - - if (sel =3D=3D 1) { - /* S32LDDR */ - tcg_gen_bswap32_tl(t1, t1); - } - gen_store_mxu_gpr(t1, XRa); - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - - -/* - * MXU instruction category: logic - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * S32NOR S32AND S32OR S32XOR - */ - -/* - * S32NOR XRa, XRb, XRc - * Update XRa with the result of logical bitwise 'nor' operation - * applied to the content of XRb and XRc. - */ -static void gen_mxu_S32NOR(DisasContext *ctx) -{ - uint32_t pad, XRc, XRb, XRa; - - pad =3D extract32(ctx->opcode, 21, 5); - XRc =3D extract32(ctx->opcode, 14, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRa =3D extract32(ctx->opcode, 6, 4); - - if (unlikely(pad !=3D 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa =3D=3D 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { - /* both operands zero registers -> just set destination to all 1s = */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF); - } else if (unlikely(XRb =3D=3D 0)) { - /* XRb zero register -> just set destination to the negation of XR= c */ - tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - } else if (unlikely(XRc =3D=3D 0)) { - /* XRa zero register -> just set destination to the negation of XR= b */ - tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else if (unlikely(XRb =3D=3D XRc)) { - /* both operands same -> just set destination to the negation of X= Rb */ - tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - = 1]); - } -} - -/* - * S32AND XRa, XRb, XRc - * Update XRa with the result of logical bitwise 'and' operation - * applied to the content of XRb and XRc. - */ -static void gen_mxu_S32AND(DisasContext *ctx) -{ - uint32_t pad, XRc, XRb, XRa; - - pad =3D extract32(ctx->opcode, 21, 5); - XRc =3D extract32(ctx->opcode, 14, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRa =3D extract32(ctx->opcode, 6, 4); - - if (unlikely(pad !=3D 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa =3D=3D 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb =3D=3D 0) || (XRc =3D=3D 0))) { - /* one of operands zero register -> just set destination to all 0s= */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely(XRb =3D=3D XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - = 1]); - } -} - -/* - * S32OR XRa, XRb, XRc - * Update XRa with the result of logical bitwise 'or' operation - * applied to the content of XRb and XRc. - */ -static void gen_mxu_S32OR(DisasContext *ctx) -{ - uint32_t pad, XRc, XRb, XRa; - - pad =3D extract32(ctx->opcode, 21, 5); - XRc =3D extract32(ctx->opcode, 14, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRa =3D extract32(ctx->opcode, 6, 4); - - if (unlikely(pad !=3D 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa =3D=3D 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { - /* both operands zero registers -> just set destination to all 0s = */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely(XRb =3D=3D 0)) { - /* XRb zero register -> just set destination to the content of XRc= */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - } else if (unlikely(XRc =3D=3D 0)) { - /* XRc zero register -> just set destination to the content of XRb= */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else if (unlikely(XRb =3D=3D XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1= ]); - } -} - -/* - * S32XOR XRa, XRb, XRc - * Update XRa with the result of logical bitwise 'xor' operation - * applied to the content of XRb and XRc. - */ -static void gen_mxu_S32XOR(DisasContext *ctx) -{ - uint32_t pad, XRc, XRb, XRa; - - pad =3D extract32(ctx->opcode, 21, 5); - XRc =3D extract32(ctx->opcode, 14, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRa =3D extract32(ctx->opcode, 6, 4); - - if (unlikely(pad !=3D 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa =3D=3D 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { - /* both operands zero registers -> just set destination to all 0s = */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely(XRb =3D=3D 0)) { - /* XRb zero register -> just set destination to the content of XRc= */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - } else if (unlikely(XRc =3D=3D 0)) { - /* XRc zero register -> just set destination to the content of XRb= */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else if (unlikely(XRb =3D=3D XRc)) { - /* both operands same -> just set destination to all 0s */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else { - /* the most general case */ - tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - = 1]); - } -} - - -/* - * MXU instruction category max/min - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * S32MAX D16MAX Q8MAX - * S32MIN D16MIN Q8MIN - */ - -/* - * S32MAX XRa, XRb, XRc - * Update XRa with the maximum of signed 32-bit integers contained - * in XRb and XRc. - * - * S32MIN XRa, XRb, XRc - * Update XRa with the minimum of signed 32-bit integers contained - * in XRb and XRc. - */ -static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx) -{ - uint32_t pad, opc, XRc, XRb, XRa; - - pad =3D extract32(ctx->opcode, 21, 5); - opc =3D extract32(ctx->opcode, 18, 3); - XRc =3D extract32(ctx->opcode, 14, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRa =3D extract32(ctx->opcode, 6, 4); - - if (unlikely(pad !=3D 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa =3D=3D 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { - /* both operands zero registers -> just set destination to zero */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely((XRb =3D=3D 0) || (XRc =3D=3D 0))) { - /* exactly one operand is zero register - find which one is not...= */ - uint32_t XRx =3D XRb ? XRb : XRc; - /* ...and do max/min operation with one operand 0 */ - if (opc =3D=3D OPC_MXU_S32MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); - } - } else if (unlikely(XRb =3D=3D XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - if (opc =3D=3D OPC_MXU_S32MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], - mxu_gpr[XRc - 1]); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], - mxu_gpr[XRc - 1]); - } - } -} - -/* - * D16MAX - * Update XRa with the 16-bit-wise maximums of signed integers - * contained in XRb and XRc. - * - * D16MIN - * Update XRa with the 16-bit-wise minimums of signed integers - * contained in XRb and XRc. - */ -static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) -{ - uint32_t pad, opc, XRc, XRb, XRa; - - pad =3D extract32(ctx->opcode, 21, 5); - opc =3D extract32(ctx->opcode, 18, 3); - XRc =3D extract32(ctx->opcode, 14, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRa =3D extract32(ctx->opcode, 6, 4); - - if (unlikely(pad !=3D 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRc =3D=3D 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb =3D=3D 0) && (XRa =3D=3D 0))) { - /* both operands zero registers -> just set destination to zero */ - tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0); - } else if (unlikely((XRb =3D=3D 0) || (XRa =3D=3D 0))) { - /* exactly one operand is zero register - find which one is not...= */ - uint32_t XRx =3D XRb ? XRb : XRc; - /* ...and do half-word-wise max/min with one operand 0 */ - TCGv_i32 t0 =3D tcg_temp_new(); - TCGv_i32 t1 =3D tcg_const_i32(0); - - /* the left half-word first */ - tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000); - if (opc =3D=3D OPC_MXU_D16MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); - } - - /* the right half-word */ - tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF); - /* move half-words to the leftmost position */ - tcg_gen_shli_i32(t0, t0, 16); - /* t0 will be max/min of t0 and t1 */ - if (opc =3D=3D OPC_MXU_D16MAX) { - tcg_gen_smax_i32(t0, t0, t1); - } else { - tcg_gen_smin_i32(t0, t0, t1); - } - /* return resulting half-words to its original position */ - tcg_gen_shri_i32(t0, t0, 16); - /* finally update the destination */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } else if (unlikely(XRb =3D=3D XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - TCGv_i32 t0 =3D tcg_temp_new(); - TCGv_i32 t1 =3D tcg_temp_new(); - - /* the left half-word first */ - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000); - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000); - if (opc =3D=3D OPC_MXU_D16MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); - } - - /* the right half-word */ - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF); - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF); - /* move half-words to the leftmost position */ - tcg_gen_shli_i32(t0, t0, 16); - tcg_gen_shli_i32(t1, t1, 16); - /* t0 will be max/min of t0 and t1 */ - if (opc =3D=3D OPC_MXU_D16MAX) { - tcg_gen_smax_i32(t0, t0, t1); - } else { - tcg_gen_smin_i32(t0, t0, t1); - } - /* return resulting half-words to its original position */ - tcg_gen_shri_i32(t0, t0, 16); - /* finally update the destination */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } -} - -/* - * Q8MAX - * Update XRa with the 8-bit-wise maximums of signed integers - * contained in XRb and XRc. - * - * Q8MIN - * Update XRa with the 8-bit-wise minimums of signed integers - * contained in XRb and XRc. - */ -static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx) -{ - uint32_t pad, opc, XRc, XRb, XRa; - - pad =3D extract32(ctx->opcode, 21, 5); - opc =3D extract32(ctx->opcode, 18, 3); - XRc =3D extract32(ctx->opcode, 14, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRa =3D extract32(ctx->opcode, 6, 4); - - if (unlikely(pad !=3D 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa =3D=3D 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { - /* both operands zero registers -> just set destination to zero */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely((XRb =3D=3D 0) || (XRc =3D=3D 0))) { - /* exactly one operand is zero register - make it be the first...*/ - uint32_t XRx =3D XRb ? XRb : XRc; - /* ...and do byte-wise max/min with one operand 0 */ - TCGv_i32 t0 =3D tcg_temp_new(); - TCGv_i32 t1 =3D tcg_const_i32(0); - int32_t i; - - /* the leftmost byte (byte 3) first */ - tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000); - if (opc =3D=3D OPC_MXU_Q8MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); - } - - /* bytes 2, 1, 0 */ - for (i =3D 2; i >=3D 0; i--) { - /* extract the byte */ - tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i)); - /* move the byte to the leftmost position */ - tcg_gen_shli_i32(t0, t0, 8 * (3 - i)); - /* t0 will be max/min of t0 and t1 */ - if (opc =3D=3D OPC_MXU_Q8MAX) { - tcg_gen_smax_i32(t0, t0, t1); - } else { - tcg_gen_smin_i32(t0, t0, t1); - } - /* return resulting byte to its original position */ - tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); - /* finally update the destination */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); - } - - tcg_temp_free(t1); - tcg_temp_free(t0); - } else if (unlikely(XRb =3D=3D XRc)) { - /* both operands same -> just set destination to one of them */ - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } else { - /* the most general case */ - TCGv_i32 t0 =3D tcg_temp_new(); - TCGv_i32 t1 =3D tcg_temp_new(); - int32_t i; - - /* the leftmost bytes (bytes 3) first */ - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000); - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000); - if (opc =3D=3D OPC_MXU_Q8MAX) { - tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1); - } else { - tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1); - } - - /* bytes 2, 1, 0 */ - for (i =3D 2; i >=3D 0; i--) { - /* extract corresponding bytes */ - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i)); - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i)); - /* move the bytes to the leftmost position */ - tcg_gen_shli_i32(t0, t0, 8 * (3 - i)); - tcg_gen_shli_i32(t1, t1, 8 * (3 - i)); - /* t0 will be max/min of t0 and t1 */ - if (opc =3D=3D OPC_MXU_Q8MAX) { - tcg_gen_smax_i32(t0, t0, t1); - } else { - tcg_gen_smin_i32(t0, t0, t1); - } - /* return resulting byte to its original position */ - tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); - /* finally update the destination */ - tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); - } - - tcg_temp_free(t1); - tcg_temp_free(t0); - } -} - - -/* - * MXU instruction category: align - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * S32ALN S32ALNI - */ - -/* - * S32ALNI XRc, XRb, XRa, optn3 - * Arrange bytes from XRb and XRc according to one of five sets of - * rules determined by optn3, and place the result in XRa. - */ -static void gen_mxu_S32ALNI(DisasContext *ctx) -{ - uint32_t optn3, pad, XRc, XRb, XRa; - - optn3 =3D extract32(ctx->opcode, 23, 3); - pad =3D extract32(ctx->opcode, 21, 2); - XRc =3D extract32(ctx->opcode, 14, 4); - XRb =3D extract32(ctx->opcode, 10, 4); - XRa =3D extract32(ctx->opcode, 6, 4); - - if (unlikely(pad !=3D 0)) { - /* opcode padding incorrect -> do nothing */ - } else if (unlikely(XRa =3D=3D 0)) { - /* destination is zero register -> do nothing */ - } else if (unlikely((XRb =3D=3D 0) && (XRc =3D=3D 0))) { - /* both operands zero registers -> just set destination to all 0s = */ - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - } else if (unlikely(XRb =3D=3D 0)) { - /* XRb zero register -> just appropriatelly shift XRc into XRa */ - switch (optn3) { - case MXU_OPTN3_PTN0: - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - break; - case MXU_OPTN3_PTN1: - case MXU_OPTN3_PTN2: - case MXU_OPTN3_PTN3: - tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1], - 8 * (4 - optn3)); - break; - case MXU_OPTN3_PTN4: - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - break; - } - } else if (unlikely(XRc =3D=3D 0)) { - /* XRc zero register -> just appropriatelly shift XRb into XRa */ - switch (optn3) { - case MXU_OPTN3_PTN0: - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - break; - case MXU_OPTN3_PTN1: - case MXU_OPTN3_PTN2: - case MXU_OPTN3_PTN3: - tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3= ); - break; - case MXU_OPTN3_PTN4: - tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); - break; - } - } else if (unlikely(XRb =3D=3D XRc)) { - /* both operands same -> just rotation or moving from any of them = */ - switch (optn3) { - case MXU_OPTN3_PTN0: - case MXU_OPTN3_PTN4: - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - break; - case MXU_OPTN3_PTN1: - case MXU_OPTN3_PTN2: - case MXU_OPTN3_PTN3: - tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn= 3); - break; - } - } else { - /* the most general case */ - switch (optn3) { - case MXU_OPTN3_PTN0: - { - /* */ - /* XRb XRc */ - /* +---------------+ */ - /* | A B C D | E F G H */ - /* +-------+-------+ */ - /* | */ - /* XRa */ - /* */ - - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); - } - break; - case MXU_OPTN3_PTN1: - { - /* */ - /* XRb XRc */ - /* +-------------------+ */ - /* A | B C D E | F G H */ - /* +---------+---------+ */ - /* | */ - /* XRa */ - /* */ - - TCGv_i32 t0 =3D tcg_temp_new(); - TCGv_i32 t1 =3D tcg_temp_new(); - - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF); - tcg_gen_shli_i32(t0, t0, 8); - - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000); - tcg_gen_shri_i32(t1, t1, 24); - - tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } - break; - case MXU_OPTN3_PTN2: - { - /* */ - /* XRb XRc */ - /* +-------------------+ */ - /* A B | C D E F | G H */ - /* +---------+---------+ */ - /* | */ - /* XRa */ - /* */ - - TCGv_i32 t0 =3D tcg_temp_new(); - TCGv_i32 t1 =3D tcg_temp_new(); - - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF); - tcg_gen_shli_i32(t0, t0, 16); - - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000); - tcg_gen_shri_i32(t1, t1, 16); - - tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } - break; - case MXU_OPTN3_PTN3: - { - /* */ - /* XRb XRc */ - /* +-------------------+ */ - /* A B C | D E F G | H */ - /* +---------+---------+ */ - /* | */ - /* XRa */ - /* */ - - TCGv_i32 t0 =3D tcg_temp_new(); - TCGv_i32 t1 =3D tcg_temp_new(); - - tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF); - tcg_gen_shli_i32(t0, t0, 24); - - tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00); - tcg_gen_shri_i32(t1, t1, 8); - - tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1); - - tcg_temp_free(t1); - tcg_temp_free(t0); - } - break; - case MXU_OPTN3_PTN4: - { - /* */ - /* XRb XRc */ - /* +---------------+ */ - /* A B C D | E F G H | */ - /* +-------+-------+ */ - /* | */ - /* XRa */ - /* */ - - tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]); - } - break; - } - } -} - - -/* - * Decoding engine for MXU - * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - */ - -static void decode_opc_mxu__pool00(DisasContext *ctx) -{ - uint32_t opcode =3D extract32(ctx->opcode, 18, 3); - - switch (opcode) { - case OPC_MXU_S32MAX: - case OPC_MXU_S32MIN: - gen_mxu_S32MAX_S32MIN(ctx); - break; - case OPC_MXU_D16MAX: - case OPC_MXU_D16MIN: - gen_mxu_D16MAX_D16MIN(ctx); - break; - case OPC_MXU_Q8MAX: - case OPC_MXU_Q8MIN: - gen_mxu_Q8MAX_Q8MIN(ctx); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - gen_reserved_instruction(ctx); - break; - } -} - -static void decode_opc_mxu__pool04(DisasContext *ctx) -{ - uint32_t opcode =3D extract32(ctx->opcode, 20, 1); - - switch (opcode) { - case OPC_MXU_S32LDD: - case OPC_MXU_S32LDDR: - gen_mxu_s32ldd_s32lddr(ctx); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - gen_reserved_instruction(ctx); - break; - } -} - -static void decode_opc_mxu__pool16(DisasContext *ctx) -{ - uint32_t opcode =3D extract32(ctx->opcode, 18, 3); - - switch (opcode) { - case OPC_MXU_S32ALNI: - gen_mxu_S32ALNI(ctx); - break; - case OPC_MXU_S32NOR: - gen_mxu_S32NOR(ctx); - break; - case OPC_MXU_S32AND: - gen_mxu_S32AND(ctx); - break; - case OPC_MXU_S32OR: - gen_mxu_S32OR(ctx); - break; - case OPC_MXU_S32XOR: - gen_mxu_S32XOR(ctx); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - gen_reserved_instruction(ctx); - break; - } -} - -static void decode_opc_mxu__pool19(DisasContext *ctx) -{ - uint32_t opcode =3D extract32(ctx->opcode, 22, 2); - - switch (opcode) { - case OPC_MXU_Q8MUL: - case OPC_MXU_Q8MULSU: - gen_mxu_q8mul_q8mulsu(ctx); - break; - default: - MIPS_INVAL("decode_opc_mxu"); - gen_reserved_instruction(ctx); - break; - } -} - -/* - * Main MXU decoding function - */ -bool decode_ase_mxu(DisasContext *ctx, uint32_t insn) -{ - uint32_t opcode =3D extract32(insn, 0, 6); - - if (opcode =3D=3D OPC_MXU_S32M2I) { - gen_mxu_s32m2i(ctx); - return true; - } - - if (opcode =3D=3D OPC_MXU_S32I2M) { - gen_mxu_s32i2m(ctx); - return true; - } - - { - TCGv t_mxu_cr =3D tcg_temp_new(); - TCGLabel *l_exit =3D 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); - } - - gen_set_label(l_exit); - tcg_temp_free(t_mxu_cr); - } - - return true; -} - -#endif /* !defined(TARGET_MIPS64) */ - - static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ct= x) { int rs, rt, rd; diff --git a/target/mips/meson.build b/target/mips/meson.build index 53580633ce0..4a951e522d4 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -24,6 +24,10 @@ 'translate.c', 'translate_addr_const.c', )) +mips_tcg_ss.add(when: 'TARGET_MIPS64', if_false: files( + 'mxu_translate.c', +)) + mips_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) =20 mips_softmmu_ss =3D ss.source_set() --=20 2.26.2