Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2222286/?format=api
{ "id": 2222286, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2222286/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260411070637.72421-4-james.hilliard1@gmail.com/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/1.1/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260411070637.72421-4-james.hilliard1@gmail.com>", "date": "2026-04-11T07:06:30", "name": "[4/9] target/mips: add Octeon COP2 crypto core support", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "3479039d67e932743817bf5d386a7b76ea7972c5", "submitter": { "id": 66301, "url": "http://patchwork.ozlabs.org/api/1.1/people/66301/?format=api", "name": "James Hilliard", "email": "james.hilliard1@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260411070637.72421-4-james.hilliard1@gmail.com/mbox/", "series": [ { "id": 499531, "url": "http://patchwork.ozlabs.org/api/1.1/series/499531/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=499531", "date": "2026-04-11T07:06:33", "name": "[1/9] linux-user/mips, target/mips: honor MIPS_FIXADE for unaligned accesses", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/499531/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2222286/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2222286/checks/", "tags": {}, "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=QB6wB/Is;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from lists.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4ft4Wz5rt9z1yGb\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 11 Apr 2026 17:08:31 +1000 (AEST)", "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wBSQt-0001ar-LW; Sat, 11 Apr 2026 03:07:07 -0400", "from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <james.hilliard1@gmail.com>)\n id 1wBSQs-0001aC-FR\n for qemu-devel@nongnu.org; Sat, 11 Apr 2026 03:07:06 -0400", "from mail-oi1-x22f.google.com ([2607:f8b0:4864:20::22f])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <james.hilliard1@gmail.com>)\n id 1wBSQn-000105-UI\n for qemu-devel@nongnu.org; Sat, 11 Apr 2026 03:07:06 -0400", "by mail-oi1-x22f.google.com with SMTP id\n 5614622812f47-463a0e14abfso1475658b6e.2\n for <qemu-devel@nongnu.org>; Sat, 11 Apr 2026 00:07:01 -0700 (PDT)", "from Mac.localdomain (71-218-253-186.hlrn.qwest.net.\n [71.218.253.186]) by smtp.gmail.com with ESMTPSA id\n 5614622812f47-478a0f1e841sm2651091b6e.5.2026.04.11.00.06.58\n (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256);\n Sat, 11 Apr 2026 00:06:59 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1775891220; x=1776496020; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=cAQOy1mjwPEtx9Z4okALADHZoJ1HVQKJHqo9jz6p7UE=;\n b=QB6wB/IsmInDF4LA8HJVMNL5dmS//+BLTQqR3y7Xk/VA1Vkf1lpdzCipuxnqK4UHw8\n af4RIaYnrIy8uH0RmloipJPhZWvg1EWPods8b/sK4+XEboDVh/v+8wmrfJtJ+6E6ErEg\n zKCe9LshIRMqCYge15WWaVT3WKjJLT5TNoBCUiBBElyBuUptVqWN9cdFGNQm7rQTVrbt\n GfwuY7EkDbuewMxw4c6iZjx+N6uOtEzWzE0/50JeyE+xbGeNj1TnaBZ/701B7/pVHm5R\n EN3QZB3BcxLI8QxLssKa1tbTdrE80lwuz1rznbbiBUiSSfol0fdTyb/hPipa+oAAi0HM\n B4og==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775891220; x=1776496020;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=cAQOy1mjwPEtx9Z4okALADHZoJ1HVQKJHqo9jz6p7UE=;\n b=aic6xx63N+eD7ru8xdqfR4omQjFKoPX3yVIC38Cn3hRJmMxZk8MsZ2gcDcgVBOBgeu\n 9KEYuFmmgI8CHXne/qjPMpY6YVARlY1obVsPuziqFreRrE+JkQCHJXmejhoaXpkaCvtd\n vBpJ9h8yRY3jPNeIrimE3xR1cyFnYfTDzY/HA70RGqIQgxFpo580ifyKlJfGZ4pseBUk\n ndrfmu218c1oedLestjPKfs9eJy5cnyGANPE1CjvbJT/jBI0Yvd8TbV77QvK/XH5dK5Q\n IRW7oDSDLZpRQaR7DQtWbryv0FjP/DbTmKPsVOjfRGoCdYC20OXWPqplYSQGsw61kutt\n U/mg==", "X-Gm-Message-State": "AOJu0YzT4iKfvJ7dP+3d3yURX/9rdyGwiMb5hm/bctDuu5xllxS0MH0L\n vek8VpfG0wiVcZT2zj1dGtVXcFsE7TZ+NGRR2awSVJUN+oyRsagOco5WmFbxALaEs+o=", "X-Gm-Gg": "AeBDieswonFys3vcPKdLi2fyr4w/KkzprUILWxOrz3uGcfqPdqvarZh9z53yJ2+3VtL\n OyWV5GTXaeDaGqC9J/zUntBsexqKCnDLabr0tQJSNm2LrSFjE5c3isU5udPKLYpmDs/f8mVRziz\n q3ZlZ8VNZNpDs/UUSICLFveoJzwKKzmx20tZYwARNuH7+JDhsxi1qgHcSrZVnv+aCBj2TZED+QP\n Rx9zGfyEQ/H++1de+HgEaKLIF7WP+dc4cVlfJK47GjblLcDU7OoSz6vgUbTTLT/AM1XbUKZyDet\n Mxc1hnOfXjVt4kP6QuxLR/8bsFb/6YYj9Z+tqTUsCC2erNpwtg6/yJrOUiC4I8Ko4mUIEoAaepz\n VvpB9aBhQRndTDrxK8MtQkuIdrat/jHvVoEU2WKB+T3eOo7LNtmA91JcpKtsia31DGjEJPB0dhn\n yBceFzM6rYs/HLh4ZKiHzkwLYdTHlkPizFCJx8i9sqd52PIhA0F/yM7ZBczk6IOVSaKZjizJOG3\n L2fOVZ3YRcTYwnxXgovnSshObmLelyAkUbmc+a5y5QhOrXr/iA531nj+B8x7UG9Z4Wk0QM=", "X-Received": "by 2002:a05:6808:4f29:b0:467:36f:181c with SMTP id\n 5614622812f47-478a090ffe0mr3046561b6e.51.1775891220097;\n Sat, 11 Apr 2026 00:07:00 -0700 (PDT)", "From": "James Hilliard <james.hilliard1@gmail.com>", "To": "qemu-devel@nongnu.org", "Cc": "James Hilliard <james.hilliard1@gmail.com>,\n Laurent Vivier <laurent@vivier.eu>,\n Pierrick Bouvier <pierrick.bouvier@linaro.org>, =?utf-8?q?Philippe_Mathieu-?=\n\t=?utf-8?q?Daud=C3=A9?= <philmd@linaro.org>,\n Aurelien Jarno <aurelien@aurel32.net>, Jiaxun Yang <jiaxun.yang@flygoat.com>,\n Aleksandar Rikalo <arikalo@gmail.com>, Huacai Chen <chenhuacai@kernel.org>", "Subject": "[PATCH 4/9] target/mips: add Octeon COP2 crypto core support", "Date": "Sat, 11 Apr 2026 01:06:30 -0600", "Message-ID": "<20260411070637.72421-4-james.hilliard1@gmail.com>", "X-Mailer": "git-send-email 2.53.0", "In-Reply-To": "<20260411070637.72421-1-james.hilliard1@gmail.com>", "References": "<20260411070637.72421-1-james.hilliard1@gmail.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=2607:f8b0:4864:20::22f;\n envelope-from=james.hilliard1@gmail.com; helo=mail-oi1-x22f.google.com", "X-Spam_score_int": "-17", "X-Spam_score": "-1.8", "X-Spam_bar": "-", "X-Spam_report": "(-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no", "X-Spam_action": "no action", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "qemu development <qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org" }, "content": "Octeon processors expose their crypto engines through selector-driven\nDMFC2/DMTC2 accesses rather than architected standalone opcodes. Add\nthe common COP2 state, selector decode, and helper plumbing for the base\nengine set.\n\nThis covers the initial hash, AES, CRC, GFM, 3DES, KASUMI, and SNOW3G\nengines and moves the implementation into octeon_crypto.c to keep the\nMIPS helper layer manageable.\n\nSigned-off-by: James Hilliard <james.hilliard1@gmail.com>\n---\n target/mips/cpu.h | 165 +++\n target/mips/helper.h | 3 +\n target/mips/tcg/meson.build | 1 +\n target/mips/tcg/octeon.decode | 2 +\n target/mips/tcg/octeon_crypto.c | 1628 ++++++++++++++++++++++++++++\n target/mips/tcg/octeon_translate.c | 6 +\n target/mips/tcg/op_helper.c | 14 +\n target/mips/tcg/translate.c | 196 ++++\n 8 files changed, 2015 insertions(+)\n create mode 100644 target/mips/tcg/octeon_crypto.c", "diff": "diff --git a/target/mips/cpu.h b/target/mips/cpu.h\nindex 98cd7ae83e..b4b7575ecb 100644\n--- a/target/mips/cpu.h\n+++ b/target/mips/cpu.h\n@@ -537,6 +537,169 @@ struct TCState {\n };\n \n struct MIPSITUState;\n+typedef enum MIPSOcteonSharedMode {\n+ OCTEON_SHARED_MODE_NONE = 0,\n+ OCTEON_SHARED_MODE_SHA512,\n+ OCTEON_SHARED_MODE_SNOW3G,\n+} MIPSOcteonSharedMode;\n+\n+typedef enum MIPSOcteonCop2Sel {\n+ OCTEON_COP2_SEL_HSH_DAT0 = 0x0040,\n+ OCTEON_COP2_SEL_HSH_DAT1,\n+ OCTEON_COP2_SEL_HSH_DAT2,\n+ OCTEON_COP2_SEL_HSH_DAT3,\n+ OCTEON_COP2_SEL_HSH_DAT4,\n+ OCTEON_COP2_SEL_HSH_DAT5,\n+ OCTEON_COP2_SEL_HSH_DAT6,\n+ OCTEON_COP2_SEL_HSH_IV0 = 0x0048,\n+ OCTEON_COP2_SEL_HSH_IV1,\n+ OCTEON_COP2_SEL_HSH_IV2,\n+ OCTEON_COP2_SEL_HSH_IV3,\n+ OCTEON_COP2_SEL_SHA3_DAT24 = 0x0050,\n+ OCTEON_COP2_SEL_SHA3_DAT15_WRITE = 0x0051,\n+ OCTEON_COP2_SEL_HSH_STARTSHA1_COMPAT = 0x0057,\n+ OCTEON_COP2_SEL_GFM_MUL_REFLECT0 = 0x0058,\n+ OCTEON_COP2_SEL_GFM_MUL_REFLECT1,\n+ OCTEON_COP2_SEL_GFM_RESINP_REFLECT0 = 0x005a,\n+ OCTEON_COP2_SEL_GFM_RESINP_REFLECT1,\n+ OCTEON_COP2_SEL_GFM_XOR0_REFLECT = 0x005c,\n+ OCTEON_COP2_SEL_3DES_KEY0 = 0x0080,\n+ OCTEON_COP2_SEL_3DES_KEY1,\n+ OCTEON_COP2_SEL_3DES_KEY2,\n+ OCTEON_COP2_SEL_3DES_IV = 0x0084,\n+ OCTEON_COP2_SEL_3DES_RESULT = 0x0088,\n+ OCTEON_COP2_SEL_3DES_RESULT_IN = 0x0098,\n+ OCTEON_COP2_SEL_3DES_ENC_CBC = 0x4088,\n+ /*\n+ * Octeon reuses the 3DES key/result bank for KASUMI and only adds\n+ * KASUMI-specific operation selectors.\n+ */\n+ OCTEON_COP2_SEL_KAS_ENC_CBC = 0x4089,\n+ OCTEON_COP2_SEL_3DES_ENC = 0x408a,\n+ OCTEON_COP2_SEL_KAS_ENC = 0x408b,\n+ OCTEON_COP2_SEL_3DES_DEC_CBC = 0x408c,\n+ OCTEON_COP2_SEL_3DES_DEC = 0x408e,\n+ OCTEON_COP2_SEL_AES_RESULT0 = 0x0100,\n+ OCTEON_COP2_SEL_AES_RESULT1,\n+ OCTEON_COP2_SEL_AES_IV0,\n+ OCTEON_COP2_SEL_AES_IV1,\n+ OCTEON_COP2_SEL_AES_KEY0,\n+ OCTEON_COP2_SEL_AES_KEY1,\n+ OCTEON_COP2_SEL_AES_KEY2,\n+ OCTEON_COP2_SEL_AES_KEY3,\n+ OCTEON_COP2_SEL_AES_ENC_CBC0 = 0x0108,\n+ OCTEON_COP2_SEL_AES_ENC0 = 0x010a,\n+ OCTEON_COP2_SEL_AES_DEC_CBC0 = 0x010c,\n+ OCTEON_COP2_SEL_AES_DEC0 = 0x010e,\n+ OCTEON_COP2_SEL_AES_KEYLENGTH = 0x0110,\n+ OCTEON_COP2_SEL_AES_DAT0 = 0x0111,\n+ OCTEON_COP2_SEL_CRC_POLYNOMIAL = 0x0200,\n+ OCTEON_COP2_SEL_CRC_IV = 0x0201,\n+ OCTEON_COP2_SEL_CRC_LEN = 0x0202,\n+ OCTEON_COP2_SEL_CRC_IV_REFLECT = 0x0203,\n+ OCTEON_COP2_SEL_CRC_WRITE_BYTE = 0x0204,\n+ OCTEON_COP2_SEL_CRC_WRITE_HALF = 0x0205,\n+ OCTEON_COP2_SEL_CRC_WRITE_WORD = 0x0206,\n+ OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL = 0x4200,\n+ OCTEON_COP2_SEL_CRC_WRITE_LEN = 0x1202,\n+ OCTEON_COP2_SEL_CRC_WRITE_IV_REFLECT = 0x0211,\n+ OCTEON_COP2_SEL_CRC_WRITE_BYTE_REFLECT = 0x0214,\n+ OCTEON_COP2_SEL_CRC_WRITE_HALF_REFLECT = 0x0215,\n+ OCTEON_COP2_SEL_CRC_WRITE_WORD_REFLECT = 0x0216,\n+ OCTEON_COP2_SEL_CRC_WRITE_DWORD = 0x1207,\n+ OCTEON_COP2_SEL_CRC_WRITE_VAR = 0x1208,\n+ OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL_REFLECT = 0x4210,\n+ OCTEON_COP2_SEL_CRC_WRITE_DWORD_REFLECT = 0x1217,\n+ OCTEON_COP2_SEL_CRC_WRITE_VAR_REFLECT = 0x1218,\n+ /*\n+ * Octeon shares 0x0240..0x0257 between SHA512 state/data and the SNOW3G\n+ * RESULT/FSM/LFSR window.\n+ */\n+ OCTEON_COP2_SEL_HSH_DATW0 = 0x0240,\n+ OCTEON_COP2_SEL_HSH_DATW1,\n+ OCTEON_COP2_SEL_HSH_DATW2,\n+ OCTEON_COP2_SEL_HSH_DATW3,\n+ OCTEON_COP2_SEL_HSH_DATW4,\n+ OCTEON_COP2_SEL_HSH_DATW5,\n+ OCTEON_COP2_SEL_HSH_DATW6,\n+ OCTEON_COP2_SEL_HSH_DATW7,\n+ OCTEON_COP2_SEL_HSH_DATW8,\n+ OCTEON_COP2_SEL_HSH_DATW9,\n+ OCTEON_COP2_SEL_HSH_DATW10,\n+ OCTEON_COP2_SEL_HSH_DATW11,\n+ OCTEON_COP2_SEL_HSH_DATW12,\n+ OCTEON_COP2_SEL_HSH_DATW13,\n+ OCTEON_COP2_SEL_HSH_DATW14,\n+ OCTEON_COP2_SEL_HSH_DATW15,\n+ OCTEON_COP2_SEL_HSH_IVW0 = 0x0250,\n+ OCTEON_COP2_SEL_HSH_IVW1,\n+ OCTEON_COP2_SEL_HSH_IVW2,\n+ OCTEON_COP2_SEL_HSH_IVW3,\n+ OCTEON_COP2_SEL_HSH_IVW4,\n+ OCTEON_COP2_SEL_HSH_IVW5,\n+ OCTEON_COP2_SEL_HSH_IVW6,\n+ OCTEON_COP2_SEL_HSH_IVW7,\n+ OCTEON_COP2_SEL_SNOW3G_LFSR0 = 0x0240,\n+ OCTEON_COP2_SEL_SNOW3G_LFSR1,\n+ OCTEON_COP2_SEL_SNOW3G_LFSR2,\n+ OCTEON_COP2_SEL_SNOW3G_LFSR3,\n+ OCTEON_COP2_SEL_SNOW3G_LFSR4,\n+ OCTEON_COP2_SEL_SNOW3G_LFSR5,\n+ OCTEON_COP2_SEL_SNOW3G_LFSR6,\n+ OCTEON_COP2_SEL_SNOW3G_LFSR7,\n+ OCTEON_COP2_SEL_SNOW3G_RESULT = 0x0250,\n+ OCTEON_COP2_SEL_SNOW3G_FSM0,\n+ OCTEON_COP2_SEL_SNOW3G_FSM1,\n+ OCTEON_COP2_SEL_SNOW3G_FSM2,\n+ OCTEON_COP2_SEL_GFM_MUL0 = 0x0258,\n+ OCTEON_COP2_SEL_GFM_MUL1,\n+ OCTEON_COP2_SEL_GFM_RESINP0,\n+ OCTEON_COP2_SEL_GFM_RESINP1,\n+ OCTEON_COP2_SEL_GFM_XOR0,\n+ OCTEON_COP2_SEL_GFM_POLY = 0x025e,\n+ OCTEON_COP2_SEL_AES_ENC_CBC1 = 0x3109,\n+ OCTEON_COP2_SEL_AES_ENC1 = 0x310b,\n+ OCTEON_COP2_SEL_AES_DEC_CBC1 = 0x310d,\n+ OCTEON_COP2_SEL_AES_DEC1 = 0x310f,\n+ OCTEON_COP2_SEL_HSH_STARTMD5 = 0x4047,\n+ OCTEON_COP2_SEL_SNOW3G_START = 0x404d,\n+ OCTEON_COP2_SEL_SNOW3G_MORE = 0x404e,\n+ OCTEON_COP2_SEL_HSH_STARTSHA256 = 0x404f,\n+ OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT = 0x405d,\n+ OCTEON_COP2_SEL_HSH_STARTSHA1 = 0x4057,\n+ OCTEON_COP2_SEL_HSH_STARTSHA512 = 0x424f,\n+ OCTEON_COP2_SEL_GFM_XORMUL1 = 0x425d,\n+} MIPSOcteonCop2Sel;\n+\n+typedef struct MIPSOcteonCryptoState {\n+ uint64_t des3_key[3];\n+ uint64_t des3_iv;\n+ uint64_t des3_result;\n+ uint64_t hash_state[4];\n+ uint64_t hash_block[8];\n+ uint64_t sha512_state[8];\n+ uint64_t sha512_block[16];\n+ uint64_t aes_iv[2];\n+ uint64_t aes_key[4];\n+ uint64_t aes_result[2];\n+ uint64_t aes_input[2];\n+ uint64_t gfm_mul[2];\n+ uint64_t gfm_result[2];\n+ uint64_t gfm_xor0;\n+ uint64_t gfm_reflect_mul[2];\n+ uint64_t gfm_reflect_result[2];\n+ uint64_t gfm_reflect_xor0;\n+ uint16_t gfm_poly;\n+ uint8_t aes_keylen;\n+ MIPSOcteonSharedMode shared_mode;\n+ uint32_t crc_poly;\n+ uint32_t crc_iv;\n+ uint32_t crc_len;\n+ uint32_t snow3g_fsm[3];\n+ uint32_t snow3g_lfsr[16];\n+ uint64_t snow3g_result;\n+} MIPSOcteonCryptoState;\n+\n typedef struct CPUArchState {\n TCState active_tc;\n CPUMIPSFPUContext active_fpu;\n@@ -558,6 +721,8 @@ typedef struct CPUArchState {\n #define MSAIR_ProcID 8\n #define MSAIR_Rev 0\n \n+ MIPSOcteonCryptoState octeon_crypto;\n+\n /*\n * CP0 Register 0\n */\ndiff --git a/target/mips/helper.h b/target/mips/helper.h\nindex 3c9f67ec40..0d5713b705 100644\n--- a/target/mips/helper.h\n+++ b/target/mips/helper.h\n@@ -25,7 +25,10 @@ DEF_HELPER_3(crc32, tl, tl, tl, i32)\n DEF_HELPER_3(crc32c, tl, tl, tl, i32)\n DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32)\n DEF_HELPER_3(octeon_vmulu, tl, env, tl, tl)\n+DEF_HELPER_3(octeon_vmm0, tl, env, tl, tl)\n DEF_HELPER_3(octeon_v3mulu, tl, env, tl, tl)\n+DEF_HELPER_2(octeon_cop2_dmfc2, tl, env, i32)\n+DEF_HELPER_3(octeon_cop2_dmtc2, void, env, tl, i32)\n \n /* microMIPS functions */\n DEF_HELPER_4(lwm, void, env, tl, tl, i32)\ndiff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build\nindex fff9cd6c7f..4ee359874a 100644\n--- a/target/mips/tcg/meson.build\n+++ b/target/mips/tcg/meson.build\n@@ -18,6 +18,7 @@ mips_ss.add(files(\n 'lmmi_helper.c',\n 'msa_helper.c',\n 'msa_translate.c',\n+ 'octeon_crypto.c',\n 'op_helper.c',\n 'rel6_translate.c',\n 'translate.c',\ndiff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode\nindex 0f5fe83609..9dcc5a6ae0 100644\n--- a/target/mips/tcg/octeon.decode\n+++ b/target/mips/tcg/octeon.decode\n@@ -52,6 +52,7 @@ MTP2 011100 rs:5 rt:5 00000 00000 001011 &r2\n MTM1 011100 rs:5 rt:5 00000 00000 001100 &r2\n MTM2 011100 rs:5 rt:5 00000 00000 001101 &r2\n VMULU 011100 ..... ..... ..... 00000 001111 @r3\n+VMM0 011100 ..... ..... ..... 00000 010000 @r3\n V3MULU 011100 ..... ..... ..... 00000 010001 @r3\n \n &saa base rt\n@@ -78,6 +79,7 @@ LAWD 011100 ..... ..... ..... 10111 011111 @laa\n \n &zcb base\n ZCB 011100 base:5 00000 00000 11100 011111 &zcb\n+ZCBT 011100 base:5 00000 00000 11101 011111 &zcb\n \n &lx base index rd\n @lx ...... base:5 index:5 rd:5 ...... ..... &lx\ndiff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c\nnew file mode 100644\nindex 0000000000..a308c3957e\n--- /dev/null\n+++ b/target/mips/tcg/octeon_crypto.c\n@@ -0,0 +1,1628 @@\n+/*\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ *\n+ * MIPS Octeon crypto emulation helpers.\n+ *\n+ * Copyright (c) 2026 James Hilliard\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"cpu.h\"\n+#include \"internal.h\"\n+#include \"exec/helper-proto.h\"\n+#include \"exec/memop.h\"\n+#include \"crypto/aes.h\"\n+#include \"qemu/bitops.h\"\n+#include \"qemu/host-utils.h\"\n+\n+static inline void octeon_set_shared_mode(MIPSOcteonCryptoState *crypto,\n+ MIPSOcteonSharedMode mode)\n+{\n+ crypto->shared_mode = mode;\n+}\n+\n+static inline uint32_t octeon_crc_reflect32_by_byte(uint32_t v)\n+{\n+ return bswap32(revbit32(v));\n+}\n+\n+static uint32_t octeon_crc_state_reflect(const MIPSOcteonCryptoState *crypto)\n+{\n+ return octeon_crc_reflect32_by_byte(crypto->crc_iv);\n+}\n+\n+static void octeon_crc_set_state_reflect(MIPSOcteonCryptoState *crypto,\n+ uint32_t state)\n+{\n+ crypto->crc_iv = octeon_crc_reflect32_by_byte(state);\n+}\n+\n+static void octeon_crc_update_normal(MIPSOcteonCryptoState *crypto,\n+ uint64_t value, unsigned int bytes)\n+{\n+ uint32_t crc = crypto->crc_iv;\n+ uint32_t poly = crypto->crc_poly;\n+\n+ for (unsigned int i = 0; i < bytes; i++) {\n+ uint8_t byte = value >> ((bytes - 1 - i) * 8);\n+\n+ crc ^= (uint32_t)byte << 24;\n+ for (int bit = 0; bit < 8; bit++) {\n+ if (crc & 0x80000000U) {\n+ crc = (crc << 1) ^ poly;\n+ } else {\n+ crc <<= 1;\n+ }\n+ }\n+ }\n+\n+ crypto->crc_iv = crc;\n+}\n+\n+static void octeon_crc_update_reflect(MIPSOcteonCryptoState *crypto,\n+ uint64_t value, unsigned int bytes)\n+{\n+ uint32_t crc = octeon_crc_state_reflect(crypto);\n+ uint32_t poly = bswap32(crypto->crc_poly);\n+\n+ for (unsigned int i = 0; i < bytes; i++) {\n+ uint8_t byte = value >> ((bytes - 1 - i) * 8);\n+\n+ crc ^= byte;\n+ for (int bit = 0; bit < 8; bit++) {\n+ if (crc & 1U) {\n+ crc = (crc >> 1) ^ poly;\n+ } else {\n+ crc >>= 1;\n+ }\n+ }\n+ }\n+\n+ octeon_crc_set_state_reflect(crypto, crc);\n+}\n+\n+static uint64_t octeon_gfm_mul64x(uint64_t v, uint8_t c)\n+{\n+ if (v & 0x8000000000000000ULL) {\n+ return (v << 1) ^ c;\n+ }\n+ return v << 1;\n+}\n+\n+static uint64_t octeon_gfm_mul64(uint64_t v, uint64_t p, uint8_t c)\n+{\n+ uint64_t result = 0;\n+ int i;\n+\n+ for (i = 0; i < 64; i++) {\n+ if ((p >> i) & 1) {\n+ result ^= v;\n+ }\n+ v = octeon_gfm_mul64x(v, c);\n+ }\n+\n+ return result;\n+}\n+\n+static void octeon_gfm_mul64_uia2(const uint64_t x[2], const uint64_t y[2],\n+ uint8_t poly, uint64_t out[2])\n+{\n+ uint64_t vx = revbit64(x[1]);\n+ uint64_t vy = revbit64(y[0]);\n+ uint64_t res = octeon_gfm_mul64(vx, vy, revbit32(poly) >> 24);\n+\n+ out[0] = 0;\n+ out[1] = revbit64(res);\n+}\n+\n+static void octeon_gfm_mul_reflect(MIPSOcteonCryptoState *crypto, uint64_t q)\n+{\n+ uint64_t in[2] = {\n+ crypto->gfm_reflect_result[0] ^ crypto->gfm_reflect_xor0,\n+ crypto->gfm_reflect_result[1] ^ q,\n+ };\n+\n+ octeon_gfm_mul64_uia2(in, crypto->gfm_reflect_mul,\n+ crypto->gfm_poly, crypto->gfm_reflect_result);\n+ crypto->gfm_reflect_xor0 = 0;\n+}\n+\n+static inline void octeon_hash_load_reg_words_be(uint64_t reg,\n+ uint32_t *hi, uint32_t *lo)\n+{\n+ uint8_t buf[8];\n+\n+ stq_be_p(buf, reg);\n+ *hi = ldl_be_p(buf);\n+ *lo = ldl_be_p(buf + 4);\n+}\n+\n+static inline void octeon_hash_load_reg_words_le(uint64_t reg,\n+ uint32_t *lo0, uint32_t *lo1)\n+{\n+ uint8_t buf[8];\n+\n+ stq_be_p(buf, reg);\n+ *lo0 = ldl_le_p(buf);\n+ *lo1 = ldl_le_p(buf + 4);\n+}\n+\n+static inline uint64_t octeon_hash_store_reg_words_be(uint32_t hi, uint32_t lo)\n+{\n+ uint8_t buf[8];\n+\n+ stl_be_p(buf, hi);\n+ stl_be_p(buf + 4, lo);\n+ return ldq_be_p(buf);\n+}\n+\n+static inline uint64_t octeon_hash_store_reg_words_le(uint32_t lo0,\n+ uint32_t lo1)\n+{\n+ uint8_t buf[8];\n+\n+ stl_le_p(buf, lo0);\n+ stl_le_p(buf + 4, lo1);\n+ return ldq_be_p(buf);\n+}\n+\n+static void octeon_md5_transform(MIPSOcteonCryptoState *crypto)\n+{\n+ static const uint32_t k[64] = {\n+ 0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU,\n+ 0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U,\n+ 0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU,\n+ 0x6b901122U, 0xfd987193U, 0xa679438eU, 0x49b40821U,\n+ 0xf61e2562U, 0xc040b340U, 0x265e5a51U, 0xe9b6c7aaU,\n+ 0xd62f105dU, 0x02441453U, 0xd8a1e681U, 0xe7d3fbc8U,\n+ 0x21e1cde6U, 0xc33707d6U, 0xf4d50d87U, 0x455a14edU,\n+ 0xa9e3e905U, 0xfcefa3f8U, 0x676f02d9U, 0x8d2a4c8aU,\n+ 0xfffa3942U, 0x8771f681U, 0x6d9d6122U, 0xfde5380cU,\n+ 0xa4beea44U, 0x4bdecfa9U, 0xf6bb4b60U, 0xbebfbc70U,\n+ 0x289b7ec6U, 0xeaa127faU, 0xd4ef3085U, 0x04881d05U,\n+ 0xd9d4d039U, 0xe6db99e5U, 0x1fa27cf8U, 0xc4ac5665U,\n+ 0xf4292244U, 0x432aff97U, 0xab9423a7U, 0xfc93a039U,\n+ 0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU, 0x85845dd1U,\n+ 0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U,\n+ 0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U,\n+ };\n+ static const uint8_t s[64] = {\n+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,\n+ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,\n+ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,\n+ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,\n+ };\n+ uint8_t block_bytes[64];\n+ uint32_t m[16];\n+ uint32_t a, b, c, d;\n+ uint32_t aa, bb, cc, dd;\n+ int i;\n+\n+ for (i = 0; i < 8; i++) {\n+ stq_be_p(block_bytes + (i * 8), crypto->hash_block[i]);\n+ m[i * 2] = ldl_le_p(block_bytes + (i * 8));\n+ m[i * 2 + 1] = ldl_le_p(block_bytes + (i * 8) + 4);\n+ }\n+\n+ octeon_hash_load_reg_words_le(crypto->hash_state[0], &a, &b);\n+ octeon_hash_load_reg_words_le(crypto->hash_state[1], &c, &d);\n+ aa = a;\n+ bb = b;\n+ cc = c;\n+ dd = d;\n+\n+ for (i = 0; i < 64; i++) {\n+ uint32_t f, g, tmp;\n+\n+ if (i < 16) {\n+ f = (b & c) | ((~b) & d);\n+ g = i;\n+ } else if (i < 32) {\n+ f = (d & b) | ((~d) & c);\n+ g = (5 * i + 1) & 0xf;\n+ } else if (i < 48) {\n+ f = b ^ c ^ d;\n+ g = (3 * i + 5) & 0xf;\n+ } else {\n+ f = c ^ (b | (~d));\n+ g = (7 * i) & 0xf;\n+ }\n+\n+ tmp = d;\n+ d = c;\n+ c = b;\n+ b = b + rol32(a + f + k[i] + m[g], s[i]);\n+ a = tmp;\n+ }\n+\n+ a += aa;\n+ b += bb;\n+ c += cc;\n+ d += dd;\n+ crypto->hash_state[0] = octeon_hash_store_reg_words_le(a, b);\n+ crypto->hash_state[1] = octeon_hash_store_reg_words_le(c, d);\n+}\n+\n+static void octeon_sha1_transform(MIPSOcteonCryptoState *crypto)\n+{\n+ uint32_t w[80];\n+ uint32_t a, b, c, d, e;\n+ int i;\n+\n+ for (i = 0; i < 8; i++) {\n+ octeon_hash_load_reg_words_be(crypto->hash_block[i],\n+ &w[i * 2], &w[i * 2 + 1]);\n+ }\n+ for (i = 16; i < 80; i++) {\n+ w[i] = rol32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);\n+ }\n+\n+ octeon_hash_load_reg_words_be(crypto->hash_state[0], &a, &b);\n+ octeon_hash_load_reg_words_be(crypto->hash_state[1], &c, &d);\n+ e = crypto->hash_state[2] >> 32;\n+\n+ for (i = 0; i < 80; i++) {\n+ uint32_t f, k, temp;\n+\n+ if (i < 20) {\n+ f = (b & c) | ((~b) & d);\n+ k = 0x5a827999;\n+ } else if (i < 40) {\n+ f = b ^ c ^ d;\n+ k = 0x6ed9eba1;\n+ } else if (i < 60) {\n+ f = (b & c) | (b & d) | (c & d);\n+ k = 0x8f1bbcdc;\n+ } else {\n+ f = b ^ c ^ d;\n+ k = 0xca62c1d6;\n+ }\n+\n+ temp = rol32(a, 5) + f + e + k + w[i];\n+ e = d;\n+ d = c;\n+ c = rol32(b, 30);\n+ b = a;\n+ a = temp;\n+ }\n+\n+ octeon_hash_load_reg_words_be(crypto->hash_state[0], &w[0], &w[1]);\n+ octeon_hash_load_reg_words_be(crypto->hash_state[1], &w[2], &w[3]);\n+ w[4] = crypto->hash_state[2] >> 32;\n+ w[0] += a;\n+ w[1] += b;\n+ w[2] += c;\n+ w[3] += d;\n+ w[4] += e;\n+ crypto->hash_state[0] = octeon_hash_store_reg_words_be(w[0], w[1]);\n+ crypto->hash_state[1] = octeon_hash_store_reg_words_be(w[2], w[3]);\n+ crypto->hash_state[2] = (uint64_t)w[4] << 32;\n+}\n+\n+static void octeon_sha256_transform(MIPSOcteonCryptoState *crypto)\n+{\n+ static const uint32_t k[64] = {\n+ 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U,\n+ 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,\n+ 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U,\n+ 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,\n+ 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,\n+ 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,\n+ 0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,\n+ 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,\n+ 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,\n+ 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,\n+ 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U,\n+ 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,\n+ 0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U,\n+ 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,\n+ 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,\n+ 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U,\n+ };\n+ uint32_t w[64];\n+ uint32_t a, b, c, d, e, f, g, h;\n+ uint32_t orig[8];\n+ int i;\n+\n+ for (i = 0; i < 8; i++) {\n+ octeon_hash_load_reg_words_be(crypto->hash_block[i],\n+ &w[i * 2], &w[i * 2 + 1]);\n+ }\n+ for (i = 16; i < 64; i++) {\n+ uint32_t s0 = ror32(w[i - 15], 7) ^\n+ ror32(w[i - 15], 18) ^\n+ (w[i - 15] >> 3);\n+ uint32_t s1 = ror32(w[i - 2], 17) ^\n+ ror32(w[i - 2], 19) ^\n+ (w[i - 2] >> 10);\n+ w[i] = w[i - 16] + s0 + w[i - 7] + s1;\n+ }\n+\n+ for (i = 0; i < 4; i++) {\n+ octeon_hash_load_reg_words_be(crypto->hash_state[i],\n+ &orig[i * 2], &orig[i * 2 + 1]);\n+ }\n+ a = orig[0];\n+ b = orig[1];\n+ c = orig[2];\n+ d = orig[3];\n+ e = orig[4];\n+ f = orig[5];\n+ g = orig[6];\n+ h = orig[7];\n+\n+ for (i = 0; i < 64; i++) {\n+ uint32_t s1 = ror32(e, 6) ^\n+ ror32(e, 11) ^\n+ ror32(e, 25);\n+ uint32_t ch = (e & f) ^ ((~e) & g);\n+ uint32_t temp1 = h + s1 + ch + k[i] + w[i];\n+ uint32_t s0 = ror32(a, 2) ^\n+ ror32(a, 13) ^\n+ ror32(a, 22);\n+ uint32_t maj = (a & b) ^ (a & c) ^ (b & c);\n+ uint32_t temp2 = s0 + maj;\n+\n+ h = g;\n+ g = f;\n+ f = e;\n+ e = d + temp1;\n+ d = c;\n+ c = b;\n+ b = a;\n+ a = temp1 + temp2;\n+ }\n+\n+ orig[0] += a;\n+ orig[1] += b;\n+ orig[2] += c;\n+ orig[3] += d;\n+ orig[4] += e;\n+ orig[5] += f;\n+ orig[6] += g;\n+ orig[7] += h;\n+ for (i = 0; i < 4; i++) {\n+ crypto->hash_state[i] =\n+ octeon_hash_store_reg_words_be(orig[i * 2], orig[i * 2 + 1]);\n+ }\n+}\n+\n+static void octeon_sha512_transform(MIPSOcteonCryptoState *crypto)\n+{\n+ static const uint64_t k[80] = {\n+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,\n+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,\n+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,\n+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,\n+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,\n+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,\n+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,\n+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,\n+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,\n+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,\n+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,\n+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,\n+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,\n+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,\n+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,\n+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,\n+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,\n+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,\n+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,\n+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,\n+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,\n+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,\n+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,\n+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,\n+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,\n+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,\n+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,\n+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,\n+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,\n+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,\n+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,\n+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,\n+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,\n+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,\n+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,\n+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,\n+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,\n+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,\n+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,\n+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,\n+ };\n+ uint64_t w[80];\n+ uint64_t a, b, c, d, e, f, g, h;\n+ int i;\n+\n+ for (i = 0; i < 16; i++) {\n+ w[i] = crypto->sha512_block[i];\n+ }\n+ for (i = 16; i < 80; i++) {\n+ uint64_t s0 = ror64(w[i - 15], 1) ^\n+ ror64(w[i - 15], 8) ^\n+ (w[i - 15] >> 7);\n+ uint64_t s1 = ror64(w[i - 2], 19) ^\n+ ror64(w[i - 2], 61) ^\n+ (w[i - 2] >> 6);\n+ w[i] = w[i - 16] + s0 + w[i - 7] + s1;\n+ }\n+\n+ a = crypto->sha512_state[0];\n+ b = crypto->sha512_state[1];\n+ c = crypto->sha512_state[2];\n+ d = crypto->sha512_state[3];\n+ e = crypto->sha512_state[4];\n+ f = crypto->sha512_state[5];\n+ g = crypto->sha512_state[6];\n+ h = crypto->sha512_state[7];\n+\n+ for (i = 0; i < 80; i++) {\n+ uint64_t s0 = ror64(a, 28) ^\n+ ror64(a, 34) ^\n+ ror64(a, 39);\n+ uint64_t s1 = ror64(e, 14) ^\n+ ror64(e, 18) ^\n+ ror64(e, 41);\n+ uint64_t ch = (e & f) ^ ((~e) & g);\n+ uint64_t maj = (a & b) ^ (a & c) ^ (b & c);\n+ uint64_t temp1 = h + s1 + ch + k[i] + w[i];\n+ uint64_t temp2 = s0 + maj;\n+\n+ h = g;\n+ g = f;\n+ f = e;\n+ e = d + temp1;\n+ d = c;\n+ c = b;\n+ b = a;\n+ a = temp1 + temp2;\n+ }\n+\n+ crypto->sha512_state[0] += a;\n+ crypto->sha512_state[1] += b;\n+ crypto->sha512_state[2] += c;\n+ crypto->sha512_state[3] += d;\n+ crypto->sha512_state[4] += e;\n+ crypto->sha512_state[5] += f;\n+ crypto->sha512_state[6] += g;\n+ crypto->sha512_state[7] += h;\n+}\n+\n+static const uint8_t octeon_snow3g_sr[256] = {\n+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,\n+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,\n+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,\n+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,\n+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,\n+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,\n+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,\n+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,\n+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,\n+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,\n+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,\n+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,\n+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,\n+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,\n+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,\n+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,\n+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n+};\n+\n+static const uint8_t octeon_snow3g_sq[256] = {\n+ 0x25, 0x24, 0x73, 0x67, 0xd7, 0xae, 0x5c, 0x30,\n+ 0xa4, 0xee, 0x6e, 0xcb, 0x7d, 0xb5, 0x82, 0xdb,\n+ 0xe4, 0x8e, 0x48, 0x49, 0x4f, 0x5d, 0x6a, 0x78,\n+ 0x70, 0x88, 0xe8, 0x5f, 0x5e, 0x84, 0x65, 0xe2,\n+ 0xd8, 0xe9, 0xcc, 0xed, 0x40, 0x2f, 0x11, 0x28,\n+ 0x57, 0xd2, 0xac, 0xe3, 0x4a, 0x15, 0x1b, 0xb9,\n+ 0xb2, 0x80, 0x85, 0xa6, 0x2e, 0x02, 0x47, 0x29,\n+ 0x07, 0x4b, 0x0e, 0xc1, 0x51, 0xaa, 0x89, 0xd4,\n+ 0xca, 0x01, 0x46, 0xb3, 0xef, 0xdd, 0x44, 0x7b,\n+ 0xc2, 0x7f, 0xbe, 0xc3, 0x9f, 0x20, 0x4c, 0x64,\n+ 0x83, 0xa2, 0x68, 0x42, 0x13, 0xb4, 0x41, 0xcd,\n+ 0xba, 0xc6, 0xbb, 0x6d, 0x4d, 0x71, 0x21, 0xf4,\n+ 0x8d, 0xb0, 0xe5, 0x93, 0xfe, 0x8f, 0xe6, 0xcf,\n+ 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xfa,\n+ 0xbc, 0x0f, 0x08, 0x52, 0x1d, 0x55, 0x1a, 0xc5,\n+ 0x4e, 0x23, 0x69, 0x7a, 0x92, 0xff, 0x5b, 0x5a,\n+ 0xeb, 0x9a, 0x1c, 0xa9, 0xd1, 0x7e, 0x0d, 0xfc,\n+ 0x50, 0x8a, 0xb6, 0x62, 0xf5, 0x0a, 0xf8, 0xdc,\n+ 0x03, 0x3c, 0x0c, 0x39, 0xf1, 0xb8, 0xf3, 0x3d,\n+ 0xf2, 0xd5, 0x97, 0x66, 0x81, 0x32, 0xa0, 0x00,\n+ 0x06, 0xce, 0xf6, 0xea, 0xb7, 0x17, 0xf7, 0x8c,\n+ 0x79, 0xd6, 0xa7, 0xbf, 0x8b, 0x3f, 0x1f, 0x53,\n+ 0x63, 0x75, 0x35, 0x2c, 0x60, 0xfd, 0x27, 0xd3,\n+ 0x94, 0xa5, 0x7c, 0xa1, 0x05, 0x58, 0x2d, 0xbd,\n+ 0xd9, 0xc7, 0xaf, 0x6b, 0x54, 0x0b, 0xe0, 0x38,\n+ 0x04, 0xc8, 0x9d, 0xe7, 0x14, 0xb1, 0x87, 0x9c,\n+ 0xdf, 0x6f, 0xf9, 0xda, 0x2a, 0xc4, 0x59, 0x16,\n+ 0x74, 0x91, 0xab, 0x26, 0x61, 0x76, 0x34, 0x2b,\n+ 0xad, 0x99, 0xfb, 0x72, 0xec, 0x33, 0x12, 0xde,\n+ 0x98, 0x3b, 0xc0, 0x9b, 0x3e, 0x18, 0x10, 0x3a,\n+ 0x56, 0xe1, 0x77, 0xc9, 0x1e, 0x9e, 0x95, 0xa3,\n+ 0x90, 0x19, 0xa8, 0x6c, 0x09, 0xd0, 0xf0, 0x86,\n+};\n+\n+static inline uint8_t octeon_snow3g_mulx(uint8_t v, uint8_t c)\n+{\n+ return (v & 0x80) ? ((v << 1) ^ c) : (v << 1);\n+}\n+\n+static uint8_t octeon_snow3g_mulxpow(uint8_t v, unsigned int n, uint8_t c)\n+{\n+ while (n-- > 0) {\n+ v = octeon_snow3g_mulx(v, c);\n+ }\n+ return v;\n+}\n+\n+static inline uint32_t octeon_snow3g_pack32(uint8_t b0, uint8_t b1,\n+ uint8_t b2, uint8_t b3)\n+{\n+ return ((uint32_t)b0 << 24) | ((uint32_t)b1 << 16) |\n+ ((uint32_t)b2 << 8) | b3;\n+}\n+\n+static uint32_t octeon_snow3g_mulalpha(uint8_t c)\n+{\n+ return octeon_snow3g_pack32(octeon_snow3g_mulxpow(c, 23, 0xa9),\n+ octeon_snow3g_mulxpow(c, 245, 0xa9),\n+ octeon_snow3g_mulxpow(c, 48, 0xa9),\n+ octeon_snow3g_mulxpow(c, 239, 0xa9));\n+}\n+\n+static uint32_t octeon_snow3g_divalpha(uint8_t c)\n+{\n+ return octeon_snow3g_pack32(octeon_snow3g_mulxpow(c, 16, 0xa9),\n+ octeon_snow3g_mulxpow(c, 39, 0xa9),\n+ octeon_snow3g_mulxpow(c, 6, 0xa9),\n+ octeon_snow3g_mulxpow(c, 64, 0xa9));\n+}\n+\n+static uint32_t octeon_snow3g_s1(uint32_t w)\n+{\n+ uint8_t x0 = octeon_snow3g_sr[w >> 24];\n+ uint8_t x1 = octeon_snow3g_sr[(uint8_t)(w >> 16)];\n+ uint8_t x2 = octeon_snow3g_sr[(uint8_t)(w >> 8)];\n+ uint8_t x3 = octeon_snow3g_sr[(uint8_t)w];\n+ uint8_t r0 = octeon_snow3g_mulx(x0, 0x1b) ^ x1 ^ x2 ^\n+ octeon_snow3g_mulx(x3, 0x1b) ^ x3;\n+ uint8_t r1 = octeon_snow3g_mulx(x0, 0x1b) ^ x0 ^\n+ octeon_snow3g_mulx(x1, 0x1b) ^ x2 ^ x3;\n+ uint8_t r2 = x0 ^ octeon_snow3g_mulx(x1, 0x1b) ^ x1 ^\n+ octeon_snow3g_mulx(x2, 0x1b) ^ x3;\n+ uint8_t r3 = x0 ^ x1 ^ octeon_snow3g_mulx(x2, 0x1b) ^ x2 ^\n+ octeon_snow3g_mulx(x3, 0x1b);\n+\n+ return octeon_snow3g_pack32(r0, r1, r2, r3);\n+}\n+\n+static uint32_t octeon_snow3g_s2(uint32_t w)\n+{\n+ uint8_t x0 = octeon_snow3g_sq[w >> 24];\n+ uint8_t x1 = octeon_snow3g_sq[(uint8_t)(w >> 16)];\n+ uint8_t x2 = octeon_snow3g_sq[(uint8_t)(w >> 8)];\n+ uint8_t x3 = octeon_snow3g_sq[(uint8_t)w];\n+ uint8_t r0 = octeon_snow3g_mulx(x0, 0x69) ^ x1 ^ x2 ^\n+ octeon_snow3g_mulx(x3, 0x69) ^ x3;\n+ uint8_t r1 = octeon_snow3g_mulx(x0, 0x69) ^ x0 ^\n+ octeon_snow3g_mulx(x1, 0x69) ^ x2 ^ x3;\n+ uint8_t r2 = x0 ^ octeon_snow3g_mulx(x1, 0x69) ^ x1 ^\n+ octeon_snow3g_mulx(x2, 0x69) ^ x3;\n+ uint8_t r3 = x0 ^ x1 ^ octeon_snow3g_mulx(x2, 0x69) ^ x2 ^\n+ octeon_snow3g_mulx(x3, 0x69);\n+\n+ return octeon_snow3g_pack32(r0, r1, r2, r3);\n+}\n+\n+static uint32_t octeon_snow3g_clock_fsm(MIPSOcteonCryptoState *crypto)\n+{\n+ uint32_t f = (uint32_t)(crypto->snow3g_lfsr[15] + crypto->snow3g_fsm[0]) ^\n+ crypto->snow3g_fsm[1];\n+ uint32_t r = (uint32_t)(crypto->snow3g_fsm[1] +\n+ (crypto->snow3g_fsm[2] ^ crypto->snow3g_lfsr[5]));\n+\n+ crypto->snow3g_fsm[2] = octeon_snow3g_s2(crypto->snow3g_fsm[1]);\n+ crypto->snow3g_fsm[1] = octeon_snow3g_s1(crypto->snow3g_fsm[0]);\n+ crypto->snow3g_fsm[0] = r;\n+ return f;\n+}\n+\n+static void octeon_snow3g_clock_lfsr(MIPSOcteonCryptoState *crypto,\n+ bool init_mode, uint32_t f)\n+{\n+ uint32_t s0 = crypto->snow3g_lfsr[0];\n+ uint32_t s11 = crypto->snow3g_lfsr[11];\n+ uint32_t v = (s0 << 8) ^ octeon_snow3g_mulalpha(s0 >> 24) ^\n+ crypto->snow3g_lfsr[2] ^ (s11 >> 8) ^\n+ octeon_snow3g_divalpha((uint8_t)s11);\n+ int i;\n+\n+ if (init_mode) {\n+ v ^= f;\n+ }\n+\n+ for (i = 0; i < 15; i++) {\n+ crypto->snow3g_lfsr[i] = crypto->snow3g_lfsr[i + 1];\n+ }\n+ crypto->snow3g_lfsr[15] = v;\n+}\n+\n+static uint32_t octeon_snow3g_generate_word(MIPSOcteonCryptoState *crypto)\n+{\n+ uint32_t f = octeon_snow3g_clock_fsm(crypto);\n+ uint32_t z = f ^ crypto->snow3g_lfsr[0];\n+\n+ octeon_snow3g_clock_lfsr(crypto, false, 0);\n+ return z;\n+}\n+\n+static void octeon_snow3g_queue_result(MIPSOcteonCryptoState *crypto)\n+{\n+ uint32_t z0 = octeon_snow3g_generate_word(crypto);\n+ uint32_t z1 = octeon_snow3g_generate_word(crypto);\n+\n+ crypto->snow3g_result = ((uint64_t)z0 << 32) | z1;\n+}\n+\n+static void octeon_snow3g_start(MIPSOcteonCryptoState *crypto, uint64_t q)\n+{\n+ int i;\n+\n+ octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SNOW3G);\n+ for (i = 0; i < 7; i++) {\n+ uint64_t pair = crypto->sha512_block[i];\n+\n+ crypto->snow3g_lfsr[i * 2] = pair >> 32;\n+ crypto->snow3g_lfsr[i * 2 + 1] = pair;\n+ }\n+ crypto->snow3g_lfsr[14] = q >> 32;\n+ crypto->snow3g_lfsr[15] = q;\n+ memset(crypto->snow3g_fsm, 0, sizeof(crypto->snow3g_fsm));\n+\n+ for (i = 0; i < 32; i++) {\n+ uint32_t f = octeon_snow3g_clock_fsm(crypto);\n+\n+ octeon_snow3g_clock_lfsr(crypto, true, f);\n+ }\n+\n+ (void)octeon_snow3g_clock_fsm(crypto);\n+ octeon_snow3g_clock_lfsr(crypto, false, 0);\n+ octeon_snow3g_queue_result(crypto);\n+}\n+\n+static void octeon_snow3g_more(MIPSOcteonCryptoState *crypto)\n+{\n+ octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SNOW3G);\n+ octeon_snow3g_queue_result(crypto);\n+}\n+\n+static int octeon_aes_key_bits(const MIPSOcteonCryptoState *crypto)\n+{\n+ enum {\n+ OCTEON_AES_KEYLEN_128 = 1,\n+ OCTEON_AES_KEYLEN_192 = 2,\n+ OCTEON_AES_KEYLEN_256 = 3,\n+ };\n+\n+ switch (crypto->aes_keylen) {\n+ case OCTEON_AES_KEYLEN_128:\n+ return 128;\n+ case OCTEON_AES_KEYLEN_192:\n+ return 192;\n+ case OCTEON_AES_KEYLEN_256:\n+ return 256;\n+ default:\n+ return 0;\n+ }\n+}\n+\n+static const uint8_t octeon_des_ip[64] = {\n+ 58, 50, 42, 34, 26, 18, 10, 2,\n+ 60, 52, 44, 36, 28, 20, 12, 4,\n+ 62, 54, 46, 38, 30, 22, 14, 6,\n+ 64, 56, 48, 40, 32, 24, 16, 8,\n+ 57, 49, 41, 33, 25, 17, 9, 1,\n+ 59, 51, 43, 35, 27, 19, 11, 3,\n+ 61, 53, 45, 37, 29, 21, 13, 5,\n+ 63, 55, 47, 39, 31, 23, 15, 7,\n+};\n+\n+static const uint8_t octeon_des_fp[64] = {\n+ 40, 8, 48, 16, 56, 24, 64, 32,\n+ 39, 7, 47, 15, 55, 23, 63, 31,\n+ 38, 6, 46, 14, 54, 22, 62, 30,\n+ 37, 5, 45, 13, 53, 21, 61, 29,\n+ 36, 4, 44, 12, 52, 20, 60, 28,\n+ 35, 3, 43, 11, 51, 19, 59, 27,\n+ 34, 2, 42, 10, 50, 18, 58, 26,\n+ 33, 1, 41, 9, 49, 17, 57, 25,\n+};\n+\n+static const uint8_t octeon_des_e[48] = {\n+ 32, 1, 2, 3, 4, 5,\n+ 4, 5, 6, 7, 8, 9,\n+ 8, 9, 10, 11, 12, 13,\n+ 12, 13, 14, 15, 16, 17,\n+ 16, 17, 18, 19, 20, 21,\n+ 20, 21, 22, 23, 24, 25,\n+ 24, 25, 26, 27, 28, 29,\n+ 28, 29, 30, 31, 32, 1,\n+};\n+\n+static const uint8_t octeon_des_p[32] = {\n+ 16, 7, 20, 21, 29, 12, 28, 17,\n+ 1, 15, 23, 26, 5, 18, 31, 10,\n+ 2, 8, 24, 14, 32, 27, 3, 9,\n+ 19, 13, 30, 6, 22, 11, 4, 25,\n+};\n+\n+static const uint8_t octeon_des_pc1[56] = {\n+ 57, 49, 41, 33, 25, 17, 9,\n+ 1, 58, 50, 42, 34, 26, 18,\n+ 10, 2, 59, 51, 43, 35, 27,\n+ 19, 11, 3, 60, 52, 44, 36,\n+ 63, 55, 47, 39, 31, 23, 15,\n+ 7, 62, 54, 46, 38, 30, 22,\n+ 14, 6, 61, 53, 45, 37, 29,\n+ 21, 13, 5, 28, 20, 12, 4,\n+};\n+\n+static const uint8_t octeon_des_pc2[48] = {\n+ 14, 17, 11, 24, 1, 5,\n+ 3, 28, 15, 6, 21, 10,\n+ 23, 19, 12, 4, 26, 8,\n+ 16, 7, 27, 20, 13, 2,\n+ 41, 52, 31, 37, 47, 55,\n+ 30, 40, 51, 45, 33, 48,\n+ 44, 49, 39, 56, 34, 53,\n+ 46, 42, 50, 36, 29, 32,\n+};\n+\n+static const uint8_t octeon_des_rotations[16] = {\n+ 1, 1, 2, 2, 2, 2, 2, 2,\n+ 1, 2, 2, 2, 2, 2, 2, 1,\n+};\n+\n+static const uint8_t octeon_des_sboxes[8][64] = {\n+ {\n+ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,\n+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,\n+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,\n+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,\n+ },\n+ {\n+ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,\n+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,\n+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,\n+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,\n+ },\n+ {\n+ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,\n+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,\n+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,\n+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,\n+ },\n+ {\n+ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,\n+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,\n+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,\n+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,\n+ },\n+ {\n+ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,\n+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,\n+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,\n+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,\n+ },\n+ {\n+ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,\n+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,\n+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,\n+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,\n+ },\n+ {\n+ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,\n+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,\n+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,\n+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,\n+ },\n+ {\n+ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,\n+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,\n+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,\n+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,\n+ },\n+};\n+\n+static const uint8_t octeon_kasumi_s7[128] = {\n+ 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18,\n+ 123, 33, 55, 113, 39, 114, 21, 67, 65, 12, 47, 73, 46, 27,\n+ 25, 111, 124, 81, 53, 9, 121, 79, 52, 60, 58, 48, 101, 127,\n+ 40, 120, 104, 70, 71, 43, 20, 122, 72, 61, 23, 109, 13, 100,\n+ 77, 1, 16, 7, 82, 10, 105, 98, 117, 116, 76, 11, 89, 106,\n+ 0, 125, 118, 99, 86, 69, 30, 57, 126, 87, 112, 51, 17, 5,\n+ 95, 14, 90, 84, 91, 8, 35, 103, 32, 97, 28, 66, 102, 31,\n+ 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29, 115, 44,\n+ 64, 107, 108, 24, 110, 83, 36, 78, 42, 19, 15, 41, 88, 119,\n+ 59, 3,\n+};\n+\n+static const uint16_t octeon_kasumi_s9[512] = {\n+ 167, 239, 161, 379, 391, 334, 9, 338, 38, 226, 48, 358, 452, 385,\n+ 90, 397, 183, 253, 147, 331, 415, 340, 51, 362, 306, 500, 262, 82,\n+ 216, 159, 356, 177, 175, 241, 489, 37, 206, 17, 0, 333, 44, 254,\n+ 378, 58, 143, 220, 81, 400, 95, 3, 315, 245, 54, 235, 218, 405,\n+ 472, 264, 172, 494, 371, 290, 399, 76, 165, 197, 395, 121, 257, 480,\n+ 423, 212, 240, 28, 462, 176, 406, 507, 288, 223, 501, 407, 249, 265,\n+ 89, 186, 221, 428, 164, 74, 440, 196, 458, 421, 350, 163, 232, 158,\n+ 134, 354, 13, 250, 491, 142, 191, 69, 193, 425, 152, 227, 366, 135,\n+ 344, 300, 276, 242, 437, 320, 113, 278, 11, 243, 87, 317, 36, 93,\n+ 496, 27, 487, 446, 482, 41, 68, 156, 457, 131, 326, 403, 339, 20,\n+ 39, 115, 442, 124, 475, 384, 508, 53, 112, 170, 479, 151, 126, 169,\n+ 73, 268, 279, 321, 168, 364, 363, 292, 46, 499, 393, 327, 324, 24,\n+ 456, 267, 157, 460, 488, 426, 309, 229, 439, 506, 208, 271, 349, 401,\n+ 434, 236, 16, 209, 359, 52, 56, 120, 199, 277, 465, 416, 252, 287,\n+ 246, 6, 83, 305, 420, 345, 153, 502, 65, 61, 244, 282, 173, 222,\n+ 418, 67, 386, 368, 261, 101, 476, 291, 195, 430, 49, 79, 166, 330,\n+ 280, 383, 373, 128, 382, 408, 155, 495, 367, 388, 274, 107, 459, 417,\n+ 62, 454, 132, 225, 203, 316, 234, 14, 301, 91, 503, 286, 424, 211,\n+ 347, 307, 140, 374, 35, 103, 125, 427, 19, 214, 453, 146, 498, 314,\n+ 444, 230, 256, 329, 198, 285, 50, 116, 78, 410, 10, 205, 510, 171,\n+ 231, 45, 139, 467, 29, 86, 505, 32, 72, 26, 342, 150, 313, 490,\n+ 431, 238, 411, 325, 149, 473, 40, 119, 174, 355, 185, 233, 389, 71,\n+ 448, 273, 372, 55, 110, 178, 322, 12, 469, 392, 369, 190, 1, 109,\n+ 375, 137, 181, 88, 75, 308, 260, 484, 98, 272, 370, 275, 412, 111,\n+ 336, 318, 4, 504, 492, 259, 304, 77, 337, 435, 21, 357, 303, 332,\n+ 483, 18, 47, 85, 25, 497, 474, 289, 100, 269, 296, 478, 270, 106,\n+ 31, 104, 433, 84, 414, 486, 394, 96, 99, 154, 511, 148, 413, 361,\n+ 409, 255, 162, 215, 302, 201, 266, 351, 343, 144, 441, 365, 108, 298,\n+ 251, 34, 182, 509, 138, 210, 335, 133, 311, 352, 328, 141, 396, 346,\n+ 123, 319, 450, 281, 429, 228, 443, 481, 92, 404, 485, 422, 248, 297,\n+ 23, 213, 130, 466, 22, 217, 283, 70, 294, 360, 419, 127, 312, 377,\n+ 7, 468, 194, 2, 117, 295, 463, 258, 224, 447, 247, 187, 80, 398,\n+ 284, 353, 105, 390, 299, 471, 470, 184, 57, 200, 348, 63, 204, 188,\n+ 33, 451, 97, 30, 310, 219, 94, 160, 129, 493, 64, 179, 263, 102,\n+ 189, 207, 114, 402, 438, 477, 387, 122, 192, 42, 381, 5, 145, 118,\n+ 180, 449, 293, 323, 136, 380, 43, 66, 60, 455, 341, 445, 202, 432,\n+ 8, 237, 15, 376, 436, 464, 59, 461,\n+};\n+\n+static const uint16_t octeon_kasumi_constants[8] = {\n+ 0x0123, 0x4567, 0x89ab, 0xcdef, 0xfedc, 0xba98, 0x7654, 0x3210,\n+};\n+\n+typedef struct OcteonKasumiSubkeys {\n+ uint16_t kli1[8];\n+ uint16_t kli2[8];\n+ uint16_t koi1[8];\n+ uint16_t koi2[8];\n+ uint16_t koi3[8];\n+ uint16_t kii1[8];\n+ uint16_t kii2[8];\n+ uint16_t kii3[8];\n+} OcteonKasumiSubkeys;\n+\n+static uint64_t octeon_des_permute(uint64_t input, const uint8_t *table,\n+ size_t output_bits, size_t input_bits)\n+{\n+ uint64_t out = 0;\n+\n+ for (size_t i = 0; i < output_bits; i++) {\n+ unsigned src = table[i] - 1;\n+\n+ out = (out << 1) | ((input >> (input_bits - 1 - src)) & 1);\n+ }\n+ return out;\n+}\n+\n+static uint32_t octeon_des_rotate28(uint32_t v, unsigned shift)\n+{\n+ return ((v << shift) | (v >> (28 - shift))) & 0x0fffffffU;\n+}\n+\n+static void octeon_des_expand_subkeys(uint64_t key, uint64_t subkeys[16])\n+{\n+ uint64_t permuted = octeon_des_permute(key, octeon_des_pc1,\n+ ARRAY_SIZE(octeon_des_pc1), 64);\n+ uint32_t c = (permuted >> 28) & 0x0fffffffU;\n+ uint32_t d = permuted & 0x0fffffffU;\n+\n+ for (int i = 0; i < 16; i++) {\n+ c = octeon_des_rotate28(c, octeon_des_rotations[i]);\n+ d = octeon_des_rotate28(d, octeon_des_rotations[i]);\n+ subkeys[i] = octeon_des_permute(((uint64_t)c << 28) | d,\n+ octeon_des_pc2,\n+ ARRAY_SIZE(octeon_des_pc2), 56);\n+ }\n+}\n+\n+static uint32_t octeon_des_f(uint32_t r, uint64_t subkey)\n+{\n+ uint64_t expanded = octeon_des_permute(r, octeon_des_e,\n+ ARRAY_SIZE(octeon_des_e), 32);\n+ uint32_t out = 0;\n+\n+ expanded ^= subkey;\n+ for (int i = 0; i < 8; i++) {\n+ uint8_t sextet = (expanded >> (42 - i * 6)) & 0x3f;\n+ uint8_t row = ((sextet & 0x20) >> 4) | (sextet & 0x01);\n+ uint8_t col = (sextet >> 1) & 0x0f;\n+\n+ out = (out << 4) | octeon_des_sboxes[i][row * 16 + col];\n+ }\n+\n+ return octeon_des_permute(out, octeon_des_p, ARRAY_SIZE(octeon_des_p), 32);\n+}\n+\n+static uint64_t octeon_des_block_crypt(uint64_t block, uint64_t key,\n+ bool encrypt)\n+{\n+ uint64_t subkeys[16];\n+ uint64_t permuted = octeon_des_permute(block, octeon_des_ip,\n+ ARRAY_SIZE(octeon_des_ip), 64);\n+ uint32_t l = permuted >> 32;\n+ uint32_t r = permuted;\n+\n+ octeon_des_expand_subkeys(key, subkeys);\n+\n+ for (int i = 0; i < 16; i++) {\n+ uint32_t next = l ^ octeon_des_f(r, subkeys[encrypt ? i : 15 - i]);\n+\n+ l = r;\n+ r = next;\n+ }\n+\n+ return octeon_des_permute(((uint64_t)r << 32) | l,\n+ octeon_des_fp, ARRAY_SIZE(octeon_des_fp), 64);\n+}\n+\n+static uint64_t octeon_3des_block_crypt(uint64_t block, const uint64_t keys[3],\n+ bool encrypt)\n+{\n+ if (encrypt) {\n+ block = octeon_des_block_crypt(block, keys[0], true);\n+ block = octeon_des_block_crypt(block, keys[1], false);\n+ block = octeon_des_block_crypt(block, keys[2], true);\n+ } else {\n+ block = octeon_des_block_crypt(block, keys[2], false);\n+ block = octeon_des_block_crypt(block, keys[1], true);\n+ block = octeon_des_block_crypt(block, keys[0], false);\n+ }\n+ return block;\n+}\n+\n+static void octeon_3des_crypt_common(MIPSOcteonCryptoState *crypto,\n+ uint64_t input_reg,\n+ bool encrypt, bool cbc)\n+{\n+ const uint64_t keys[3] = {\n+ crypto->des3_key[0],\n+ crypto->des3_key[1],\n+ crypto->des3_key[2],\n+ };\n+ uint64_t block = input_reg;\n+\n+ if (cbc) {\n+ if (encrypt) {\n+ block ^= crypto->des3_iv;\n+ block = octeon_3des_block_crypt(block, keys, true);\n+ crypto->des3_iv = block;\n+ } else {\n+ block = octeon_3des_block_crypt(block, keys, false);\n+ block ^= crypto->des3_iv;\n+ crypto->des3_iv = input_reg;\n+ }\n+ } else {\n+ block = octeon_3des_block_crypt(block, keys, encrypt);\n+ }\n+\n+ crypto->des3_result = block;\n+}\n+\n+static inline uint16_t octeon_rol16(uint16_t value, unsigned int bits)\n+{\n+ return (value << bits) | (value >> (16 - bits));\n+}\n+\n+static void octeon_kasumi_key_schedule(const uint64_t key_regs[2],\n+ OcteonKasumiSubkeys *subkeys)\n+{\n+ uint16_t key[8];\n+ uint16_t key_prime[8];\n+\n+ key[0] = key_regs[0] >> 48;\n+ key[1] = key_regs[0] >> 32;\n+ key[2] = key_regs[0] >> 16;\n+ key[3] = key_regs[0];\n+ key[4] = key_regs[1] >> 48;\n+ key[5] = key_regs[1] >> 32;\n+ key[6] = key_regs[1] >> 16;\n+ key[7] = key_regs[1];\n+\n+ for (int i = 0; i < 8; i++) {\n+ key_prime[i] = key[i] ^ octeon_kasumi_constants[i];\n+ }\n+\n+ for (int i = 0; i < 8; i++) {\n+ subkeys->kli1[i] = octeon_rol16(key[i], 1);\n+ subkeys->kli2[i] = key_prime[(i + 2) & 7];\n+ subkeys->koi1[i] = octeon_rol16(key[(i + 1) & 7], 5);\n+ subkeys->koi2[i] = octeon_rol16(key[(i + 5) & 7], 8);\n+ subkeys->koi3[i] = octeon_rol16(key[(i + 6) & 7], 13);\n+ subkeys->kii1[i] = key_prime[(i + 4) & 7];\n+ subkeys->kii2[i] = key_prime[(i + 3) & 7];\n+ subkeys->kii3[i] = key_prime[(i + 7) & 7];\n+ }\n+}\n+\n+static uint16_t octeon_kasumi_fi(uint16_t in, uint16_t subkey)\n+{\n+ uint16_t nine = in >> 7;\n+ uint16_t seven = in & 0x7f;\n+\n+ nine = octeon_kasumi_s9[nine] ^ seven;\n+ seven = octeon_kasumi_s7[seven] ^ (nine & 0x7f);\n+ seven ^= subkey >> 9;\n+ nine ^= subkey & 0x1ff;\n+ nine = octeon_kasumi_s9[nine] ^ seven;\n+ seven = octeon_kasumi_s7[seven] ^ (nine & 0x7f);\n+ return (seven << 9) | nine;\n+}\n+\n+static uint32_t octeon_kasumi_fo(uint32_t in, int index,\n+ const OcteonKasumiSubkeys *subkeys)\n+{\n+ uint16_t left = in >> 16;\n+ uint16_t right = in;\n+\n+ left ^= subkeys->koi1[index];\n+ left = octeon_kasumi_fi(left, subkeys->kii1[index]);\n+ left ^= right;\n+ right ^= subkeys->koi2[index];\n+ right = octeon_kasumi_fi(right, subkeys->kii2[index]);\n+ right ^= left;\n+ left ^= subkeys->koi3[index];\n+ left = octeon_kasumi_fi(left, subkeys->kii3[index]);\n+ left ^= right;\n+\n+ return ((uint32_t)right << 16) | left;\n+}\n+\n+static uint32_t octeon_kasumi_fl(uint32_t in, int index,\n+ const OcteonKasumiSubkeys *subkeys)\n+{\n+ uint16_t left = in >> 16;\n+ uint16_t right = in;\n+ uint16_t a = left & subkeys->kli1[index];\n+ uint16_t b;\n+\n+ right ^= octeon_rol16(a, 1);\n+ b = right | subkeys->kli2[index];\n+ left ^= octeon_rol16(b, 1);\n+ return ((uint32_t)left << 16) | right;\n+}\n+\n+static uint64_t octeon_kasumi_block_encrypt(uint64_t block,\n+ const uint64_t key_regs[2])\n+{\n+ OcteonKasumiSubkeys subkeys;\n+ uint32_t left = block >> 32;\n+ uint32_t right = block;\n+\n+ octeon_kasumi_key_schedule(key_regs, &subkeys);\n+\n+ for (int i = 0; i < 8; ) {\n+ uint32_t temp = octeon_kasumi_fl(left, i, &subkeys);\n+\n+ temp = octeon_kasumi_fo(temp, i++, &subkeys);\n+ right ^= temp;\n+ temp = octeon_kasumi_fo(right, i, &subkeys);\n+ temp = octeon_kasumi_fl(temp, i++, &subkeys);\n+ left ^= temp;\n+ }\n+\n+ return ((uint64_t)left << 32) | right;\n+}\n+\n+static void octeon_kasumi_crypt_common(MIPSOcteonCryptoState *crypto,\n+ uint64_t input_reg, bool cbc)\n+{\n+ const uint64_t key_regs[2] = {\n+ crypto->des3_key[0],\n+ crypto->des3_key[1],\n+ };\n+ uint64_t block = input_reg;\n+\n+ if (cbc) {\n+ block ^= crypto->des3_iv;\n+ }\n+\n+ block = octeon_kasumi_block_encrypt(block, key_regs);\n+ if (cbc) {\n+ crypto->des3_iv = block;\n+ }\n+ crypto->des3_result = block;\n+}\n+\n+static void octeon_aes_load_key(const MIPSOcteonCryptoState *crypto,\n+ uint8_t *key, size_t keylen)\n+{\n+ stq_be_p(key, crypto->aes_key[0]);\n+ stq_be_p(key + 8, crypto->aes_key[1]);\n+ if (keylen > 16) {\n+ stq_be_p(key + 16, crypto->aes_key[2]);\n+ }\n+ if (keylen > 24) {\n+ stq_be_p(key + 24, crypto->aes_key[3]);\n+ }\n+}\n+\n+static void octeon_aes_load_block(const uint64_t regs[2], uint8_t *block)\n+{\n+ stq_be_p(block, regs[0]);\n+ stq_be_p(block + 8, regs[1]);\n+}\n+\n+static void octeon_aes_store_block(uint64_t regs[2], const uint8_t *block)\n+{\n+ regs[0] = ldq_be_p(block);\n+ regs[1] = ldq_be_p(block + 8);\n+}\n+\n+static void octeon_aes_encrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)\n+{\n+ AES_KEY key;\n+ uint8_t in[16];\n+ uint8_t out[16];\n+ uint8_t iv[16];\n+ uint8_t raw_key[32] = {};\n+ int bits = octeon_aes_key_bits(crypto);\n+\n+ if (!bits) {\n+ return;\n+ }\n+\n+ octeon_aes_load_key(crypto, raw_key, bits / 8);\n+ octeon_aes_load_block(crypto->aes_input, in);\n+ if (cbc) {\n+ int i;\n+\n+ octeon_aes_load_block(crypto->aes_iv, iv);\n+ for (i = 0; i < sizeof(in); i++) {\n+ in[i] ^= iv[i];\n+ }\n+ }\n+\n+ AES_set_encrypt_key(raw_key, bits, &key);\n+ AES_encrypt(in, out, &key);\n+ octeon_aes_store_block(crypto->aes_result, out);\n+ if (cbc) {\n+ octeon_aes_store_block(crypto->aes_iv, out);\n+ }\n+}\n+\n+static void octeon_aes_decrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)\n+{\n+ AES_KEY key;\n+ uint8_t in[16];\n+ uint8_t out[16];\n+ uint8_t iv[16];\n+ uint8_t next_iv[16];\n+ uint8_t raw_key[32] = {};\n+ int bits = octeon_aes_key_bits(crypto);\n+ int i;\n+\n+ if (!bits) {\n+ return;\n+ }\n+\n+ octeon_aes_load_key(crypto, raw_key, bits / 8);\n+ octeon_aes_load_block(crypto->aes_input, in);\n+ if (cbc) {\n+ memcpy(next_iv, in, sizeof(next_iv));\n+ octeon_aes_load_block(crypto->aes_iv, iv);\n+ }\n+\n+ AES_set_decrypt_key(raw_key, bits, &key);\n+ AES_decrypt(in, out, &key);\n+ if (cbc) {\n+ for (i = 0; i < sizeof(out); i++) {\n+ out[i] ^= iv[i];\n+ }\n+ }\n+\n+ octeon_aes_store_block(crypto->aes_result, out);\n+ if (cbc) {\n+ octeon_aes_store_block(crypto->aes_iv, next_iv);\n+ }\n+}\n+\n+static void octeon_gfm_mul(const uint64_t x[2], const uint64_t y[2],\n+ uint16_t poly, uint64_t out[2])\n+{\n+ uint64_t zh = 0, zl = 0;\n+ uint64_t vh = y[0], vl = y[1];\n+ uint64_t rh = (uint64_t)poly << 48;\n+ int i;\n+\n+ for (i = 0; i < 128; i++) {\n+ bool bit;\n+ bool lsb;\n+\n+ if (i < 64) {\n+ bit = (x[0] >> (63 - i)) & 1;\n+ } else {\n+ bit = (x[1] >> (127 - i)) & 1;\n+ }\n+ if (bit) {\n+ zh ^= vh;\n+ zl ^= vl;\n+ }\n+\n+ lsb = vl & 1;\n+ vl = (vh << 63) | (vl >> 1);\n+ vh >>= 1;\n+ if (lsb) {\n+ vh ^= rh;\n+ }\n+ }\n+\n+ out[0] = zh;\n+ out[1] = zl;\n+}\n+\n+target_ulong helper_octeon_cop2_dmfc2(CPUMIPSState *env, uint32_t sel)\n+{\n+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;\n+\n+ if (crypto->shared_mode == OCTEON_SHARED_MODE_SNOW3G) {\n+ if (sel >= OCTEON_COP2_SEL_SNOW3G_LFSR0 &&\n+ sel <= OCTEON_COP2_SEL_SNOW3G_LFSR7) {\n+ unsigned int idx = sel - OCTEON_COP2_SEL_SNOW3G_LFSR0;\n+\n+ return ((uint64_t)crypto->snow3g_lfsr[idx * 2] << 32) |\n+ crypto->snow3g_lfsr[idx * 2 + 1];\n+ }\n+ switch (sel) {\n+ case OCTEON_COP2_SEL_SNOW3G_RESULT:\n+ return crypto->snow3g_result;\n+ case OCTEON_COP2_SEL_SNOW3G_FSM0:\n+ case OCTEON_COP2_SEL_SNOW3G_FSM1:\n+ case OCTEON_COP2_SEL_SNOW3G_FSM2:\n+ return crypto->snow3g_fsm[sel - OCTEON_COP2_SEL_SNOW3G_FSM0];\n+ default:\n+ break;\n+ }\n+ }\n+\n+ switch (sel) {\n+ case OCTEON_COP2_SEL_3DES_KEY0:\n+ case OCTEON_COP2_SEL_3DES_KEY1:\n+ case OCTEON_COP2_SEL_3DES_KEY2:\n+ return crypto->des3_key[sel - OCTEON_COP2_SEL_3DES_KEY0];\n+ case OCTEON_COP2_SEL_3DES_IV:\n+ return crypto->des3_iv;\n+ case OCTEON_COP2_SEL_3DES_RESULT:\n+ case OCTEON_COP2_SEL_3DES_RESULT_IN:\n+ return crypto->des3_result;\n+ case OCTEON_COP2_SEL_AES_RESULT0:\n+ case OCTEON_COP2_SEL_AES_RESULT1:\n+ return crypto->aes_result[sel - OCTEON_COP2_SEL_AES_RESULT0];\n+ case OCTEON_COP2_SEL_AES_KEY0:\n+ case OCTEON_COP2_SEL_AES_KEY1:\n+ case OCTEON_COP2_SEL_AES_KEY2:\n+ case OCTEON_COP2_SEL_AES_KEY3:\n+ return crypto->aes_key[sel - OCTEON_COP2_SEL_AES_KEY0];\n+ case OCTEON_COP2_SEL_AES_KEYLENGTH:\n+ return crypto->aes_keylen;\n+ case OCTEON_COP2_SEL_AES_DAT0:\n+ return crypto->aes_input[0];\n+ case OCTEON_COP2_SEL_AES_IV0:\n+ case OCTEON_COP2_SEL_AES_IV1:\n+ return crypto->aes_iv[sel - OCTEON_COP2_SEL_AES_IV0];\n+ case OCTEON_COP2_SEL_CRC_POLYNOMIAL:\n+ return crypto->crc_poly;\n+ case OCTEON_COP2_SEL_CRC_IV:\n+ return crypto->crc_iv;\n+ case OCTEON_COP2_SEL_CRC_LEN:\n+ return crypto->crc_len;\n+ case OCTEON_COP2_SEL_CRC_IV_REFLECT:\n+ return octeon_crc_reflect32_by_byte(crypto->crc_iv);\n+ case OCTEON_COP2_SEL_HSH_DATW0:\n+ case OCTEON_COP2_SEL_HSH_DATW1:\n+ case OCTEON_COP2_SEL_HSH_DATW2:\n+ case OCTEON_COP2_SEL_HSH_DATW3:\n+ case OCTEON_COP2_SEL_HSH_DATW4:\n+ case OCTEON_COP2_SEL_HSH_DATW5:\n+ case OCTEON_COP2_SEL_HSH_DATW6:\n+ case OCTEON_COP2_SEL_HSH_DATW7:\n+ return crypto->sha512_block[sel - OCTEON_COP2_SEL_HSH_DATW0];\n+ case OCTEON_COP2_SEL_HSH_IVW0:\n+ case OCTEON_COP2_SEL_HSH_IVW1:\n+ case OCTEON_COP2_SEL_HSH_IVW2:\n+ case OCTEON_COP2_SEL_HSH_IVW3:\n+ case OCTEON_COP2_SEL_HSH_IVW4:\n+ case OCTEON_COP2_SEL_HSH_IVW5:\n+ case OCTEON_COP2_SEL_HSH_IVW6:\n+ case OCTEON_COP2_SEL_HSH_IVW7:\n+ return crypto->sha512_state[sel - OCTEON_COP2_SEL_HSH_IVW0];\n+ case OCTEON_COP2_SEL_HSH_IV0:\n+ case OCTEON_COP2_SEL_HSH_IV1:\n+ case OCTEON_COP2_SEL_HSH_IV2:\n+ case OCTEON_COP2_SEL_HSH_IV3:\n+ return crypto->hash_state[sel - OCTEON_COP2_SEL_HSH_IV0];\n+ case OCTEON_COP2_SEL_GFM_MUL_REFLECT0:\n+ case OCTEON_COP2_SEL_GFM_MUL_REFLECT1:\n+ return crypto->gfm_reflect_mul[sel - OCTEON_COP2_SEL_GFM_MUL_REFLECT0];\n+ case OCTEON_COP2_SEL_GFM_RESINP_REFLECT0:\n+ case OCTEON_COP2_SEL_GFM_RESINP_REFLECT1:\n+ return crypto->gfm_reflect_result[\n+ sel - OCTEON_COP2_SEL_GFM_RESINP_REFLECT0];\n+ case OCTEON_COP2_SEL_GFM_MUL0:\n+ case OCTEON_COP2_SEL_GFM_MUL1:\n+ return crypto->gfm_mul[sel - OCTEON_COP2_SEL_GFM_MUL0];\n+ case OCTEON_COP2_SEL_GFM_RESINP0:\n+ case OCTEON_COP2_SEL_GFM_RESINP1:\n+ return crypto->gfm_result[sel - OCTEON_COP2_SEL_GFM_RESINP0];\n+ case OCTEON_COP2_SEL_GFM_POLY:\n+ return crypto->gfm_poly;\n+ default:\n+ return 0;\n+ }\n+}\n+\n+void helper_octeon_cop2_dmtc2(CPUMIPSState *env, target_ulong value,\n+ uint32_t sel)\n+{\n+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;\n+ uint64_t q = (uint64_t)value;\n+\n+ switch (sel) {\n+ case OCTEON_COP2_SEL_3DES_KEY0:\n+ case OCTEON_COP2_SEL_3DES_KEY1:\n+ case OCTEON_COP2_SEL_3DES_KEY2:\n+ crypto->des3_key[sel - OCTEON_COP2_SEL_3DES_KEY0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_3DES_IV:\n+ crypto->des3_iv = q;\n+ break;\n+ case OCTEON_COP2_SEL_3DES_RESULT_IN:\n+ crypto->des3_result = q;\n+ break;\n+ case OCTEON_COP2_SEL_3DES_ENC_CBC:\n+ octeon_3des_crypt_common(crypto, q, true, true);\n+ break;\n+ case OCTEON_COP2_SEL_KAS_ENC_CBC:\n+ octeon_kasumi_crypt_common(crypto, q, true);\n+ break;\n+ case OCTEON_COP2_SEL_3DES_ENC:\n+ octeon_3des_crypt_common(crypto, q, true, false);\n+ break;\n+ case OCTEON_COP2_SEL_KAS_ENC:\n+ octeon_kasumi_crypt_common(crypto, q, false);\n+ break;\n+ case OCTEON_COP2_SEL_3DES_DEC_CBC:\n+ octeon_3des_crypt_common(crypto, q, false, true);\n+ break;\n+ case OCTEON_COP2_SEL_3DES_DEC:\n+ octeon_3des_crypt_common(crypto, q, false, false);\n+ break;\n+ case OCTEON_COP2_SEL_AES_IV0:\n+ case OCTEON_COP2_SEL_AES_IV1:\n+ crypto->aes_iv[sel - OCTEON_COP2_SEL_AES_IV0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_AES_KEY0:\n+ case OCTEON_COP2_SEL_AES_KEY1:\n+ case OCTEON_COP2_SEL_AES_KEY2:\n+ case OCTEON_COP2_SEL_AES_KEY3:\n+ crypto->aes_key[sel - OCTEON_COP2_SEL_AES_KEY0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_AES_ENC_CBC0:\n+ case OCTEON_COP2_SEL_AES_ENC0:\n+ case OCTEON_COP2_SEL_AES_DEC_CBC0:\n+ case OCTEON_COP2_SEL_AES_DEC0:\n+ crypto->aes_input[0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_AES_KEYLENGTH:\n+ crypto->aes_keylen = q;\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL:\n+ case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL_REFLECT:\n+ crypto->crc_poly = q;\n+ break;\n+ case OCTEON_COP2_SEL_CRC_IV:\n+ crypto->crc_iv = q;\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_LEN:\n+ crypto->crc_len = q;\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_IV_REFLECT:\n+ crypto->crc_iv = octeon_crc_reflect32_by_byte((uint32_t)q);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_BYTE:\n+ octeon_crc_update_normal(crypto, q, 1);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_HALF:\n+ octeon_crc_update_normal(crypto, q, 2);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_WORD:\n+ octeon_crc_update_normal(crypto, q, 4);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_DWORD:\n+ octeon_crc_update_normal(crypto, q, 8);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_VAR:\n+ octeon_crc_update_normal(crypto, q, MIN(8U, crypto->crc_len));\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_BYTE_REFLECT:\n+ octeon_crc_update_reflect(crypto, q, 1);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_HALF_REFLECT:\n+ octeon_crc_update_reflect(crypto, q, 2);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_WORD_REFLECT:\n+ octeon_crc_update_reflect(crypto, q, 4);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_DWORD_REFLECT:\n+ octeon_crc_update_reflect(crypto, q, 8);\n+ break;\n+ case OCTEON_COP2_SEL_CRC_WRITE_VAR_REFLECT:\n+ octeon_crc_update_reflect(crypto, q, MIN(8U, crypto->crc_len));\n+ break;\n+ case OCTEON_COP2_SEL_HSH_DATW0:\n+ case OCTEON_COP2_SEL_HSH_DATW1:\n+ case OCTEON_COP2_SEL_HSH_DATW2:\n+ case OCTEON_COP2_SEL_HSH_DATW3:\n+ case OCTEON_COP2_SEL_HSH_DATW4:\n+ case OCTEON_COP2_SEL_HSH_DATW5:\n+ case OCTEON_COP2_SEL_HSH_DATW6:\n+ case OCTEON_COP2_SEL_HSH_DATW7:\n+ case OCTEON_COP2_SEL_HSH_DATW8:\n+ case OCTEON_COP2_SEL_HSH_DATW9:\n+ case OCTEON_COP2_SEL_HSH_DATW10:\n+ case OCTEON_COP2_SEL_HSH_DATW11:\n+ case OCTEON_COP2_SEL_HSH_DATW12:\n+ case OCTEON_COP2_SEL_HSH_DATW13:\n+ case OCTEON_COP2_SEL_HSH_DATW14:\n+ crypto->sha512_block[sel - OCTEON_COP2_SEL_HSH_DATW0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_HSH_DATW15:\n+ case OCTEON_COP2_SEL_HSH_STARTSHA512:\n+ crypto->sha512_block[15] = q;\n+ octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA512);\n+ octeon_sha512_transform(crypto);\n+ break;\n+ case OCTEON_COP2_SEL_HSH_IVW0:\n+ case OCTEON_COP2_SEL_HSH_IVW1:\n+ case OCTEON_COP2_SEL_HSH_IVW2:\n+ case OCTEON_COP2_SEL_HSH_IVW3:\n+ case OCTEON_COP2_SEL_HSH_IVW4:\n+ case OCTEON_COP2_SEL_HSH_IVW5:\n+ case OCTEON_COP2_SEL_HSH_IVW6:\n+ case OCTEON_COP2_SEL_HSH_IVW7:\n+ crypto->sha512_state[sel - OCTEON_COP2_SEL_HSH_IVW0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_GFM_MUL_REFLECT0:\n+ case OCTEON_COP2_SEL_GFM_MUL_REFLECT1:\n+ crypto->gfm_reflect_mul[\n+ sel - OCTEON_COP2_SEL_GFM_MUL_REFLECT0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_GFM_XOR0_REFLECT:\n+ crypto->gfm_reflect_xor0 = q;\n+ break;\n+ case OCTEON_COP2_SEL_GFM_MUL0:\n+ case OCTEON_COP2_SEL_GFM_MUL1:\n+ crypto->gfm_mul[sel - OCTEON_COP2_SEL_GFM_MUL0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_GFM_RESINP0:\n+ case OCTEON_COP2_SEL_GFM_RESINP1:\n+ crypto->gfm_result[sel - OCTEON_COP2_SEL_GFM_RESINP0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_GFM_XOR0:\n+ crypto->gfm_xor0 = q;\n+ break;\n+ case OCTEON_COP2_SEL_GFM_POLY:\n+ crypto->gfm_poly = q;\n+ break;\n+ case OCTEON_COP2_SEL_HSH_DAT0:\n+ case OCTEON_COP2_SEL_HSH_DAT1:\n+ case OCTEON_COP2_SEL_HSH_DAT2:\n+ case OCTEON_COP2_SEL_HSH_DAT3:\n+ case OCTEON_COP2_SEL_HSH_DAT4:\n+ case OCTEON_COP2_SEL_HSH_DAT5:\n+ case OCTEON_COP2_SEL_HSH_DAT6:\n+ crypto->hash_block[sel - OCTEON_COP2_SEL_HSH_DAT0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_HSH_IV0:\n+ case OCTEON_COP2_SEL_HSH_IV1:\n+ case OCTEON_COP2_SEL_HSH_IV2:\n+ case OCTEON_COP2_SEL_HSH_IV3:\n+ crypto->hash_state[sel - OCTEON_COP2_SEL_HSH_IV0] = q;\n+ break;\n+ case OCTEON_COP2_SEL_HSH_STARTMD5:\n+ crypto->hash_block[7] = q;\n+ octeon_md5_transform(crypto);\n+ break;\n+ case OCTEON_COP2_SEL_HSH_STARTSHA256:\n+ crypto->hash_block[7] = q;\n+ octeon_sha256_transform(crypto);\n+ break;\n+ case OCTEON_COP2_SEL_HSH_STARTSHA1_COMPAT:\n+ case OCTEON_COP2_SEL_HSH_STARTSHA1:\n+ crypto->hash_block[7] = q;\n+ octeon_sha1_transform(crypto);\n+ break;\n+ case OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT:\n+ octeon_gfm_mul_reflect(crypto, q);\n+ break;\n+ case OCTEON_COP2_SEL_AES_ENC_CBC1:\n+ crypto->aes_input[1] = q;\n+ octeon_aes_encrypt_common(crypto, true);\n+ break;\n+ case OCTEON_COP2_SEL_AES_ENC1:\n+ crypto->aes_input[1] = q;\n+ octeon_aes_encrypt_common(crypto, false);\n+ break;\n+ case OCTEON_COP2_SEL_AES_DEC_CBC1:\n+ crypto->aes_input[1] = q;\n+ octeon_aes_decrypt_common(crypto, true);\n+ break;\n+ case OCTEON_COP2_SEL_AES_DEC1:\n+ crypto->aes_input[1] = q;\n+ octeon_aes_decrypt_common(crypto, false);\n+ break;\n+ case OCTEON_COP2_SEL_GFM_XORMUL1: {\n+ uint64_t in[2] = {\n+ crypto->gfm_result[0] ^ crypto->gfm_xor0,\n+ crypto->gfm_result[1] ^ q,\n+ };\n+\n+ /*\n+ * The reflected GFM selectors form a distinct 64-bit reflected\n+ * multiply path. When the block is programmed with only MUL0, an\n+ * 8-bit polynomial, and a zero high half, use the dedicated reflected\n+ * helper instead of the normal GHASH-style multiplier.\n+ */\n+ if (crypto->gfm_poly <= 0xff &&\n+ crypto->gfm_mul[1] == 0 &&\n+ in[0] == 0) {\n+ octeon_gfm_mul64_uia2(in, crypto->gfm_mul,\n+ crypto->gfm_poly, crypto->gfm_result);\n+ } else {\n+ octeon_gfm_mul(in, crypto->gfm_mul, crypto->gfm_poly,\n+ crypto->gfm_result);\n+ }\n+ /*\n+ * GFM_XOR0 is a write-only staging half consumed by the next XORMUL1\n+ * operation, so clear it once the combined multiply has been issued.\n+ */\n+ crypto->gfm_xor0 = 0;\n+ break;\n+ }\n+ case OCTEON_COP2_SEL_SNOW3G_START:\n+ octeon_snow3g_start(crypto, q);\n+ break;\n+ case OCTEON_COP2_SEL_SNOW3G_MORE:\n+ octeon_snow3g_more(crypto);\n+ break;\n+ default:\n+ break;\n+ }\n+}\ndiff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c\nindex 9ac20196de..2de750e314 100644\n--- a/target/mips/tcg/octeon_translate.c\n+++ b/target/mips/tcg/octeon_translate.c\n@@ -414,6 +414,11 @@ static bool trans_ZCB(DisasContext *ctx, arg_zcb *a)\n return true;\n }\n \n+static bool trans_ZCBT(DisasContext *ctx, arg_zcb *a)\n+{\n+ return trans_ZCB(ctx, a);\n+}\n+\n static void octeon_store_tc_field(ptrdiff_t offset, TCGv value)\n {\n tcg_gen_st_tl(value, tcg_env, offset);\n@@ -504,4 +509,5 @@ TRANS(MTP1, trans_mtp, offsetof(CPUMIPSState, active_tc.P1),\n TRANS(MTP2, trans_mtp, offsetof(CPUMIPSState, active_tc.P2),\n offsetof(CPUMIPSState, active_tc.P5));\n TRANS(VMULU, trans_vmul, gen_helper_octeon_vmulu);\n+TRANS(VMM0, trans_vmul, gen_helper_octeon_vmm0);\n TRANS(V3MULU, trans_vmul, gen_helper_octeon_v3mulu);\ndiff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c\nindex d2398b6426..3164166910 100644\n--- a/target/mips/tcg/op_helper.c\n+++ b/target/mips/tcg/op_helper.c\n@@ -181,6 +181,20 @@ target_ulong helper_octeon_vmulu(CPUMIPSState *env, target_ulong arg1,\n return res[0];\n }\n \n+target_ulong helper_octeon_vmm0(CPUMIPSState *env, target_ulong arg1,\n+ target_ulong arg2)\n+{\n+ uint64_t lo;\n+\n+ /*\n+ * VMM0 is the Montgomery-reduction companion to VMULU: it computes the\n+ * low limb of MPL0 * arg1 + arg2 and writes that result back to M0.\n+ */\n+ lo = env->active_tc.MPL0 * (uint64_t)arg1 + (uint64_t)arg2;\n+ env->active_tc.MPL0 = lo;\n+ return lo;\n+}\n+\n target_ulong helper_octeon_v3mulu(CPUMIPSState *env, target_ulong arg1,\n target_ulong arg2)\n {\ndiff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c\nindex 2e3fe1fa16..42445e5526 100644\n--- a/target/mips/tcg/translate.c\n+++ b/target/mips/tcg/translate.c\n@@ -9127,6 +9127,195 @@ static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)\n }\n }\n \n+static bool octeon_cop2_is_supported_dmfc2(uint16_t sel)\n+{\n+ switch (sel) {\n+ case OCTEON_COP2_SEL_3DES_KEY0:\n+ case OCTEON_COP2_SEL_3DES_KEY1:\n+ case OCTEON_COP2_SEL_3DES_KEY2:\n+ case OCTEON_COP2_SEL_3DES_IV:\n+ case OCTEON_COP2_SEL_3DES_RESULT:\n+ case OCTEON_COP2_SEL_3DES_RESULT_IN:\n+ case OCTEON_COP2_SEL_AES_RESULT0:\n+ case OCTEON_COP2_SEL_AES_RESULT1:\n+ case OCTEON_COP2_SEL_CRC_POLYNOMIAL:\n+ case OCTEON_COP2_SEL_AES_IV0:\n+ case OCTEON_COP2_SEL_AES_IV1:\n+ case OCTEON_COP2_SEL_CRC_IV:\n+ case OCTEON_COP2_SEL_CRC_LEN:\n+ case OCTEON_COP2_SEL_CRC_IV_REFLECT:\n+ case OCTEON_COP2_SEL_HSH_DATW0:\n+ case OCTEON_COP2_SEL_HSH_DATW1:\n+ case OCTEON_COP2_SEL_HSH_DATW2:\n+ case OCTEON_COP2_SEL_HSH_DATW3:\n+ case OCTEON_COP2_SEL_HSH_DATW4:\n+ case OCTEON_COP2_SEL_HSH_DATW5:\n+ case OCTEON_COP2_SEL_HSH_DATW6:\n+ case OCTEON_COP2_SEL_HSH_DATW7:\n+ case OCTEON_COP2_SEL_HSH_IV0:\n+ case OCTEON_COP2_SEL_HSH_IV1:\n+ case OCTEON_COP2_SEL_HSH_IV2:\n+ case OCTEON_COP2_SEL_HSH_IV3:\n+ case OCTEON_COP2_SEL_HSH_IVW0:\n+ case OCTEON_COP2_SEL_HSH_IVW1:\n+ case OCTEON_COP2_SEL_HSH_IVW2:\n+ case OCTEON_COP2_SEL_HSH_IVW3:\n+ case OCTEON_COP2_SEL_HSH_IVW4:\n+ case OCTEON_COP2_SEL_HSH_IVW5:\n+ case OCTEON_COP2_SEL_HSH_IVW6:\n+ case OCTEON_COP2_SEL_HSH_IVW7:\n+ case OCTEON_COP2_SEL_AES_DAT0:\n+ case OCTEON_COP2_SEL_GFM_MUL_REFLECT0:\n+ case OCTEON_COP2_SEL_GFM_MUL_REFLECT1:\n+ case OCTEON_COP2_SEL_GFM_RESINP_REFLECT0:\n+ case OCTEON_COP2_SEL_GFM_RESINP_REFLECT1:\n+ case OCTEON_COP2_SEL_GFM_MUL0:\n+ case OCTEON_COP2_SEL_GFM_MUL1:\n+ case OCTEON_COP2_SEL_GFM_RESINP0:\n+ case OCTEON_COP2_SEL_GFM_RESINP1:\n+ case OCTEON_COP2_SEL_GFM_POLY:\n+ return true;\n+ default:\n+ return false;\n+ }\n+}\n+\n+static bool octeon_cop2_is_supported_dmtc2(uint16_t sel)\n+{\n+ switch (sel) {\n+ case OCTEON_COP2_SEL_3DES_KEY0:\n+ case OCTEON_COP2_SEL_3DES_KEY1:\n+ case OCTEON_COP2_SEL_3DES_KEY2:\n+ case OCTEON_COP2_SEL_3DES_IV:\n+ case OCTEON_COP2_SEL_3DES_RESULT_IN:\n+ case OCTEON_COP2_SEL_3DES_ENC_CBC:\n+ case OCTEON_COP2_SEL_KAS_ENC_CBC:\n+ case OCTEON_COP2_SEL_3DES_ENC:\n+ case OCTEON_COP2_SEL_KAS_ENC:\n+ case OCTEON_COP2_SEL_3DES_DEC_CBC:\n+ case OCTEON_COP2_SEL_3DES_DEC:\n+ case OCTEON_COP2_SEL_AES_IV0:\n+ case OCTEON_COP2_SEL_AES_IV1:\n+ case OCTEON_COP2_SEL_AES_KEY0:\n+ case OCTEON_COP2_SEL_AES_KEY1:\n+ case OCTEON_COP2_SEL_AES_KEY2:\n+ case OCTEON_COP2_SEL_AES_KEY3:\n+ case OCTEON_COP2_SEL_AES_ENC_CBC0:\n+ case OCTEON_COP2_SEL_AES_ENC0:\n+ case OCTEON_COP2_SEL_AES_DEC_CBC0:\n+ case OCTEON_COP2_SEL_AES_DEC0:\n+ case OCTEON_COP2_SEL_AES_KEYLENGTH:\n+ case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL:\n+ case OCTEON_COP2_SEL_CRC_IV:\n+ case OCTEON_COP2_SEL_CRC_WRITE_LEN:\n+ case OCTEON_COP2_SEL_CRC_WRITE_IV_REFLECT:\n+ case OCTEON_COP2_SEL_CRC_WRITE_BYTE:\n+ case OCTEON_COP2_SEL_CRC_WRITE_HALF:\n+ case OCTEON_COP2_SEL_CRC_WRITE_WORD:\n+ case OCTEON_COP2_SEL_CRC_WRITE_DWORD:\n+ case OCTEON_COP2_SEL_CRC_WRITE_VAR:\n+ case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL_REFLECT:\n+ case OCTEON_COP2_SEL_CRC_WRITE_BYTE_REFLECT:\n+ case OCTEON_COP2_SEL_CRC_WRITE_HALF_REFLECT:\n+ case OCTEON_COP2_SEL_CRC_WRITE_WORD_REFLECT:\n+ case OCTEON_COP2_SEL_CRC_WRITE_DWORD_REFLECT:\n+ case OCTEON_COP2_SEL_CRC_WRITE_VAR_REFLECT:\n+ case OCTEON_COP2_SEL_HSH_DAT0:\n+ case OCTEON_COP2_SEL_HSH_DAT1:\n+ case OCTEON_COP2_SEL_HSH_DAT2:\n+ case OCTEON_COP2_SEL_HSH_DAT3:\n+ case OCTEON_COP2_SEL_HSH_DAT4:\n+ case OCTEON_COP2_SEL_HSH_DAT5:\n+ case OCTEON_COP2_SEL_HSH_DAT6:\n+ case OCTEON_COP2_SEL_HSH_IV0:\n+ case OCTEON_COP2_SEL_HSH_IV1:\n+ case OCTEON_COP2_SEL_HSH_IV2:\n+ case OCTEON_COP2_SEL_HSH_IV3:\n+ case OCTEON_COP2_SEL_HSH_DATW0:\n+ case OCTEON_COP2_SEL_HSH_DATW1:\n+ case OCTEON_COP2_SEL_HSH_DATW2:\n+ case OCTEON_COP2_SEL_HSH_DATW3:\n+ case OCTEON_COP2_SEL_HSH_DATW4:\n+ case OCTEON_COP2_SEL_HSH_DATW5:\n+ case OCTEON_COP2_SEL_HSH_DATW6:\n+ case OCTEON_COP2_SEL_HSH_DATW7:\n+ case OCTEON_COP2_SEL_HSH_DATW8:\n+ case OCTEON_COP2_SEL_HSH_DATW9:\n+ case OCTEON_COP2_SEL_HSH_DATW10:\n+ case OCTEON_COP2_SEL_HSH_DATW11:\n+ case OCTEON_COP2_SEL_HSH_DATW12:\n+ case OCTEON_COP2_SEL_HSH_DATW13:\n+ case OCTEON_COP2_SEL_HSH_DATW14:\n+ case OCTEON_COP2_SEL_HSH_DATW15:\n+ case OCTEON_COP2_SEL_HSH_IVW0:\n+ case OCTEON_COP2_SEL_HSH_IVW1:\n+ case OCTEON_COP2_SEL_HSH_IVW2:\n+ case OCTEON_COP2_SEL_HSH_IVW3:\n+ case OCTEON_COP2_SEL_HSH_IVW4:\n+ case OCTEON_COP2_SEL_HSH_IVW5:\n+ case OCTEON_COP2_SEL_HSH_IVW6:\n+ case OCTEON_COP2_SEL_HSH_IVW7:\n+ case OCTEON_COP2_SEL_GFM_MUL_REFLECT0:\n+ case OCTEON_COP2_SEL_GFM_MUL_REFLECT1:\n+ case OCTEON_COP2_SEL_GFM_XOR0_REFLECT:\n+ case OCTEON_COP2_SEL_GFM_MUL0:\n+ case OCTEON_COP2_SEL_GFM_MUL1:\n+ case OCTEON_COP2_SEL_GFM_RESINP0:\n+ case OCTEON_COP2_SEL_GFM_RESINP1:\n+ case OCTEON_COP2_SEL_GFM_XOR0:\n+ case OCTEON_COP2_SEL_GFM_POLY:\n+ case OCTEON_COP2_SEL_HSH_STARTSHA1_COMPAT:\n+ case OCTEON_COP2_SEL_HSH_STARTMD5:\n+ case OCTEON_COP2_SEL_SNOW3G_START:\n+ case OCTEON_COP2_SEL_SNOW3G_MORE:\n+ case OCTEON_COP2_SEL_HSH_STARTSHA256:\n+ case OCTEON_COP2_SEL_HSH_STARTSHA1:\n+ case OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT:\n+ case OCTEON_COP2_SEL_HSH_STARTSHA512:\n+ case OCTEON_COP2_SEL_GFM_XORMUL1:\n+ case OCTEON_COP2_SEL_AES_ENC_CBC1:\n+ case OCTEON_COP2_SEL_AES_ENC1:\n+ case OCTEON_COP2_SEL_AES_DEC_CBC1:\n+ case OCTEON_COP2_SEL_AES_DEC1:\n+ return true;\n+ default:\n+ return false;\n+ }\n+}\n+\n+static bool gen_octeon_cop2(DisasContext *ctx)\n+{\n+ enum {\n+ OCTEON_CP2_RS_DMFC2 = 0x01,\n+ OCTEON_CP2_RS_DMTC2 = 0x05,\n+ };\n+ int rs = extract32(ctx->opcode, 21, 5);\n+ int rt = extract32(ctx->opcode, 16, 5);\n+ uint16_t sel = ctx->opcode;\n+ TCGv t0;\n+\n+ switch (rs) {\n+ case OCTEON_CP2_RS_DMFC2:\n+ if (!octeon_cop2_is_supported_dmfc2(sel)) {\n+ return false;\n+ }\n+ t0 = tcg_temp_new();\n+ gen_helper_octeon_cop2_dmfc2(t0, tcg_env, tcg_constant_i32(sel));\n+ gen_store_gpr(t0, rt);\n+ return true;\n+ case OCTEON_CP2_RS_DMTC2:\n+ if (!octeon_cop2_is_supported_dmtc2(sel)) {\n+ return false;\n+ }\n+ t0 = tcg_temp_new();\n+ gen_load_gpr(t0, rt);\n+ gen_helper_octeon_cop2_dmtc2(tcg_env, t0, tcg_constant_i32(sel));\n+ return true;\n+ default:\n+ return false;\n+ }\n+}\n+\n static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)\n {\n TCGLabel *l1;\n@@ -14860,6 +15049,13 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)\n }\n break;\n case OPC_CP2:\n+ if (ctx->insn_flags & INSN_OCTEON) {\n+ if (gen_octeon_cop2(ctx)) {\n+ break;\n+ }\n+ generate_exception_err(ctx, EXCP_CpU, 2);\n+ break;\n+ }\n check_insn(ctx, ASE_LMMI);\n /* Note that these instructions use different fields. */\n gen_loongson_multimedia(ctx, sa, rd, rt);\n", "prefixes": [ "4/9" ] }