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 _putmxcsr(), _getmxcsr(); 37 int csr; 38 double z; 39 40 _putmxcsr(CSR_DEFAULT); 41 z = x * y; 42 _getmxcsr(&csr); 43 if ((csr & 0x3f) == 0) { 44 *pe = 0; 45 } else { 46 *pe = 1; 47 } 48 return (z); 49} 50 51 */ 52 ENTRY(__mul_set) 53 xorl %eax, %eax /* Zero-out eax for later... */ 54 subq $0x4, %rsp 55 movl $0x1f80, (%rsp) /* 0x1f80 == CSR_DEFAULT. */ 56 /* Set the MXCSR to its default (i.e. No FP exceptions). */ 57 ldmxcsr (%rsp) /* Essentially _putmxcsr(CSR_DEFAULT); */ 58 59 mulsd %xmm1, %xmm0 /* Do the multiply. */ 60 61 /* Check to see if the multiply caused any exceptions. */ 62 stmxcsr (%rsp) /* Essentially do _getmxcsr(). */ 63 andl $0x3f, (%rsp) /* Check it. */ 64 setne %al /* Boolean FP exception indicator for *pe. */ 65 movl %eax, (%rdi) 66 addq $0x4, %rsp 67 ret 68 SET_SIZE(__mul_set) 69 70/* 71 * Divides two normal or subnormal doubles x/y, returns result and exceptions. 72 * 73 74double 75__div_set(double x, double y, int *pe) { 76 extern void _putmxcsr(), _getmxcsr(); 77 int csr; 78 double z; 79 80 _putmxcsr(CSR_DEFAULT); 81 z = x / y; 82 _getmxcsr(&csr); 83 if ((csr & 0x3f) == 0) { 84 *pe = 0; 85 } else { 86 *pe = 1; 87 } 88 return (z); 89} 90 91 */ 92 93 ENTRY(__div_set) 94 xorl %eax, %eax /* Zero-out eax for later... */ 95 subq $0x4, %rsp 96 movl $0x1f80, (%rsp) /* 0x1f80 == CSR_DEFAULT. */ 97 /* Set the MXCSR to its default (i.e. No FP exceptions). */ 98 ldmxcsr (%rsp) /* Essentially _putmxcsr(CSR_DEFAULT); */ 99 100 divsd %xmm1, %xmm0 /* Do the divide. */ 101 102 /* Check to see if the divide caused any exceptions. */ 103 stmxcsr (%rsp) /* Essentially do _getmxcsr(). */ 104 andl $0x3f, (%rsp) /* Check it. */ 105 setne %al /* Boolean FP exception indicator for *pe. */ 106 movl %eax, (%rdi) 107 addq $0x4, %rsp 108 ret 109 SET_SIZE(__div_set) 110 111/* double __dabs(double *d) - Get the abs. value of *d. Straightforward. */ 112 113 ENTRY(__dabs) 114 subq $0x8, %rsp 115 movq (%rdi), %rax /* Zero the sign bit of the 64-bit double. */ 116 btrq $63, %rax 117 movq %rax, (%rsp) /* Get it into %xmm0... */ 118 movsd (%rsp), %xmm0 /* ....for an amd64 "double" return. */ 119 addq $0x8, %rsp 120 ret 121 SET_SIZE(__dabs) 122