Add PowerPC vpmsum implementation of CRC
[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 .arch armv8-a
28 .fpu crypto-neon-fp-armv8
29 .arm
30
31 .text
32
33 #ifdef __PIC__
34 #  define GET_DATA_POINTER(reg, name, rtmp) \
35                 ldr reg, 1f; \
36                 ldr rtmp, 2f; \
37                 b 3f; \
38         1:      .word _GLOBAL_OFFSET_TABLE_-(3f+8); \
39         2:      .word name(GOT); \
40         3:      add reg, pc, reg; \
41                 ldr reg, [reg, rtmp];
42 #else
43 #  define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name
44 #endif
45
46
47 /* Constants */
48
49 .align 4
50 gcry_sha256_aarch32_ce_K:
51 .LK:
52   .long 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
53   .long 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
54   .long 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
55   .long 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
56   .long 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
57   .long 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
58   .long 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
59   .long 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
60   .long 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
61   .long 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
62   .long 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
63   .long 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
64   .long 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
65   .long 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
66   .long 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
67   .long 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
68
69
70 /* Register macros */
71
72 #define qH0123 q0
73 #define qH4567 q1
74
75 #define qABCD0 q2
76 #define qABCD1 q3
77 #define qEFGH  q4
78
79 #define qT0 q5
80 #define qT1 q6
81
82 #define qW0 q8
83 #define qW1 q9
84 #define qW2 q10
85 #define qW3 q11
86
87 #define qK0 q12
88 #define qK1 q13
89 #define qK2 q14
90 #define qK3 q15
91
92
93 /* Round macros */
94
95 #define _(...) /*_*/
96
97 #define do_loadk(nk0, nk1) vld1.32 {nk0-nk1},[lr]!;
98 #define do_add(a, b) vadd.u32 a, a, b;
99 #define do_sha256su0(w0, w1) sha256su0.32 w0, w1;
100 #define do_sha256su1(w0, w2, w3) sha256su1.32 w0, w2, w3;
101
102 #define do_rounds(k, nk0, nk1, w0, w1, w2, w3, loadk_fn, add_fn, su0_fn, su1_fn) \
103         loadk_fn(   nk0, nk1     ); \
104         su0_fn(     w0, w1       ); \
105         vmov        qABCD1, qABCD0; \
106         sha256h.32  qABCD0, qEFGH, k; \
107         sha256h2.32 qEFGH, qABCD1, k; \
108         add_fn(     nk0, w2      ); \
109         su1_fn(     w0, w2, w3   );
110
111
112 /* Other functional macros */
113
114 #define CLEAR_REG(reg) veor reg, reg;
115
116
117 /*
118  * unsigned int
119  * _gcry_sha256_transform_armv8_ce (u32 state[8], const void *input_data,
120  *                                  size_t num_blks)
121  */
122 .align 3
123 .globl _gcry_sha256_transform_armv8_ce
124 .type  _gcry_sha256_transform_armv8_ce,%function;
125 _gcry_sha256_transform_armv8_ce:
126   /* input:
127    *    r0: ctx, CTX
128    *    r1: data (64*nblks bytes)
129    *    r2: nblks
130    */
131
132   cmp r2, #0;
133   push {r4,lr};
134   beq .Ldo_nothing;
135
136   vpush {q4-q7};
137
138   GET_DATA_POINTER(r4, .LK, lr);
139   mov lr, r4
140
141   vld1.32 {qH0123-qH4567}, [r0]  /* load state */
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