xref: /openssl/crypto/sm4/asm/sm4-armv8.pl (revision 15b7175f)
1#! /usr/bin/env perl
2# Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3#
4# Licensed under the Apache License 2.0 (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
8
9#
10# This module implements support for SM4 hw support on aarch64
11# Oct 2021
12#
13
14# $output is the last argument if it looks like a file (it has an extension)
15# $flavour is the first argument if it doesn't look like a file
16$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
17$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
18
19$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
20( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
21( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
22die "can't locate arm-xlate.pl";
23
24open OUT,"| \"$^X\" $xlate $flavour \"$output\""
25    or die "can't call $xlate: $!";
26*STDOUT=*OUT;
27
28$prefix="sm4_v8";
29my @rks=map("v$_",(0..7));
30
31sub rev32() {
32my $dst = shift;
33my $src = shift;
34$code.=<<___;
35#ifndef __ARMEB__
36	rev32	$dst.16b,$src.16b
37#endif
38___
39}
40
41sub enc_blk () {
42my $data = shift;
43$code.=<<___;
44	sm4e	$data.4s,@rks[0].4s
45	sm4e	$data.4s,@rks[1].4s
46	sm4e	$data.4s,@rks[2].4s
47	sm4e	$data.4s,@rks[3].4s
48	sm4e	$data.4s,@rks[4].4s
49	sm4e	$data.4s,@rks[5].4s
50	sm4e	$data.4s,@rks[6].4s
51	sm4e	$data.4s,@rks[7].4s
52	rev64	$data.4S,$data.4S
53	ext	$data.16b,$data.16b,$data.16b,#8
54___
55}
56
57sub enc_4blks () {
58my $data0 = shift;
59my $data1 = shift;
60my $data2 = shift;
61my $data3 = shift;
62$code.=<<___;
63	sm4e	$data0.4s,@rks[0].4s
64	sm4e	$data1.4s,@rks[0].4s
65	sm4e	$data2.4s,@rks[0].4s
66	sm4e	$data3.4s,@rks[0].4s
67
68	sm4e	$data0.4s,@rks[1].4s
69	sm4e	$data1.4s,@rks[1].4s
70	sm4e	$data2.4s,@rks[1].4s
71	sm4e	$data3.4s,@rks[1].4s
72
73	sm4e	$data0.4s,@rks[2].4s
74	sm4e	$data1.4s,@rks[2].4s
75	sm4e	$data2.4s,@rks[2].4s
76	sm4e	$data3.4s,@rks[2].4s
77
78	sm4e	$data0.4s,@rks[3].4s
79	sm4e	$data1.4s,@rks[3].4s
80	sm4e	$data2.4s,@rks[3].4s
81	sm4e	$data3.4s,@rks[3].4s
82
83	sm4e	$data0.4s,@rks[4].4s
84	sm4e	$data1.4s,@rks[4].4s
85	sm4e	$data2.4s,@rks[4].4s
86	sm4e	$data3.4s,@rks[4].4s
87
88	sm4e	$data0.4s,@rks[5].4s
89	sm4e	$data1.4s,@rks[5].4s
90	sm4e	$data2.4s,@rks[5].4s
91	sm4e	$data3.4s,@rks[5].4s
92
93	sm4e	$data0.4s,@rks[6].4s
94	sm4e	$data1.4s,@rks[6].4s
95	sm4e	$data2.4s,@rks[6].4s
96	sm4e	$data3.4s,@rks[6].4s
97
98	sm4e	$data0.4s,@rks[7].4s
99	rev64	$data0.4S,$data0.4S
100	sm4e	$data1.4s,@rks[7].4s
101	ext	$data0.16b,$data0.16b,$data0.16b,#8
102	rev64	$data1.4S,$data1.4S
103	sm4e	$data2.4s,@rks[7].4s
104	ext	$data1.16b,$data1.16b,$data1.16b,#8
105	rev64	$data2.4S,$data2.4S
106	sm4e	$data3.4s,@rks[7].4s
107	ext	$data2.16b,$data2.16b,$data2.16b,#8
108	rev64	$data3.4S,$data3.4S
109	ext	$data3.16b,$data3.16b,$data3.16b,#8
110___
111}
112
113$code=<<___;
114#include "arm_arch.h"
115.arch	armv8-a+crypto
116.text
117___
118
119{{{
120$code.=<<___;
121.align	6
122.Lck:
123	.long 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269
124	.long 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9
125	.long 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249
126	.long 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9
127	.long 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229
128	.long 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299
129	.long 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209
130	.long 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279
131.Lfk:
132	.long 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
133___
134}}}
135
136{{{
137my ($key,$keys)=("x0","x1");
138my ($tmp)=("x2");
139my ($key0,$key1,$key2,$key3,$key4,$key5,$key6,$key7)=map("v$_",(0..7));
140my ($const0,$const1,$const2,$const3,$const4,$const5,$const6,$const7)=map("v$_",(16..23));
141my ($fkconst) = ("v24");
142$code.=<<___;
143.globl	${prefix}_set_encrypt_key
144.type	${prefix}_set_encrypt_key,%function
145.align	5
146${prefix}_set_encrypt_key:
147	AARCH64_VALID_CALL_TARGET
148	ld1	{$key0.4s},[$key]
149	adr	$tmp,.Lfk
150	ld1	{$fkconst.4s},[$tmp]
151	adr	$tmp,.Lck
152	ld1	{$const0.4s,$const1.4s,$const2.4s,$const3.4s},[$tmp],64
153___
154	&rev32($key0, $key0);
155$code.=<<___;
156	ld1	{$const4.4s,$const5.4s,$const6.4s,$const7.4s},[$tmp]
157	eor	$key0.16b,$key0.16b,$fkconst.16b;
158	sm4ekey	$key0.4S,$key0.4S,$const0.4S
159	sm4ekey	$key1.4S,$key0.4S,$const1.4S
160	sm4ekey	$key2.4S,$key1.4S,$const2.4S
161	sm4ekey	$key3.4S,$key2.4S,$const3.4S
162	sm4ekey	$key4.4S,$key3.4S,$const4.4S
163	st1	{$key0.4s,$key1.4s,$key2.4s,$key3.4s},[$keys],64
164	sm4ekey	$key5.4S,$key4.4S,$const5.4S
165	sm4ekey	$key6.4S,$key5.4S,$const6.4S
166	sm4ekey	$key7.4S,$key6.4S,$const7.4S
167	st1	{$key4.4s,$key5.4s,$key6.4s,$key7.4s},[$keys]
168	ret
169.size	${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key
170___
171}}}
172
173{{{
174my ($key,$keys)=("x0","x1");
175my ($tmp)=("x2");
176my ($key7,$key6,$key5,$key4,$key3,$key2,$key1,$key0)=map("v$_",(0..7));
177my ($const0,$const1,$const2,$const3,$const4,$const5,$const6,$const7)=map("v$_",(16..23));
178my ($fkconst) = ("v24");
179$code.=<<___;
180.globl	${prefix}_set_decrypt_key
181.type	${prefix}_set_decrypt_key,%function
182.align	5
183${prefix}_set_decrypt_key:
184	AARCH64_VALID_CALL_TARGET
185	ld1	{$key0.4s},[$key]
186	adr	$tmp,.Lfk
187	ld1	{$fkconst.4s},[$tmp]
188	adr	$tmp, .Lck
189	ld1	{$const0.4s,$const1.4s,$const2.4s,$const3.4s},[$tmp],64
190___
191	&rev32($key0, $key0);
192$code.=<<___;
193	ld1	{$const4.4s,$const5.4s,$const6.4s,$const7.4s},[$tmp]
194	eor	$key0.16b, $key0.16b,$fkconst.16b;
195	sm4ekey	$key0.4S,$key0.4S,$const0.4S
196	sm4ekey	$key1.4S,$key0.4S,$const1.4S
197	sm4ekey	$key2.4S,$key1.4S,$const2.4S
198	rev64	$key0.4s,$key0.4s
199	rev64	$key1.4s,$key1.4s
200	ext	$key0.16b,$key0.16b,$key0.16b,#8
201	ext	$key1.16b,$key1.16b,$key1.16b,#8
202	sm4ekey	$key3.4S,$key2.4S,$const3.4S
203	sm4ekey	$key4.4S,$key3.4S,$const4.4S
204	rev64	$key2.4s,$key2.4s
205	rev64	$key3.4s,$key3.4s
206	ext	$key2.16b,$key2.16b,$key2.16b,#8
207	ext	$key3.16b,$key3.16b,$key3.16b,#8
208	sm4ekey	$key5.4S,$key4.4S,$const5.4S
209	sm4ekey	$key6.4S,$key5.4S,$const6.4S
210	rev64	$key4.4s,$key4.4s
211	rev64	$key5.4s,$key5.4s
212	ext	$key4.16b,$key4.16b,$key4.16b,#8
213	ext	$key5.16b,$key5.16b,$key5.16b,#8
214	sm4ekey	$key7.4S,$key6.4S,$const7.4S
215	rev64	$key6.4s, $key6.4s
216	rev64	$key7.4s, $key7.4s
217	ext	$key6.16b,$key6.16b,$key6.16b,#8
218	ext	$key7.16b,$key7.16b,$key7.16b,#8
219	st1	{$key7.4s,$key6.4s,$key5.4s,$key4.4s},[$keys],64
220	st1	{$key3.4s,$key2.4s,$key1.4s,$key0.4s},[$keys]
221	ret
222.size	${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key
223___
224}}}
225
226{{{
227sub gen_block () {
228my $dir = shift;
229my ($inp,$out,$rk)=map("x$_",(0..2));
230my ($data)=("v16");
231$code.=<<___;
232.globl	${prefix}_${dir}crypt
233.type	${prefix}_${dir}crypt,%function
234.align	5
235${prefix}_${dir}crypt:
236	AARCH64_VALID_CALL_TARGET
237	ld1	{$data.4s},[$inp]
238	ld1	{@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],64
239	ld1	{@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk]
240___
241	&rev32($data,$data);
242	&enc_blk($data);
243	&rev32($data,$data);
244$code.=<<___;
245	st1	{$data.4s},[$out]
246	ret
247.size	${prefix}_${dir}crypt,.-${prefix}_${dir}crypt
248___
249}
250
251&gen_block("en");
252&gen_block("de");
253}}}
254
255{{{
256my ($inp,$out,$len,$rk)=map("x$_",(0..3));
257my ($enc) = ("w4");
258my @dat=map("v$_",(16..23));
259$code.=<<___;
260.globl	${prefix}_ecb_encrypt
261.type	${prefix}_ecb_encrypt,%function
262.align	5
263${prefix}_ecb_encrypt:
264	AARCH64_VALID_CALL_TARGET
265	ld1	{@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],#64
266	ld1	{@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk]
2671:
268	cmp	$len,#64
269	b.lt	1f
270	ld1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp],#64
271	cmp	$len,#128
272	b.lt	2f
273	ld1	{@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$inp],#64
274	// 8 blocks
275___
276	&rev32(@dat[0],@dat[0]);
277	&rev32(@dat[1],@dat[1]);
278	&rev32(@dat[2],@dat[2]);
279	&rev32(@dat[3],@dat[3]);
280	&rev32(@dat[4],@dat[4]);
281	&rev32(@dat[5],@dat[5]);
282	&rev32(@dat[6],@dat[6]);
283	&rev32(@dat[7],@dat[7]);
284	&enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
285	&enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]);
286	&rev32(@dat[0],@dat[0]);
287	&rev32(@dat[1],@dat[1]);
288	&rev32(@dat[2],@dat[2]);
289	&rev32(@dat[3],@dat[3]);
290	&rev32(@dat[4],@dat[4]);
291	&rev32(@dat[5],@dat[5]);
292$code.=<<___;
293	st1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
294___
295	&rev32(@dat[6],@dat[6]);
296	&rev32(@dat[7],@dat[7]);
297$code.=<<___;
298	st1	{@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64
299	subs	$len,$len,#128
300	b.gt	1b
301	ret
302	// 4 blocks
3032:
304___
305	&rev32(@dat[0],@dat[0]);
306	&rev32(@dat[1],@dat[1]);
307	&rev32(@dat[2],@dat[2]);
308	&rev32(@dat[3],@dat[3]);
309	&enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
310	&rev32(@dat[0],@dat[0]);
311	&rev32(@dat[1],@dat[1]);
312	&rev32(@dat[2],@dat[2]);
313	&rev32(@dat[3],@dat[3]);
314$code.=<<___;
315	st1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
316	subs	$len,$len,#64
317	b.gt	1b
3181:
319	subs	$len,$len,#16
320	b.lt	1f
321	ld1	{@dat[0].4s},[$inp],#16
322___
323	&rev32(@dat[0],@dat[0]);
324	&enc_blk(@dat[0]);
325	&rev32(@dat[0],@dat[0]);
326$code.=<<___;
327	st1	{@dat[0].4s},[$out],#16
328	b.ne	1b
3291:
330	ret
331.size	${prefix}_ecb_encrypt,.-${prefix}_ecb_encrypt
332___
333}}}
334
335{{{
336my ($inp,$out,$len,$rk,$ivp)=map("x$_",(0..4));
337my ($enc) = ("w5");
338my @dat=map("v$_",(16..23));
339my @in=map("v$_",(24..31));
340my ($ivec) = ("v8");
341$code.=<<___;
342.globl	${prefix}_cbc_encrypt
343.type	${prefix}_cbc_encrypt,%function
344.align	5
345${prefix}_cbc_encrypt:
346	AARCH64_VALID_CALL_TARGET
347	stp	d8,d9,[sp, #-16]!
348
349	ld1	{@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],#64
350	ld1	{@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk]
351	ld1	{$ivec.4s},[$ivp]
352	cmp	$enc,#0
353	b.eq	.Ldec
3541:
355	cmp	$len, #64
356	b.lt	1f
357	ld1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp],#64
358	eor	@dat[0].16b,@dat[0].16b,$ivec.16b
359___
360	&rev32(@dat[1],@dat[1]);
361	&rev32(@dat[0],@dat[0]);
362	&rev32(@dat[2],@dat[2]);
363	&rev32(@dat[3],@dat[3]);
364	&enc_blk(@dat[0]);
365$code.=<<___;
366	eor	@dat[1].16b,@dat[1].16b,@dat[0].16b
367___
368	&enc_blk(@dat[1]);
369	&rev32(@dat[0],@dat[0]);
370$code.=<<___;
371	eor	@dat[2].16b,@dat[2].16b,@dat[1].16b
372___
373	&enc_blk(@dat[2]);
374	&rev32(@dat[1],@dat[1]);
375$code.=<<___;
376	eor	@dat[3].16b,@dat[3].16b,@dat[2].16b
377___
378	&enc_blk(@dat[3]);
379	&rev32(@dat[2],@dat[2]);
380	&rev32(@dat[3],@dat[3]);
381$code.=<<___;
382	mov	$ivec.16b,@dat[3].16b
383	st1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
384	subs	$len,$len,#64
385	b.ne	1b
3861:
387	subs	$len,$len,#16
388	b.lt	3f
389	ld1	{@dat[0].4s},[$inp],#16
390	eor	$ivec.16b,$ivec.16b,@dat[0].16b
391___
392	&rev32($ivec,$ivec);
393	&enc_blk($ivec);
394	&rev32($ivec,$ivec);
395$code.=<<___;
396	st1	{$ivec.16b},[$out],#16
397	b.ne	1b
398	b	3f
399.Ldec:
4001:
401	cmp	$len, #64
402	b.lt	1f
403	ld1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp]
404	ld1	{@in[0].4s,@in[1].4s,@in[2].4s,@in[3].4s},[$inp],#64
405	cmp	$len,#128
406	b.lt	2f
407	// 8 blocks mode
408	ld1	{@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$inp]
409	ld1	{@in[4].4s,@in[5].4s,@in[6].4s,@in[7].4s},[$inp],#64
410___
411	&rev32(@dat[0],@dat[0]);
412	&rev32(@dat[1],@dat[1]);
413	&rev32(@dat[2],@dat[2]);
414	&rev32(@dat[3],$dat[3]);
415	&rev32(@dat[4],@dat[4]);
416	&rev32(@dat[5],@dat[5]);
417	&rev32(@dat[6],@dat[6]);
418	&rev32(@dat[7],$dat[7]);
419	&enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
420	&enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]);
421	&rev32(@dat[0],@dat[0]);
422	&rev32(@dat[1],@dat[1]);
423	&rev32(@dat[2],@dat[2]);
424	&rev32(@dat[3],@dat[3]);
425	&rev32(@dat[4],@dat[4]);
426	&rev32(@dat[5],@dat[5]);
427	&rev32(@dat[6],@dat[6]);
428	&rev32(@dat[7],@dat[7]);
429$code.=<<___;
430	eor	@dat[0].16b,@dat[0].16b,$ivec.16b
431	eor	@dat[1].16b,@dat[1].16b,@in[0].16b
432	eor	@dat[2].16b,@dat[2].16b,@in[1].16b
433	mov	$ivec.16b,@in[7].16b
434	eor	@dat[3].16b,$dat[3].16b,@in[2].16b
435	eor	@dat[4].16b,$dat[4].16b,@in[3].16b
436	eor	@dat[5].16b,$dat[5].16b,@in[4].16b
437	eor	@dat[6].16b,$dat[6].16b,@in[5].16b
438	eor	@dat[7].16b,$dat[7].16b,@in[6].16b
439	st1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
440	st1	{@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64
441	subs	$len,$len,128
442	b.gt	1b
443	b	3f
444	// 4 blocks mode
4452:
446___
447	&rev32(@dat[0],@dat[0]);
448	&rev32(@dat[1],@dat[1]);
449	&rev32(@dat[2],@dat[2]);
450	&rev32(@dat[3],$dat[3]);
451	&enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
452	&rev32(@dat[0],@dat[0]);
453	&rev32(@dat[1],@dat[1]);
454	&rev32(@dat[2],@dat[2]);
455	&rev32(@dat[3],@dat[3]);
456$code.=<<___;
457	eor	@dat[0].16b,@dat[0].16b,$ivec.16b
458	eor	@dat[1].16b,@dat[1].16b,@in[0].16b
459	mov	$ivec.16b,@in[3].16b
460	eor	@dat[2].16b,@dat[2].16b,@in[1].16b
461	eor	@dat[3].16b,$dat[3].16b,@in[2].16b
462	st1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
463	subs	$len,$len,#64
464	b.gt	1b
4651:
466	subs	$len,$len,#16
467	b.lt	3f
468	ld1	{@dat[0].4s},[$inp],#16
469	mov	@in[0].16b,@dat[0].16b
470___
471	&rev32(@dat[0],@dat[0]);
472	&enc_blk(@dat[0]);
473	&rev32(@dat[0],@dat[0]);
474$code.=<<___;
475	eor	@dat[0].16b,@dat[0].16b,$ivec.16b
476	mov	$ivec.16b,@in[0].16b
477	st1	{@dat[0].16b},[$out],#16
478	b.ne	1b
4793:
480	// save back IV
481	st1	{$ivec.16b},[$ivp]
482	ldp	d8,d9,[sp],#16
483	ret
484.size	${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt
485___
486}}}
487
488{{{
489my ($inp,$out,$len,$rk,$ivp)=map("x$_",(0..4));
490my ($ctr)=("w5");
491my @dat=map("v$_",(16..23));
492my @in=map("v$_",(24..31));
493my ($ivec)=("v8");
494$code.=<<___;
495.globl	${prefix}_ctr32_encrypt_blocks
496.type	${prefix}_ctr32_encrypt_blocks,%function
497.align	5
498${prefix}_ctr32_encrypt_blocks:
499	AARCH64_VALID_CALL_TARGET
500	stp	d8,d9,[sp, #-16]!
501
502	ld1	{$ivec.4s},[$ivp]
503	ld1	{@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],64
504	ld1	{@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk]
505___
506	&rev32($ivec,$ivec);
507$code.=<<___;
508	mov	$ctr,$ivec.s[3]
5091:
510	cmp	$len,#4
511	b.lt	1f
512	ld1	{@in[0].4s,@in[1].4s,@in[2].4s,@in[3].4s},[$inp],#64
513	mov	@dat[0].16b,$ivec.16b
514	mov	@dat[1].16b,$ivec.16b
515	mov	@dat[2].16b,$ivec.16b
516	mov	@dat[3].16b,$ivec.16b
517	add	$ctr,$ctr,#1
518	mov	$dat[1].s[3],$ctr
519	add	$ctr,$ctr,#1
520	mov	@dat[2].s[3],$ctr
521	add	$ctr,$ctr,#1
522	mov	@dat[3].s[3],$ctr
523	cmp	$len,#8
524	b.lt	2f
525	ld1	{@in[4].4s,@in[5].4s,@in[6].4s,@in[7].4s},[$inp],#64
526	mov	@dat[4].16b,$ivec.16b
527	mov	@dat[5].16b,$ivec.16b
528	mov	@dat[6].16b,$ivec.16b
529	mov	@dat[7].16b,$ivec.16b
530	add	$ctr,$ctr,#1
531	mov	$dat[4].s[3],$ctr
532	add	$ctr,$ctr,#1
533	mov	@dat[5].s[3],$ctr
534	add	$ctr,$ctr,#1
535	mov	@dat[6].s[3],$ctr
536	add	$ctr,$ctr,#1
537	mov	@dat[7].s[3],$ctr
538___
539	&enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
540	&enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]);
541	&rev32(@dat[0],@dat[0]);
542	&rev32(@dat[1],@dat[1]);
543	&rev32(@dat[2],@dat[2]);
544	&rev32(@dat[3],@dat[3]);
545	&rev32(@dat[4],@dat[4]);
546	&rev32(@dat[5],@dat[5]);
547	&rev32(@dat[6],@dat[6]);
548	&rev32(@dat[7],@dat[7]);
549$code.=<<___;
550	eor	@dat[0].16b,@dat[0].16b,@in[0].16b
551	eor	@dat[1].16b,@dat[1].16b,@in[1].16b
552	eor	@dat[2].16b,@dat[2].16b,@in[2].16b
553	eor	@dat[3].16b,@dat[3].16b,@in[3].16b
554	eor	@dat[4].16b,@dat[4].16b,@in[4].16b
555	eor	@dat[5].16b,@dat[5].16b,@in[5].16b
556	eor	@dat[6].16b,@dat[6].16b,@in[6].16b
557	eor	@dat[7].16b,@dat[7].16b,@in[7].16b
558	st1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
559	st1	{@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64
560	subs	$len,$len,#8
561	b.eq	3f
562	add	$ctr,$ctr,#1
563	mov	$ivec.s[3],$ctr
564	b	1b
5652:
566___
567	&enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
568	&rev32(@dat[0],@dat[0]);
569	&rev32(@dat[1],@dat[1]);
570	&rev32(@dat[2],@dat[2]);
571	&rev32(@dat[3],@dat[3]);
572$code.=<<___;
573	eor	@dat[0].16b,@dat[0].16b,@in[0].16b
574	eor	@dat[1].16b,@dat[1].16b,@in[1].16b
575	eor	@dat[2].16b,@dat[2].16b,@in[2].16b
576	eor	@dat[3].16b,@dat[3].16b,@in[3].16b
577	st1	{@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
578	subs	$len,$len,#4
579	b.eq	3f
580	add	$ctr,$ctr,#1
581	mov	$ivec.s[3],$ctr
582	b	1b
5831:
584	subs	$len,$len,#1
585	b.lt	3f
586	mov	$dat[0].16b,$ivec.16b
587	ld1	{@in[0].4s},[$inp],#16
588___
589	&enc_blk(@dat[0]);
590	&rev32(@dat[0],@dat[0]);
591$code.=<<___;
592	eor	$dat[0].16b,$dat[0].16b,@in[0].16b
593	st1	{$dat[0].4s},[$out],#16
594	b.eq	3f
595	add	$ctr,$ctr,#1
596	mov	$ivec.s[3],$ctr
597	b	1b
5983:
599	ldp	d8,d9,[sp],#16
600	ret
601.size	${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks
602___
603}}}
604########################################
605{   my  %opcode = (
606        "sm4e"          => 0xcec08400,
607        "sm4ekey"       => 0xce60c800);
608
609    sub unsm4 {
610        my ($mnemonic,$arg)=@_;
611
612        $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o
613        &&
614        sprintf ".inst\t0x%08x\t//%s %s",
615                        $opcode{$mnemonic}|$1|($2<<5)|($3<<16),
616                        $mnemonic,$arg;
617    }
618}
619
620open SELF,$0;
621while(<SELF>) {
622        next if (/^#!/);
623        last if (!s/^#/\/\// and !/^$/);
624        print;
625}
626close SELF;
627
628foreach(split("\n",$code)) {
629	s/\`([^\`]*)\`/eval($1)/ge;
630
631	s/\b(sm4\w+)\s+([qv].*)/unsm4($1,$2)/ge;
632	print $_,"\n";
633}
634
635close STDOUT or die "error closing STDOUT: $!";
636