--- old/usr/src/lib/libc/amd64/Makefile	Tue Oct 28 23:21:08 2014
+++ new/usr/src/lib/libc/amd64/Makefile	Tue Oct 28 23:21:08 2014
@@ -47,12 +47,12 @@
 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 @@
 	__xgetRD.o		\
 	_xtoll.o		\
 	_xtoull.o		\
+	_base_il.o		\
 	fpcw.o			\
 	fpgetsticky.o		\
 	fpsetsticky.o
--- old/usr/src/lib/libc/amd64/fp/_base_il.c	Tue Oct 28 23:21:09 2014
+++ /dev/null	Tue Oct 28 23:21:04 2014
@@ -1,107 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * 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.
- */
-void
-__get_ieee_flags(__ieee_flags_type *b) {
-	extern void _getmxcsr(), _putmxcsr();
-
-	_getmxcsr(&b->status);
-
-	/* round-to-nearest, all exceptions masked, gradual underflow */
-	_putmxcsr(CSR_DEFAULT);
-}
-
-/*
- * Restores previous IEEE mode/status
- */
-void
-__set_ieee_flags(__ieee_flags_type *b) {
-	extern void _putmxcsr();
-
-	_putmxcsr(b->status);
-}
--- /dev/null	Tue Oct 28 23:21:09 2014
+++ new/usr/src/lib/libc/amd64/fp/_base_il.s	Tue Oct 28 23:21:09 2014
@@ -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)
--- /dev/null	Tue Oct 28 23:21:09 2014
+++ new/usr/src/lib/libc/amd64/fp/ieee.c	Tue Oct 28 23:21:09 2014
@@ -0,0 +1,55 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "lint.h"
+#include "base_conversion.h"
+#include <sys/isa_defs.h>
+
+#define	CSR_DEFAULT 0x1f80
+
+/*
+ * Returns IEEE mode/status and
+ * sets up standard environment for base conversion.
+ */
+void
+__get_ieee_flags(__ieee_flags_type *b) {
+	extern void _getmxcsr(), _putmxcsr();
+
+	_getmxcsr(&b->status);
+
+	/* round-to-nearest, all exceptions masked, gradual underflow */
+	_putmxcsr(CSR_DEFAULT);
+}
+
+/*
+ * Restores previous IEEE mode/status
+ */
+void
+__set_ieee_flags(__ieee_flags_type *b) {
+	extern void _putmxcsr();
+
+	_putmxcsr(b->status);
+}
--- old/usr/src/lib/libc/i386/Makefile.com	Tue Oct 28 23:21:09 2014
+++ new/usr/src/lib/libc/i386/Makefile.com	Tue Oct 28 23:21:09 2014
@@ -70,7 +70,6 @@
 	_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		\
@@ -77,10 +76,12 @@
 	fpsetmask.o		\
 	fpsetround.o		\
 	fpsetsticky.o		\
-	fpstart.o
+	fpstart.o		\
+	ieee.o
 
 FPASMOBJS=			\
 	__xgetRD.o		\
+	_base_il.o		\
 	_xtoll.o		\
 	_xtoull.o		\
 	fpcw.o
--- old/usr/src/lib/libc/i386/fp/_base_il.c	Tue Oct 28 23:21:09 2014
+++ /dev/null	Tue Oct 28 23:21:09 2014
@@ -1,113 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * 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.
- */
-void
-__get_ieee_flags(__ieee_flags_type *b) {
-	extern void _getcw(), _getsw(), _putcw();
-	int cw;
-
-	_getcw(&cw);
-	b->mode = cw;
-	_getsw(&b->status);
-	/*
-	 * set CW to...
-	 * RC (bits 10:11)	0 == round to nearest even
-	 * PC (bits 8:9)	2 == round to double
-	 * EM (bits 0:5)	0x3f == all exception trapping masked off
-	 */
-	cw = (cw & ~0xf3f) | 0x23f;
-	_putcw(cw);
-}
-
-/*
- * Restores previous IEEE mode/status
- */
-void
-__set_ieee_flags(__ieee_flags_type *b) {
-	extern void _putcw(), _putsw();
-
-	_putcw(b->mode);
-	_putsw(b->status);
-}
--- /dev/null	Tue Oct 28 23:21:09 2014
+++ new/usr/src/lib/libc/i386/fp/_base_il.s	Tue Oct 28 23:21:09 2014
@@ -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)
--- /dev/null	Tue Oct 28 23:21:09 2014
+++ new/usr/src/lib/libc/i386/fp/ieee.c	Tue Oct 28 23:21:09 2014
@@ -0,0 +1,61 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "lint.h"
+#include "base_conversion.h"
+
+/*
+ * Returns IEEE mode/status and
+ * sets up standard environment for base conversion.
+ */
+void
+__get_ieee_flags(__ieee_flags_type *b) {
+	extern void _getcw(), _getsw(), _putcw();
+	int cw;
+
+	_getcw(&cw);
+	b->mode = cw;
+	_getsw(&b->status);
+	/*
+	 * set CW to...
+	 * RC (bits 10:11)	0 == round to nearest even
+	 * PC (bits 8:9)	2 == round to double
+	 * EM (bits 0:5)	0x3f == all exception trapping masked off
+	 */
+	cw = (cw & ~0xf3f) | 0x23f;
+	_putcw(cw);
+}
+
+/*
+ * Restores previous IEEE mode/status
+ */
+void
+__set_ieee_flags(__ieee_flags_type *b) {
+	extern void _putcw(), _putsw();
+
+	_putcw(b->mode);
+	_putsw(b->status);
+}
