]>
Commit | Line | Data |
---|---|---|
04067002 | 1 | /* llround function. PowerPC32 on PowerPC64 version. |
d4697bc9 | 2 | Copyright (C) 2004-2014 Free Software Foundation, Inc. |
04067002 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/>. */ | |
04067002 UD |
18 | |
19 | #include <sysdep.h> | |
20 | #include <math_ldbl_opt.h> | |
21 | ||
6a31fe7f | 22 | .section .rodata.cst8,"aM",@progbits,8 |
c1e6b459 | 23 | .align 3 |
6a31fe7f AM |
24 | .LC0: .long (52+127)<<23 /* 0x1p+52 */ |
25 | .long (-1+127)<<23 /* 0.5 */ | |
04067002 UD |
26 | |
27 | .section ".text" | |
c1e6b459 | 28 | |
04067002 | 29 | /* long [r3] lround (float x [fp1]) |
9c84384c | 30 | IEEE 1003.1 lround function. IEEE specifies "round to the nearest |
04067002 UD |
31 | integer value, rounding halfway cases away from zero, regardless of |
32 | the current rounding mode." However PowerPC Architecture defines | |
9c84384c JM |
33 | "round to Nearest" as "Choose the best approximation. In case of a |
34 | tie, choose the one that is even (least significant bit o).". | |
04067002 UD |
35 | So we can't use the PowerPC "round to Nearest" mode. Instead we set |
36 | "round toward Zero" mode and round by adding +-0.5 before rounding | |
c1e6b459 UD |
37 | to the integer value. |
38 | ||
39 | It is necessary to detect when x is (+-)0x1.fffffffffffffp-2 | |
40 | because adding +-0.5 in this case will cause an erroneous shift, | |
41 | carry and round. We simply return 0 if 0.5 > x > -0.5. Likewise | |
42 | if x is and odd number between +-(2^52 and 2^53-1) a shift and | |
43 | carry will erroneously round if biased with +-0.5. Therefore if x | |
44 | is greater/less than +-2^52 we don't need to bias the number with | |
45 | +-0.5. */ | |
04067002 UD |
46 | |
47 | ENTRY (__llround) | |
48 | stwu r1,-16(r1) | |
49 | cfi_adjust_cfa_offset (16) | |
50 | #ifdef SHARED | |
51 | mflr r11 | |
52 | cfi_register(lr,r11) | |
91d2a845 WS |
53 | SETUP_GOT_ACCESS(r9,got_label) |
54 | addis r9,r9,.LC0-got_label@ha | |
55 | addi r9,r9,.LC0-got_label@l | |
04067002 UD |
56 | mtlr r11 |
57 | cfi_same_value (lr) | |
6a31fe7f AM |
58 | lfs fp9,0(r9) |
59 | lfs fp10,4(r9) | |
04067002 | 60 | #else |
c1e6b459 | 61 | lis r9,.LC0@ha |
6a31fe7f AM |
62 | lfs fp9,.LC0@l(r9) /* Load 2^52 into fpr9. */ |
63 | lfs fp10,.LC0@l+4(r9) /* Load 0.5 into fpr10. */ | |
04067002 | 64 | #endif |
c1e6b459 UD |
65 | fabs fp2,fp1 /* Get the absolute value of x. */ |
66 | fsub fp12,fp10,fp10 /* Compute 0.0 into fpr12. */ | |
67 | fcmpu cr6,fp2,fp10 /* if |x| < 0.5 */ | |
9ea8bfec UD |
68 | fcmpu cr7,fp2,fp9 /* if |x| >= 2^52 */ |
69 | fcmpu cr1,fp1,fp12 /* x is negative? x < 0.0 */ | |
c1e6b459 | 70 | blt- cr6,.Lretzero /* 0.5 > x < -0.5 so just return 0. */ |
9ea8bfec | 71 | bge- cr7,.Lnobias /* 2^52 > x < -2^52 just convert with no bias. */ |
c1e6b459 | 72 | fadd fp3,fp2,fp10 /* |x|+=0.5 bias to prepare to round. */ |
9ea8bfec | 73 | bge cr1,.Lconvert /* x is positive so don't negate x. */ |
c1e6b459 UD |
74 | fnabs fp3,fp3 /* -(|x|+=0.5) */ |
75 | .Lconvert: | |
76 | fctidz fp4,fp3 /* Convert to Integer double word round toward 0. */ | |
77 | stfd fp4,8(r1) | |
78 | nop | |
79 | nop | |
04067002 | 80 | nop |
6a31fe7f AM |
81 | lwz r3,8+HIWORD(r1) /* Load return as integer. */ |
82 | lwz r4,8+LOWORD(r1) | |
c1e6b459 | 83 | .Lout: |
04067002 UD |
84 | addi r1,r1,16 |
85 | blr | |
c1e6b459 UD |
86 | .Lretzero: /* 0.5 > x > -0.5 */ |
87 | li r3,0 /* return 0. */ | |
88 | li r4,0 | |
89 | b .Lout | |
90 | .Lnobias: | |
91 | fmr fp3,fp1 | |
92 | b .Lconvert | |
04067002 UD |
93 | END (__llround) |
94 | ||
95 | weak_alias (__llround, llround) | |
96 | ||
97 | strong_alias (__llround, __llroundf) | |
98 | weak_alias (__llround, llroundf) | |
99 | ||
100 | #ifdef NO_LONG_DOUBLE | |
101 | weak_alias (__llround, llroundl) | |
102 | strong_alias (__llround, __llroundl) | |
103 | #endif | |
104 | #if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1) | |
105 | compat_symbol (libm, __llround, llroundl, GLIBC_2_1) | |
106 | #endif |