target/mips: add Octeon SHA3 COP2 helpers
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>
James Hilliard committed
Jun 8, 2026 at 12:59 UTC
20d1f0e84238f0a0c4d7937204252c3d52e1731f
2 files changed
+94
target/mips/helper.h
+1
@@ -47,6 +47,7 @@ DEF_HELPER_2(octeon_cp2_mt_gfm_mul_reflect1, void, env, i64)
47
DEF_HELPER_2(octeon_cp2_mt_gfm_xor0_reflect, void, env, i64)
48
DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1_reflect, void, env, i64)
49
DEF_HELPER_2(octeon_cp2_mt_gfm_xormul1, void, env, i64)
50
+DEF_HELPER_1(octeon_cp2_mt_sha3_startop, void, env)
51
52
/* microMIPS functions */
53
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
target/mips/tcg/octeon_crypto.c
+93
@@ -153,6 +153,94 @@ static void octeon_gfm_mul64_uia2(const uint64_t x[2], const uint64_t y[2],
153
out[1] = revbit64(res);
154
}
155
156
+static const uint64_t octeon_sha3_round_constants[24] = {
157
+ 0x0000000000000001ULL, 0x0000000000008082ULL,
158
+ 0x800000000000808aULL, 0x8000000080008000ULL,
159
+ 0x000000000000808bULL, 0x0000000080000001ULL,
160
+ 0x8000000080008081ULL, 0x8000000000008009ULL,
161
+ 0x000000000000008aULL, 0x0000000000000088ULL,
162
+ 0x0000000080008009ULL, 0x000000008000000aULL,
163
+ 0x000000008000808bULL, 0x800000000000008bULL,
164
+ 0x8000000000008089ULL, 0x8000000000008003ULL,
165
+ 0x8000000000008002ULL, 0x8000000000000080ULL,
166
+ 0x000000000000800aULL, 0x800000008000000aULL,
167
+ 0x8000000080008081ULL, 0x8000000000008080ULL,
168
+ 0x0000000080000001ULL, 0x8000000080008008ULL,
169
+};
170
+
171
+static const uint8_t octeon_sha3_rotation_constants[24] = {
172
+ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
173
+ 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
174
+};
175
+
176
+static const uint8_t octeon_sha3_pi_lanes[24] = {
177
+ 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
178
+ 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
179
+};
180
+
181
+static uint64_t octeon_sha3_reg_to_lane(uint64_t value)
182
+{
183
+ /*
184
+ * The COP2 register interface is consumed by big-endian MIPS code as
185
+ * 64-bit register values, while Keccak lanes are byte-little-endian.
186
+ */
187
+ return bswap64(value);
188
+}
189
+
190
+static uint64_t octeon_sha3_lane_to_reg(uint64_t value)
191
+{
192
+ return bswap64(value);
193
+}
194
+
195
+static void octeon_sha3_permute(MIPSOcteonCryptoState *crypto)
196
+{
197
+ uint64_t state[25];
198
+
199
+ for (int i = 0; i < 25; i++) {
200
+ state[i] = octeon_sha3_reg_to_lane(crypto->sha3_dat[i]);
201
+ }
202
+
203
+ for (int round = 0; round < 24; round++) {
204
+ uint64_t bc[5];
205
+ uint64_t temp;
206
+
207
+ for (int x = 0; x < 5; x++) {
208
+ bc[x] = state[x] ^ state[5 + x] ^ state[10 + x] ^
209
+ state[15 + x] ^ state[20 + x];
210
+ }
211
+ for (int x = 0; x < 5; x++) {
212
+ temp = bc[(x + 4) % 5] ^ rol64(bc[(x + 1) % 5], 1);
213
+ for (int y = 0; y < 25; y += 5) {
214
+ state[y + x] ^= temp;
215
+ }
216
+ }
217
+
218
+ temp = state[1];
219
+ for (int i = 0; i < 24; i++) {
220
+ uint64_t next = state[octeon_sha3_pi_lanes[i]];
221
+
222
+ state[octeon_sha3_pi_lanes[i]] =
223
+ rol64(temp, octeon_sha3_rotation_constants[i]);
224
+ temp = next;
225
+ }
226
+
227
+ for (int y = 0; y < 25; y += 5) {
228
+ for (int x = 0; x < 5; x++) {
229
+ bc[x] = state[y + x];
230
+ }
231
+ for (int x = 0; x < 5; x++) {
232
+ state[y + x] = bc[x] ^ ((~bc[(x + 1) % 5]) & bc[(x + 2) % 5]);
233
+ }
234
+ }
235
+
236
+ state[0] ^= octeon_sha3_round_constants[round];
237
+ }
238
+
239
+ for (int i = 0; i < 25; i++) {
240
+ crypto->sha3_dat[i] = octeon_sha3_lane_to_reg(state[i]);
241
+ }
242
+}
243
+
244
uint64_t helper_octeon_cp2_mf_crc_iv_reflect(CPUMIPSState *env)
245
{
246
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)
310
octeon_gfm_xormul1_common(crypto, value);
311
}
312
313
+void helper_octeon_cp2_mt_sha3_startop(CPUMIPSState *env)
314
+{
315
+ octeon_sha3_permute(&env->octeon_crypto);
316
+}
317
+
318
void helper_octeon_cp2_mt_crc_write_iv_reflect(CPUMIPSState *env,
319
uint64_t value)
320
{