summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-10-16 14:40:27 -0700
committerH. Peter Anvin <hpa@zytor.com>2007-10-16 14:40:27 -0700
commitf6c9e65d4f906d0847ef747595de6495c92b9778 (patch)
tree2f37e73e9150c1e8699da19baa9b7deaad669216
parentfab3a6c9de9c56f1db7770c7c5e0271e33455ea2 (diff)
downloadnasm-f6c9e65d4f906d0847ef747595de6495c92b9778.tar.gz
Implement floating-point option control directive
New directive [FLOAT] with associated standard macros; allows the setting to be saved and restored.
-rw-r--r--doc/nasmdoc.src30
-rw-r--r--float.c31
-rw-r--r--float.h1
-rw-r--r--nasm.c13
-rw-r--r--standard.mac27
5 files changed, 98 insertions, 4 deletions
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index f6616ebe..66eaf10c 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -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
diff --git a/float.c b/float.c
index 18156efa..ec37775e 100644
--- a/float.c
+++ b/float.c
@@ -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 */
+ }
+}
+
diff --git a/float.h b/float.h
index 430c4643..04e9b172 100644
--- a/float.h
+++ b/float.h
@@ -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
diff --git a/nasm.c b/nasm.c
index 04f41909..af2f0b37 100644
--- a/nasm.c
+++ b/nasm.c
@@ -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"))
diff --git a/standard.mac b/standard.mac
index bfc2af08..e056352e 100644
--- a/standard.mac
+++ b/standard.mac
@@ -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