mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-03-19 18:00:23 +08:00
Support generating NaNs and infinities
Support generating NaNs and infinities as part of floating-point constants.
This commit is contained in:
parent
5107d672a0
commit
f48bc6fb48
184
float.c
184
float.c
@ -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,59 +339,84 @@ static int to_float(char *str, int32_t sign, uint8_t *result,
|
||||
|
||||
sign = (sign < 0 ? 0x8000L : 0L);
|
||||
|
||||
ieee_flconvert(str, mant, &exponent, error);
|
||||
if (mant[0] & 0x8000) {
|
||||
/*
|
||||
* Non-zero.
|
||||
*/
|
||||
exponent--;
|
||||
if (exponent >= 2-expmax && exponent <= expmax) {
|
||||
/*
|
||||
* Normalised.
|
||||
*/
|
||||
exponent += expmax;
|
||||
ieee_shr(mant, fmt->exponent);
|
||||
ieee_round(mant, fmt->words);
|
||||
/* did we scale up by one? */
|
||||
if (mant[0] & (implicit_one << 1)) {
|
||||
ieee_shr(mant, 1);
|
||||
exponent++;
|
||||
}
|
||||
if (str[0] == '_') {
|
||||
/* NaN or Infinity */
|
||||
int32_t expmask = (1 << fmt->exponent)-1;
|
||||
|
||||
mant[0] &= (implicit_one-1); /* remove leading one */
|
||||
mant[0] |= exponent << (15 - fmt->exponent);
|
||||
} else if (exponent < 2-expmax && exponent >= 2-expmax-fmt->mantissa) {
|
||||
/*
|
||||
* Denormal.
|
||||
*/
|
||||
int shift = -(exponent + expmax-2-fmt->exponent);
|
||||
int sh = shift % 16, wds = shift / 16;
|
||||
ieee_shr(mant, sh);
|
||||
if (ieee_round(mant, fmt->words - wds)
|
||||
|| (sh > 0 && (mant[0] & (0x8000 >> (sh - 1))))) {
|
||||
ieee_shr(mant, 1);
|
||||
if (sh == 0)
|
||||
mant[0] |= 0x8000;
|
||||
exponent++;
|
||||
}
|
||||
memset(mant, 0, sizeof mant);
|
||||
mant[0] = expmask << (15-fmt->exponent); /* Exponent: all bits one */
|
||||
|
||||
if (wds) {
|
||||
for (i = fmt->words-1; i >= wds; i--)
|
||||
mant[i] = mant[i-wds];
|
||||
for (; i >= 0; i--)
|
||||
mant[i] = 0;
|
||||
}
|
||||
} else {
|
||||
if (exponent > 0) {
|
||||
error(ERR_NONFATAL, "overflow in floating-point constant");
|
||||
return 0;
|
||||
} else {
|
||||
memset(mant, 0, 2*fmt->words);
|
||||
}
|
||||
}
|
||||
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 {
|
||||
/* Zero */
|
||||
memset(mant, 0, 2*fmt->words);
|
||||
ieee_flconvert(str, mant, &exponent, error);
|
||||
if (mant[0] & 0x8000) {
|
||||
/*
|
||||
* Non-zero.
|
||||
*/
|
||||
exponent--;
|
||||
if (exponent >= 2-expmax && exponent <= expmax) {
|
||||
/*
|
||||
* Normalised.
|
||||
*/
|
||||
exponent += expmax;
|
||||
ieee_shr(mant, fmt->exponent);
|
||||
ieee_round(mant, fmt->words);
|
||||
/* did we scale up by one? */
|
||||
if (mant[0] & (implicit_one << 1)) {
|
||||
ieee_shr(mant, 1);
|
||||
exponent++;
|
||||
}
|
||||
|
||||
mant[0] &= (implicit_one-1); /* remove leading one */
|
||||
mant[0] |= exponent << (15 - fmt->exponent);
|
||||
} else if (exponent < 2-expmax &&
|
||||
exponent >= 2-expmax-fmt->mantissa) {
|
||||
/*
|
||||
* Denormal.
|
||||
*/
|
||||
int shift = -(exponent + expmax-2-fmt->exponent);
|
||||
int sh = shift % 16, wds = shift / 16;
|
||||
ieee_shr(mant, sh);
|
||||
if (ieee_round(mant, fmt->words - wds)
|
||||
|| (sh > 0 && (mant[0] & (0x8000 >> (sh - 1))))) {
|
||||
ieee_shr(mant, 1);
|
||||
if (sh == 0)
|
||||
mant[0] |= 0x8000;
|
||||
exponent++;
|
||||
}
|
||||
|
||||
if (wds) {
|
||||
for (i = fmt->words-1; i >= wds; i--)
|
||||
mant[i] = mant[i-wds];
|
||||
for (; i >= 0; i--)
|
||||
mant[i] = 0;
|
||||
}
|
||||
} else {
|
||||
if (exponent > 0) {
|
||||
error(ERR_NONFATAL, "overflow in floating-point constant");
|
||||
return 0;
|
||||
} else {
|
||||
memset(mant, 0, 2*fmt->words);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* 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;
|
||||
}
|
||||
|
4
insns.h
4
insns.h
@ -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 {
|
||||
|
@ -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__
|
||||
|
@ -32,6 +32,12 @@ to
|
||||
tword
|
||||
word
|
||||
|
||||
% TOKEN_FLOAT, 0, 0
|
||||
__infinity__
|
||||
__nan__
|
||||
__qnan__
|
||||
__snan__
|
||||
|
||||
% TOKEN_*, 0, 0
|
||||
seg
|
||||
wrt
|
||||
|
Loading…
x
Reference in New Issue
Block a user