Commit e32e36298e for qemu.org
commit e32e36298e2645bf7c18efd9a031827681235030
Author: James Hilliard <james.hilliard1@gmail.com>
Date: Mon Jun 8 12:59:39 2026 -0600
target/mips: decode Octeon COP2 register selectors
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>
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 1e44c588dd..09fbc6c1e3 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 b0af2f4838..b33252dd1f 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 9153e37e9e..7a7445c40a 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;
}