ec1810d5dd1eb37948cb2836eb2aa02258281f51
[libgcrypt.git] / cipher / sha1-armv8-aarch64-ce.S
1 /* sha1-armv8-aarch64-ce.S - ARM/CE accelerated SHA-1 transform function
2  * Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #if defined(__AARCH64EL__) && \
23     defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
24     defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO) && defined(USE_SHA1)
25
26 .cpu generic+simd+crypto
27
28 .text
29
30
31 #define GET_DATA_POINTER(reg, name) \
32                 adrp    reg, :got:name ; \
33                 ldr     reg, [reg, #:got_lo12:name] ;
34
35
36 /* Constants */
37
38 #define K1  0x5A827999
39 #define K2  0x6ED9EBA1
40 #define K3  0x8F1BBCDC
41 #define K4  0xCA62C1D6
42 .align 4
43 gcry_sha1_aarch64_ce_K_VEC:
44 .LK_VEC:
45 .LK1:   .long K1, K1, K1, K1
46 .LK2:   .long K2, K2, K2, K2
47 .LK3:   .long K3, K3, K3, K3
48 .LK4:   .long K4, K4, K4, K4
49
50
51 /* Register macros */
52
53 #define sH4    s0
54 #define vH4    v0
55 #define vH0123 v1
56
57 #define qABCD q2
58 #define sABCD s2
59 #define vABCD v2
60 #define sE0   s3
61 #define vE0   v3
62 #define sE1   s4
63 #define vE1   v4
64
65 #define vT0   v5
66 #define vT1   v6
67
68 #define vW0 v16
69 #define vW1 v17
70 #define vW2 v18
71 #define vW3 v19
72
73 #define vK1 v20
74 #define vK2 v21
75 #define vK3 v22
76 #define vK4 v23
77
78
79 /* Round macros */
80
81 #define _(...) /*_*/
82 #define do_add(dst, src0, src1) add dst.4s, src0.4s, src1.4s;
83 #define do_sha1su0(w0,w1,w2) sha1su0 w0.4s,w1.4s,w2.4s;
84 #define do_sha1su1(w0,w3) sha1su1 w0.4s,w3.4s;
85
86 #define do_rounds(f, e0, e1, t, k, w0, w1, w2, w3, add_fn, sha1su0_fn, sha1su1_fn) \
87         sha1su1_fn( v##w3, v##w2     ); \
88         sha1h       e0, sABCD; \
89         sha1##f     qABCD, e1, v##t.4s; \
90         add_fn(     v##t, v##w2, v##k   ); \
91         sha1su0_fn( v##w0, v##w1, v##w2 );
92
93
94 /* Other functional macros */
95
96 #define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
97
98
99 /*
100  * unsigned int
101  * _gcry_sha1_transform_armv8_ce (void *ctx, const unsigned char *data,
102  *                                size_t nblks)
103  */
104 .align 3
105 .globl _gcry_sha1_transform_armv8_ce
106 .type  _gcry_sha1_transform_armv8_ce,%function;
107 _gcry_sha1_transform_armv8_ce:
108   /* input:
109    *    x0: ctx, CTX
110    *    x1: data (64*nblks bytes)
111    *    x2: nblks
112    */
113
114   cbz x2, .Ldo_nothing;
115
116   GET_DATA_POINTER(x4, .LK_VEC);
117
118   ld1 {vH0123.4s}, [x0]     /* load h0,h1,h2,h3 */
119   ld1 {vK1.4s-vK4.4s}, [x4] /* load K1,K2,K3,K4 */
120   ldr sH4, [x0, #16]        /* load h4 */
121
122   ld1 {vW0.16b-vW3.16b}, [x1], #64
123   mov vABCD.16b, vH0123.16b
124
125   rev32 vW0.16b, vW0.16b
126   rev32 vW1.16b, vW1.16b
127   rev32 vW2.16b, vW2.16b
128   do_add(vT0, vW0, vK1)
129   rev32 vW3.16b, vW3.16b
130   do_add(vT1, vW1, vK1)
131
132 .Loop:
133   do_rounds(c, sE1, sH4, T0, K1, W0, W1, W2, W3, do_add, do_sha1su0, _)
134   sub x2, x2, #1
135   do_rounds(c, sE0, sE1, T1, K1, W1, W2, W3, W0, do_add, do_sha1su0, do_sha1su1)
136   do_rounds(c, sE1, sE0, T0, K1, W2, W3, W0, W1, do_add, do_sha1su0, do_sha1su1)
137   do_rounds(c, sE0, sE1, T1, K2, W3, W0, W1, W2, do_add, do_sha1su0, do_sha1su1)
138   do_rounds(c, sE1, sE0, T0, K2, W0, W1, W2, W3, do_add, do_sha1su0, do_sha1su1)
139
140   do_rounds(p, sE0, sE1, T1, K2, W1, W2, W3, W0, do_add, do_sha1su0, do_sha1su1)
141   do_rounds(p, sE1, sE0, T0, K2, W2, W3, W0, W1, do_add, do_sha1su0, do_sha1su1)
142   do_rounds(p, sE0, sE1, T1, K2, W3, W0, W1, W2, do_add, do_sha1su0, do_sha1su1)
143   do_rounds(p, sE1, sE0, T0, K3, W0, W1, W2, W3, do_add, do_sha1su0, do_sha1su1)
144   do_rounds(p, sE0, sE1, T1, K3, W1, W2, W3, W0, do_add, do_sha1su0, do_sha1su1)
145
146   do_rounds(m, sE1, sE0, T0, K3, W2, W3, W0, W1, do_add, do_sha1su0, do_sha1su1)
147   do_rounds(m, sE0, sE1, T1, K3, W3, W0, W1, W2, do_add, do_sha1su0, do_sha1su1)
148   do_rounds(m, sE1, sE0, T0, K3, W0, W1, W2, W3, do_add, do_sha1su0, do_sha1su1)
149   do_rounds(m, sE0, sE1, T1, K4, W1, W2, W3, W0, do_add, do_sha1su0, do_sha1su1)
150   do_rounds(m, sE1, sE0, T0, K4, W2, W3, W0, W1, do_add, do_sha1su0, do_sha1su1)
151
152   do_rounds(p, sE0, sE1, T1, K4, W3, W0, W1, W2, do_add, do_sha1su0, do_sha1su1)
153   cbz x2, .Lend
154
155   ld1 {vW0.16b-vW1.16b}, [x1], #32 /* preload */
156   do_rounds(p, sE1, sE0, T0, K4, _  , _  , W2, W3, do_add, _, do_sha1su1)
157   rev32 vW0.16b, vW0.16b
158   ld1 {vW2.16b}, [x1], #16
159   rev32 vW1.16b, vW1.16b
160   do_rounds(p, sE0, sE1, T1, K4, _  , _  , W3, _  , do_add, _, _)
161   ld1 {vW3.16b}, [x1], #16
162   rev32 vW2.16b, vW2.16b
163   do_rounds(p, sE1, sE0, T0, _, _, _, _, _, _, _, _)
164   rev32 vW3.16b, vW3.16b
165   do_rounds(p, sE0, sE1, T1, _, _, _, _, _, _, _, _)
166
167   do_add(vT0, vW0, vK1)
168   add vH4.2s, vH4.2s, vE0.2s
169   add vABCD.4s, vABCD.4s, vH0123.4s
170   do_add(vT1, vW1, vK1)
171
172   mov vH0123.16b, vABCD.16b
173
174   b .Loop
175
176 .Lend:
177   do_rounds(p, sE1, sE0, T0, K4, _  , _  , W2, W3, do_add, _, do_sha1su1)
178   do_rounds(p, sE0, sE1, T1, K4, _  , _  , W3, _  , do_add, _, _)
179   do_rounds(p, sE1, sE0, T0, _, _, _, _, _, _, _, _)
180   do_rounds(p, sE0, sE1, T1, _, _, _, _, _, _, _, _)
181
182   add vH4.2s, vH4.2s, vE0.2s
183   add vH0123.4s, vH0123.4s, vABCD.4s
184
185   CLEAR_REG(vW0)
186   CLEAR_REG(vW1)
187   CLEAR_REG(vW2)
188   CLEAR_REG(vW3)
189   CLEAR_REG(vABCD)
190   CLEAR_REG(vE1)
191   CLEAR_REG(vE0)
192
193   str sH4, [x0, #16]    /* store h4 */
194   st1 {vH0123.4s}, [x0] /* store h0,h1,h2,h3 */
195
196   CLEAR_REG(vH0123)
197   CLEAR_REG(vH4)
198
199 .Ldo_nothing:
200   mov x0, #0
201   ret
202 .size _gcry_sha1_transform_armv8_ce,.-_gcry_sha1_transform_armv8_ce;
203
204 #endif