Skip to content

Commit f1b6d31

Browse files
author
H. Peter Anvin
committed
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>
1 parent e4044cf commit f1b6d31

File tree

3 files changed

+73
-23
lines changed

3 files changed

+73
-23
lines changed

asm/preproc.c

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7738,9 +7738,9 @@ stdmac_tok(const SMacro *s, Token **params, int nparams)
77387738
return reverse_tokens(tokenize(unquote_token_cstr(params[0])));
77397739
}
77407740

7741-
/* %cond() or %sel() */
7741+
/* %sel() */
77427742
static Token *
7743-
stdmac_cond_sel(const SMacro *s, Token **params, int nparams)
7743+
stdmac_sel(const SMacro *s, Token **params, int nparams)
77447744
{
77457745
int64_t which;
77467746

@@ -7749,29 +7749,57 @@ stdmac_cond_sel(const SMacro *s, Token **params, int nparams)
77497749
*/
77507750
which = get_tok_num(params[0], NULL);
77517751

7752-
if (s->expandpvt.u) {
7753-
/* Booleanize (for %cond): true -> 1, false -> 2 (else) */
7754-
which = which ? 1 : 2;
7755-
if (which >= nparams) {
7756-
/* false, and no else clause */
7757-
return NULL;
7758-
}
7759-
} else {
7760-
if (unlikely(which < 1)) {
7761-
nasm_warn(WARN_PP_SEL_RANGE,
7762-
"%s(%"PRId64") is not a valid selector", s->name, which);
7763-
return NULL;
7764-
} else if (unlikely(which >= nparams)) {
7765-
nasm_warn(WARN_PP_SEL_RANGE,
7766-
"%s(%"PRId64") exceeds the number of arguments",
7767-
s->name, which);
7768-
return NULL;
7769-
}
7752+
if (unlikely(which < 1)) {
7753+
nasm_warn(WARN_PP_SEL_RANGE,
7754+
"%s(%"PRId64") is not a valid selector", s->name, which);
7755+
return NULL;
7756+
} else if (unlikely(which >= nparams)) {
7757+
nasm_warn(WARN_PP_SEL_RANGE,
7758+
"%s(%"PRId64") exceeds the number of arguments",
7759+
s->name, which);
7760+
return NULL;
77707761
}
77717762

77727763
return new_Token(NULL, tok_smac_param(which), "", 0);
77737764
}
77747765

7766+
/* %cond() */
7767+
static Token *
7768+
stdmac_cond(const SMacro *s, Token **params, int nparams)
7769+
{
7770+
int64_t which;
7771+
(void)s;
7772+
(void)params;
7773+
7774+
/*
7775+
* params[0] will have been generated by make_tok_num.
7776+
*/
7777+
which = get_tok_num(params[0], NULL);
7778+
7779+
/* Booleanize: true -> 1, false -> 2 (else) */
7780+
which = which ? 1 : 2;
7781+
if (which >= nparams) {
7782+
/* false, and no else clause */
7783+
return NULL;
7784+
}
7785+
7786+
return new_Token(NULL, tok_smac_param(which), "", 0);
7787+
}
7788+
7789+
/* %selbits() */
7790+
static Token *
7791+
stdmac_selbits(const SMacro *s, Token **params, int nparams)
7792+
{
7793+
int which = ilog2_32(globl.bits)-4;
7794+
(void)s;
7795+
(void)params;
7796+
7797+
if (nparams <= which)
7798+
which = nparams - 1;
7799+
7800+
return new_Token(NULL, tok_smac_param(which), "", 0);
7801+
}
7802+
77757803
/* %count() function */
77767804
static Token *
77777805
stdmac_count(const SMacro *s, Token **params, int nparams)
@@ -8173,6 +8201,7 @@ static void pp_add_magic_simple(void)
81738201
{ "%null", false, 1, SPARM_GREEDY, stdmac_null },
81748202
{ "%pathsearch", false, 1, SPARM_PLAIN, stdmac_pathsearch },
81758203
{ "%realpath", false, 1, SPARM_PLAIN, stdmac_realpath },
8204+
{ "%selbits", false, 1, SPARM_PLAIN|SPARM_VARADIC, stdmac_selbits },
81768205
{ "%str", false, 1, SPARM_GREEDY|SPARM_STR, stdmac_join },
81778206
{ "%strcat", false, 1, SPARM_STR|SPARM_CONDQUOTE|SPARM_VARADIC, stdmac_strcat },
81788207
{ "%strlen", false, 1, SPARM_STR|SPARM_CONDQUOTE, stdmac_strlen },
@@ -8268,15 +8297,16 @@ static void pp_add_magic_miscfunc(void)
82688297
/* %sel() function */
82698298
nasm_zero(tmpl);
82708299
tmpl.nparam = 2;
8271-
tmpl.expand = stdmac_cond_sel;
8300+
tmpl.expand = stdmac_sel;
82728301
nasm_newn(tmpl.params, tmpl.nparam);
82738302
tmpl.params[0].flags = SPARM_EVAL;
82748303
tmpl.params[1].flags = SPARM_VARADIC;
82758304
define_magic("%sel", false, &tmpl);
82768305

8277-
/* %cond() function, a variation on %sel */
8306+
/* %cond() function */
8307+
nasm_zero(tmpl);
82788308
tmpl.nparam = 3;
8279-
tmpl.expandpvt.u = 1; /* Booleanize */
8309+
tmpl.expand = stdmac_cond;
82808310
nasm_newn(tmpl.params, tmpl.nparam);
82818311
tmpl.params[0].flags = SPARM_EVAL;
82828312
tmpl.params[1].flags = 0;

doc/changes.src

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ It is the production version of NASM since 2025.
3131
now be specified for the same group; the resulting group includes
3232
all sections specified in all \c{GROUP} directives for the group.
3333

34+
\b A new \c{%selbits()} preprocessor function. See \k{f_selbits}.
35+
3436

3537
\S{cl-3.00} Version 3.00
3638

doc/preproc.src

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,24 @@ expands to nothing.
10111011
The arguments not selected are never expanded.
10121012

10131013

1014+
\S{f_selbits} \i\c{%selbits()} Function
1015+
1016+
The \c{%selbits()} function returns its first, second, or third
1017+
argument depending on if the current mode is 16, 32 or 64 bits. If
1018+
less than three arguments are given, the last argument is considered
1019+
repeated. Like \c{%cond()}, this is a specialized version of the
1020+
\c{%sel()} function.
1021+
1022+
For example:
1023+
1024+
\c BITS 64
1025+
\c
1026+
\c %define breg %selbits(bx,ebx,rbx)
1027+
\c %define vreg %selbits(ax,eax)
1028+
\c
1029+
\c mov vreg,[breg] ; mov eax,[rbx]
1030+
1031+
10141032
\S{f_str} \i\c\{%str()} Function
10151033

10161034
The \c{%str()} function converts its argument, including any commas,

0 commit comments

Comments
 (0)