diff options
author | Keith M Wesolowski <wesolows@foobazco.org> | 2014-10-31 15:35:24 +0000 |
---|---|---|
committer | Keith M Wesolowski <wesolows@foobazco.org> | 2014-10-31 15:35:24 +0000 |
commit | 17d29671cb8be10e20dee85973c91d75605ccfdc (patch) | |
tree | 4e06f28256ef1aa8ae41f8f8543b145de3141f70 /usr/src/lib/libc | |
parent | 17cf16577a651f32bd17655cbdb526c41cf90d36 (diff) | |
parent | 5a172a1e0f9068ec8db35fa123baecf7bd540eb5 (diff) | |
download | illumos-joyent-17d29671cb8be10e20dee85973c91d75605ccfdc.tar.gz |
[illumos-gate merge]
commit 5a172a1e0f9068ec8db35fa123baecf7bd540eb5
5224 snprintf rounding under [default] FE_TONEAREST
Diffstat (limited to 'usr/src/lib/libc')
-rw-r--r-- | usr/src/lib/libc/amd64/Makefile | 5 | ||||
-rw-r--r-- | usr/src/lib/libc/amd64/fp/_base_il.s | 121 | ||||
-rw-r--r-- | usr/src/lib/libc/amd64/fp/ieee.c (renamed from usr/src/lib/libc/amd64/fp/_base_il.c) | 52 | ||||
-rw-r--r-- | usr/src/lib/libc/i386/Makefile.com | 5 | ||||
-rw-r--r-- | usr/src/lib/libc/i386/fp/_base_il.s | 120 | ||||
-rw-r--r-- | usr/src/lib/libc/i386/fp/ieee.c (renamed from usr/src/lib/libc/i386/fp/_base_il.c) | 52 |
6 files changed, 247 insertions, 108 deletions
diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile index a7cfc36ddb..9a496b0d7e 100644 --- a/usr/src/lib/libc/amd64/Makefile +++ b/usr/src/lib/libc/amd64/Makefile @@ -47,12 +47,12 @@ CRTOBJS= \ DYNOBJS= FPOBJS= \ - _base_il.o \ fpgetmask.o \ fpgetround.o \ fpsetmask.o \ fpsetround.o \ - fpstart.o + fpstart.o \ + ieee.o I386FPOBJS= \ _D_cplx_div.o \ @@ -81,6 +81,7 @@ FPASMOBJS= \ __xgetRD.o \ _xtoll.o \ _xtoull.o \ + _base_il.o \ fpcw.o \ fpgetsticky.o \ fpsetsticky.o diff --git a/usr/src/lib/libc/amd64/fp/_base_il.s b/usr/src/lib/libc/amd64/fp/_base_il.s new file mode 100644 index 0000000000..221c848538 --- /dev/null +++ b/usr/src/lib/libc/amd64/fp/_base_il.s @@ -0,0 +1,121 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved. + */ + + .file "_base_il.s" + +/* + * These files are in assembly because some compilers will mistakenly reorder + * multiplications or divisions wrapped in _putsw() and _getsw(). They are + * proper subroutines for now, but should be considered candidates for + * inlining eventually. + * + * The original C sources are included for readability in the pre-function + * comment blocks. + */ + +#include <SYS.h> + +/* + * Multiplies two normal or subnormal doubles, returns result and exceptions. + * + +double +__mul_set(double x, double y, int *pe) { + extern void _putmxcsr(), _getmxcsr(); + int csr; + double z; + + _putmxcsr(CSR_DEFAULT); + z = x * y; + _getmxcsr(&csr); + if ((csr & 0x3f) == 0) { + *pe = 0; + } else { + *pe = 1; + } + return (z); +} + + */ + ENTRY(__mul_set) + xorl %eax, %eax /* Zero-out eax for later... */ + subq $0x4, %rsp + movl $0x1f80, (%rsp) /* 0x1f80 == CSR_DEFAULT. */ + /* Set the MXCSR to its default (i.e. No FP exceptions). */ + ldmxcsr (%rsp) /* Essentially _putmxcsr(CSR_DEFAULT); */ + + mulsd %xmm1, %xmm0 /* Do the multiply. */ + + /* Check to see if the multiply caused any exceptions. */ + stmxcsr (%rsp) /* Essentially do _getmxcsr(). */ + andl $0x3f, (%rsp) /* Check it. */ + setne %al /* Boolean FP exception indicator for *pe. */ + movl %eax, (%rdi) + addq $0x4, %rsp + ret + SET_SIZE(__mul_set) + +/* + * Divides two normal or subnormal doubles x/y, returns result and exceptions. + * + +double +__div_set(double x, double y, int *pe) { + extern void _putmxcsr(), _getmxcsr(); + int csr; + double z; + + _putmxcsr(CSR_DEFAULT); + z = x / y; + _getmxcsr(&csr); + if ((csr & 0x3f) == 0) { + *pe = 0; + } else { + *pe = 1; + } + return (z); +} + + */ + + ENTRY(__div_set) + xorl %eax, %eax /* Zero-out eax for later... */ + subq $0x4, %rsp + movl $0x1f80, (%rsp) /* 0x1f80 == CSR_DEFAULT. */ + /* Set the MXCSR to its default (i.e. No FP exceptions). */ + ldmxcsr (%rsp) /* Essentially _putmxcsr(CSR_DEFAULT); */ + + divsd %xmm1, %xmm0 /* Do the divide. */ + + /* Check to see if the divide caused any exceptions. */ + stmxcsr (%rsp) /* Essentially do _getmxcsr(). */ + andl $0x3f, (%rsp) /* Check it. */ + setne %al /* Boolean FP exception indicator for *pe. */ + movl %eax, (%rdi) + addq $0x4, %rsp + ret + SET_SIZE(__div_set) + +/* double __dabs(double *d) - Get the abs. value of *d. Straightforward. */ + + ENTRY(__dabs) + subq $0x8, %rsp + movq (%rdi), %rax /* Zero the sign bit of the 64-bit double. */ + btrq $63, %rax + movq %rax, (%rsp) /* Get it into %xmm0... */ + movsd (%rsp), %xmm0 /* ....for an amd64 "double" return. */ + addq $0x8, %rsp + ret + SET_SIZE(__dabs) diff --git a/usr/src/lib/libc/amd64/fp/_base_il.c b/usr/src/lib/libc/amd64/fp/ieee.c index da4e3ea506..8327d64611 100644 --- a/usr/src/lib/libc/amd64/fp/_base_il.c +++ b/usr/src/lib/libc/amd64/fp/ieee.c @@ -24,64 +24,12 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "lint.h" #include "base_conversion.h" #include <sys/isa_defs.h> #define CSR_DEFAULT 0x1f80 -/* The following should be coded as inline expansion templates. */ - -/* - * Multiplies two normal or subnormal doubles, returns result and exceptions. - */ -double -__mul_set(double x, double y, int *pe) { - extern void _putmxcsr(), _getmxcsr(); - int csr; - double z; - - _putmxcsr(CSR_DEFAULT); - z = x * y; - _getmxcsr(&csr); - if ((csr & 0x3f) == 0) { - *pe = 0; - } else { - /* Result may not be exact. */ - *pe = 1; - } - return (z); -} - -/* - * Divides two normal or subnormal doubles x/y, returns result and exceptions. - */ -double -__div_set(double x, double y, int *pe) { - extern void _putmxcsr(), _getmxcsr(); - int csr; - double z; - - _putmxcsr(CSR_DEFAULT); - z = x / y; - _getmxcsr(&csr); - if ((csr & 0x3f) == 0) { - *pe = 0; - } else { - *pe = 1; - } - return (z); -} - -double -__dabs(double *d) -{ - /* should use hardware fabs instruction */ - return ((*d < 0.0) ? -*d : *d); -} - /* * Returns IEEE mode/status and * sets up standard environment for base conversion. diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com index e8b72336f3..01f71c334c 100644 --- a/usr/src/lib/libc/i386/Makefile.com +++ b/usr/src/lib/libc/i386/Makefile.com @@ -70,17 +70,18 @@ FPOBJS= \ _X_cplx_lr_div_ix.o \ _X_cplx_lr_div_rx.o \ _X_cplx_mul.o \ - _base_il.o \ fpgetmask.o \ fpgetround.o \ fpgetsticky.o \ fpsetmask.o \ fpsetround.o \ fpsetsticky.o \ - fpstart.o + fpstart.o \ + ieee.o FPASMOBJS= \ __xgetRD.o \ + _base_il.o \ _xtoll.o \ _xtoull.o \ fpcw.o diff --git a/usr/src/lib/libc/i386/fp/_base_il.s b/usr/src/lib/libc/i386/fp/_base_il.s new file mode 100644 index 0000000000..157e977922 --- /dev/null +++ b/usr/src/lib/libc/i386/fp/_base_il.s @@ -0,0 +1,120 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved. + */ + + .file "_base_il.s" + +/* + * These files are in assembly because some compilers will mistakenly reorder + * multiplications or divisions wrapped in _putsw() and _getsw(). They are + * proper subroutines for now, but should be considered candidates for + * inlining eventually. + * + * The original C sources are included for readability in the pre-function + * comment blocks. + */ + +#include <SYS.h> + +/* + * Multiplies two normal or subnormal doubles, returns result and exceptions. + * + +double +__mul_set(double x, double y, int *pe) { + extern void _putsw(), _getsw(); + int sw; + double z; + + _putsw(0); + z = x * y; + _getsw(&sw); + if ((sw & 0x3f) == 0) { + *pe = 0; + } else { + *pe = 1; + } + return (z); +} + + */ + ENTRY(__mul_set) + subl $0x8, %esp /* Give us an extra 8 bytes to play with. */ + /* Clear the floating point exception register. */ + fnclex /* Equivalent of _putsw(0); */ + + fldl 0xc(%esp) /* Load up x */ + fmull 0x14(%esp) /* And multiply! */ + + /* Check to see if the multiply caused any exceptions. */ + fstsw (%esp) /* Equivalent of... */ + xorl %edx, %edx + andl $0x3f, (%esp) /* If the status word (low bits) are zero... */ + setne %dl /* ... set *pe (aka. (%eax)) accordingly. */ + movl 0x1c(%esp), %eax/* Get pe. */ + movl %edx, (%eax) /* And set it. (True == FP exception). */ + addl $0x8, %esp /* Release the 8 play bytes. */ + ret + SET_SIZE(__mul_set) + +/* + * Divides two normal or subnormal doubles x/y, returns result and exceptions. + * + +double +__div_set(double x, double y, int *pe) { + extern void _putsw(), _getsw(); + int sw; + double z; + + _putsw(0); + z = x / y; + _getsw(&sw); + if ((sw & 0x3f) == 0) { + *pe = 0; + } else { + *pe = 1; + } + return (z); +} + + */ + + ENTRY(__div_set) + subl $0x8, %esp /* Give us an extra 8 bytes to play with. */ + /* Clear the floating point exception register. */ + fnclex /* Equivalent of _putsw(0); */ + + fldl 0xc(%esp) /* Load up x */ + fdivl 0x14(%esp) /* And divide! */ + + /* Check to see if the divide caused any exceptions. */ + fstsw (%esp) /* Equivalent of... */ + xorl %edx, %edx + andl $0x3f, (%esp) /* If the status word (low bits) are zero... */ + setne %dl /* ... set *pe (aka. (%eax)) accordingly. */ + movl 0x1c(%esp), %eax/* Get pe. */ + movl %edx, (%eax) /* And set it. (True == FP exception). */ + addl $0x8, %esp /* Release the 8 play bytes. */ + ret + SET_SIZE(__div_set) + +/* double __dabs(double *d) - Get the abs. value of *d. Straightforward. */ + + ENTRY(__dabs) + movl 0x4(%esp), %eax + fldl (%eax) + fabs /* Just let the FPU do its thing. */ + ret + SET_SIZE(__dabs) diff --git a/usr/src/lib/libc/i386/fp/_base_il.c b/usr/src/lib/libc/i386/fp/ieee.c index a821932d41..3e2f4c950c 100644 --- a/usr/src/lib/libc/i386/fp/_base_il.c +++ b/usr/src/lib/libc/i386/fp/ieee.c @@ -24,61 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "lint.h" #include "base_conversion.h" -/* The following should be coded as inline expansion templates. */ - -/* - * Multiplies two normal or subnormal doubles, returns result and exceptions. - */ -double -__mul_set(double x, double y, int *pe) { - extern void _putsw(), _getsw(); - int sw; - double z; - - _putsw(0); - z = x * y; - _getsw(&sw); - if ((sw & 0x3f) == 0) { - *pe = 0; - } else { - /* Result may not be exact. */ - *pe = 1; - } - return (z); -} - -/* - * Divides two normal or subnormal doubles x/y, returns result and exceptions. - */ -double -__div_set(double x, double y, int *pe) { - extern void _putsw(), _getsw(); - int sw; - double z; - - _putsw(0); - z = x / y; - _getsw(&sw); - if ((sw & 0x3f) == 0) { - *pe = 0; - } else { - *pe = 1; - } - return (z); -} - -double -__dabs(double *d) -{ - /* should use hardware fabs instruction */ - return ((*d < 0.0) ? -*d : *d); -} - /* * Returns IEEE mode/status and * sets up standard environment for base conversion. |