1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 4 * 5 * Floating-point emulation code 6 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 7 */ 8 /* 9 * BEGIN_DESC 10 * 11 * File: 12 * @(#) pa/fp/denormal.c $ Revision: $ 13 * 14 * Purpose: 15 * <<please update with a synopsis of the functionality provided by this file>> 16 * 17 * External Interfaces: 18 * <<the following list was autogenerated, please review>> 19 * dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode) 20 * sgl_denormalize(sgl_opnd,inexactflag,rmode) 21 * 22 * Internal Interfaces: 23 * <<please update>> 24 * 25 * Theory: 26 * <<please update with a overview of the operation of this file>> 27 * 28 * END_DESC 29 */ 30 31 32 33 #include "float.h" 34 #include "sgl_float.h" 35 #include "dbl_float.h" 36 #include "hppa.h" 37 #include <linux/kernel.h> 38 /* #include <machine/sys/mdep_private.h> */ 39 40 #undef Fpustatus_register 41 #define Fpustatus_register Fpu_register[0] 42 43 void 44 sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode) 45 { 46 unsigned int opnd; 47 int sign, exponent; 48 boolean guardbit = FALSE, stickybit, inexact; 49 50 opnd = *sgl_opnd; 51 stickybit = *inexactflag; 52 exponent = Sgl_exponent(opnd) - SGL_WRAP; 53 sign = Sgl_sign(opnd); 54 Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact); 55 if (inexact) { 56 switch (rmode) { 57 case ROUNDPLUS: 58 if (sign == 0) { 59 Sgl_increment(opnd); 60 } 61 break; 62 case ROUNDMINUS: 63 if (sign != 0) { 64 Sgl_increment(opnd); 65 } 66 break; 67 case ROUNDNEAREST: 68 if (guardbit && (stickybit || 69 Sgl_isone_lowmantissa(opnd))) { 70 Sgl_increment(opnd); 71 } 72 break; 73 } 74 } 75 Sgl_set_sign(opnd,sign); 76 *sgl_opnd = opnd; 77 *inexactflag = inexact; 78 return; 79 } 80 81 void 82 dbl_denormalize(unsigned int *dbl_opndp1, 83 unsigned int * dbl_opndp2, 84 boolean *inexactflag, 85 int rmode) 86 { 87 unsigned int opndp1, opndp2; 88 int sign, exponent; 89 boolean guardbit = FALSE, stickybit, inexact; 90 91 opndp1 = *dbl_opndp1; 92 opndp2 = *dbl_opndp2; 93 stickybit = *inexactflag; 94 exponent = Dbl_exponent(opndp1) - DBL_WRAP; 95 sign = Dbl_sign(opndp1); 96 Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact); 97 if (inexact) { 98 switch (rmode) { 99 case ROUNDPLUS: 100 if (sign == 0) { 101 Dbl_increment(opndp1,opndp2); 102 } 103 break; 104 case ROUNDMINUS: 105 if (sign != 0) { 106 Dbl_increment(opndp1,opndp2); 107 } 108 break; 109 case ROUNDNEAREST: 110 if (guardbit && (stickybit || 111 Dbl_isone_lowmantissap2(opndp2))) { 112 Dbl_increment(opndp1,opndp2); 113 } 114 break; 115 } 116 } 117 Dbl_set_sign(opndp1,sign); 118 *dbl_opndp1 = opndp1; 119 *dbl_opndp2 = opndp2; 120 *inexactflag = inexact; 121 return; 122 } 123