@samitouri / QOSamiQemu / commits / e1ac6b2775

target/mips: add Octeon CRC COP2 helpers

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>

James Hilliard committed Jun 8, 2026 at 12:59 UTC e1ac6b277591a2e00233fad10d8736a97f07598e
2 files changed +145
target/mips/helper.h
+14
@@ -25,6 +25,20 @@ DEF_HELPER_3(crc32, tl, tl, tl, i32)
25 DEF_HELPER_3(crc32c, tl, tl, tl, i32)
26 DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32)
27
28 +/* Octeon COP2 selector operation helpers. */
29 +DEF_HELPER_1(octeon_cp2_mf_crc_iv_reflect, i64, env)
30 +DEF_HELPER_2(octeon_cp2_mt_crc_write_iv_reflect, void, env, i64)
31 +DEF_HELPER_2(octeon_cp2_mt_crc_write_byte, void, env, i64)
32 +DEF_HELPER_2(octeon_cp2_mt_crc_write_half, void, env, i64)
33 +DEF_HELPER_2(octeon_cp2_mt_crc_write_word, void, env, i64)
34 +DEF_HELPER_2(octeon_cp2_mt_crc_write_byte_reflect, void, env, i64)
35 +DEF_HELPER_2(octeon_cp2_mt_crc_write_half_reflect, void, env, i64)
36 +DEF_HELPER_2(octeon_cp2_mt_crc_write_word_reflect, void, env, i64)
37 +DEF_HELPER_2(octeon_cp2_mt_crc_write_dword, void, env, i64)
38 +DEF_HELPER_2(octeon_cp2_mt_crc_write_var, void, env, i64)
39 +DEF_HELPER_2(octeon_cp2_mt_crc_write_dword_reflect, void, env, i64)
40 +DEF_HELPER_2(octeon_cp2_mt_crc_write_var_reflect, void, env, i64)
41 +
42 /* microMIPS functions */
43 DEF_HELPER_4(lwm, void, env, tl, tl, i32)
44 DEF_HELPER_4(swm, void, env, tl, tl, i32)
target/mips/tcg/octeon_crypto.c
+131
@@ -14,3 +14,134 @@
14 #include "crypto/sm4.h"
15 #include "qemu/bitops.h"
16 #include "qemu/host-utils.h"
17 +
18 +static uint32_t octeon_crc_reflect32_by_byte(uint32_t v)
19 +{
20 + return bswap32(revbit32(v));
21 +}
22 +
23 +static uint32_t octeon_crc_state_reflect(const MIPSOcteonCryptoState *crypto)
24 +{
25 + return octeon_crc_reflect32_by_byte(crypto->crc_iv);
26 +}
27 +
28 +static void octeon_crc_set_state_reflect(MIPSOcteonCryptoState *crypto,
29 + uint32_t state)
30 +{
31 + crypto->crc_iv = octeon_crc_reflect32_by_byte(state);
32 +}
33 +
34 +static void octeon_crc_update_normal(MIPSOcteonCryptoState *crypto,
35 + uint64_t value, unsigned int bytes)
36 +{
37 + uint32_t crc = crypto->crc_iv;
38 + uint32_t poly = crypto->crc_poly;
39 +
40 + for (unsigned int i = 0; i < bytes; i++) {
41 + uint8_t byte = value >> ((bytes - 1 - i) * 8);
42 +
43 + crc ^= (uint32_t)byte << 24;
44 + for (int bit = 0; bit < 8; bit++) {
45 + if (crc & 0x80000000U) {
46 + crc = (crc << 1) ^ poly;
47 + } else {
48 + crc <<= 1;
49 + }
50 + }
51 + }
52 +
53 + crypto->crc_iv = crc;
54 +}
55 +
56 +static void octeon_crc_update_reflect(MIPSOcteonCryptoState *crypto,
57 + uint64_t value, unsigned int bytes)
58 +{
59 + uint32_t crc = octeon_crc_state_reflect(crypto);
60 + uint32_t poly = bswap32(crypto->crc_poly);
61 +
62 + for (unsigned int i = 0; i < bytes; i++) {
63 + uint8_t byte = value >> ((bytes - 1 - i) * 8);
64 +
65 + crc ^= byte;
66 + for (int bit = 0; bit < 8; bit++) {
67 + if (crc & 1U) {
68 + crc = (crc >> 1) ^ poly;
69 + } else {
70 + crc >>= 1;
71 + }
72 + }
73 + }
74 +
75 + octeon_crc_set_state_reflect(crypto, crc);
76 +}
77 +
78 +uint64_t helper_octeon_cp2_mf_crc_iv_reflect(CPUMIPSState *env)
79 +{
80 + return octeon_crc_reflect32_by_byte(env->octeon_crypto.crc_iv);
81 +}
82 +
83 +void helper_octeon_cp2_mt_crc_write_iv_reflect(CPUMIPSState *env,
84 + uint64_t value)
85 +{
86 + env->octeon_crypto.crc_iv =
87 + octeon_crc_reflect32_by_byte((uint32_t)value);
88 +}
89 +
90 +void helper_octeon_cp2_mt_crc_write_byte(CPUMIPSState *env, uint64_t value)
91 +{
92 + octeon_crc_update_normal(&env->octeon_crypto, value, 1);
93 +}
94 +
95 +void helper_octeon_cp2_mt_crc_write_half(CPUMIPSState *env, uint64_t value)
96 +{
97 + octeon_crc_update_normal(&env->octeon_crypto, value, 2);
98 +}
99 +
100 +void helper_octeon_cp2_mt_crc_write_word(CPUMIPSState *env, uint64_t value)
101 +{
102 + octeon_crc_update_normal(&env->octeon_crypto, value, 4);
103 +}
104 +
105 +void helper_octeon_cp2_mt_crc_write_dword(CPUMIPSState *env, uint64_t value)
106 +{
107 + octeon_crc_update_normal(&env->octeon_crypto, value, 8);
108 +}
109 +
110 +void helper_octeon_cp2_mt_crc_write_var(CPUMIPSState *env, uint64_t value)
111 +{
112 + MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
113 +
114 + octeon_crc_update_normal(crypto, value, MIN(8U, crypto->crc_len & 0xf));
115 +}
116 +
117 +void helper_octeon_cp2_mt_crc_write_byte_reflect(CPUMIPSState *env,
118 + uint64_t value)
119 +{
120 + octeon_crc_update_reflect(&env->octeon_crypto, value, 1);
121 +}
122 +
123 +void helper_octeon_cp2_mt_crc_write_half_reflect(CPUMIPSState *env,
124 + uint64_t value)
125 +{
126 + octeon_crc_update_reflect(&env->octeon_crypto, value, 2);
127 +}
128 +
129 +void helper_octeon_cp2_mt_crc_write_word_reflect(CPUMIPSState *env,
130 + uint64_t value)
131 +{
132 + octeon_crc_update_reflect(&env->octeon_crypto, value, 4);
133 +}
134 +
135 +void helper_octeon_cp2_mt_crc_write_dword_reflect(CPUMIPSState *env,
136 + uint64_t value)
137 +{
138 + octeon_crc_update_reflect(&env->octeon_crypto, value, 8);
139 +}
140 +
141 +void helper_octeon_cp2_mt_crc_write_var_reflect(CPUMIPSState *env,
142 + uint64_t value)
143 +{
144 + MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
145 +
146 + octeon_crc_update_reflect(crypto, value, MIN(8U, crypto->crc_len & 0xf));
147 +}