Check in all changes.
[kopensolaris-gnu/glibc.git] / sysdeps / i386 / fpu / s_frexpl.S
1 /* ix87 specific frexp implementation for long double.
2    Copyright (C) 1997, 2000 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library 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 GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include <machine/asm.h>
22 #include "bp-sym.h"
23 #include "bp-asm.h"
24
25 #ifdef __ELF__
26         .section .rodata
27 #else
28         .text
29 #endif
30
31         .align ALIGNARG(4)
32         ASM_TYPE_DIRECTIVE(two64,@object)
33 two64:  .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x43
34         ASM_SIZE_DIRECTIVE(two64)
35         /* The following is LDBL_MAX / ldexp (1.0, 64), the largest
36            number we can handle the normal way.  */
37         ASM_TYPE_DIRECTIVE(largest,@object)
38 largest:
39         .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0x7f, 0, 0
40         ASM_SIZE_DIRECTIVE(largest)
41
42 #ifdef PIC
43 #define MO(op) op##@GOTOFF(%edx)
44 #else
45 #define MO(op) op
46 #endif
47
48 #define PARMS   LINKAGE         /* no space for saved regs */
49 #define VAL0    PARMS
50 #define VAL1    VAL0+4
51 #define VAL2    VAL1+4
52 #define EXPP    VAL2+4
53
54         .text
55 ENTRY (BP_SYM (__frexpl))
56         ENTER
57
58         movl    VAL0(%esp), %ecx
59         movl    VAL2(%esp), %eax
60         orl     VAL1(%esp), %ecx
61         movl    %eax, %edx
62         andl    $0x7fff, %eax
63         orl     %eax, %ecx
64         jz      1f
65         xorl    %ecx, %ecx
66         cmpl    $0x7fff, %eax
67         je      1f
68
69         cmpl    $0, %eax
70         je      2f
71
72         cmpl    $0x7fbe, %eax
73         ja      4f
74
75         fldt    VAL0(%esp)
76 #ifdef  PIC
77         call    3f
78 3:      popl    %edx
79         addl    $_GLOBAL_OFFSET_TABLE_+[.-3b], %edx
80 #endif
81
82         fmull   MO(two64)       /* It's not necessary to use a 80bit factor */
83         movl    $-64, %ecx
84         fstpt   VAL0(%esp)
85         fwait
86         movl    VAL2(%esp), %eax
87         movl    %eax, %edx
88         andl    $0x7fff, %eax
89
90 2:      andl    $0x8000, %edx
91         subl    $16382, %eax
92         orl     $0x3ffe, %edx
93         addl    %eax, %ecx
94         movl    %edx, VAL2(%esp)
95
96         /* Store %ecx in the variable pointed to by the second argument,
97            get the factor from the stack and return.  */
98 1:      movl    EXPP(%esp), %eax
99         CHECK_BOUNDS_BOTH_WIDE (%eax, EXPP(%esp), $4)
100         fldt    VAL0(%esp)
101         movl    %ecx, (%eax)
102
103         LEAVE
104         ret
105
106 4:      movl    VAL2(%esp), %ecx
107         movl    %ecx, %edx
108         andl    $0x7fff, %ecx
109
110         andl    $0x8000, %edx
111         subl    $16382, %ecx
112         orl     $0x3ffe, %edx
113         movl    %edx, VAL2(%esp)
114         jmp     1b
115 END (BP_SYM (__frexpl))
116 weak_alias (BP_SYM (__frexpl), BP_SYM (frexpl))