xref: /linux/arch/mips/math-emu/sp_add.c (revision c4ee0af3fa0dc65f690fc908f02b8355f9576ea0)
1 /* IEEE754 floating point arithmetic
2  * single precision
3  */
4 /*
5  * MIPS floating point support
6  * Copyright (C) 1994-2000 Algorithmics Ltd.
7  *
8  * ########################################################################
9  *
10  *  This program is free software; you can distribute it and/or modify it
11  *  under the terms of the GNU General Public License (Version 2) as
12  *  published by the Free Software Foundation.
13  *
14  *  This program is distributed in the hope it will be useful, but WITHOUT
15  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17  *  for more details.
18  *
19  *  You should have received a copy of the GNU General Public License along
20  *  with this program; if not, write to the Free Software Foundation, Inc.,
21  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * ########################################################################
24  */
25 
26 
27 #include "ieee754sp.h"
28 
29 ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
30 {
31 	COMPXSP;
32 	COMPYSP;
33 
34 	EXPLODEXSP;
35 	EXPLODEYSP;
36 
37 	CLEARCX;
38 
39 	FLUSHXSP;
40 	FLUSHYSP;
41 
42 	switch (CLPAIR(xc, yc)) {
43 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
44 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
45 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
46 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
47 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
48 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
49 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
50 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
51 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
52 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
53 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
54 		SETCX(IEEE754_INVALID_OPERATION);
55 		return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y);
56 
57 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
58 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
59 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
60 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
61 		return y;
62 
63 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
64 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
65 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
66 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
67 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
68 		return x;
69 
70 
71 		/* Infinity handling
72 		 */
73 
74 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
75 		if (xs == ys)
76 			return x;
77 		SETCX(IEEE754_INVALID_OPERATION);
78 		return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
79 
80 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
81 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
82 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
83 		return y;
84 
85 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
86 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
87 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
88 		return x;
89 
90 		/* Zero handling
91 		 */
92 
93 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
94 		if (xs == ys)
95 			return x;
96 		else
97 			return ieee754sp_zero(ieee754_csr.rm ==
98 					      IEEE754_RD);
99 
100 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
101 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
102 		return x;
103 
104 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
105 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
106 		return y;
107 
108 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
109 		SPDNORMX;
110 
111 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
112 		SPDNORMY;
113 		break;
114 
115 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
116 		SPDNORMX;
117 		break;
118 
119 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
120 		break;
121 	}
122 	assert(xm & SP_HIDDEN_BIT);
123 	assert(ym & SP_HIDDEN_BIT);
124 
125 	/* provide guard,round and stick bit space */
126 	xm <<= 3;
127 	ym <<= 3;
128 
129 	if (xe > ye) {
130 		/* have to shift y fraction right to align
131 		 */
132 		int s = xe - ye;
133 		SPXSRSYn(s);
134 	} else if (ye > xe) {
135 		/* have to shift x fraction right to align
136 		 */
137 		int s = ye - xe;
138 		SPXSRSXn(s);
139 	}
140 	assert(xe == ye);
141 	assert(xe <= SP_EMAX);
142 
143 	if (xs == ys) {
144 		/* generate 28 bit result of adding two 27 bit numbers
145 		 * leaving result in xm,xs,xe
146 		 */
147 		xm = xm + ym;
148 		xe = xe;
149 		xs = xs;
150 
151 		if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
152 			SPXSRSX1();
153 		}
154 	} else {
155 		if (xm >= ym) {
156 			xm = xm - ym;
157 			xe = xe;
158 			xs = xs;
159 		} else {
160 			xm = ym - xm;
161 			xe = xe;
162 			xs = ys;
163 		}
164 		if (xm == 0)
165 			return ieee754sp_zero(ieee754_csr.rm ==
166 					      IEEE754_RD);
167 
168 		/* normalize in extended single precision */
169 		while ((xm >> (SP_MBITS + 3)) == 0) {
170 			xm <<= 1;
171 			xe--;
172 		}
173 
174 	}
175 	SPNORMRET2(xs, xe, xm, "add", x, y);
176 }
177