Implement floating-point option control directive

New directive [FLOAT] with associated standard macros; allows the
setting to be saved and restored.
This commit is contained in:
H. Peter Anvin 2007-10-16 14:40:27 -07:00
parent fab3a6c9de
commit f6c9e65d4f
5 changed files with 98 additions and 4 deletions

View file

@ -3786,7 +3786,7 @@ Options are:
\b\c{CPU WILLAMETTE} Same as P4
\b\c{CPU PRESCOTT} Prescott instruction set
\b\c{CPU PRESCOTT} Prescott instruction set
\b\c{CPU X64} x86-64 (x64/AMD64/EM64T) instruction set
@ -3797,6 +3797,34 @@ only if they apply to the selected CPU or lower. By default, all
instructions are available.
\H{FLOAT} \i\c{FLOAT}: Handling of \I{floating-point, constants}floating-point constants
By default, floating-point constants are rounded to nearest, and IEEE
denormals are supported. The following options can be set to alter
this behaviour:
\b\c{FLOAT DAZ} Flush denormals to zero
\b\c{FLOAT NODAZ} Do not flush denormals to zero (default)
\b\c{FLOAT NEAR} Round to nearest (default)
\b\c{FLOAT UP} Round up (toward +Infinity)
\b\c{FLOAT DOWN} Round down (toward -Infinity)
\b\c{FLOAT ZERO} Round toward zero
\b\c{FLOAT DEFAULT} Restore default settings
The standard macros \i\c{__FLOAT_DAZ__}, \i\c{__FLOAT_ROUND__}, and
\i\c{__FLOAT__} contain the current state, as long as the programmer
has avoided the use of the brackeded primitive form, (\c{[FLOAT]}).
\c{__FLOAT__} contains the full set of floating-point settings; this
value can be saved away and invoked later to restore the setting.
\C{outfmt} \i{Output Formats}
NASM is a portable assembler, designed to be able to compile on any

31
float.c
View file

@ -776,3 +776,34 @@ int float_const(const char *number, int32_t sign, uint8_t * result,
return 0;
}
}
/* Set floating-point options */
int float_option(const char *option)
{
if (!nasm_stricmp(option, "daz")) {
daz = true;
return 0;
} else if (!nasm_stricmp(option, "nodaz")) {
daz = false;
return 0;
} else if (!nasm_stricmp(option, "near")) {
rc = FLOAT_RC_NEAR;
return 0;
} else if (!nasm_stricmp(option, "down")) {
rc = FLOAT_RC_DOWN;
return 0;
} else if (!nasm_stricmp(option, "up")) {
rc = FLOAT_RC_UP;
return 0;
} else if (!nasm_stricmp(option, "zero")) {
rc = FLOAT_RC_ZERO;
return 0;
} else if (!nasm_stricmp(option, "default")) {
rc = FLOAT_RC_NEAR;
daz = false;
return 0;
} else {
return -1; /* Unknown option */
}
}

View file

@ -19,5 +19,6 @@ enum float_round {
int float_const(const char *string, int sign, uint8_t *result, int bytes,
efunc error);
int float_option(const char *option);
#endif

13
nasm.c
View file

@ -18,6 +18,7 @@
#include "nasm.h"
#include "nasmlib.h"
#include "float.h"
#include "stdscan.h"
#include "insns.h"
#include "preproc.h"
@ -822,11 +823,11 @@ static void parse_cmdline(int argc, char **argv)
/* List of directives */
enum directives {
D_NONE, D_ABSOLUTE, D_BITS, D_COMMON, D_CPU, D_DEBUG, D_DEFAULT,
D_EXTERN, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
D_EXTERN, D_FLOAT, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
};
static const char *directives[] = {
"", "absolute", "bits", "common", "cpu", "debug", "default",
"extern", "global", "list", "section", "segment", "warning"
"extern", "float", "global", "list", "section", "segment", "warning"
};
static enum directives getkw(char **directive, char **value);
@ -1143,6 +1144,13 @@ static void assemble_file(char *fname)
err = 1;
}
break;
case D_FLOAT:
if (float_option(value)) {
report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
"unknown 'float' directive: %s",
value);
}
break;
default:
if (!ofmt->directive(directive, value, pass2))
report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
@ -1730,7 +1738,6 @@ static void no_pp_cleanup(int pass)
static uint32_t get_cpu(char *value)
{
if (!strcmp(value, "8086"))
return IF_8086;
if (!strcmp(value, "186"))

View file

@ -111,6 +111,33 @@ __SECT__
[cpu %1]
%endmacro
%define __FLOAT_DAZ__ nodaz
%define __FLOAT_ROUND__ near
; __FLOAT__ contains the whole floating-point configuration so it can
; be saved and restored
%define __FLOAT__ __FLOAT_DAZ__ __FLOAT_ROUND__
%imacro float 1-*.nolist
%rep %0
[float %1]
%ifidni %1,daz
%define __FLOAT_DAZ__ daz
%elifidni %1,nodaz
%define __FLOAT_DAZ__ nodaz
%elifidni %1,near
%define __FLOAT_ROUND__ near
%elifidni %1,up
%define __FLOAT_ROUND__ up
%elifidni %1,down
%define __FLOAT_ROUND__ down
%elifidni %1,zero
%define __FLOAT_ROUND__ zero
%elifidni %1,default
%define __FLOAT_DAZ__ nodaz
%define __FLOAT_ROUND__ near
%endif
%endrep
%endmacro
%imacro default 1+.nolist
[default %1]
%endmacro