Home | History | Annotate | Download | only in i386
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 	.ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 	.file	"fsr.s"
     30 
     31 	.section	.data
     32 	.align 4
     33 
     34 	.weak	__fsr_init_value
     35 
     36 __fsr_init_value_ptr:
     37 	.4byte	__fsr_init_value
     38 	.type   __fsr_init_value_ptr,@object
     39 	.size   __fsr_init_value_ptr,4
     40 
     41 /*
     42  * The following table maps trap enable bits in __fsr_init_value
     43  * (after shifting right one bit):
     44  *
     45  * bit 0 - inexact trap
     46  * bit 1 - division trap
     47  * bit 2 - underflow trap
     48  * bit 3 - overflow trap
     49  * bit 4 - invalid trap
     50  *
     51  * to exception masks in the floating point control word
     52  *
     53  * bit 0 - invalid mask
     54  * bit 2 - zero divide mask
     55  * bit 3 - overflow mask
     56  * bit 4 - underflow mask
     57  * bit 5 - inexact mask
     58  */
     59 	.local	trap_table
     60 	.type	trap_table,@object
     61 trap_table:
     62 	.byte	0b11111111
     63 	.byte	0b11011111
     64 	.byte	0b11111011
     65 	.byte	0b11011011
     66 	.byte	0b11101111
     67 	.byte	0b11001111
     68 	.byte	0b11101011
     69 	.byte	0b11001011
     70 	.byte	0b11110111
     71 	.byte	0b11010111
     72 	.byte	0b11110011
     73 	.byte	0b11010011
     74 	.byte	0b11100111
     75 	.byte	0b11000111
     76 	.byte	0b11100011
     77 	.byte	0b11000011
     78 	.byte	0b11111110
     79 	.byte	0b11011110
     80 	.byte	0b11111010
     81 	.byte	0b11011010
     82 	.byte	0b11101110
     83 	.byte	0b11001110
     84 	.byte	0b11101010
     85 	.byte	0b11001010
     86 	.byte	0b11110110
     87 	.byte	0b11010110
     88 	.byte	0b11110010
     89 	.byte	0b11010010
     90 	.byte	0b11100110
     91 	.byte	0b11000110
     92 	.byte	0b11100010
     93 	.byte	0b11000010
     94 
     95 	.size	trap_table,32
     96 
     97 	.section	.text
     98 	.align	4
     99 
    100 	.globl	__fsr
    101 	.type	__fsr,@function
    102 __fsr:
    103 	pushl	%ebp
    104 	movl	%esp,%ebp
    105 	pushl	%edx
    106 	pushl	%ecx
    107 	subl	$4,%esp
    108 
    109 	lea	__fsr_init_value_ptr, %ecx
    110 	movl	(%ecx),%ecx		/* get the value set by CG */
    111 	shrl	$1,%ecx			/* get rid of fns bit */
    112 	cmpl	$0,%ecx			/* if remaining bits are zero */
    113 	je	3f			/*   there's nothing to do */
    114 
    115 	fstcw	0(%esp)			/* store the control word */
    116 
    117 	movl	%ecx,%edx
    118 	andl	$0x1f,%edx		/* get the trap enable bits */
    119 	movb	trap_table(%edx),%al
    120 	andb	%al,0(%esp)	/* unmask the corresponding exceptions */
    121 
    122 	testl	$0x200,%ecx		/* test denormal trap enable */
    123 	jz	1f			/* skip if zero */
    124 
    125 	andb	$0xfd,0(%esp)	/* unmask denormal exception */
    126 
    127 1:
    128 	movl	%ecx,%edx
    129 	andl	$0x60,%edx		/* get the rounding direction */
    130 	jz	1f			/* skip if zero */
    131 
    132 	movl	%edx,%eax		/* exchange negative<->tozero */
    133 	andl	$0x20,%eax		/*   leaving nearest and positive */
    134 	shll	$1,%eax			/*   as is */
    135 	xorl	%eax,%edx
    136 	shll	$5,%edx
    137 	andw	$0xf3ff,0(%esp)		/* update rounding direction */
    138 	orw	%dx,0(%esp)
    139 
    140 1:
    141 	andl	$0x180,%ecx		/* get the rounding precision */
    142 	jz	1f			/* skip if zero */
    143 
    144 	xorl	$0x180,%ecx		/* reverse bits */
    145 	shll	$1,%ecx
    146 	andw	$0xfcff,0(%esp)		/* update rounding precision */
    147 	orw	%cx,0(%esp)
    148 
    149 1:
    150 	fldcw	0(%esp)			/* load the modified control word */
    151 
    152 3:
    153 	addl	$4,%esp
    154 	popl	%ecx
    155 	popl	%edx
    156 	popl	%ebp
    157 	ret
    158 
    159 	.size	__fsr,[.-__fsr]
    160