Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fcnvxf.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/fcnvxf.c $Revision: 1.1 $
26  *
27  * Purpose:
28  * Single Fixed-point to Single Floating-point
29  * Single Fixed-point to Double Floating-point
30  * Double Fixed-point to Single Floating-point
31  * Double Fixed-point to Double Floating-point
32  *
33  * External Interfaces:
34  * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
35  * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
36  * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
37  * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
38  *
39  * Internal Interfaces:
40  *
41  * Theory:
42  * <<please update with a overview of the operation of this file>>
43  *
44  * END_DESC
45 */
46 
47 
48 #include "float.h"
49 #include "sgl_float.h"
50 #include "dbl_float.h"
51 #include "cnv_float.h"
52 
53 /*
54  * Convert single fixed-point to single floating-point format
55  */
56 
57 int
59  int *srcptr,
60  unsigned int *nullptr,
61  sgl_floating_point *dstptr,
62  unsigned int *status)
63 {
64  register int src, dst_exponent;
65  register unsigned int result = 0;
66 
67  src = *srcptr;
68  /*
69  * set sign bit of result and get magnitude of source
70  */
71  if (src < 0) {
72  Sgl_setone_sign(result);
73  Int_negate(src);
74  }
75  else {
76  Sgl_setzero_sign(result);
77  /* Check for zero */
78  if (src == 0) {
79  Sgl_setzero(result);
80  *dstptr = result;
81  return(NOEXCEPTION);
82  }
83  }
84  /*
85  * Generate exponent and normalized mantissa
86  */
87  dst_exponent = 16; /* initialize for normalization */
88  /*
89  * Check word for most significant bit set. Returns
90  * a value in dst_exponent indicating the bit position,
91  * between -1 and 30.
92  */
93  Find_ms_one_bit(src,dst_exponent);
94  /* left justify source, with msb at bit position 1 */
95  if (dst_exponent >= 0) src <<= dst_exponent;
96  else src = 1 << 30;
97  Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
98  Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
99 
100  /* check for inexact */
101  if (Int_isinexact_to_sgl(src)) {
102  switch (Rounding_mode()) {
103  case ROUNDPLUS:
104  if (Sgl_iszero_sign(result))
105  Sgl_increment(result);
106  break;
107  case ROUNDMINUS:
108  if (Sgl_isone_sign(result))
109  Sgl_increment(result);
110  break;
111  case ROUNDNEAREST:
112  Sgl_roundnearest_from_int(src,result);
113  }
114  if (Is_inexacttrap_enabled()) {
115  *dstptr = result;
116  return(INEXACTEXCEPTION);
117  }
118  else Set_inexactflag();
119  }
120  *dstptr = result;
121  return(NOEXCEPTION);
122 }
123 
124 /*
125  * Single Fixed-point to Double Floating-point
126  */
127 
128 int
130  int *srcptr,
131  unsigned int *nullptr,
132  dbl_floating_point *dstptr,
133  unsigned int *status)
134 {
135  register int src, dst_exponent;
136  register unsigned int resultp1 = 0, resultp2 = 0;
137 
138  src = *srcptr;
139  /*
140  * set sign bit of result and get magnitude of source
141  */
142  if (src < 0) {
143  Dbl_setone_sign(resultp1);
144  Int_negate(src);
145  }
146  else {
147  Dbl_setzero_sign(resultp1);
148  /* Check for zero */
149  if (src == 0) {
150  Dbl_setzero(resultp1,resultp2);
151  Dbl_copytoptr(resultp1,resultp2,dstptr);
152  return(NOEXCEPTION);
153  }
154  }
155  /*
156  * Generate exponent and normalized mantissa
157  */
158  dst_exponent = 16; /* initialize for normalization */
159  /*
160  * Check word for most significant bit set. Returns
161  * a value in dst_exponent indicating the bit position,
162  * between -1 and 30.
163  */
164  Find_ms_one_bit(src,dst_exponent);
165  /* left justify source, with msb at bit position 1 */
166  if (dst_exponent >= 0) src <<= dst_exponent;
167  else src = 1 << 30;
168  Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
169  Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
170  Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
171  Dbl_copytoptr(resultp1,resultp2,dstptr);
172  return(NOEXCEPTION);
173 }
174 
175 /*
176  * Double Fixed-point to Single Floating-point
177  */
178 
179 int
181  dbl_integer *srcptr,
182  unsigned int *nullptr,
183  sgl_floating_point *dstptr,
184  unsigned int *status)
185 {
186  int dst_exponent, srcp1;
187  unsigned int result = 0, srcp2;
188 
189  Dint_copyfromptr(srcptr,srcp1,srcp2);
190  /*
191  * set sign bit of result and get magnitude of source
192  */
193  if (srcp1 < 0) {
194  Sgl_setone_sign(result);
195  Dint_negate(srcp1,srcp2);
196  }
197  else {
198  Sgl_setzero_sign(result);
199  /* Check for zero */
200  if (srcp1 == 0 && srcp2 == 0) {
201  Sgl_setzero(result);
202  *dstptr = result;
203  return(NOEXCEPTION);
204  }
205  }
206  /*
207  * Generate exponent and normalized mantissa
208  */
209  dst_exponent = 16; /* initialize for normalization */
210  if (srcp1 == 0) {
211  /*
212  * Check word for most significant bit set. Returns
213  * a value in dst_exponent indicating the bit position,
214  * between -1 and 30.
215  */
216  Find_ms_one_bit(srcp2,dst_exponent);
217  /* left justify source, with msb at bit position 1 */
218  if (dst_exponent >= 0) {
219  srcp1 = srcp2 << dst_exponent;
220  srcp2 = 0;
221  }
222  else {
223  srcp1 = srcp2 >> 1;
224  srcp2 <<= 31;
225  }
226  /*
227  * since msb set is in second word, need to
228  * adjust bit position count
229  */
230  dst_exponent += 32;
231  }
232  else {
233  /*
234  * Check word for most significant bit set. Returns
235  * a value in dst_exponent indicating the bit position,
236  * between -1 and 30.
237  *
238  */
239  Find_ms_one_bit(srcp1,dst_exponent);
240  /* left justify source, with msb at bit position 1 */
241  if (dst_exponent > 0) {
242  Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
243  srcp1);
244  srcp2 <<= dst_exponent;
245  }
246  /*
247  * If dst_exponent = 0, we don't need to shift anything.
248  * If dst_exponent = -1, src = - 2**63 so we won't need to
249  * shift srcp2.
250  */
251  else srcp1 >>= -(dst_exponent);
252  }
253  Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
254  Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
255 
256  /* check for inexact */
257  if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
258  switch (Rounding_mode()) {
259  case ROUNDPLUS:
260  if (Sgl_iszero_sign(result))
261  Sgl_increment(result);
262  break;
263  case ROUNDMINUS:
264  if (Sgl_isone_sign(result))
265  Sgl_increment(result);
266  break;
267  case ROUNDNEAREST:
268  Sgl_roundnearest_from_dint(srcp1,srcp2,result);
269  }
270  if (Is_inexacttrap_enabled()) {
271  *dstptr = result;
272  return(INEXACTEXCEPTION);
273  }
274  else Set_inexactflag();
275  }
276  *dstptr = result;
277  return(NOEXCEPTION);
278 }
279 
280 /*
281  * Double Fixed-point to Double Floating-point
282  */
283 
284 int
286  dbl_integer *srcptr,
287  unsigned int *nullptr,
288  dbl_floating_point *dstptr,
289  unsigned int *status)
290 {
291  register int srcp1, dst_exponent;
292  register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
293 
294  Dint_copyfromptr(srcptr,srcp1,srcp2);
295  /*
296  * set sign bit of result and get magnitude of source
297  */
298  if (srcp1 < 0) {
299  Dbl_setone_sign(resultp1);
300  Dint_negate(srcp1,srcp2);
301  }
302  else {
303  Dbl_setzero_sign(resultp1);
304  /* Check for zero */
305  if (srcp1 == 0 && srcp2 ==0) {
306  Dbl_setzero(resultp1,resultp2);
307  Dbl_copytoptr(resultp1,resultp2,dstptr);
308  return(NOEXCEPTION);
309  }
310  }
311  /*
312  * Generate exponent and normalized mantissa
313  */
314  dst_exponent = 16; /* initialize for normalization */
315  if (srcp1 == 0) {
316  /*
317  * Check word for most significant bit set. Returns
318  * a value in dst_exponent indicating the bit position,
319  * between -1 and 30.
320  */
321  Find_ms_one_bit(srcp2,dst_exponent);
322  /* left justify source, with msb at bit position 1 */
323  if (dst_exponent >= 0) {
324  srcp1 = srcp2 << dst_exponent;
325  srcp2 = 0;
326  }
327  else {
328  srcp1 = srcp2 >> 1;
329  srcp2 <<= 31;
330  }
331  /*
332  * since msb set is in second word, need to
333  * adjust bit position count
334  */
335  dst_exponent += 32;
336  }
337  else {
338  /*
339  * Check word for most significant bit set. Returns
340  * a value in dst_exponent indicating the bit position,
341  * between -1 and 30.
342  */
343  Find_ms_one_bit(srcp1,dst_exponent);
344  /* left justify source, with msb at bit position 1 */
345  if (dst_exponent > 0) {
346  Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
347  srcp1);
348  srcp2 <<= dst_exponent;
349  }
350  /*
351  * If dst_exponent = 0, we don't need to shift anything.
352  * If dst_exponent = -1, src = - 2**63 so we won't need to
353  * shift srcp2.
354  */
355  else srcp1 >>= -(dst_exponent);
356  }
357  Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
358  Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
359  Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
360 
361  /* check for inexact */
362  if (Dint_isinexact_to_dbl(srcp2)) {
363  switch (Rounding_mode()) {
364  case ROUNDPLUS:
365  if (Dbl_iszero_sign(resultp1)) {
366  Dbl_increment(resultp1,resultp2);
367  }
368  break;
369  case ROUNDMINUS:
370  if (Dbl_isone_sign(resultp1)) {
371  Dbl_increment(resultp1,resultp2);
372  }
373  break;
374  case ROUNDNEAREST:
375  Dbl_roundnearest_from_dint(srcp2,resultp1,
376  resultp2);
377  }
378  if (Is_inexacttrap_enabled()) {
379  Dbl_copytoptr(resultp1,resultp2,dstptr);
380  return(INEXACTEXCEPTION);
381  }
382  else Set_inexactflag();
383  }
384  Dbl_copytoptr(resultp1,resultp2,dstptr);
385  return(NOEXCEPTION);
386 }