Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dfmpy.c
Go to the documentation of this file.
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) <[email protected]>
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/spmath/dfmpy.c $Revision: 1.1 $
26  *
27  * Purpose:
28  * Double Precision Floating-point Multiply
29  *
30  * External Interfaces:
31  * dbl_fmpy(srcptr1,srcptr2,dstptr,status)
32  *
33  * Internal Interfaces:
34  *
35  * Theory:
36  * <<please update with a overview of the operation of this file>>
37  *
38  * END_DESC
39 */
40 
41 
42 #include "float.h"
43 #include "dbl_float.h"
44 
45 /*
46  * Double Precision Floating-point Multiply
47  */
48 
49 int
51  dbl_floating_point *srcptr1,
52  dbl_floating_point *srcptr2,
53  dbl_floating_point *dstptr,
54  unsigned int *status)
55 {
56  register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
57  register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
58  register int dest_exponent, count;
59  register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
60  boolean is_tiny;
61 
62  Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
63  Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
64 
65  /*
66  * set sign bit of result
67  */
68  if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
69  Dbl_setnegativezerop1(resultp1);
70  else Dbl_setzerop1(resultp1);
71  /*
72  * check first operand for NaN's or infinity
73  */
74  if (Dbl_isinfinity_exponent(opnd1p1)) {
75  if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
76  if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
77  if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
78  /*
79  * invalid since operands are infinity
80  * and zero
81  */
83  return(INVALIDEXCEPTION);
85  Dbl_makequietnan(resultp1,resultp2);
86  Dbl_copytoptr(resultp1,resultp2,dstptr);
87  return(NOEXCEPTION);
88  }
89  /*
90  * return infinity
91  */
92  Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
93  Dbl_copytoptr(resultp1,resultp2,dstptr);
94  return(NOEXCEPTION);
95  }
96  }
97  else {
98  /*
99  * is NaN; signaling or quiet?
100  */
101  if (Dbl_isone_signaling(opnd1p1)) {
102  /* trap if INVALIDTRAP enabled */
103  if (Is_invalidtrap_enabled())
104  return(INVALIDEXCEPTION);
105  /* make NaN quiet */
106  Set_invalidflag();
107  Dbl_set_quiet(opnd1p1);
108  }
109  /*
110  * is second operand a signaling NaN?
111  */
112  else if (Dbl_is_signalingnan(opnd2p1)) {
113  /* trap if INVALIDTRAP enabled */
115  return(INVALIDEXCEPTION);
116  /* make NaN quiet */
117  Set_invalidflag();
118  Dbl_set_quiet(opnd2p1);
119  Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
120  return(NOEXCEPTION);
121  }
122  /*
123  * return quiet NaN
124  */
125  Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
126  return(NOEXCEPTION);
127  }
128  }
129  /*
130  * check second operand for NaN's or infinity
131  */
132  if (Dbl_isinfinity_exponent(opnd2p1)) {
133  if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
134  if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
135  /* invalid since operands are zero & infinity */
137  return(INVALIDEXCEPTION);
138  Set_invalidflag();
139  Dbl_makequietnan(opnd2p1,opnd2p2);
140  Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
141  return(NOEXCEPTION);
142  }
143  /*
144  * return infinity
145  */
146  Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
147  Dbl_copytoptr(resultp1,resultp2,dstptr);
148  return(NOEXCEPTION);
149  }
150  /*
151  * is NaN; signaling or quiet?
152  */
153  if (Dbl_isone_signaling(opnd2p1)) {
154  /* trap if INVALIDTRAP enabled */
156  /* make NaN quiet */
157  Set_invalidflag();
158  Dbl_set_quiet(opnd2p1);
159  }
160  /*
161  * return quiet NaN
162  */
163  Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
164  return(NOEXCEPTION);
165  }
166  /*
167  * Generate exponent
168  */
169  dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS;
170 
171  /*
172  * Generate mantissa
173  */
174  if (Dbl_isnotzero_exponent(opnd1p1)) {
175  /* set hidden bit */
177  }
178  else {
179  /* check for zero */
180  if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
181  Dbl_setzero_exponentmantissa(resultp1,resultp2);
182  Dbl_copytoptr(resultp1,resultp2,dstptr);
183  return(NOEXCEPTION);
184  }
185  /* is denormalized, adjust exponent */
186  Dbl_clear_signexponent(opnd1p1);
187  Dbl_leftshiftby1(opnd1p1,opnd1p2);
188  Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
189  }
190  /* opnd2 needs to have hidden bit set with msb in hidden bit */
191  if (Dbl_isnotzero_exponent(opnd2p1)) {
193  }
194  else {
195  /* check for zero */
196  if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
197  Dbl_setzero_exponentmantissa(resultp1,resultp2);
198  Dbl_copytoptr(resultp1,resultp2,dstptr);
199  return(NOEXCEPTION);
200  }
201  /* is denormalized; want to normalize */
202  Dbl_clear_signexponent(opnd2p1);
203  Dbl_leftshiftby1(opnd2p1,opnd2p2);
204  Dbl_normalize(opnd2p1,opnd2p2,dest_exponent);
205  }
206 
207  /* Multiply two source mantissas together */
208 
209  /* make room for guard bits */
210  Dbl_leftshiftby7(opnd2p1,opnd2p2);
211  Dbl_setzero(opnd3p1,opnd3p2);
212  /*
213  * Four bits at a time are inspected in each loop, and a
214  * simple shift and add multiply algorithm is used.
215  */
216  for (count=1;count<=DBL_P;count+=4) {
217  stickybit |= Dlow4p2(opnd3p2);
218  Dbl_rightshiftby4(opnd3p1,opnd3p2);
219  if (Dbit28p2(opnd1p2)) {
220  /* Twoword_add should be an ADDC followed by an ADD. */
221  Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29,
222  opnd2p2<<3);
223  }
224  if (Dbit29p2(opnd1p2)) {
225  Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30,
226  opnd2p2<<2);
227  }
228  if (Dbit30p2(opnd1p2)) {
229  Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31,
230  opnd2p2<<1);
231  }
232  if (Dbit31p2(opnd1p2)) {
233  Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2);
234  }
235  Dbl_rightshiftby4(opnd1p1,opnd1p2);
236  }
237  if (Dbit3p1(opnd3p1)==0) {
238  Dbl_leftshiftby1(opnd3p1,opnd3p2);
239  }
240  else {
241  /* result mantissa >= 2. */
242  dest_exponent++;
243  }
244  /* check for denormalized result */
245  while (Dbit3p1(opnd3p1)==0) {
246  Dbl_leftshiftby1(opnd3p1,opnd3p2);
247  dest_exponent--;
248  }
249  /*
250  * check for guard, sticky and inexact bits
251  */
252  stickybit |= Dallp2(opnd3p2) << 25;
253  guardbit = (Dallp2(opnd3p2) << 24) >> 31;
254  inexact = guardbit | stickybit;
255 
256  /* align result mantissa */
257  Dbl_rightshiftby8(opnd3p1,opnd3p2);
258 
259  /*
260  * round result
261  */
262  if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
263  Dbl_clear_signexponent(opnd3p1);
264  switch (Rounding_mode()) {
265  case ROUNDPLUS:
266  if (Dbl_iszero_sign(resultp1))
267  Dbl_increment(opnd3p1,opnd3p2);
268  break;
269  case ROUNDMINUS:
270  if (Dbl_isone_sign(resultp1))
271  Dbl_increment(opnd3p1,opnd3p2);
272  break;
273  case ROUNDNEAREST:
274  if (guardbit) {
275  if (stickybit || Dbl_isone_lowmantissap2(opnd3p2))
276  Dbl_increment(opnd3p1,opnd3p2);
277  }
278  }
279  if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
280  }
281  Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
282 
283  /*
284  * Test for overflow
285  */
286  if (dest_exponent >= DBL_INFINITY_EXPONENT) {
287  /* trap if OVERFLOWTRAP enabled */
288  if (Is_overflowtrap_enabled()) {
289  /*
290  * Adjust bias of result
291  */
292  Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
293  Dbl_copytoptr(resultp1,resultp2,dstptr);
294  if (inexact)
297  else Set_inexactflag();
298  return (OVERFLOWEXCEPTION);
299  }
300  inexact = TRUE;
302  /* set result to infinity or largest number */
303  Dbl_setoverflow(resultp1,resultp2);
304  }
305  /*
306  * Test for underflow
307  */
308  else if (dest_exponent <= 0) {
309  /* trap if UNDERFLOWTRAP enabled */
310  if (Is_underflowtrap_enabled()) {
311  /*
312  * Adjust bias of result
313  */
314  Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
315  Dbl_copytoptr(resultp1,resultp2,dstptr);
316  if (inexact)
319  else Set_inexactflag();
320  return (UNDERFLOWEXCEPTION);
321  }
322 
323  /* Determine if should set underflow flag */
324  is_tiny = TRUE;
325  if (dest_exponent == 0 && inexact) {
326  switch (Rounding_mode()) {
327  case ROUNDPLUS:
328  if (Dbl_iszero_sign(resultp1)) {
329  Dbl_increment(opnd3p1,opnd3p2);
330  if (Dbl_isone_hiddenoverflow(opnd3p1))
331  is_tiny = FALSE;
332  Dbl_decrement(opnd3p1,opnd3p2);
333  }
334  break;
335  case ROUNDMINUS:
336  if (Dbl_isone_sign(resultp1)) {
337  Dbl_increment(opnd3p1,opnd3p2);
338  if (Dbl_isone_hiddenoverflow(opnd3p1))
339  is_tiny = FALSE;
340  Dbl_decrement(opnd3p1,opnd3p2);
341  }
342  break;
343  case ROUNDNEAREST:
344  if (guardbit && (stickybit ||
345  Dbl_isone_lowmantissap2(opnd3p2))) {
346  Dbl_increment(opnd3p1,opnd3p2);
347  if (Dbl_isone_hiddenoverflow(opnd3p1))
348  is_tiny = FALSE;
349  Dbl_decrement(opnd3p1,opnd3p2);
350  }
351  break;
352  }
353  }
354 
355  /*
356  * denormalize result or set to signed zero
357  */
358  stickybit = inexact;
359  Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
360  stickybit,inexact);
361 
362  /* return zero or smallest number */
363  if (inexact) {
364  switch (Rounding_mode()) {
365  case ROUNDPLUS:
366  if (Dbl_iszero_sign(resultp1)) {
367  Dbl_increment(opnd3p1,opnd3p2);
368  }
369  break;
370  case ROUNDMINUS:
371  if (Dbl_isone_sign(resultp1)) {
372  Dbl_increment(opnd3p1,opnd3p2);
373  }
374  break;
375  case ROUNDNEAREST:
376  if (guardbit && (stickybit ||
377  Dbl_isone_lowmantissap2(opnd3p2))) {
378  Dbl_increment(opnd3p1,opnd3p2);
379  }
380  break;
381  }
382  if (is_tiny) Set_underflowflag();
383  }
384  Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
385  }
386  else Dbl_set_exponent(resultp1,dest_exponent);
387  /* check for inexact */
388  Dbl_copytoptr(resultp1,resultp2,dstptr);
389  if (inexact) {
391  else Set_inexactflag();
392  }
393  return(NOEXCEPTION);
394 }