a0dbcea315c47f6b47037e710118342165b563fd
[libgcrypt.git] / cipher / sha256-armv8-aarch32-ce.S
1 /* sha256-armv8-aarch32-ce.S - ARM/CE accelerated SHA-256 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(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \
23     defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
24     defined(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO) && defined(USE_SHA256)
25
26 .syntax unified
27 .fpu crypto-neon-fp-armv8
28 .arm
29
30 .text
31
32 #ifdef __PIC__
33 #  define GET_DATA_POINTER(reg, name, rtmp) \
34                 ldr reg, 1f; \
35                 ldr rtmp, 2f; \
36                 b 3f; \
37         1:      .word _GLOBAL_OFFSET_TABLE_-(3f+8); \
38         2:      .word name(GOT); \
39         3:      add reg, pc, reg; \
40                 ldr reg, [reg, rtmp];
41 #else
42 #  define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name
43 #endif
44
45
46 /* Constants */
47
48 .align 4
49 gcry_sha256_aarch32_ce_K:
50 .LK:
51   .long 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
52   .long 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
53   .long 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
54   .long 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
55   .long 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
56   .long 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
57   .long 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
58   .long 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
59   .long 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
60   .long 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
61   .long 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
62   .long 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
63   .long 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
64   .long 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
65   .long 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
66   .long 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
67
68
69 /* Register macros */
70
71 #define qH0123 q0
72 #define qH4567 q1
73
74 #define qABCD0 q2
75 #define qABCD1 q3
76 #define qEFGH  q4
77
78 #define qT0 q5
79 #define qT1 q6
80
81 #define qW0 q8
82 #define qW1 q9
83 #define qW2 q10
84 #define qW3 q11
85
86 #define qK0 q12
87 #define qK1 q13
88 #define qK2 q14
89 #define qK3 q15
90
91
92 /* Round macros */
93
94 #define _(...) /*_*/
95
96
97
98 /* Other functional macros */
99
100 #define CLEAR_REG(reg) veor reg, reg;
101
102
103 /*
104  * unsigned int
105  * _gcry_sha256_transform_armv8_ce (u32 state[8], const void *input_data,
106  *                                  size_t num_blks)
107  */
108 .align 3
109 .globl _gcry_sha256_transform_armv8_ce
110 .type  _gcry_sha256_transform_armv8_ce,%function;
111 _gcry_sha256_transform_armv8_ce:
112   /* input:
113    *    r0: ctx, CTX
114    *    r1: data (64*nblks bytes)
115    *    r2: nblks
116    */
117
118   cmp r2, #0;
119   push {r4,lr};
120   beq .Ldo_nothing;
121
122   vpush {q4-q7};
123
124   GET_DATA_POINTER(r4, .LK, lr);
125   mov lr, r4
126
127   vld1.32 {qH0123-qH4567}, [r0]  /* load state */
128
129 #define do_loadk(nk0, nk1) vld1.32 {nk0-nk1},[lr]!;
130 #define do_add(a, b) vadd.u32 a, a, b;
131 #define do_sha256su0(w0, w1) sha256su0.32 w0, w1;
132 #define do_sha256su1(w0, w2, w3) sha256su1.32 w0, w2, w3;
133
134 #define do_rounds(k, nk0, nk1, w0, w1, w2, w3, loadk_fn, add_fn, su0_fn, su1_fn) \
135         loadk_fn(   nk0, nk1     ); \
136         su0_fn(     w0, w1       ); \
137         vmov        qABCD1, qABCD0; \
138         sha256h.32  qABCD0, qEFGH, k; \
139         sha256h2.32 qEFGH, qABCD1, k; \
140         add_fn(     nk0, w2      ); \
141         su1_fn(     w0, w2, w3   ); \
142
143   vld1.8 {qW0-qW1}, [r1]!
144   do_loadk(qK0, qK1)
145   vld1.8 {qW2-qW3}, [r1]!
146   vmov qABCD0, qH0123
147   vmov qEFGH, qH4567
148
149   vrev32.8 qW0, qW0
150   vrev32.8 qW1, qW1
151   vrev32.8 qW2, qW2
152   do_add(qK0, qW0)
153   vrev32.8 qW3, qW3
154   do_add(qK1, qW1)
155
156 .Loop:
157   do_rounds(qK0, qK2, qK3, qW0, qW1, qW2, qW3, do_loadk, do_add, do_sha256su0, do_sha256su1)
158   subs r2,r2,#1
159   do_rounds(qK1, qK3, _  , qW1, qW2, qW3, qW0, _       , do_add, do_sha256su0, do_sha256su1)
160   do_rounds(qK2, qK0, qK1, qW2, qW3, qW0, qW1, do_loadk, do_add, do_sha256su0, do_sha256su1)
161   do_rounds(qK3, qK1, _  , qW3, qW0, qW1, qW2, _       , do_add, do_sha256su0, do_sha256su1)
162
163   do_rounds(qK0, qK2, qK3, qW0, qW1, qW2, qW3, do_loadk, do_add, do_sha256su0, do_sha256su1)
164   do_rounds(qK1, qK3, _  , qW1, qW2, qW3, qW0, _       , do_add, do_sha256su0, do_sha256su1)
165   do_rounds(qK2, qK0, qK1, qW2, qW3, qW0, qW1, do_loadk, do_add, do_sha256su0, do_sha256su1)
166   do_rounds(qK3, qK1, _  , qW3, qW0, qW1, qW2, _       , do_add, do_sha256su0, do_sha256su1)
167
168   do_rounds(qK0, qK2, qK3, qW0, qW1, qW2, qW3, do_loadk, do_add, do_sha256su0, do_sha256su1)
169   do_rounds(qK1, qK3, _  , qW1, qW2, qW3, qW0, _       , do_add, do_sha256su0, do_sha256su1)
170   do_rounds(qK2, qK0, qK1, qW2, qW3, qW0, qW1, do_loadk, do_add, do_sha256su0, do_sha256su1)
171   do_rounds(qK3, qK1, _  , qW3, qW0, qW1, qW2, _       , do_add, do_sha256su0, do_sha256su1)
172
173   beq .Lend
174
175   do_rounds(qK0, qK2, qK3, qW0, _  , qW2, qW3, do_loadk, do_add, _, _)
176   vld1.8 {qW0}, [r1]!
177   mov lr, r4
178   do_rounds(qK1, qK3, _  , qW1, _  , qW3, _  , _       , do_add, _, _)
179   vld1.8 {qW1}, [r1]!
180   vrev32.8 qW0, qW0
181   do_rounds(qK2, qK0, qK1, qW2, _  , qW0, _  , do_loadk, do_add, _, _)
182   vrev32.8 qW1, qW1
183   vld1.8 {qW2}, [r1]!
184   do_rounds(qK3, qK1, _  , qW3, _  , qW1, _  , _       , do_add, _, _)
185   vld1.8 {qW3}, [r1]!
186
187   vadd.u32 qH0123, qABCD0
188   vadd.u32 qH4567, qEFGH
189
190   vrev32.8 qW2, qW2
191   vmov qABCD0, qH0123
192   vrev32.8 qW3, qW3
193   vmov qEFGH, qH4567
194
195   b .Loop
196
197 .Lend:
198
199   do_rounds(qK0, qK2, qK3, qW0, _  , qW2, qW3, do_loadk, do_add, _, _)
200   do_rounds(qK1, qK3, _  , qW1, _  , qW3, _  , _       , do_add, _, _)
201   do_rounds(qK2, _  , _  , qW2, _  , _  , _  , _       , _, _, _)
202   do_rounds(qK3, _  , _  , qW3, _  , _  , _  , _       , _, _, _)
203
204   CLEAR_REG(qW0)
205   CLEAR_REG(qW1)
206   CLEAR_REG(qW2)
207   CLEAR_REG(qW3)
208   CLEAR_REG(qK0)
209   CLEAR_REG(qK1)
210   CLEAR_REG(qK2)
211   CLEAR_REG(qK3)
212
213   vadd.u32 qH0123, qABCD0
214   vadd.u32 qH4567, qEFGH
215
216   CLEAR_REG(qABCD0)
217   CLEAR_REG(qABCD1)
218   CLEAR_REG(qEFGH)
219
220   vst1.32 {qH0123-qH4567}, [r0] /* store state */
221
222   CLEAR_REG(qH0123)
223   CLEAR_REG(qH4567)
224   vpop {q4-q7}
225
226 .Ldo_nothing:
227   mov r0, #0
228   pop {r4,pc}
229 .size _gcry_sha256_transform_armv8_ce,.-_gcry_sha256_transform_armv8_ce;
230
231 #endif