1 | /* |
2 | * Public domain. |
3 | */ |
4 | |
5 | #include <machine/asm.h> |
6 | #include <libm-alias-finite.h> |
7 | |
8 | .section .rodata.cst8,"aM" ,@progbits,8 |
9 | |
10 | .p2align 3 |
11 | .type one,@object |
12 | one: .double 1.0 |
13 | ASM_SIZE_DIRECTIVE(one) |
14 | /* It is not important that this constant is precise. It is only |
15 | a value which is known to be on the safe side for using the |
16 | fyl2xp1 instruction. */ |
17 | .type limit,@object |
18 | limit: .double 0.29 |
19 | ASM_SIZE_DIRECTIVE(limit) |
20 | |
21 | |
22 | #ifdef PIC |
23 | # define MO(op) op##@GOTOFF(%edx) |
24 | #else |
25 | # define MO(op) op |
26 | #endif |
27 | |
28 | .text |
29 | ENTRY(__ieee754_log2l) |
30 | #ifdef PIC |
31 | LOAD_PIC_REG (dx) |
32 | #endif |
33 | fldl MO(one) |
34 | fldt 4(%esp) // x : 1 |
35 | fxam |
36 | fnstsw |
37 | fld %st // x : x : 1 |
38 | sahf |
39 | jc 3f // in case x is NaN or ħInf |
40 | 4: fsub %st(2), %st // x-1 : x : 1 |
41 | fld %st // x-1 : x-1 : x : 1 |
42 | fabs // |x-1| : x-1 : x : 1 |
43 | fcompl MO(limit) // x-1 : x : 1 |
44 | fnstsw // x-1 : x : 1 |
45 | andb $0x45, %ah |
46 | jz 2f |
47 | fxam |
48 | fnstsw |
49 | andb $0x45, %ah |
50 | cmpb $0x40, %ah |
51 | jne 5f |
52 | fabs // log2(1) is +0 in all rounding modes. |
53 | 5: fstp %st(1) // x-1 : 1 |
54 | fyl2xp1 // log(x) |
55 | ret |
56 | |
57 | 2: fstp %st(0) // x : 1 |
58 | fyl2x // log(x) |
59 | ret |
60 | |
61 | 3: jp 4b // in case x is ħInf |
62 | fstp %st(1) |
63 | fstp %st(1) |
64 | fadd %st(0) |
65 | ret |
66 | END (__ieee754_log2l) |
67 | libm_alias_finite (__ieee754_log2l, __log2l) |
68 | |