2 # Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
4 # Licensed under the OpenSSL license (the "License"). You may not use
5 # this file except in compliance with the License. You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
10 # ====================================================================
11 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 # project. The module is, however, dual licensed under OpenSSL and
13 # CRYPTOGAMS licenses depending on where you obtain it. For further
14 # details see http://www.openssl.org/~appro/cryptogams/.
15 # ====================================================================
17 # Poly1305 hash for C64x+.
21 # Performance is [incredible for a 32-bit processor] 1.82 cycles per
22 # processed byte. Comparison to compiler-generated code is problematic,
23 # because results were observed to vary from 2.1 to 7.6 cpb depending
24 # on compiler's ability to inline small functions. Compiler also
25 # disables interrupts for some reason, thus making interrupt response
26 # time dependent on input length. This module on the other hand is free
27 # from such limitation.
30 open STDOUT,">$output";
32 ($CTXA,$INPB,$LEN,$PADBIT)=("A4","B4","A6","B6");
33 ($H0,$H1,$H2,$H3,$H4,$H4a)=("A8","B8","A10","B10","B2",$LEN);
34 ($D0,$D1,$D2,$D3)= ("A9","B9","A11","B11");
35 ($R0,$R1,$R2,$R3,$S1,$S2,$S3,$S3b)=("A0","B0","A1","B1","A12","B12","A13","B13");
36 ($THREE,$R0b,$S2a)=("B7","B5","A5");
41 .if .ASSEMBLER_VERSION<7000000
45 .asg poly1305_init,_poly1305_init
46 .asg poly1305_blocks,_poly1305_blocks
47 .asg poly1305_emit,_poly1305_emit
59 .global _poly1305_init
62 LDNDW *${INPB}[0],B17:B16 ; load key material
63 LDNDW *${INPB}[1],A17:A16
67 STDW B9:B8,*${CTXA}[0] ; initialize h1:h0
68 || SHRU B0,4,B0 ; 0x0fffffff
70 STDW B9:B8,*${CTXA}[1] ; initialize h3:h2
71 || AND B0,B1,B1 ; 0x0ffffffc
72 STW B8,*${CTXA}[4] ; initialize h4
85 AND B16,B0,B20 ; r0 = key[0] & 0x0fffffff
86 || AND B17,B1,B22 ; r1 = key[1] & 0x0ffffffc
87 || EXTU B17,4,6,B16 ; r1>>2
88 AND A16,B1,B21 ; r2 = key[2] & 0x0ffffffc
89 || AND A17,B1,A23 ; r3 = key[3] & 0x0ffffffc
92 || ADD B22,B16,B16 ; s1 = r1 + r1>>2
94 STDW B21:B20,*${CTXA}[3] ; save r2:r0
95 || ADD B21,B18,B18 ; s2 = r2 + r2>>2
98 STDW B23:B22,*${CTXA}[4] ; save r3:r1
99 || ADD B23,B17,B19 ; s3 = r3 + r3>>2
100 || ADD B23,B17,B17 ; s3 = r3 + r3>>2
101 STDW B17:B16,*${CTXA}[5] ; save s3:s1
102 STDW B19:B18,*${CTXA}[6] ; save s3:s2
103 || ZERO A4 ; return 0
106 .global _poly1305_blocks
109 .asmfunc stack_usage(40)
110 SHRU $LEN,4,A2 ; A2 is loop counter, number of blocks
111 [!A2] BNOP RA ; no data
112 || [A2] STW FP,*SP--(40) ; save frame pointer and alloca(40)
114 [A2] STDW B13:B12,*SP[4] ; ABI says so
115 || [A2] MV $CTXA,$S3b ; borrow $S3b
116 [A2] STDW B11:B10,*SP[3]
117 || [A2] STDW A13:A12,*FP[-3]
118 [A2] STDW A11:A10,*FP[-4]
120 || [A2] LDDW *${S3b}[0],B25:B24 ; load h1:h0
121 [A2] LDNW *${INPB}++[4],$D0 ; load inp[0]
122 [A2] LDNW *${INPB}[-3],$D1 ; load inp[1]
124 LDDW *${CTXA}[1],B29:B28 ; load h3:h2, B28 is h2
125 LDNW *${INPB}[-2],$D2 ; load inp[2]
126 LDNW *${INPB}[-1],$D3 ; load inp[3]
128 LDDW *${CTXA}[3],$R2:$R0 ; load r2:r0
129 || LDDW *${S3b}[4],$R3:$R1 ; load r3:r1
132 LDDW *${CTXA}[5],$S3:$S1 ; load s3:s1
133 || LDDW *${S3b}[6],$S3b:$S2 ; load s3:s2
137 ADDU $D0,B24,$D0:$H0 ; h0+=inp[0]
138 || ADD $D0,B24,B27 ; B-copy of h0+inp[0]
140 ADDU $D1,B25,$D1:$H1 ; h1+=inp[1]
143 LDW *${CTXA}[4],$H4 ; load h4
145 || MV B29,B30 ; B30 is h3
149 MPY32U $H0,$R0,A17:A16
150 || MPY32U B27,$R1,B17:B16 ; MPY32U $H0,$R1,B17:B16
151 || ADDU $D0,$D1:$H1,B25:B24 ; ADDU $D0,$D1:$H1,$D1:$H1
152 || ADDU $D2,B28,$D2:$H2 ; h2+=inp[2]
154 MPY32U $H0,$R2,A19:A18
155 || MPY32U B27,$R3,B19:B18 ; MPY32U $H0,$R3,B19:B18
156 || ADD $D0,$H1,A24 ; A-copy of B24
158 || [A2] SUB A2,1,A2 ; decrement loop counter
160 MPY32U A24,$S3,A21:A20 ; MPY32U $H1,$S3,A21:A20
161 || MPY32U B24,$R0b,B21:B20 ; MPY32U $H1,$R0,B21:B20
162 || ADDU B25,$D2:$H2,$D2:$H2 ; ADDU $D1,$D2:$H2,$D2:$H2
163 || ADDU $D3,B30,$D3:$H3 ; h3+=inp[3]
164 || ADD B25,$H2,B25 ; B-copy of $H2
165 MPY32U A24,$R1,A23:A22 ; MPY32U $H1,$R1,A23:A22
166 || MPY32U B24,$R2,B23:B22 ; MPY32U $H1,$R2,B23:B22
168 MPY32U $H2,$S2,A25:A24
169 || MPY32U B25,$S3b,B25:B24 ; MPY32U $H2,$S3,B25:B24
170 || ADDU $D2,$D3:$H3,$D3:$H3
171 || ADD $PADBIT,$H4,$H4 ; h4+=padbit
172 MPY32U $H2,$R0,A27:A26
173 || MPY32U $H2,$R1,B27:B26
177 MPY32U $H3,$S1,A29:A28
178 || MPY32U $H3,$S2,B29:B28
179 || ADD A21,A17,A21 ; start accumulating "d3:d0"
181 || ADDU A20,A16,A17:A16
182 || ADDU B20,B16,B17:B16
183 || [A2] LDNW *${INPB}++[4],$D0 ; load inp[0]
184 MPY32U $H3,$S3,A31:A30
185 || MPY32U $H3,$R0b,B31:B30
188 || ADDU A22,A18,A19:A18
189 || ADDU B22,B18,B19:B18
190 || [A2] LDNW *${INPB}[-3],$D1 ; load inp[1]
193 || MPY32 $H4,$S2a,A20
196 || ADDU A24,A17:A16,A17:A16
197 || ADDU B24,B17:B16,B17:B16
198 || [A2] LDNW *${INPB}[-2],$D2 ; load inp[2]
202 || ADDU A26,A19:A18,A19:A18
203 || ADDU B26,B19:B18,B19:B18
204 || [A2] LDNW *${INPB}[-1],$D3 ; load inp[3]
207 || ADD A29,A21,A21 ; final hi("d0")
208 || ADD B29,B21,B21 ; final hi("d1")
209 || ADDU A28,A17:A16,A17:A16 ; final lo("d0")
210 || ADDU B28,B17:B16,B17:B16
211 ADD A31,A23,A23 ; final hi("d2")
212 || ADD B31,B23,B23 ; final hi("d3")
213 || ADDU A30,A19:A18,A19:A18
214 || ADDU B30,B19:B18,B19:B18
215 ADDU B20,B17:B16,B17:B16 ; final lo("d1")
216 || ADDU A20,A19:A18,A19:A18 ; final lo("d2")
217 ADDU B22,B19:B18,B19:B18 ; final lo("d3")
219 || ADD A17,A21,A21 ; "flatten" "d3:d0"
220 MV A19,B29 ; move to avoid cross-path stalls
221 ADDU A21,B17:B16,B27:B26 ; B26 is h1
223 || DMV B29,A18,B29:B28 ; move to avoid cross-path stalls
224 ADDU B27,B29:B28,B29:B28 ; B28 is h2
225 || [A2] SWAP2 $D0,$D0
227 || [A2] SWAP4 $D0,$D0
228 ADDU B29,B19:B18,B31:B30 ; B30 is h3
230 || MV A16,B24 ; B24 is h0
231 || [A2] SWAP2 $D1,$D1
233 || [A2] SWAP4 $D1,$D1
235 SHRU $H4,2,B16 ; last reduction step
236 || AND $H4,$THREE,$H4
237 ADDAW B16,B16,B16 ; 5*(h4>>2)
240 ADDU B24,B16,B25:B24 ; B24 is h0
241 || [A2] SWAP2 $D2,$D2
242 ADDU B26,B25,B27:B26 ; B26 is h1
243 || [A2] SWAP4 $D2,$D2
244 ADDU B28,B27,B29:B28 ; B28 is h2
245 || [A2] ADDU $D0,B24,$D0:$H0 ; h0+=inp[0]
246 || [A2] ADD $D0,B24,B27 ; B-copy of h0+inp[0]
247 ADDU B30,B29,B31:B30 ; B30 is h3
249 || [A2] ADDU $D1,B26,$D1:$H1 ; h1+=inp[1]
250 ;;===== branch to loop? is taken here
252 LDDW *FP[-4],A11:A10 ; ABI says so
254 || LDDW *SP[3],B11:B10
258 LDW *++SP(40),FP ; restore frame pointer
260 STDW B25:B24,*${CTXA}[0] ; save h1:h0
261 STDW B29:B28,*${CTXA}[1] ; save h3:h2
262 STW $H4,*${CTXA}[4] ; save h4
267 my ($MAC,$NONCEA,$NONCEB)=($INPB,$LEN,$PADBIT);
270 .global _poly1305_emit
274 LDDW *${CTXA}[0],A17:A16 ; load h1:h0
275 LDDW *${CTXA}[1],A19:A18 ; load h3:h2
276 LDW *${CTXA}[4],A20 ; load h4
279 MVK 5,A22 ; compare to modulus
281 || LDW *${NONCEA}[0],A8
282 || LDW *${NONCEB}[1],B8
284 || LDW *${NONCEA}[2],A9
285 || LDW *${NONCEB}[3],B9
290 SHRU A29,2,A2 ; check for overflow in 130-th bit
292 [A2] MV A22,A16 ; select
297 || ADDU A8,A16,A23:A22 ; accumulate nonce
300 ADDU A23,A25:A24,A25:A24
303 ADDU A25,A27:A26,A27:A26
318 STNW A22,*${MAC}[0] ; write the result
327 .cstring "Poly1305 for C64x+, CRYPTOGAMS by <appro\@openssl.org>"