From: James Hilliard <[email protected]> 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 <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-15-daef7a0d8...@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <[email protected]> --- 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
