xref: /isa-l/igzip/adler32_sse.asm (revision 1500db751d08b6c4ad6097135fe78259540a2807)
1e1f5284fSGreg Tucker;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2e1f5284fSGreg Tucker;  Copyright(c) 2011-2017 Intel Corporation All rights reserved.
3e1f5284fSGreg Tucker;
4e1f5284fSGreg Tucker;  Redistribution and use in source and binary forms, with or without
5e1f5284fSGreg Tucker;  modification, are permitted provided that the following conditions
6e1f5284fSGreg Tucker;  are met:
7e1f5284fSGreg Tucker;    * Redistributions of source code must retain the above copyright
8e1f5284fSGreg Tucker;      notice, this list of conditions and the following disclaimer.
9e1f5284fSGreg Tucker;    * Redistributions in binary form must reproduce the above copyright
10e1f5284fSGreg Tucker;      notice, this list of conditions and the following disclaimer in
11e1f5284fSGreg Tucker;      the documentation and/or other materials provided with the
12e1f5284fSGreg Tucker;      distribution.
13e1f5284fSGreg Tucker;    * Neither the name of Intel Corporation nor the names of its
14e1f5284fSGreg Tucker;      contributors may be used to endorse or promote products derived
15e1f5284fSGreg Tucker;      from this software without specific prior written permission.
16e1f5284fSGreg Tucker;
17e1f5284fSGreg Tucker;  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18e1f5284fSGreg Tucker;  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19e1f5284fSGreg Tucker;  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20e1f5284fSGreg Tucker;  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21e1f5284fSGreg Tucker;  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22e1f5284fSGreg Tucker;  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23e1f5284fSGreg Tucker;  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24e1f5284fSGreg Tucker;  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25e1f5284fSGreg Tucker;  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26e1f5284fSGreg Tucker;  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27e1f5284fSGreg Tucker;  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28e1f5284fSGreg Tucker;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29e1f5284fSGreg Tucker
30e1f5284fSGreg Tucker; uint32_t adler32_avx2(uint32_t init, const unsigned char *buf, uint64_t len)
31e1f5284fSGreg Tucker
32e1f5284fSGreg Tucker%define LIMIT 5552
33e1f5284fSGreg Tucker%define BASE  0xFFF1 ; 65521
34e1f5284fSGreg Tucker
35e1f5284fSGreg Tucker%include "reg_sizes.asm"
36e1f5284fSGreg Tucker
37e1f5284fSGreg Tuckerdefault rel
38e1f5284fSGreg Tucker[bits 64]
39e1f5284fSGreg Tucker
40e1f5284fSGreg Tucker; need to keep free: eax, ecx, edx
41e1f5284fSGreg Tucker
42e1f5284fSGreg Tucker%ifidn __OUTPUT_FORMAT__, elf64
43e1f5284fSGreg Tucker %define arg1   rdi
44e1f5284fSGreg Tucker %define arg2   rsi
45e1f5284fSGreg Tucker %define arg3   rdx
46e1f5284fSGreg Tucker
47e1f5284fSGreg Tucker %define init_d edi
48e1f5284fSGreg Tucker %define data   r9
49e1f5284fSGreg Tucker %define size   r10
50e1f5284fSGreg Tucker %define s      r11
51e1f5284fSGreg Tucker %define a_d    r12d
52e1f5284fSGreg Tucker %define b_d    r8d
53e1f5284fSGreg Tucker %define end    r13
54e1f5284fSGreg Tucker
55cd888f01SH.J. Lu %define func(x) x: endbranch
56e1f5284fSGreg Tucker %macro FUNC_SAVE 0
57e1f5284fSGreg Tucker	push	r12
58e1f5284fSGreg Tucker	push	r13
59e1f5284fSGreg Tucker %endmacro
60e1f5284fSGreg Tucker%macro FUNC_RESTORE 0
61e1f5284fSGreg Tucker	pop	r13
62e1f5284fSGreg Tucker	pop	r12
63e1f5284fSGreg Tucker %endmacro
64e1f5284fSGreg Tucker%endif
65e1f5284fSGreg Tucker
66e1f5284fSGreg Tucker
67e1f5284fSGreg Tucker%ifidn __OUTPUT_FORMAT__, win64
68e1f5284fSGreg Tucker %define arg1   rcx
69e1f5284fSGreg Tucker %define arg2   rdx
70e1f5284fSGreg Tucker %define arg3   r8
71e1f5284fSGreg Tucker
72e1f5284fSGreg Tucker %define init_d r12d
73e1f5284fSGreg Tucker %define data   r9
74e1f5284fSGreg Tucker %define size	r10
75e1f5284fSGreg Tucker %define s	r11
76e1f5284fSGreg Tucker %define a_d	esi
77e1f5284fSGreg Tucker %define b_d	edi
78e1f5284fSGreg Tucker %define end	r13
79e1f5284fSGreg Tucker
80e1f5284fSGreg Tucker %define stack_size  5*8		; must be an odd multiple of 8
81e1f5284fSGreg Tucker %define func(x) proc_frame x
82e1f5284fSGreg Tucker %macro FUNC_SAVE 0
83e1f5284fSGreg Tucker	alloc_stack	stack_size
84e1f5284fSGreg Tucker	save_reg	rdi,  0*8
85e1f5284fSGreg Tucker	save_reg	rsi,  1*8
86e1f5284fSGreg Tucker	save_reg	r12,  2*8
87e1f5284fSGreg Tucker	save_reg	r13,  3*8
88e1f5284fSGreg Tucker	end_prolog
89*1500db75SColin Ian King	mov	init_d, ecx	; initialize init_d from arg1 to keep ecx free
90e1f5284fSGreg Tucker %endmacro
91e1f5284fSGreg Tucker
92e1f5284fSGreg Tucker %macro FUNC_RESTORE 0
93e1f5284fSGreg Tucker	mov	rdi,  [rsp + 0*8]
94e1f5284fSGreg Tucker	mov	rsi,  [rsp + 1*8]
95e1f5284fSGreg Tucker	mov	r12,  [rsp + 2*8]
96e1f5284fSGreg Tucker	mov	r13,  [rsp + 3*8]
97e1f5284fSGreg Tucker	add	rsp, stack_size
98e1f5284fSGreg Tucker %endmacro
99e1f5284fSGreg Tucker%endif
100e1f5284fSGreg Tucker
101e1f5284fSGreg Tucker%define xa	xmm0
102e1f5284fSGreg Tucker%define xb	xmm1
103e1f5284fSGreg Tucker%define xdata0	xmm2
104e1f5284fSGreg Tucker%define xdata1	xmm3
105e1f5284fSGreg Tucker%define xsa	xmm4
106e1f5284fSGreg Tucker
107ede04f0aSGreg Tucker[bits 64]
108ede04f0aSGreg Tuckerdefault rel
109ede04f0aSGreg Tuckersection .text
110ede04f0aSGreg Tucker
111ede04f0aSGreg Tuckermk_global adler32_sse, function
112e1f5284fSGreg Tuckerfunc(adler32_sse)
113e1f5284fSGreg Tucker	FUNC_SAVE
114e1f5284fSGreg Tucker
115e1f5284fSGreg Tucker	mov	data, arg2
116e1f5284fSGreg Tucker	mov	size, arg3
117e1f5284fSGreg Tucker
118e1f5284fSGreg Tucker	mov	b_d, init_d
119e1f5284fSGreg Tucker	shr	b_d, 16
120e1f5284fSGreg Tucker	and	init_d, 0xFFFF
121e1f5284fSGreg Tucker	cmp	size, 32
122e1f5284fSGreg Tucker	jb	.lt64
123e1f5284fSGreg Tucker	movd	xa, init_d
124e1f5284fSGreg Tucker	pxor	xb, xb
125e1f5284fSGreg Tucker.sloop1:
126e1f5284fSGreg Tucker	mov	s, LIMIT
127e1f5284fSGreg Tucker	cmp	s, size
128e1f5284fSGreg Tucker	cmova	s, size		; s = min(size, LIMIT)
129e1f5284fSGreg Tucker	lea	end, [data + s - 7]
130e1f5284fSGreg Tucker	cmp	data, end
131e1f5284fSGreg Tucker	jae	.skip_loop_1a
132e1f5284fSGreg Tuckeralign 32
133e1f5284fSGreg Tucker.sloop1a:
134e1f5284fSGreg Tucker	; do 8 adds
135e1f5284fSGreg Tucker	pmovzxbd xdata0, [data]
136e1f5284fSGreg Tucker	pmovzxbd xdata1, [data + 4]
137e1f5284fSGreg Tucker	add	data, 8
138e1f5284fSGreg Tucker	paddd	xa, xdata0
139e1f5284fSGreg Tucker	paddd	xb, xa
140e1f5284fSGreg Tucker	paddd	xa, xdata1
141e1f5284fSGreg Tucker	paddd	xb, xa
142e1f5284fSGreg Tucker	cmp	data, end
143e1f5284fSGreg Tucker	jb	.sloop1a
144e1f5284fSGreg Tucker
145e1f5284fSGreg Tucker.skip_loop_1a:
146e1f5284fSGreg Tucker	add	end, 7
147e1f5284fSGreg Tucker
148e1f5284fSGreg Tucker	test	s, 7
149e1f5284fSGreg Tucker	jnz	.do_final
150e1f5284fSGreg Tucker
151e1f5284fSGreg Tucker	; either we're done, or we just did LIMIT
152e1f5284fSGreg Tucker	sub	size, s
153e1f5284fSGreg Tucker
154e1f5284fSGreg Tucker	; reduce
155e1f5284fSGreg Tucker	pslld	xb, 2   ; b is scaled by 4
156e1f5284fSGreg Tucker	movdqa	xsa, xa ; scaled a
157e1f5284fSGreg Tucker	pmulld	xsa, [A_SCALE]
158e1f5284fSGreg Tucker
159e1f5284fSGreg Tucker	phaddd	xa, xa
160e1f5284fSGreg Tucker	phaddd	xb, xb
161e1f5284fSGreg Tucker	phaddd	xsa, xsa
162e1f5284fSGreg Tucker	phaddd	xa, xa
163e1f5284fSGreg Tucker	phaddd	xb, xb
164e1f5284fSGreg Tucker	phaddd	xsa, xsa
165e1f5284fSGreg Tucker
166e1f5284fSGreg Tucker	movd	eax, xa
167e1f5284fSGreg Tucker	xor	edx, edx
168e1f5284fSGreg Tucker	mov	ecx, BASE
169e1f5284fSGreg Tucker	div	ecx		; divide edx:eax by ecx, quot->eax, rem->edx
170e1f5284fSGreg Tucker	mov	a_d, edx
171e1f5284fSGreg Tucker
172e1f5284fSGreg Tucker	psubd	xb, xsa
173e1f5284fSGreg Tucker	movd	eax, xb
174e1f5284fSGreg Tucker	add	eax, b_d
175e1f5284fSGreg Tucker	xor	edx, edx
176e1f5284fSGreg Tucker	mov	ecx, BASE
177e1f5284fSGreg Tucker	div	ecx		; divide edx:eax by ecx, quot->eax, rem->edx
178e1f5284fSGreg Tucker	mov	b_d, edx
179e1f5284fSGreg Tucker
180e1f5284fSGreg Tucker	test	size, size
181e1f5284fSGreg Tucker	jz	.finish
182e1f5284fSGreg Tucker
183e1f5284fSGreg Tucker	; continue loop
184e1f5284fSGreg Tucker	movd	xa, a_d
185e1f5284fSGreg Tucker	pxor	xb, xb
186e1f5284fSGreg Tucker	jmp	.sloop1
187e1f5284fSGreg Tucker
188e1f5284fSGreg Tucker.finish:
189e1f5284fSGreg Tucker	mov	eax, b_d
190e1f5284fSGreg Tucker	shl	eax, 16
191e1f5284fSGreg Tucker	or	eax, a_d
192e1f5284fSGreg Tucker	jmp	.end
193e1f5284fSGreg Tucker
194e1f5284fSGreg Tucker.lt64:
195e1f5284fSGreg Tucker	mov	a_d, init_d
196e1f5284fSGreg Tucker	lea	end, [data + size]
197e1f5284fSGreg Tucker	test	size, size
198e1f5284fSGreg Tucker	jnz	.final_loop
199e1f5284fSGreg Tucker	jmp	.zero_size
200e1f5284fSGreg Tucker
201e1f5284fSGreg Tucker	; handle remaining 1...15 bytes
202e1f5284fSGreg Tucker.do_final:
203e1f5284fSGreg Tucker	; reduce
204e1f5284fSGreg Tucker	pslld	xb, 2   ; b is scaled by 4
205e1f5284fSGreg Tucker	movdqa	xsa, xa ; scaled a
206e1f5284fSGreg Tucker	pmulld	xsa, [A_SCALE]
207e1f5284fSGreg Tucker
208e1f5284fSGreg Tucker	phaddd	xa, xa
209e1f5284fSGreg Tucker	phaddd	xb, xb
210e1f5284fSGreg Tucker	phaddd	xsa, xsa
211e1f5284fSGreg Tucker	phaddd	xa, xa
212e1f5284fSGreg Tucker	phaddd	xb, xb
213e1f5284fSGreg Tucker	phaddd	xsa, xsa
214e1f5284fSGreg Tucker	psubd	xb, xsa
215e1f5284fSGreg Tucker
216e1f5284fSGreg Tucker	movd	a_d, xa
217e1f5284fSGreg Tucker	movd	eax, xb
218e1f5284fSGreg Tucker	add	b_d, eax
219e1f5284fSGreg Tucker
220e1f5284fSGreg Tuckeralign 32
221e1f5284fSGreg Tucker.final_loop:
222e1f5284fSGreg Tucker	movzx	eax, byte[data]
223e1f5284fSGreg Tucker	add	a_d, eax
224e1f5284fSGreg Tucker	inc	data
225e1f5284fSGreg Tucker	add	b_d, a_d
226e1f5284fSGreg Tucker	cmp	data, end
227e1f5284fSGreg Tucker	jb	.final_loop
228e1f5284fSGreg Tucker
229e1f5284fSGreg Tucker.zero_size:
230e1f5284fSGreg Tucker	mov	eax, a_d
231e1f5284fSGreg Tucker	xor	edx, edx
232e1f5284fSGreg Tucker	mov	ecx, BASE
233e1f5284fSGreg Tucker	div	ecx		; divide edx:eax by ecx, quot->eax, rem->edx
234e1f5284fSGreg Tucker	mov	a_d, edx
235e1f5284fSGreg Tucker
236e1f5284fSGreg Tucker	mov	eax, b_d
237e1f5284fSGreg Tucker	xor	edx, edx
238e1f5284fSGreg Tucker	mov	ecx, BASE
239e1f5284fSGreg Tucker	div	ecx		; divide edx:eax by ecx, quot->eax, rem->edx
240e1f5284fSGreg Tucker	shl	edx, 16
241e1f5284fSGreg Tucker	or	edx, a_d
242e1f5284fSGreg Tucker	mov	eax, edx
243e1f5284fSGreg Tucker
244e1f5284fSGreg Tucker.end:
245e1f5284fSGreg Tucker	FUNC_RESTORE
246e1f5284fSGreg Tucker	ret
247e1f5284fSGreg Tucker
248e1f5284fSGreg Tuckerendproc_frame
249e1f5284fSGreg Tucker
250e1f5284fSGreg Tuckersection .data
251e1f5284fSGreg Tuckeralign 32
252e1f5284fSGreg TuckerA_SCALE:
253e1f5284fSGreg Tucker	dq	0x0000000100000000, 0x0000000300000002
254