{"id":2225873,"url":"http://patchwork.ozlabs.org/api/patches/2225873/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260421-mips-octeon-missing-insns-v2-v2-7-a0791df188c9@gmail.com/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/projects/14/?format=json","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":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260421-mips-octeon-missing-insns-v2-v2-7-a0791df188c9@gmail.com>","list_archive_url":null,"date":"2026-04-21T17:27:34","name":"[v2,07/13] target/mips: add Octeon COP2 crypto core support","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"ef6ff4426dace0abb54c9cdae3642c04dccbbd3a","submitter":{"id":66301,"url":"http://patchwork.ozlabs.org/api/people/66301/?format=json","name":"James Hilliard","email":"james.hilliard1@gmail.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260421-mips-octeon-missing-insns-v2-v2-7-a0791df188c9@gmail.com/mbox/","series":[{"id":500858,"url":"http://patchwork.ozlabs.org/api/series/500858/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=500858","date":"2026-04-21T17:27:27","name":"target/mips: add missing Octeon user-mode support","version":2,"mbox":"http://patchwork.ozlabs.org/series/500858/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2225873/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2225873/checks/","tags":{},"related":[],"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=k5VeV0SL;\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=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.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 4g0Tr60ZXcz1yHB\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 03:29:42 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wFEtQ-00041M-H2; Tue, 21 Apr 2026 13:28:12 -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 1wFEtG-0003pg-7X\n for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:28:03 -0400","from mail-oa1-x29.google.com ([2001:4860:4864:20::29])\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 1wFEt6-0006hw-H5\n for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:28:00 -0400","by mail-oa1-x29.google.com with SMTP id\n 586e51a60fabf-42fbf95cca8so4344fac.0\n for <qemu-devel@nongnu.org>; Tue, 21 Apr 2026 10:27:47 -0700 (PDT)","from mac.localdomain (97-118-149-104.hlrn.qwest.net.\n [97.118.149.104]) by smtp.gmail.com with ESMTPSA id\n 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.44\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 21 Apr 2026 10:27:45 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1776792466; x=1777397266; darn=nongnu.org;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:from:to:cc:subject:date:message-id\n :reply-to; bh=J90ro9vd/+OCgHNOe/fQYAmiD6Gu+yQKI1y3Fv35DmQ=;\n b=k5VeV0SLig97OnvLj/YWaZl6gsdDVRb6eTi1oyL48YKnsTOIruUCuPeBnNStcqWzLp\n UxGWgKCVOx9nAzIaQqiZ5YbL8Kg1b5DFz8Lmlm3X83aHZ3yGS/fkVzocGvfALNDeBlkc\n 07/vAoqbQjgs8UH6Njn1vu3nTuZTxzPlse4eqw8dZ/zDIrOg2dPIlFLvYbkTGABew3gu\n ifQ1aIyTRh7P81H2svbWbxAbUS0YMZw4RiMfRZ8wjYeZWYvtykrpSm/OKtKAUnLqrwST\n sA6UbOPRQfEFXzKfxsWWZtjwBfz46wkLUwhB6776+MbPEyqaBenRBOHNPFA5tvvDQqHn\n PMRw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776792466; x=1777397266;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=J90ro9vd/+OCgHNOe/fQYAmiD6Gu+yQKI1y3Fv35DmQ=;\n b=JOWyvjQHPqbz0XGPF2SY6ahqhszhhQDvXQrac3NecrPDEYz2ghER1uXUfJoSN/TbRz\n H2KXcUDdfSNeEbGW0sbSm8/NSspp67z/2DSuo7H3MqkUzu9PEyuj7zu8Us8u6kX0AfzO\n as9K5RFhYcUR0rLeKTDeMhVDp2d2/O+mljtrWtGsVtaK6a+XO3ydVeKjRhsiJBI/m47s\n c0n49kfyHEiPJyZSYxGb6t5iSSAqKcgHaSDpij4SWKR2g3J7mJYroX2d0ESUpP10Yl5Y\n x6CDLWcqPlHS0QIM2vTnQmfY0staAsW6RbEMPuzTdbbDdbWxaQbOXWOneK6Q/3BxVbtv\n B47w==","X-Gm-Message-State":"AOJu0YzUjPRA83n2gcB8/GpqP4kk6d7saGDLObR+RaHdxlW4EbyFanvl\n dAEl84L2tYW4CxB0cfAOz0xJD33Nr80OgD6dMHN4lJjaV5aRUMy+3eTD","X-Gm-Gg":"AeBDieuA2sQV4//PoqToRX7lf+s4+HxYsET1JHqifK2gOR8Dx6Pr8kMnG7mehT6FKPT\n BTW/ZbaswcT0dC0d9oQqB97BqjViPz23uf+S0VLCoRaweMkZDnK5FoWvS25Rz1HdMPcwknzHFul\n l8xLluRqVCCHFC2UPS+OKJBqLQk1MVCDWXiXz4OV+wFj03notzjlEsCGlsK2WOD4UAuSKX8t+g0\n MuulZgkj4LI8uJN1hrUjvmvUSyr3vj0+dBdmkEHqq3DXo7bPsA0ED7Gz9g3+JFaDNDDm+kKT3DD\n i0Q8vp/KQxe1JKvLC3HkrCOgS5T4yHGAEWH0Cx52X5lChIOX99c/HHHOz/BsY1vJrWmB/sb/CI0\n t+/wTuOVKsD967uC7NoiVjmv6JJMhtLZEisWVirawrmTnXZ8/APlHaR4yUbaN3hVwDWRcAD/5cW\n JIW5ZQsX/8xshbe0OGv3wL/8tMlzJv64zbLuznAcRolMMFVnbygkZZfLtHXz4Nouo6oejiuAuq0\n c8ccZ+hfpXKO1uOXjXToGfbuVuP3LZWcw/Uo7GytCMLp3JejeIGINvice/F+Rqd8DVfsqlSqmfd\n N+I+8sG+kpwV+KM9","X-Received":"by 2002:a05:6820:1620:b0:67e:1a79:1f30 with SMTP id\n 006d021491bc7-69462e2e231mr9107988eaf.1.1776792465731;\n Tue, 21 Apr 2026 10:27:45 -0700 (PDT)","From":"James Hilliard <james.hilliard1@gmail.com>","Date":"Tue, 21 Apr 2026 11:27:34 -0600","Subject":"[PATCH v2 07/13] target/mips: add Octeon COP2 crypto core support","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"8bit","Message-Id":"\n <20260421-mips-octeon-missing-insns-v2-v2-7-a0791df188c9@gmail.com>","References":"\n <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com>","In-Reply-To":"\n <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com>","To":"qemu-devel@nongnu.org","Cc":"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>,\n  Jiaxun Yang <jiaxun.yang@flygoat.com>,\n  Aleksandar Rikalo <arikalo@gmail.com>, Huacai Chen <chenhuacai@kernel.org>,\n  James Hilliard <james.hilliard1@gmail.com>","X-Mailer":"b4 0.15.2","Received-SPF":"pass client-ip=2001:4860:4864:20::29;\n envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x29.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 the\ncommon COP2 state, selector decode, and helper plumbing for the base\nengine set.\n\nThis covers the hash, AES, CRC, GFM, 3DES, KASUMI, and SNOW3G engines\nand moves the implementation into octeon_crypto.c to keep the MIPS\nhelper layer manageable.\n\nModel the AES result/input selector bank as writable as well as\nreadable. Octeon COP2 engines use these slots as result-input staging\nregisters, so the shared bank belongs with the base selector support.\n\nExtend the TCG smoke test with AES key-register readback checks for the\nselector window introduced here.\n\nSigned-off-by: James Hilliard <james.hilliard1@gmail.com>\n---\nChanges v1 -> v2:\n  - Fold the AES COP2 selector readback smoke coverage into this patch.\n  - Move Octeon COP2 decode plumbing into octeon_translate.c.\n    (suggested by Philippe Mathieu-Daudé)\n  - Use uint64_t/i64 helper types for Octeon COP2 state transfers.\n    (suggested by Philippe Mathieu-Daudé)\n---\n target/mips/cpu.h                             |  165 +++\n target/mips/helper.h                          |    2 +\n target/mips/system/machine.c                  |   37 +\n target/mips/tcg/meson.build                   |    1 +\n target/mips/tcg/octeon_crypto.c               | 1654 +++++++++++++++++++++++++\n target/mips/tcg/octeon_translate.c            |  210 ++++\n target/mips/tcg/translate.c                   |    9 +\n target/mips/tcg/translate.h                   |    1 +\n tests/tcg/mips/user/isa/octeon/octeon-insns.c |   71 ++\n 9 files changed, 2150 insertions(+)","diff":"diff --git a/target/mips/cpu.h b/target/mips/cpu.h\nindex 540edf2906..9e398e1ce5 100644\n--- a/target/mips/cpu.h\n+++ b/target/mips/cpu.h\n@@ -529,6 +529,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+    uint32_t 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@@ -550,6 +713,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 756ef92bfd..899120d0ca 100644\n--- a/target/mips/helper.h\n+++ b/target/mips/helper.h\n@@ -27,6 +27,8 @@ DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32)\n DEF_HELPER_3(octeon_vmulu, i64, env, i64, i64)\n DEF_HELPER_3(octeon_vmm0, i64, env, i64, i64)\n DEF_HELPER_3(octeon_v3mulu, i64, env, i64, i64)\n+DEF_HELPER_2(octeon_cop2_dmfc2, i64, env, i32)\n+DEF_HELPER_3(octeon_cop2_dmtc2, void, env, i64, i32)\n \n /* microMIPS functions */\n DEF_HELPER_4(lwm, void, env, tl, tl, i32)\ndiff --git a/target/mips/system/machine.c b/target/mips/system/machine.c\nindex c29b7c56fa..d5452a3157 100644\n--- a/target/mips/system/machine.c\n+++ b/target/mips/system/machine.c\n@@ -269,6 +269,42 @@ static const VMStateDescription mips_vmstate_octeon_multiplier = {\n     }\n };\n \n+static const VMStateDescription mips_vmstate_octeon_crypto = {\n+    .name = \"cpu/octeon_crypto\",\n+    .version_id = 1,\n+    .minimum_version_id = 1,\n+    .needed = mips_octeon_needed,\n+    .fields = (const VMStateField[]) {\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.des3_key, MIPSCPU, 3),\n+        VMSTATE_UINT64(env.octeon_crypto.des3_iv, MIPSCPU),\n+        VMSTATE_UINT64(env.octeon_crypto.des3_result, MIPSCPU),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.hash_state, MIPSCPU, 4),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.hash_block, MIPSCPU, 8),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.sha512_state, MIPSCPU, 8),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.sha512_block, MIPSCPU, 16),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_iv, MIPSCPU, 2),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_key, MIPSCPU, 4),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_result, MIPSCPU, 2),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_input, MIPSCPU, 2),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_mul, MIPSCPU, 2),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_result, MIPSCPU, 2),\n+        VMSTATE_UINT64(env.octeon_crypto.gfm_xor0, MIPSCPU),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_reflect_mul, MIPSCPU, 2),\n+        VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_reflect_result, MIPSCPU, 2),\n+        VMSTATE_UINT64(env.octeon_crypto.gfm_reflect_xor0, MIPSCPU),\n+        VMSTATE_UINT16(env.octeon_crypto.gfm_poly, MIPSCPU),\n+        VMSTATE_UINT8(env.octeon_crypto.aes_keylen, MIPSCPU),\n+        VMSTATE_UINT32(env.octeon_crypto.shared_mode, MIPSCPU),\n+        VMSTATE_UINT32(env.octeon_crypto.crc_poly, MIPSCPU),\n+        VMSTATE_UINT32(env.octeon_crypto.crc_iv, MIPSCPU),\n+        VMSTATE_UINT32(env.octeon_crypto.crc_len, MIPSCPU),\n+        VMSTATE_UINT32_ARRAY(env.octeon_crypto.snow3g_fsm, MIPSCPU, 3),\n+        VMSTATE_UINT32_ARRAY(env.octeon_crypto.snow3g_lfsr, MIPSCPU, 16),\n+        VMSTATE_UINT64(env.octeon_crypto.snow3g_result, MIPSCPU),\n+        VMSTATE_END_OF_LIST()\n+    }\n+};\n+\n const VMStateDescription vmstate_mips_cpu = {\n     .name = \"cpu\",\n     .version_id = 21,\n@@ -386,6 +422,7 @@ const VMStateDescription vmstate_mips_cpu = {\n     .subsections = (const VMStateDescription * const []) {\n         &mips_vmstate_timer,\n         &mips_vmstate_octeon_multiplier,\n+        &mips_vmstate_octeon_crypto,\n         NULL\n     }\n };\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_crypto.c b/target/mips/tcg/octeon_crypto.c\nnew file mode 100644\nindex 0000000000..43012ff027\n--- /dev/null\n+++ b/target/mips/tcg/octeon_crypto.c\n@@ -0,0 +1,1654 @@\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 \"crypto/aes.h\"\n+#include \"crypto/clmul.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_reduce64(Int128 product, uint8_t poly)\n+{\n+    uint64_t lo = int128_getlo(product);\n+    uint64_t hi = int128_gethi(product);\n+\n+    while (hi) {\n+        int bit = 63 - clz64(hi);\n+        uint64_t shifted_poly = (uint64_t)poly << bit;\n+\n+        hi ^= 1ULL << bit;\n+        lo ^= shifted_poly;\n+        if (bit > 56) {\n+            hi ^= (uint64_t)poly >> (64 - bit);\n+        }\n+    }\n+\n+    return lo;\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+    Int128 product = clmul_64(vx, vy);\n+    uint64_t res = octeon_gfm_reduce64(product, 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 void octeon_store_shared_hash_dat(MIPSOcteonCryptoState *crypto,\n+                                         uint32_t sel, uint64_t value)\n+{\n+    switch (sel) {\n+    case OCTEON_COP2_SEL_HSH_DATW0 ... OCTEON_COP2_SEL_HSH_DATW14:\n+        crypto->sha512_block[sel - OCTEON_COP2_SEL_HSH_DATW0] = value;\n+        break;\n+    case OCTEON_COP2_SEL_HSH_IVW0 ... OCTEON_COP2_SEL_HSH_IVW7:\n+        crypto->sha512_state[sel - OCTEON_COP2_SEL_HSH_IVW0] = value;\n+        break;\n+    default:\n+        g_assert_not_reached();\n+    }\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+uint64_t 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+    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+        return crypto->sha512_block[sel - OCTEON_COP2_SEL_HSH_DATW0];\n+    case OCTEON_COP2_SEL_HSH_DATW15:\n+        return crypto->sha512_block[15];\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, uint64_t 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_RESULT0:\n+    case OCTEON_COP2_SEL_AES_RESULT1:\n+        crypto->aes_input[sel - OCTEON_COP2_SEL_AES_RESULT0] = q;\n+        crypto->aes_result[sel - OCTEON_COP2_SEL_AES_RESULT0] = q;\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+        octeon_store_shared_hash_dat(crypto, sel, 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+        octeon_store_shared_hash_dat(crypto, sel, 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+         * A 64-bit reflected GFM operation uses this XORMUL1 path when the\n+         * block is programmed with only MUL0, an 8-bit polynomial, and a zero\n+         * high input half. Detect that shape and use the reflected helper\n+         * 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 6309cd5fff..ac5065398d 100644\n--- a/target/mips/tcg/octeon_translate.c\n+++ b/target/mips/tcg/octeon_translate.c\n@@ -21,6 +21,216 @@ static bool octeon_check_64(DisasContext *ctx)\n     return ctx->base.is_jmp == DISAS_NEXT;\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_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_KEYLENGTH:\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_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_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_RESULT0:\n+    case OCTEON_COP2_SEL_AES_RESULT1:\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+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_i64 t0;\n+\n+    switch (rs) {\n+    case OCTEON_CP2_RS_DMFC2:\n+        if (!octeon_check_64(ctx)) {\n+            return true;\n+        }\n+        if (!octeon_cop2_is_supported_dmfc2(sel)) {\n+            return false;\n+        }\n+        t0 = tcg_temp_new_i64();\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_check_64(ctx)) {\n+            return true;\n+        }\n+        if (!octeon_cop2_is_supported_dmtc2(sel)) {\n+            return false;\n+        }\n+        t0 = tcg_temp_new_i64();\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 bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)\n {\n     TCGv_i64 p;\ndiff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c\nindex 2e3fe1fa16..ca9cee7ed6 100644\n--- a/target/mips/tcg/translate.c\n+++ b/target/mips/tcg/translate.c\n@@ -14860,6 +14860,15 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)\n         }\n         break;\n     case OPC_CP2:\n+#if defined(TARGET_MIPS64)\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+#endif\n         check_insn(ctx, ASE_LMMI);\n         /* Note that these instructions use different fields.  */\n         gen_loongson_multimedia(ctx, sa, rd, rt);\ndiff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h\nindex 89dde1e712..feb3c47c44 100644\n--- a/target/mips/tcg/translate.h\n+++ b/target/mips/tcg/translate.h\n@@ -232,6 +232,7 @@ bool decode_ext_loongson(DisasContext *ctx, uint32_t insn);\n bool decode_ase_lcsr(DisasContext *ctx, uint32_t insn);\n bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);\n bool decode_ext_octeon(DisasContext *ctx, uint32_t insn);\n+bool gen_octeon_cop2(DisasContext *ctx);\n #endif\n bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);\n \ndiff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c\nindex e9db93d1b6..059527fe5d 100644\n--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c\n+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c\n@@ -129,6 +129,70 @@ static uint64_t octeon_vmm0(uint64_t mpl0, uint64_t p0,\n     return rd;\n }\n \n+static uint64_t octeon_cop2_key0_readback(uint64_t value)\n+{\n+    uint64_t rd;\n+\n+    asm volatile(\n+        \"move $8, %[value]\\n\\t\"\n+        \".word 0x48a80104\\n\\t\" /* dmtc2 $8, AES_KEY0 selector */\n+        \".word 0x482a0104\\n\\t\" /* dmfc2 $10, AES_KEY0 selector */\n+        \"move %[rd], $10\\n\\t\"\n+        : [rd] \"=r\" (rd)\n+        : [value] \"r\" (value)\n+        : \"$8\", \"$10\");\n+\n+    return rd;\n+}\n+\n+static uint64_t octeon_cop2_key2_readback(uint64_t value)\n+{\n+    uint64_t rd;\n+\n+    asm volatile(\n+        \"move $8, %[value]\\n\\t\"\n+        \".word 0x48a80106\\n\\t\" /* dmtc2 $8, AES_KEY2 selector */\n+        \".word 0x482a0106\\n\\t\" /* dmfc2 $10, AES_KEY2 selector */\n+        \"move %[rd], $10\\n\\t\"\n+        : [rd] \"=r\" (rd)\n+        : [value] \"r\" (value)\n+        : \"$8\", \"$10\");\n+\n+    return rd;\n+}\n+\n+static uint64_t octeon_cop2_key3_readback(uint64_t value)\n+{\n+    uint64_t rd;\n+\n+    asm volatile(\n+        \"move $8, %[value]\\n\\t\"\n+        \".word 0x48a80107\\n\\t\" /* dmtc2 $8, AES_KEY3 selector */\n+        \".word 0x482a0107\\n\\t\" /* dmfc2 $10, AES_KEY3 selector */\n+        \"move %[rd], $10\\n\\t\"\n+        : [rd] \"=r\" (rd)\n+        : [value] \"r\" (value)\n+        : \"$8\", \"$10\");\n+\n+    return rd;\n+}\n+\n+static uint64_t octeon_cop2_keylength_readback(uint64_t value)\n+{\n+    uint64_t rd;\n+\n+    asm volatile(\n+        \"move $8, %[value]\\n\\t\"\n+        \".word 0x48a80110\\n\\t\" /* dmtc2 $8, AES_KEYLENGTH selector */\n+        \".word 0x482a0110\\n\\t\" /* dmfc2 $10, AES_KEYLENGTH selector */\n+        \"move %[rd], $10\\n\\t\"\n+        : [rd] \"=r\" (rd)\n+        : [value] \"r\" (value)\n+        : \"$8\", \"$10\");\n+\n+    return rd;\n+}\n+\n int main(void)\n {\n     assert(octeon_baddu(0x123, 0x0f0) == 0x13);\n@@ -140,6 +204,13 @@ int main(void)\n     assert(octeon_sne(0xabc, 0xdef) == 1);\n     assert(octeon_vmulu(5, 7, 11) == 46);\n     assert(octeon_vmm0(5, 13, 7, 11) == 59);\n+    assert(octeon_cop2_key0_readback(0x1122334455667788ULL) ==\n+           0x1122334455667788ULL);\n+    assert(octeon_cop2_key2_readback(0x8877665544332211ULL) ==\n+           0x8877665544332211ULL);\n+    assert(octeon_cop2_key3_readback(0x0102030405060708ULL) ==\n+           0x0102030405060708ULL);\n+    assert(octeon_cop2_keylength_readback(0xa5) == 0xa5);\n \n     return 0;\n }\n","prefixes":["v2","07/13"]}