diff --git a/asm/preproc.c b/asm/preproc.c index d1237096..cda0fee1 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -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; diff --git a/doc/changes.src b/doc/changes.src index e08c24c6..5563de9f 100644 --- a/doc/changes.src +++ b/doc/changes.src @@ -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 diff --git a/doc/preproc.src b/doc/preproc.src index 5b9799d9..37d8afc9 100644 --- a/doc/preproc.src +++ b/doc/preproc.src @@ -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,