1 /* 2 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 3 * 4 * Floating-point emulation code 5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 /* 22 * BEGIN_DESC 23 * 24 * File: 25 * @(#) pa/fp/denormal.c $ Revision: $ 26 * 27 * Purpose: 28 * <<please update with a synopsis of the functionality provided by this file>> 29 * 30 * External Interfaces: 31 * <<the following list was autogenerated, please review>> 32 * dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode) 33 * sgl_denormalize(sgl_opnd,inexactflag,rmode) 34 * 35 * Internal Interfaces: 36 * <<please update>> 37 * 38 * Theory: 39 * <<please update with a overview of the operation of this file>> 40 * 41 * END_DESC 42 */ 43 44 45 46 #include "float.h" 47 #include "sgl_float.h" 48 #include "dbl_float.h" 49 #include "hppa.h" 50 #include <linux/kernel.h> 51 /* #include <machine/sys/mdep_private.h> */ 52 53 #undef Fpustatus_register 54 #define Fpustatus_register Fpu_register[0] 55 56 void 57 sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode) 58 { 59 unsigned int opnd; 60 int sign, exponent; 61 boolean guardbit = FALSE, stickybit, inexact; 62 63 opnd = *sgl_opnd; 64 stickybit = *inexactflag; 65 exponent = Sgl_exponent(opnd) - SGL_WRAP; 66 sign = Sgl_sign(opnd); 67 Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact); 68 if (inexact) { 69 switch (rmode) { 70 case ROUNDPLUS: 71 if (sign == 0) { 72 Sgl_increment(opnd); 73 } 74 break; 75 case ROUNDMINUS: 76 if (sign != 0) { 77 Sgl_increment(opnd); 78 } 79 break; 80 case ROUNDNEAREST: 81 if (guardbit && (stickybit || 82 Sgl_isone_lowmantissa(opnd))) { 83 Sgl_increment(opnd); 84 } 85 break; 86 } 87 } 88 Sgl_set_sign(opnd,sign); 89 *sgl_opnd = opnd; 90 *inexactflag = inexact; 91 return; 92 } 93 94 void 95 dbl_denormalize(unsigned int *dbl_opndp1, 96 unsigned int * dbl_opndp2, 97 boolean *inexactflag, 98 int rmode) 99 { 100 unsigned int opndp1, opndp2; 101 int sign, exponent; 102 boolean guardbit = FALSE, stickybit, inexact; 103 104 opndp1 = *dbl_opndp1; 105 opndp2 = *dbl_opndp2; 106 stickybit = *inexactflag; 107 exponent = Dbl_exponent(opndp1) - DBL_WRAP; 108 sign = Dbl_sign(opndp1); 109 Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact); 110 if (inexact) { 111 switch (rmode) { 112 case ROUNDPLUS: 113 if (sign == 0) { 114 Dbl_increment(opndp1,opndp2); 115 } 116 break; 117 case ROUNDMINUS: 118 if (sign != 0) { 119 Dbl_increment(opndp1,opndp2); 120 } 121 break; 122 case ROUNDNEAREST: 123 if (guardbit && (stickybit || 124 Dbl_isone_lowmantissap2(opndp2))) { 125 Dbl_increment(opndp1,opndp2); 126 } 127 break; 128 } 129 } 130 Dbl_set_sign(opndp1,sign); 131 *dbl_opndp1 = opndp1; 132 *dbl_opndp2 = opndp2; 133 *inexactflag = inexact; 134 return; 135 } 136