eval: add general support for "integer functions" and add ilog2*()
authorH. Peter Anvin <hpa@zytor.com>
Thu, 31 May 2012 17:25:37 +0000 (10:25 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 31 May 2012 17:25:37 +0000 (10:25 -0700)
Add general support in the function parser for "integer functions"
(actually implemented as special unary operators, then wrapped in
macros) and implement a family of integer logarithms.  The only
difference is the behavior on a non-power-of-two argument:

ilog2[e] -- throw an error
ilog2w -- throw a warning
ilog2f -- round down to power of 2
ilog2c -- round up to power of 2

This is useful for back-converting from masks to bit values.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
eval.c
macros/ifunc.mac [new file with mode: 0644]
nasm.h
tokens.dat

diff --git a/eval.c b/eval.c
index e526723..d7cf844 100644 (file)
--- a/eval.c
+++ b/eval.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2012 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -274,7 +274,7 @@ static expr *segment_part(expr * e)
  * expr3 : expr4 [ {<<,>>} expr4...]
  * expr4 : expr5 [ {+,-} expr5...]
  * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
- * expr6 : { ~,+,-,SEG } expr6
+ * expr6 : { ~,+,-,IFUNC,SEG } expr6
  *       | (bexpr)
  *       | symbol
  *       | $
@@ -732,6 +732,37 @@ static expr *eval_strfunc(enum strfunc type)
     return finishtemp();
 }
 
+static int64_t eval_ifunc(int64_t val, enum ifunc func)
+{
+    int errtype;
+    uint64_t uval = (uint64_t)val;
+    int64_t rv;
+
+    switch (func) {
+    case IFUNC_ILOG2E:
+    case IFUNC_ILOG2W:
+        errtype = (func == IFUNC_ILOG2E) ? ERR_NONFATAL : ERR_WARNING;
+        
+        if ((!uval) | (uval & (uval-1)))
+            error(errtype, "ilog2 argument is not a power of two");
+        /* fall through */
+    case IFUNC_ILOG2F:
+        rv = ilog2_64(uval);
+        break;
+
+    case IFUNC_ILOG2C:
+        rv = (uval < 2) ? 0 : ilog2_64(uval-1) + 1;
+        break;
+
+    default:
+        error(ERR_PANIC, "invalid IFUNC token %d", func);
+        rv = 0;
+        break;
+    }
+
+    return rv;
+}
+
 static expr *expr6(int critical)
 {
     int32_t type;
@@ -782,6 +813,23 @@ static expr *expr6(int critical)
         }
         return scalarvect(!reloc_value(e));
 
+    case TOKEN_IFUNC:
+    {
+        enum ifunc func = tokval->t_integer;
+        i = scan(scpriv, tokval);
+        e = expr6(critical);
+        if (!e)
+            return NULL;
+        if (is_just_unknown(e))
+            return unknown_expr();
+        else if (!is_simple(e)) {
+            error(ERR_NONFATAL, "function may only be applied to"
+                  " scalar values");
+            return NULL;
+        }
+        return scalarvect(eval_ifunc(reloc_value(e), func));
+    }
+
     case TOKEN_SEG:
         i = scan(scpriv, tokval);
         e = expr6(critical);
diff --git a/macros/ifunc.mac b/macros/ifunc.mac
new file mode 100644 (file)
index 0000000..fc0d313
--- /dev/null
@@ -0,0 +1,46 @@
+;; --------------------------------------------------------------------------
+;;   
+;;   Copyright 2012 The NASM Authors - All Rights Reserved
+;;   See the file AUTHORS included with the NASM distribution for
+;;   the specific copyright holders.
+;;
+;;   Redistribution and use in source and binary forms, with or without
+;;   modification, are permitted provided that the following
+;;   conditions are met:
+;;
+;;   * Redistributions of source code must retain the above copyright
+;;     notice, this list of conditions and the following disclaimer.
+;;   * Redistributions in binary form must reproduce the above
+;;     copyright notice, this list of conditions and the following
+;;     disclaimer in the documentation and/or other materials provided
+;;     with the distribution.
+;;     
+;;     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+;;     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+;;     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+;;     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+;;     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+;;     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+;;     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+;;     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+;;     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+;;     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+;;     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+;;     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+;;     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;;
+;; --------------------------------------------------------------------------
+
+;;
+;; ifunc.mac
+;;
+;; Integer function utility macros
+;;
+
+USE: ifunc
+
+%idefine ilog2(x)      (__ilog2e__(x))
+%idefine ilog2e(x)     (__ilog2e__(x))
+%idefine ilog2w(x)     (__ilog2w__(x))
+%idefine ilog2f(x)     (__ilog2f__(x))
+%idefine ilog2c(x)     (__ilog2c__(x))
diff --git a/nasm.h b/nasm.h
index f7dd060..7422635 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -225,6 +225,7 @@ enum token_type { /* token types, other than chars */
     TOKEN_WRT,          /* WRT */
     TOKEN_FLOATIZE,     /* __floatX__ */
     TOKEN_STRFUNC,      /* __utf16*__, __utf32*__ */
+    TOKEN_IFUNC,        /* __ilog2*__ */
 };
 
 enum floatize {
@@ -248,6 +249,13 @@ enum strfunc {
     STRFUNC_UTF32BE,
 };
 
+enum ifunc {
+    IFUNC_ILOG2E,
+    IFUNC_ILOG2W,
+    IFUNC_ILOG2F,
+    IFUNC_ILOG2C,
+};
+
 size_t string_transform(char *, size_t, char **, enum strfunc);
 
 /*
index bb5fccb..c2df469 100644 (file)
@@ -97,6 +97,12 @@ __utf32__
 __utf32le__
 __utf32be__
 
+% TOKEN_IFUNC, 0, IFUNC_{__*__}
+__ilog2e__
+__ilog2w__
+__ilog2f__
+__ilog2c__
+
 % TOKEN_*, 0, 0
 seg
 wrt