Support generating NaNs and infinities

Support generating NaNs and infinities as part of floating-point
constants.
This commit is contained in:
H. Peter Anvin 2007-09-18 21:55:56 -07:00
parent 5107d672a0
commit f48bc6fb48
4 changed files with 161 additions and 63 deletions

86
float.c
View file

@ -303,6 +303,12 @@ static int ieee_round(uint16_t *mant, int i)
#define put(a,b) ( (*(a)=(b)), ((a)[1]=(b)>>8) )
/* Set a bit, using *bigendian* bit numbering (0 = MSB) */
static void set_bit(uint16_t *mant, int bit)
{
mant[bit >> 4] |= 1 << (~bit & 15);
}
/* Produce standard IEEE formats, with implicit "1" bit; this makes
the following assumptions:
@ -333,6 +339,29 @@ static int to_float(char *str, int32_t sign, uint8_t *result,
sign = (sign < 0 ? 0x8000L : 0L);
if (str[0] == '_') {
/* NaN or Infinity */
int32_t expmask = (1 << fmt->exponent)-1;
memset(mant, 0, sizeof mant);
mant[0] = expmask << (15-fmt->exponent); /* Exponent: all bits one */
switch (str[2]) {
case 'n': /* __nan__ */
case 'N':
case 'q': /* __qnan__ */
case 'Q':
set_bit(mant, fmt->exponent+1); /* Highest bit in mantissa */
break;
case 's': /* __snan__ */
case 'S':
set_bit(mant, fmt->exponent+fmt->mantissa); /* Last bit */
break;
case 'i': /* __infinity__ */
case 'I':
break;
}
} else {
ieee_flconvert(str, mant, &exponent, error);
if (mant[0] & 0x8000) {
/*
@ -354,7 +383,8 @@ static int to_float(char *str, int32_t sign, uint8_t *result,
mant[0] &= (implicit_one-1); /* remove leading one */
mant[0] |= exponent << (15 - fmt->exponent);
} else if (exponent < 2-expmax && exponent >= 2-expmax-fmt->mantissa) {
} else if (exponent < 2-expmax &&
exponent >= 2-expmax-fmt->mantissa) {
/*
* Denormal.
*/
@ -387,6 +417,7 @@ static int to_float(char *str, int32_t sign, uint8_t *result,
/* Zero */
memset(mant, 0, 2*fmt->words);
}
}
mant[0] |= sign;
@ -409,6 +440,31 @@ static int to_ldoub(char *str, int32_t sign, uint8_t *result,
sign = (sign < 0 ? 0x8000L : 0L);
if (str[0] == '_') {
uint16_t is_snan = 0, is_qnan = 0x8000;
switch (str[2]) {
case 'n':
case 'N':
case 'q':
case 'Q':
is_qnan = 0xc000;
break;
case 's':
case 'S':
is_snan = 1;
break;
case 'i':
case 'I':
break;
}
put(result + 0, is_snan);
put(result + 2, 0);
put(result + 4, 0);
put(result + 6, is_qnan);
put(result + 8, 0x7fff|sign);
return 1;
}
ieee_flconvert(str, mant, &exponent, error);
if (mant[0] & 0x8000) {
/*
@ -422,11 +478,11 @@ static int to_ldoub(char *str, int32_t sign, uint8_t *result,
exponent += 16383;
if (ieee_round(mant, 4)) /* did we scale up by one? */
ieee_shr(mant, 1), mant[0] |= 0x8000, exponent++;
put(result + 8, exponent | sign);
put(result + 6, mant[0]);
put(result + 4, mant[1]);
put(result + 2, mant[2]);
put(result + 0, mant[3]);
put(result + 2, mant[2]);
put(result + 4, mant[1]);
put(result + 6, mant[0]);
put(result + 8, exponent | sign);
} else if (exponent < -16383 && exponent >= -16446) {
/*
* Denormal.
@ -441,23 +497,29 @@ static int to_ldoub(char *str, int32_t sign, uint8_t *result,
mant[0] |= 0x8000;
exponent++;
}
put(result + 8, sign);
put(result + 6, (wds == 0 ? mant[0] : 0));
put(result + 4, (wds <= 1 ? mant[1 - wds] : 0));
put(result + 2, (wds <= 2 ? mant[2 - wds] : 0));
put(result + 0, (wds <= 3 ? mant[3 - wds] : 0));
put(result + 2, (wds <= 2 ? mant[2 - wds] : 0));
put(result + 4, (wds <= 1 ? mant[1 - wds] : 0));
put(result + 6, (wds == 0 ? mant[0] : 0));
put(result + 8, sign);
} else {
if (exponent > 0) {
error(ERR_NONFATAL, "overflow in floating-point constant");
return 0;
} else
memset(result, 0, 10);
} else {
goto zero;
}
}
} else {
/*
* Zero.
*/
memset(result, 0, 10);
zero:
put(result + 0, 0);
put(result + 2, 0);
put(result + 4, 0);
put(result + 6, 0);
put(result + 8, sign);
}
return 1;
}

View file

@ -12,10 +12,10 @@
#include "nasm.h"
/* max length of any instruction, register name etc. */
#if MAX_INSLEN > 9 /* MAX_INSLEN defined in insnsi.h */
#if MAX_INSLEN > 12 /* MAX_INSLEN defined in insnsi.h */
#define MAX_KEYWORD MAX_INSLEN
#else
#define MAX_KEYWORD 9
#define MAX_KEYWORD 12
#endif
struct itemplate {

View file

@ -21,6 +21,12 @@
dw 1.83203125e-6 ; Denormal!
dw +1.83203125e-6 ; Denormal!
dw -1.83203125e-6 ; Denormal!
dw __Infinity__
dw +__Infinity__
dw -__Infinity__
dw __NaN__
dw __QNaN__
dw __SNaN__
; 32-bit
dd 1.0
@ -41,6 +47,12 @@
dd 1.83203125e-40 ; Denormal!
dd +1.83203125e-40 ; Denormal!
dd -1.83203125e-40 ; Denormal!
dd __Infinity__
dd +__Infinity__
dd -__Infinity__
dd __NaN__
dd __QNaN__
dd __SNaN__
; 64-bit
dq 1.0
@ -61,6 +73,12 @@
dq 1.83203125e-320 ; Denormal!
dq +1.83203125e-320 ; Denormal!
dq -1.83203125e-320 ; Denormal!
dq __Infinity__
dq +__Infinity__
dq -__Infinity__
dq __NaN__
dq __QNaN__
dq __SNaN__
; 80-bit
dt 1.0
@ -81,6 +99,12 @@
dt 1.83203125e-4940 ; Denormal!
dt +1.83203125e-4940 ; Denormal!
dt -1.83203125e-4940 ; Denormal!
dt __Infinity__
dt +__Infinity__
dt -__Infinity__
dt __NaN__
dt __QNaN__
dt __SNaN__
; 128-bit
do 1.0
@ -101,3 +125,9 @@
do 1.83203125e-4940 ; Denormal!
do +1.83203125e-4940 ; Denormal!
do -1.83203125e-4940 ; Denormal!
do __Infinity__
do +__Infinity__
do -__Infinity__
do __NaN__
do __QNaN__
do __SNaN__

View file

@ -32,6 +32,12 @@ to
tword
word
% TOKEN_FLOAT, 0, 0
__infinity__
__nan__
__qnan__
__snan__
% TOKEN_*, 0, 0
seg
wrt