]>
Commit | Line | Data |
---|---|---|
aece054b | 1 | /* sqrt function. PowerPC32 version. |
568035b7 | 2 | Copyright (C) 2007-2013 Free Software Foundation, Inc. |
aece054b UD |
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 | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
aece054b UD |
18 | |
19 | #include <sysdep.h> | |
20 | #include <math_ldbl_opt.h> | |
21 | ||
22 | /* double [fp1] sqrt (double x [fp1]) | |
23 | Power4 (ISA V2.0) and above implement sqrt in hardware (not optional). | |
24 | The fsqrt instruction generates the correct value for all inputs and | |
2ccdea26 | 25 | sets the appropriate floating point exceptions. Extended checking is |
aece054b UD |
26 | only needed to set errno (via __kernel_standard) if the input value |
27 | is negative. | |
9c84384c | 28 | |
aece054b UD |
29 | The fsqrt will set FPCC and FU (Floating Point Unordered or NaN |
30 | to indicated that the input value was negative or NaN. Use Move to | |
31 | Condition Register from FPSCR to copy the FPCC field to cr1. The | |
32 | branch on summary overflow transfers control to w_sqrt to process | |
33 | any error conditions. Otherwise we can return the result directly. | |
9c84384c | 34 | |
aece054b UD |
35 | This part of the function is a leaf routine, so no need to stack a |
36 | frame or execute prologue/epilogue code. This means it is safe to | |
37 | transfer directly to w_sqrt as long as the input value (f1) is | |
ded5b9b7 | 38 | preserved. Putting the sqrt result into f2 (double parameter 2) |
aece054b UD |
39 | allows passing both the input value and sqrt result into the extended |
40 | wrapper so there is no need to recompute. | |
9c84384c | 41 | |
aece054b UD |
42 | This tactic avoids the overhead of stacking a frame for the normal |
43 | (non-error) case. Until gcc supports prologue shrink-wrapping | |
44 | this is the best we can do. */ | |
45 | ||
46 | .section ".text" | |
47 | .machine power4 | |
48 | EALIGN (__sqrt, 5, 0) | |
49 | fsqrt fp2,fp1 | |
50 | mcrfs cr1,4 | |
51 | bso- cr1,.Lw_sqrt | |
52 | fmr fp1,fp2 | |
53 | blr | |
54 | .align 4 | |
55 | .Lw_sqrt: | |
56 | mflr r0 | |
57 | stwu r1,-16(r1) | |
58 | cfi_adjust_cfa_offset(16) | |
59 | fmr fp12,fp2 | |
60 | stw r0,20(r1) | |
61 | stw r30,8(r1) | |
3f241d75 AS |
62 | cfi_offset(lr,20-16) |
63 | cfi_offset(r30,8-16) | |
aece054b | 64 | #ifdef SHARED |
91d2a845 WS |
65 | SETUP_GOT_ACCESS(r30,got_label) |
66 | addis r30,r30,_GLOBAL_OFFSET_TABLE_-got_label@ha | |
67 | addi r30,r30,_GLOBAL_OFFSET_TABLE_-got_label@l | |
aece054b UD |
68 | lwz r9,_LIB_VERSION@got(30) |
69 | lwz r0,0(r9) | |
aece054b UD |
70 | #else |
71 | lis r9,_LIB_VERSION@ha | |
72 | lwz r0,_LIB_VERSION@l(r9) | |
73 | #endif | |
74 | /* if (_LIB_VERSION == _IEEE_) return z; */ | |
75 | cmpwi cr7,r0,-1 | |
76 | beq- cr7,.L4 | |
77 | /* if (x != x) return z; !isnan*/ | |
78 | fcmpu cr7,fp1,fp1 | |
79 | bne- cr7,.L4 | |
80 | /* if (x < 0.0) | |
81 | return __kernel_standard (x, x, 26) */ | |
82 | fmr fp2,fp1 | |
83 | fabs fp0,fp1 | |
84 | li r3,26 | |
85 | fcmpu cr7,fp1,fp0 | |
86 | bne- cr7,.L11 | |
87 | .L4: | |
88 | lwz r0,20(r1) | |
89 | fmr fp1,fp12 | |
90 | lwz r30,8(r1) | |
91 | addi r1,r1,16 | |
92 | mtlr r0 | |
93 | blr | |
94 | .L11: | |
95 | bl __kernel_standard@plt | |
96 | fmr fp12,fp1 | |
97 | b .L4 | |
98 | END (__sqrt) | |
99 | ||
100 | weak_alias (__sqrt, sqrt) | |
101 | ||
102 | #ifdef NO_LONG_DOUBLE | |
103 | weak_alias (__sqrt, sqrtl) | |
104 | strong_alias (__sqrt, __sqrtl) | |
105 | #endif | |
106 | #if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0) | |
107 | compat_symbol (libm, __sqrt, sqrtl, GLIBC_2_0) | |
108 | #endif | |
109 |