blob: a6ad39360795a71d9810ace65cc012b89a7a38c6 [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* float.c floating-point constant support for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
8 * initial version 13/ix/96 by Simon Tatham
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000014#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000015
16#include "nasm.h"
17
18#define TRUE 1
19#define FALSE 0
20
H. Peter Anvine31747e2007-09-18 17:50:34 -070021#define MANT_WORDS 10 /* 112 bits + 48 for accuracy == 160 */
22#define MANT_DIGITS 49 /* 50 digits don't fit in 160 bits */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000023
24/*
25 * guaranteed top bit of from is set
26 * => we only have to worry about _one_ bit shift to the left
27 */
28
Keith Kaniosb7a89542007-04-12 02:40:54 +000029static int ieee_multiply(uint16_t *to, uint16_t *from)
H. Peter Anvineba20a72002-04-30 20:53:55 +000030{
Keith Kaniosb7a89542007-04-12 02:40:54 +000031 uint32_t temp[MANT_WORDS * 2];
H. Peter Anvine2c80182005-01-15 22:15:51 +000032 int i, j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000033
H. Peter Anvine2c80182005-01-15 22:15:51 +000034 for (i = 0; i < MANT_WORDS * 2; i++)
35 temp[i] = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036
H. Peter Anvine2c80182005-01-15 22:15:51 +000037 for (i = 0; i < MANT_WORDS; i++)
38 for (j = 0; j < MANT_WORDS; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +000039 uint32_t n;
40 n = (uint32_t)to[i] * (uint32_t)from[j];
H. Peter Anvine2c80182005-01-15 22:15:51 +000041 temp[i + j] += n >> 16;
42 temp[i + j + 1] += n & 0xFFFF;
43 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000044
H. Peter Anvine2c80182005-01-15 22:15:51 +000045 for (i = MANT_WORDS * 2; --i;) {
46 temp[i - 1] += temp[i] >> 16;
47 temp[i] &= 0xFFFF;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000048 }
49 if (temp[0] & 0x8000) {
H. Peter Anvine31747e2007-09-18 17:50:34 -070050 memcpy(to, temp, 2*MANT_WORDS);
51 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000052 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +000053 for (i = 0; i < MANT_WORDS; i++)
54 to[i] = (temp[i] << 1) + !!(temp[i + 1] & 0x8000);
55 return -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000056 }
57}
58
Keith Kaniosa6dfa782007-04-13 16:47:53 +000059static void ieee_flconvert(char *string, uint16_t *mant,
Keith Kaniosb7a89542007-04-12 02:40:54 +000060 int32_t *exponent, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +000061{
Keith Kaniosa6dfa782007-04-13 16:47:53 +000062 char digits[MANT_DIGITS];
63 char *p, *q, *r;
Keith Kaniosb7a89542007-04-12 02:40:54 +000064 uint16_t mult[MANT_WORDS], bit;
65 uint16_t *m;
66 int32_t tenpwr, twopwr;
H. Peter Anvine2c80182005-01-15 22:15:51 +000067 int extratwos, started, seendot;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000068
69 p = digits;
70 tenpwr = 0;
71 started = seendot = FALSE;
72 while (*string && *string != 'E' && *string != 'e') {
H. Peter Anvine2c80182005-01-15 22:15:51 +000073 if (*string == '.') {
74 if (!seendot)
75 seendot = TRUE;
76 else {
77 error(ERR_NONFATAL,
78 "too many periods in floating-point constant");
79 return;
80 }
81 } else if (*string >= '0' && *string <= '9') {
82 if (*string == '0' && !started) {
83 if (seendot)
84 tenpwr--;
85 } else {
86 started = TRUE;
87 if (p < digits + sizeof(digits))
88 *p++ = *string - '0';
89 if (!seendot)
90 tenpwr++;
91 }
92 } else {
93 error(ERR_NONFATAL,
94 "floating-point constant: `%c' is invalid character",
95 *string);
96 return;
97 }
98 string++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000099 }
100 if (*string) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000101 string++; /* eat the E */
102 tenpwr += atoi(string);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000103 }
104
105 /*
106 * At this point, the memory interval [digits,p) contains a
107 * series of decimal digits zzzzzzz such that our number X
108 * satisfies
109 *
110 * X = 0.zzzzzzz * 10^tenpwr
111 */
112
113 bit = 0x8000;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000114 for (m = mant; m < mant + MANT_WORDS; m++)
115 *m = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000116 m = mant;
117 q = digits;
118 started = FALSE;
119 twopwr = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000120 while (m < mant + MANT_WORDS) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000121 uint16_t carry = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000122 while (p > q && !p[-1])
123 p--;
124 if (p <= q)
125 break;
126 for (r = p; r-- > q;) {
127 int i;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000128
H. Peter Anvine2c80182005-01-15 22:15:51 +0000129 i = 2 * *r + carry;
130 if (i >= 10)
131 carry = 1, i -= 10;
132 else
133 carry = 0;
134 *r = i;
135 }
136 if (carry)
137 *m |= bit, started = TRUE;
138 if (started) {
139 if (bit == 1)
140 bit = 0x8000, m++;
141 else
142 bit >>= 1;
143 } else
144 twopwr--;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000145 }
146 twopwr += tenpwr;
147
148 /*
149 * At this point the `mant' array contains the first six
150 * fractional places of a base-2^16 real number, which when
151 * multiplied by 2^twopwr and 5^tenpwr gives X. So now we
152 * really do multiply by 5^tenpwr.
153 */
154
155 if (tenpwr < 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000156 for (m = mult; m < mult + MANT_WORDS; m++)
157 *m = 0xCCCC;
158 extratwos = -2;
159 tenpwr = -tenpwr;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000160 } else if (tenpwr > 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000161 mult[0] = 0xA000;
162 for (m = mult + 1; m < mult + MANT_WORDS; m++)
163 *m = 0;
164 extratwos = 3;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000165 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000166 extratwos = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000167 while (tenpwr) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000168 if (tenpwr & 1)
169 twopwr += extratwos + ieee_multiply(mant, mult);
170 extratwos = extratwos * 2 + ieee_multiply(mult, mult);
171 tenpwr >>= 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000172 }
173
174 /*
175 * Conversion is done. The elements of `mant' contain the first
176 * fractional places of a base-2^16 real number in [0.5,1)
177 * which we can multiply by 2^twopwr to get X. Or, of course,
178 * it contains zero.
179 */
180 *exponent = twopwr;
181}
182
183/*
184 * Shift a mantissa to the right by i (i < 16) bits.
185 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000186static void ieee_shr(uint16_t *mant, int i)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000187{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000188 uint16_t n = 0, m;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000189 int j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000190
H. Peter Anvine2c80182005-01-15 22:15:51 +0000191 for (j = 0; j < MANT_WORDS; j++) {
192 m = (mant[j] << (16 - i)) & 0xFFFF;
193 mant[j] = (mant[j] >> i) | n;
194 n = m;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000195 }
196}
197
198/*
199 * Round a mantissa off after i words.
200 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000201static int ieee_round(uint16_t *mant, int i)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000202{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000203 if (mant[i] & 0x8000) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000204 do {
205 ++mant[--i];
206 mant[i] &= 0xFFFF;
207 } while (i > 0 && !mant[i]);
208 return !i && !mant[i];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000209 }
210 return 0;
211}
212
213#define put(a,b) ( (*(a)=(b)), ((a)[1]=(b)>>8) )
214
H. Peter Anvine31747e2007-09-18 17:50:34 -0700215/* Produce standard IEEE formats, with implicit "1" bit; this makes
216 the following assumptions:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000217
H. Peter Anvine31747e2007-09-18 17:50:34 -0700218 - the sign bit is the MSB, followed by the exponent.
219 - the sign bit plus exponent fit in 16 bits.
220 - the exponent bias is 2^(n-1)-1 for an n-bit exponent */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000221
H. Peter Anvine31747e2007-09-18 17:50:34 -0700222struct ieee_format {
223 int words;
224 int mantissa; /* Bits in the mantissa */
225 int exponent; /* Bits in the exponent */
226};
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000227
H. Peter Anvine31747e2007-09-18 17:50:34 -0700228static const struct ieee_format ieee_16 = { 1, 10, 5 };
229static const struct ieee_format ieee_32 = { 2, 23, 8 };
230static const struct ieee_format ieee_64 = { 4, 52, 11 };
231static const struct ieee_format ieee_128 = { 8, 112, 15 };
232
233/* Produce all the standard IEEE formats: 16, 32, 64, and 128 bits */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000234static int to_float(char *str, int32_t sign, uint8_t *result,
H. Peter Anvine31747e2007-09-18 17:50:34 -0700235 const struct ieee_format *fmt, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000236{
H. Peter Anvine31747e2007-09-18 17:50:34 -0700237 uint16_t mant[MANT_WORDS], *mp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000238 int32_t exponent;
H. Peter Anvine31747e2007-09-18 17:50:34 -0700239 int32_t expmax = 1 << (fmt->exponent-1);
240 uint16_t implicit_one = 0x8000 >> fmt->exponent;
241 int i;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000242
243 sign = (sign < 0 ? 0x8000L : 0L);
244
H. Peter Anvine2c80182005-01-15 22:15:51 +0000245 ieee_flconvert(str, mant, &exponent, error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000246 if (mant[0] & 0x8000) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000247 /*
248 * Non-zero.
249 */
250 exponent--;
H. Peter Anvine31747e2007-09-18 17:50:34 -0700251 if (exponent >= 2-expmax && exponent <= expmax) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000252 /*
253 * Normalised.
254 */
H. Peter Anvine31747e2007-09-18 17:50:34 -0700255 exponent += expmax;
256 ieee_shr(mant, fmt->exponent);
257 ieee_round(mant, fmt->words);
258 /* did we scale up by one? */
259 if (mant[0] & (implicit_one << 1)) {
260 ieee_shr(mant, 1);
261 exponent++;
262 }
263
264 mant[0] &= (implicit_one-1); /* remove leading one */
265 mant[0] |= exponent << (15 - fmt->exponent);
266 } else if (exponent < 2-expmax && exponent >= 2-expmax-fmt->mantissa) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000267 /*
268 * Denormal.
269 */
H. Peter Anvine31747e2007-09-18 17:50:34 -0700270 int shift = -(exponent + expmax-2-fmt->exponent);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000271 int sh = shift % 16, wds = shift / 16;
272 ieee_shr(mant, sh);
H. Peter Anvine31747e2007-09-18 17:50:34 -0700273 if (ieee_round(mant, fmt->words - wds)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000274 || (sh > 0 && (mant[0] & (0x8000 >> (sh - 1))))) {
275 ieee_shr(mant, 1);
276 if (sh == 0)
277 mant[0] |= 0x8000;
278 exponent++;
279 }
H. Peter Anvine31747e2007-09-18 17:50:34 -0700280
281 if (wds) {
282 for (i = fmt->words-1; i >= wds; i--)
283 mant[i] = mant[i-wds];
284 for (; i >= 0; i--)
285 mant[i] = 0;
286 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000287 } else {
288 if (exponent > 0) {
289 error(ERR_NONFATAL, "overflow in floating-point constant");
290 return 0;
H. Peter Anvine31747e2007-09-18 17:50:34 -0700291 } else {
292 memset(mant, 0, 2*fmt->words);
293 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000294 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000295 } else {
H. Peter Anvine31747e2007-09-18 17:50:34 -0700296 /* Zero */
297 memset(mant, 0, 2*fmt->words);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000298 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000299
H. Peter Anvine31747e2007-09-18 17:50:34 -0700300 mant[0] |= sign;
H. Peter Anvin141d7cf2007-09-18 16:39:03 -0700301
H. Peter Anvine31747e2007-09-18 17:50:34 -0700302 for (mp = &mant[fmt->words], i = 0; i < fmt->words; i++) {
303 uint16_t m = *--mp;
304 put(result, m);
305 result += 2;
H. Peter Anvin141d7cf2007-09-18 16:39:03 -0700306 }
H. Peter Anvine31747e2007-09-18 17:50:34 -0700307
308 return 1; /* success */
H. Peter Anvin141d7cf2007-09-18 16:39:03 -0700309}
310
311/* 80-bit format with 64-bit mantissa *including an explicit integer 1*
312 and 15-bit exponent. */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000313static int to_ldoub(char *str, int32_t sign, uint8_t *result,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000314 efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000315{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000316 uint16_t mant[MANT_WORDS];
317 int32_t exponent;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000318
319 sign = (sign < 0 ? 0x8000L : 0L);
320
H. Peter Anvine2c80182005-01-15 22:15:51 +0000321 ieee_flconvert(str, mant, &exponent, error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000322 if (mant[0] & 0x8000) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000323 /*
324 * Non-zero.
325 */
326 exponent--;
327 if (exponent >= -16383 && exponent <= 16384) {
328 /*
329 * Normalised.
330 */
331 exponent += 16383;
332 if (ieee_round(mant, 4)) /* did we scale up by one? */
333 ieee_shr(mant, 1), mant[0] |= 0x8000, exponent++;
334 put(result + 8, exponent | sign);
335 put(result + 6, mant[0]);
336 put(result + 4, mant[1]);
337 put(result + 2, mant[2]);
338 put(result + 0, mant[3]);
339 } else if (exponent < -16383 && exponent >= -16446) {
340 /*
341 * Denormal.
342 */
343 int shift = -(exponent + 16383);
344 int sh = shift % 16, wds = shift / 16;
345 ieee_shr(mant, sh);
346 if (ieee_round(mant, 4 - wds)
347 || (sh > 0 && (mant[0] & (0x8000 >> (sh - 1))))) {
348 ieee_shr(mant, 1);
349 if (sh == 0)
350 mant[0] |= 0x8000;
351 exponent++;
352 }
353 put(result + 8, sign);
354 put(result + 6, (wds == 0 ? mant[0] : 0));
355 put(result + 4, (wds <= 1 ? mant[1 - wds] : 0));
356 put(result + 2, (wds <= 2 ? mant[2 - wds] : 0));
357 put(result + 0, (wds <= 3 ? mant[3 - wds] : 0));
358 } else {
359 if (exponent > 0) {
360 error(ERR_NONFATAL, "overflow in floating-point constant");
361 return 0;
362 } else
363 memset(result, 0, 10);
364 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000365 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000366 /*
367 * Zero.
368 */
369 memset(result, 0, 10);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000370 }
371 return 1;
372}
373
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000374int float_const(char *number, int32_t sign, uint8_t *result, int bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000375 efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000376{
H. Peter Anvin141d7cf2007-09-18 16:39:03 -0700377 switch (bytes) {
378 case 2:
H. Peter Anvine31747e2007-09-18 17:50:34 -0700379 return to_float(number, sign, result, &ieee_16, error);
H. Peter Anvin141d7cf2007-09-18 16:39:03 -0700380 case 4:
H. Peter Anvine31747e2007-09-18 17:50:34 -0700381 return to_float(number, sign, result, &ieee_32, error);
H. Peter Anvin141d7cf2007-09-18 16:39:03 -0700382 case 8:
H. Peter Anvine31747e2007-09-18 17:50:34 -0700383 return to_float(number, sign, result, &ieee_64, error);
H. Peter Anvin141d7cf2007-09-18 16:39:03 -0700384 case 10:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000385 return to_ldoub(number, sign, result, error);
H. Peter Anvine31747e2007-09-18 17:50:34 -0700386 case 16:
387 return to_float(number, sign, result, &ieee_128, error);
H. Peter Anvin141d7cf2007-09-18 16:39:03 -0700388 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000389 error(ERR_PANIC, "strange value %d passed to float_const", bytes);
390 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000391 }
392}