1/* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12/* 13 * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved. 14 */ 15 16 .file "_base_il.s" 17 18/* 19 * These files are in assembly because some compilers will mistakenly reorder 20 * multiplications or divisions wrapped in _putsw() and _getsw(). They are 21 * proper subroutines for now, but should be considered candidates for 22 * inlining eventually. 23 * 24 * The original C sources are included for readability in the pre-function 25 * comment blocks. 26 */ 27 28#include <SYS.h> 29 30/* 31 * Multiplies two normal or subnormal doubles, returns result and exceptions. 32 * 33 34double 35__mul_set(double x, double y, int *pe) { 36 extern void _putsw(), _getsw(); 37 int sw; 38 double z; 39 40 _putsw(0); 41 z = x * y; 42 _getsw(&sw); 43 if ((sw & 0x3f) == 0) { 44 *pe = 0; 45 } else { 46 *pe = 1; 47 } 48 return (z); 49} 50 51 */ 52 ENTRY(__mul_set) 53 subl $0x8, %esp /* Give us an extra 8 bytes to play with. */ 54 /* Clear the floating point exception register. */ 55 fnclex /* Equivalent of _putsw(0); */ 56 57 fldl 0xc(%esp) /* Load up x */ 58 fmull 0x14(%esp) /* And multiply! */ 59 60 /* Check to see if the multiply caused any exceptions. */ 61 fstsw (%esp) /* Equivalent of... */ 62 xorl %edx, %edx 63 andl $0x3f, (%esp) /* If the status word (low bits) are zero... */ 64 setne %dl /* ... set *pe (aka. (%eax)) accordingly. */ 65 movl 0x1c(%esp), %eax/* Get pe. */ 66 movl %edx, (%eax) /* And set it. (True == FP exception). */ 67 addl $0x8, %esp /* Release the 8 play bytes. */ 68 ret 69 SET_SIZE(__mul_set) 70 71/* 72 * Divides two normal or subnormal doubles x/y, returns result and exceptions. 73 * 74 75double 76__div_set(double x, double y, int *pe) { 77 extern void _putsw(), _getsw(); 78 int sw; 79 double z; 80 81 _putsw(0); 82 z = x / y; 83 _getsw(&sw); 84 if ((sw & 0x3f) == 0) { 85 *pe = 0; 86 } else { 87 *pe = 1; 88 } 89 return (z); 90} 91 92 */ 93 94 ENTRY(__div_set) 95 subl $0x8, %esp /* Give us an extra 8 bytes to play with. */ 96 /* Clear the floating point exception register. */ 97 fnclex /* Equivalent of _putsw(0); */ 98 99 fldl 0xc(%esp) /* Load up x */ 100 fdivl 0x14(%esp) /* And divide! */ 101 102 /* Check to see if the divide caused any exceptions. */ 103 fstsw (%esp) /* Equivalent of... */ 104 xorl %edx, %edx 105 andl $0x3f, (%esp) /* If the status word (low bits) are zero... */ 106 setne %dl /* ... set *pe (aka. (%eax)) accordingly. */ 107 movl 0x1c(%esp), %eax/* Get pe. */ 108 movl %edx, (%eax) /* And set it. (True == FP exception). */ 109 addl $0x8, %esp /* Release the 8 play bytes. */ 110 ret 111 SET_SIZE(__div_set) 112 113/* double __dabs(double *d) - Get the abs. value of *d. Straightforward. */ 114 115 ENTRY(__dabs) 116 movl 0x4(%esp), %eax 117 fldl (%eax) 118 fabs /* Just let the FPU do its thing. */ 119 ret 120 SET_SIZE(__dabs) 121