update go packages
[platform/core/system/edge-orchestration.git] / vendor / golang.org / x / crypto / poly1305 / sum_vmsl_s390x.s
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // +build s390x,go1.11,!gccgo,!appengine
6
7 #include "textflag.h"
8
9 // Implementation of Poly1305 using the vector facility (vx) and the VMSL instruction.
10
11 // constants
12 #define EX0   V1
13 #define EX1   V2
14 #define EX2   V3
15
16 // temporaries
17 #define T_0 V4
18 #define T_1 V5
19 #define T_2 V6
20 #define T_3 V7
21 #define T_4 V8
22 #define T_5 V9
23 #define T_6 V10
24 #define T_7 V11
25 #define T_8 V12
26 #define T_9 V13
27 #define T_10 V14
28
29 // r**2 & r**4
30 #define R_0  V15
31 #define R_1  V16
32 #define R_2  V17
33 #define R5_1 V18
34 #define R5_2 V19
35 // key (r)
36 #define RSAVE_0 R7
37 #define RSAVE_1 R8
38 #define RSAVE_2 R9
39 #define R5SAVE_1 R10
40 #define R5SAVE_2 R11
41
42 // message block
43 #define M0 V20
44 #define M1 V21
45 #define M2 V22
46 #define M3 V23
47 #define M4 V24
48 #define M5 V25
49
50 // accumulator
51 #define H0_0 V26
52 #define H1_0 V27
53 #define H2_0 V28
54 #define H0_1 V29
55 #define H1_1 V30
56 #define H2_1 V31
57
58 GLOBL ·keyMask<>(SB), RODATA, $16
59 DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f
60 DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f
61
62 GLOBL ·bswapMask<>(SB), RODATA, $16
63 DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908
64 DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100
65
66 GLOBL ·constants<>(SB), RODATA, $48
67 // EX0
68 DATA ·constants<>+0(SB)/8, $0x18191a1b1c1d1e1f
69 DATA ·constants<>+8(SB)/8, $0x0000050403020100
70 // EX1
71 DATA ·constants<>+16(SB)/8, $0x18191a1b1c1d1e1f
72 DATA ·constants<>+24(SB)/8, $0x00000a0908070605
73 // EX2
74 DATA ·constants<>+32(SB)/8, $0x18191a1b1c1d1e1f
75 DATA ·constants<>+40(SB)/8, $0x0000000f0e0d0c0b
76
77 GLOBL ·c<>(SB), RODATA, $48
78 // EX0
79 DATA ·c<>+0(SB)/8, $0x0000050403020100
80 DATA ·c<>+8(SB)/8, $0x0000151413121110
81 // EX1
82 DATA ·c<>+16(SB)/8, $0x00000a0908070605
83 DATA ·c<>+24(SB)/8, $0x00001a1918171615
84 // EX2
85 DATA ·c<>+32(SB)/8, $0x0000000f0e0d0c0b
86 DATA ·c<>+40(SB)/8, $0x0000001f1e1d1c1b
87
88 GLOBL ·reduce<>(SB), RODATA, $32
89 // 44 bit
90 DATA ·reduce<>+0(SB)/8, $0x0
91 DATA ·reduce<>+8(SB)/8, $0xfffffffffff
92 // 42 bit
93 DATA ·reduce<>+16(SB)/8, $0x0
94 DATA ·reduce<>+24(SB)/8, $0x3ffffffffff
95
96 // h = (f*g) % (2**130-5) [partial reduction]
97 // uses T_0...T_9 temporary registers
98 // input: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2
99 // temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
100 // output: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2
101 #define MULTIPLY(m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
102         \ // Eliminate the dependency for the last 2 VMSLs
103         VMSLG m02_0, r_2, m4_2, m4_2                       \
104         VMSLG m13_0, r_2, m5_2, m5_2                       \ // 8 VMSLs pipelined
105         VMSLG m02_0, r_0, m4_0, m4_0                       \
106         VMSLG m02_1, r5_2, V0, T_0                         \
107         VMSLG m02_0, r_1, m4_1, m4_1                       \
108         VMSLG m02_1, r_0, V0, T_1                          \
109         VMSLG m02_1, r_1, V0, T_2                          \
110         VMSLG m02_2, r5_1, V0, T_3                         \
111         VMSLG m02_2, r5_2, V0, T_4                         \
112         VMSLG m13_0, r_0, m5_0, m5_0                       \
113         VMSLG m13_1, r5_2, V0, T_5                         \
114         VMSLG m13_0, r_1, m5_1, m5_1                       \
115         VMSLG m13_1, r_0, V0, T_6                          \
116         VMSLG m13_1, r_1, V0, T_7                          \
117         VMSLG m13_2, r5_1, V0, T_8                         \
118         VMSLG m13_2, r5_2, V0, T_9                         \
119         VMSLG m02_2, r_0, m4_2, m4_2                       \
120         VMSLG m13_2, r_0, m5_2, m5_2                       \
121         VAQ   m4_0, T_0, m02_0                             \
122         VAQ   m4_1, T_1, m02_1                             \
123         VAQ   m5_0, T_5, m13_0                             \
124         VAQ   m5_1, T_6, m13_1                             \
125         VAQ   m02_0, T_3, m02_0                            \
126         VAQ   m02_1, T_4, m02_1                            \
127         VAQ   m13_0, T_8, m13_0                            \
128         VAQ   m13_1, T_9, m13_1                            \
129         VAQ   m4_2, T_2, m02_2                             \
130         VAQ   m5_2, T_7, m13_2                             \
131
132 // SQUARE uses three limbs of r and r_2*5 to output square of r
133 // uses T_1, T_5 and T_7 temporary registers
134 // input: r_0, r_1, r_2, r5_2
135 // temp: TEMP0, TEMP1, TEMP2
136 // output: p0, p1, p2
137 #define SQUARE(r_0, r_1, r_2, r5_2, p0, p1, p2, TEMP0, TEMP1, TEMP2) \
138         VMSLG r_0, r_0, p0, p0     \
139         VMSLG r_1, r5_2, V0, TEMP0 \
140         VMSLG r_2, r5_2, p1, p1    \
141         VMSLG r_0, r_1, V0, TEMP1  \
142         VMSLG r_1, r_1, p2, p2     \
143         VMSLG r_0, r_2, V0, TEMP2  \
144         VAQ   TEMP0, p0, p0        \
145         VAQ   TEMP1, p1, p1        \
146         VAQ   TEMP2, p2, p2        \
147         VAQ   TEMP0, p0, p0        \
148         VAQ   TEMP1, p1, p1        \
149         VAQ   TEMP2, p2, p2        \
150
151 // carry h0->h1->h2->h0 || h3->h4->h5->h3
152 // uses T_2, T_4, T_5, T_7, T_8, T_9
153 //       t6,  t7,  t8,  t9, t10, t11
154 // input: h0, h1, h2, h3, h4, h5
155 // temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11
156 // output: h0, h1, h2, h3, h4, h5
157 #define REDUCE(h0, h1, h2, h3, h4, h5, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \
158         VLM    (R12), t6, t7  \ // 44 and 42 bit clear mask
159         VLEIB  $7, $0x28, t10 \ // 5 byte shift mask
160         VREPIB $4, t8         \ // 4 bit shift mask
161         VREPIB $2, t11        \ // 2 bit shift mask
162         VSRLB  t10, h0, t0    \ // h0 byte shift
163         VSRLB  t10, h1, t1    \ // h1 byte shift
164         VSRLB  t10, h2, t2    \ // h2 byte shift
165         VSRLB  t10, h3, t3    \ // h3 byte shift
166         VSRLB  t10, h4, t4    \ // h4 byte shift
167         VSRLB  t10, h5, t5    \ // h5 byte shift
168         VSRL   t8, t0, t0     \ // h0 bit shift
169         VSRL   t8, t1, t1     \ // h2 bit shift
170         VSRL   t11, t2, t2    \ // h2 bit shift
171         VSRL   t8, t3, t3     \ // h3 bit shift
172         VSRL   t8, t4, t4     \ // h4 bit shift
173         VESLG  $2, t2, t9     \ // h2 carry x5
174         VSRL   t11, t5, t5    \ // h5 bit shift
175         VN     t6, h0, h0     \ // h0 clear carry
176         VAQ    t2, t9, t2     \ // h2 carry x5
177         VESLG  $2, t5, t9     \ // h5 carry x5
178         VN     t6, h1, h1     \ // h1 clear carry
179         VN     t7, h2, h2     \ // h2 clear carry
180         VAQ    t5, t9, t5     \ // h5 carry x5
181         VN     t6, h3, h3     \ // h3 clear carry
182         VN     t6, h4, h4     \ // h4 clear carry
183         VN     t7, h5, h5     \ // h5 clear carry
184         VAQ    t0, h1, h1     \ // h0->h1
185         VAQ    t3, h4, h4     \ // h3->h4
186         VAQ    t1, h2, h2     \ // h1->h2
187         VAQ    t4, h5, h5     \ // h4->h5
188         VAQ    t2, h0, h0     \ // h2->h0
189         VAQ    t5, h3, h3     \ // h5->h3
190         VREPG  $1, t6, t6     \ // 44 and 42 bit masks across both halves
191         VREPG  $1, t7, t7     \
192         VSLDB  $8, h0, h0, h0 \ // set up [h0/1/2, h3/4/5]
193         VSLDB  $8, h1, h1, h1 \
194         VSLDB  $8, h2, h2, h2 \
195         VO     h0, h3, h3     \
196         VO     h1, h4, h4     \
197         VO     h2, h5, h5     \
198         VESRLG $44, h3, t0    \ // 44 bit shift right
199         VESRLG $44, h4, t1    \
200         VESRLG $42, h5, t2    \
201         VN     t6, h3, h3     \ // clear carry bits
202         VN     t6, h4, h4     \
203         VN     t7, h5, h5     \
204         VESLG  $2, t2, t9     \ // multiply carry by 5
205         VAQ    t9, t2, t2     \
206         VAQ    t0, h4, h4     \
207         VAQ    t1, h5, h5     \
208         VAQ    t2, h3, h3     \
209
210 // carry h0->h1->h2->h0
211 // input: h0, h1, h2
212 // temp: t0, t1, t2, t3, t4, t5, t6, t7, t8
213 // output: h0, h1, h2
214 #define REDUCE2(h0, h1, h2, t0, t1, t2, t3, t4, t5, t6, t7, t8) \
215         VLEIB  $7, $0x28, t3 \ // 5 byte shift mask
216         VREPIB $4, t4        \ // 4 bit shift mask
217         VREPIB $2, t7        \ // 2 bit shift mask
218         VGBM   $0x003F, t5   \ // mask to clear carry bits
219         VSRLB  t3, h0, t0    \
220         VSRLB  t3, h1, t1    \
221         VSRLB  t3, h2, t2    \
222         VESRLG $4, t5, t5    \ // 44 bit clear mask
223         VSRL   t4, t0, t0    \
224         VSRL   t4, t1, t1    \
225         VSRL   t7, t2, t2    \
226         VESRLG $2, t5, t6    \ // 42 bit clear mask
227         VESLG  $2, t2, t8    \
228         VAQ    t8, t2, t2    \
229         VN     t5, h0, h0    \
230         VN     t5, h1, h1    \
231         VN     t6, h2, h2    \
232         VAQ    t0, h1, h1    \
233         VAQ    t1, h2, h2    \
234         VAQ    t2, h0, h0    \
235         VSRLB  t3, h0, t0    \
236         VSRLB  t3, h1, t1    \
237         VSRLB  t3, h2, t2    \
238         VSRL   t4, t0, t0    \
239         VSRL   t4, t1, t1    \
240         VSRL   t7, t2, t2    \
241         VN     t5, h0, h0    \
242         VN     t5, h1, h1    \
243         VESLG  $2, t2, t8    \
244         VN     t6, h2, h2    \
245         VAQ    t0, h1, h1    \
246         VAQ    t8, t2, t2    \
247         VAQ    t1, h2, h2    \
248         VAQ    t2, h0, h0    \
249
250 // expands two message blocks into the lower halfs of the d registers
251 // moves the contents of the d registers into upper halfs
252 // input: in1, in2, d0, d1, d2, d3, d4, d5
253 // temp: TEMP0, TEMP1, TEMP2, TEMP3
254 // output: d0, d1, d2, d3, d4, d5
255 #define EXPACC(in1, in2, d0, d1, d2, d3, d4, d5, TEMP0, TEMP1, TEMP2, TEMP3) \
256         VGBM   $0xff3f, TEMP0      \
257         VGBM   $0xff1f, TEMP1      \
258         VESLG  $4, d1, TEMP2       \
259         VESLG  $4, d4, TEMP3       \
260         VESRLG $4, TEMP0, TEMP0    \
261         VPERM  in1, d0, EX0, d0    \
262         VPERM  in2, d3, EX0, d3    \
263         VPERM  in1, d2, EX2, d2    \
264         VPERM  in2, d5, EX2, d5    \
265         VPERM  in1, TEMP2, EX1, d1 \
266         VPERM  in2, TEMP3, EX1, d4 \
267         VN     TEMP0, d0, d0       \
268         VN     TEMP0, d3, d3       \
269         VESRLG $4, d1, d1          \
270         VESRLG $4, d4, d4          \
271         VN     TEMP1, d2, d2       \
272         VN     TEMP1, d5, d5       \
273         VN     TEMP0, d1, d1       \
274         VN     TEMP0, d4, d4       \
275
276 // expands one message block into the lower halfs of the d registers
277 // moves the contents of the d registers into upper halfs
278 // input: in, d0, d1, d2
279 // temp: TEMP0, TEMP1, TEMP2
280 // output: d0, d1, d2
281 #define EXPACC2(in, d0, d1, d2, TEMP0, TEMP1, TEMP2) \
282         VGBM   $0xff3f, TEMP0     \
283         VESLG  $4, d1, TEMP2      \
284         VGBM   $0xff1f, TEMP1     \
285         VPERM  in, d0, EX0, d0    \
286         VESRLG $4, TEMP0, TEMP0   \
287         VPERM  in, d2, EX2, d2    \
288         VPERM  in, TEMP2, EX1, d1 \
289         VN     TEMP0, d0, d0      \
290         VN     TEMP1, d2, d2      \
291         VESRLG $4, d1, d1         \
292         VN     TEMP0, d1, d1      \
293
294 // pack h2:h0 into h1:h0 (no carry)
295 // input: h0, h1, h2
296 // output: h0, h1, h2
297 #define PACK(h0, h1, h2) \
298         VMRLG  h1, h2, h2  \ // copy h1 to upper half h2
299         VESLG  $44, h1, h1 \ // shift limb 1 44 bits, leaving 20
300         VO     h0, h1, h0  \ // combine h0 with 20 bits from limb 1
301         VESRLG $20, h2, h1 \ // put top 24 bits of limb 1 into h1
302         VLEIG  $1, $0, h1  \ // clear h2 stuff from lower half of h1
303         VO     h0, h1, h0  \ // h0 now has 88 bits (limb 0 and 1)
304         VLEIG  $0, $0, h2  \ // clear upper half of h2
305         VESRLG $40, h2, h1 \ // h1 now has upper two bits of result
306         VLEIB  $7, $88, h1 \ // for byte shift (11 bytes)
307         VSLB   h1, h2, h2  \ // shift h2 11 bytes to the left
308         VO     h0, h2, h0  \ // combine h0 with 20 bits from limb 1
309         VLEIG  $0, $0, h1  \ // clear upper half of h1
310
311 // if h > 2**130-5 then h -= 2**130-5
312 // input: h0, h1
313 // temp: t0, t1, t2
314 // output: h0
315 #define MOD(h0, h1, t0, t1, t2) \
316         VZERO t0          \
317         VLEIG $1, $5, t0  \
318         VACCQ h0, t0, t1  \
319         VAQ   h0, t0, t0  \
320         VONE  t2          \
321         VLEIG $1, $-4, t2 \
322         VAQ   t2, t1, t1  \
323         VACCQ h1, t1, t1  \
324         VONE  t2          \
325         VAQ   t2, t1, t1  \
326         VN    h0, t1, t2  \
327         VNC   t0, t1, t1  \
328         VO    t1, t2, h0  \
329
330 // func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]key)
331 TEXT ·poly1305vmsl(SB), $0-32
332         // This code processes 6 + up to 4 blocks (32 bytes) per iteration
333         // using the algorithm described in:
334         // NEON crypto, Daniel J. Bernstein & Peter Schwabe
335         // https://cryptojedi.org/papers/neoncrypto-20120320.pdf
336         // And as moddified for VMSL as described in
337         // Accelerating Poly1305 Cryptographic Message Authentication on the z14
338         // O'Farrell et al, CASCON 2017, p48-55
339         // https://ibm.ent.box.com/s/jf9gedj0e9d2vjctfyh186shaztavnht
340
341         LMG   out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key
342         VZERO V0                // c
343
344         // load EX0, EX1 and EX2
345         MOVD $·constants<>(SB), R5
346         VLM  (R5), EX0, EX2        // c
347
348         // setup r
349         VL    (R4), T_0
350         MOVD  $·keyMask<>(SB), R6
351         VL    (R6), T_1
352         VN    T_0, T_1, T_0
353         VZERO T_2                 // limbs for r
354         VZERO T_3
355         VZERO T_4
356         EXPACC2(T_0, T_2, T_3, T_4, T_1, T_5, T_7)
357
358         // T_2, T_3, T_4: [0, r]
359
360         // setup r*20
361         VLEIG $0, $0, T_0
362         VLEIG $1, $20, T_0       // T_0: [0, 20]
363         VZERO T_5
364         VZERO T_6
365         VMSLG T_0, T_3, T_5, T_5
366         VMSLG T_0, T_4, T_6, T_6
367
368         // store r for final block in GR
369         VLGVG $1, T_2, RSAVE_0  // c
370         VLGVG $1, T_3, RSAVE_1  // c
371         VLGVG $1, T_4, RSAVE_2  // c
372         VLGVG $1, T_5, R5SAVE_1 // c
373         VLGVG $1, T_6, R5SAVE_2 // c
374
375         // initialize h
376         VZERO H0_0
377         VZERO H1_0
378         VZERO H2_0
379         VZERO H0_1
380         VZERO H1_1
381         VZERO H2_1
382
383         // initialize pointer for reduce constants
384         MOVD $·reduce<>(SB), R12
385
386         // calculate r**2 and 20*(r**2)
387         VZERO R_0
388         VZERO R_1
389         VZERO R_2
390         SQUARE(T_2, T_3, T_4, T_6, R_0, R_1, R_2, T_1, T_5, T_7)
391         REDUCE2(R_0, R_1, R_2, M0, M1, M2, M3, M4, R5_1, R5_2, M5, T_1)
392         VZERO R5_1
393         VZERO R5_2
394         VMSLG T_0, R_1, R5_1, R5_1
395         VMSLG T_0, R_2, R5_2, R5_2
396
397         // skip r**4 calculation if 3 blocks or less
398         CMPBLE R3, $48, b4
399
400         // calculate r**4 and 20*(r**4)
401         VZERO T_8
402         VZERO T_9
403         VZERO T_10
404         SQUARE(R_0, R_1, R_2, R5_2, T_8, T_9, T_10, T_1, T_5, T_7)
405         REDUCE2(T_8, T_9, T_10, M0, M1, M2, M3, M4, T_2, T_3, M5, T_1)
406         VZERO T_2
407         VZERO T_3
408         VMSLG T_0, T_9, T_2, T_2
409         VMSLG T_0, T_10, T_3, T_3
410
411         // put r**2 to the right and r**4 to the left of R_0, R_1, R_2
412         VSLDB $8, T_8, T_8, T_8
413         VSLDB $8, T_9, T_9, T_9
414         VSLDB $8, T_10, T_10, T_10
415         VSLDB $8, T_2, T_2, T_2
416         VSLDB $8, T_3, T_3, T_3
417
418         VO T_8, R_0, R_0
419         VO T_9, R_1, R_1
420         VO T_10, R_2, R_2
421         VO T_2, R5_1, R5_1
422         VO T_3, R5_2, R5_2
423
424         CMPBLE R3, $80, load // less than or equal to 5 blocks in message
425
426         // 6(or 5+1) blocks
427         SUB    $81, R3
428         VLM    (R2), M0, M4
429         VLL    R3, 80(R2), M5
430         ADD    $1, R3
431         MOVBZ  $1, R0
432         CMPBGE R3, $16, 2(PC)
433         VLVGB  R3, R0, M5
434         MOVD   $96(R2), R2
435         EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
436         EXPACC(M2, M3, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
437         VLEIB  $2, $1, H2_0
438         VLEIB  $2, $1, H2_1
439         VLEIB  $10, $1, H2_0
440         VLEIB  $10, $1, H2_1
441
442         VZERO  M0
443         VZERO  M1
444         VZERO  M2
445         VZERO  M3
446         VZERO  T_4
447         VZERO  T_10
448         EXPACC(M4, M5, M0, M1, M2, M3, T_4, T_10, T_0, T_1, T_2, T_3)
449         VLR    T_4, M4
450         VLEIB  $10, $1, M2
451         CMPBLT R3, $16, 2(PC)
452         VLEIB  $10, $1, T_10
453         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
454         REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9)
455         VMRHG  V0, H0_1, H0_0
456         VMRHG  V0, H1_1, H1_0
457         VMRHG  V0, H2_1, H2_0
458         VMRLG  V0, H0_1, H0_1
459         VMRLG  V0, H1_1, H1_1
460         VMRLG  V0, H2_1, H2_1
461
462         SUB    $16, R3
463         CMPBLE R3, $0, square
464
465 load:
466         // load EX0, EX1 and EX2
467         MOVD $·c<>(SB), R5
468         VLM  (R5), EX0, EX2
469
470 loop:
471         CMPBLE R3, $64, add // b4       // last 4 or less blocks left
472
473         // next 4 full blocks
474         VLM  (R2), M2, M5
475         SUB  $64, R3
476         MOVD $64(R2), R2
477         REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, T_0, T_1, T_3, T_4, T_5, T_2, T_7, T_8, T_9)
478
479         // expacc in-lined to create [m2, m3] limbs
480         VGBM   $0x3f3f, T_0     // 44 bit clear mask
481         VGBM   $0x1f1f, T_1     // 40 bit clear mask
482         VPERM  M2, M3, EX0, T_3
483         VESRLG $4, T_0, T_0     // 44 bit clear mask ready
484         VPERM  M2, M3, EX1, T_4
485         VPERM  M2, M3, EX2, T_5
486         VN     T_0, T_3, T_3
487         VESRLG $4, T_4, T_4
488         VN     T_1, T_5, T_5
489         VN     T_0, T_4, T_4
490         VMRHG  H0_1, T_3, H0_0
491         VMRHG  H1_1, T_4, H1_0
492         VMRHG  H2_1, T_5, H2_0
493         VMRLG  H0_1, T_3, H0_1
494         VMRLG  H1_1, T_4, H1_1
495         VMRLG  H2_1, T_5, H2_1
496         VLEIB  $10, $1, H2_0
497         VLEIB  $10, $1, H2_1
498         VPERM  M4, M5, EX0, T_3
499         VPERM  M4, M5, EX1, T_4
500         VPERM  M4, M5, EX2, T_5
501         VN     T_0, T_3, T_3
502         VESRLG $4, T_4, T_4
503         VN     T_1, T_5, T_5
504         VN     T_0, T_4, T_4
505         VMRHG  V0, T_3, M0
506         VMRHG  V0, T_4, M1
507         VMRHG  V0, T_5, M2
508         VMRLG  V0, T_3, M3
509         VMRLG  V0, T_4, M4
510         VMRLG  V0, T_5, M5
511         VLEIB  $10, $1, M2
512         VLEIB  $10, $1, M5
513
514         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
515         CMPBNE R3, $0, loop
516         REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
517         VMRHG  V0, H0_1, H0_0
518         VMRHG  V0, H1_1, H1_0
519         VMRHG  V0, H2_1, H2_0
520         VMRLG  V0, H0_1, H0_1
521         VMRLG  V0, H1_1, H1_1
522         VMRLG  V0, H2_1, H2_1
523
524         // load EX0, EX1, EX2
525         MOVD $·constants<>(SB), R5
526         VLM  (R5), EX0, EX2
527
528         // sum vectors
529         VAQ H0_0, H0_1, H0_0
530         VAQ H1_0, H1_1, H1_0
531         VAQ H2_0, H2_1, H2_0
532
533         // h may be >= 2*(2**130-5) so we need to reduce it again
534         // M0...M4 are used as temps here
535         REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
536
537 next:  // carry h1->h2
538         VLEIB  $7, $0x28, T_1
539         VREPIB $4, T_2
540         VGBM   $0x003F, T_3
541         VESRLG $4, T_3
542
543         // byte shift
544         VSRLB T_1, H1_0, T_4
545
546         // bit shift
547         VSRL T_2, T_4, T_4
548
549         // clear h1 carry bits
550         VN T_3, H1_0, H1_0
551
552         // add carry
553         VAQ T_4, H2_0, H2_0
554
555         // h is now < 2*(2**130-5)
556         // pack h into h1 (hi) and h0 (lo)
557         PACK(H0_0, H1_0, H2_0)
558
559         // if h > 2**130-5 then h -= 2**130-5
560         MOD(H0_0, H1_0, T_0, T_1, T_2)
561
562         // h += s
563         MOVD  $·bswapMask<>(SB), R5
564         VL    (R5), T_1
565         VL    16(R4), T_0
566         VPERM T_0, T_0, T_1, T_0    // reverse bytes (to big)
567         VAQ   T_0, H0_0, H0_0
568         VPERM H0_0, H0_0, T_1, H0_0 // reverse bytes (to little)
569         VST   H0_0, (R1)
570         RET
571
572 add:
573         // load EX0, EX1, EX2
574         MOVD $·constants<>(SB), R5
575         VLM  (R5), EX0, EX2
576
577         REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
578         VMRHG  V0, H0_1, H0_0
579         VMRHG  V0, H1_1, H1_0
580         VMRHG  V0, H2_1, H2_0
581         VMRLG  V0, H0_1, H0_1
582         VMRLG  V0, H1_1, H1_1
583         VMRLG  V0, H2_1, H2_1
584         CMPBLE R3, $64, b4
585
586 b4:
587         CMPBLE R3, $48, b3 // 3 blocks or less
588
589         // 4(3+1) blocks remaining
590         SUB    $49, R3
591         VLM    (R2), M0, M2
592         VLL    R3, 48(R2), M3
593         ADD    $1, R3
594         MOVBZ  $1, R0
595         CMPBEQ R3, $16, 2(PC)
596         VLVGB  R3, R0, M3
597         MOVD   $64(R2), R2
598         EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
599         VLEIB  $10, $1, H2_0
600         VLEIB  $10, $1, H2_1
601         VZERO  M0
602         VZERO  M1
603         VZERO  M4
604         VZERO  M5
605         VZERO  T_4
606         VZERO  T_10
607         EXPACC(M2, M3, M0, M1, M4, M5, T_4, T_10, T_0, T_1, T_2, T_3)
608         VLR    T_4, M2
609         VLEIB  $10, $1, M4
610         CMPBNE R3, $16, 2(PC)
611         VLEIB  $10, $1, T_10
612         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M4, M5, M2, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
613         REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
614         VMRHG  V0, H0_1, H0_0
615         VMRHG  V0, H1_1, H1_0
616         VMRHG  V0, H2_1, H2_0
617         VMRLG  V0, H0_1, H0_1
618         VMRLG  V0, H1_1, H1_1
619         VMRLG  V0, H2_1, H2_1
620         SUB    $16, R3
621         CMPBLE R3, $0, square // this condition must always hold true!
622
623 b3:
624         CMPBLE R3, $32, b2
625
626         // 3 blocks remaining
627
628         // setup [r²,r]
629         VSLDB $8, R_0, R_0, R_0
630         VSLDB $8, R_1, R_1, R_1
631         VSLDB $8, R_2, R_2, R_2
632         VSLDB $8, R5_1, R5_1, R5_1
633         VSLDB $8, R5_2, R5_2, R5_2
634
635         VLVGG $1, RSAVE_0, R_0
636         VLVGG $1, RSAVE_1, R_1
637         VLVGG $1, RSAVE_2, R_2
638         VLVGG $1, R5SAVE_1, R5_1
639         VLVGG $1, R5SAVE_2, R5_2
640
641         // setup [h0, h1]
642         VSLDB $8, H0_0, H0_0, H0_0
643         VSLDB $8, H1_0, H1_0, H1_0
644         VSLDB $8, H2_0, H2_0, H2_0
645         VO    H0_1, H0_0, H0_0
646         VO    H1_1, H1_0, H1_0
647         VO    H2_1, H2_0, H2_0
648         VZERO H0_1
649         VZERO H1_1
650         VZERO H2_1
651
652         VZERO M0
653         VZERO M1
654         VZERO M2
655         VZERO M3
656         VZERO M4
657         VZERO M5
658
659         // H*[r**2, r]
660         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
661         REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, T_10, M5)
662
663         SUB    $33, R3
664         VLM    (R2), M0, M1
665         VLL    R3, 32(R2), M2
666         ADD    $1, R3
667         MOVBZ  $1, R0
668         CMPBEQ R3, $16, 2(PC)
669         VLVGB  R3, R0, M2
670
671         // H += m0
672         VZERO T_1
673         VZERO T_2
674         VZERO T_3
675         EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)
676         VLEIB $10, $1, T_3
677         VAG   H0_0, T_1, H0_0
678         VAG   H1_0, T_2, H1_0
679         VAG   H2_0, T_3, H2_0
680
681         VZERO M0
682         VZERO M3
683         VZERO M4
684         VZERO M5
685         VZERO T_10
686
687         // (H+m0)*r
688         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M3, M4, M5, V0, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
689         REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_10, H0_1, H1_1, H2_1, T_9)
690
691         // H += m1
692         VZERO V0
693         VZERO T_1
694         VZERO T_2
695         VZERO T_3
696         EXPACC2(M1, T_1, T_2, T_3, T_4, T_5, T_6)
697         VLEIB $10, $1, T_3
698         VAQ   H0_0, T_1, H0_0
699         VAQ   H1_0, T_2, H1_0
700         VAQ   H2_0, T_3, H2_0
701         REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10)
702
703         // [H, m2] * [r**2, r]
704         EXPACC2(M2, H0_0, H1_0, H2_0, T_1, T_2, T_3)
705         CMPBNE R3, $16, 2(PC)
706         VLEIB  $10, $1, H2_0
707         VZERO  M0
708         VZERO  M1
709         VZERO  M2
710         VZERO  M3
711         VZERO  M4
712         VZERO  M5
713         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
714         REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, M5, T_10)
715         SUB    $16, R3
716         CMPBLE R3, $0, next   // this condition must always hold true!
717
718 b2:
719         CMPBLE R3, $16, b1
720
721         // 2 blocks remaining
722
723         // setup [r²,r]
724         VSLDB $8, R_0, R_0, R_0
725         VSLDB $8, R_1, R_1, R_1
726         VSLDB $8, R_2, R_2, R_2
727         VSLDB $8, R5_1, R5_1, R5_1
728         VSLDB $8, R5_2, R5_2, R5_2
729
730         VLVGG $1, RSAVE_0, R_0
731         VLVGG $1, RSAVE_1, R_1
732         VLVGG $1, RSAVE_2, R_2
733         VLVGG $1, R5SAVE_1, R5_1
734         VLVGG $1, R5SAVE_2, R5_2
735
736         // setup [h0, h1]
737         VSLDB $8, H0_0, H0_0, H0_0
738         VSLDB $8, H1_0, H1_0, H1_0
739         VSLDB $8, H2_0, H2_0, H2_0
740         VO    H0_1, H0_0, H0_0
741         VO    H1_1, H1_0, H1_0
742         VO    H2_1, H2_0, H2_0
743         VZERO H0_1
744         VZERO H1_1
745         VZERO H2_1
746
747         VZERO M0
748         VZERO M1
749         VZERO M2
750         VZERO M3
751         VZERO M4
752         VZERO M5
753
754         // H*[r**2, r]
755         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
756         REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9)
757         VMRHG V0, H0_1, H0_0
758         VMRHG V0, H1_1, H1_0
759         VMRHG V0, H2_1, H2_0
760         VMRLG V0, H0_1, H0_1
761         VMRLG V0, H1_1, H1_1
762         VMRLG V0, H2_1, H2_1
763
764         // move h to the left and 0s at the right
765         VSLDB $8, H0_0, H0_0, H0_0
766         VSLDB $8, H1_0, H1_0, H1_0
767         VSLDB $8, H2_0, H2_0, H2_0
768
769         // get message blocks and append 1 to start
770         SUB    $17, R3
771         VL     (R2), M0
772         VLL    R3, 16(R2), M1
773         ADD    $1, R3
774         MOVBZ  $1, R0
775         CMPBEQ R3, $16, 2(PC)
776         VLVGB  R3, R0, M1
777         VZERO  T_6
778         VZERO  T_7
779         VZERO  T_8
780         EXPACC2(M0, T_6, T_7, T_8, T_1, T_2, T_3)
781         EXPACC2(M1, T_6, T_7, T_8, T_1, T_2, T_3)
782         VLEIB  $2, $1, T_8
783         CMPBNE R3, $16, 2(PC)
784         VLEIB  $10, $1, T_8
785
786         // add [m0, m1] to h
787         VAG H0_0, T_6, H0_0
788         VAG H1_0, T_7, H1_0
789         VAG H2_0, T_8, H2_0
790
791         VZERO M2
792         VZERO M3
793         VZERO M4
794         VZERO M5
795         VZERO T_10
796         VZERO M0
797
798         // at this point R_0 .. R5_2 look like [r**2, r]
799         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M2, M3, M4, M5, T_10, M0, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
800         REDUCE2(H0_0, H1_0, H2_0, M2, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10)
801         SUB    $16, R3, R3
802         CMPBLE R3, $0, next
803
804 b1:
805         CMPBLE R3, $0, next
806
807         // 1 block remaining
808
809         // setup [r²,r]
810         VSLDB $8, R_0, R_0, R_0
811         VSLDB $8, R_1, R_1, R_1
812         VSLDB $8, R_2, R_2, R_2
813         VSLDB $8, R5_1, R5_1, R5_1
814         VSLDB $8, R5_2, R5_2, R5_2
815
816         VLVGG $1, RSAVE_0, R_0
817         VLVGG $1, RSAVE_1, R_1
818         VLVGG $1, RSAVE_2, R_2
819         VLVGG $1, R5SAVE_1, R5_1
820         VLVGG $1, R5SAVE_2, R5_2
821
822         // setup [h0, h1]
823         VSLDB $8, H0_0, H0_0, H0_0
824         VSLDB $8, H1_0, H1_0, H1_0
825         VSLDB $8, H2_0, H2_0, H2_0
826         VO    H0_1, H0_0, H0_0
827         VO    H1_1, H1_0, H1_0
828         VO    H2_1, H2_0, H2_0
829         VZERO H0_1
830         VZERO H1_1
831         VZERO H2_1
832
833         VZERO M0
834         VZERO M1
835         VZERO M2
836         VZERO M3
837         VZERO M4
838         VZERO M5
839
840         // H*[r**2, r]
841         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
842         REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
843
844         // set up [0, m0] limbs
845         SUB    $1, R3
846         VLL    R3, (R2), M0
847         ADD    $1, R3
848         MOVBZ  $1, R0
849         CMPBEQ R3, $16, 2(PC)
850         VLVGB  R3, R0, M0
851         VZERO  T_1
852         VZERO  T_2
853         VZERO  T_3
854         EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)// limbs: [0, m]
855         CMPBNE R3, $16, 2(PC)
856         VLEIB  $10, $1, T_3
857
858         // h+m0
859         VAQ H0_0, T_1, H0_0
860         VAQ H1_0, T_2, H1_0
861         VAQ H2_0, T_3, H2_0
862
863         VZERO M0
864         VZERO M1
865         VZERO M2
866         VZERO M3
867         VZERO M4
868         VZERO M5
869         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
870         REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
871
872         BR next
873
874 square:
875         // setup [r²,r]
876         VSLDB $8, R_0, R_0, R_0
877         VSLDB $8, R_1, R_1, R_1
878         VSLDB $8, R_2, R_2, R_2
879         VSLDB $8, R5_1, R5_1, R5_1
880         VSLDB $8, R5_2, R5_2, R5_2
881
882         VLVGG $1, RSAVE_0, R_0
883         VLVGG $1, RSAVE_1, R_1
884         VLVGG $1, RSAVE_2, R_2
885         VLVGG $1, R5SAVE_1, R5_1
886         VLVGG $1, R5SAVE_2, R5_2
887
888         // setup [h0, h1]
889         VSLDB $8, H0_0, H0_0, H0_0
890         VSLDB $8, H1_0, H1_0, H1_0
891         VSLDB $8, H2_0, H2_0, H2_0
892         VO    H0_1, H0_0, H0_0
893         VO    H1_1, H1_0, H1_0
894         VO    H2_1, H2_0, H2_0
895         VZERO H0_1
896         VZERO H1_1
897         VZERO H2_1
898
899         VZERO M0
900         VZERO M1
901         VZERO M2
902         VZERO M3
903         VZERO M4
904         VZERO M5
905
906         // (h0*r**2) + (h1*r)
907         MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
908         REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
909         BR next