* [PULL 00/23] MIPS & SH4 patches for 2026-07-07
@ 2026-07-07 18:15 Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 01/23] target/mips: add Octeon COP2 crypto state Philippe Mathieu-Daudé
` (24 more replies)
0 siblings, 25 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
The following changes since commit 916ab315cc2b3a3825ebb399d83339660144d5bd:
Merge tag 'pull-nvme-20260707' of https://gitlab.com/birkelund/qemu into staging (2026-07-07 07:09:38 +0200)
are available in the Git repository at:
https://github.com/philmd/qemu.git tags/mips-20260707
for you to fetch changes up to f086625548aa2f839c119243121ef863ecb606a0:
qemu-options: Do not list -enable-kvm on MIPS binaries (2026-07-07 20:14:51 +0200)
----------------------------------------------------------------
MIPS and SuperH patches queue
- MIPS Octeon COP2 crypto opcodes
- Fix for SH4 FIPR/FTRV vector math opcodes
----------------------------------------------------------------
James Hilliard (21):
target/mips: add Octeon COP2 crypto state
target/mips: add Octeon COP2 crypto helper plumbing
target/mips: add Octeon CRC COP2 helpers
target/mips: add Octeon GFM COP2 helpers
target/mips: add Octeon SHA3 COP2 helpers
target/mips: add Octeon ZUC COP2 helpers
target/mips: add Octeon SNOW3G COP2 helpers
target/mips: add Octeon AES COP2 helpers
target/mips: add Octeon SMS4 COP2 helpers
target/mips: add Octeon 3DES and KASUMI COP2 helpers
target/mips: add Octeon Camellia COP2 helpers
target/mips: add Octeon HSH COP2 helpers
target/mips: add Octeon CHORD and LLM COP2 helpers
target/mips: decode Octeon COP2 register selectors
target/mips: decode Octeon CRC and GFM COP2 selectors
target/mips: decode Octeon HSH and SHA3 COP2 selectors
target/mips: decode Octeon ZUC and SNOW3G COP2 selectors
target/mips: decode Octeon block-cipher COP2 selectors
target/mips: decode Octeon CHORD and LLM COP2 selectors
target/mips: add Octeon CvmCount RDHWR support
tests/tcg/mips: cover Octeon QMAC instructions
Philippe Mathieu-Daudé (1):
qemu-options: Do not list -enable-kvm on MIPS binaries
Randy Schifflin (1):
target/sh4: fixup tcg for sh4 fipr/ftrv instructions
target/mips/cpu.h | 31 +
target/mips/helper.h | 61 +
target/mips/internal.h | 3 +
target/mips/tcg/octeon.decode | 213 ++
target/mips/cpu.c | 68 +
target/mips/system/machine.c | 94 +
target/mips/tcg/octeon_crypto.c | 2310 +++++++++++++++++
target/mips/tcg/octeon_translate.c | 396 +++
target/mips/tcg/op_helper.c | 19 +-
target/mips/tcg/translate.c | 19 +
target/sh4/op_helper.c | 2 +-
target/sh4/translate.c | 15 +-
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 216 ++
qemu-options.hx | 2 +-
target/mips/tcg/meson.build | 1 +
15 files changed, 3437 insertions(+), 13 deletions(-)
create mode 100644 target/mips/tcg/octeon_crypto.c
--
2.53.0
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PULL 01/23] target/mips: add Octeon COP2 crypto state
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 02/23] target/mips: add Octeon COP2 crypto helper plumbing Philippe Mathieu-Daudé
` (23 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add the common architectural state needed by Octeon's selector-driven
COP2 crypto interfaces. This includes storage for the base hash, AES,
CRC, GFM, 3DES, KASUMI, and overlapping HSH/SHA512/SHA3/SNOW3G/ZUC
selector windows.
Keep selector values and helper-local aliasing logic out of the CPU state
header so the state definition remains limited to architectural storage.
Helper code uses the same register banks instead of adding
non-architectural shadow state. Model the SHA3 view as a direct 25-lane
alias of the architectural HSH DAT/IV/SHA3_DAT24 storage.
Migrate the state in an Octeon-only subsection so non-Octeon CPU models
do not grow migration data.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-1-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/cpu.h | 26 ++++++++++++++++++++++++++
target/mips/system/machine.c | 27 +++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 392406aff8a..3df71adf9bd 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -537,6 +537,30 @@ struct TCState {
};
struct MIPSITUState;
+typedef struct MIPSOcteonCryptoState {
+ union {
+ struct {
+ uint64_t hsh_dat[16];
+ uint64_t hsh_iv[8];
+ uint64_t sha3_dat24;
+ };
+ uint64_t sha3_dat[25];
+ };
+ uint64_t des3_key[3];
+ uint64_t des3_iv;
+ uint64_t des3_result;
+ uint64_t aes_resinp[2];
+ uint64_t aes_iv[2];
+ uint64_t aes_key[4];
+ uint32_t crc_poly;
+ uint32_t crc_iv;
+ uint64_t gfm_mul[2];
+ uint64_t gfm_resinp[2];
+ uint16_t gfm_poly;
+ uint8_t aes_keylen;
+ uint8_t crc_len;
+} MIPSOcteonCryptoState;
+
typedef struct CPUArchState {
TCState active_tc;
CPUMIPSFPUContext active_fpu;
@@ -558,6 +582,8 @@ typedef struct CPUArchState {
#define MSAIR_ProcID 8
#define MSAIR_Rev 0
+ MIPSOcteonCryptoState octeon_crypto;
+
/*
* CP0 Register 0
*/
diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c
index f988b3695bc..77f576a25b1 100644
--- a/target/mips/system/machine.c
+++ b/target/mips/system/machine.c
@@ -279,6 +279,32 @@ static const VMStateDescription mips_vmstate_octeon_multiplier = {
}
};
+static const VMStateDescription mips_vmstate_octeon_crypto = {
+ .name = "cpu/octeon_crypto",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = mips_octeon_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.hsh_dat, MIPSCPU, 16),
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.hsh_iv, MIPSCPU, 8),
+ VMSTATE_UINT64(env.octeon_crypto.sha3_dat24, MIPSCPU),
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.des3_key, MIPSCPU, 3),
+ VMSTATE_UINT64(env.octeon_crypto.des3_iv, MIPSCPU),
+ VMSTATE_UINT64(env.octeon_crypto.des3_result, MIPSCPU),
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_resinp, MIPSCPU, 2),
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_iv, MIPSCPU, 2),
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_key, MIPSCPU, 4),
+ VMSTATE_UINT32(env.octeon_crypto.crc_poly, MIPSCPU),
+ VMSTATE_UINT32(env.octeon_crypto.crc_iv, MIPSCPU),
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_mul, MIPSCPU, 2),
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_resinp, MIPSCPU, 2),
+ VMSTATE_UINT16(env.octeon_crypto.gfm_poly, MIPSCPU),
+ VMSTATE_UINT8(env.octeon_crypto.aes_keylen, MIPSCPU),
+ VMSTATE_UINT8(env.octeon_crypto.crc_len, MIPSCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
const VMStateDescription vmstate_mips_cpu = {
.name = "cpu",
.version_id = 21,
@@ -396,6 +422,7 @@ const VMStateDescription vmstate_mips_cpu = {
.subsections = (const VMStateDescription * const []) {
&mips_vmstate_timer,
&mips_vmstate_octeon_multiplier,
+ &mips_vmstate_octeon_crypto,
NULL
}
};
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 02/23] target/mips: add Octeon COP2 crypto helper plumbing
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 01/23] target/mips: add Octeon COP2 crypto state Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 03/23] target/mips: add Octeon CRC COP2 helpers Philippe Mathieu-Daudé
` (22 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add the Octeon COP2 crypto helper source file and build it with the MIPS
TCG target. This provides the common compilation unit for the COP2 engine
helpers.
The instruction dispatch itself remains fully decoded by decodetree, and
operation selectors call per-operation helpers rather than a common
selector-dispatch helper.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-2-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/tcg/octeon_crypto.c | 16 ++++++++++++++++
target/mips/tcg/meson.build | 1 +
2 files changed, 17 insertions(+)
create mode 100644 target/mips/tcg/octeon_crypto.c
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
new file mode 100644
index 00000000000..df5b0449aeb
--- /dev/null
+++ b/target/mips/tcg/octeon_crypto.c
@@ -0,0 +1,16 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * MIPS Octeon crypto emulation helpers.
+ *
+ * Copyright (c) 2026 James Hilliard
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "internal.h"
+#include "exec/helper-proto.h"
+#include "crypto/aes.h"
+#include "crypto/sm4.h"
+#include "qemu/bitops.h"
+#include "qemu/host-utils.h"
diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build
index fff9cd6c7f5..4ee359874ac 100644
--- a/target/mips/tcg/meson.build
+++ b/target/mips/tcg/meson.build
@@ -18,6 +18,7 @@ mips_ss.add(files(
'lmmi_helper.c',
'msa_helper.c',
'msa_translate.c',
+ 'octeon_crypto.c',
'op_helper.c',
'rel6_translate.c',
'translate.c',
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 03/23] target/mips: add Octeon CRC COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 01/23] target/mips: add Octeon COP2 crypto state Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 02/23] target/mips: add Octeon COP2 crypto helper plumbing Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 04/23] target/mips: add Octeon GFM " Philippe Mathieu-Daudé
` (21 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add helper support for the Octeon COP2 CRC register interface. This
covers normal and reflected CRC state handling, byte/halfword/word/
doubleword/variable-width update selectors, and the reflected IV readback
operation.
Register moves that can be represented as direct TCG loads/stores do not
need helpers. Add only the side-effecting CRC helper implementation here.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-3-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 14 ++++
target/mips/tcg/octeon_crypto.c | 131 ++++++++++++++++++++++++++++++++
2 files changed, 145 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index e2b83a1d19d..e802f50fd6e 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -25,6 +25,20 @@ DEF_HELPER_3(crc32, tl, tl, tl, i32)
DEF_HELPER_3(crc32c, tl, tl, tl, i32)
DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32)
+/* Octeon COP2 selector operation helpers. */
+DEF_HELPER_1(octeon_cp2_mf_crc_iv_reflect, i64, env)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_iv_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_byte, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_half, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_word, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_byte_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_half_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_word_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_dword, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_var, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_dword_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_var_reflect, void, env, i64)
+
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
DEF_HELPER_4(swm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index df5b0449aeb..c589077ea7c 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -14,3 +14,134 @@
#include "crypto/sm4.h"
#include "qemu/bitops.h"
#include "qemu/host-utils.h"
+
+static uint32_t octeon_crc_reflect32_by_byte(uint32_t v)
+{
+ return bswap32(revbit32(v));
+}
+
+static uint32_t octeon_crc_state_reflect(const MIPSOcteonCryptoState *crypto)
+{
+ return octeon_crc_reflect32_by_byte(crypto->crc_iv);
+}
+
+static void octeon_crc_set_state_reflect(MIPSOcteonCryptoState *crypto,
+ uint32_t state)
+{
+ crypto->crc_iv = octeon_crc_reflect32_by_byte(state);
+}
+
+static void octeon_crc_update_normal(MIPSOcteonCryptoState *crypto,
+ uint64_t value, unsigned int bytes)
+{
+ uint32_t crc = crypto->crc_iv;
+ uint32_t poly = crypto->crc_poly;
+
+ for (unsigned int i = 0; i < bytes; i++) {
+ uint8_t byte = value >> ((bytes - 1 - i) * 8);
+
+ crc ^= (uint32_t)byte << 24;
+ for (int bit = 0; bit < 8; bit++) {
+ if (crc & 0x80000000U) {
+ crc = (crc << 1) ^ poly;
+ } else {
+ crc <<= 1;
+ }
+ }
+ }
+
+ crypto->crc_iv = crc;
+}
+
+static void octeon_crc_update_reflect(MIPSOcteonCryptoState *crypto,
+ uint64_t value, unsigned int bytes)
+{
+ uint32_t crc = octeon_crc_state_reflect(crypto);
+ uint32_t poly = bswap32(crypto->crc_poly);
+
+ for (unsigned int i = 0; i < bytes; i++) {
+ uint8_t byte = value >> ((bytes - 1 - i) * 8);
+
+ crc ^= byte;
+ for (int bit = 0; bit < 8; bit++) {
+ if (crc & 1U) {
+ crc = (crc >> 1) ^ poly;
+ } else {
+ crc >>= 1;
+ }
+ }
+ }
+
+ octeon_crc_set_state_reflect(crypto, crc);
+}
+
+uint64_t helper_octeon_cp2_mf_crc_iv_reflect(CPUMIPSState *env)
+{
+ return octeon_crc_reflect32_by_byte(env->octeon_crypto.crc_iv);
+}
+
+void helper_octeon_cp2_mt_crc_write_iv_reflect(CPUMIPSState *env,
+ uint64_t value)
+{
+ env->octeon_crypto.crc_iv =
+ octeon_crc_reflect32_by_byte((uint32_t)value);
+}
+
+void helper_octeon_cp2_mt_crc_write_byte(CPUMIPSState *env, uint64_t value)
+{
+ octeon_crc_update_normal(&env->octeon_crypto, value, 1);
+}
+
+void helper_octeon_cp2_mt_crc_write_half(CPUMIPSState *env, uint64_t value)
+{
+ octeon_crc_update_normal(&env->octeon_crypto, value, 2);
+}
+
+void helper_octeon_cp2_mt_crc_write_word(CPUMIPSState *env, uint64_t value)
+{
+ octeon_crc_update_normal(&env->octeon_crypto, value, 4);
+}
+
+void helper_octeon_cp2_mt_crc_write_dword(CPUMIPSState *env, uint64_t value)
+{
+ octeon_crc_update_normal(&env->octeon_crypto, value, 8);
+}
+
+void helper_octeon_cp2_mt_crc_write_var(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ octeon_crc_update_normal(crypto, value, MIN(8U, crypto->crc_len & 0xf));
+}
+
+void helper_octeon_cp2_mt_crc_write_byte_reflect(CPUMIPSState *env,
+ uint64_t value)
+{
+ octeon_crc_update_reflect(&env->octeon_crypto, value, 1);
+}
+
+void helper_octeon_cp2_mt_crc_write_half_reflect(CPUMIPSState *env,
+ uint64_t value)
+{
+ octeon_crc_update_reflect(&env->octeon_crypto, value, 2);
+}
+
+void helper_octeon_cp2_mt_crc_write_word_reflect(CPUMIPSState *env,
+ uint64_t value)
+{
+ octeon_crc_update_reflect(&env->octeon_crypto, value, 4);
+}
+
+void helper_octeon_cp2_mt_crc_write_dword_reflect(CPUMIPSState *env,
+ uint64_t value)
+{
+ octeon_crc_update_reflect(&env->octeon_crypto, value, 8);
+}
+
+void helper_octeon_cp2_mt_crc_write_var_reflect(CPUMIPSState *env,
+ uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ octeon_crc_update_reflect(crypto, value, MIN(8U, crypto->crc_len & 0xf));
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 04/23] target/mips: add Octeon GFM COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2026-07-07 18:15 ` [PULL 03/23] target/mips: add Octeon CRC COP2 helpers Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 05/23] target/mips: add Octeon SHA3 " Philippe Mathieu-Daudé
` (20 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add helper support for the Octeon GFM carryless multiply selectors. This
models the normal and reflected multiplication paths, including the
XOR-and-multiply forms that update the result/input state used by Octeon
crypto code.
Reflected selectors operate on the architectural GFM register bank using
bit-reflected register transfers rather than a separate shadow state.
Keep the 64-bit UIA2 reduction path used by SNOW3G F9 and share that
shortcut between the normal and reflected XORMUL1 paths.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-4-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 9 ++
target/mips/tcg/octeon_crypto.c | 142 ++++++++++++++++++++++++++++++++
2 files changed, 151 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index e802f50fd6e..20ffbfb7096 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -27,6 +27,10 @@ DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32)
/* Octeon COP2 selector operation helpers. */
DEF_HELPER_1(octeon_cp2_mf_crc_iv_reflect, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_gfm_mul_reflect0, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_gfm_mul_reflect1, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_gfm_resinp_reflect0, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_gfm_resinp_reflect1, i64, env)
DEF_HELPER_2(octeon_cp2_mt_crc_write_iv_reflect, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_crc_write_byte, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_crc_write_half, void, env, i64)
@@ -38,6 +42,11 @@ DEF_HELPER_2(octeon_cp2_mt_crc_write_dword, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_crc_write_var, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_crc_write_dword_reflect, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_crc_write_var_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_gfm_mul_reflect0, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_gfm_mul_reflect1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_gfm_xor0_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index c589077ea7c..b417dcf53b6 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -11,6 +11,7 @@
#include "internal.h"
#include "exec/helper-proto.h"
#include "crypto/aes.h"
+#include "crypto/clmul.h"
#include "crypto/sm4.h"
#include "qemu/bitops.h"
#include "qemu/host-utils.h"
@@ -75,11 +76,152 @@ static void octeon_crc_update_reflect(MIPSOcteonCryptoState *crypto,
octeon_crc_set_state_reflect(crypto, crc);
}
+static void octeon_gfm_mul(const uint64_t x[2], const uint64_t y[2],
+ uint16_t poly, uint64_t out[2])
+{
+ uint64_t zh = 0, zl = 0;
+ uint64_t vh = y[0], vl = y[1];
+ uint64_t rh = (uint64_t)poly << 48;
+ int i;
+
+ /*
+ * Keep the reflected-shift formulation used by Octeon software: the
+ * selector polynomial is already in reflected bit order, and the software
+ * view folds its 16 reduction bits from the top of the high word.
+ */
+ for (i = 0; i < 128; i++) {
+ bool bit;
+ bool lsb;
+
+ if (i < 64) {
+ bit = (x[0] >> (63 - i)) & 1;
+ } else {
+ bit = (x[1] >> (127 - i)) & 1;
+ }
+ if (bit) {
+ zh ^= vh;
+ zl ^= vl;
+ }
+
+ lsb = vl & 1;
+ vl = (vh << 63) | (vl >> 1);
+ vh >>= 1;
+ if (lsb) {
+ vh ^= rh;
+ }
+ }
+
+ out[0] = zh;
+ out[1] = zl;
+}
+
+static uint64_t octeon_gfm_reduce64(Int128 product, uint8_t poly)
+{
+ uint64_t lo = int128_getlo(product);
+ uint64_t hi = int128_gethi(product);
+
+ while (hi) {
+ int bit = 63 - clz64(hi);
+
+ hi ^= 1ULL << bit;
+ lo ^= (uint64_t)poly << bit;
+ if (bit > 56) {
+ hi ^= (uint64_t)poly >> (64 - bit);
+ }
+ }
+
+ return lo;
+}
+
+static void octeon_gfm_mul64_uia2(const uint64_t x[2], const uint64_t y[2],
+ uint8_t poly, uint64_t out[2])
+{
+ /*
+ * SNOW3G UIA2 uses the GFM datapath as a reflected 64-bit multiply in
+ * the low half of the 128-bit register pair. When RESINP[0], MUL[1],
+ * and the high polynomial byte are all zero, octeon_gfm_mul() observes
+ * only x[1], y[0], and the low 8-bit polynomial. Reflect those operands
+ * into normal carryless-multiply order and reflect the reduced result
+ * back into RESINP[1].
+ */
+ uint64_t vx = revbit64(x[1]);
+ uint64_t vy = revbit64(y[0]);
+ Int128 product = clmul_64(vx, vy);
+ uint64_t res = octeon_gfm_reduce64(product, revbit32(poly) >> 24);
+
+ out[0] = 0;
+ out[1] = revbit64(res);
+}
+
uint64_t helper_octeon_cp2_mf_crc_iv_reflect(CPUMIPSState *env)
{
return octeon_crc_reflect32_by_byte(env->octeon_crypto.crc_iv);
}
+uint64_t helper_octeon_cp2_mf_gfm_mul_reflect0(CPUMIPSState *env)
+{
+ return revbit64(env->octeon_crypto.gfm_mul[0]);
+}
+
+uint64_t helper_octeon_cp2_mf_gfm_mul_reflect1(CPUMIPSState *env)
+{
+ return revbit64(env->octeon_crypto.gfm_mul[1]);
+}
+
+uint64_t helper_octeon_cp2_mf_gfm_resinp_reflect0(CPUMIPSState *env)
+{
+ return revbit64(env->octeon_crypto.gfm_resinp[0]);
+}
+
+uint64_t helper_octeon_cp2_mf_gfm_resinp_reflect1(CPUMIPSState *env)
+{
+ return revbit64(env->octeon_crypto.gfm_resinp[1]);
+}
+
+void helper_octeon_cp2_mt_gfm_mul_reflect0(CPUMIPSState *env, uint64_t value)
+{
+ env->octeon_crypto.gfm_mul[0] = revbit64(value);
+}
+
+void helper_octeon_cp2_mt_gfm_mul_reflect1(CPUMIPSState *env, uint64_t value)
+{
+ env->octeon_crypto.gfm_mul[1] = revbit64(value);
+}
+
+void helper_octeon_cp2_mt_gfm_xor0_reflect(CPUMIPSState *env, uint64_t value)
+{
+ env->octeon_crypto.gfm_resinp[0] ^= revbit64(value);
+}
+
+static void octeon_gfm_xormul1_common(MIPSOcteonCryptoState *crypto,
+ uint64_t value)
+{
+ crypto->gfm_resinp[1] ^= value;
+ if (crypto->gfm_poly <= 0xff && crypto->gfm_mul[1] == 0 &&
+ crypto->gfm_resinp[0] == 0) {
+ octeon_gfm_mul64_uia2(crypto->gfm_resinp, crypto->gfm_mul,
+ crypto->gfm_poly, crypto->gfm_resinp);
+ } else {
+ octeon_gfm_mul(crypto->gfm_resinp, crypto->gfm_mul, crypto->gfm_poly,
+ crypto->gfm_resinp);
+ }
+}
+
+void helper_octeon_cp2_mt_gfm_xormul1_reflect(CPUMIPSState *env,
+ uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ octeon_gfm_xormul1_common(crypto, revbit64(value));
+}
+
+void helper_octeon_cp2_mt_gfm_xormul1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ octeon_gfm_xormul1_common(crypto, value);
+}
+
void helper_octeon_cp2_mt_crc_write_iv_reflect(CPUMIPSState *env,
uint64_t value)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 05/23] target/mips: add Octeon SHA3 COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2026-07-07 18:15 ` [PULL 04/23] target/mips: add Octeon GFM " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 06/23] target/mips: add Octeon ZUC " Philippe Mathieu-Daudé
` (19 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add the Octeon SHA3 helper operations for the architectural 25-lane
Keccak state view and implement the Keccak-f[1600] permutation used by
the STARTOP selector.
The simple SHA3 DAT register moves and XORDAT selectors are decoded as
direct TCG transfers in the selector decode patch. This helper patch only
keeps the side-effecting SHA3 operation support.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-5-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 1 +
target/mips/tcg/octeon_crypto.c | 93 +++++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 20ffbfb7096..b887e05199a 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -47,6 +47,7 @@ DEF_HELPER_2(octeon_cp2_mt_gfm_mul_reflect1, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_gfm_xor0_reflect, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1_reflect, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1, void, env, i64)
+DEF_HELPER_1(octeon_cp2_mt_sha3_startop, void, env)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index b417dcf53b6..cf718d64829 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -153,6 +153,94 @@ static void octeon_gfm_mul64_uia2(const uint64_t x[2], const uint64_t y[2],
out[1] = revbit64(res);
}
+static const uint64_t octeon_sha3_round_constants[24] = {
+ 0x0000000000000001ULL, 0x0000000000008082ULL,
+ 0x800000000000808aULL, 0x8000000080008000ULL,
+ 0x000000000000808bULL, 0x0000000080000001ULL,
+ 0x8000000080008081ULL, 0x8000000000008009ULL,
+ 0x000000000000008aULL, 0x0000000000000088ULL,
+ 0x0000000080008009ULL, 0x000000008000000aULL,
+ 0x000000008000808bULL, 0x800000000000008bULL,
+ 0x8000000000008089ULL, 0x8000000000008003ULL,
+ 0x8000000000008002ULL, 0x8000000000000080ULL,
+ 0x000000000000800aULL, 0x800000008000000aULL,
+ 0x8000000080008081ULL, 0x8000000000008080ULL,
+ 0x0000000080000001ULL, 0x8000000080008008ULL,
+};
+
+static const uint8_t octeon_sha3_rotation_constants[24] = {
+ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
+ 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
+};
+
+static const uint8_t octeon_sha3_pi_lanes[24] = {
+ 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
+ 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
+};
+
+static uint64_t octeon_sha3_reg_to_lane(uint64_t value)
+{
+ /*
+ * The COP2 register interface is consumed by big-endian MIPS code as
+ * 64-bit register values, while Keccak lanes are byte-little-endian.
+ */
+ return bswap64(value);
+}
+
+static uint64_t octeon_sha3_lane_to_reg(uint64_t value)
+{
+ return bswap64(value);
+}
+
+static void octeon_sha3_permute(MIPSOcteonCryptoState *crypto)
+{
+ uint64_t state[25];
+
+ for (int i = 0; i < 25; i++) {
+ state[i] = octeon_sha3_reg_to_lane(crypto->sha3_dat[i]);
+ }
+
+ for (int round = 0; round < 24; round++) {
+ uint64_t bc[5];
+ uint64_t temp;
+
+ for (int x = 0; x < 5; x++) {
+ bc[x] = state[x] ^ state[5 + x] ^ state[10 + x] ^
+ state[15 + x] ^ state[20 + x];
+ }
+ for (int x = 0; x < 5; x++) {
+ temp = bc[(x + 4) % 5] ^ rol64(bc[(x + 1) % 5], 1);
+ for (int y = 0; y < 25; y += 5) {
+ state[y + x] ^= temp;
+ }
+ }
+
+ temp = state[1];
+ for (int i = 0; i < 24; i++) {
+ uint64_t next = state[octeon_sha3_pi_lanes[i]];
+
+ state[octeon_sha3_pi_lanes[i]] =
+ rol64(temp, octeon_sha3_rotation_constants[i]);
+ temp = next;
+ }
+
+ for (int y = 0; y < 25; y += 5) {
+ for (int x = 0; x < 5; x++) {
+ bc[x] = state[y + x];
+ }
+ for (int x = 0; x < 5; x++) {
+ state[y + x] = bc[x] ^ ((~bc[(x + 1) % 5]) & bc[(x + 2) % 5]);
+ }
+ }
+
+ state[0] ^= octeon_sha3_round_constants[round];
+ }
+
+ for (int i = 0; i < 25; i++) {
+ crypto->sha3_dat[i] = octeon_sha3_lane_to_reg(state[i]);
+ }
+}
+
uint64_t helper_octeon_cp2_mf_crc_iv_reflect(CPUMIPSState *env)
{
return octeon_crc_reflect32_by_byte(env->octeon_crypto.crc_iv);
@@ -222,6 +310,11 @@ void helper_octeon_cp2_mt_gfm_xormul1(CPUMIPSState *env, uint64_t value)
octeon_gfm_xormul1_common(crypto, value);
}
+void helper_octeon_cp2_mt_sha3_startop(CPUMIPSState *env)
+{
+ octeon_sha3_permute(&env->octeon_crypto);
+}
+
void helper_octeon_cp2_mt_crc_write_iv_reflect(CPUMIPSState *env,
uint64_t value)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 06/23] target/mips: add Octeon ZUC COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2026-07-07 18:15 ` [PULL 05/23] target/mips: add Octeon SHA3 " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 07/23] target/mips: add Octeon SNOW3G " Philippe Mathieu-Daudé
` (18 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add the Octeon ZUC START and MORE helper operations and model the shared
state window used by the hardware interface. This covers the keystream
and MAC engine state, including the save-and-restore view that overlaps
the HSH/SHA3 bank.
Keep the LFSR words in the architectural HSH DAT input registers and the
runtime MAC/FSM/result state in the documented HASHIV window. The third
MAC lookahead word is generated on demand instead of being kept in a
non-architectural shadow slot.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-6-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 2 +
target/mips/tcg/octeon_crypto.c | 338 ++++++++++++++++++++++++++++++++
2 files changed, 340 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index b887e05199a..292336ec629 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -48,6 +48,8 @@ DEF_HELPER_2(octeon_cp2_mt_gfm_xor0_reflect, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1_reflect, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1, void, env, i64)
DEF_HELPER_1(octeon_cp2_mt_sha3_startop, void, env)
+DEF_HELPER_2(octeon_cp2_mt_zuc_start, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_zuc_more, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index cf718d64829..548269b9b8f 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -241,6 +241,344 @@ static void octeon_sha3_permute(MIPSOcteonCryptoState *crypto)
}
}
+static uint32_t octeon_crypto_hi32(uint64_t value)
+{
+ return value >> 32;
+}
+
+static uint32_t octeon_crypto_lo32(uint64_t value)
+{
+ return value;
+}
+
+static const uint8_t octeon_zuc_s0[256] = {
+ 0x3e, 0x72, 0x5b, 0x47, 0xca, 0xe0, 0x00, 0x33,
+ 0x04, 0xd1, 0x54, 0x98, 0x09, 0xb9, 0x6d, 0xcb,
+ 0x7b, 0x1b, 0xf9, 0x32, 0xaf, 0x9d, 0x6a, 0xa5,
+ 0xb8, 0x2d, 0xfc, 0x1d, 0x08, 0x53, 0x03, 0x90,
+ 0x4d, 0x4e, 0x84, 0x99, 0xe4, 0xce, 0xd9, 0x91,
+ 0xdd, 0xb6, 0x85, 0x48, 0x8b, 0x29, 0x6e, 0xac,
+ 0xcd, 0xc1, 0xf8, 0x1e, 0x73, 0x43, 0x69, 0xc6,
+ 0xb5, 0xbd, 0xfd, 0x39, 0x63, 0x20, 0xd4, 0x38,
+ 0x76, 0x7d, 0xb2, 0xa7, 0xcf, 0xed, 0x57, 0xc5,
+ 0xf3, 0x2c, 0xbb, 0x14, 0x21, 0x06, 0x55, 0x9b,
+ 0xe3, 0xef, 0x5e, 0x31, 0x4f, 0x7f, 0x5a, 0xa4,
+ 0x0d, 0x82, 0x51, 0x49, 0x5f, 0xba, 0x58, 0x1c,
+ 0x4a, 0x16, 0xd5, 0x17, 0xa8, 0x92, 0x24, 0x1f,
+ 0x8c, 0xff, 0xd8, 0xae, 0x2e, 0x01, 0xd3, 0xad,
+ 0x3b, 0x4b, 0xda, 0x46, 0xeb, 0xc9, 0xde, 0x9a,
+ 0x8f, 0x87, 0xd7, 0x3a, 0x80, 0x6f, 0x2f, 0xc8,
+ 0xb1, 0xb4, 0x37, 0xf7, 0x0a, 0x22, 0x13, 0x28,
+ 0x7c, 0xcc, 0x3c, 0x89, 0xc7, 0xc3, 0x96, 0x56,
+ 0x07, 0xbf, 0x7e, 0xf0, 0x0b, 0x2b, 0x97, 0x52,
+ 0x35, 0x41, 0x79, 0x61, 0xa6, 0x4c, 0x10, 0xfe,
+ 0xbc, 0x26, 0x95, 0x88, 0x8a, 0xb0, 0xa3, 0xfb,
+ 0xc0, 0x18, 0x94, 0xf2, 0xe1, 0xe5, 0xe9, 0x5d,
+ 0xd0, 0xdc, 0x11, 0x66, 0x64, 0x5c, 0xec, 0x59,
+ 0x42, 0x75, 0x12, 0xf5, 0x74, 0x9c, 0xaa, 0x23,
+ 0x0e, 0x86, 0xab, 0xbe, 0x2a, 0x02, 0xe7, 0x67,
+ 0xe6, 0x44, 0xa2, 0x6c, 0xc2, 0x93, 0x9f, 0xf1,
+ 0xf6, 0xfa, 0x36, 0xd2, 0x50, 0x68, 0x9e, 0x62,
+ 0x71, 0x15, 0x3d, 0xd6, 0x40, 0xc4, 0xe2, 0x0f,
+ 0x8e, 0x83, 0x77, 0x6b, 0x25, 0x05, 0x3f, 0x0c,
+ 0x30, 0xea, 0x70, 0xb7, 0xa1, 0xe8, 0xa9, 0x65,
+ 0x8d, 0x27, 0x1a, 0xdb, 0x81, 0xb3, 0xa0, 0xf4,
+ 0x45, 0x7a, 0x19, 0xdf, 0xee, 0x78, 0x34, 0x60,
+};
+
+static const uint8_t octeon_zuc_s1[256] = {
+ 0x55, 0xc2, 0x63, 0x71, 0x3b, 0xc8, 0x47, 0x86,
+ 0x9f, 0x3c, 0xda, 0x5b, 0x29, 0xaa, 0xfd, 0x77,
+ 0x8c, 0xc5, 0x94, 0x0c, 0xa6, 0x1a, 0x13, 0x00,
+ 0xe3, 0xa8, 0x16, 0x72, 0x40, 0xf9, 0xf8, 0x42,
+ 0x44, 0x26, 0x68, 0x96, 0x81, 0xd9, 0x45, 0x3e,
+ 0x10, 0x76, 0xc6, 0xa7, 0x8b, 0x39, 0x43, 0xe1,
+ 0x3a, 0xb5, 0x56, 0x2a, 0xc0, 0x6d, 0xb3, 0x05,
+ 0x22, 0x66, 0xbf, 0xdc, 0x0b, 0xfa, 0x62, 0x48,
+ 0xdd, 0x20, 0x11, 0x06, 0x36, 0xc9, 0xc1, 0xcf,
+ 0xf6, 0x27, 0x52, 0xbb, 0x69, 0xf5, 0xd4, 0x87,
+ 0x7f, 0x84, 0x4c, 0xd2, 0x9c, 0x57, 0xa4, 0xbc,
+ 0x4f, 0x9a, 0xdf, 0xfe, 0xd6, 0x8d, 0x7a, 0xeb,
+ 0x2b, 0x53, 0xd8, 0x5c, 0xa1, 0x14, 0x17, 0xfb,
+ 0x23, 0xd5, 0x7d, 0x30, 0x67, 0x73, 0x08, 0x09,
+ 0xee, 0xb7, 0x70, 0x3f, 0x61, 0xb2, 0x19, 0x8e,
+ 0x4e, 0xe5, 0x4b, 0x93, 0x8f, 0x5d, 0xdb, 0xa9,
+ 0xad, 0xf1, 0xae, 0x2e, 0xcb, 0x0d, 0xfc, 0xf4,
+ 0x2d, 0x46, 0x6e, 0x1d, 0x97, 0xe8, 0xd1, 0xe9,
+ 0x4d, 0x37, 0xa5, 0x75, 0x5e, 0x83, 0x9e, 0xab,
+ 0x82, 0x9d, 0xb9, 0x1c, 0xe0, 0xcd, 0x49, 0x89,
+ 0x01, 0xb6, 0xbd, 0x58, 0x24, 0xa2, 0x5f, 0x38,
+ 0x78, 0x99, 0x15, 0x90, 0x50, 0xb8, 0x95, 0xe4,
+ 0xd0, 0x91, 0xc7, 0xce, 0xed, 0x0f, 0xb4, 0x6f,
+ 0xa0, 0xcc, 0xf0, 0x02, 0x4a, 0x79, 0xc3, 0xde,
+ 0xa3, 0xef, 0xea, 0x51, 0xe6, 0x6b, 0x18, 0xec,
+ 0x1b, 0x2c, 0x80, 0xf7, 0x74, 0xe7, 0xff, 0x21,
+ 0x5a, 0x6a, 0x54, 0x1e, 0x41, 0x31, 0x92, 0x35,
+ 0xc4, 0x33, 0x07, 0x0a, 0xba, 0x7e, 0x0e, 0x34,
+ 0x88, 0xb1, 0x98, 0x7c, 0xf3, 0x3d, 0x60, 0x6c,
+ 0x7b, 0xca, 0xd3, 0x1f, 0x32, 0x65, 0x04, 0x28,
+ 0x64, 0xbe, 0x85, 0x9b, 0x2f, 0x59, 0x8a, 0xd7,
+ 0xb0, 0x25, 0xac, 0xaf, 0x12, 0x03, 0xe2, 0xf2,
+};
+
+static uint32_t octeon_zuc_addm(uint32_t a, uint32_t b)
+{
+ uint32_t c = a + b;
+
+ c = (c & 0x7fffffffU) + (c >> 31);
+ return c ? c : 0x7fffffffU;
+}
+
+static uint32_t octeon_zuc_mul_by_pow2(uint32_t v, unsigned int shift)
+{
+ return ((v << shift) | (v >> (31 - shift))) & 0x7fffffffU;
+}
+
+static uint32_t octeon_zuc_make_u32(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
+{
+ return ((uint32_t)a << 24) | ((uint32_t)b << 16) |
+ ((uint32_t)c << 8) | d;
+}
+
+static uint64_t octeon_zuc_pack_pair(uint32_t hi, uint32_t lo)
+{
+ return ((uint64_t)hi << 32) | lo;
+}
+
+static uint32_t octeon_zuc_lfsr(const MIPSOcteonCryptoState *crypto,
+ unsigned int index)
+{
+ uint64_t pair = crypto->hsh_dat[index / 2];
+
+ return index & 1 ? octeon_crypto_lo32(pair) : octeon_crypto_hi32(pair);
+}
+
+static void octeon_zuc_set_lfsr(MIPSOcteonCryptoState *crypto,
+ unsigned int index, uint32_t value)
+{
+ uint32_t hi = octeon_crypto_hi32(crypto->hsh_dat[index / 2]);
+ uint32_t lo = octeon_crypto_lo32(crypto->hsh_dat[index / 2]);
+
+ value &= 0x7fffffffU;
+ if (index & 1) {
+ lo = value;
+ } else {
+ hi = value;
+ }
+ crypto->hsh_dat[index / 2] = octeon_zuc_pack_pair(hi, lo);
+}
+
+static uint32_t octeon_zuc_fsm(const MIPSOcteonCryptoState *crypto,
+ unsigned int index)
+{
+ g_assert(index < 2);
+ return crypto->hsh_iv[1 + index];
+}
+
+static void octeon_zuc_set_fsm(MIPSOcteonCryptoState *crypto,
+ unsigned int index, uint32_t value)
+{
+ g_assert(index < 2);
+ crypto->hsh_iv[1 + index] = value;
+}
+
+static uint32_t octeon_zuc_window(const MIPSOcteonCryptoState *crypto,
+ unsigned int index)
+{
+ uint64_t pair = crypto->hsh_iv[0];
+
+ switch (index) {
+ case 0:
+ return octeon_crypto_hi32(pair);
+ case 1:
+ return octeon_crypto_lo32(pair);
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void octeon_zuc_set_window_pair(MIPSOcteonCryptoState *crypto,
+ uint32_t hi, uint32_t lo)
+{
+ crypto->hsh_iv[0] = octeon_zuc_pack_pair(hi, lo);
+}
+
+static uint32_t octeon_zuc_tresult(const MIPSOcteonCryptoState *crypto)
+{
+ return crypto->hsh_iv[3];
+}
+
+static void octeon_zuc_set_tresult(MIPSOcteonCryptoState *crypto,
+ uint32_t value)
+{
+ crypto->hsh_iv[3] = value;
+}
+
+static void octeon_zuc_bit_reorganization(const MIPSOcteonCryptoState *crypto,
+ uint32_t x[4])
+{
+ x[0] = ((octeon_zuc_lfsr(crypto, 15) & 0x7fff8000U) << 1) |
+ (octeon_zuc_lfsr(crypto, 14) & 0xffffU);
+ x[1] = ((octeon_zuc_lfsr(crypto, 11) & 0xffffU) << 16) |
+ (octeon_zuc_lfsr(crypto, 9) >> 15);
+ x[2] = ((octeon_zuc_lfsr(crypto, 7) & 0xffffU) << 16) |
+ (octeon_zuc_lfsr(crypto, 5) >> 15);
+ x[3] = ((octeon_zuc_lfsr(crypto, 2) & 0xffffU) << 16) |
+ (octeon_zuc_lfsr(crypto, 0) >> 15);
+}
+
+static uint32_t octeon_zuc_l1(uint32_t x)
+{
+ return x ^ rol32(x, 2) ^ rol32(x, 10) ^ rol32(x, 18) ^ rol32(x, 24);
+}
+
+static uint32_t octeon_zuc_l2(uint32_t x)
+{
+ return x ^ rol32(x, 8) ^ rol32(x, 14) ^ rol32(x, 22) ^ rol32(x, 30);
+}
+
+static uint32_t octeon_zuc_f(MIPSOcteonCryptoState *crypto, const uint32_t x[4])
+{
+ uint32_t fsm0 = octeon_zuc_fsm(crypto, 0);
+ uint32_t fsm1 = octeon_zuc_fsm(crypto, 1);
+ uint32_t w = (x[0] ^ fsm0) + fsm1;
+ uint32_t w1 = fsm0 + x[1];
+ uint32_t w2 = fsm1 ^ x[2];
+ uint32_t u = octeon_zuc_l1((w1 << 16) | (w2 >> 16));
+ uint32_t v = octeon_zuc_l2((w2 << 16) | (w1 >> 16));
+
+ octeon_zuc_set_fsm(crypto, 0,
+ octeon_zuc_make_u32(octeon_zuc_s0[u >> 24],
+ octeon_zuc_s1[(uint8_t)(u >> 16)],
+ octeon_zuc_s0[(uint8_t)(u >> 8)],
+ octeon_zuc_s1[(uint8_t)u]));
+ octeon_zuc_set_fsm(crypto, 1,
+ octeon_zuc_make_u32(octeon_zuc_s0[v >> 24],
+ octeon_zuc_s1[(uint8_t)(v >> 16)],
+ octeon_zuc_s0[(uint8_t)(v >> 8)],
+ octeon_zuc_s1[(uint8_t)v]));
+ return w;
+}
+
+static void octeon_zuc_lfsr_step(MIPSOcteonCryptoState *crypto,
+ bool init_mode, uint32_t u)
+{
+ uint32_t lfsr[16];
+ uint32_t f;
+
+ for (int i = 0; i < 16; i++) {
+ lfsr[i] = octeon_zuc_lfsr(crypto, i);
+ }
+
+ f = lfsr[0];
+ f = octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(lfsr[0], 8));
+ f = octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(lfsr[4], 20));
+ f = octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(lfsr[10], 21));
+ f = octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(lfsr[13], 17));
+ f = octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(lfsr[15], 15));
+ if (init_mode) {
+ f = octeon_zuc_addm(f, u);
+ }
+
+ for (int i = 0; i < 15; i++) {
+ octeon_zuc_set_lfsr(crypto, i, lfsr[i + 1]);
+ }
+ octeon_zuc_set_lfsr(crypto, 15, f);
+}
+
+static uint32_t octeon_zuc_generate_word(MIPSOcteonCryptoState *crypto)
+{
+ uint32_t x[4];
+ uint32_t z;
+
+ octeon_zuc_bit_reorganization(crypto, x);
+ z = octeon_zuc_f(crypto, x) ^ x[3];
+ octeon_zuc_lfsr_step(crypto, false, 0);
+ return z;
+}
+
+static void octeon_zuc_fill_window_pair(MIPSOcteonCryptoState *crypto)
+{
+ uint32_t z0 = octeon_zuc_generate_word(crypto);
+ uint32_t z1 = octeon_zuc_generate_word(crypto);
+
+ octeon_zuc_set_window_pair(crypto, z0, z1);
+}
+
+static uint32_t
+octeon_zuc_window_word(const MIPSOcteonCryptoState *crypto, unsigned int bit,
+ uint32_t z2)
+{
+ if (bit == 0) {
+ return octeon_zuc_window(crypto, 0);
+ }
+ if (bit < 32) {
+ return (octeon_zuc_window(crypto, 0) << bit) |
+ (octeon_zuc_window(crypto, 1) >> (32 - bit));
+ }
+ if (bit == 32) {
+ return octeon_zuc_window(crypto, 1);
+ }
+ return (octeon_zuc_window(crypto, 1) << (bit - 32)) |
+ (z2 >> (64 - bit));
+}
+
+static void octeon_zuc_advance_window(MIPSOcteonCryptoState *crypto,
+ uint32_t z2)
+{
+ uint32_t z3 = octeon_zuc_generate_word(crypto);
+
+ octeon_zuc_set_window_pair(crypto, z2, z3);
+}
+
+static void octeon_zuc_start(MIPSOcteonCryptoState *crypto, uint64_t data)
+{
+ uint32_t x[4];
+
+ for (int i = 0; i < 14; i++) {
+ octeon_zuc_set_lfsr(crypto, i, octeon_zuc_lfsr(crypto, i));
+ }
+ octeon_zuc_set_lfsr(crypto, 14, data >> 32);
+ octeon_zuc_set_lfsr(crypto, 15, data);
+ octeon_zuc_set_fsm(crypto, 0, 0);
+ octeon_zuc_set_fsm(crypto, 1, 0);
+ octeon_zuc_set_tresult(crypto, 0);
+
+ for (int i = 0; i < 32; i++) {
+ octeon_zuc_bit_reorganization(crypto, x);
+ octeon_zuc_lfsr_step(crypto, true, octeon_zuc_f(crypto, x) >> 1);
+ }
+
+ octeon_zuc_bit_reorganization(crypto, x);
+ (void)octeon_zuc_f(crypto, x);
+ octeon_zuc_lfsr_step(crypto, false, 0);
+ octeon_zuc_fill_window_pair(crypto);
+}
+
+static void octeon_zuc_more(MIPSOcteonCryptoState *crypto, uint64_t data)
+{
+ uint32_t t = octeon_zuc_tresult(crypto);
+ uint32_t z2 = octeon_zuc_generate_word(crypto);
+
+ for (unsigned int bit = 0; bit < 64; bit++) {
+ if ((data >> (63 - bit)) & 1) {
+ t ^= octeon_zuc_window_word(crypto, bit, z2);
+ }
+ }
+ octeon_zuc_set_tresult(crypto, t);
+ octeon_zuc_advance_window(crypto, z2);
+}
+
+void helper_octeon_cp2_mt_zuc_start(CPUMIPSState *env, uint64_t value)
+{
+ octeon_zuc_start(&env->octeon_crypto, value);
+}
+
+void helper_octeon_cp2_mt_zuc_more(CPUMIPSState *env, uint64_t value)
+{
+ octeon_zuc_more(&env->octeon_crypto, value);
+}
+
uint64_t helper_octeon_cp2_mf_crc_iv_reflect(CPUMIPSState *env)
{
return octeon_crc_reflect32_by_byte(env->octeon_crypto.crc_iv);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 07/23] target/mips: add Octeon SNOW3G COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2026-07-07 18:15 ` [PULL 06/23] target/mips: add Octeon ZUC " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 08/23] target/mips: add Octeon AES " Philippe Mathieu-Daudé
` (17 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add helper support for the Octeon SNOW3G START and MORE selectors. The
engine state and result are represented through the architectural HSH IV
and DAT register banks that SNOW3G aliases for save and restore.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-7-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 2 +
target/mips/tcg/octeon_crypto.c | 282 ++++++++++++++++++++++++++++++++
2 files changed, 284 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 292336ec629..c4e7693df63 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -50,6 +50,8 @@ DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1, void, env, i64)
DEF_HELPER_1(octeon_cp2_mt_sha3_startop, void, env)
DEF_HELPER_2(octeon_cp2_mt_zuc_start, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_zuc_more, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_snow3g_start, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_snow3g_more, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index 548269b9b8f..930a67346ef 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -251,6 +251,11 @@ static uint32_t octeon_crypto_lo32(uint64_t value)
return value;
}
+static uint64_t octeon_crypto_pack32(uint32_t hi, uint32_t lo)
+{
+ return ((uint64_t)hi << 32) | lo;
+}
+
static const uint8_t octeon_zuc_s0[256] = {
0x3e, 0x72, 0x5b, 0x47, 0xca, 0xe0, 0x00, 0x33,
0x04, 0xd1, 0x54, 0x98, 0x09, 0xb9, 0x6d, 0xcb,
@@ -569,6 +574,283 @@ static void octeon_zuc_more(MIPSOcteonCryptoState *crypto, uint64_t data)
octeon_zuc_advance_window(crypto, z2);
}
+static const uint8_t octeon_snow3g_sr[256] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
+};
+
+static const uint8_t octeon_snow3g_sq[256] = {
+ 0x25, 0x24, 0x73, 0x67, 0xd7, 0xae, 0x5c, 0x30,
+ 0xa4, 0xee, 0x6e, 0xcb, 0x7d, 0xb5, 0x82, 0xdb,
+ 0xe4, 0x8e, 0x48, 0x49, 0x4f, 0x5d, 0x6a, 0x78,
+ 0x70, 0x88, 0xe8, 0x5f, 0x5e, 0x84, 0x65, 0xe2,
+ 0xd8, 0xe9, 0xcc, 0xed, 0x40, 0x2f, 0x11, 0x28,
+ 0x57, 0xd2, 0xac, 0xe3, 0x4a, 0x15, 0x1b, 0xb9,
+ 0xb2, 0x80, 0x85, 0xa6, 0x2e, 0x02, 0x47, 0x29,
+ 0x07, 0x4b, 0x0e, 0xc1, 0x51, 0xaa, 0x89, 0xd4,
+ 0xca, 0x01, 0x46, 0xb3, 0xef, 0xdd, 0x44, 0x7b,
+ 0xc2, 0x7f, 0xbe, 0xc3, 0x9f, 0x20, 0x4c, 0x64,
+ 0x83, 0xa2, 0x68, 0x42, 0x13, 0xb4, 0x41, 0xcd,
+ 0xba, 0xc6, 0xbb, 0x6d, 0x4d, 0x71, 0x21, 0xf4,
+ 0x8d, 0xb0, 0xe5, 0x93, 0xfe, 0x8f, 0xe6, 0xcf,
+ 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xfa,
+ 0xbc, 0x0f, 0x08, 0x52, 0x1d, 0x55, 0x1a, 0xc5,
+ 0x4e, 0x23, 0x69, 0x7a, 0x92, 0xff, 0x5b, 0x5a,
+ 0xeb, 0x9a, 0x1c, 0xa9, 0xd1, 0x7e, 0x0d, 0xfc,
+ 0x50, 0x8a, 0xb6, 0x62, 0xf5, 0x0a, 0xf8, 0xdc,
+ 0x03, 0x3c, 0x0c, 0x39, 0xf1, 0xb8, 0xf3, 0x3d,
+ 0xf2, 0xd5, 0x97, 0x66, 0x81, 0x32, 0xa0, 0x00,
+ 0x06, 0xce, 0xf6, 0xea, 0xb7, 0x17, 0xf7, 0x8c,
+ 0x79, 0xd6, 0xa7, 0xbf, 0x8b, 0x3f, 0x1f, 0x53,
+ 0x63, 0x75, 0x35, 0x2c, 0x60, 0xfd, 0x27, 0xd3,
+ 0x94, 0xa5, 0x7c, 0xa1, 0x05, 0x58, 0x2d, 0xbd,
+ 0xd9, 0xc7, 0xaf, 0x6b, 0x54, 0x0b, 0xe0, 0x38,
+ 0x04, 0xc8, 0x9d, 0xe7, 0x14, 0xb1, 0x87, 0x9c,
+ 0xdf, 0x6f, 0xf9, 0xda, 0x2a, 0xc4, 0x59, 0x16,
+ 0x74, 0x91, 0xab, 0x26, 0x61, 0x76, 0x34, 0x2b,
+ 0xad, 0x99, 0xfb, 0x72, 0xec, 0x33, 0x12, 0xde,
+ 0x98, 0x3b, 0xc0, 0x9b, 0x3e, 0x18, 0x10, 0x3a,
+ 0x56, 0xe1, 0x77, 0xc9, 0x1e, 0x9e, 0x95, 0xa3,
+ 0x90, 0x19, 0xa8, 0x6c, 0x09, 0xd0, 0xf0, 0x86,
+};
+
+static uint8_t octeon_snow3g_mulx(uint8_t v, uint8_t c)
+{
+ return (v & 0x80) ? ((v << 1) ^ c) : (v << 1);
+}
+
+static uint8_t octeon_snow3g_mulxpow(uint8_t v, unsigned int n, uint8_t c)
+{
+ while (n-- > 0) {
+ v = octeon_snow3g_mulx(v, c);
+ }
+ return v;
+}
+
+static uint32_t octeon_snow3g_pack32(uint8_t b0, uint8_t b1,
+ uint8_t b2, uint8_t b3)
+{
+ return ((uint32_t)b0 << 24)
+ | ((uint32_t)b1 << 16)
+ | ((uint32_t)b2 << 8)
+ | b3;
+}
+
+static uint32_t octeon_snow3g_mulalpha(uint8_t c)
+{
+ return octeon_snow3g_pack32(octeon_snow3g_mulxpow(c, 23, 0xa9),
+ octeon_snow3g_mulxpow(c, 245, 0xa9),
+ octeon_snow3g_mulxpow(c, 48, 0xa9),
+ octeon_snow3g_mulxpow(c, 239, 0xa9));
+}
+
+static uint32_t octeon_snow3g_divalpha(uint8_t c)
+{
+ return octeon_snow3g_pack32(octeon_snow3g_mulxpow(c, 16, 0xa9),
+ octeon_snow3g_mulxpow(c, 39, 0xa9),
+ octeon_snow3g_mulxpow(c, 6, 0xa9),
+ octeon_snow3g_mulxpow(c, 64, 0xa9));
+}
+
+static uint32_t octeon_snow3g_s1(uint32_t w)
+{
+ uint8_t x0 = octeon_snow3g_sr[w >> 24];
+ uint8_t x1 = octeon_snow3g_sr[(uint8_t)(w >> 16)];
+ uint8_t x2 = octeon_snow3g_sr[(uint8_t)(w >> 8)];
+ uint8_t x3 = octeon_snow3g_sr[(uint8_t)w];
+ uint8_t r0 = octeon_snow3g_mulx(x0, 0x1b) ^ x1 ^ x2 ^
+ octeon_snow3g_mulx(x3, 0x1b) ^ x3;
+ uint8_t r1 = octeon_snow3g_mulx(x0, 0x1b) ^ x0 ^
+ octeon_snow3g_mulx(x1, 0x1b) ^ x2 ^ x3;
+ uint8_t r2 = x0 ^ octeon_snow3g_mulx(x1, 0x1b) ^ x1 ^
+ octeon_snow3g_mulx(x2, 0x1b) ^ x3;
+ uint8_t r3 = x0 ^ x1 ^ octeon_snow3g_mulx(x2, 0x1b) ^ x2 ^
+ octeon_snow3g_mulx(x3, 0x1b);
+
+ return octeon_snow3g_pack32(r0, r1, r2, r3);
+}
+
+static uint32_t octeon_snow3g_s2(uint32_t w)
+{
+ uint8_t x0 = octeon_snow3g_sq[w >> 24];
+ uint8_t x1 = octeon_snow3g_sq[(uint8_t)(w >> 16)];
+ uint8_t x2 = octeon_snow3g_sq[(uint8_t)(w >> 8)];
+ uint8_t x3 = octeon_snow3g_sq[(uint8_t)w];
+ uint8_t r0 = octeon_snow3g_mulx(x0, 0x69) ^ x1 ^ x2 ^
+ octeon_snow3g_mulx(x3, 0x69) ^ x3;
+ uint8_t r1 = octeon_snow3g_mulx(x0, 0x69) ^ x0 ^
+ octeon_snow3g_mulx(x1, 0x69) ^ x2 ^ x3;
+ uint8_t r2 = x0 ^ octeon_snow3g_mulx(x1, 0x69) ^ x1 ^
+ octeon_snow3g_mulx(x2, 0x69) ^ x3;
+ uint8_t r3 = x0 ^ x1 ^ octeon_snow3g_mulx(x2, 0x69) ^ x2 ^
+ octeon_snow3g_mulx(x3, 0x69);
+
+ return octeon_snow3g_pack32(r0, r1, r2, r3);
+}
+
+static uint32_t octeon_snow3g_lfsr(const MIPSOcteonCryptoState *crypto,
+ unsigned int index)
+{
+ uint64_t pair = crypto->hsh_dat[index / 2];
+
+ return index & 1 ? octeon_crypto_lo32(pair) : octeon_crypto_hi32(pair);
+}
+
+static void octeon_snow3g_set_lfsr(MIPSOcteonCryptoState *crypto,
+ unsigned int index, uint32_t value)
+{
+ uint32_t hi = octeon_crypto_hi32(crypto->hsh_dat[index / 2]);
+ uint32_t lo = octeon_crypto_lo32(crypto->hsh_dat[index / 2]);
+
+ if (index & 1) {
+ lo = value;
+ } else {
+ hi = value;
+ }
+ crypto->hsh_dat[index / 2] = octeon_crypto_pack32(hi, lo);
+}
+
+static uint32_t octeon_snow3g_fsm(const MIPSOcteonCryptoState *crypto,
+ unsigned int index)
+{
+ return crypto->hsh_iv[1 + index];
+}
+
+static void octeon_snow3g_set_fsm(MIPSOcteonCryptoState *crypto,
+ unsigned int index, uint32_t value)
+{
+ crypto->hsh_iv[1 + index] = value;
+}
+
+static uint32_t octeon_snow3g_clock_fsm(MIPSOcteonCryptoState *crypto)
+{
+ uint32_t fsm0 = octeon_snow3g_fsm(crypto, 0);
+ uint32_t fsm1 = octeon_snow3g_fsm(crypto, 1);
+ uint32_t fsm2 = octeon_snow3g_fsm(crypto, 2);
+ uint32_t f = (uint32_t)(octeon_snow3g_lfsr(crypto, 15) + fsm0) ^ fsm1;
+ uint32_t r = (uint32_t)(fsm1 + (fsm2 ^ octeon_snow3g_lfsr(crypto, 5)));
+
+ octeon_snow3g_set_fsm(crypto, 2, octeon_snow3g_s2(fsm1));
+ octeon_snow3g_set_fsm(crypto, 1, octeon_snow3g_s1(fsm0));
+ octeon_snow3g_set_fsm(crypto, 0, r);
+ return f;
+}
+
+static void octeon_snow3g_clock_lfsr(MIPSOcteonCryptoState *crypto,
+ bool init_mode, uint32_t f)
+{
+ uint32_t lfsr[16];
+ uint32_t s0;
+ uint32_t s11;
+ uint32_t v;
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ lfsr[i] = octeon_snow3g_lfsr(crypto, i);
+ }
+
+ s0 = lfsr[0];
+ s11 = lfsr[11];
+ v = (s0 << 8) ^ octeon_snow3g_mulalpha(s0 >> 24) ^
+ lfsr[2] ^ (s11 >> 8) ^ octeon_snow3g_divalpha((uint8_t)s11);
+
+ if (init_mode) {
+ v ^= f;
+ }
+
+ for (i = 0; i < 15; i++) {
+ octeon_snow3g_set_lfsr(crypto, i, lfsr[i + 1]);
+ }
+ octeon_snow3g_set_lfsr(crypto, 15, v);
+}
+
+static uint32_t octeon_snow3g_generate_word(MIPSOcteonCryptoState *crypto)
+{
+ uint32_t f = octeon_snow3g_clock_fsm(crypto);
+ uint32_t z = f ^ octeon_snow3g_lfsr(crypto, 0);
+
+ octeon_snow3g_clock_lfsr(crypto, false, 0);
+ return z;
+}
+
+static void octeon_snow3g_queue_result(MIPSOcteonCryptoState *crypto)
+{
+ uint32_t z0 = octeon_snow3g_generate_word(crypto);
+ uint32_t z1 = octeon_snow3g_generate_word(crypto);
+
+ crypto->hsh_iv[0] = octeon_crypto_pack32(z0, z1);
+}
+
+static void octeon_snow3g_start(MIPSOcteonCryptoState *crypto, uint64_t data)
+{
+ int i;
+
+ for (i = 0; i < 14; i++) {
+ octeon_snow3g_set_lfsr(crypto, i, octeon_snow3g_lfsr(crypto, i));
+ }
+ octeon_snow3g_set_lfsr(crypto, 14, data >> 32);
+ octeon_snow3g_set_lfsr(crypto, 15, data);
+ for (i = 0; i < 3; i++) {
+ octeon_snow3g_set_fsm(crypto, i, 0);
+ }
+
+ for (i = 0; i < 32; i++) {
+ uint32_t f = octeon_snow3g_clock_fsm(crypto);
+
+ octeon_snow3g_clock_lfsr(crypto, true, f);
+ }
+
+ (void)octeon_snow3g_clock_fsm(crypto);
+ octeon_snow3g_clock_lfsr(crypto, false, 0);
+ octeon_snow3g_queue_result(crypto);
+}
+
+static void octeon_snow3g_more(MIPSOcteonCryptoState *crypto)
+{
+ octeon_snow3g_queue_result(crypto);
+}
+
+void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
+{
+ octeon_snow3g_start(&env->octeon_crypto, value);
+}
+
+void helper_octeon_cp2_mt_snow3g_more(CPUMIPSState *env, uint64_t value)
+{
+ (void)value;
+ octeon_snow3g_more(&env->octeon_crypto);
+}
+
void helper_octeon_cp2_mt_zuc_start(CPUMIPSState *env, uint64_t value)
{
octeon_zuc_start(&env->octeon_crypto, value);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 08/23] target/mips: add Octeon AES COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (6 preceding siblings ...)
2026-07-07 18:15 ` [PULL 07/23] target/mips: add Octeon SNOW3G " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 09/23] target/mips: add Octeon SMS4 " Philippe Mathieu-Daudé
` (16 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add helper support for the Octeon AES operation selectors. Direct
register-transfer selectors do not need helpers; the ECB/CBC encrypt and
decrypt operations consume the AES input, key, IV, and key-length state.
AESRESINP is modeled as one architectural register bank; operation
helpers consume the current AESRESINP block and write the result back to
the same bank.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-8-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 4 +
target/mips/tcg/octeon_crypto.c | 145 ++++++++++++++++++++++++++++++++
2 files changed, 149 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index c4e7693df63..39c226ded92 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -52,6 +52,10 @@ DEF_HELPER_2(octeon_cp2_mt_zuc_start, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_zuc_more, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_snow3g_start, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_snow3g_more, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_aes_enc_cbc1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_aes_enc1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_aes_dec_cbc1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_aes_dec1, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index 930a67346ef..117e3a5026e 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -840,6 +840,151 @@ static void octeon_snow3g_more(MIPSOcteonCryptoState *crypto)
octeon_snow3g_queue_result(crypto);
}
+static int octeon_aes_key_bits(const MIPSOcteonCryptoState *crypto)
+{
+ enum {
+ OCTEON_AES_KEYLEN_128 = 1,
+ OCTEON_AES_KEYLEN_192 = 2,
+ OCTEON_AES_KEYLEN_256 = 3,
+ };
+
+ switch (crypto->aes_keylen) {
+ case OCTEON_AES_KEYLEN_128:
+ return 128;
+ case OCTEON_AES_KEYLEN_192:
+ return 192;
+ case OCTEON_AES_KEYLEN_256:
+ return 256;
+ default:
+ return 0;
+ }
+}
+
+static void octeon_aes_load_key(const MIPSOcteonCryptoState *crypto,
+ uint8_t *key, size_t keylen)
+{
+ stq_be_p(key, crypto->aes_key[0]);
+ stq_be_p(key + 8, crypto->aes_key[1]);
+ if (keylen > 16) {
+ stq_be_p(key + 16, crypto->aes_key[2]);
+ }
+ if (keylen > 24) {
+ stq_be_p(key + 24, crypto->aes_key[3]);
+ }
+}
+
+static void octeon_aes_load_block(const uint64_t regs[2], uint8_t *block)
+{
+ stq_be_p(block, regs[0]);
+ stq_be_p(block + 8, regs[1]);
+}
+
+static void octeon_aes_store_block(uint64_t regs[2], const uint8_t *block)
+{
+ regs[0] = ldq_be_p(block);
+ regs[1] = ldq_be_p(block + 8);
+}
+
+static void octeon_aes_encrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)
+{
+ AES_KEY key;
+ uint8_t in[16];
+ uint8_t out[16];
+ uint8_t iv[16];
+ uint8_t raw_key[32] = {};
+ int bits = octeon_aes_key_bits(crypto);
+
+ if (!bits) {
+ return;
+ }
+
+ octeon_aes_load_key(crypto, raw_key, bits / 8);
+ octeon_aes_load_block(crypto->aes_resinp, in);
+ if (cbc) {
+ int i;
+
+ octeon_aes_load_block(crypto->aes_iv, iv);
+ for (i = 0; i < sizeof(in); i++) {
+ in[i] ^= iv[i];
+ }
+ }
+
+ AES_set_encrypt_key(raw_key, bits, &key);
+ AES_encrypt(in, out, &key);
+ octeon_aes_store_block(crypto->aes_resinp, out);
+ if (cbc) {
+ octeon_aes_store_block(crypto->aes_iv, out);
+ }
+}
+
+static void octeon_aes_decrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)
+{
+ AES_KEY key;
+ uint8_t in[16];
+ uint8_t out[16];
+ uint8_t iv[16];
+ uint8_t next_iv[16];
+ uint8_t raw_key[32] = {};
+ int bits = octeon_aes_key_bits(crypto);
+ int i;
+
+ if (!bits) {
+ return;
+ }
+
+ octeon_aes_load_key(crypto, raw_key, bits / 8);
+ octeon_aes_load_block(crypto->aes_resinp, in);
+ if (cbc) {
+ memcpy(next_iv, in, sizeof(next_iv));
+ octeon_aes_load_block(crypto->aes_iv, iv);
+ }
+
+ AES_set_decrypt_key(raw_key, bits, &key);
+ AES_decrypt(in, out, &key);
+ if (cbc) {
+ for (i = 0; i < sizeof(out); i++) {
+ out[i] ^= iv[i];
+ }
+ }
+
+ octeon_aes_store_block(crypto->aes_resinp, out);
+ if (cbc) {
+ octeon_aes_store_block(crypto->aes_iv, next_iv);
+ }
+}
+
+void helper_octeon_cp2_mt_aes_enc_cbc1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->aes_resinp[1] = value;
+ octeon_aes_encrypt_common(crypto, true);
+}
+
+void helper_octeon_cp2_mt_aes_enc1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->aes_resinp[1] = value;
+ octeon_aes_encrypt_common(crypto, false);
+}
+
+void helper_octeon_cp2_mt_aes_dec_cbc1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->aes_resinp[1] = value;
+ octeon_aes_decrypt_common(crypto, true);
+}
+
+void helper_octeon_cp2_mt_aes_dec1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->aes_resinp[1] = value;
+ octeon_aes_decrypt_common(crypto, false);
+}
+
void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
{
octeon_snow3g_start(&env->octeon_crypto, value);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 09/23] target/mips: add Octeon SMS4 COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (7 preceding siblings ...)
2026-07-07 18:15 ` [PULL 08/23] target/mips: add Octeon AES " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 10/23] target/mips: add Octeon 3DES and KASUMI " Philippe Mathieu-Daudé
` (15 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add helper support for the Octeon SMS4 operation selectors. SMS4 reuses
the AES RESINP, IV, and key banks, so the helpers share the existing AES
state while implementing the SMS4 ECB/CBC encrypt and decrypt operations.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-9-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 4 ++
target/mips/tcg/octeon_crypto.c | 123 ++++++++++++++++++++++++++++++++
2 files changed, 127 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 39c226ded92..4949b94657f 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -56,6 +56,10 @@ DEF_HELPER_2(octeon_cp2_mt_aes_enc_cbc1, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_aes_enc1, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_aes_dec_cbc1, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_aes_dec1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_sms4_enc_cbc1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_sms4_enc1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_sms4_dec_cbc1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_sms4_dec1, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index 117e3a5026e..bcffd17ab6c 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -985,6 +985,129 @@ void helper_octeon_cp2_mt_aes_dec1(CPUMIPSState *env, uint64_t value)
octeon_aes_decrypt_common(crypto, false);
}
+static uint32_t octeon_sms4_t(uint32_t x)
+{
+ x = sm4_subword(x);
+ return x ^ rol32(x, 2) ^ rol32(x, 10) ^ rol32(x, 18) ^ rol32(x, 24);
+}
+
+static uint32_t octeon_sms4_t_key(uint32_t x)
+{
+ x = sm4_subword(x);
+ return x ^ rol32(x, 13) ^ rol32(x, 23);
+}
+
+static void octeon_sms4_expand_key(const uint8_t *key, uint32_t round_keys[32])
+{
+ static const uint32_t fk[4] = {
+ 0xa3b1bac6U, 0x56aa3350U, 0x677d9197U, 0xb27022dcU,
+ };
+ uint32_t k[36];
+
+ for (int i = 0; i < 4; i++) {
+ k[i] = ldl_be_p(key + i * 4) ^ fk[i];
+ }
+ for (int i = 0; i < 32; i++) {
+ k[i + 4] = k[i] ^ octeon_sms4_t_key(k[i + 1] ^ k[i + 2] ^
+ k[i + 3] ^ sm4_ck[i]);
+ round_keys[i] = k[i + 4];
+ }
+}
+
+static void octeon_sms4_crypt_block(const uint8_t *in, uint8_t *out,
+ const uint32_t round_keys[32],
+ bool encrypt)
+{
+ uint32_t x[36];
+
+ for (int i = 0; i < 4; i++) {
+ x[i] = ldl_be_p(in + i * 4);
+ }
+ for (int i = 0; i < 32; i++) {
+ uint32_t rk = round_keys[encrypt ? i : 31 - i];
+
+ x[i + 4] = x[i] ^ octeon_sms4_t(x[i + 1] ^ x[i + 2] ^
+ x[i + 3] ^ rk);
+ }
+ stl_be_p(out, x[35]);
+ stl_be_p(out + 4, x[34]);
+ stl_be_p(out + 8, x[33]);
+ stl_be_p(out + 12, x[32]);
+}
+
+static void octeon_sms4_crypt_common(MIPSOcteonCryptoState *crypto,
+ bool encrypt, bool cbc)
+{
+ uint8_t key[16];
+ uint8_t in[16];
+ uint8_t out[16];
+ uint8_t iv[16];
+ uint8_t next_iv[16];
+ uint32_t round_keys[32];
+
+ /*
+ * SMS4 aliases the AES state onto the RESINP, IV, and KEY banks,
+ * with only the operation selectors remaining distinct.
+ */
+ octeon_aes_load_key(crypto, key, sizeof(key));
+ octeon_aes_load_block(crypto->aes_resinp, in);
+ if (cbc) {
+ octeon_aes_load_block(crypto->aes_iv, iv);
+ if (encrypt) {
+ for (int i = 0; i < sizeof(in); i++) {
+ in[i] ^= iv[i];
+ }
+ } else {
+ memcpy(next_iv, in, sizeof(next_iv));
+ }
+ }
+
+ octeon_sms4_expand_key(key, round_keys);
+ octeon_sms4_crypt_block(in, out, round_keys, encrypt);
+ if (cbc && !encrypt) {
+ for (int i = 0; i < sizeof(out); i++) {
+ out[i] ^= iv[i];
+ }
+ }
+
+ octeon_aes_store_block(crypto->aes_resinp, out);
+ if (cbc) {
+ octeon_aes_store_block(crypto->aes_iv, encrypt ? out : next_iv);
+ }
+}
+
+void helper_octeon_cp2_mt_sms4_enc_cbc1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->aes_resinp[1] = value;
+ octeon_sms4_crypt_common(crypto, true, true);
+}
+
+void helper_octeon_cp2_mt_sms4_enc1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->aes_resinp[1] = value;
+ octeon_sms4_crypt_common(crypto, true, false);
+}
+
+void helper_octeon_cp2_mt_sms4_dec_cbc1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->aes_resinp[1] = value;
+ octeon_sms4_crypt_common(crypto, false, true);
+}
+
+void helper_octeon_cp2_mt_sms4_dec1(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->aes_resinp[1] = value;
+ octeon_sms4_crypt_common(crypto, false, false);
+}
+
void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
{
octeon_snow3g_start(&env->octeon_crypto, value);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 10/23] target/mips: add Octeon 3DES and KASUMI COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (8 preceding siblings ...)
2026-07-07 18:15 ` [PULL 09/23] target/mips: add Octeon SMS4 " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 11/23] target/mips: add Octeon Camellia " Philippe Mathieu-Daudé
` (14 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add helper support for the Octeon 3DES and KASUMI operation selectors.
The 3DES helpers implement ECB and CBC encrypt/decrypt over the shared
3DES key, IV, and result bank. KASUMI reuses the same register bank and
adds its own encrypt selectors.
Only the operation selectors require helper code. Simple key, IV, and
result register transfers are handled by direct selector decode.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-10-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 6 +
target/mips/tcg/octeon_crypto.c | 458 ++++++++++++++++++++++++++++++++
2 files changed, 464 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 4949b94657f..c9332c5c522 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -60,6 +60,12 @@ DEF_HELPER_2(octeon_cp2_mt_sms4_enc_cbc1, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_sms4_enc1, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_sms4_dec_cbc1, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_sms4_dec1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_des3_enc_cbc, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_kas_enc_cbc, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_des3_enc, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_kas_enc, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_des3_dec_cbc, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_des3_dec, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index bcffd17ab6c..8ea79e37568 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -1108,6 +1108,464 @@ void helper_octeon_cp2_mt_sms4_dec1(CPUMIPSState *env, uint64_t value)
octeon_sms4_crypt_common(crypto, false, false);
}
+static const uint8_t octeon_des_ip[64] = {
+ 58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7,
+};
+
+static const uint8_t octeon_des_fp[64] = {
+ 40, 8, 48, 16, 56, 24, 64, 32,
+ 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30,
+ 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28,
+ 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26,
+ 33, 1, 41, 9, 49, 17, 57, 25,
+};
+
+static const uint8_t octeon_des_e[48] = {
+ 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1,
+};
+
+static const uint8_t octeon_des_p[32] = {
+ 16, 7, 20, 21, 29, 12, 28, 17,
+ 1, 15, 23, 26, 5, 18, 31, 10,
+ 2, 8, 24, 14, 32, 27, 3, 9,
+ 19, 13, 30, 6, 22, 11, 4, 25,
+};
+
+static const uint8_t octeon_des_pc1[56] = {
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4,
+};
+
+static const uint8_t octeon_des_pc2[48] = {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32,
+};
+
+static const uint8_t octeon_des_rotations[16] = {
+ 1, 1, 2, 2, 2, 2, 2, 2,
+ 1, 2, 2, 2, 2, 2, 2, 1,
+};
+
+static const uint8_t octeon_des_sboxes[8][64] = {
+ {
+ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
+ },
+ {
+ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
+ },
+ {
+ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
+ },
+ {
+ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
+ },
+ {
+ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
+ },
+ {
+ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
+ },
+ {
+ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
+ },
+ {
+ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
+ },
+};
+
+static const uint8_t octeon_kasumi_s7[128] = {
+ 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18,
+ 123, 33, 55, 113, 39, 114, 21, 67, 65, 12, 47, 73, 46, 27,
+ 25, 111, 124, 81, 53, 9, 121, 79, 52, 60, 58, 48, 101, 127,
+ 40, 120, 104, 70, 71, 43, 20, 122, 72, 61, 23, 109, 13, 100,
+ 77, 1, 16, 7, 82, 10, 105, 98, 117, 116, 76, 11, 89, 106,
+ 0, 125, 118, 99, 86, 69, 30, 57, 126, 87, 112, 51, 17, 5,
+ 95, 14, 90, 84, 91, 8, 35, 103, 32, 97, 28, 66, 102, 31,
+ 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29, 115, 44,
+ 64, 107, 108, 24, 110, 83, 36, 78, 42, 19, 15, 41, 88, 119,
+ 59, 3,
+};
+
+static const uint16_t octeon_kasumi_s9[512] = {
+ 167, 239, 161, 379, 391, 334, 9, 338, 38, 226, 48, 358, 452, 385,
+ 90, 397, 183, 253, 147, 331, 415, 340, 51, 362, 306, 500, 262, 82,
+ 216, 159, 356, 177, 175, 241, 489, 37, 206, 17, 0, 333, 44, 254,
+ 378, 58, 143, 220, 81, 400, 95, 3, 315, 245, 54, 235, 218, 405,
+ 472, 264, 172, 494, 371, 290, 399, 76, 165, 197, 395, 121, 257, 480,
+ 423, 212, 240, 28, 462, 176, 406, 507, 288, 223, 501, 407, 249, 265,
+ 89, 186, 221, 428, 164, 74, 440, 196, 458, 421, 350, 163, 232, 158,
+ 134, 354, 13, 250, 491, 142, 191, 69, 193, 425, 152, 227, 366, 135,
+ 344, 300, 276, 242, 437, 320, 113, 278, 11, 243, 87, 317, 36, 93,
+ 496, 27, 487, 446, 482, 41, 68, 156, 457, 131, 326, 403, 339, 20,
+ 39, 115, 442, 124, 475, 384, 508, 53, 112, 170, 479, 151, 126, 169,
+ 73, 268, 279, 321, 168, 364, 363, 292, 46, 499, 393, 327, 324, 24,
+ 456, 267, 157, 460, 488, 426, 309, 229, 439, 506, 208, 271, 349, 401,
+ 434, 236, 16, 209, 359, 52, 56, 120, 199, 277, 465, 416, 252, 287,
+ 246, 6, 83, 305, 420, 345, 153, 502, 65, 61, 244, 282, 173, 222,
+ 418, 67, 386, 368, 261, 101, 476, 291, 195, 430, 49, 79, 166, 330,
+ 280, 383, 373, 128, 382, 408, 155, 495, 367, 388, 274, 107, 459, 417,
+ 62, 454, 132, 225, 203, 316, 234, 14, 301, 91, 503, 286, 424, 211,
+ 347, 307, 140, 374, 35, 103, 125, 427, 19, 214, 453, 146, 498, 314,
+ 444, 230, 256, 329, 198, 285, 50, 116, 78, 410, 10, 205, 510, 171,
+ 231, 45, 139, 467, 29, 86, 505, 32, 72, 26, 342, 150, 313, 490,
+ 431, 238, 411, 325, 149, 473, 40, 119, 174, 355, 185, 233, 389, 71,
+ 448, 273, 372, 55, 110, 178, 322, 12, 469, 392, 369, 190, 1, 109,
+ 375, 137, 181, 88, 75, 308, 260, 484, 98, 272, 370, 275, 412, 111,
+ 336, 318, 4, 504, 492, 259, 304, 77, 337, 435, 21, 357, 303, 332,
+ 483, 18, 47, 85, 25, 497, 474, 289, 100, 269, 296, 478, 270, 106,
+ 31, 104, 433, 84, 414, 486, 394, 96, 99, 154, 511, 148, 413, 361,
+ 409, 255, 162, 215, 302, 201, 266, 351, 343, 144, 441, 365, 108, 298,
+ 251, 34, 182, 509, 138, 210, 335, 133, 311, 352, 328, 141, 396, 346,
+ 123, 319, 450, 281, 429, 228, 443, 481, 92, 404, 485, 422, 248, 297,
+ 23, 213, 130, 466, 22, 217, 283, 70, 294, 360, 419, 127, 312, 377,
+ 7, 468, 194, 2, 117, 295, 463, 258, 224, 447, 247, 187, 80, 398,
+ 284, 353, 105, 390, 299, 471, 470, 184, 57, 200, 348, 63, 204, 188,
+ 33, 451, 97, 30, 310, 219, 94, 160, 129, 493, 64, 179, 263, 102,
+ 189, 207, 114, 402, 438, 477, 387, 122, 192, 42, 381, 5, 145, 118,
+ 180, 449, 293, 323, 136, 380, 43, 66, 60, 455, 341, 445, 202, 432,
+ 8, 237, 15, 376, 436, 464, 59, 461,
+};
+
+static const uint16_t octeon_kasumi_constants[8] = {
+ 0x0123, 0x4567, 0x89ab, 0xcdef, 0xfedc, 0xba98, 0x7654, 0x3210,
+};
+
+typedef struct OcteonKasumiSubkeys {
+ uint16_t kli1[8];
+ uint16_t kli2[8];
+ uint16_t koi1[8];
+ uint16_t koi2[8];
+ uint16_t koi3[8];
+ uint16_t kii1[8];
+ uint16_t kii2[8];
+ uint16_t kii3[8];
+} OcteonKasumiSubkeys;
+
+static uint64_t octeon_des_permute(uint64_t input, const uint8_t *table,
+ size_t output_bits, size_t input_bits)
+{
+ uint64_t out = 0;
+
+ for (size_t i = 0; i < output_bits; i++) {
+ unsigned src = table[i] - 1;
+
+ out = (out << 1) | ((input >> (input_bits - 1 - src)) & 1);
+ }
+ return out;
+}
+
+static uint32_t octeon_des_rotate28(uint32_t v, unsigned shift)
+{
+ return ((v << shift) | (v >> (28 - shift))) & 0x0fffffffU;
+}
+
+static void octeon_des_expand_subkeys(uint64_t key, uint64_t subkeys[16])
+{
+ uint64_t permuted = octeon_des_permute(key, octeon_des_pc1,
+ ARRAY_SIZE(octeon_des_pc1), 64);
+ uint32_t c = (permuted >> 28) & 0x0fffffffU;
+ uint32_t d = permuted & 0x0fffffffU;
+
+ for (int i = 0; i < 16; i++) {
+ c = octeon_des_rotate28(c, octeon_des_rotations[i]);
+ d = octeon_des_rotate28(d, octeon_des_rotations[i]);
+ subkeys[i] = octeon_des_permute(((uint64_t)c << 28) | d,
+ octeon_des_pc2,
+ ARRAY_SIZE(octeon_des_pc2), 56);
+ }
+}
+
+static uint32_t octeon_des_f(uint32_t r, uint64_t subkey)
+{
+ uint64_t expanded = octeon_des_permute(r, octeon_des_e,
+ ARRAY_SIZE(octeon_des_e), 32);
+ uint32_t out = 0;
+
+ expanded ^= subkey;
+ for (int i = 0; i < 8; i++) {
+ uint8_t sextet = (expanded >> (42 - i * 6)) & 0x3f;
+ uint8_t row = ((sextet & 0x20) >> 4) | (sextet & 0x01);
+ uint8_t col = (sextet >> 1) & 0x0f;
+
+ out = (out << 4) | octeon_des_sboxes[i][row * 16 + col];
+ }
+
+ return octeon_des_permute(out, octeon_des_p, ARRAY_SIZE(octeon_des_p), 32);
+}
+
+static uint64_t octeon_des_block_crypt(uint64_t block, uint64_t key,
+ bool encrypt)
+{
+ uint64_t subkeys[16];
+ uint64_t permuted = octeon_des_permute(block, octeon_des_ip,
+ ARRAY_SIZE(octeon_des_ip), 64);
+ uint32_t l = permuted >> 32;
+ uint32_t r = permuted;
+
+ octeon_des_expand_subkeys(key, subkeys);
+
+ for (int i = 0; i < 16; i++) {
+ uint32_t next = l ^ octeon_des_f(r, subkeys[encrypt ? i : 15 - i]);
+
+ l = r;
+ r = next;
+ }
+
+ return octeon_des_permute(((uint64_t)r << 32) | l,
+ octeon_des_fp, ARRAY_SIZE(octeon_des_fp), 64);
+}
+
+static uint64_t octeon_3des_block_crypt(uint64_t block, const uint64_t keys[3],
+ bool encrypt)
+{
+ if (encrypt) {
+ block = octeon_des_block_crypt(block, keys[0], true);
+ block = octeon_des_block_crypt(block, keys[1], false);
+ block = octeon_des_block_crypt(block, keys[2], true);
+ } else {
+ block = octeon_des_block_crypt(block, keys[2], false);
+ block = octeon_des_block_crypt(block, keys[1], true);
+ block = octeon_des_block_crypt(block, keys[0], false);
+ }
+ return block;
+}
+
+static void octeon_3des_crypt_common(MIPSOcteonCryptoState *crypto,
+ uint64_t input_reg,
+ bool encrypt, bool cbc)
+{
+ const uint64_t keys[3] = {
+ crypto->des3_key[0],
+ crypto->des3_key[1],
+ crypto->des3_key[2],
+ };
+ uint64_t block = input_reg;
+
+ if (cbc) {
+ if (encrypt) {
+ block ^= crypto->des3_iv;
+ block = octeon_3des_block_crypt(block, keys, true);
+ crypto->des3_iv = block;
+ } else {
+ block = octeon_3des_block_crypt(block, keys, false);
+ block ^= crypto->des3_iv;
+ crypto->des3_iv = input_reg;
+ }
+ } else {
+ block = octeon_3des_block_crypt(block, keys, encrypt);
+ }
+
+ crypto->des3_result = block;
+}
+
+static uint16_t octeon_rol16(uint16_t value, unsigned int bits)
+{
+ return (value << bits) | (value >> (16 - bits));
+}
+
+static void octeon_kasumi_key_schedule(const uint64_t key_regs[2],
+ OcteonKasumiSubkeys *subkeys)
+{
+ uint16_t key[8];
+ uint16_t key_prime[8];
+
+ key[0] = key_regs[0] >> 48;
+ key[1] = key_regs[0] >> 32;
+ key[2] = key_regs[0] >> 16;
+ key[3] = key_regs[0];
+ key[4] = key_regs[1] >> 48;
+ key[5] = key_regs[1] >> 32;
+ key[6] = key_regs[1] >> 16;
+ key[7] = key_regs[1];
+
+ for (int i = 0; i < 8; i++) {
+ key_prime[i] = key[i] ^ octeon_kasumi_constants[i];
+ }
+
+ for (int i = 0; i < 8; i++) {
+ subkeys->kli1[i] = octeon_rol16(key[i], 1);
+ subkeys->kli2[i] = key_prime[(i + 2) & 7];
+ subkeys->koi1[i] = octeon_rol16(key[(i + 1) & 7], 5);
+ subkeys->koi2[i] = octeon_rol16(key[(i + 5) & 7], 8);
+ subkeys->koi3[i] = octeon_rol16(key[(i + 6) & 7], 13);
+ subkeys->kii1[i] = key_prime[(i + 4) & 7];
+ subkeys->kii2[i] = key_prime[(i + 3) & 7];
+ subkeys->kii3[i] = key_prime[(i + 7) & 7];
+ }
+}
+
+static uint16_t octeon_kasumi_fi(uint16_t in, uint16_t subkey)
+{
+ uint16_t nine = in >> 7;
+ uint16_t seven = in & 0x7f;
+
+ nine = octeon_kasumi_s9[nine] ^ seven;
+ seven = octeon_kasumi_s7[seven] ^ (nine & 0x7f);
+ seven ^= subkey >> 9;
+ nine ^= subkey & 0x1ff;
+ nine = octeon_kasumi_s9[nine] ^ seven;
+ seven = octeon_kasumi_s7[seven] ^ (nine & 0x7f);
+ return (seven << 9) | nine;
+}
+
+static uint32_t octeon_kasumi_fo(uint32_t in, int index,
+ const OcteonKasumiSubkeys *subkeys)
+{
+ uint16_t left = in >> 16;
+ uint16_t right = in;
+
+ left ^= subkeys->koi1[index];
+ left = octeon_kasumi_fi(left, subkeys->kii1[index]);
+ left ^= right;
+ right ^= subkeys->koi2[index];
+ right = octeon_kasumi_fi(right, subkeys->kii2[index]);
+ right ^= left;
+ left ^= subkeys->koi3[index];
+ left = octeon_kasumi_fi(left, subkeys->kii3[index]);
+ left ^= right;
+
+ return ((uint32_t)right << 16) | left;
+}
+
+static uint32_t octeon_kasumi_fl(uint32_t in, int index,
+ const OcteonKasumiSubkeys *subkeys)
+{
+ uint16_t left = in >> 16;
+ uint16_t right = in;
+ uint16_t a = left & subkeys->kli1[index];
+ uint16_t b;
+
+ right ^= octeon_rol16(a, 1);
+ b = right | subkeys->kli2[index];
+ left ^= octeon_rol16(b, 1);
+ return ((uint32_t)left << 16) | right;
+}
+
+static uint64_t octeon_kasumi_block_encrypt(uint64_t block,
+ const uint64_t key_regs[2])
+{
+ OcteonKasumiSubkeys subkeys;
+ uint32_t left = block >> 32;
+ uint32_t right = block;
+
+ octeon_kasumi_key_schedule(key_regs, &subkeys);
+
+ for (int i = 0; i < 8; ) {
+ uint32_t temp = octeon_kasumi_fl(left, i, &subkeys);
+
+ temp = octeon_kasumi_fo(temp, i++, &subkeys);
+ right ^= temp;
+ temp = octeon_kasumi_fo(right, i, &subkeys);
+ temp = octeon_kasumi_fl(temp, i++, &subkeys);
+ left ^= temp;
+ }
+
+ return ((uint64_t)left << 32) | right;
+}
+
+static void octeon_kasumi_crypt_common(MIPSOcteonCryptoState *crypto,
+ uint64_t input_reg, bool cbc)
+{
+ const uint64_t key_regs[2] = {
+ crypto->des3_key[0],
+ crypto->des3_key[1],
+ };
+ uint64_t block = input_reg;
+
+ if (cbc) {
+ block ^= crypto->des3_iv;
+ }
+
+ block = octeon_kasumi_block_encrypt(block, key_regs);
+ if (cbc) {
+ crypto->des3_iv = block;
+ }
+ crypto->des3_result = block;
+}
+
+void helper_octeon_cp2_mt_des3_enc_cbc(CPUMIPSState *env, uint64_t value)
+{
+ octeon_3des_crypt_common(&env->octeon_crypto, value, true, true);
+}
+
+void helper_octeon_cp2_mt_kas_enc_cbc(CPUMIPSState *env, uint64_t value)
+{
+ octeon_kasumi_crypt_common(&env->octeon_crypto, value, true);
+}
+
+void helper_octeon_cp2_mt_des3_enc(CPUMIPSState *env, uint64_t value)
+{
+ octeon_3des_crypt_common(&env->octeon_crypto, value, true, false);
+}
+
+void helper_octeon_cp2_mt_kas_enc(CPUMIPSState *env, uint64_t value)
+{
+ octeon_kasumi_crypt_common(&env->octeon_crypto, value, false);
+}
+
+void helper_octeon_cp2_mt_des3_dec_cbc(CPUMIPSState *env, uint64_t value)
+{
+ octeon_3des_crypt_common(&env->octeon_crypto, value, false, true);
+}
+
+void helper_octeon_cp2_mt_des3_dec(CPUMIPSState *env, uint64_t value)
+{
+ octeon_3des_crypt_common(&env->octeon_crypto, value, false, false);
+}
+
void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
{
octeon_snow3g_start(&env->octeon_crypto, value);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 11/23] target/mips: add Octeon Camellia COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (9 preceding siblings ...)
2026-07-07 18:15 ` [PULL 10/23] target/mips: add Octeon 3DES and KASUMI " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 12/23] target/mips: add Octeon HSH " Philippe Mathieu-Daudé
` (13 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add helper support for the Octeon Camellia ROUND, FL, and FLINV
selectors. The engine reuses the AES RESINP bank, and guest-managed key
schedules drive the Camellia F-function and FL layers through these COP2
operations.
Implement the Camellia F-function and FL layers directly from RFC 3713.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-11-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 3 +
target/mips/tcg/octeon_crypto.c | 126 ++++++++++++++++++++++++++++++++
2 files changed, 129 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index c9332c5c522..71b7a2b30ec 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -66,6 +66,9 @@ DEF_HELPER_2(octeon_cp2_mt_des3_enc, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_kas_enc, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_des3_dec_cbc, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_des3_dec, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_camellia_fl, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_camellia_flinv, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_camellia_round, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index 8ea79e37568..430feaf5f4f 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -1566,6 +1566,132 @@ void helper_octeon_cp2_mt_des3_dec(CPUMIPSState *env, uint64_t value)
octeon_3des_crypt_common(&env->octeon_crypto, value, false, false);
}
+static const uint8_t camellia_sbox1[256] = {
+ 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12,
+ 174, 65, 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78,
+ 29, 101, 146, 189, 134, 184, 175, 143, 124, 235, 31, 206, 62, 48,
+ 220, 95, 94, 197, 11, 26, 166, 225, 57, 202, 213, 71, 93, 61,
+ 217, 1, 90, 214, 81, 86, 108, 77, 139, 13, 154, 102, 251, 204,
+ 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, 223, 76, 203, 194,
+ 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, 20, 88,
+ 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,
+ 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252,
+ 105, 80, 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149,
+ 224, 255, 100, 210, 16, 196, 0, 72, 163, 247, 117, 219, 138, 3,
+ 230, 218, 9, 63, 221, 148, 135, 92, 131, 2, 205, 74, 144, 51,
+ 115, 103, 246, 243, 157, 127, 191, 226, 82, 155, 216, 38, 200, 55,
+ 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, 233, 121, 167, 140,
+ 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, 120, 152,
+ 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,
+ 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56,
+ 241, 164, 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244,
+ 119, 199, 128, 158,
+};
+
+static uint8_t camellia_rotl8(uint8_t v, unsigned int shift)
+{
+ return (v << shift) | (v >> (8 - shift));
+}
+
+static uint8_t camellia_sbox2(uint8_t x)
+{
+ return camellia_rotl8(camellia_sbox1[x], 1);
+}
+
+static uint8_t camellia_sbox3(uint8_t x)
+{
+ return camellia_rotl8(camellia_sbox1[x], 7);
+}
+
+static uint8_t camellia_sbox4(uint8_t x)
+{
+ return camellia_sbox1[camellia_rotl8(x, 1)];
+}
+
+static uint64_t camellia_f(uint64_t input, uint64_t key)
+{
+ uint64_t x = input ^ key;
+ uint8_t t1 = camellia_sbox1[x >> 56];
+ uint8_t t2 = camellia_sbox2((x >> 48) & 0xff);
+ uint8_t t3 = camellia_sbox3((x >> 40) & 0xff);
+ uint8_t t4 = camellia_sbox4((x >> 32) & 0xff);
+ uint8_t t5 = camellia_sbox2((x >> 24) & 0xff);
+ uint8_t t6 = camellia_sbox3((x >> 16) & 0xff);
+ uint8_t t7 = camellia_sbox4((x >> 8) & 0xff);
+ uint8_t t8 = camellia_sbox1[x & 0xff];
+ uint8_t y1 = t1 ^ t3 ^ t4 ^ t6 ^ t7 ^ t8;
+ uint8_t y2 = t1 ^ t2 ^ t4 ^ t5 ^ t7 ^ t8;
+ uint8_t y3 = t1 ^ t2 ^ t3 ^ t5 ^ t6 ^ t8;
+ uint8_t y4 = t2 ^ t3 ^ t4 ^ t5 ^ t6 ^ t7;
+ uint8_t y5 = t1 ^ t2 ^ t6 ^ t7 ^ t8;
+ uint8_t y6 = t2 ^ t3 ^ t5 ^ t7 ^ t8;
+ uint8_t y7 = t3 ^ t4 ^ t5 ^ t6 ^ t8;
+ uint8_t y8 = t1 ^ t4 ^ t5 ^ t6 ^ t7;
+
+ return ((uint64_t)y1 << 56) | ((uint64_t)y2 << 48) |
+ ((uint64_t)y3 << 40) | ((uint64_t)y4 << 32) |
+ ((uint64_t)y5 << 24) | ((uint64_t)y6 << 16) |
+ ((uint64_t)y7 << 8) | y8;
+}
+
+static uint64_t camellia_fl(uint64_t input, uint64_t key)
+{
+ uint32_t x1 = input >> 32;
+ uint32_t x2 = input;
+ uint32_t k1 = key >> 32;
+ uint32_t k2 = key;
+
+ x2 ^= rol32(x1 & k1, 1);
+ x1 ^= x2 | k2;
+ return ((uint64_t)x1 << 32) | x2;
+}
+
+static uint64_t camellia_flinv(uint64_t input, uint64_t key)
+{
+ uint32_t y1 = input >> 32;
+ uint32_t y2 = input;
+ uint32_t k1 = key >> 32;
+ uint32_t k2 = key;
+
+ y1 ^= y2 | k2;
+ y2 ^= rol32(y1 & k1, 1);
+ return ((uint64_t)y1 << 32) | y2;
+}
+
+static void octeon_camellia_round(MIPSOcteonCryptoState *crypto, uint64_t key)
+{
+ uint64_t left = crypto->aes_resinp[0];
+ uint64_t right = crypto->aes_resinp[1];
+
+ crypto->aes_resinp[0] = right ^ camellia_f(left, key);
+ crypto->aes_resinp[1] = left;
+}
+
+static void octeon_camellia_fl_layer(MIPSOcteonCryptoState *crypto,
+ uint64_t key, bool inverse)
+{
+ uint64_t state = crypto->aes_resinp[inverse ? 1 : 0];
+
+ crypto->aes_resinp[inverse ? 1 : 0] = inverse ?
+ camellia_flinv(state, key) :
+ camellia_fl(state, key);
+}
+
+void helper_octeon_cp2_mt_camellia_fl(CPUMIPSState *env, uint64_t value)
+{
+ octeon_camellia_fl_layer(&env->octeon_crypto, value, false);
+}
+
+void helper_octeon_cp2_mt_camellia_flinv(CPUMIPSState *env, uint64_t value)
+{
+ octeon_camellia_fl_layer(&env->octeon_crypto, value, true);
+}
+
+void helper_octeon_cp2_mt_camellia_round(CPUMIPSState *env, uint64_t value)
+{
+ octeon_camellia_round(&env->octeon_crypto, value);
+}
+
void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
{
octeon_snow3g_start(&env->octeon_crypto, value);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 12/23] target/mips: add Octeon HSH COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (10 preceding siblings ...)
2026-07-07 18:15 ` [PULL 11/23] target/mips: add Octeon Camellia " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 13/23] target/mips: add Octeon CHORD and LLM " Philippe Mathieu-Daudé
` (12 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add helper support for the Octeon HSH hash selectors. This includes the
base HSH data/IV windows, MD5, SHA1, SHA256, and SHA512 transform paths,
and the shared HSH/SHA512 register-window readback and write operations.
The SHA512 path shares the wide HSH register bank with SHA3, SNOW3G, and
ZUC. Keep the aliased readback and write paths centralized so selector
decode can route register accesses through these helpers when side
effects are required.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-12-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 5 +
target/mips/tcg/octeon_crypto.c | 373 ++++++++++++++++++++++++++++++++
2 files changed, 378 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 71b7a2b30ec..834f2d07690 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -69,6 +69,11 @@ DEF_HELPER_2(octeon_cp2_mt_des3_dec, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_camellia_fl, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_camellia_flinv, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_camellia_round, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startsha1_compat, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startmd5, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startsha256, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startsha, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startsha512, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index 430feaf5f4f..82ad355d56f 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -153,6 +153,346 @@ static void octeon_gfm_mul64_uia2(const uint64_t x[2], const uint64_t y[2],
out[1] = revbit64(res);
}
+static uint32_t octeon_hsh_get32(const uint64_t *regs, unsigned int index)
+{
+ return regs[index];
+}
+
+static void octeon_hsh_set32(uint64_t *regs, unsigned int index, uint32_t value)
+{
+ regs[index] = (regs[index] & ~(uint64_t)UINT32_MAX) | value;
+}
+
+static void octeon_hsh_set_pair(uint64_t *regs, unsigned int index,
+ uint64_t value)
+{
+ octeon_hsh_set32(regs, index * 2, value >> 32);
+ octeon_hsh_set32(regs, index * 2 + 1, value);
+}
+
+static void octeon_md5_transform(MIPSOcteonCryptoState *crypto)
+{
+ static const uint32_t k[64] = {
+ 0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU,
+ 0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U,
+ 0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU,
+ 0x6b901122U, 0xfd987193U, 0xa679438eU, 0x49b40821U,
+ 0xf61e2562U, 0xc040b340U, 0x265e5a51U, 0xe9b6c7aaU,
+ 0xd62f105dU, 0x02441453U, 0xd8a1e681U, 0xe7d3fbc8U,
+ 0x21e1cde6U, 0xc33707d6U, 0xf4d50d87U, 0x455a14edU,
+ 0xa9e3e905U, 0xfcefa3f8U, 0x676f02d9U, 0x8d2a4c8aU,
+ 0xfffa3942U, 0x8771f681U, 0x6d9d6122U, 0xfde5380cU,
+ 0xa4beea44U, 0x4bdecfa9U, 0xf6bb4b60U, 0xbebfbc70U,
+ 0x289b7ec6U, 0xeaa127faU, 0xd4ef3085U, 0x04881d05U,
+ 0xd9d4d039U, 0xe6db99e5U, 0x1fa27cf8U, 0xc4ac5665U,
+ 0xf4292244U, 0x432aff97U, 0xab9423a7U, 0xfc93a039U,
+ 0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU, 0x85845dd1U,
+ 0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U,
+ 0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U,
+ };
+ static const uint8_t s[64] = {
+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
+ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
+ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
+ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
+ };
+ uint32_t m[16];
+ uint32_t a, b, c, d;
+ uint32_t aa, bb, cc, dd;
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ m[i] = bswap32(octeon_hsh_get32(crypto->hsh_dat, i));
+ }
+
+ a = bswap32(octeon_hsh_get32(crypto->hsh_iv, 0));
+ b = bswap32(octeon_hsh_get32(crypto->hsh_iv, 1));
+ c = bswap32(octeon_hsh_get32(crypto->hsh_iv, 2));
+ d = bswap32(octeon_hsh_get32(crypto->hsh_iv, 3));
+ aa = a;
+ bb = b;
+ cc = c;
+ dd = d;
+
+ for (i = 0; i < 64; i++) {
+ uint32_t f, g, tmp;
+
+ if (i < 16) {
+ f = (b & c) | ((~b) & d);
+ g = i;
+ } else if (i < 32) {
+ f = (d & b) | ((~d) & c);
+ g = (5 * i + 1) & 0xf;
+ } else if (i < 48) {
+ f = b ^ c ^ d;
+ g = (3 * i + 5) & 0xf;
+ } else {
+ f = c ^ (b | (~d));
+ g = (7 * i) & 0xf;
+ }
+
+ tmp = d;
+ d = c;
+ c = b;
+ b = b + rol32(a + f + k[i] + m[g], s[i]);
+ a = tmp;
+ }
+
+ a += aa;
+ b += bb;
+ c += cc;
+ d += dd;
+ octeon_hsh_set32(crypto->hsh_iv, 0, bswap32(a));
+ octeon_hsh_set32(crypto->hsh_iv, 1, bswap32(b));
+ octeon_hsh_set32(crypto->hsh_iv, 2, bswap32(c));
+ octeon_hsh_set32(crypto->hsh_iv, 3, bswap32(d));
+}
+
+static void octeon_sha1_transform(MIPSOcteonCryptoState *crypto)
+{
+ uint32_t w[80];
+ uint32_t a, b, c, d, e;
+ uint32_t orig[5];
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ w[i] = octeon_hsh_get32(crypto->hsh_dat, i);
+ }
+ for (i = 16; i < 80; i++) {
+ w[i] = rol32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
+ }
+
+ for (i = 0; i < 5; i++) {
+ orig[i] = octeon_hsh_get32(crypto->hsh_iv, i);
+ }
+ a = orig[0];
+ b = orig[1];
+ c = orig[2];
+ d = orig[3];
+ e = orig[4];
+
+ for (i = 0; i < 80; i++) {
+ uint32_t f, k, temp;
+
+ if (i < 20) {
+ f = (b & c) | ((~b) & d);
+ k = 0x5a827999;
+ } else if (i < 40) {
+ f = b ^ c ^ d;
+ k = 0x6ed9eba1;
+ } else if (i < 60) {
+ f = (b & c) | (b & d) | (c & d);
+ k = 0x8f1bbcdc;
+ } else {
+ f = b ^ c ^ d;
+ k = 0xca62c1d6;
+ }
+
+ temp = rol32(a, 5) + f + e + k + w[i];
+ e = d;
+ d = c;
+ c = rol32(b, 30);
+ b = a;
+ a = temp;
+ }
+
+ orig[0] += a;
+ orig[1] += b;
+ orig[2] += c;
+ orig[3] += d;
+ orig[4] += e;
+ for (i = 0; i < 5; i++) {
+ octeon_hsh_set32(crypto->hsh_iv, i, orig[i]);
+ }
+}
+
+static void octeon_sha256_transform(MIPSOcteonCryptoState *crypto)
+{
+ static const uint32_t k[64] = {
+ 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U,
+ 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
+ 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U,
+ 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
+ 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
+ 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
+ 0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
+ 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
+ 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,
+ 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
+ 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U,
+ 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
+ 0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U,
+ 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
+ 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
+ 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U,
+ };
+ uint32_t w[64];
+ uint32_t a, b, c, d, e, f, g, h;
+ uint32_t orig[8];
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ w[i] = octeon_hsh_get32(crypto->hsh_dat, i);
+ }
+ for (i = 16; i < 64; i++) {
+ uint32_t s0 = ror32(w[i - 15], 7) ^
+ ror32(w[i - 15], 18) ^
+ (w[i - 15] >> 3);
+ uint32_t s1 = ror32(w[i - 2], 17) ^
+ ror32(w[i - 2], 19) ^
+ (w[i - 2] >> 10);
+ w[i] = w[i - 16] + s0 + w[i - 7] + s1;
+ }
+
+ for (i = 0; i < 8; i++) {
+ orig[i] = octeon_hsh_get32(crypto->hsh_iv, i);
+ }
+ a = orig[0];
+ b = orig[1];
+ c = orig[2];
+ d = orig[3];
+ e = orig[4];
+ f = orig[5];
+ g = orig[6];
+ h = orig[7];
+
+ for (i = 0; i < 64; i++) {
+ uint32_t s1 = ror32(e, 6) ^
+ ror32(e, 11) ^
+ ror32(e, 25);
+ uint32_t ch = (e & f) ^ ((~e) & g);
+ uint32_t temp1 = h + s1 + ch + k[i] + w[i];
+ uint32_t s0 = ror32(a, 2) ^
+ ror32(a, 13) ^
+ ror32(a, 22);
+ uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
+ uint32_t temp2 = s0 + maj;
+
+ h = g;
+ g = f;
+ f = e;
+ e = d + temp1;
+ d = c;
+ c = b;
+ b = a;
+ a = temp1 + temp2;
+ }
+
+ orig[0] += a;
+ orig[1] += b;
+ orig[2] += c;
+ orig[3] += d;
+ orig[4] += e;
+ orig[5] += f;
+ orig[6] += g;
+ orig[7] += h;
+ for (i = 0; i < 8; i++) {
+ octeon_hsh_set32(crypto->hsh_iv, i, orig[i]);
+ }
+}
+
+static void octeon_sha512_transform(MIPSOcteonCryptoState *crypto)
+{
+ static const uint64_t k[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
+ };
+ uint64_t w[80];
+ uint64_t a, b, c, d, e, f, g, h;
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ w[i] = crypto->hsh_dat[i];
+ }
+ for (i = 16; i < 80; i++) {
+ uint64_t s0 = ror64(w[i - 15], 1) ^
+ ror64(w[i - 15], 8) ^
+ (w[i - 15] >> 7);
+ uint64_t s1 = ror64(w[i - 2], 19) ^
+ ror64(w[i - 2], 61) ^
+ (w[i - 2] >> 6);
+ w[i] = w[i - 16] + s0 + w[i - 7] + s1;
+ }
+
+ a = crypto->hsh_iv[0];
+ b = crypto->hsh_iv[1];
+ c = crypto->hsh_iv[2];
+ d = crypto->hsh_iv[3];
+ e = crypto->hsh_iv[4];
+ f = crypto->hsh_iv[5];
+ g = crypto->hsh_iv[6];
+ h = crypto->hsh_iv[7];
+
+ for (i = 0; i < 80; i++) {
+ uint64_t s0 = ror64(a, 28) ^
+ ror64(a, 34) ^
+ ror64(a, 39);
+ uint64_t s1 = ror64(e, 14) ^
+ ror64(e, 18) ^
+ ror64(e, 41);
+ uint64_t ch = (e & f) ^ ((~e) & g);
+ uint64_t maj = (a & b) ^ (a & c) ^ (b & c);
+ uint64_t temp1 = h + s1 + ch + k[i] + w[i];
+ uint64_t temp2 = s0 + maj;
+
+ h = g;
+ g = f;
+ f = e;
+ e = d + temp1;
+ d = c;
+ c = b;
+ b = a;
+ a = temp1 + temp2;
+ }
+
+ crypto->hsh_iv[0] += a;
+ crypto->hsh_iv[1] += b;
+ crypto->hsh_iv[2] += c;
+ crypto->hsh_iv[3] += d;
+ crypto->hsh_iv[4] += e;
+ crypto->hsh_iv[5] += f;
+ crypto->hsh_iv[6] += g;
+ crypto->hsh_iv[7] += h;
+}
+
static const uint64_t octeon_sha3_round_constants[24] = {
0x0000000000000001ULL, 0x0000000000008082ULL,
0x800000000000808aULL, 0x8000000080008000ULL,
@@ -1713,6 +2053,39 @@ void helper_octeon_cp2_mt_zuc_more(CPUMIPSState *env, uint64_t value)
octeon_zuc_more(&env->octeon_crypto, value);
}
+void helper_octeon_cp2_mt_hsh_startsha1_compat(CPUMIPSState *env,
+ uint64_t value)
+{
+ octeon_hsh_set_pair(env->octeon_crypto.hsh_dat, 7, value);
+ octeon_sha1_transform(&env->octeon_crypto);
+}
+
+void helper_octeon_cp2_mt_hsh_startmd5(CPUMIPSState *env, uint64_t value)
+{
+ octeon_hsh_set_pair(env->octeon_crypto.hsh_dat, 7, value);
+ octeon_md5_transform(&env->octeon_crypto);
+}
+
+void helper_octeon_cp2_mt_hsh_startsha256(CPUMIPSState *env, uint64_t value)
+{
+ octeon_hsh_set_pair(env->octeon_crypto.hsh_dat, 7, value);
+ octeon_sha256_transform(&env->octeon_crypto);
+}
+
+void helper_octeon_cp2_mt_hsh_startsha(CPUMIPSState *env, uint64_t value)
+{
+ octeon_hsh_set_pair(env->octeon_crypto.hsh_dat, 7, value);
+ octeon_sha1_transform(&env->octeon_crypto);
+}
+
+void helper_octeon_cp2_mt_hsh_startsha512(CPUMIPSState *env, uint64_t value)
+{
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+ crypto->hsh_dat[15] = value;
+ octeon_sha512_transform(crypto);
+}
+
uint64_t helper_octeon_cp2_mf_crc_iv_reflect(CPUMIPSState *env)
{
return octeon_crc_reflect32_by_byte(env->octeon_crypto.crc_iv);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 13/23] target/mips: add Octeon CHORD and LLM COP2 helpers
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (11 preceding siblings ...)
2026-07-07 18:15 ` [PULL 12/23] target/mips: add Octeon HSH " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 14/23] target/mips: decode Octeon COP2 register selectors Philippe Mathieu-Daudé
` (11 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add the Octeon CHORD hardware register access path and the LLM 36-bit
and 64-bit read and write windows. Model both CHORD access forms,
including the RDHWR $30 path and the legacy DMFC2 alias.
Implement sparse backing storage for the two LLM sets so user-mode code
can save, restore, and probe the architectural state without allocating a
full hardware-sized backing array.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-13-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/cpu.h | 5 +++
target/mips/helper.h | 9 ++++
target/mips/internal.h | 3 ++
target/mips/cpu.c | 67 +++++++++++++++++++++++++++++
target/mips/system/machine.c | 67 +++++++++++++++++++++++++++++
target/mips/tcg/octeon_crypto.c | 76 +++++++++++++++++++++++++++++++++
target/mips/tcg/op_helper.c | 6 +++
target/mips/tcg/translate.c | 8 ++++
8 files changed, 241 insertions(+)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 3df71adf9bd..319147a948c 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -11,6 +11,7 @@
#include "fpu/softfloat-types.h"
#include "hw/core/clock.h"
#include "mips-defs.h"
+#include "qemu/qtree.h"
typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
@@ -559,6 +560,10 @@ typedef struct MIPSOcteonCryptoState {
uint16_t gfm_poly;
uint8_t aes_keylen;
uint8_t crc_len;
+ uint64_t chord;
+ uint64_t llm_data[2];
+ QTree *llm36;
+ QTree *llm64;
} MIPSOcteonCryptoState;
typedef struct CPUArchState {
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 834f2d07690..e210e406f9c 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -74,6 +74,14 @@ DEF_HELPER_2(octeon_cp2_mt_hsh_startmd5, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_hsh_startsha256, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_hsh_startsha, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_hsh_startsha512, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_llm_read_addr0, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_llm_write_addr0, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_llm_read64_addr0, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_llm_write64_addr0, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_llm_read_addr1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_llm_write_addr1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_llm_read64_addr1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_llm_write64_addr1, void, env, i64)
/* microMIPS functions */
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
@@ -245,6 +253,7 @@ DEF_HELPER_1(rdhwr_cc, tl, env)
DEF_HELPER_1(rdhwr_ccres, tl, env)
DEF_HELPER_1(rdhwr_performance, tl, env)
DEF_HELPER_1(rdhwr_xnp, tl, env)
+DEF_HELPER_1(rdhwr_chord, tl, env)
DEF_HELPER_2(pmon, void, env, int)
DEF_HELPER_1(wait, void, env)
diff --git a/target/mips/internal.h b/target/mips/internal.h
index aab77b1b257..c5c286872eb 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -93,6 +93,9 @@ extern const int mips_defs_number;
int mips_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+QTree *mips_octeon_llm_tree_new(void);
+uint64_t mips_octeon_llm_load(QTree *tree, uint64_t addr);
+void mips_octeon_llm_store(QTree **treep, uint64_t addr, uint64_t value);
#define USEG_LIMIT ((target_ulong)(int32_t)0x7FFFFFFFUL)
#define KSEG0_BASE ((target_ulong)(int32_t)0x80000000UL)
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index fccc7a711d3..b223b767c9c 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -26,6 +26,7 @@
#include "cpu.h"
#include "internal.h"
#include "qemu/module.h"
+#include "qemu/qtree.h"
#include "system/qtest.h"
#include "hw/core/qdev-properties.h"
#include "hw/core/qdev-clock.h"
@@ -181,6 +182,57 @@ static bool mips_cpu_has_work(CPUState *cs)
#include "cpu-defs.c.inc"
+static gint mips_octeon_u64_tree_compare(gconstpointer a, gconstpointer b,
+ gpointer user_data)
+{
+ uint64_t av = *(const uint64_t *)a;
+ uint64_t bv = *(const uint64_t *)b;
+
+ return (av > bv) - (av < bv);
+}
+
+QTree *mips_octeon_llm_tree_new(void)
+{
+ return q_tree_new_full(mips_octeon_u64_tree_compare,
+ NULL, g_free, g_free);
+}
+
+uint64_t mips_octeon_llm_load(QTree *tree, uint64_t addr)
+{
+ uint64_t key = addr;
+ uint64_t *value = tree ? q_tree_lookup(tree, &key) : NULL;
+
+ return value ? *value : 0;
+}
+
+void mips_octeon_llm_store(QTree **treep, uint64_t addr, uint64_t value)
+{
+ uint64_t *key;
+ uint64_t *stored;
+
+ if (!*treep) {
+ *treep = mips_octeon_llm_tree_new();
+ }
+
+ key = g_new(uint64_t, 1);
+ stored = g_new(uint64_t, 1);
+ *key = addr;
+ *stored = value;
+ q_tree_replace(*treep, key, stored);
+}
+
+static void mips_octeon_destroy_llm_state(MIPSOcteonCryptoState *crypto)
+{
+ if (crypto->llm36) {
+ q_tree_destroy(crypto->llm36);
+ crypto->llm36 = NULL;
+ }
+ if (crypto->llm64) {
+ q_tree_destroy(crypto->llm64);
+ crypto->llm64 = NULL;
+ }
+}
+
static void mips_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
@@ -192,6 +244,7 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
mcc->parent_phases.hold(obj, type);
}
+ mips_octeon_destroy_llm_state(&env->octeon_crypto);
memset(env, 0, offsetof(CPUMIPSState, end_reset_fields));
/* Reset registers to their default values */
@@ -246,6 +299,9 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
env->msair = env->cpu_model->MSAIR;
env->insn_flags = env->cpu_model->insn_flags;
+ if (env->insn_flags & INSN_OCTEON) {
+ env->octeon_crypto.chord = 1;
+ }
#if defined(CONFIG_USER_ONLY)
env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
@@ -262,6 +318,9 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
* hardware registers.
*/
env->CP0_HWREna |= 0x0000000F;
+ if (env->insn_flags & INSN_OCTEON) {
+ env->CP0_HWREna |= 0x40000000u;
+ }
if (env->CP0_Config1 & (1 << CP0C1_FP)) {
env->CP0_Status |= (1 << CP0St_CU1);
}
@@ -417,6 +476,13 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
#endif
}
+static void mips_cpu_finalize(Object *obj)
+{
+ MIPSCPU *cpu = MIPS_CPU(obj);
+
+ mips_octeon_destroy_llm_state(&cpu->env.octeon_crypto);
+}
+
static void mips_cpu_disas_set_info(const CPUState *cs, disassemble_info *info)
{
const MIPSCPU *cpu = MIPS_CPU(cs);
@@ -645,6 +711,7 @@ static const TypeInfo mips_cpu_type_info = {
.instance_size = sizeof(MIPSCPU),
.instance_align = __alignof(MIPSCPU),
.instance_init = mips_cpu_initfn,
+ .instance_finalize = mips_cpu_finalize,
.abstract = true,
.class_size = sizeof(MIPSCPUClass),
.class_init = mips_cpu_class_init,
diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c
index 77f576a25b1..bd1e4002cfd 100644
--- a/target/mips/system/machine.c
+++ b/target/mips/system/machine.c
@@ -131,6 +131,69 @@ static const VMStateDescription vmstate_octeon_multiplier_tc = {
}
};
+typedef struct OcteonLLMTreePutData {
+ QEMUFile *f;
+} OcteonLLMTreePutData;
+
+static gboolean put_octeon_llm_tree_entry(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ OcteonLLMTreePutData *data = user_data;
+
+ qemu_put_be64(data->f, *(uint64_t *)key);
+ qemu_put_be64(data->f, *(uint64_t *)value);
+ return false;
+}
+
+static int put_octeon_llm_tree(QEMUFile *f, void *pv, size_t size,
+ const VMStateField *field, JSONWriter *vmdesc)
+{
+ QTree *tree = *(QTree **)pv;
+ OcteonLLMTreePutData data = { .f = f };
+ uint32_t nnodes = tree ? q_tree_nnodes(tree) : 0;
+
+ qemu_put_be32(f, nnodes);
+ if (tree) {
+ q_tree_foreach(tree, put_octeon_llm_tree_entry, &data);
+ }
+
+ return 0;
+}
+
+static int get_octeon_llm_tree(QEMUFile *f, void *pv, size_t size,
+ const VMStateField *field)
+{
+ QTree **treep = pv;
+ uint32_t nnodes = qemu_get_be32(f);
+
+ if (*treep) {
+ q_tree_destroy(*treep);
+ }
+ *treep = mips_octeon_llm_tree_new();
+
+ for (uint32_t i = 0; i < nnodes; i++) {
+ uint64_t addr = qemu_get_be64(f);
+ uint64_t value = qemu_get_be64(f);
+
+ mips_octeon_llm_store(treep, addr, value);
+ }
+
+ return 0;
+}
+
+static const VMStateInfo vmstate_info_octeon_llm_tree = {
+ .name = "octeon_llm_tree",
+ .get = get_octeon_llm_tree,
+ .put = put_octeon_llm_tree,
+};
+
+#define VMSTATE_OCTEON_LLM_TREE(_f, _s) { \
+ .name = stringify(_f), \
+ .version_id = 1, \
+ .info = &vmstate_info_octeon_llm_tree, \
+ .offset = vmstate_offset_pointer(_s, _f, QTree), \
+}
+
/* MVP state */
static const VMStateDescription vmstate_mvp = {
@@ -301,6 +364,10 @@ static const VMStateDescription mips_vmstate_octeon_crypto = {
VMSTATE_UINT16(env.octeon_crypto.gfm_poly, MIPSCPU),
VMSTATE_UINT8(env.octeon_crypto.aes_keylen, MIPSCPU),
VMSTATE_UINT8(env.octeon_crypto.crc_len, MIPSCPU),
+ VMSTATE_UINT64(env.octeon_crypto.chord, MIPSCPU),
+ VMSTATE_UINT64_ARRAY(env.octeon_crypto.llm_data, MIPSCPU, 2),
+ VMSTATE_OCTEON_LLM_TREE(env.octeon_crypto.llm36, MIPSCPU),
+ VMSTATE_OCTEON_LLM_TREE(env.octeon_crypto.llm64, MIPSCPU),
VMSTATE_END_OF_LIST()
}
};
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index 82ad355d56f..b24533e03df 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -16,6 +16,42 @@
#include "qemu/bitops.h"
#include "qemu/host-utils.h"
+#define OCTEON_LLM_NARROW_MASK ((1ULL << 36) - 1)
+
+static uint64_t octeon_llm_pack_narrow(uint64_t value)
+{
+ value &= OCTEON_LLM_NARROW_MASK;
+ return value | ((uint64_t)(ctpop64(value) & 1) << 36);
+}
+
+static void octeon_llm_read(MIPSOcteonCryptoState *crypto, unsigned int set,
+ uint64_t addr, bool wide)
+{
+ uint64_t value;
+
+ if (wide) {
+ value = mips_octeon_llm_load(crypto->llm64, addr);
+ } else {
+ value = octeon_llm_pack_narrow(
+ mips_octeon_llm_load(crypto->llm36, addr));
+ }
+
+ crypto->llm_data[set] = value;
+}
+
+static void octeon_llm_write(MIPSOcteonCryptoState *crypto, unsigned int set,
+ uint64_t addr, bool wide)
+{
+ uint64_t value = crypto->llm_data[set];
+
+ if (wide) {
+ mips_octeon_llm_store(&crypto->llm64, addr, value);
+ } else {
+ mips_octeon_llm_store(&crypto->llm36, addr,
+ value & OCTEON_LLM_NARROW_MASK);
+ }
+}
+
static uint32_t octeon_crc_reflect32_by_byte(uint32_t v)
{
return bswap32(revbit32(v));
@@ -2225,3 +2261,43 @@ void helper_octeon_cp2_mt_crc_write_var_reflect(CPUMIPSState *env,
octeon_crc_update_reflect(crypto, value, MIN(8U, crypto->crc_len & 0xf));
}
+
+void helper_octeon_cp2_mt_llm_read_addr0(CPUMIPSState *env, uint64_t value)
+{
+ octeon_llm_read(&env->octeon_crypto, 0, value, false);
+}
+
+void helper_octeon_cp2_mt_llm_write_addr0(CPUMIPSState *env, uint64_t value)
+{
+ octeon_llm_write(&env->octeon_crypto, 0, value, false);
+}
+
+void helper_octeon_cp2_mt_llm_read64_addr0(CPUMIPSState *env, uint64_t value)
+{
+ octeon_llm_read(&env->octeon_crypto, 0, value, true);
+}
+
+void helper_octeon_cp2_mt_llm_write64_addr0(CPUMIPSState *env, uint64_t value)
+{
+ octeon_llm_write(&env->octeon_crypto, 0, value, true);
+}
+
+void helper_octeon_cp2_mt_llm_read_addr1(CPUMIPSState *env, uint64_t value)
+{
+ octeon_llm_read(&env->octeon_crypto, 1, value, false);
+}
+
+void helper_octeon_cp2_mt_llm_write_addr1(CPUMIPSState *env, uint64_t value)
+{
+ octeon_llm_write(&env->octeon_crypto, 1, value, false);
+}
+
+void helper_octeon_cp2_mt_llm_read64_addr1(CPUMIPSState *env, uint64_t value)
+{
+ octeon_llm_read(&env->octeon_crypto, 1, value, true);
+}
+
+void helper_octeon_cp2_mt_llm_write64_addr1(CPUMIPSState *env, uint64_t value)
+{
+ octeon_llm_write(&env->octeon_crypto, 1, value, true);
+}
diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c
index 4502ae2b5be..3e586e3049e 100644
--- a/target/mips/tcg/op_helper.c
+++ b/target/mips/tcg/op_helper.c
@@ -255,6 +255,12 @@ target_ulong helper_rdhwr_xnp(CPUMIPSState *env)
return (env->CP0_Config5 >> CP0C5_XNP) & 1;
}
+target_ulong helper_rdhwr_chord(CPUMIPSState *env)
+{
+ check_hwrena(env, 30, GETPC());
+ return env->octeon_crypto.chord;
+}
+
void helper_pmon(CPUMIPSState *env, int function)
{
function /= 2;
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 123d2c89c3d..1f449328825 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -10925,6 +10925,14 @@ void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
}
break;
#endif
+ case 30:
+ if (!(ctx->insn_flags & INSN_OCTEON)) {
+ gen_reserved_instruction(ctx);
+ break;
+ }
+ gen_helper_rdhwr_chord(t0, tcg_env);
+ gen_store_gpr(t0, rt);
+ break;
default: /* Invalid */
MIPS_INVAL("rdhwr");
gen_reserved_instruction(ctx);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 14/23] target/mips: decode Octeon COP2 register selectors
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (12 preceding siblings ...)
2026-07-07 18:15 ` [PULL 13/23] target/mips: add Octeon CHORD and LLM " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 15/23] target/mips: decode Octeon CRC and GFM COP2 selectors Philippe Mathieu-Daudé
` (10 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add explicit decodetree entries and translator bindings for Octeon
DMFC2/DMTC2 selectors that are simple COP2 register transfers.
Emit direct TCG loads and stores for register moves. Use signed 32-bit
loads for 32-bit DMFC2 readback and mask narrow writable fields such as
AESKEYLEN and CRCLEN on DMTC2.
Keep operation selectors with side effects in later functional decode
patches.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-14-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/tcg/octeon.decode | 80 +++++++
target/mips/tcg/octeon_translate.c | 210 ++++++++++++++++++
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 89 ++++++++
3 files changed, 379 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 1e44c588dd6..09fbc6c1e34 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -97,3 +97,83 @@ LBUX 011111 ..... ..... ..... 00110 001010 @lx
LWUX 011111 ..... ..... ..... 10000 001010 @lx
LBX 011111 ..... ..... ..... 10110 001010 @lx
LDX 011111 ..... ..... ..... 01000 001010 @lx
+
+# Selector-driven DMFC2/DMTC2 interfaces for Octeon COP2 engines.
+&cp2 rt
+{
+ [
+ CVM_MF_HSH_IV0 010010 00001 rt:5 0000 0000 0100 1000 &cp2
+ CVM_MF_HSH_IV1 010010 00001 rt:5 0000 0000 0100 1001 &cp2
+ CVM_MF_HSH_IV2 010010 00001 rt:5 0000 0000 0100 1010 &cp2
+ CVM_MF_HSH_IV3 010010 00001 rt:5 0000 0000 0100 1011 &cp2
+ CVM_MF_HSH_DAT0 010010 00001 rt:5 0000 0000 0100 0000 &cp2
+ CVM_MF_HSH_DAT1 010010 00001 rt:5 0000 0000 0100 0001 &cp2
+ CVM_MF_HSH_DAT2 010010 00001 rt:5 0000 0000 0100 0010 &cp2
+ CVM_MF_HSH_DAT3 010010 00001 rt:5 0000 0000 0100 0011 &cp2
+ CVM_MF_HSH_DAT4 010010 00001 rt:5 0000 0000 0100 0100 &cp2
+ CVM_MF_HSH_DAT5 010010 00001 rt:5 0000 0000 0100 0101 &cp2
+ CVM_MF_HSH_DAT6 010010 00001 rt:5 0000 0000 0100 0110 &cp2
+ CVM_MF_3DES_KEY0 010010 00001 rt:5 0000 0000 1000 0000 &cp2
+ CVM_MF_3DES_KEY1 010010 00001 rt:5 0000 0000 1000 0001 &cp2
+ CVM_MF_3DES_KEY2 010010 00001 rt:5 0000 0000 1000 0010 &cp2
+ CVM_MF_3DES_IV 010010 00001 rt:5 0000 0000 1000 0100 &cp2
+ CVM_MF_3DES_RESULT 010010 00001 rt:5 0000 0000 1000 1000 &cp2
+ CVM_MF_KAS_RESULT 010010 00001 rt:5 0000 0000 1001 1000 &cp2
+ CVM_MF_AES_RESINP0 010010 00001 rt:5 0000 0001 0000 0000 &cp2
+ CVM_MF_AES_RESINP1 010010 00001 rt:5 0000 0001 0000 0001 &cp2
+ CVM_MF_AES_IV0 010010 00001 rt:5 0000 0001 0000 0010 &cp2
+ CVM_MF_AES_IV1 010010 00001 rt:5 0000 0001 0000 0011 &cp2
+ CVM_MF_AES_KEY0 010010 00001 rt:5 0000 0001 0000 0100 &cp2
+ CVM_MF_AES_KEY1 010010 00001 rt:5 0000 0001 0000 0101 &cp2
+ CVM_MF_AES_KEY2 010010 00001 rt:5 0000 0001 0000 0110 &cp2
+ CVM_MF_AES_KEY3 010010 00001 rt:5 0000 0001 0000 0111 &cp2
+ CVM_MF_AES_KEYLENGTH 010010 00001 rt:5 0000 0001 0001 0000 &cp2
+ CVM_MF_AES_INP0 010010 00001 rt:5 0000 0001 0001 0001 &cp2
+ CVM_MF_CRC_POLYNOMIAL 010010 00001 rt:5 0000 0010 0000 0000 &cp2
+ CVM_MF_CRC_IV 010010 00001 rt:5 0000 0010 0000 0001 &cp2
+ CVM_MF_CRC_LEN 010010 00001 rt:5 0000 0010 0000 0010 &cp2
+ CVM_MF_GFM_MUL0 010010 00001 rt:5 0000 0010 0101 1000 &cp2
+ CVM_MF_GFM_MUL1 010010 00001 rt:5 0000 0010 0101 1001 &cp2
+ CVM_MF_GFM_RESINP0 010010 00001 rt:5 0000 0010 0101 1010 &cp2
+ CVM_MF_GFM_RESINP1 010010 00001 rt:5 0000 0010 0101 1011 &cp2
+ CVM_MF_GFM_POLY 010010 00001 rt:5 0000 0010 0101 1110 &cp2
+ CVM_MT_HSH_DAT0 010010 00101 rt:5 0000 0000 0100 0000 &cp2
+ CVM_MT_HSH_DAT1 010010 00101 rt:5 0000 0000 0100 0001 &cp2
+ CVM_MT_HSH_DAT2 010010 00101 rt:5 0000 0000 0100 0010 &cp2
+ CVM_MT_HSH_DAT3 010010 00101 rt:5 0000 0000 0100 0011 &cp2
+ CVM_MT_HSH_DAT4 010010 00101 rt:5 0000 0000 0100 0100 &cp2
+ CVM_MT_HSH_DAT5 010010 00101 rt:5 0000 0000 0100 0101 &cp2
+ CVM_MT_HSH_DAT6 010010 00101 rt:5 0000 0000 0100 0110 &cp2
+ CVM_MT_HSH_IV0 010010 00101 rt:5 0000 0000 0100 1000 &cp2
+ CVM_MT_HSH_IV1 010010 00101 rt:5 0000 0000 0100 1001 &cp2
+ CVM_MT_HSH_IV2 010010 00101 rt:5 0000 0000 0100 1010 &cp2
+ CVM_MT_HSH_IV3 010010 00101 rt:5 0000 0000 0100 1011 &cp2
+ CVM_MT_3DES_KEY0 010010 00101 rt:5 0000 0000 1000 0000 &cp2
+ CVM_MT_3DES_KEY1 010010 00101 rt:5 0000 0000 1000 0001 &cp2
+ CVM_MT_3DES_KEY2 010010 00101 rt:5 0000 0000 1000 0010 &cp2
+ CVM_MT_3DES_IV 010010 00101 rt:5 0000 0000 1000 0100 &cp2
+ CVM_MT_3DES_RESULT 010010 00101 rt:5 0000 0000 1001 1000 &cp2
+ CVM_MT_AES_RESINP0 010010 00101 rt:5 0000 0001 0000 0000 &cp2
+ CVM_MT_AES_RESINP1 010010 00101 rt:5 0000 0001 0000 0001 &cp2
+ CVM_MT_AES_IV0 010010 00101 rt:5 0000 0001 0000 0010 &cp2
+ CVM_MT_AES_IV1 010010 00101 rt:5 0000 0001 0000 0011 &cp2
+ CVM_MT_AES_KEY0 010010 00101 rt:5 0000 0001 0000 0100 &cp2
+ CVM_MT_AES_KEY1 010010 00101 rt:5 0000 0001 0000 0101 &cp2
+ CVM_MT_AES_KEY2 010010 00101 rt:5 0000 0001 0000 0110 &cp2
+ CVM_MT_AES_KEY3 010010 00101 rt:5 0000 0001 0000 0111 &cp2
+ CVM_MT_AES_ENC_CBC0 010010 00101 rt:5 0000 0001 0000 1000 &cp2
+ CVM_MT_AES_ENC0 010010 00101 rt:5 0000 0001 0000 1010 &cp2
+ CVM_MT_AES_DEC_CBC0 010010 00101 rt:5 0000 0001 0000 1100 &cp2
+ CVM_MT_AES_DEC0 010010 00101 rt:5 0000 0001 0000 1110 &cp2
+ CVM_MT_AES_KEYLENGTH 010010 00101 rt:5 0000 0001 0001 0000 &cp2
+ CVM_MT_CRC_IV 010010 00101 rt:5 0000 0010 0000 0001 &cp2
+ CVM_MT_GFM_MUL0 010010 00101 rt:5 0000 0010 0101 1000 &cp2
+ CVM_MT_GFM_MUL1 010010 00101 rt:5 0000 0010 0101 1001 &cp2
+ CVM_MT_GFM_RESINP0 010010 00101 rt:5 0000 0010 0101 1010 &cp2
+ CVM_MT_GFM_RESINP1 010010 00101 rt:5 0000 0010 0101 1011 &cp2
+ CVM_MT_GFM_POLY 010010 00101 rt:5 0000 0010 0101 1110 &cp2
+ CVM_MT_CRC_LEN 010010 00101 rt:5 0001 0010 0000 0010 &cp2
+ CVM_MT_CRC_POLYNOMIAL 010010 00101 rt:5 0100 0010 0000 0000 &cp2
+ ]
+ CP2_Undef 010010 ----- ----- ---- ---- ---- ----
+}
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index b0af2f48382..b33252dd1f8 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -13,6 +13,216 @@
/* Include the auto-generated decoder. */
#include "decode-octeon.c.inc"
+#define OCTEON_CRYPTO_OFFSET(FIELD) \
+ offsetof(CPUMIPSState, octeon_crypto.FIELD)
+
+#define CP2_MF_I64(NAME, FIELD) \
+ TRANS(NAME, trans_octeon_cp2_mf_i64, OCTEON_CRYPTO_OFFSET(FIELD))
+#define CP2_MF_S32(NAME, FIELD) \
+ TRANS(NAME, trans_octeon_cp2_mf_s32, OCTEON_CRYPTO_OFFSET(FIELD))
+#define CP2_MF_U16(NAME, FIELD) \
+ TRANS(NAME, trans_octeon_cp2_mf_u16, OCTEON_CRYPTO_OFFSET(FIELD))
+#define CP2_MF_U8(NAME, FIELD) \
+ TRANS(NAME, trans_octeon_cp2_mf_u8, OCTEON_CRYPTO_OFFSET(FIELD))
+#define CP2_MF_HSH_PAIR(NAME, FIELD, INDEX) \
+ TRANS(NAME, trans_octeon_cp2_mf_hsh_pair, \
+ OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX)]), \
+ OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX) + 1]))
+#define CP2_MT_I64(NAME, FIELD) \
+ TRANS(NAME, trans_octeon_cp2_mt_i64, OCTEON_CRYPTO_OFFSET(FIELD))
+#define CP2_MT_U32(NAME, FIELD) \
+ TRANS(NAME, trans_octeon_cp2_mt_u32, OCTEON_CRYPTO_OFFSET(FIELD))
+#define CP2_MT_U16(NAME, FIELD) \
+ TRANS(NAME, trans_octeon_cp2_mt_u16, OCTEON_CRYPTO_OFFSET(FIELD))
+#define CP2_MT_U8_MASKED(NAME, FIELD, MASK) \
+ TRANS(NAME, trans_octeon_cp2_mt_u8_masked, \
+ OCTEON_CRYPTO_OFFSET(FIELD), MASK)
+#define CP2_MT_HSH_PAIR(NAME, FIELD, INDEX) \
+ TRANS(NAME, trans_octeon_cp2_mt_hsh_pair, \
+ OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX)]), \
+ OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX) + 1]))
+
+#define OCTEON_LO32_OFFSET (HOST_BIG_ENDIAN ? 4 : 0)
+
+static bool trans_CP2_Undef(DisasContext *ctx, arg_CP2_Undef *a)
+{
+ generate_exception_err(ctx, EXCP_CpU, 2);
+ return true;
+}
+
+static bool trans_octeon_cp2_mf_i64(DisasContext *ctx, arg_cp2 *a, int offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ tcg_gen_ld_i64(value, tcg_env, offset);
+ gen_store_gpr(value, a->rt);
+ return true;
+}
+
+static bool trans_octeon_cp2_mf_s32(DisasContext *ctx, arg_cp2 *a, int offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ tcg_gen_ld32s_i64(value, tcg_env, offset);
+ gen_store_gpr(value, a->rt);
+ return true;
+}
+
+static bool trans_octeon_cp2_mf_u16(DisasContext *ctx, arg_cp2 *a, int offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ tcg_gen_ld16u_i64(value, tcg_env, offset);
+ gen_store_gpr(value, a->rt);
+ return true;
+}
+
+static bool trans_octeon_cp2_mf_u8(DisasContext *ctx, arg_cp2 *a, int offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ tcg_gen_ld8u_i64(value, tcg_env, offset);
+ gen_store_gpr(value, a->rt);
+ return true;
+}
+
+static bool trans_octeon_cp2_mf_hsh_pair(DisasContext *ctx, arg_cp2 *a,
+ int hi_offset, int lo_offset)
+{
+ TCGv_i64 hi = tcg_temp_new_i64();
+ TCGv_i64 lo = tcg_temp_new_i64();
+
+ tcg_gen_ld_i64(hi, tcg_env, hi_offset);
+ tcg_gen_ld_i64(lo, tcg_env, lo_offset);
+ tcg_gen_concat32_i64(lo, lo, hi);
+ gen_store_gpr(lo, a->rt);
+ return true;
+}
+
+static bool trans_octeon_cp2_mt_i64(DisasContext *ctx, arg_cp2 *a, int offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ gen_load_gpr(value, a->rt);
+ tcg_gen_st_i64(value, tcg_env, offset);
+ return true;
+}
+
+static bool trans_octeon_cp2_mt_u32(DisasContext *ctx, arg_cp2 *a, int offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ gen_load_gpr(value, a->rt);
+ tcg_gen_st32_i64(value, tcg_env, offset);
+ return true;
+}
+
+static bool trans_octeon_cp2_mt_u16(DisasContext *ctx, arg_cp2 *a, int offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ gen_load_gpr(value, a->rt);
+ tcg_gen_st16_i64(value, tcg_env, offset);
+ return true;
+}
+
+static bool trans_octeon_cp2_mt_u8_masked(DisasContext *ctx, arg_cp2 *a,
+ int offset, uint8_t mask)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ gen_load_gpr(value, a->rt);
+ tcg_gen_andi_i64(value, value, mask);
+ tcg_gen_st8_i64(value, tcg_env, offset);
+ return true;
+}
+
+static bool trans_octeon_cp2_mt_hsh_pair(DisasContext *ctx, arg_cp2 *a,
+ int hi_offset, int lo_offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ gen_load_gpr(value, a->rt);
+ tcg_gen_st32_i64(value, tcg_env, lo_offset + OCTEON_LO32_OFFSET);
+ tcg_gen_shri_i64(value, value, 32);
+ tcg_gen_st32_i64(value, tcg_env, hi_offset + OCTEON_LO32_OFFSET);
+ return true;
+}
+
+CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT0, hsh_dat, 0);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT1, hsh_dat, 1);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT2, hsh_dat, 2);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT3, hsh_dat, 3);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT4, hsh_dat, 4);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT5, hsh_dat, 5);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT6, hsh_dat, 6);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_IV0, hsh_iv, 0);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_IV1, hsh_iv, 1);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_IV2, hsh_iv, 2);
+CP2_MF_HSH_PAIR(CVM_MF_HSH_IV3, hsh_iv, 3);
+CP2_MF_I64(CVM_MF_3DES_KEY0, des3_key[0]);
+CP2_MF_I64(CVM_MF_3DES_KEY1, des3_key[1]);
+CP2_MF_I64(CVM_MF_3DES_KEY2, des3_key[2]);
+CP2_MF_I64(CVM_MF_3DES_IV, des3_iv);
+CP2_MF_I64(CVM_MF_3DES_RESULT, des3_result);
+CP2_MF_I64(CVM_MF_KAS_RESULT, des3_result);
+CP2_MF_I64(CVM_MF_AES_RESINP0, aes_resinp[0]);
+CP2_MF_I64(CVM_MF_AES_RESINP1, aes_resinp[1]);
+CP2_MF_I64(CVM_MF_AES_IV0, aes_iv[0]);
+CP2_MF_I64(CVM_MF_AES_IV1, aes_iv[1]);
+CP2_MF_I64(CVM_MF_AES_KEY0, aes_key[0]);
+CP2_MF_I64(CVM_MF_AES_KEY1, aes_key[1]);
+CP2_MF_I64(CVM_MF_AES_KEY2, aes_key[2]);
+CP2_MF_I64(CVM_MF_AES_KEY3, aes_key[3]);
+CP2_MF_U8(CVM_MF_AES_KEYLENGTH, aes_keylen);
+CP2_MF_I64(CVM_MF_AES_INP0, aes_resinp[0]);
+CP2_MF_S32(CVM_MF_CRC_POLYNOMIAL, crc_poly);
+CP2_MF_S32(CVM_MF_CRC_IV, crc_iv);
+CP2_MF_U8(CVM_MF_CRC_LEN, crc_len);
+CP2_MF_I64(CVM_MF_GFM_MUL0, gfm_mul[0]);
+CP2_MF_I64(CVM_MF_GFM_MUL1, gfm_mul[1]);
+CP2_MF_I64(CVM_MF_GFM_RESINP0, gfm_resinp[0]);
+CP2_MF_I64(CVM_MF_GFM_RESINP1, gfm_resinp[1]);
+CP2_MF_U16(CVM_MF_GFM_POLY, gfm_poly);
+
+CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT0, hsh_dat, 0);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT1, hsh_dat, 1);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT2, hsh_dat, 2);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT3, hsh_dat, 3);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT4, hsh_dat, 4);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT5, hsh_dat, 5);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT6, hsh_dat, 6);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_IV0, hsh_iv, 0);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_IV1, hsh_iv, 1);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_IV2, hsh_iv, 2);
+CP2_MT_HSH_PAIR(CVM_MT_HSH_IV3, hsh_iv, 3);
+CP2_MT_I64(CVM_MT_3DES_KEY0, des3_key[0]);
+CP2_MT_I64(CVM_MT_3DES_KEY1, des3_key[1]);
+CP2_MT_I64(CVM_MT_3DES_KEY2, des3_key[2]);
+CP2_MT_I64(CVM_MT_3DES_IV, des3_iv);
+CP2_MT_I64(CVM_MT_3DES_RESULT, des3_result);
+CP2_MT_I64(CVM_MT_AES_RESINP0, aes_resinp[0]);
+CP2_MT_I64(CVM_MT_AES_RESINP1, aes_resinp[1]);
+CP2_MT_I64(CVM_MT_AES_IV0, aes_iv[0]);
+CP2_MT_I64(CVM_MT_AES_IV1, aes_iv[1]);
+CP2_MT_I64(CVM_MT_AES_KEY0, aes_key[0]);
+CP2_MT_I64(CVM_MT_AES_KEY1, aes_key[1]);
+CP2_MT_I64(CVM_MT_AES_KEY2, aes_key[2]);
+CP2_MT_I64(CVM_MT_AES_KEY3, aes_key[3]);
+CP2_MT_I64(CVM_MT_AES_ENC_CBC0, aes_resinp[0]);
+CP2_MT_I64(CVM_MT_AES_ENC0, aes_resinp[0]);
+CP2_MT_I64(CVM_MT_AES_DEC_CBC0, aes_resinp[0]);
+CP2_MT_I64(CVM_MT_AES_DEC0, aes_resinp[0]);
+CP2_MT_U8_MASKED(CVM_MT_AES_KEYLENGTH, aes_keylen, 3);
+CP2_MT_U32(CVM_MT_CRC_IV, crc_iv);
+CP2_MT_I64(CVM_MT_GFM_MUL0, gfm_mul[0]);
+CP2_MT_I64(CVM_MT_GFM_MUL1, gfm_mul[1]);
+CP2_MT_I64(CVM_MT_GFM_RESINP0, gfm_resinp[0]);
+CP2_MT_I64(CVM_MT_GFM_RESINP1, gfm_resinp[1]);
+CP2_MT_U16(CVM_MT_GFM_POLY, gfm_poly);
+CP2_MT_U8_MASKED(CVM_MT_CRC_LEN, crc_len, 0xf);
+CP2_MT_U32(CVM_MT_CRC_POLYNOMIAL, crc_poly);
+
static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
{
TCGv_i64 p;
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index 9153e37e9e0..7a7445c40a5 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -186,6 +186,86 @@ static uint64_t octeon_mtp0_zeroes_p1(void)
return rd;
}
+static uint64_t octeon_cop2_key0_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a80104\n\t" /* dmtc2 $8, AES_KEY0 selector */
+ ".word 0x482a0104\n\t" /* dmfc2 $10, AES_KEY0 selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_cop2_key2_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a80106\n\t" /* dmtc2 $8, AES_KEY2 selector */
+ ".word 0x482a0106\n\t" /* dmfc2 $10, AES_KEY2 selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_cop2_key3_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a80107\n\t" /* dmtc2 $8, AES_KEY3 selector */
+ ".word 0x482a0107\n\t" /* dmfc2 $10, AES_KEY3 selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_cop2_keylength_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a80110\n\t" /* dmtc2 $8, AES_KEYLENGTH selector */
+ ".word 0x482a0110\n\t" /* dmfc2 $10, AES_KEYLENGTH selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_cop2_hsh_dat0_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a80040\n\t" /* dmtc2 $8, HSH_DAT0 selector */
+ ".word 0x482a0040\n\t" /* dmfc2 $10, HSH_DAT0 selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
int main(void)
{
assert(octeon_baddu(0x123, 0x0f0) == 0x13);
@@ -199,6 +279,15 @@ int main(void)
assert(octeon_vmm0(5, 13, 7, 11) == 59);
assert(octeon_vmm0_zeroes_mpl1() == 0);
assert(octeon_mtp0_zeroes_p1() == 0);
+ assert(octeon_cop2_key0_readback(0x1122334455667788ULL) ==
+ 0x1122334455667788ULL);
+ assert(octeon_cop2_key2_readback(0x8877665544332211ULL) ==
+ 0x8877665544332211ULL);
+ assert(octeon_cop2_key3_readback(0x0102030405060708ULL) ==
+ 0x0102030405060708ULL);
+ assert(octeon_cop2_keylength_readback(0xa5) == 1);
+ assert(octeon_cop2_hsh_dat0_readback(0x0102030405060708ULL) ==
+ 0x0102030405060708ULL);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 15/23] target/mips: decode Octeon CRC and GFM COP2 selectors
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (13 preceding siblings ...)
2026-07-07 18:15 ` [PULL 14/23] target/mips: decode Octeon COP2 register selectors Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 16/23] target/mips: decode Octeon HSH and SHA3 " Philippe Mathieu-Daudé
` (9 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add explicit decodetree entries and translator bindings for the Octeon
CRC and GFM COP2 operation selectors. Unlike simple register moves,
these selectors update CRC or Galois-field state and therefore remain
per-operation helper calls.
Keep CRC/GFM decode next to the helpers that implement these side
effects while avoiding a monolithic selector-dispatch helper.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-15-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 1 +
target/mips/tcg/octeon.decode | 22 ++++++
target/mips/tcg/octeon_crypto.c | 7 ++
target/mips/tcg/octeon_translate.c | 50 +++++++++++++
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 70 +++++++++++++++++++
5 files changed, 150 insertions(+)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index e210e406f9c..141350e80ad 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -32,6 +32,7 @@ DEF_HELPER_1(octeon_cp2_mf_gfm_mul_reflect1, i64, env)
DEF_HELPER_1(octeon_cp2_mf_gfm_resinp_reflect0, i64, env)
DEF_HELPER_1(octeon_cp2_mf_gfm_resinp_reflect1, i64, env)
DEF_HELPER_2(octeon_cp2_mt_crc_write_iv_reflect, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_crc_write_polynomial_reflect, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_crc_write_byte, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_crc_write_half, void, env, i64)
DEF_HELPER_2(octeon_cp2_mt_crc_write_word, void, env, i64)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 09fbc6c1e34..70e02d0b0e9 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -132,6 +132,11 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MF_CRC_POLYNOMIAL 010010 00001 rt:5 0000 0010 0000 0000 &cp2
CVM_MF_CRC_IV 010010 00001 rt:5 0000 0010 0000 0001 &cp2
CVM_MF_CRC_LEN 010010 00001 rt:5 0000 0010 0000 0010 &cp2
+ CVM_MF_CRC_IV_REFLECT 010010 00001 rt:5 0000 0010 0000 0011 &cp2
+ CVM_MF_GFM_MUL_REFLECT0 010010 00001 rt:5 0000 0000 0101 1000 &cp2
+ CVM_MF_GFM_MUL_REFLECT1 010010 00001 rt:5 0000 0000 0101 1001 &cp2
+ CVM_MF_GFM_RESINP_REFLECT0 010010 00001 rt:5 0000 0000 0101 1010 &cp2
+ CVM_MF_GFM_RESINP_REFLECT1 010010 00001 rt:5 0000 0000 0101 1011 &cp2
CVM_MF_GFM_MUL0 010010 00001 rt:5 0000 0010 0101 1000 &cp2
CVM_MF_GFM_MUL1 010010 00001 rt:5 0000 0010 0101 1001 &cp2
CVM_MF_GFM_RESINP0 010010 00001 rt:5 0000 0010 0101 1010 &cp2
@@ -148,6 +153,9 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_HSH_IV1 010010 00101 rt:5 0000 0000 0100 1001 &cp2
CVM_MT_HSH_IV2 010010 00101 rt:5 0000 0000 0100 1010 &cp2
CVM_MT_HSH_IV3 010010 00101 rt:5 0000 0000 0100 1011 &cp2
+ CVM_MT_GFM_MUL_REFLECT0 010010 00101 rt:5 0000 0000 0101 1000 &cp2
+ CVM_MT_GFM_MUL_REFLECT1 010010 00101 rt:5 0000 0000 0101 1001 &cp2
+ CVM_MT_GFM_XOR0_REFLECT 010010 00101 rt:5 0000 0000 0101 1100 &cp2
CVM_MT_3DES_KEY0 010010 00101 rt:5 0000 0000 1000 0000 &cp2
CVM_MT_3DES_KEY1 010010 00101 rt:5 0000 0000 1000 0001 &cp2
CVM_MT_3DES_KEY2 010010 00101 rt:5 0000 0000 1000 0010 &cp2
@@ -167,13 +175,27 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_AES_DEC0 010010 00101 rt:5 0000 0001 0000 1110 &cp2
CVM_MT_AES_KEYLENGTH 010010 00101 rt:5 0000 0001 0001 0000 &cp2
CVM_MT_CRC_IV 010010 00101 rt:5 0000 0010 0000 0001 &cp2
+ CVM_MT_CRC_IV_REFLECT 010010 00101 rt:5 0000 0010 0001 0001 &cp2
+ CVM_MT_CRC_BYTE 010010 00101 rt:5 0000 0010 0000 0100 &cp2
+ CVM_MT_CRC_HALF 010010 00101 rt:5 0000 0010 0000 0101 &cp2
+ CVM_MT_CRC_WORD 010010 00101 rt:5 0000 0010 0000 0110 &cp2
+ CVM_MT_CRC_BYTE_REFLECT 010010 00101 rt:5 0000 0010 0001 0100 &cp2
+ CVM_MT_CRC_HALF_REFLECT 010010 00101 rt:5 0000 0010 0001 0101 &cp2
+ CVM_MT_CRC_WORD_REFLECT 010010 00101 rt:5 0000 0010 0001 0110 &cp2
CVM_MT_GFM_MUL0 010010 00101 rt:5 0000 0010 0101 1000 &cp2
CVM_MT_GFM_MUL1 010010 00101 rt:5 0000 0010 0101 1001 &cp2
CVM_MT_GFM_RESINP0 010010 00101 rt:5 0000 0010 0101 1010 &cp2
CVM_MT_GFM_RESINP1 010010 00101 rt:5 0000 0010 0101 1011 &cp2
CVM_MT_GFM_POLY 010010 00101 rt:5 0000 0010 0101 1110 &cp2
CVM_MT_CRC_LEN 010010 00101 rt:5 0001 0010 0000 0010 &cp2
+ CVM_MT_CRC_DWORD 010010 00101 rt:5 0001 0010 0000 0111 &cp2
+ CVM_MT_CRC_VAR 010010 00101 rt:5 0001 0010 0000 1000 &cp2
+ CVM_MT_CRC_DWORD_REFLECT 010010 00101 rt:5 0001 0010 0001 0111 &cp2
+ CVM_MT_CRC_VAR_REFLECT 010010 00101 rt:5 0001 0010 0001 1000 &cp2
+ CVM_MT_GFM_XORMUL1_REFLECT 010010 00101 rt:5 0100 0000 0101 1101 &cp2
CVM_MT_CRC_POLYNOMIAL 010010 00101 rt:5 0100 0010 0000 0000 &cp2
+ CVM_MT_CRC_POLYNOMIAL_REFLECT 010010 00101 rt:5 0100 0010 0001 0000 &cp2
+ CVM_MT_GFM_XORMUL1 010010 00101 rt:5 0100 0010 0101 1101 &cp2
]
CP2_Undef 010010 ----- ----- ---- ---- ---- ----
}
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index b24533e03df..fbf80be2a53 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -2203,6 +2203,13 @@ void helper_octeon_cp2_mt_crc_write_iv_reflect(CPUMIPSState *env,
octeon_crc_reflect32_by_byte((uint32_t)value);
}
+void helper_octeon_cp2_mt_crc_write_polynomial_reflect(CPUMIPSState *env,
+ uint64_t value)
+{
+ env->octeon_crypto.crc_poly =
+ octeon_crc_reflect32_by_byte((uint32_t)value);
+}
+
void helper_octeon_cp2_mt_crc_write_byte(CPUMIPSState *env, uint64_t value)
{
octeon_crc_update_normal(&env->octeon_crypto, value, 1);
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index b33252dd1f8..ce4cfcb3f30 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -28,6 +28,9 @@
TRANS(NAME, trans_octeon_cp2_mf_hsh_pair, \
OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX)]), \
OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX) + 1]))
+#define CP2_MF_HELPER(NAME, SUFFIX) \
+ TRANS(NAME, trans_octeon_cp2_mf_helper, \
+ gen_helper_octeon_cp2_mf_ ## SUFFIX)
#define CP2_MT_I64(NAME, FIELD) \
TRANS(NAME, trans_octeon_cp2_mt_i64, OCTEON_CRYPTO_OFFSET(FIELD))
#define CP2_MT_U32(NAME, FIELD) \
@@ -41,6 +44,9 @@
TRANS(NAME, trans_octeon_cp2_mt_hsh_pair, \
OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX)]), \
OCTEON_CRYPTO_OFFSET(FIELD[2 * (INDEX) + 1]))
+#define CP2_MT_HELPER(NAME, SUFFIX) \
+ TRANS(NAME, trans_octeon_cp2_mt_helper, \
+ gen_helper_octeon_cp2_mt_ ## SUFFIX)
#define OCTEON_LO32_OFFSET (HOST_BIG_ENDIAN ? 4 : 0)
@@ -99,6 +105,16 @@ static bool trans_octeon_cp2_mf_hsh_pair(DisasContext *ctx, arg_cp2 *a,
return true;
}
+static bool trans_octeon_cp2_mf_helper(DisasContext *ctx, arg_cp2 *a,
+ void (*gen_helper)(TCGv_i64, TCGv_env))
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ gen_helper(value, tcg_env);
+ gen_store_gpr(value, a->rt);
+ return true;
+}
+
static bool trans_octeon_cp2_mt_i64(DisasContext *ctx, arg_cp2 *a, int offset)
{
TCGv_i64 value = tcg_temp_new_i64();
@@ -149,6 +165,16 @@ static bool trans_octeon_cp2_mt_hsh_pair(DisasContext *ctx, arg_cp2 *a,
return true;
}
+static bool trans_octeon_cp2_mt_helper(DisasContext *ctx, arg_cp2 *a,
+ void (*gen_helper)(TCGv_env, TCGv_i64))
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+
+ gen_load_gpr(value, a->rt);
+ gen_helper(tcg_env, value);
+ return true;
+}
+
CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT0, hsh_dat, 0);
CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT1, hsh_dat, 1);
CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT2, hsh_dat, 2);
@@ -185,6 +211,12 @@ CP2_MF_I64(CVM_MF_GFM_RESINP0, gfm_resinp[0]);
CP2_MF_I64(CVM_MF_GFM_RESINP1, gfm_resinp[1]);
CP2_MF_U16(CVM_MF_GFM_POLY, gfm_poly);
+CP2_MF_HELPER(CVM_MF_CRC_IV_REFLECT, crc_iv_reflect);
+CP2_MF_HELPER(CVM_MF_GFM_MUL_REFLECT0, gfm_mul_reflect0);
+CP2_MF_HELPER(CVM_MF_GFM_MUL_REFLECT1, gfm_mul_reflect1);
+CP2_MF_HELPER(CVM_MF_GFM_RESINP_REFLECT0, gfm_resinp_reflect0);
+CP2_MF_HELPER(CVM_MF_GFM_RESINP_REFLECT1, gfm_resinp_reflect1);
+
CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT0, hsh_dat, 0);
CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT1, hsh_dat, 1);
CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT2, hsh_dat, 2);
@@ -196,6 +228,9 @@ CP2_MT_HSH_PAIR(CVM_MT_HSH_IV0, hsh_iv, 0);
CP2_MT_HSH_PAIR(CVM_MT_HSH_IV1, hsh_iv, 1);
CP2_MT_HSH_PAIR(CVM_MT_HSH_IV2, hsh_iv, 2);
CP2_MT_HSH_PAIR(CVM_MT_HSH_IV3, hsh_iv, 3);
+CP2_MT_HELPER(CVM_MT_GFM_MUL_REFLECT0, gfm_mul_reflect0);
+CP2_MT_HELPER(CVM_MT_GFM_MUL_REFLECT1, gfm_mul_reflect1);
+CP2_MT_HELPER(CVM_MT_GFM_XOR0_REFLECT, gfm_xor0_reflect);
CP2_MT_I64(CVM_MT_3DES_KEY0, des3_key[0]);
CP2_MT_I64(CVM_MT_3DES_KEY1, des3_key[1]);
CP2_MT_I64(CVM_MT_3DES_KEY2, des3_key[2]);
@@ -223,6 +258,21 @@ CP2_MT_U16(CVM_MT_GFM_POLY, gfm_poly);
CP2_MT_U8_MASKED(CVM_MT_CRC_LEN, crc_len, 0xf);
CP2_MT_U32(CVM_MT_CRC_POLYNOMIAL, crc_poly);
+CP2_MT_HELPER(CVM_MT_CRC_POLYNOMIAL_REFLECT, crc_write_polynomial_reflect);
+CP2_MT_HELPER(CVM_MT_CRC_IV_REFLECT, crc_write_iv_reflect);
+CP2_MT_HELPER(CVM_MT_CRC_BYTE, crc_write_byte);
+CP2_MT_HELPER(CVM_MT_CRC_HALF, crc_write_half);
+CP2_MT_HELPER(CVM_MT_CRC_WORD, crc_write_word);
+CP2_MT_HELPER(CVM_MT_CRC_BYTE_REFLECT, crc_write_byte_reflect);
+CP2_MT_HELPER(CVM_MT_CRC_HALF_REFLECT, crc_write_half_reflect);
+CP2_MT_HELPER(CVM_MT_CRC_WORD_REFLECT, crc_write_word_reflect);
+CP2_MT_HELPER(CVM_MT_CRC_DWORD, crc_write_dword);
+CP2_MT_HELPER(CVM_MT_CRC_VAR, crc_write_var);
+CP2_MT_HELPER(CVM_MT_CRC_DWORD_REFLECT, crc_write_dword_reflect);
+CP2_MT_HELPER(CVM_MT_CRC_VAR_REFLECT, crc_write_var_reflect);
+CP2_MT_HELPER(CVM_MT_GFM_XORMUL1_REFLECT, gfm_xormul1_reflect);
+CP2_MT_HELPER(CVM_MT_GFM_XORMUL1, gfm_xormul1);
+
static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
{
TCGv_i64 p;
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index 7a7445c40a5..f3c52d7829e 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -266,6 +266,70 @@ static uint64_t octeon_cop2_hsh_dat0_readback(uint64_t value)
return rd;
}
+static uint64_t octeon_cop2_crc_len_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a81202\n\t" /* dmtc2 $8, CRC_LEN selector */
+ ".word 0x482a0202\n\t" /* dmfc2 $10, CRC_LEN selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_cop2_crc_poly_reflect_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a84210\n\t" /* dmtc2 $8, CRC_POLYNOMIAL_REFLECT selector */
+ ".word 0x482a0200\n\t" /* dmfc2 $10, CRC_POLYNOMIAL selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_cop2_gfm_mul_reflect_write_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a80058\n\t" /* dmtc2 $8, GFM_MUL_REFLECT0 selector */
+ ".word 0x482a0258\n\t" /* dmfc2 $10, GFM_MUL0 selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_cop2_gfm_mul_reflect_readback(uint64_t value)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[value]\n\t"
+ ".word 0x48a80258\n\t" /* dmtc2 $8, GFM_MUL0 selector */
+ ".word 0x482a0058\n\t" /* dmfc2 $10, GFM_MUL_REFLECT0 selector */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [value] "r" (value)
+ : "$8", "$10");
+
+ return rd;
+}
+
int main(void)
{
assert(octeon_baddu(0x123, 0x0f0) == 0x13);
@@ -288,6 +352,12 @@ int main(void)
assert(octeon_cop2_keylength_readback(0xa5) == 1);
assert(octeon_cop2_hsh_dat0_readback(0x0102030405060708ULL) ==
0x0102030405060708ULL);
+ assert(octeon_cop2_crc_len_readback(0xb5) == 5);
+ assert(octeon_cop2_crc_poly_reflect_readback(0x12345678) == 0x482c6a1e);
+ assert(octeon_cop2_gfm_mul_reflect_write_readback(
+ 0x0123456789abcdefULL) == 0xf7b3d591e6a2c480ULL);
+ assert(octeon_cop2_gfm_mul_reflect_readback(
+ 0xfedcba9876543210ULL) == 0x084c2a6e195d3b7fULL);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 16/23] target/mips: decode Octeon HSH and SHA3 COP2 selectors
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (14 preceding siblings ...)
2026-07-07 18:15 ` [PULL 15/23] target/mips: decode Octeon CRC and GFM COP2 selectors Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 17/23] target/mips: decode Octeon ZUC and SNOW3G " Philippe Mathieu-Daudé
` (8 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add explicit decodetree entries and translator bindings for the Octeon
HSH shared-window selectors and SHA3 operation selectors. Simple SHA3 DAT
register moves and XORDAT selectors use direct TCG transfers, while HSH
operation selectors and SHA3 STARTOP remain helper-backed for their
visible side effects.
Keep HSH/SHA3 decode separate from direct register transfers because the
shared hash-window aliases and side-effecting operations need their own
selector coverage.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-16-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/tcg/octeon.decode | 77 ++++++++++++++++++++++
target/mips/tcg/octeon_translate.c | 102 +++++++++++++++++++++++++++++
2 files changed, 179 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 70e02d0b0e9..b1a63b743f2 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -113,6 +113,7 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MF_HSH_DAT4 010010 00001 rt:5 0000 0000 0100 0100 &cp2
CVM_MF_HSH_DAT5 010010 00001 rt:5 0000 0000 0100 0101 &cp2
CVM_MF_HSH_DAT6 010010 00001 rt:5 0000 0000 0100 0110 &cp2
+ CVM_MF_SHA3_DAT24 010010 00001 rt:5 0000 0000 0101 0000 &cp2
CVM_MF_3DES_KEY0 010010 00001 rt:5 0000 0000 1000 0000 &cp2
CVM_MF_3DES_KEY1 010010 00001 rt:5 0000 0000 1000 0001 &cp2
CVM_MF_3DES_KEY2 010010 00001 rt:5 0000 0000 1000 0010 &cp2
@@ -137,6 +138,30 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MF_GFM_MUL_REFLECT1 010010 00001 rt:5 0000 0000 0101 1001 &cp2
CVM_MF_GFM_RESINP_REFLECT0 010010 00001 rt:5 0000 0000 0101 1010 &cp2
CVM_MF_GFM_RESINP_REFLECT1 010010 00001 rt:5 0000 0000 0101 1011 &cp2
+ CVM_MF_HSH_DATW0 010010 00001 rt:5 0000 0010 0100 0000 &cp2
+ CVM_MF_HSH_DATW1 010010 00001 rt:5 0000 0010 0100 0001 &cp2
+ CVM_MF_HSH_DATW2 010010 00001 rt:5 0000 0010 0100 0010 &cp2
+ CVM_MF_HSH_DATW3 010010 00001 rt:5 0000 0010 0100 0011 &cp2
+ CVM_MF_HSH_DATW4 010010 00001 rt:5 0000 0010 0100 0100 &cp2
+ CVM_MF_HSH_DATW5 010010 00001 rt:5 0000 0010 0100 0101 &cp2
+ CVM_MF_HSH_DATW6 010010 00001 rt:5 0000 0010 0100 0110 &cp2
+ CVM_MF_HSH_DATW7 010010 00001 rt:5 0000 0010 0100 0111 &cp2
+ CVM_MF_HSH_DATW8 010010 00001 rt:5 0000 0010 0100 1000 &cp2
+ CVM_MF_HSH_DATW9 010010 00001 rt:5 0000 0010 0100 1001 &cp2
+ CVM_MF_HSH_DATW10 010010 00001 rt:5 0000 0010 0100 1010 &cp2
+ CVM_MF_HSH_DATW11 010010 00001 rt:5 0000 0010 0100 1011 &cp2
+ CVM_MF_HSH_DATW12 010010 00001 rt:5 0000 0010 0100 1100 &cp2
+ CVM_MF_HSH_DATW13 010010 00001 rt:5 0000 0010 0100 1101 &cp2
+ CVM_MF_HSH_DATW14 010010 00001 rt:5 0000 0010 0100 1110 &cp2
+ CVM_MF_HSH_DATW15 010010 00001 rt:5 0000 0010 0100 1111 &cp2
+ CVM_MF_HSH_IVW0 010010 00001 rt:5 0000 0010 0101 0000 &cp2
+ CVM_MF_HSH_IVW1 010010 00001 rt:5 0000 0010 0101 0001 &cp2
+ CVM_MF_HSH_IVW2 010010 00001 rt:5 0000 0010 0101 0010 &cp2
+ CVM_MF_HSH_IVW3 010010 00001 rt:5 0000 0010 0101 0011 &cp2
+ CVM_MF_HSH_IVW4 010010 00001 rt:5 0000 0010 0101 0100 &cp2
+ CVM_MF_HSH_IVW5 010010 00001 rt:5 0000 0010 0101 0101 &cp2
+ CVM_MF_HSH_IVW6 010010 00001 rt:5 0000 0010 0101 0110 &cp2
+ CVM_MF_HSH_IVW7 010010 00001 rt:5 0000 0010 0101 0111 &cp2
CVM_MF_GFM_MUL0 010010 00001 rt:5 0000 0010 0101 1000 &cp2
CVM_MF_GFM_MUL1 010010 00001 rt:5 0000 0010 0101 1001 &cp2
CVM_MF_GFM_RESINP0 010010 00001 rt:5 0000 0010 0101 1010 &cp2
@@ -153,6 +178,10 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_HSH_IV1 010010 00101 rt:5 0000 0000 0100 1001 &cp2
CVM_MT_HSH_IV2 010010 00101 rt:5 0000 0000 0100 1010 &cp2
CVM_MT_HSH_IV3 010010 00101 rt:5 0000 0000 0100 1011 &cp2
+ CVM_MT_SHA3_DAT24 010010 00101 rt:5 0000 0000 0101 0000 &cp2
+ CVM_MT_SHA3_DAT15 010010 00101 rt:5 0000 0000 0101 0001 &cp2
+ # Cavium SDK code uses 0x0057 as a STARTSHA1 compatibility alias.
+ CVM_MT_HSH_STARTSHA1_COMPAT 010010 00101 rt:5 0000 0000 0101 0111 &cp2
CVM_MT_GFM_MUL_REFLECT0 010010 00101 rt:5 0000 0000 0101 1000 &cp2
CVM_MT_GFM_MUL_REFLECT1 010010 00101 rt:5 0000 0000 0101 1001 &cp2
CVM_MT_GFM_XOR0_REFLECT 010010 00101 rt:5 0000 0000 0101 1100 &cp2
@@ -182,19 +211,67 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_CRC_BYTE_REFLECT 010010 00101 rt:5 0000 0010 0001 0100 &cp2
CVM_MT_CRC_HALF_REFLECT 010010 00101 rt:5 0000 0010 0001 0101 &cp2
CVM_MT_CRC_WORD_REFLECT 010010 00101 rt:5 0000 0010 0001 0110 &cp2
+ CVM_MT_HSH_DATW0 010010 00101 rt:5 0000 0010 0100 0000 &cp2
+ CVM_MT_HSH_DATW1 010010 00101 rt:5 0000 0010 0100 0001 &cp2
+ CVM_MT_HSH_DATW2 010010 00101 rt:5 0000 0010 0100 0010 &cp2
+ CVM_MT_HSH_DATW3 010010 00101 rt:5 0000 0010 0100 0011 &cp2
+ CVM_MT_HSH_DATW4 010010 00101 rt:5 0000 0010 0100 0100 &cp2
+ CVM_MT_HSH_DATW5 010010 00101 rt:5 0000 0010 0100 0101 &cp2
+ CVM_MT_HSH_DATW6 010010 00101 rt:5 0000 0010 0100 0110 &cp2
+ CVM_MT_HSH_DATW7 010010 00101 rt:5 0000 0010 0100 0111 &cp2
+ CVM_MT_HSH_DATW8 010010 00101 rt:5 0000 0010 0100 1000 &cp2
+ CVM_MT_HSH_DATW9 010010 00101 rt:5 0000 0010 0100 1001 &cp2
+ CVM_MT_HSH_DATW10 010010 00101 rt:5 0000 0010 0100 1010 &cp2
+ CVM_MT_HSH_DATW11 010010 00101 rt:5 0000 0010 0100 1011 &cp2
+ CVM_MT_HSH_DATW12 010010 00101 rt:5 0000 0010 0100 1100 &cp2
+ CVM_MT_HSH_DATW13 010010 00101 rt:5 0000 0010 0100 1101 &cp2
+ CVM_MT_HSH_DATW14 010010 00101 rt:5 0000 0010 0100 1110 &cp2
+ CVM_MT_HSH_DATW15 010010 00101 rt:5 0000 0010 0100 1111 &cp2
+ CVM_MT_HSH_IVW0 010010 00101 rt:5 0000 0010 0101 0000 &cp2
+ CVM_MT_HSH_IVW1 010010 00101 rt:5 0000 0010 0101 0001 &cp2
+ CVM_MT_HSH_IVW2 010010 00101 rt:5 0000 0010 0101 0010 &cp2
+ CVM_MT_HSH_IVW3 010010 00101 rt:5 0000 0010 0101 0011 &cp2
+ CVM_MT_HSH_IVW4 010010 00101 rt:5 0000 0010 0101 0100 &cp2
+ CVM_MT_HSH_IVW5 010010 00101 rt:5 0000 0010 0101 0101 &cp2
+ CVM_MT_HSH_IVW6 010010 00101 rt:5 0000 0010 0101 0110 &cp2
+ CVM_MT_HSH_IVW7 010010 00101 rt:5 0000 0010 0101 0111 &cp2
CVM_MT_GFM_MUL0 010010 00101 rt:5 0000 0010 0101 1000 &cp2
CVM_MT_GFM_MUL1 010010 00101 rt:5 0000 0010 0101 1001 &cp2
CVM_MT_GFM_RESINP0 010010 00101 rt:5 0000 0010 0101 1010 &cp2
CVM_MT_GFM_RESINP1 010010 00101 rt:5 0000 0010 0101 1011 &cp2
+ CVM_MT_GFM_XOR0 010010 00101 rt:5 0000 0010 0101 1100 &cp2
CVM_MT_GFM_POLY 010010 00101 rt:5 0000 0010 0101 1110 &cp2
+ CVM_MT_SHA3_XORDAT0 010010 00101 rt:5 0000 0010 1100 0000 &cp2
+ CVM_MT_SHA3_XORDAT1 010010 00101 rt:5 0000 0010 1100 0001 &cp2
+ CVM_MT_SHA3_XORDAT2 010010 00101 rt:5 0000 0010 1100 0010 &cp2
+ CVM_MT_SHA3_XORDAT3 010010 00101 rt:5 0000 0010 1100 0011 &cp2
+ CVM_MT_SHA3_XORDAT4 010010 00101 rt:5 0000 0010 1100 0100 &cp2
+ CVM_MT_SHA3_XORDAT5 010010 00101 rt:5 0000 0010 1100 0101 &cp2
+ CVM_MT_SHA3_XORDAT6 010010 00101 rt:5 0000 0010 1100 0110 &cp2
+ CVM_MT_SHA3_XORDAT7 010010 00101 rt:5 0000 0010 1100 0111 &cp2
+ CVM_MT_SHA3_XORDAT8 010010 00101 rt:5 0000 0010 1100 1000 &cp2
+ CVM_MT_SHA3_XORDAT9 010010 00101 rt:5 0000 0010 1100 1001 &cp2
+ CVM_MT_SHA3_XORDAT10 010010 00101 rt:5 0000 0010 1100 1010 &cp2
+ CVM_MT_SHA3_XORDAT11 010010 00101 rt:5 0000 0010 1100 1011 &cp2
+ CVM_MT_SHA3_XORDAT12 010010 00101 rt:5 0000 0010 1100 1100 &cp2
+ CVM_MT_SHA3_XORDAT13 010010 00101 rt:5 0000 0010 1100 1101 &cp2
+ CVM_MT_SHA3_XORDAT14 010010 00101 rt:5 0000 0010 1100 1110 &cp2
+ CVM_MT_SHA3_XORDAT15 010010 00101 rt:5 0000 0010 1100 1111 &cp2
+ CVM_MT_SHA3_XORDAT16 010010 00101 rt:5 0000 0010 1101 0000 &cp2
+ CVM_MT_SHA3_XORDAT17 010010 00101 rt:5 0000 0010 1101 0001 &cp2
CVM_MT_CRC_LEN 010010 00101 rt:5 0001 0010 0000 0010 &cp2
CVM_MT_CRC_DWORD 010010 00101 rt:5 0001 0010 0000 0111 &cp2
CVM_MT_CRC_VAR 010010 00101 rt:5 0001 0010 0000 1000 &cp2
CVM_MT_CRC_DWORD_REFLECT 010010 00101 rt:5 0001 0010 0001 0111 &cp2
CVM_MT_CRC_VAR_REFLECT 010010 00101 rt:5 0001 0010 0001 1000 &cp2
+ CVM_MT_HSH_STARTMD5 010010 00101 rt:5 0100 0000 0100 0111 &cp2
+ CVM_MT_HSH_STARTSHA256 010010 00101 rt:5 0100 0000 0100 1111 &cp2
+ CVM_MT_SHA3_STARTOP 010010 00101 rt:5 0100 0000 0101 0010 &cp2
+ CVM_MT_HSH_STARTSHA 010010 00101 rt:5 0100 0000 0101 0111 &cp2
CVM_MT_GFM_XORMUL1_REFLECT 010010 00101 rt:5 0100 0000 0101 1101 &cp2
CVM_MT_CRC_POLYNOMIAL 010010 00101 rt:5 0100 0010 0000 0000 &cp2
CVM_MT_CRC_POLYNOMIAL_REFLECT 010010 00101 rt:5 0100 0010 0001 0000 &cp2
+ CVM_MT_HSH_STARTSHA512 010010 00101 rt:5 0100 0010 0100 1111 &cp2
CVM_MT_GFM_XORMUL1 010010 00101 rt:5 0100 0010 0101 1101 &cp2
]
CP2_Undef 010010 ----- ----- ---- ---- ---- ----
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index ce4cfcb3f30..5497e5a6cec 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -47,6 +47,11 @@
#define CP2_MT_HELPER(NAME, SUFFIX) \
TRANS(NAME, trans_octeon_cp2_mt_helper, \
gen_helper_octeon_cp2_mt_ ## SUFFIX)
+#define CP2_MT_HELPER_ENV(NAME, SUFFIX) \
+ TRANS(NAME, trans_octeon_cp2_mt_helper_env, \
+ gen_helper_octeon_cp2_mt_ ## SUFFIX)
+#define CP2_MT_XOR_I64(NAME, FIELD) \
+ TRANS(NAME, trans_octeon_cp2_mt_xor_i64, OCTEON_CRYPTO_OFFSET(FIELD))
#define OCTEON_LO32_OFFSET (HOST_BIG_ENDIAN ? 4 : 0)
@@ -165,6 +170,19 @@ static bool trans_octeon_cp2_mt_hsh_pair(DisasContext *ctx, arg_cp2 *a,
return true;
}
+static bool trans_octeon_cp2_mt_xor_i64(DisasContext *ctx, arg_cp2 *a,
+ int offset)
+{
+ TCGv_i64 value = tcg_temp_new_i64();
+ TCGv_i64 old = tcg_temp_new_i64();
+
+ gen_load_gpr(value, a->rt);
+ tcg_gen_ld_i64(old, tcg_env, offset);
+ tcg_gen_xor_i64(old, old, value);
+ tcg_gen_st_i64(old, tcg_env, offset);
+ return true;
+}
+
static bool trans_octeon_cp2_mt_helper(DisasContext *ctx, arg_cp2 *a,
void (*gen_helper)(TCGv_env, TCGv_i64))
{
@@ -175,6 +193,13 @@ static bool trans_octeon_cp2_mt_helper(DisasContext *ctx, arg_cp2 *a,
return true;
}
+static bool trans_octeon_cp2_mt_helper_env(DisasContext *ctx, arg_cp2 *a,
+ void (*gen_helper)(TCGv_env))
+{
+ gen_helper(tcg_env);
+ return true;
+}
+
CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT0, hsh_dat, 0);
CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT1, hsh_dat, 1);
CP2_MF_HSH_PAIR(CVM_MF_HSH_DAT2, hsh_dat, 2);
@@ -212,10 +237,35 @@ CP2_MF_I64(CVM_MF_GFM_RESINP1, gfm_resinp[1]);
CP2_MF_U16(CVM_MF_GFM_POLY, gfm_poly);
CP2_MF_HELPER(CVM_MF_CRC_IV_REFLECT, crc_iv_reflect);
+CP2_MF_I64(CVM_MF_SHA3_DAT24, sha3_dat24);
CP2_MF_HELPER(CVM_MF_GFM_MUL_REFLECT0, gfm_mul_reflect0);
CP2_MF_HELPER(CVM_MF_GFM_MUL_REFLECT1, gfm_mul_reflect1);
CP2_MF_HELPER(CVM_MF_GFM_RESINP_REFLECT0, gfm_resinp_reflect0);
CP2_MF_HELPER(CVM_MF_GFM_RESINP_REFLECT1, gfm_resinp_reflect1);
+CP2_MF_I64(CVM_MF_HSH_DATW0, hsh_dat[0]);
+CP2_MF_I64(CVM_MF_HSH_DATW1, hsh_dat[1]);
+CP2_MF_I64(CVM_MF_HSH_DATW2, hsh_dat[2]);
+CP2_MF_I64(CVM_MF_HSH_DATW3, hsh_dat[3]);
+CP2_MF_I64(CVM_MF_HSH_DATW4, hsh_dat[4]);
+CP2_MF_I64(CVM_MF_HSH_DATW5, hsh_dat[5]);
+CP2_MF_I64(CVM_MF_HSH_DATW6, hsh_dat[6]);
+CP2_MF_I64(CVM_MF_HSH_DATW7, hsh_dat[7]);
+CP2_MF_I64(CVM_MF_HSH_DATW8, hsh_dat[8]);
+CP2_MF_I64(CVM_MF_HSH_DATW9, hsh_dat[9]);
+CP2_MF_I64(CVM_MF_HSH_DATW10, hsh_dat[10]);
+CP2_MF_I64(CVM_MF_HSH_DATW11, hsh_dat[11]);
+CP2_MF_I64(CVM_MF_HSH_DATW12, hsh_dat[12]);
+CP2_MF_I64(CVM_MF_HSH_DATW13, hsh_dat[13]);
+CP2_MF_I64(CVM_MF_HSH_DATW14, hsh_dat[14]);
+CP2_MF_I64(CVM_MF_HSH_DATW15, hsh_dat[15]);
+CP2_MF_I64(CVM_MF_HSH_IVW0, hsh_iv[0]);
+CP2_MF_I64(CVM_MF_HSH_IVW1, hsh_iv[1]);
+CP2_MF_I64(CVM_MF_HSH_IVW2, hsh_iv[2]);
+CP2_MF_I64(CVM_MF_HSH_IVW3, hsh_iv[3]);
+CP2_MF_I64(CVM_MF_HSH_IVW4, hsh_iv[4]);
+CP2_MF_I64(CVM_MF_HSH_IVW5, hsh_iv[5]);
+CP2_MF_I64(CVM_MF_HSH_IVW6, hsh_iv[6]);
+CP2_MF_I64(CVM_MF_HSH_IVW7, hsh_iv[7]);
CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT0, hsh_dat, 0);
CP2_MT_HSH_PAIR(CVM_MT_HSH_DAT1, hsh_dat, 1);
@@ -254,11 +304,13 @@ CP2_MT_I64(CVM_MT_GFM_MUL0, gfm_mul[0]);
CP2_MT_I64(CVM_MT_GFM_MUL1, gfm_mul[1]);
CP2_MT_I64(CVM_MT_GFM_RESINP0, gfm_resinp[0]);
CP2_MT_I64(CVM_MT_GFM_RESINP1, gfm_resinp[1]);
+CP2_MT_XOR_I64(CVM_MT_GFM_XOR0, gfm_resinp[0]);
CP2_MT_U16(CVM_MT_GFM_POLY, gfm_poly);
CP2_MT_U8_MASKED(CVM_MT_CRC_LEN, crc_len, 0xf);
CP2_MT_U32(CVM_MT_CRC_POLYNOMIAL, crc_poly);
CP2_MT_HELPER(CVM_MT_CRC_POLYNOMIAL_REFLECT, crc_write_polynomial_reflect);
+
CP2_MT_HELPER(CVM_MT_CRC_IV_REFLECT, crc_write_iv_reflect);
CP2_MT_HELPER(CVM_MT_CRC_BYTE, crc_write_byte);
CP2_MT_HELPER(CVM_MT_CRC_HALF, crc_write_half);
@@ -272,6 +324,56 @@ CP2_MT_HELPER(CVM_MT_CRC_DWORD_REFLECT, crc_write_dword_reflect);
CP2_MT_HELPER(CVM_MT_CRC_VAR_REFLECT, crc_write_var_reflect);
CP2_MT_HELPER(CVM_MT_GFM_XORMUL1_REFLECT, gfm_xormul1_reflect);
CP2_MT_HELPER(CVM_MT_GFM_XORMUL1, gfm_xormul1);
+CP2_MT_I64(CVM_MT_SHA3_DAT24, sha3_dat24);
+CP2_MT_I64(CVM_MT_SHA3_DAT15, hsh_dat[15]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT0, sha3_dat[0]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT1, sha3_dat[1]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT2, sha3_dat[2]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT3, sha3_dat[3]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT4, sha3_dat[4]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT5, sha3_dat[5]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT6, sha3_dat[6]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT7, sha3_dat[7]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT8, sha3_dat[8]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT9, sha3_dat[9]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT10, sha3_dat[10]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT11, sha3_dat[11]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT12, sha3_dat[12]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT13, sha3_dat[13]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT14, sha3_dat[14]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT15, sha3_dat[15]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT16, sha3_dat[16]);
+CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT17, sha3_dat[17]);
+CP2_MT_HELPER_ENV(CVM_MT_SHA3_STARTOP, sha3_startop);
+CP2_MT_HELPER(CVM_MT_HSH_STARTSHA1_COMPAT, hsh_startsha1_compat);
+CP2_MT_I64(CVM_MT_HSH_DATW0, hsh_dat[0]);
+CP2_MT_I64(CVM_MT_HSH_DATW1, hsh_dat[1]);
+CP2_MT_I64(CVM_MT_HSH_DATW2, hsh_dat[2]);
+CP2_MT_I64(CVM_MT_HSH_DATW3, hsh_dat[3]);
+CP2_MT_I64(CVM_MT_HSH_DATW4, hsh_dat[4]);
+CP2_MT_I64(CVM_MT_HSH_DATW5, hsh_dat[5]);
+CP2_MT_I64(CVM_MT_HSH_DATW6, hsh_dat[6]);
+CP2_MT_I64(CVM_MT_HSH_DATW7, hsh_dat[7]);
+CP2_MT_I64(CVM_MT_HSH_DATW8, hsh_dat[8]);
+CP2_MT_I64(CVM_MT_HSH_DATW9, hsh_dat[9]);
+CP2_MT_I64(CVM_MT_HSH_DATW10, hsh_dat[10]);
+CP2_MT_I64(CVM_MT_HSH_DATW11, hsh_dat[11]);
+CP2_MT_I64(CVM_MT_HSH_DATW12, hsh_dat[12]);
+CP2_MT_I64(CVM_MT_HSH_DATW13, hsh_dat[13]);
+CP2_MT_I64(CVM_MT_HSH_DATW14, hsh_dat[14]);
+CP2_MT_I64(CVM_MT_HSH_DATW15, hsh_dat[15]);
+CP2_MT_I64(CVM_MT_HSH_IVW0, hsh_iv[0]);
+CP2_MT_I64(CVM_MT_HSH_IVW1, hsh_iv[1]);
+CP2_MT_I64(CVM_MT_HSH_IVW2, hsh_iv[2]);
+CP2_MT_I64(CVM_MT_HSH_IVW3, hsh_iv[3]);
+CP2_MT_I64(CVM_MT_HSH_IVW4, hsh_iv[4]);
+CP2_MT_I64(CVM_MT_HSH_IVW5, hsh_iv[5]);
+CP2_MT_I64(CVM_MT_HSH_IVW6, hsh_iv[6]);
+CP2_MT_I64(CVM_MT_HSH_IVW7, hsh_iv[7]);
+CP2_MT_HELPER(CVM_MT_HSH_STARTMD5, hsh_startmd5);
+CP2_MT_HELPER(CVM_MT_HSH_STARTSHA256, hsh_startsha256);
+CP2_MT_HELPER(CVM_MT_HSH_STARTSHA, hsh_startsha);
+CP2_MT_HELPER(CVM_MT_HSH_STARTSHA512, hsh_startsha512);
static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 17/23] target/mips: decode Octeon ZUC and SNOW3G COP2 selectors
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (15 preceding siblings ...)
2026-07-07 18:15 ` [PULL 16/23] target/mips: decode Octeon HSH and SHA3 " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 18/23] target/mips: decode Octeon block-cipher " Philippe Mathieu-Daudé
` (7 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add explicit decodetree entries and translator bindings for the Octeon
ZUC and SNOW3G COP2 operation selectors. These stream-cipher selectors
operate on the shared HSH register window state, so dispatch them through
the per-operation helpers added with the corresponding engine support.
Keep stream-cipher decode separate because these selectors share the HSH
register window with unrelated engines.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-17-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/tcg/octeon.decode | 4 ++++
target/mips/tcg/octeon_translate.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index b1a63b743f2..2b27fa205ff 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -265,8 +265,12 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_CRC_DWORD_REFLECT 010010 00101 rt:5 0001 0010 0001 0111 &cp2
CVM_MT_CRC_VAR_REFLECT 010010 00101 rt:5 0001 0010 0001 1000 &cp2
CVM_MT_HSH_STARTMD5 010010 00101 rt:5 0100 0000 0100 0111 &cp2
+ CVM_MT_SNOW3G_START 010010 00101 rt:5 0100 0000 0100 1101 &cp2
+ CVM_MT_SNOW3G_MORE 010010 00101 rt:5 0100 0000 0100 1110 &cp2
CVM_MT_HSH_STARTSHA256 010010 00101 rt:5 0100 0000 0100 1111 &cp2
CVM_MT_SHA3_STARTOP 010010 00101 rt:5 0100 0000 0101 0010 &cp2
+ CVM_MT_ZUC_START 010010 00101 rt:5 0100 0000 0101 0101 &cp2
+ CVM_MT_ZUC_MORE 010010 00101 rt:5 0100 0000 0101 0110 &cp2
CVM_MT_HSH_STARTSHA 010010 00101 rt:5 0100 0000 0101 0111 &cp2
CVM_MT_GFM_XORMUL1_REFLECT 010010 00101 rt:5 0100 0000 0101 1101 &cp2
CVM_MT_CRC_POLYNOMIAL 010010 00101 rt:5 0100 0010 0000 0000 &cp2
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 5497e5a6cec..b4663b35a34 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -345,6 +345,10 @@ CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT15, sha3_dat[15]);
CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT16, sha3_dat[16]);
CP2_MT_XOR_I64(CVM_MT_SHA3_XORDAT17, sha3_dat[17]);
CP2_MT_HELPER_ENV(CVM_MT_SHA3_STARTOP, sha3_startop);
+CP2_MT_HELPER(CVM_MT_ZUC_START, zuc_start);
+CP2_MT_HELPER(CVM_MT_ZUC_MORE, zuc_more);
+CP2_MT_HELPER(CVM_MT_SNOW3G_START, snow3g_start);
+CP2_MT_HELPER(CVM_MT_SNOW3G_MORE, snow3g_more);
CP2_MT_HELPER(CVM_MT_HSH_STARTSHA1_COMPAT, hsh_startsha1_compat);
CP2_MT_I64(CVM_MT_HSH_DATW0, hsh_dat[0]);
CP2_MT_I64(CVM_MT_HSH_DATW1, hsh_dat[1]);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 18/23] target/mips: decode Octeon block-cipher COP2 selectors
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (16 preceding siblings ...)
2026-07-07 18:15 ` [PULL 17/23] target/mips: decode Octeon ZUC and SNOW3G " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 19/23] target/mips: decode Octeon CHORD and LLM " Philippe Mathieu-Daudé
` (6 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add explicit decodetree entries and translator bindings for the Octeon
AES, SMS4, 3DES, KASUMI, and Camellia COP2 operation selectors. These
selectors consume or update engine state, so keep them as per-operation
helper calls while the simple block-cipher register moves remain direct
TCG loads and stores from the earlier register-selector patch.
This completes the block-cipher selector coverage without reintroducing a
generic runtime selector dispatch path.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-18-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/tcg/octeon.decode | 17 +++++++++++++++++
target/mips/tcg/octeon_translate.c | 17 +++++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 2b27fa205ff..4ac38d264c8 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -203,6 +203,8 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_AES_DEC_CBC0 010010 00101 rt:5 0000 0001 0000 1100 &cp2
CVM_MT_AES_DEC0 010010 00101 rt:5 0000 0001 0000 1110 &cp2
CVM_MT_AES_KEYLENGTH 010010 00101 rt:5 0000 0001 0001 0000 &cp2
+ CVM_MT_CAMELLIA_FL 010010 00101 rt:5 0000 0001 0001 0101 &cp2
+ CVM_MT_CAMELLIA_FLINV 010010 00101 rt:5 0000 0001 0001 0110 &cp2
CVM_MT_CRC_IV 010010 00101 rt:5 0000 0010 0000 0001 &cp2
CVM_MT_CRC_IV_REFLECT 010010 00101 rt:5 0000 0010 0001 0001 &cp2
CVM_MT_CRC_BYTE 010010 00101 rt:5 0000 0010 0000 0100 &cp2
@@ -264,6 +266,15 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_CRC_VAR 010010 00101 rt:5 0001 0010 0000 1000 &cp2
CVM_MT_CRC_DWORD_REFLECT 010010 00101 rt:5 0001 0010 0001 0111 &cp2
CVM_MT_CRC_VAR_REFLECT 010010 00101 rt:5 0001 0010 0001 1000 &cp2
+ CVM_MT_AES_ENC_CBC1 010010 00101 rt:5 0011 0001 0000 1001 &cp2
+ CVM_MT_AES_ENC1 010010 00101 rt:5 0011 0001 0000 1011 &cp2
+ CVM_MT_AES_DEC_CBC1 010010 00101 rt:5 0011 0001 0000 1101 &cp2
+ CVM_MT_AES_DEC1 010010 00101 rt:5 0011 0001 0000 1111 &cp2
+ CVM_MT_CAMELLIA_ROUND 010010 00101 rt:5 0011 0001 0001 0100 &cp2
+ CVM_MT_SMS4_ENC_CBC1 010010 00101 rt:5 0011 0001 0001 1001 &cp2
+ CVM_MT_SMS4_ENC1 010010 00101 rt:5 0011 0001 0001 1011 &cp2
+ CVM_MT_SMS4_DEC_CBC1 010010 00101 rt:5 0011 0001 0001 1101 &cp2
+ CVM_MT_SMS4_DEC1 010010 00101 rt:5 0011 0001 0001 1111 &cp2
CVM_MT_HSH_STARTMD5 010010 00101 rt:5 0100 0000 0100 0111 &cp2
CVM_MT_SNOW3G_START 010010 00101 rt:5 0100 0000 0100 1101 &cp2
CVM_MT_SNOW3G_MORE 010010 00101 rt:5 0100 0000 0100 1110 &cp2
@@ -273,6 +284,12 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_ZUC_MORE 010010 00101 rt:5 0100 0000 0101 0110 &cp2
CVM_MT_HSH_STARTSHA 010010 00101 rt:5 0100 0000 0101 0111 &cp2
CVM_MT_GFM_XORMUL1_REFLECT 010010 00101 rt:5 0100 0000 0101 1101 &cp2
+ CVM_MT_3DES_ENC_CBC 010010 00101 rt:5 0100 0000 1000 1000 &cp2
+ CVM_MT_KAS_ENC_CBC 010010 00101 rt:5 0100 0000 1000 1001 &cp2
+ CVM_MT_3DES_ENC 010010 00101 rt:5 0100 0000 1000 1010 &cp2
+ CVM_MT_KAS_ENC 010010 00101 rt:5 0100 0000 1000 1011 &cp2
+ CVM_MT_3DES_DEC_CBC 010010 00101 rt:5 0100 0000 1000 1100 &cp2
+ CVM_MT_3DES_DEC 010010 00101 rt:5 0100 0000 1000 1110 &cp2
CVM_MT_CRC_POLYNOMIAL 010010 00101 rt:5 0100 0010 0000 0000 &cp2
CVM_MT_CRC_POLYNOMIAL_REFLECT 010010 00101 rt:5 0100 0010 0001 0000 &cp2
CVM_MT_HSH_STARTSHA512 010010 00101 rt:5 0100 0010 0100 1111 &cp2
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index b4663b35a34..76792c9c874 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -349,6 +349,23 @@ CP2_MT_HELPER(CVM_MT_ZUC_START, zuc_start);
CP2_MT_HELPER(CVM_MT_ZUC_MORE, zuc_more);
CP2_MT_HELPER(CVM_MT_SNOW3G_START, snow3g_start);
CP2_MT_HELPER(CVM_MT_SNOW3G_MORE, snow3g_more);
+CP2_MT_HELPER(CVM_MT_AES_ENC_CBC1, aes_enc_cbc1);
+CP2_MT_HELPER(CVM_MT_AES_ENC1, aes_enc1);
+CP2_MT_HELPER(CVM_MT_AES_DEC_CBC1, aes_dec_cbc1);
+CP2_MT_HELPER(CVM_MT_AES_DEC1, aes_dec1);
+CP2_MT_HELPER(CVM_MT_SMS4_ENC_CBC1, sms4_enc_cbc1);
+CP2_MT_HELPER(CVM_MT_SMS4_ENC1, sms4_enc1);
+CP2_MT_HELPER(CVM_MT_SMS4_DEC_CBC1, sms4_dec_cbc1);
+CP2_MT_HELPER(CVM_MT_SMS4_DEC1, sms4_dec1);
+CP2_MT_HELPER(CVM_MT_3DES_ENC_CBC, des3_enc_cbc);
+CP2_MT_HELPER(CVM_MT_KAS_ENC_CBC, kas_enc_cbc);
+CP2_MT_HELPER(CVM_MT_3DES_ENC, des3_enc);
+CP2_MT_HELPER(CVM_MT_KAS_ENC, kas_enc);
+CP2_MT_HELPER(CVM_MT_3DES_DEC_CBC, des3_dec_cbc);
+CP2_MT_HELPER(CVM_MT_3DES_DEC, des3_dec);
+CP2_MT_HELPER(CVM_MT_CAMELLIA_FL, camellia_fl);
+CP2_MT_HELPER(CVM_MT_CAMELLIA_FLINV, camellia_flinv);
+CP2_MT_HELPER(CVM_MT_CAMELLIA_ROUND, camellia_round);
CP2_MT_HELPER(CVM_MT_HSH_STARTSHA1_COMPAT, hsh_startsha1_compat);
CP2_MT_I64(CVM_MT_HSH_DATW0, hsh_dat[0]);
CP2_MT_I64(CVM_MT_HSH_DATW1, hsh_dat[1]);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 19/23] target/mips: decode Octeon CHORD and LLM COP2 selectors
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (17 preceding siblings ...)
2026-07-07 18:15 ` [PULL 18/23] target/mips: decode Octeon block-cipher " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 20/23] target/mips: add Octeon CvmCount RDHWR support Philippe Mathieu-Daudé
` (5 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add explicit decodetree entries and translator bindings for the Octeon
CHORD and sparse LLM COP2 selectors. CHORD and LLM use their own COP2
selector window rather than the crypto engine windows covered by the
preceding decode patches.
This completes the explicit COP2 selector coverage by adding the
remaining CHORD and LLM register and operation selectors.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Acked-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-19-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/tcg/octeon.decode | 13 +++++++++++++
target/mips/tcg/octeon_translate.c | 13 +++++++++++++
2 files changed, 26 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 4ac38d264c8..a8c944e6681 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -167,6 +167,9 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MF_GFM_RESINP0 010010 00001 rt:5 0000 0010 0101 1010 &cp2
CVM_MF_GFM_RESINP1 010010 00001 rt:5 0000 0010 0101 1011 &cp2
CVM_MF_GFM_POLY 010010 00001 rt:5 0000 0010 0101 1110 &cp2
+ CVM_MF_CHORD 010010 00001 rt:5 0000 0100 0000 0000 &cp2
+ CVM_MF_LLM_DATA0 010010 00001 rt:5 0000 0100 0000 0010 &cp2
+ CVM_MF_LLM_DATA1 010010 00001 rt:5 0000 0100 0000 1010 &cp2
CVM_MT_HSH_DAT0 010010 00101 rt:5 0000 0000 0100 0000 &cp2
CVM_MT_HSH_DAT1 010010 00101 rt:5 0000 0000 0100 0001 &cp2
CVM_MT_HSH_DAT2 010010 00101 rt:5 0000 0000 0100 0010 &cp2
@@ -261,6 +264,16 @@ LDX 011111 ..... ..... ..... 01000 001010 @lx
CVM_MT_SHA3_XORDAT15 010010 00101 rt:5 0000 0010 1100 1111 &cp2
CVM_MT_SHA3_XORDAT16 010010 00101 rt:5 0000 0010 1101 0000 &cp2
CVM_MT_SHA3_XORDAT17 010010 00101 rt:5 0000 0010 1101 0001 &cp2
+ CVM_MT_LLM_READ_ADDR0 010010 00101 rt:5 0000 0100 0000 0000 &cp2
+ CVM_MT_LLM_WRITE_ADDR0 010010 00101 rt:5 0000 0100 0000 0001 &cp2
+ CVM_MT_LLM_DATA0 010010 00101 rt:5 0000 0100 0000 0010 &cp2
+ CVM_MT_LLM_READ64_ADDR0 010010 00101 rt:5 0000 0100 0000 0100 &cp2
+ CVM_MT_LLM_WRITE64_ADDR0 010010 00101 rt:5 0000 0100 0000 0101 &cp2
+ CVM_MT_LLM_READ_ADDR1 010010 00101 rt:5 0000 0100 0000 1000 &cp2
+ CVM_MT_LLM_WRITE_ADDR1 010010 00101 rt:5 0000 0100 0000 1001 &cp2
+ CVM_MT_LLM_DATA1 010010 00101 rt:5 0000 0100 0000 1010 &cp2
+ CVM_MT_LLM_READ64_ADDR1 010010 00101 rt:5 0000 0100 0000 1100 &cp2
+ CVM_MT_LLM_WRITE64_ADDR1 010010 00101 rt:5 0000 0100 0000 1101 &cp2
CVM_MT_CRC_LEN 010010 00101 rt:5 0001 0010 0000 0010 &cp2
CVM_MT_CRC_DWORD 010010 00101 rt:5 0001 0010 0000 0111 &cp2
CVM_MT_CRC_VAR 010010 00101 rt:5 0001 0010 0000 1000 &cp2
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 76792c9c874..a0db6630c7d 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -235,6 +235,9 @@ CP2_MF_I64(CVM_MF_GFM_MUL1, gfm_mul[1]);
CP2_MF_I64(CVM_MF_GFM_RESINP0, gfm_resinp[0]);
CP2_MF_I64(CVM_MF_GFM_RESINP1, gfm_resinp[1]);
CP2_MF_U16(CVM_MF_GFM_POLY, gfm_poly);
+CP2_MF_I64(CVM_MF_CHORD, chord);
+CP2_MF_I64(CVM_MF_LLM_DATA0, llm_data[0]);
+CP2_MF_I64(CVM_MF_LLM_DATA1, llm_data[1]);
CP2_MF_HELPER(CVM_MF_CRC_IV_REFLECT, crc_iv_reflect);
CP2_MF_I64(CVM_MF_SHA3_DAT24, sha3_dat24);
@@ -306,6 +309,8 @@ CP2_MT_I64(CVM_MT_GFM_RESINP0, gfm_resinp[0]);
CP2_MT_I64(CVM_MT_GFM_RESINP1, gfm_resinp[1]);
CP2_MT_XOR_I64(CVM_MT_GFM_XOR0, gfm_resinp[0]);
CP2_MT_U16(CVM_MT_GFM_POLY, gfm_poly);
+CP2_MT_I64(CVM_MT_LLM_DATA0, llm_data[0]);
+CP2_MT_I64(CVM_MT_LLM_DATA1, llm_data[1]);
CP2_MT_U8_MASKED(CVM_MT_CRC_LEN, crc_len, 0xf);
CP2_MT_U32(CVM_MT_CRC_POLYNOMIAL, crc_poly);
@@ -395,6 +400,14 @@ CP2_MT_HELPER(CVM_MT_HSH_STARTMD5, hsh_startmd5);
CP2_MT_HELPER(CVM_MT_HSH_STARTSHA256, hsh_startsha256);
CP2_MT_HELPER(CVM_MT_HSH_STARTSHA, hsh_startsha);
CP2_MT_HELPER(CVM_MT_HSH_STARTSHA512, hsh_startsha512);
+CP2_MT_HELPER(CVM_MT_LLM_READ_ADDR0, llm_read_addr0);
+CP2_MT_HELPER(CVM_MT_LLM_WRITE_ADDR0, llm_write_addr0);
+CP2_MT_HELPER(CVM_MT_LLM_READ64_ADDR0, llm_read64_addr0);
+CP2_MT_HELPER(CVM_MT_LLM_WRITE64_ADDR0, llm_write64_addr0);
+CP2_MT_HELPER(CVM_MT_LLM_READ_ADDR1, llm_read_addr1);
+CP2_MT_HELPER(CVM_MT_LLM_WRITE_ADDR1, llm_write_addr1);
+CP2_MT_HELPER(CVM_MT_LLM_READ64_ADDR1, llm_read64_addr1);
+CP2_MT_HELPER(CVM_MT_LLM_WRITE64_ADDR1, llm_write64_addr1);
static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 20/23] target/mips: add Octeon CvmCount RDHWR support
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (18 preceding siblings ...)
2026-07-07 18:15 ` [PULL 19/23] target/mips: decode Octeon CHORD and LLM " Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 21/23] tests/tcg/mips: cover Octeon QMAC instructions Philippe Mathieu-Daudé
` (4 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Octeon exposes CvmCount through RDHWR register 31. Add the Octeon-only
decode path, enable the corresponding HWREna bit for linux-user, and use
an unsigned mask when checking HWREna so bit 31 is handled safely.
For user-mode emulation, return host ticks as a monotonic counter source
suitable for existing Octeon userspace code. In system mode, fall back to
the existing CP0 Count value.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-20-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/helper.h | 1 +
target/mips/cpu.c | 1 +
target/mips/tcg/op_helper.c | 13 ++++++++++++-
target/mips/tcg/translate.c | 11 +++++++++++
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 17 +++++++++++++++++
5 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 141350e80ad..786117813ae 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -255,6 +255,7 @@ DEF_HELPER_1(rdhwr_ccres, tl, env)
DEF_HELPER_1(rdhwr_performance, tl, env)
DEF_HELPER_1(rdhwr_xnp, tl, env)
DEF_HELPER_1(rdhwr_chord, tl, env)
+DEF_HELPER_1(rdhwr_cvmcount, tl, env)
DEF_HELPER_2(pmon, void, env, int)
DEF_HELPER_1(wait, void, env)
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index b223b767c9c..d72044aef61 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -320,6 +320,7 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
env->CP0_HWREna |= 0x0000000F;
if (env->insn_flags & INSN_OCTEON) {
env->CP0_HWREna |= 0x40000000u;
+ env->CP0_HWREna |= 0x80000000u;
}
if (env->CP0_Config1 & (1 << CP0C1_FP)) {
env->CP0_Status |= (1 << CP0St_CU1);
diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c
index 3e586e3049e..df1b5c37347 100644
--- a/target/mips/tcg/op_helper.c
+++ b/target/mips/tcg/op_helper.c
@@ -25,6 +25,7 @@
#include "exec/memop.h"
#include "fpu_helper.h"
#include "qemu/crc32c.h"
+#include "qemu/timer.h"
#include <zlib.h>
static inline target_ulong bitswap(target_ulong v)
@@ -209,7 +210,7 @@ target_ulong helper_yield(CPUMIPSState *env, target_ulong arg)
static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc)
{
- if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) {
+ if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1u << reg))) {
return;
}
do_raise_exception(env, EXCP_RI, pc);
@@ -261,6 +262,16 @@ target_ulong helper_rdhwr_chord(CPUMIPSState *env)
return env->octeon_crypto.chord;
}
+target_ulong helper_rdhwr_cvmcount(CPUMIPSState *env)
+{
+ check_hwrena(env, 31, GETPC());
+#ifdef CONFIG_USER_ONLY
+ return cpu_get_host_ticks();
+#else
+ return (uint32_t)cpu_mips_get_count(env);
+#endif
+}
+
void helper_pmon(CPUMIPSState *env, int function)
{
function /= 2;
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 1f449328825..e3467d15251 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -10933,6 +10933,17 @@ void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
gen_helper_rdhwr_chord(t0, tcg_env);
gen_store_gpr(t0, rt);
break;
+ case 31:
+ if (!(ctx->insn_flags & INSN_OCTEON)) {
+ gen_reserved_instruction(ctx);
+ break;
+ }
+ translator_io_start(&ctx->base);
+ gen_helper_rdhwr_cvmcount(t0, tcg_env);
+ gen_store_gpr(t0, rt);
+ gen_save_pc(ctx->base.pc_next + 4);
+ ctx->base.is_jmp = DISAS_EXIT;
+ break;
default: /* Invalid */
MIPS_INVAL("rdhwr");
gen_reserved_instruction(ctx);
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index f3c52d7829e..6480c8532a1 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -330,6 +330,22 @@ static uint64_t octeon_cop2_gfm_mul_reflect_readback(uint64_t value)
return rd;
}
+static uint64_t octeon_rdhwr31_non_decreasing(void)
+{
+ uint64_t first, second;
+
+ asm volatile(
+ ".word 0x7c08f83b\n\t" /* rdhwr $8, $31 */
+ ".word 0x7c09f83b\n\t" /* rdhwr $9, $31 */
+ "move %[first], $8\n\t"
+ "move %[second], $9\n\t"
+ : [first] "=r" (first), [second] "=r" (second)
+ :
+ : "$8", "$9");
+
+ return second >= first;
+}
+
int main(void)
{
assert(octeon_baddu(0x123, 0x0f0) == 0x13);
@@ -358,6 +374,7 @@ int main(void)
0x0123456789abcdefULL) == 0xf7b3d591e6a2c480ULL);
assert(octeon_cop2_gfm_mul_reflect_readback(
0xfedcba9876543210ULL) == 0x084c2a6e195d3b7fULL);
+ assert(octeon_rdhwr31_non_decreasing());
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 21/23] tests/tcg/mips: cover Octeon QMAC instructions
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (19 preceding siblings ...)
2026-07-07 18:15 ` [PULL 20/23] target/mips: add Octeon CvmCount RDHWR support Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 22/23] target/sh4: fixup tcg for sh4 fipr/ftrv instructions Philippe Mathieu-Daudé
` (3 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add smoke coverage for Octeon QMAC and QMACS fixed-point accumulator
instruction paths.
The coverage exercises normal accumulation, saturating accumulation, and
the sticky saturation flag.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-21-daef7a0d8b04@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 40 +++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index 6480c8532a1..6fffc820103 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -129,6 +129,43 @@ static uint64_t octeon_vmm0(uint64_t mpl0, uint64_t p0,
return rd;
}
+static uint64_t octeon_qmac_lo(uint64_t rs, uint64_t rt, uint64_t lo)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[rs]\n\t"
+ "move $9, %[rt]\n\t"
+ "mtlo %[lo]\n\t"
+ "mthi $0\n\t"
+ ".word 0x710904d2\n\t" /* qmac.03 $8, $9 */
+ "mflo %[rd]\n\t"
+ : [rd] "=r" (rd)
+ : [rs] "r" (rs), [rt] "r" (rt), [lo] "r" (lo)
+ : "$8", "$9");
+
+ return rd;
+}
+
+static uint64_t octeon_qmacs_state(uint64_t rs, uint64_t rt, uint64_t lo)
+{
+ uint64_t hi, rd;
+
+ asm volatile(
+ "move $8, %[rs]\n\t"
+ "move $9, %[rt]\n\t"
+ "mtlo %[lo]\n\t"
+ "mthi $0\n\t"
+ ".word 0x71090012\n\t" /* qmacs.00 $8, $9 */
+ "mfhi %[hi]\n\t"
+ "mflo %[rd]\n\t"
+ : [hi] "=r" (hi), [rd] "=r" (rd)
+ : [rs] "r" (rs), [rt] "r" (rt), [lo] "r" (lo)
+ : "$8", "$9");
+
+ return ((hi & 1) << 32) | (rd & 0xffffffff);
+}
+
static uint64_t octeon_vmm0_zeroes_mpl1(void)
{
uint64_t rd;
@@ -355,6 +392,9 @@ int main(void)
assert(octeon_seq(0xabc, 0xdef) == 0);
assert(octeon_sne(0xabc, 0xabc) == 0);
assert(octeon_sne(0xabc, 0xdef) == 1);
+ assert(octeon_qmac_lo(0x0003000000000000ULL, 2, 1) == 13);
+ assert(octeon_qmacs_state(1, 1, 0x7ffffffe) == 0x17fffffffULL);
+ assert(octeon_qmacs_state(0x8000, 0x8000, 0) == 0x17fffffffULL);
assert(octeon_vmulu(5, 7, 11) == 46);
assert(octeon_vmm0(5, 13, 7, 11) == 59);
assert(octeon_vmm0_zeroes_mpl1() == 0);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 22/23] target/sh4: fixup tcg for sh4 fipr/ftrv instructions
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (20 preceding siblings ...)
2026-07-07 18:15 ` [PULL 21/23] tests/tcg/mips: cover Octeon QMAC instructions Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 23/23] qemu-options: Do not list -enable-kvm on MIPS binaries Philippe Mathieu-Daudé
` (2 subsequent siblings)
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
From: Randy Schifflin <randy.schifflin@gmail.com>
Fixes TCG generation for sh4 `fipr` and `ftrv` instructions.
Updates the current logic for these instructions to check the
FPSCR register appropriately (according to the sh4 cpu manual, `fipr`
and `ftrv` are only defined when the FPSCR register PR flag is 0).
Also fixes the mth/nth-vector operands by multiplying by 4 to convert
to the correct floating point register offset.
Signed-off-by: Randy Schifflin <randy.schifflin@gmail.com>
Reviewed-by: Yoshinori Sato <yoshinori.sato@nifty.com>
Message-ID: <20260629-fixup-sh4-tcg-fpu-instructions-b4-v1-2-4356b305f971@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/sh4/op_helper.c | 2 +-
target/sh4/translate.c | 15 +++++----------
2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index 90c065b217b..777380f8e40 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -488,7 +488,7 @@ void helper_ftrv(CPUSH4State *env, uint32_t n)
float32 p;
bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
- bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
+ bank_vector = (env->sr & FPSCR_FR) ? 16 + n : n;
set_float_exception_flags(0, &env->fp_status);
for (i = 0 ; i < 4 ; i++) {
r[i] = float32_zero;
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index d38a6bd352f..373950fd662 100644
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -377,11 +377,6 @@ static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
goto do_illegal; \
}
-#define CHECK_FPSCR_PR_1 \
- if (!(ctx->tbflags & FPSCR_PR)) { \
- goto do_illegal; \
- }
-
#define CHECK_SH4A \
if (!(ctx->features & SH_FEATURE_SH4A)) { \
goto do_illegal; \
@@ -1740,22 +1735,22 @@ static void _decode_opc(DisasContext * ctx)
return;
case 0xf0ed: /* fipr FVm,FVn */
CHECK_FPU_ENABLED
- CHECK_FPSCR_PR_1
+ CHECK_FPSCR_PR_0
{
- TCGv m = tcg_constant_i32((ctx->opcode >> 8) & 3);
- TCGv n = tcg_constant_i32((ctx->opcode >> 10) & 3);
+ TCGv m = tcg_constant_i32(((ctx->opcode >> 8) & 3) << 2);
+ TCGv n = tcg_constant_i32(((ctx->opcode >> 10) & 3) << 2);
gen_helper_fipr(tcg_env, m, n);
return;
}
break;
case 0xf0fd: /* ftrv XMTRX,FVn */
CHECK_FPU_ENABLED
- CHECK_FPSCR_PR_1
+ CHECK_FPSCR_PR_0
{
if ((ctx->opcode & 0x0300) != 0x0100) {
goto do_illegal;
}
- TCGv n = tcg_constant_i32((ctx->opcode >> 10) & 3);
+ TCGv n = tcg_constant_i32(((ctx->opcode >> 10) & 3) << 2);
gen_helper_ftrv(tcg_env, n);
return;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PULL 23/23] qemu-options: Do not list -enable-kvm on MIPS binaries
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (21 preceding siblings ...)
2026-07-07 18:15 ` [PULL 22/23] target/sh4: fixup tcg for sh4 fipr/ftrv instructions Philippe Mathieu-Daudé
@ 2026-07-07 18:15 ` Philippe Mathieu-Daudé
2026-07-08 5:19 ` [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
2026-07-08 15:32 ` Stefan Hajnoczi
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 18:15 UTC (permalink / raw)
To: qemu-devel
When removing KVM support in commit 630decdfccd we forgot
to remove MIPS of the '-enable-kvm' option help. Do it now.
Fixes: 630decdfccd ("buildsys: Remove MIPS KVM")
Inspired-by: Miao Wang <shankerwangmiao@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20260707095723.36591-1-philmd@oss.qualcomm.com>
---
qemu-options.hx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qemu-options.hx b/qemu-options.hx
index e44b47de681..ccb71743ee3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -5163,7 +5163,7 @@ ERST
DEF("enable-kvm", 0, QEMU_OPTION_enable_kvm, \
"-enable-kvm enable KVM full virtualization support\n",
- QEMU_ARCH_ARM | QEMU_ARCH_I386 | QEMU_ARCH_MIPS | QEMU_ARCH_PPC |
+ QEMU_ARCH_ARM | QEMU_ARCH_I386 | QEMU_ARCH_PPC |
QEMU_ARCH_RISCV | QEMU_ARCH_S390X)
SRST
``-enable-kvm``
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PULL 00/23] MIPS & SH4 patches for 2026-07-07
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (22 preceding siblings ...)
2026-07-07 18:15 ` [PULL 23/23] qemu-options: Do not list -enable-kvm on MIPS binaries Philippe Mathieu-Daudé
@ 2026-07-08 5:19 ` Philippe Mathieu-Daudé
2026-07-08 15:32 ` Stefan Hajnoczi
24 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-08 5:19 UTC (permalink / raw)
To: qemu-devel
On 7/7/26 20:15, Philippe Mathieu-Daudé wrote:
> The following changes since commit 916ab315cc2b3a3825ebb399d83339660144d5bd:
>
> Merge tag 'pull-nvme-20260707' of https://gitlab.com/birkelund/qemu into staging (2026-07-07 07:09:38 +0200)
>
> are available in the Git repository at:
>
> https://github.com/philmd/qemu.git tags/mips-20260707
>
> for you to fetch changes up to f086625548aa2f839c119243121ef863ecb606a0:
>
> qemu-options: Do not list -enable-kvm on MIPS binaries (2026-07-07 20:14:51 +0200)
>
> ----------------------------------------------------------------
> MIPS and SuperH patches queue
>
> - MIPS Octeon COP2 crypto opcodes
> - Fix for SH4 FIPR/FTRV vector math opcodes
>
> ----------------------------------------------------------------
I forgot to mention I deliberately ignored this checkpatch.pl warning:
3/25 Checking commit b5e013415478 (target/mips: add Octeon COP2 crypto
helper plumbing)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
target/mips/tcg/octeon_crypto.c
$ ./scripts/get_maintainer.pl -f target/mips/tcg/octeon_crypto.c
"Philippe Mathieu-Daudé" <philmd@mailo.com> (odd fixer:MIPS TCG CPUs)
Aurelien Jarno <aurelien@aurel32.net> (reviewer:MIPS TCG CPUs)
Jiaxun Yang <jiaxun.yang@flygoat.com> (reviewer:MIPS TCG CPUs)
Aleksandar Rikalo <arikalo@gmail.com> (reviewer:MIPS TCG CPUs)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PULL 00/23] MIPS & SH4 patches for 2026-07-07
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
` (23 preceding siblings ...)
2026-07-08 5:19 ` [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
@ 2026-07-08 15:32 ` Stefan Hajnoczi
24 siblings, 0 replies; 26+ messages in thread
From: Stefan Hajnoczi @ 2026-07-08 15:32 UTC (permalink / raw)
To: Philippe Mathieu-Daudé; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2026-07-09 9:06 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-07 18:15 [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 01/23] target/mips: add Octeon COP2 crypto state Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 02/23] target/mips: add Octeon COP2 crypto helper plumbing Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 03/23] target/mips: add Octeon CRC COP2 helpers Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 04/23] target/mips: add Octeon GFM " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 05/23] target/mips: add Octeon SHA3 " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 06/23] target/mips: add Octeon ZUC " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 07/23] target/mips: add Octeon SNOW3G " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 08/23] target/mips: add Octeon AES " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 09/23] target/mips: add Octeon SMS4 " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 10/23] target/mips: add Octeon 3DES and KASUMI " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 11/23] target/mips: add Octeon Camellia " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 12/23] target/mips: add Octeon HSH " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 13/23] target/mips: add Octeon CHORD and LLM " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 14/23] target/mips: decode Octeon COP2 register selectors Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 15/23] target/mips: decode Octeon CRC and GFM COP2 selectors Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 16/23] target/mips: decode Octeon HSH and SHA3 " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 17/23] target/mips: decode Octeon ZUC and SNOW3G " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 18/23] target/mips: decode Octeon block-cipher " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 19/23] target/mips: decode Octeon CHORD and LLM " Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 20/23] target/mips: add Octeon CvmCount RDHWR support Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 21/23] tests/tcg/mips: cover Octeon QMAC instructions Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 22/23] target/sh4: fixup tcg for sh4 fipr/ftrv instructions Philippe Mathieu-Daudé
2026-07-07 18:15 ` [PULL 23/23] qemu-options: Do not list -enable-kvm on MIPS binaries Philippe Mathieu-Daudé
2026-07-08 5:19 ` [PULL 00/23] MIPS & SH4 patches for 2026-07-07 Philippe Mathieu-Daudé
2026-07-08 15:32 ` Stefan Hajnoczi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.