1*660662f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Linux/PA-RISC Project (http://www.parisc-linux.org/)
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Floating-point emulation code
61da177e4SLinus Torvalds * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
71da177e4SLinus Torvalds */
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds * BEGIN_DESC
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds * File:
121da177e4SLinus Torvalds * @(#) pa/fp/denormal.c $ Revision: $
131da177e4SLinus Torvalds *
141da177e4SLinus Torvalds * Purpose:
151da177e4SLinus Torvalds * <<please update with a synopsis of the functionality provided by this file>>
161da177e4SLinus Torvalds *
171da177e4SLinus Torvalds * External Interfaces:
181da177e4SLinus Torvalds * <<the following list was autogenerated, please review>>
191da177e4SLinus Torvalds * dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
201da177e4SLinus Torvalds * sgl_denormalize(sgl_opnd,inexactflag,rmode)
211da177e4SLinus Torvalds *
221da177e4SLinus Torvalds * Internal Interfaces:
231da177e4SLinus Torvalds * <<please update>>
241da177e4SLinus Torvalds *
251da177e4SLinus Torvalds * Theory:
261da177e4SLinus Torvalds * <<please update with a overview of the operation of this file>>
271da177e4SLinus Torvalds *
281da177e4SLinus Torvalds * END_DESC
291da177e4SLinus Torvalds */
301da177e4SLinus Torvalds
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds #include "float.h"
341da177e4SLinus Torvalds #include "sgl_float.h"
351da177e4SLinus Torvalds #include "dbl_float.h"
361da177e4SLinus Torvalds #include "hppa.h"
371da177e4SLinus Torvalds #include <linux/kernel.h>
381da177e4SLinus Torvalds /* #include <machine/sys/mdep_private.h> */
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds #undef Fpustatus_register
411da177e4SLinus Torvalds #define Fpustatus_register Fpu_register[0]
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds void
sgl_denormalize(unsigned int * sgl_opnd,boolean * inexactflag,int rmode)441da177e4SLinus Torvalds sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds unsigned int opnd;
471da177e4SLinus Torvalds int sign, exponent;
481da177e4SLinus Torvalds boolean guardbit = FALSE, stickybit, inexact;
491da177e4SLinus Torvalds
501da177e4SLinus Torvalds opnd = *sgl_opnd;
511da177e4SLinus Torvalds stickybit = *inexactflag;
521da177e4SLinus Torvalds exponent = Sgl_exponent(opnd) - SGL_WRAP;
531da177e4SLinus Torvalds sign = Sgl_sign(opnd);
541da177e4SLinus Torvalds Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
551da177e4SLinus Torvalds if (inexact) {
561da177e4SLinus Torvalds switch (rmode) {
571da177e4SLinus Torvalds case ROUNDPLUS:
581da177e4SLinus Torvalds if (sign == 0) {
591da177e4SLinus Torvalds Sgl_increment(opnd);
601da177e4SLinus Torvalds }
611da177e4SLinus Torvalds break;
621da177e4SLinus Torvalds case ROUNDMINUS:
631da177e4SLinus Torvalds if (sign != 0) {
641da177e4SLinus Torvalds Sgl_increment(opnd);
651da177e4SLinus Torvalds }
661da177e4SLinus Torvalds break;
671da177e4SLinus Torvalds case ROUNDNEAREST:
681da177e4SLinus Torvalds if (guardbit && (stickybit ||
691da177e4SLinus Torvalds Sgl_isone_lowmantissa(opnd))) {
701da177e4SLinus Torvalds Sgl_increment(opnd);
711da177e4SLinus Torvalds }
721da177e4SLinus Torvalds break;
731da177e4SLinus Torvalds }
741da177e4SLinus Torvalds }
751da177e4SLinus Torvalds Sgl_set_sign(opnd,sign);
761da177e4SLinus Torvalds *sgl_opnd = opnd;
771da177e4SLinus Torvalds *inexactflag = inexact;
781da177e4SLinus Torvalds return;
791da177e4SLinus Torvalds }
801da177e4SLinus Torvalds
811da177e4SLinus Torvalds void
dbl_denormalize(unsigned int * dbl_opndp1,unsigned int * dbl_opndp2,boolean * inexactflag,int rmode)821da177e4SLinus Torvalds dbl_denormalize(unsigned int *dbl_opndp1,
831da177e4SLinus Torvalds unsigned int * dbl_opndp2,
841da177e4SLinus Torvalds boolean *inexactflag,
851da177e4SLinus Torvalds int rmode)
861da177e4SLinus Torvalds {
871da177e4SLinus Torvalds unsigned int opndp1, opndp2;
881da177e4SLinus Torvalds int sign, exponent;
891da177e4SLinus Torvalds boolean guardbit = FALSE, stickybit, inexact;
901da177e4SLinus Torvalds
911da177e4SLinus Torvalds opndp1 = *dbl_opndp1;
921da177e4SLinus Torvalds opndp2 = *dbl_opndp2;
931da177e4SLinus Torvalds stickybit = *inexactflag;
941da177e4SLinus Torvalds exponent = Dbl_exponent(opndp1) - DBL_WRAP;
951da177e4SLinus Torvalds sign = Dbl_sign(opndp1);
961da177e4SLinus Torvalds Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
971da177e4SLinus Torvalds if (inexact) {
981da177e4SLinus Torvalds switch (rmode) {
991da177e4SLinus Torvalds case ROUNDPLUS:
1001da177e4SLinus Torvalds if (sign == 0) {
1011da177e4SLinus Torvalds Dbl_increment(opndp1,opndp2);
1021da177e4SLinus Torvalds }
1031da177e4SLinus Torvalds break;
1041da177e4SLinus Torvalds case ROUNDMINUS:
1051da177e4SLinus Torvalds if (sign != 0) {
1061da177e4SLinus Torvalds Dbl_increment(opndp1,opndp2);
1071da177e4SLinus Torvalds }
1081da177e4SLinus Torvalds break;
1091da177e4SLinus Torvalds case ROUNDNEAREST:
1101da177e4SLinus Torvalds if (guardbit && (stickybit ||
1111da177e4SLinus Torvalds Dbl_isone_lowmantissap2(opndp2))) {
1121da177e4SLinus Torvalds Dbl_increment(opndp1,opndp2);
1131da177e4SLinus Torvalds }
1141da177e4SLinus Torvalds break;
1151da177e4SLinus Torvalds }
1161da177e4SLinus Torvalds }
1171da177e4SLinus Torvalds Dbl_set_sign(opndp1,sign);
1181da177e4SLinus Torvalds *dbl_opndp1 = opndp1;
1191da177e4SLinus Torvalds *dbl_opndp2 = opndp2;
1201da177e4SLinus Torvalds *inexactflag = inexact;
1211da177e4SLinus Torvalds return;
1221da177e4SLinus Torvalds }
123