import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / amd64 / fp / _base_il.s
blob221c8485380755a083717c7ecaa18a30aaaf1a15
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.
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.
13 * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
16 .file "_base_il.s"
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.
24 * The original C sources are included for readability in the pre-function
25 * comment blocks.
28 #include <SYS.h>
31 * Multiplies two normal or subnormal doubles, returns result and exceptions.
34 double
35 __mul_set(double x, double y, int *pe) {
36 extern void _putmxcsr(), _getmxcsr();
37 int csr;
38 double z;
40 _putmxcsr(CSR_DEFAULT);
41 z = x * y;
42 _getmxcsr(&csr);
43 if ((csr & 0x3f) == 0) {
44 *pe = 0;
45 } else {
46 *pe = 1;
48 return (z);
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); */
59 mulsd %xmm1, %xmm0 /* Do the multiply. */
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)
71 * Divides two normal or subnormal doubles x/y, returns result and exceptions.
74 double
75 __div_set(double x, double y, int *pe) {
76 extern void _putmxcsr(), _getmxcsr();
77 int csr;
78 double z;
80 _putmxcsr(CSR_DEFAULT);
81 z = x / y;
82 _getmxcsr(&csr);
83 if ((csr & 0x3f) == 0) {
84 *pe = 0;
85 } else {
86 *pe = 1;
88 return (z);
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); */
100 divsd %xmm1, %xmm0 /* Do the divide. */
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
109 SET_SIZE(__div_set)
111 /* double __dabs(double *d) - Get the abs. value of *d. Straightforward. */
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
121 SET_SIZE(__dabs)