Skip to content

Commit 889857e

Browse files
committed
Revert most churn changes and add simpler solution
Replaces C-fallback with cleaner assembly-based misalignment handling. Signed-off-by: Brendan Moran <brendan.moran@arm.com>
1 parent 172da82 commit 889857e

7 files changed

Lines changed: 98 additions & 476 deletions

File tree

dev/fips202/armv81m/mve.h

Lines changed: 5 additions & 211 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717

1818
#if !defined(__ASSEMBLER__)
1919
#include "../api.h"
20-
21-
#define MLK_KECCAKF1600_X4_BITINTERLEAVED_ODD_WORDS 50u
20+
#include "src/fips202_native_armv81m.h"
2221

2322
/*
2423
* Native x4 permutation
@@ -34,238 +33,33 @@ static MLK_INLINE int mlk_keccak_f1600_x4_native(uint64_t *state)
3433
return mlk_keccak_f1600_x4_native_impl(state);
3534
}
3635

37-
/*
38-
* Slow path for buffers that the MVE word gather/scatter main loops cannot
39-
* access directly. Returning MLK_NATIVE_FUNC_FALLBACK is not safe here because
40-
* the Armv8.1-M x4 state is bit-interleaved, while the generic C x4 fallback
41-
* uses four contiguous scalar Keccak states.
42-
*/
43-
static MLK_INLINE uint32_t mlk_keccakf1600x4_bitinterleave_even_u8(uint8_t x)
44-
{
45-
uint32_t r;
46-
47-
r = x & 0x01u;
48-
r |= (x & 0x04u) >> 1;
49-
r |= (x & 0x10u) >> 2;
50-
r |= (x & 0x40u) >> 3;
51-
return r;
52-
}
53-
54-
static MLK_INLINE uint32_t mlk_keccakf1600x4_bitinterleave_odd_u8(uint8_t x)
55-
{
56-
uint32_t r;
57-
58-
r = (x & 0x02u) >> 1;
59-
r |= (x & 0x08u) >> 2;
60-
r |= (x & 0x20u) >> 3;
61-
r |= (x & 0x80u) >> 4;
62-
return r;
63-
}
64-
65-
static MLK_INLINE uint8_t mlk_keccakf1600x4_bitdeinterleave_u8(uint32_t even,
66-
uint32_t odd)
67-
{
68-
uint8_t r;
69-
70-
r = (uint8_t)(even & 0x01u);
71-
r = (uint8_t)(r | ((odd & 0x01u) << 1));
72-
r = (uint8_t)(r | ((even & 0x02u) << 1));
73-
r = (uint8_t)(r | ((odd & 0x02u) << 2));
74-
r = (uint8_t)(r | ((even & 0x04u) << 2));
75-
r = (uint8_t)(r | ((odd & 0x04u) << 3));
76-
r = (uint8_t)(r | ((even & 0x08u) << 3));
77-
r = (uint8_t)(r | ((odd & 0x08u) << 4));
78-
return r;
79-
}
80-
81-
static MLK_INLINE void mlk_keccakf1600x4_xor_bitinterleaved_byte(
82-
uint64_t *state, uint8_t data, unsigned byte_offset, unsigned instance)
83-
{
84-
unsigned lane;
85-
unsigned byte_in_lane;
86-
unsigned state_index;
87-
unsigned shift;
88-
uint64_t even;
89-
uint64_t odd;
90-
91-
lane = byte_offset >> 3;
92-
byte_in_lane = byte_offset & 7u;
93-
state_index = (2u * lane) + (instance >> 1);
94-
shift = 32u * (instance & 1u);
95-
96-
even = (uint64_t)mlk_keccakf1600x4_bitinterleave_even_u8(data)
97-
<< (4u * byte_in_lane);
98-
odd = (uint64_t)mlk_keccakf1600x4_bitinterleave_odd_u8(data)
99-
<< (4u * byte_in_lane);
100-
101-
state[state_index] ^= even << shift;
102-
state[MLK_KECCAKF1600_X4_BITINTERLEAVED_ODD_WORDS + state_index] ^= odd
103-
<< shift;
104-
}
105-
106-
static MLK_INLINE uint8_t mlk_keccakf1600x4_extract_bitinterleaved_byte(
107-
uint64_t *state, unsigned byte_offset, unsigned instance)
108-
{
109-
unsigned lane;
110-
unsigned byte_in_lane;
111-
unsigned state_index;
112-
unsigned shift;
113-
uint32_t even;
114-
uint32_t odd;
115-
116-
lane = byte_offset >> 3;
117-
byte_in_lane = byte_offset & 7u;
118-
state_index = (2u * lane) + (instance >> 1);
119-
shift = 32u * (instance & 1u);
120-
121-
even =
122-
(uint32_t)((state[state_index] >> shift) >> (4u * byte_in_lane)) & 0x0Fu;
123-
odd = (uint32_t)((state[MLK_KECCAKF1600_X4_BITINTERLEAVED_ODD_WORDS +
124-
state_index] >>
125-
shift) >>
126-
(4u * byte_in_lane)) &
127-
0x0Fu;
128-
129-
return mlk_keccakf1600x4_bitdeinterleave_u8(even, odd);
130-
}
131-
132-
static MLK_INLINE void mlk_keccakf1600_xor_bytes_x4_bitinterleaved_c(
133-
uint64_t *state, const uint8_t *data0, const uint8_t *data1,
134-
const uint8_t *data2, const uint8_t *data3, unsigned offset,
135-
unsigned length)
136-
{
137-
unsigned i;
138-
139-
for (i = 0; i < length; i++)
140-
{
141-
unsigned byte_offset;
142-
143-
byte_offset = offset + i;
144-
mlk_keccakf1600x4_xor_bitinterleaved_byte(state, data0[i], byte_offset, 0);
145-
mlk_keccakf1600x4_xor_bitinterleaved_byte(state, data1[i], byte_offset, 1);
146-
mlk_keccakf1600x4_xor_bitinterleaved_byte(state, data2[i], byte_offset, 2);
147-
mlk_keccakf1600x4_xor_bitinterleaved_byte(state, data3[i], byte_offset, 3);
148-
}
149-
}
150-
151-
static MLK_INLINE void mlk_keccakf1600_extract_bytes_x4_bitinterleaved_c(
152-
uint64_t *state, uint8_t *data0, uint8_t *data1, uint8_t *data2,
153-
uint8_t *data3, unsigned offset, unsigned length)
154-
{
155-
unsigned i;
156-
157-
for (i = 0; i < length; i++)
158-
{
159-
unsigned byte_offset;
160-
161-
byte_offset = offset + i;
162-
data0[i] =
163-
mlk_keccakf1600x4_extract_bitinterleaved_byte(state, byte_offset, 0);
164-
data1[i] =
165-
mlk_keccakf1600x4_extract_bitinterleaved_byte(state, byte_offset, 1);
166-
data2[i] =
167-
mlk_keccakf1600x4_extract_bitinterleaved_byte(state, byte_offset, 2);
168-
data3[i] =
169-
mlk_keccakf1600x4_extract_bitinterleaved_byte(state, byte_offset, 3);
170-
}
171-
}
172-
17336
/*
17437
* Native x4 XOR bytes (with on-the-fly bit interleaving)
17538
*/
176-
#define mlk_keccak_f1600_x4_state_xor_bytes \
177-
MLK_NAMESPACE(keccak_f1600_x4_state_xor_bytes_asm)
178-
void mlk_keccak_f1600_x4_state_xor_bytes(void *state, const uint8_t *data0,
179-
const uint8_t *data1,
180-
const uint8_t *data2,
181-
const uint8_t *data3, unsigned offset,
182-
unsigned length);
183-
18439
MLK_MUST_CHECK_RETURN_VALUE
18540
static MLK_INLINE int mlk_keccakf1600_xor_bytes_x4_native(
18641
uint64_t *state, const uint8_t *data0, const uint8_t *data1,
18742
const uint8_t *data2, const uint8_t *data3, unsigned offset,
18843
unsigned length)
18944
{
190-
unsigned offset_mod8;
191-
unsigned byte_prefix;
192-
unsigned main_length;
193-
194-
offset_mod8 = offset & 7u;
195-
byte_prefix = 0;
196-
if (offset_mod8 != 0u)
197-
{
198-
byte_prefix = 8u - offset_mod8;
199-
if (byte_prefix > length)
200-
{
201-
byte_prefix = length;
202-
}
203-
}
204-
205-
main_length = length - byte_prefix;
206-
if (main_length >= 8u &&
207-
((((uintptr_t)data0 + byte_prefix) | ((uintptr_t)data1 + byte_prefix) |
208-
((uintptr_t)data2 + byte_prefix) | ((uintptr_t)data3 + byte_prefix)) &
209-
3u) != 0u)
210-
{
211-
mlk_keccakf1600_xor_bytes_x4_bitinterleaved_c(state, data0, data1, data2,
212-
data3, offset, length);
213-
return MLK_NATIVE_FUNC_SUCCESS;
214-
}
215-
216-
mlk_keccak_f1600_x4_state_xor_bytes(state, data0, data1, data2, data3, offset,
217-
length);
45+
mlk_keccak_f1600_x4_state_xor_bytes_asm(state, data0, data1, data2, data3,
46+
offset, length);
21847
return MLK_NATIVE_FUNC_SUCCESS;
21948
}
22049

22150
/*
22251
* Native x4 extract bytes (with on-the-fly bit de-interleaving)
22352
*/
224-
#define mlk_keccak_f1600_x4_state_extract_bytes \
225-
MLK_NAMESPACE(keccak_f1600_x4_state_extract_bytes_asm)
226-
void mlk_keccak_f1600_x4_state_extract_bytes(void *state, uint8_t *data0,
227-
uint8_t *data1, uint8_t *data2,
228-
uint8_t *data3, unsigned offset,
229-
unsigned length);
230-
23153
MLK_MUST_CHECK_RETURN_VALUE
23254
static MLK_INLINE int mlk_keccakf1600_extract_bytes_x4_native(
23355
uint64_t *state, uint8_t *data0, uint8_t *data1, uint8_t *data2,
23456
uint8_t *data3, unsigned offset, unsigned length)
23557
{
236-
unsigned offset_mod8;
237-
unsigned byte_prefix;
238-
unsigned main_length;
239-
240-
offset_mod8 = offset & 7u;
241-
byte_prefix = 0;
242-
if (offset_mod8 != 0u)
243-
{
244-
byte_prefix = 8u - offset_mod8;
245-
if (byte_prefix > length)
246-
{
247-
byte_prefix = length;
248-
}
249-
}
250-
251-
main_length = length - byte_prefix;
252-
if (main_length >= 8u &&
253-
((((uintptr_t)data0 + byte_prefix) | ((uintptr_t)data1 + byte_prefix) |
254-
((uintptr_t)data2 + byte_prefix) | ((uintptr_t)data3 + byte_prefix)) &
255-
3u) != 0u)
256-
{
257-
mlk_keccakf1600_extract_bytes_x4_bitinterleaved_c(
258-
state, data0, data1, data2, data3, offset, length);
259-
return MLK_NATIVE_FUNC_SUCCESS;
260-
}
261-
262-
mlk_keccak_f1600_x4_state_extract_bytes(state, data0, data1, data2, data3,
263-
offset, length);
58+
mlk_keccak_f1600_x4_state_extract_bytes_asm(state, data0, data1, data2, data3,
59+
offset, length);
26460
return MLK_NATIVE_FUNC_SUCCESS;
26561
}
26662

26763
#endif /* !__ASSEMBLER__ */
26864

269-
#undef MLK_KECCAKF1600_X4_BITINTERLEAVED_ODD_WORDS
270-
27165
#endif /* !MLK_DEV_FIPS202_ARMV81M_MVE_H */

dev/fips202/armv81m/src/state_xor_bytes_x4_mve.S

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
// ---------------------------------------------------------------------------
5252
// Prologue -- if offset is not 8-byte aligned, absorb
5353
// min(length, 8-(offset%8)) bytes via predicated byte loads.
54-
// Main -- process full 8-byte groups via word-level gather loads,
55-
// bit-interleave, then VEOR into even/odd state halves.
54+
// Main -- process full 8-byte groups via vldrw.u32 gather loads when
55+
// 32-bit aligned, otherwise byte loads; bit-interleave, then
56+
// VEOR into even/odd state halves.
5657
// Tail -- absorb remaining <8 bytes via predicated byte loads.
5758

5859
#include "../../../../common.h"
@@ -303,13 +304,13 @@ MLK_ASM_FN_SYMBOL(keccak_f1600_x4_state_xor_bytes_asm)
303304
lsl mask, mask, off
304305
vmsr p0, mask
305306

306-
// Predicated byte loads of nB bytes per instance; post-increment of 4
307-
// positions qP for the main loop's [qP, #4]! loads.
307+
// Predicated byte loads of nB bytes per instance; post-increment to the
308+
// next lane start.
308309
vpstttt
309-
vldrbt.u8 qd0, [dp0], #4
310-
vldrbt.u8 qd1, [dp1], #4
311-
vldrbt.u8 qd2, [dp2], #4
312-
vldrbt.u8 qd3, [dp3], #4
310+
vldrbt.u8 qd0, [dp0], #8
311+
vldrbt.u8 qd1, [dp1], #8
312+
vldrbt.u8 qd2, [dp2], #8
313+
vldrbt.u8 qd3, [dp3], #8
313314

314315
// Transpose from per-instance layout to per-lane layout
315316
transpose_streams_to_lanes
@@ -320,20 +321,22 @@ MLK_ASM_FN_SYMBOL(keccak_f1600_x4_state_xor_bytes_asm)
320321
// XOR into state (post-increments rSE/rSO by 16)
321322
xor_lane_and_store_postinc q0, q1, qS0, qS1, rSE, rSO
322323

323-
// Build qP = {d0,d1,d2,d3} as u32 lanes for gather loads
324-
vmov qP[2], qP[0], dp0, dp2
325-
vmov qP[3], qP[1], dp1, dp3
326-
b keccak_f1600_x4_state_xor_bytes_asm_main_body
327-
328324
keccak_f1600_x4_state_xor_bytes_asm_pre_main:
325+
// dpN points at the next lane start; vldrw requires 32-bit alignment.
326+
orr tmp, dp0, dp1
327+
orr tmp, tmp, dp2
328+
orr tmp, tmp, dp3
329+
tst tmp, #3
330+
bne keccak_f1600_x4_state_xor_bytes_asm_main_body_byte
331+
329332
vmov qP[2], qP[0], dp0, dp2
330333
vmov qP[3], qP[1], dp1, dp3
331334
mov tmp, #4
332335
vsub.u32 qP, qP, tmp // pre-bias so first [qP,#4]! lands at original ptr
333336

334337
keccak_f1600_x4_state_xor_bytes_asm_main_body:
335338
// -----------------------------------------------------------------------
336-
// MAIN: process full 8-byte lanes
339+
// MAIN: process full 8-byte lanes with aligned gather-word loads
337340
// -----------------------------------------------------------------------
338341
lsr lr, length, #3
339342
wls lr, lr, keccak_f1600_x4_state_xor_bytes_asm_main_loop_end
@@ -351,9 +354,6 @@ keccak_f1600_x4_state_xor_bytes_asm_main_loop_start:
351354
le lr, keccak_f1600_x4_state_xor_bytes_asm_main_loop_start
352355
keccak_f1600_x4_state_xor_bytes_asm_main_loop_end:
353356

354-
// -----------------------------------------------------------------------
355-
// TAIL: absorb <8 remaining bytes at lane offset 0
356-
// -----------------------------------------------------------------------
357357
ands length, length, #7
358358
beq keccak_f1600_x4_state_xor_bytes_asm_exit
359359

@@ -363,12 +363,25 @@ keccak_f1600_x4_state_xor_bytes_asm_main_loop_end:
363363
vmov dp0, dp2, qP[2], qP[0]
364364
vmov dp1, dp3, qP[3], qP[1]
365365

366-
vctp.8 length
366+
keccak_f1600_x4_state_xor_bytes_asm_main_body_byte:
367+
// -----------------------------------------------------------------------
368+
// MAIN/TAIL: process remaining lanes using predicated byte loads
369+
// -----------------------------------------------------------------------
370+
cmp length, #0
371+
beq keccak_f1600_x4_state_xor_bytes_asm_exit
372+
keccak_f1600_x4_state_xor_bytes_asm_main_loop_byte_start:
373+
// Predicate with min(length, 8): a plain MVE byte vector load would
374+
// over-read the Keccak lane, and the last iteration may be a partial tail.
375+
mov nB, #8
376+
cmp length, #8
377+
it lo
378+
movlo nB, length
379+
vctp.8 nB
367380
vpstttt
368-
vldrbt.u8 qd0, [dp0]
369-
vldrbt.u8 qd1, [dp1]
370-
vldrbt.u8 qd2, [dp2]
371-
vldrbt.u8 qd3, [dp3]
381+
vldrbt.u8 qd0, [dp0], #8
382+
vldrbt.u8 qd1, [dp1], #8
383+
vldrbt.u8 qd2, [dp2], #8
384+
vldrbt.u8 qd3, [dp3], #8
372385

373386
// Transpose from per-instance layout to per-lane layout
374387
transpose_streams_to_lanes
@@ -377,7 +390,10 @@ keccak_f1600_x4_state_xor_bytes_asm_main_loop_end:
377390
to_bit_interleaving_4x q0, q1, q2, q3, q4
378391

379392
// XOR into state (post-increments rSE/rSO by 16)
380-
xor_lane_and_store_postinc qd0, qd1, qS0, qS1, rSE, rSO
393+
xor_lane_and_store_postinc q0, q1, qS0, qS1, rSE, rSO
394+
395+
subs length, length, nB
396+
bne keccak_f1600_x4_state_xor_bytes_asm_main_loop_byte_start
381397

382398
keccak_f1600_x4_state_xor_bytes_asm_exit:
383399
vpop {d8-d15}

mlkem/mlkem_native.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,6 @@
504504
#undef MLK_FIPS202_ARMV81M_NEED_X4
505505
#undef MLK_FIPS202_NATIVE_ARMV81M
506506
#undef MLK_FIPS202_NATIVE_ARMV81M_MVE_H
507-
#undef MLK_KECCAKF1600_X4_BITINTERLEAVED_ODD_WORDS
508507
#undef MLK_USE_FIPS202_X4_EXTRACT_BYTES_NATIVE
509508
#undef MLK_USE_FIPS202_X4_NATIVE
510509
#undef MLK_USE_FIPS202_X4_XOR_BYTES_NATIVE

mlkem/mlkem_native_asm.S

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,6 @@
528528
#undef MLK_FIPS202_ARMV81M_NEED_X4
529529
#undef MLK_FIPS202_NATIVE_ARMV81M
530530
#undef MLK_FIPS202_NATIVE_ARMV81M_MVE_H
531-
#undef MLK_KECCAKF1600_X4_BITINTERLEAVED_ODD_WORDS
532531
#undef MLK_USE_FIPS202_X4_EXTRACT_BYTES_NATIVE
533532
#undef MLK_USE_FIPS202_X4_NATIVE
534533
#undef MLK_USE_FIPS202_X4_XOR_BYTES_NATIVE

0 commit comments

Comments
 (0)