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 #include <sys/asm_linkage.h>
  28 
  29         .file   "fsr.s"
  30 
  31         .section        .data
  32         .align 4
  33 
  34 /*
  35  * The following table maps trap enable bits in __fsr_init_value
  36  * (after shifting right one bit):
  37  *
  38  * bit 0 - inexact trap
  39  * bit 1 - division trap
  40  * bit 2 - underflow trap
  41  * bit 3 - overflow trap
  42  * bit 4 - invalid trap
  43  *
  44  * to exception masks in the floating point control word
  45  *
  46  * bit 0 - invalid mask
  47  * bit 2 - zero divide mask
  48  * bit 3 - overflow mask
  49  * bit 4 - underflow mask
  50  * bit 5 - inexact mask
  51  */
  52         .local  trap_table
  53         .type   trap_table,@object
  54 trap_table:
  55         .byte   0b11111111
  56         .byte   0b11011111
  57         .byte   0b11111011
  58         .byte   0b11011011
  59         .byte   0b11101111
  60         .byte   0b11001111
  61         .byte   0b11101011
  62         .byte   0b11001011
  63         .byte   0b11110111
  64         .byte   0b11010111
  65         .byte   0b11110011
  66         .byte   0b11010011
  67         .byte   0b11100111
  68         .byte   0b11000111
  69         .byte   0b11100011
  70         .byte   0b11000011
  71         .byte   0b11111110
  72         .byte   0b11011110
  73         .byte   0b11111010
  74         .byte   0b11011010
  75         .byte   0b11101110
  76         .byte   0b11001110
  77         .byte   0b11101010
  78         .byte   0b11001010
  79         .byte   0b11110110
  80         .byte   0b11010110
  81         .byte   0b11110010
  82         .byte   0b11010010
  83         .byte   0b11100110
  84         .byte   0b11000110
  85         .byte   0b11100010
  86         .byte   0b11000010
  87 
  88         .size   trap_table,32
  89 
  90 ENTRY_NP(__fsr)
  91         pushl   %ebp
  92         movl    %esp,%ebp
  93         pushl   %edx
  94         pushl   %ecx
  95         pushl   %ebx
  96         subl    $4,%esp
  97 
  98         /* Setup PIC */
  99         call    9f
 100 9:      popl    %ebx
 101         addl    $_GLOBAL_OFFSET_TABLE_ + [. - 9b], %ebx
 102 
 103         movl    8(%ebp), %ecx           /* the value set by CG is passed in */
 104         shrl    $1,%ecx                 /* get rid of fns bit */
 105         cmpl    $0,%ecx                 /* if remaining bits are zero */
 106         je      3f                      /*   there's nothing to do */
 107 
 108         fstcw   0(%esp)                 /* store the control word */
 109 
 110         movl    %ecx,%edx
 111         andl    $0x1f,%edx              /* get the trap enable bits */
 112         movl    trap_table@GOT(%ebx), %eax
 113         addl    %eax,%edx
 114         movb    (%edx),%al
 115         andb    %al,0(%esp)     /* unmask the corresponding exceptions */
 116 
 117         testl   $0x200,%ecx             /* test denormal trap enable */
 118         jz      1f                      /* skip if zero */
 119 
 120         andb    $0xfd,0(%esp)   /* unmask denormal exception */
 121 
 122 1:
 123         movl    %ecx,%edx
 124         andl    $0x60,%edx              /* get the rounding direction */
 125         jz      1f                      /* skip if zero */
 126 
 127         movl    %edx,%eax               /* exchange negative<->tozero */
 128         andl    $0x20,%eax              /*   leaving nearest and positive */
 129         shll    $1,%eax                 /*   as is */
 130         xorl    %eax,%edx
 131         shll    $5,%edx
 132         andw    $0xf3ff,0(%esp)         /* update rounding direction */
 133         orw     %dx,0(%esp)
 134 
 135 1:
 136         andl    $0x180,%ecx             /* get the rounding precision */
 137         jz      1f                      /* skip if zero */
 138 
 139         xorl    $0x180,%ecx             /* reverse bits */
 140         shll    $1,%ecx
 141         andw    $0xfcff,0(%esp)         /* update rounding precision */
 142         orw     %cx,0(%esp)
 143 
 144 1:
 145         fldcw   0(%esp)                 /* load the modified control word */
 146 
 147 3:
 148         addl    $4,%esp
 149         popl    %ebx
 150         popl    %ecx
 151         popl    %edx
 152         popl    %ebp
 153         ret
 154 SET_SIZE(__fsr)