]>
git.saurik.com Git - apple/boot.git/blob - i386/nasm/float.c
7c482e8570c8d5584f0758f1cb89f84a5e5eec71
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* float.c floating-point constant support for the Netwide Assembler
27 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
28 * Julian Hall. All rights reserved. The software is
29 * redistributable under the licence given in the file "Licence"
30 * distributed in the NASM archive.
32 * initial version 13/ix/96 by Simon Tatham
44 #define MANT_WORDS 6 /* 64 bits + 32 for accuracy == 96 */
45 #define MANT_DIGITS 28 /* 29 digits don't fit in 96 bits */
48 * guaranteed top bit of from is set
49 * => we only have to worry about _one_ bit shift to the left
52 static int multiply(unsigned short *to
, unsigned short *from
) {
53 unsigned long temp
[MANT_WORDS
*2];
56 for (i
=0; i
<MANT_WORDS
*2; i
++)
59 for (i
=0; i
<MANT_WORDS
; i
++)
60 for (j
=0; j
<MANT_WORDS
; j
++) {
62 n
= (unsigned long)to
[i
] * (unsigned long)from
[j
];
64 temp
[i
+j
+1] += n
& 0xFFFF;
67 for (i
=MANT_WORDS
*2; --i
;) {
68 temp
[i
-1] += temp
[i
] >> 16;
71 if (temp
[0] & 0x8000) {
72 for (i
=0; i
<MANT_WORDS
; i
++)
73 to
[i
] = temp
[i
] & 0xFFFF;
76 for (i
=0; i
<MANT_WORDS
; i
++)
77 to
[i
] = (temp
[i
] << 1) + !!(temp
[i
+1] & 0x8000);
82 static void flconvert(char *string
, unsigned short *mant
, long *exponent
,
84 char digits
[MANT_DIGITS
], *p
, *q
, *r
;
85 unsigned short mult
[MANT_WORDS
], *m
, bit
;
87 int extratwos
, started
, seendot
;
91 started
= seendot
= FALSE
;
92 while (*string
&& *string
!= 'E' && *string
!= 'e') {
98 "too many periods in floating-point constant");
101 } else if (*string
>= '0' && *string
<= '9') {
102 if (*string
== '0' && !started
) {
107 if (p
< digits
+sizeof(digits
))
108 *p
++ = *string
- '0';
114 "floating-point constant: `%c' is invalid character",
121 string
++; /* eat the E */
122 tenpwr
+= atoi(string
);
126 * At this point, the memory interval [digits,p) contains a
127 * series of decimal digits zzzzzzz such that our number X
130 * X = 0.zzzzzzz * 10^tenpwr
134 for (m
=mant
; m
<mant
+MANT_WORDS
; m
++)
140 while (m
< mant
+MANT_WORDS
) {
141 unsigned short carry
= 0;
142 while (p
> q
&& !p
[-1])
146 for (r
= p
; r
-- > q
;) {
157 *m
|= bit
, started
= TRUE
;
169 * At this point the `mant' array contains the first six
170 * fractional places of a base-2^16 real number, which when
171 * multiplied by 2^twopwr and 5^tenpwr gives X. So now we
172 * really do multiply by 5^tenpwr.
176 for (m
=mult
; m
<mult
+MANT_WORDS
; m
++)
180 } else if (tenpwr
> 0) {
182 for (m
=mult
+1; m
<mult
+MANT_WORDS
; m
++)
189 twopwr
+= extratwos
+ multiply (mant
, mult
);
190 extratwos
= extratwos
* 2 + multiply (mult
, mult
);
195 * Conversion is done. The elements of `mant' contain the first
196 * fractional places of a base-2^16 real number in [0.5,1)
197 * which we can multiply by 2^twopwr to get X. Or, of course,
204 * Shift a mantissa to the right by i (i < 16) bits.
206 static void shr(unsigned short *mant
, int i
) {
207 unsigned short n
= 0, m
;
210 for (j
=0; j
<MANT_WORDS
; j
++) {
211 m
= (mant
[j
] << (16-i
)) & 0xFFFF;
212 mant
[j
] = (mant
[j
] >> i
) | n
;
218 * Round a mantissa off after i words.
220 static int round(unsigned short *mant
, int i
) {
221 if (mant
[i
] & 0x8000) {
225 } while (i
> 0 && !mant
[i
]);
226 return !i
&& !mant
[i
];
231 #define put(a,b) ( (*(a)=(b)), ((a)[1]=(b)>>8) )
233 static int to_double(char *str
, long sign
, unsigned char *result
,
235 unsigned short mant
[MANT_WORDS
];
238 sign
= (sign
< 0 ? 0x8000L
: 0L);
240 flconvert (str
, mant
, &exponent
, error
);
241 if (mant
[0] & 0x8000) {
246 if (exponent
>= -1022 && exponent
<= 1024) {
253 if (mant
[0] & 0x20) /* did we scale up by one? */
254 shr(mant
, 1), exponent
++;
255 mant
[0] &= 0xF; /* remove leading one */
256 put(result
+6,(exponent
<< 4) | mant
[0] | sign
);
257 put(result
+4,mant
[1]);
258 put(result
+2,mant
[2]);
259 put(result
+0,mant
[3]);
260 } else if (exponent
< -1022 && exponent
>= -1074) {
264 int shift
= -(exponent
+1011);
265 int sh
= shift
% 16, wds
= shift
/ 16;
267 if (round(mant
, 4-wds
) || (sh
>0 && (mant
[0]&(0x8000>>(sh
-1))))) {
273 put(result
+6,(wds
== 0 ? mant
[0] : 0) | sign
);
274 put(result
+4,(wds
<= 1 ? mant
[1-wds
] : 0));
275 put(result
+2,(wds
<= 2 ? mant
[2-wds
] : 0));
276 put(result
+0,(wds
<= 3 ? mant
[3-wds
] : 0));
279 error(ERR_NONFATAL
, "overflow in floating-point constant");
282 memset (result
, 0, 8);
288 memset (result
, 0, 8);
290 return 1; /* success */
293 static int to_float(char *str
, long sign
, unsigned char *result
,
295 unsigned short mant
[MANT_WORDS
];
298 sign
= (sign
< 0 ? 0x8000L
: 0L);
300 flconvert (str
, mant
, &exponent
, error
);
301 if (mant
[0] & 0x8000) {
306 if (exponent
>= -126 && exponent
<= 128) {
313 if (mant
[0] & 0x100) /* did we scale up by one? */
314 shr(mant
, 1), exponent
++;
315 mant
[0] &= 0x7F; /* remove leading one */
316 put(result
+2,(exponent
<< 7) | mant
[0] | sign
);
317 put(result
+0,mant
[1]);
318 } else if (exponent
< -126 && exponent
>= -149) {
322 int shift
= -(exponent
+118);
323 int sh
= shift
% 16, wds
= shift
/ 16;
325 if (round(mant
, 2-wds
) || (sh
>0 && (mant
[0]&(0x8000>>(sh
-1))))) {
331 put(result
+2,(wds
== 0 ? mant
[0] : 0) | sign
);
332 put(result
+0,(wds
<= 1 ? mant
[1-wds
] : 0));
335 error(ERR_NONFATAL
, "overflow in floating-point constant");
338 memset (result
, 0, 4);
341 memset (result
, 0, 4);
346 static int to_ldoub(char *str
, long sign
, unsigned char *result
,
348 unsigned short mant
[MANT_WORDS
];
351 sign
= (sign
< 0 ? 0x8000L
: 0L);
353 flconvert (str
, mant
, &exponent
, error
);
354 if (mant
[0] & 0x8000) {
359 if (exponent
>= -16383 && exponent
<= 16384) {
364 if (round(mant
, 4)) /* did we scale up by one? */
365 shr(mant
, 1), mant
[0] |= 0x8000, exponent
++;
366 put(result
+8,exponent
| sign
);
367 put(result
+6,mant
[0]);
368 put(result
+4,mant
[1]);
369 put(result
+2,mant
[2]);
370 put(result
+0,mant
[3]);
371 } else if (exponent
< -16383 && exponent
>= -16446) {
375 int shift
= -(exponent
+16383);
376 int sh
= shift
% 16, wds
= shift
/ 16;
378 if (round(mant
, 4-wds
) || (sh
>0 && (mant
[0]&(0x8000>>(sh
-1))))) {
385 put(result
+6,(wds
== 0 ? mant
[0] : 0));
386 put(result
+4,(wds
<= 1 ? mant
[1-wds
] : 0));
387 put(result
+2,(wds
<= 2 ? mant
[2-wds
] : 0));
388 put(result
+0,(wds
<= 3 ? mant
[3-wds
] : 0));
391 error(ERR_NONFATAL
, "overflow in floating-point constant");
394 memset (result
, 0, 10);
400 memset (result
, 0, 10);
405 int float_const (char *number
, long sign
, unsigned char *result
, int bytes
,
408 return to_float (number
, sign
, result
, error
);
410 return to_double (number
, sign
, result
, error
);
411 else if (bytes
== 10)
412 return to_ldoub (number
, sign
, result
, error
);
414 error(ERR_PANIC
, "strange value %d passed to float_const", bytes
);