eval: add general support for "integer functions" and add ilog2*()

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>
This commit is contained in:
H. Peter Anvin 2012-05-31 10:25:37 -07:00
parent 3d1d159e1c
commit 290b4cb3a4
4 changed files with 110 additions and 2 deletions

52
eval.c
View File

@ -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);

46
macros/ifunc.mac Normal file
View File

@ -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))

8
nasm.h
View File

@ -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);
/*

View File

@ -97,6 +97,12 @@ __utf32__
__utf32le__
__utf32be__
% TOKEN_IFUNC, 0, IFUNC_{__*__}
__ilog2e__
__ilog2w__
__ilog2f__
__ilog2c__
% TOKEN_*, 0, 0
seg
wrt