mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-10-10 00:25:06 -04:00
preproc: add a %selbits() function
Although one can implement this "manually" in terms of %sel(), this function is *really* useful for making multi-mode tests and allows for better error checking. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
@@ -7738,9 +7738,9 @@ stdmac_tok(const SMacro *s, Token **params, int nparams)
|
||||
return reverse_tokens(tokenize(unquote_token_cstr(params[0])));
|
||||
}
|
||||
|
||||
/* %cond() or %sel() */
|
||||
/* %sel() */
|
||||
static Token *
|
||||
stdmac_cond_sel(const SMacro *s, Token **params, int nparams)
|
||||
stdmac_sel(const SMacro *s, Token **params, int nparams)
|
||||
{
|
||||
int64_t which;
|
||||
|
||||
@@ -7749,29 +7749,57 @@ stdmac_cond_sel(const SMacro *s, Token **params, int nparams)
|
||||
*/
|
||||
which = get_tok_num(params[0], NULL);
|
||||
|
||||
if (s->expandpvt.u) {
|
||||
/* Booleanize (for %cond): true -> 1, false -> 2 (else) */
|
||||
which = which ? 1 : 2;
|
||||
if (which >= nparams) {
|
||||
/* false, and no else clause */
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (unlikely(which < 1)) {
|
||||
nasm_warn(WARN_PP_SEL_RANGE,
|
||||
"%s(%"PRId64") is not a valid selector", s->name, which);
|
||||
return NULL;
|
||||
} else if (unlikely(which >= nparams)) {
|
||||
nasm_warn(WARN_PP_SEL_RANGE,
|
||||
"%s(%"PRId64") exceeds the number of arguments",
|
||||
s->name, which);
|
||||
return NULL;
|
||||
}
|
||||
if (unlikely(which < 1)) {
|
||||
nasm_warn(WARN_PP_SEL_RANGE,
|
||||
"%s(%"PRId64") is not a valid selector", s->name, which);
|
||||
return NULL;
|
||||
} else if (unlikely(which >= nparams)) {
|
||||
nasm_warn(WARN_PP_SEL_RANGE,
|
||||
"%s(%"PRId64") exceeds the number of arguments",
|
||||
s->name, which);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new_Token(NULL, tok_smac_param(which), "", 0);
|
||||
}
|
||||
|
||||
/* %cond() */
|
||||
static Token *
|
||||
stdmac_cond(const SMacro *s, Token **params, int nparams)
|
||||
{
|
||||
int64_t which;
|
||||
(void)s;
|
||||
(void)params;
|
||||
|
||||
/*
|
||||
* params[0] will have been generated by make_tok_num.
|
||||
*/
|
||||
which = get_tok_num(params[0], NULL);
|
||||
|
||||
/* Booleanize: true -> 1, false -> 2 (else) */
|
||||
which = which ? 1 : 2;
|
||||
if (which >= nparams) {
|
||||
/* false, and no else clause */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new_Token(NULL, tok_smac_param(which), "", 0);
|
||||
}
|
||||
|
||||
/* %selbits() */
|
||||
static Token *
|
||||
stdmac_selbits(const SMacro *s, Token **params, int nparams)
|
||||
{
|
||||
int which = ilog2_32(globl.bits)-4;
|
||||
(void)s;
|
||||
(void)params;
|
||||
|
||||
if (nparams <= which)
|
||||
which = nparams - 1;
|
||||
|
||||
return new_Token(NULL, tok_smac_param(which), "", 0);
|
||||
}
|
||||
|
||||
/* %count() function */
|
||||
static Token *
|
||||
stdmac_count(const SMacro *s, Token **params, int nparams)
|
||||
@@ -8173,6 +8201,7 @@ static void pp_add_magic_simple(void)
|
||||
{ "%null", false, 1, SPARM_GREEDY, stdmac_null },
|
||||
{ "%pathsearch", false, 1, SPARM_PLAIN, stdmac_pathsearch },
|
||||
{ "%realpath", false, 1, SPARM_PLAIN, stdmac_realpath },
|
||||
{ "%selbits", false, 1, SPARM_PLAIN|SPARM_VARADIC, stdmac_selbits },
|
||||
{ "%str", false, 1, SPARM_GREEDY|SPARM_STR, stdmac_join },
|
||||
{ "%strcat", false, 1, SPARM_STR|SPARM_CONDQUOTE|SPARM_VARADIC, stdmac_strcat },
|
||||
{ "%strlen", false, 1, SPARM_STR|SPARM_CONDQUOTE, stdmac_strlen },
|
||||
@@ -8268,15 +8297,16 @@ static void pp_add_magic_miscfunc(void)
|
||||
/* %sel() function */
|
||||
nasm_zero(tmpl);
|
||||
tmpl.nparam = 2;
|
||||
tmpl.expand = stdmac_cond_sel;
|
||||
tmpl.expand = stdmac_sel;
|
||||
nasm_newn(tmpl.params, tmpl.nparam);
|
||||
tmpl.params[0].flags = SPARM_EVAL;
|
||||
tmpl.params[1].flags = SPARM_VARADIC;
|
||||
define_magic("%sel", false, &tmpl);
|
||||
|
||||
/* %cond() function, a variation on %sel */
|
||||
/* %cond() function */
|
||||
nasm_zero(tmpl);
|
||||
tmpl.nparam = 3;
|
||||
tmpl.expandpvt.u = 1; /* Booleanize */
|
||||
tmpl.expand = stdmac_cond;
|
||||
nasm_newn(tmpl.params, tmpl.nparam);
|
||||
tmpl.params[0].flags = SPARM_EVAL;
|
||||
tmpl.params[1].flags = 0;
|
||||
|
@@ -31,6 +31,8 @@ It is the production version of NASM since 2025.
|
||||
now be specified for the same group; the resulting group includes
|
||||
all sections specified in all \c{GROUP} directives for the group.
|
||||
|
||||
\b A new \c{%selbits()} preprocessor function. See \k{f_selbits}.
|
||||
|
||||
|
||||
\S{cl-3.00} Version 3.00
|
||||
|
||||
|
@@ -1011,6 +1011,24 @@ expands to nothing.
|
||||
The arguments not selected are never expanded.
|
||||
|
||||
|
||||
\S{f_selbits} \i\c{%selbits()} Function
|
||||
|
||||
The \c{%selbits()} function returns its first, second, or third
|
||||
argument depending on if the current mode is 16, 32 or 64 bits. If
|
||||
less than three arguments are given, the last argument is considered
|
||||
repeated. Like \c{%cond()}, this is a specialized version of the
|
||||
\c{%sel()} function.
|
||||
|
||||
For example:
|
||||
|
||||
\c BITS 64
|
||||
\c
|
||||
\c %define breg %selbits(bx,ebx,rbx)
|
||||
\c %define vreg %selbits(ax,eax)
|
||||
\c
|
||||
\c mov vreg,[breg] ; mov eax,[rbx]
|
||||
|
||||
|
||||
\S{f_str} \i\c\{%str()} Function
|
||||
|
||||
The \c{%str()} function converts its argument, including any commas,
|
||||
|
Reference in New Issue
Block a user