--- a/libc/sysdeps/linux/powerpc/Makefile.arch +++ b/libc/sysdeps/linux/powerpc/Makefile.arch @@ -5,7 +5,7 @@ # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. # -CSRC := __syscall_error.c pread_write.c ioctl.c +CSRC := __syscall_error.c pread_write.c ioctl.c copysignl.c SSRC := \ __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S brk.S \ --- /dev/null +++ b/libc/sysdeps/linux/powerpc/copysignl.c @@ -0,0 +1,89 @@ +/* s_copysignl.c -- long double version of s_copysign.c. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * copysignl(long double x, long double y) + * copysignl(x,y) returns a value with the magnitude of x and + * with the sign bit of y. + */ + +#include <endian.h> +#include <stdint.h> + +#if __FLOAT_WORD_ORDER == BIG_ENDIAN + +typedef union +{ + long double value; + struct + { + int sign_exponent:16; + unsigned int empty:16; + uint32_t msw; + uint32_t lsw; + } parts; +} ieee_long_double_shape_type; + +#endif + +#if __FLOAT_WORD_ORDER == LITTLE_ENDIAN + +typedef union +{ + long double value; + struct + { + uint32_t lsw; + uint32_t msw; + int sign_exponent:16; + unsigned int empty:16; + } parts; +} ieee_long_double_shape_type; + +#endif + +/* Get int from the exponent of a long double. */ + +#define GET_LDOUBLE_EXP(exp,d) \ +do { \ + ieee_long_double_shape_type ge_u; \ + ge_u.value = (d); \ + (exp) = ge_u.parts.sign_exponent; \ +} while (0) + +/* Set exponent of a long double from an int. */ + +#define SET_LDOUBLE_EXP(d,exp) \ +do { \ + ieee_long_double_shape_type se_u; \ + se_u.value = (d); \ + se_u.parts.sign_exponent = (exp); \ + (d) = se_u.value; \ +} while (0) + +long double copysignl(long double x, long double y); +libc_hidden_proto(copysignl); + +long double copysignl(long double x, long double y) +{ + uint32_t es1,es2; + GET_LDOUBLE_EXP(es1,x); + GET_LDOUBLE_EXP(es2,y); + SET_LDOUBLE_EXP(x,(es1&0x7fff)|(es2&0x8000)); + return x; +} + +libc_hidden_def(copysignl);