Implement floating-point option control directive
authorH. Peter Anvin <hpa@zytor.com>
Tue, 16 Oct 2007 21:40:27 +0000 (14:40 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 16 Oct 2007 21:40:27 +0000 (14:40 -0700)
New directive [FLOAT] with associated standard macros; allows the
setting to be saved and restored.

doc/nasmdoc.src
float.c
float.h
nasm.c
standard.mac

index f6616eb..66eaf10 100644 (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
diff --git a/float.c b/float.c
index 18156ef..ec37775 100644 (file)
--- 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 430c464..04e9b17 100644 (file)
--- 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 04f4190..af2f0b3 100644 (file)
--- 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"))
index bfc2af0..e056352 100644 (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