uClibc: implement copysignl in libc on powerpc to avoid undefined references in libstdc++
[openwrt/openwrt.git] / toolchain / uClibc / patches-0.9.30.1 / 450-powerpc_copysignl.patch
1 --- a/libc/sysdeps/linux/powerpc/Makefile.arch
2 +++ b/libc/sysdeps/linux/powerpc/Makefile.arch
3 @@ -5,7 +5,7 @@
4 # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
5 #
6
7 -CSRC := __syscall_error.c pread_write.c ioctl.c
8 +CSRC := __syscall_error.c pread_write.c ioctl.c copysignl.c
9
10 SSRC := \
11 __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S brk.S \
12 --- /dev/null
13 +++ b/libc/sysdeps/linux/powerpc/copysignl.c
14 @@ -0,0 +1,89 @@
15 +/* s_copysignl.c -- long double version of s_copysign.c.
16 + * Conversion to long double by Ulrich Drepper,
17 + * Cygnus Support, drepper@cygnus.com.
18 + */
19 +
20 +/*
21 + * ====================================================
22 + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
23 + *
24 + * Developed at SunPro, a Sun Microsystems, Inc. business.
25 + * Permission to use, copy, modify, and distribute this
26 + * software is freely granted, provided that this notice
27 + * is preserved.
28 + * ====================================================
29 + */
30 +
31 +/*
32 + * copysignl(long double x, long double y)
33 + * copysignl(x,y) returns a value with the magnitude of x and
34 + * with the sign bit of y.
35 + */
36 +
37 +#include <endian.h>
38 +#include <stdint.h>
39 +
40 +#if __FLOAT_WORD_ORDER == BIG_ENDIAN
41 +
42 +typedef union
43 +{
44 + long double value;
45 + struct
46 + {
47 + int sign_exponent:16;
48 + unsigned int empty:16;
49 + uint32_t msw;
50 + uint32_t lsw;
51 + } parts;
52 +} ieee_long_double_shape_type;
53 +
54 +#endif
55 +
56 +#if __FLOAT_WORD_ORDER == LITTLE_ENDIAN
57 +
58 +typedef union
59 +{
60 + long double value;
61 + struct
62 + {
63 + uint32_t lsw;
64 + uint32_t msw;
65 + int sign_exponent:16;
66 + unsigned int empty:16;
67 + } parts;
68 +} ieee_long_double_shape_type;
69 +
70 +#endif
71 +
72 +/* Get int from the exponent of a long double. */
73 +
74 +#define GET_LDOUBLE_EXP(exp,d) \
75 +do { \
76 + ieee_long_double_shape_type ge_u; \
77 + ge_u.value = (d); \
78 + (exp) = ge_u.parts.sign_exponent; \
79 +} while (0)
80 +
81 +/* Set exponent of a long double from an int. */
82 +
83 +#define SET_LDOUBLE_EXP(d,exp) \
84 +do { \
85 + ieee_long_double_shape_type se_u; \
86 + se_u.value = (d); \
87 + se_u.parts.sign_exponent = (exp); \
88 + (d) = se_u.value; \
89 +} while (0)
90 +
91 +long double copysignl(long double x, long double y);
92 +libc_hidden_proto(copysignl);
93 +
94 +long double copysignl(long double x, long double y)
95 +{
96 + uint32_t es1,es2;
97 + GET_LDOUBLE_EXP(es1,x);
98 + GET_LDOUBLE_EXP(es2,y);
99 + SET_LDOUBLE_EXP(x,(es1&0x7fff)|(es2&0x8000));
100 + return x;
101 +}
102 +
103 +libc_hidden_def(copysignl);