1/* ix87 specific frexp implementation for double.
2   Copyright (C) 1997-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#include <machine/asm.h>
20#include <libm-alias-double.h>
21
22	.section .rodata
23
24	.align ALIGNARG(4)
25	.type two54,@object
26two54:	.byte 0, 0, 0, 0, 0, 0, 0x50, 0x43
27	ASM_SIZE_DIRECTIVE(two54)
28
29#ifdef PIC
30#define MO(op) op##@GOTOFF(%edx)
31#else
32#define MO(op) op
33#endif
34
35#define PARMS	4		/* no space for saved regs */
36#define VAL0	PARMS
37#define VAL1	VAL0+4
38#define EXPP	VAL1+4
39
40	.text
41ENTRY (__frexp)
42
43	movl	VAL0(%esp), %ecx
44	movl	VAL1(%esp), %eax
45	movl	%eax, %edx
46	andl	$0x7fffffff, %eax
47	orl	%eax, %ecx
48	jz	1f
49	xorl	%ecx, %ecx
50	cmpl	$0x7ff00000, %eax
51	jae	1f
52
53	cmpl	$0x00100000, %eax
54	jae	2f
55
56	fldl	VAL0(%esp)
57#ifdef	PIC
58	LOAD_PIC_REG (dx)
59#endif
60	fmull	MO(two54)
61	movl	$-54, %ecx
62	fstpl	VAL0(%esp)
63	fwait
64	movl	VAL1(%esp), %eax
65	movl	%eax, %edx
66	andl	$0x7fffffff, %eax
67
682:	shrl	$20, %eax
69	andl	$0x800fffff, %edx
70	subl	$1022, %eax
71	orl	$0x3fe00000, %edx
72	addl	%eax, %ecx
73	movl	%edx, VAL1(%esp)
74
75	/* Store %ecx in the variable pointed to by the second argument,
76	   get the factor from the stack and return.  */
771:	movl	EXPP(%esp), %eax
78	fldl	VAL0(%esp)
79	movl	%ecx, (%eax)
80
81	ret
82END (__frexp)
83libm_alias_double (__frexp, frexp)
84