Line data Source code
1 : #include "fd_chacha_rng.h"
2 : #include "../../util/simd/fd_avx512.h"
3 :
4 485367248 : #define wwu_rol16(a) wwb_exch_adj_pair( (a) )
5 485367248 : #define wwu_rol12(a) wwu_rol( (a), 12 )
6 485367248 : #define wwu_rol7(a) wwu_rol( (a), 7 )
7 :
8 : static inline __attribute__((always_inline)) wwu_t
9 485367248 : wwu_rol8( wwu_t x ) {
10 485367248 : wwb_t const mask =
11 485367248 : wwb_bcast_hex( 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14 );
12 485367248 : return _mm512_shuffle_epi8( x, mask );
13 485367248 : }
14 :
15 : static void
16 : fd_chacha_rng_refill_avx512( fd_chacha_rng_t * rng,
17 9660781 : ulong rnd2_cnt ) {
18 :
19 : /* This function should only be called if the buffer is empty. */
20 9660781 : if( FD_UNLIKELY( rng->buf_off != rng->buf_fill ) ) {
21 0 : FD_LOG_CRIT(( "refill out of sync: buf_off=%lu buf_fill=%lu", rng->buf_off, rng->buf_fill ));
22 0 : }
23 :
24 9660781 : wwu_t iv0 = wwu_bcast( 0x61707865U );
25 9660781 : wwu_t iv1 = wwu_bcast( 0x3320646eU );
26 9660781 : wwu_t iv2 = wwu_bcast( 0x79622d32U );
27 9660781 : wwu_t iv3 = wwu_bcast( 0x6b206574U );
28 9660781 : wwu_t zero = wwu_zero();
29 :
30 : /* Unpack key equivalent to:
31 :
32 : c4 = wwu_bcast( (uint const *)(rng->key)[0] );
33 : c5 = wwu_bcast( (uint const *)(rng->key)[1] );
34 : ...
35 : cB = wwu_bcast( (uint const *)(rng->key)[7] ); */
36 :
37 9660781 : __m128i key_lo_v = _mm_load_si128( (__m128i const *)rng->key ); /* [0,1,2,3] */
38 9660781 : __m128i key_hi_v = _mm_load_si128( (__m128i const *)rng->key+1 ); /* [4,5,6,7] */
39 9660781 : wwu_t key_lo = _mm512_broadcast_i32x4( key_lo_v ); /* [0,1,2,3,0,1,2,3] */
40 9660781 : wwu_t key_hi = _mm512_broadcast_i32x4( key_hi_v ); /* [4,5,6,7,4,5,6,7] */
41 9660781 : wwu_t k0 = _mm512_shuffle_epi32( key_lo, 0x00 );
42 9660781 : wwu_t k1 = _mm512_shuffle_epi32( key_lo, 0x55 );
43 9660781 : wwu_t k2 = _mm512_shuffle_epi32( key_lo, 0xaa );
44 9660781 : wwu_t k3 = _mm512_shuffle_epi32( key_lo, 0xff );
45 9660781 : wwu_t k4 = _mm512_shuffle_epi32( key_hi, 0x00 );
46 9660781 : wwu_t k5 = _mm512_shuffle_epi32( key_hi, 0x55 );
47 9660781 : wwu_t k6 = _mm512_shuffle_epi32( key_hi, 0xaa );
48 9660781 : wwu_t k7 = _mm512_shuffle_epi32( key_hi, 0xff );
49 :
50 : /* Derive block index (64-bit counter split across words 12-13) */
51 :
52 9660781 : ulong idx = rng->buf_fill / FD_CHACHA_BLOCK_SZ; /* really a right shift */
53 9660781 : wwu_t offsets = wwu( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 );
54 9660781 : wwu_t idxs_lo = wwu_add( wwu_bcast( (uint)idx ), offsets );
55 9660781 : int carry = wwu_lt( idxs_lo, offsets );
56 9660781 : wwu_t idxs_hi = wwu_add_if( carry, wwu_bcast( (uint)(idx>>32) ), wwu_bcast( 1U ), wwu_bcast( (uint)(idx>>32) ) );
57 :
58 : /* Run through the round function */
59 :
60 9660781 : wwu_t c0 = iv0; wwu_t c1 = iv1; wwu_t c2 = iv2; wwu_t c3 = iv3;
61 9660781 : wwu_t c4 = k0; wwu_t c5 = k1; wwu_t c6 = k2; wwu_t c7 = k3;
62 9660781 : wwu_t c8 = k4; wwu_t c9 = k5; wwu_t cA = k6; wwu_t cB = k7;
63 9660781 : wwu_t cC = idxs_lo; wwu_t cD = idxs_hi; wwu_t cE = zero; wwu_t cF = zero;
64 :
65 9660781 : # define QUARTER_ROUND(a,b,c,d) \
66 485367248 : do { \
67 485367248 : a = wwu_add( a, b ); d = wwu_xor( d, a ); d = wwu_rol16( d ); \
68 485367248 : c = wwu_add( c, d ); b = wwu_xor( b, c ); b = wwu_rol12( b ); \
69 485367248 : a = wwu_add( a, b ); d = wwu_xor( d, a ); d = wwu_rol8( d ); \
70 485367248 : c = wwu_add( c, d ); b = wwu_xor( b, c ); b = wwu_rol7( b ); \
71 485367248 : } while(0)
72 :
73 70331687 : for( ulong i=0UL; i<rnd2_cnt; i++ ) {
74 60670906 : QUARTER_ROUND( c0, c4, c8, cC );
75 60670906 : QUARTER_ROUND( c1, c5, c9, cD );
76 60670906 : QUARTER_ROUND( c2, c6, cA, cE );
77 60670906 : QUARTER_ROUND( c3, c7, cB, cF );
78 60670906 : QUARTER_ROUND( c0, c5, cA, cF );
79 60670906 : QUARTER_ROUND( c1, c6, cB, cC );
80 60670906 : QUARTER_ROUND( c2, c7, c8, cD );
81 60670906 : QUARTER_ROUND( c3, c4, c9, cE );
82 60670906 : }
83 9660781 : # undef QUARTER_ROUND
84 :
85 : /* Finalize */
86 :
87 9660781 : c0 = wwu_add( c0, iv0 );
88 9660781 : c1 = wwu_add( c1, iv1 );
89 9660781 : c2 = wwu_add( c2, iv2 );
90 9660781 : c3 = wwu_add( c3, iv3 );
91 9660781 : c4 = wwu_add( c4, k0 );
92 9660781 : c5 = wwu_add( c5, k1 );
93 9660781 : c6 = wwu_add( c6, k2 );
94 9660781 : c7 = wwu_add( c7, k3 );
95 9660781 : c8 = wwu_add( c8, k4 );
96 9660781 : c9 = wwu_add( c9, k5 );
97 9660781 : cA = wwu_add( cA, k6 );
98 9660781 : cB = wwu_add( cB, k7 );
99 9660781 : cC = wwu_add( cC, idxs_lo );
100 9660781 : cD = wwu_add( cD, idxs_hi );
101 : //cE = wwu_add( cE, zero );
102 : //cF = wwu_add( cF, zero );
103 :
104 : /* Transpose matrix to get output vector */
105 :
106 9660781 : wwu_transpose_16x16( c0, c1, c2, c3, c4, c5, c6, c7,
107 9660781 : c8, c9, cA, cB, cC, cD, cE, cF,
108 9660781 : c0, c1, c2, c3, c4, c5, c6, c7,
109 9660781 : c8, c9, cA, cB, cC, cD, cE, cF );
110 :
111 : /* Update ring buffer */
112 :
113 9660781 : uint * out = (uint *)rng->buf;
114 9660781 : wwu_st( out+0x00, c0 ); wwu_st( out+0x10, c1 );
115 9660781 : wwu_st( out+0x20, c2 ); wwu_st( out+0x30, c3 );
116 9660781 : wwu_st( out+0x40, c4 ); wwu_st( out+0x50, c5 );
117 9660781 : wwu_st( out+0x60, c6 ); wwu_st( out+0x70, c7 );
118 9660781 : wwu_st( out+0x80, c8 ); wwu_st( out+0x90, c9 );
119 9660781 : wwu_st( out+0xa0, cA ); wwu_st( out+0xb0, cB );
120 9660781 : wwu_st( out+0xc0, cC ); wwu_st( out+0xd0, cD );
121 9660781 : wwu_st( out+0xe0, cE ); wwu_st( out+0xf0, cF );
122 :
123 : /* Update ring descriptor */
124 :
125 9660781 : rng->buf_fill += 16*FD_CHACHA_BLOCK_SZ;
126 9660781 : }
127 :
128 : void
129 5989484 : fd_chacha8_rng_refill_avx512( fd_chacha_rng_t * rng ) {
130 5989484 : fd_chacha_rng_refill_avx512( rng, 4UL );
131 5989484 : }
132 :
133 : void
134 3671297 : fd_chacha20_rng_refill_avx512( fd_chacha_rng_t * rng ) {
135 3671297 : fd_chacha_rng_refill_avx512( rng, 10UL );
136 3671297 : }
|