1/* Function log2f vectorized with AVX2.
2   Copyright (C) 2021-2022 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library; if not, see
17   https://www.gnu.org/licenses/.  */
18
19/*
20 * ALGORITHM DESCRIPTION:
21 *
22 *    Get short reciprocal approximation Rcp ~ 1/mantissa(x)
23 *    R = Rcp*x - 1.0
24 *    log2(x) = k - log2(Rcp) + poly_approximation(R)
25 *       log2(Rcp) is tabulated
26 *
27 *
28 */
29
30/* Offsets for data table __svml_slog2_data_internal
31 */
32#define MinNorm				0
33#define MaxNorm				32
34#define iBrkValue			64
35#define iOffExpoMask			96
36#define One				128
37#define sPoly				160
38
39#include <sysdep.h>
40
41	.section .text.avx2, "ax", @progbits
42ENTRY(_ZGVdN8v_log2f_avx2)
43	pushq	%rbp
44	cfi_def_cfa_offset(16)
45	movq	%rsp, %rbp
46	cfi_def_cfa(6, 16)
47	cfi_offset(6, -16)
48	andq	$-32, %rsp
49	subq	$96, %rsp
50
51	/* reduction: compute r, n */
52	vmovups	iBrkValue+__svml_slog2_data_internal(%rip), %ymm4
53	vmovups	sPoly+64+__svml_slog2_data_internal(%rip), %ymm9
54	vmovups	sPoly+128+__svml_slog2_data_internal(%rip), %ymm10
55	vmovups	sPoly+192+__svml_slog2_data_internal(%rip), %ymm12
56	vpsubd	%ymm4, %ymm0, %ymm1
57	vcmplt_oqps MinNorm+__svml_slog2_data_internal(%rip), %ymm0, %ymm5
58	vcmpnle_uqps MaxNorm+__svml_slog2_data_internal(%rip), %ymm0, %ymm6
59	vpand	iOffExpoMask+__svml_slog2_data_internal(%rip), %ymm1, %ymm3
60	vpsrad	$23, %ymm1, %ymm2
61	vmovups	sPoly+__svml_slog2_data_internal(%rip), %ymm1
62	vpaddd	%ymm4, %ymm3, %ymm8
63	vcvtdq2ps %ymm2, %ymm14
64	vsubps	One+__svml_slog2_data_internal(%rip), %ymm8, %ymm13
65	vfmadd213ps sPoly+32+__svml_slog2_data_internal(%rip), %ymm13, %ymm1
66	vfmadd213ps sPoly+96+__svml_slog2_data_internal(%rip), %ymm13, %ymm9
67	vmulps	%ymm13, %ymm13, %ymm11
68	vfmadd213ps sPoly+160+__svml_slog2_data_internal(%rip), %ymm13, %ymm10
69	vfmadd213ps sPoly+224+__svml_slog2_data_internal(%rip), %ymm13, %ymm12
70	vfmadd213ps %ymm9, %ymm11, %ymm1
71	vfmadd213ps %ymm10, %ymm11, %ymm1
72	vfmadd213ps %ymm12, %ymm11, %ymm1
73	vfmadd213ps sPoly+256+__svml_slog2_data_internal(%rip), %ymm13, %ymm1
74	vorps	%ymm6, %ymm5, %ymm7
75
76	/* combine and get argument value range mask */
77	vmovmskps %ymm7, %edx
78	vfmadd213ps %ymm14, %ymm13, %ymm1
79	testl	%edx, %edx
80
81	/* Go to special inputs processing branch */
82	jne	L(SPECIAL_VALUES_BRANCH)
83	# LOE rbx r12 r13 r14 r15 edx ymm0 ymm1
84
85	/* Restore registers
86	 * and exit the function
87	 */
88
89L(EXIT):
90	vmovaps	%ymm1, %ymm0
91	movq	%rbp, %rsp
92	popq	%rbp
93	cfi_def_cfa(7, 8)
94	cfi_restore(6)
95	ret
96	cfi_def_cfa(6, 16)
97	cfi_offset(6, -16)
98
99	/* Branch to process
100	 * special inputs
101	 */
102
103L(SPECIAL_VALUES_BRANCH):
104	vmovups	%ymm0, 32(%rsp)
105	vmovups	%ymm1, 64(%rsp)
106	# LOE rbx r12 r13 r14 r15 edx ymm1
107
108	xorl	%eax, %eax
109	# LOE rbx r12 r13 r14 r15 eax edx
110
111	vzeroupper
112	movq	%r12, 16(%rsp)
113	/*  DW_CFA_expression: r12 (r12) (DW_OP_lit8; DW_OP_minus; DW_OP_const4s: -32; DW_OP_and; DW_OP_const4s: -80; DW_OP_plus)  */
114	.cfi_escape 0x10, 0x0c, 0x0e, 0x38, 0x1c, 0x0d, 0xe0, 0xff, 0xff, 0xff, 0x1a, 0x0d, 0xb0, 0xff, 0xff, 0xff, 0x22
115	movl	%eax, %r12d
116	movq	%r13, 8(%rsp)
117	/*  DW_CFA_expression: r13 (r13) (DW_OP_lit8; DW_OP_minus; DW_OP_const4s: -32; DW_OP_and; DW_OP_const4s: -88; DW_OP_plus)  */
118	.cfi_escape 0x10, 0x0d, 0x0e, 0x38, 0x1c, 0x0d, 0xe0, 0xff, 0xff, 0xff, 0x1a, 0x0d, 0xa8, 0xff, 0xff, 0xff, 0x22
119	movl	%edx, %r13d
120	movq	%r14, (%rsp)
121	/*  DW_CFA_expression: r14 (r14) (DW_OP_lit8; DW_OP_minus; DW_OP_const4s: -32; DW_OP_and; DW_OP_const4s: -96; DW_OP_plus)  */
122	.cfi_escape 0x10, 0x0e, 0x0e, 0x38, 0x1c, 0x0d, 0xe0, 0xff, 0xff, 0xff, 0x1a, 0x0d, 0xa0, 0xff, 0xff, 0xff, 0x22
123	# LOE rbx r15 r12d r13d
124
125	/* Range mask
126	 * bits check
127	 */
128
129L(RANGEMASK_CHECK):
130	btl	%r12d, %r13d
131
132	/* Call scalar math function */
133	jc	L(SCALAR_MATH_CALL)
134	# LOE rbx r15 r12d r13d
135
136	/* Special inputs
137	 * processing loop
138	 */
139
140L(SPECIAL_VALUES_LOOP):
141	incl	%r12d
142	cmpl	$8, %r12d
143
144	/* Check bits in range mask */
145	jl	L(RANGEMASK_CHECK)
146	# LOE rbx r15 r12d r13d
147
148	movq	16(%rsp), %r12
149	cfi_restore(12)
150	movq	8(%rsp), %r13
151	cfi_restore(13)
152	movq	(%rsp), %r14
153	cfi_restore(14)
154	vmovups	64(%rsp), %ymm1
155
156	/* Go to exit */
157	jmp	L(EXIT)
158	/*  DW_CFA_expression: r12 (r12) (DW_OP_lit8; DW_OP_minus; DW_OP_const4s: -32; DW_OP_and; DW_OP_const4s: -80; DW_OP_plus)  */
159	.cfi_escape 0x10, 0x0c, 0x0e, 0x38, 0x1c, 0x0d, 0xe0, 0xff, 0xff, 0xff, 0x1a, 0x0d, 0xb0, 0xff, 0xff, 0xff, 0x22
160	/*  DW_CFA_expression: r13 (r13) (DW_OP_lit8; DW_OP_minus; DW_OP_const4s: -32; DW_OP_and; DW_OP_const4s: -88; DW_OP_plus)  */
161	.cfi_escape 0x10, 0x0d, 0x0e, 0x38, 0x1c, 0x0d, 0xe0, 0xff, 0xff, 0xff, 0x1a, 0x0d, 0xa8, 0xff, 0xff, 0xff, 0x22
162	/*  DW_CFA_expression: r14 (r14) (DW_OP_lit8; DW_OP_minus; DW_OP_const4s: -32; DW_OP_and; DW_OP_const4s: -96; DW_OP_plus)  */
163	.cfi_escape 0x10, 0x0e, 0x0e, 0x38, 0x1c, 0x0d, 0xe0, 0xff, 0xff, 0xff, 0x1a, 0x0d, 0xa0, 0xff, 0xff, 0xff, 0x22
164	# LOE rbx r12 r13 r14 r15 ymm1
165
166	/* Scalar math fucntion call
167	 * to process special input
168	 */
169
170L(SCALAR_MATH_CALL):
171	movl	%r12d, %r14d
172	vmovss	32(%rsp, %r14, 4), %xmm0
173	call	log2f@PLT
174	# LOE rbx r14 r15 r12d r13d xmm0
175
176	vmovss	%xmm0, 64(%rsp, %r14, 4)
177
178	/* Process special inputs in loop */
179	jmp	L(SPECIAL_VALUES_LOOP)
180	# LOE rbx r15 r12d r13d
181END(_ZGVdN8v_log2f_avx2)
182
183	.section .rodata, "a"
184	.align	32
185
186#ifdef __svml_slog2_data_internal_typedef
187typedef unsigned int VUINT32;
188typedef struct {
189	__declspec(align(32)) VUINT32 MinNorm[8][1];
190	__declspec(align(32)) VUINT32 MaxNorm[8][1];
191	__declspec(align(32)) VUINT32 iBrkValue[8][1];
192	__declspec(align(32)) VUINT32 iOffExpoMask[8][1];
193	__declspec(align(32)) VUINT32 One[8][1];
194	__declspec(align(32)) VUINT32 sPoly[9][8][1];
195} __svml_slog2_data_internal;
196#endif
197__svml_slog2_data_internal:
198	/* MinNorm */
199	.long	0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000
200	/* MaxNorm */
201	.align	32
202	.long	0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff
203	/* iBrkValue = SP 2/3 */
204	.align	32
205	.long	0x3f2aaaab, 0x3f2aaaab, 0x3f2aaaab, 0x3f2aaaab, 0x3f2aaaab, 0x3f2aaaab, 0x3f2aaaab, 0x3f2aaaab
206	/* iOffExpoMask = SP significand mask */
207	.align	32
208	.long	0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff
209	/* sOne = SP 1.0 */
210	.align	32
211	.long	0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000
212	/* spoly[9] */
213	.align	32
214	.long	0x3e554012, 0x3e554012, 0x3e554012, 0x3e554012, 0x3e554012, 0x3e554012, 0x3e554012, 0x3e554012 /* coeff9 */
215	.long	0xbe638E14, 0xbe638E14, 0xbe638E14, 0xbe638E14, 0xbe638E14, 0xbe638E14, 0xbe638E14, 0xbe638E14 /* coeff8 */
216	.long	0x3e4D660B, 0x3e4D660B, 0x3e4D660B, 0x3e4D660B, 0x3e4D660B, 0x3e4D660B, 0x3e4D660B, 0x3e4D660B /* coeff7 */
217	.long	0xbe727824, 0xbe727824, 0xbe727824, 0xbe727824, 0xbe727824, 0xbe727824, 0xbe727824, 0xbe727824 /* coeff6 */
218	.long	0x3e93DD07, 0x3e93DD07, 0x3e93DD07, 0x3e93DD07, 0x3e93DD07, 0x3e93DD07, 0x3e93DD07, 0x3e93DD07 /* coeff5 */
219	.long	0xbeB8B969, 0xbeB8B969, 0xbeB8B969, 0xbeB8B969, 0xbeB8B969, 0xbeB8B969, 0xbeB8B969, 0xbeB8B969 /* coeff4 */
220	.long	0x3eF637C0, 0x3eF637C0, 0x3eF637C0, 0x3eF637C0, 0x3eF637C0, 0x3eF637C0, 0x3eF637C0, 0x3eF637C0 /* coeff3 */
221	.long	0xbf38AA2B, 0xbf38AA2B, 0xbf38AA2B, 0xbf38AA2B, 0xbf38AA2B, 0xbf38AA2B, 0xbf38AA2B, 0xbf38AA2B /* coeff2 */
222	.long	0x3fB8AA3B, 0x3fB8AA3B, 0x3fB8AA3B, 0x3fB8AA3B, 0x3fB8AA3B, 0x3fB8AA3B, 0x3fB8AA3B, 0x3fB8AA3B /* coeff1 */
223	.align	32
224	.type	__svml_slog2_data_internal, @object
225	.size	__svml_slog2_data_internal, .-__svml_slog2_data_internal
226