Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/parisc/math-emu/fcnvxf.c
10817 views
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
58
sgl_to_sgl_fcnvxf(
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
129
sgl_to_dbl_fcnvxf(
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
180
dbl_to_sgl_fcnvxf(
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
285
dbl_to_dbl_fcnvxf(
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
}
387
388