xref: /illumos-gate/usr/src/lib/libc/amd64/fp/_base_il.S (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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