Reword docs now that SET is deprecated (#946)

- '=' constants are "variables" (not "mutable constants")
- EQU constants are "numeric constants" (not "immutable constants")
- EQUS constants are "string constants" (not "string equates")
- DS declarations are "static allocations" (not "variables")
This commit is contained in:
Rangi
2021-11-22 17:08:29 -05:00
committed by GitHub
parent ec6d63bce3
commit b9fd85470e
5 changed files with 121 additions and 128 deletions

View File

@@ -23,7 +23,7 @@
enum SymbolType { enum SymbolType {
SYM_LABEL, SYM_LABEL,
SYM_EQU, SYM_EQU,
SYM_SET, SYM_VAR,
SYM_MACRO, SYM_MACRO,
SYM_EQUS, SYM_EQUS,
SYM_REF // Forward reference to a label SYM_REF // Forward reference to a label
@@ -75,12 +75,12 @@ static inline bool sym_IsConstant(struct Symbol const *sym)
return sect && sect->org != (uint32_t)-1; return sect && sect->org != (uint32_t)-1;
} }
return sym->type == SYM_EQU || sym->type == SYM_SET; return sym->type == SYM_EQU || sym->type == SYM_VAR;
} }
static inline bool sym_IsNumeric(struct Symbol const *sym) static inline bool sym_IsNumeric(struct Symbol const *sym)
{ {
return sym->type == SYM_LABEL || sym->type == SYM_EQU || sym->type == SYM_SET; return sym->type == SYM_LABEL || sym->type == SYM_EQU || sym->type == SYM_VAR;
} }
static inline bool sym_IsLabel(struct Symbol const *sym) static inline bool sym_IsLabel(struct Symbol const *sym)
@@ -119,7 +119,7 @@ void sym_WriteAnonLabelName(char buf[MIN_NB_ELMS(MAXSYMLEN + 1)], uint32_t ofs,
void sym_Export(char const *symName); void sym_Export(char const *symName);
struct Symbol *sym_AddEqu(char const *symName, int32_t value); struct Symbol *sym_AddEqu(char const *symName, int32_t value);
struct Symbol *sym_RedefEqu(char const *symName, int32_t value); struct Symbol *sym_RedefEqu(char const *symName, int32_t value);
struct Symbol *sym_AddSet(char const *symName, int32_t value); struct Symbol *sym_AddVar(char const *symName, int32_t value);
uint32_t sym_GetPCValue(void); uint32_t sym_GetPCValue(void);
uint32_t sym_GetConstantSymValue(struct Symbol const *sym); uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
uint32_t sym_GetConstantValue(char const *symName); uint32_t sym_GetConstantValue(char const *symName);

View File

@@ -241,11 +241,11 @@ bool yywrap(void)
/* If this is a FOR, update the symbol value */ /* If this is a FOR, update the symbol value */
if (contextStack->forName && fileInfo->iters[0] <= contextStack->nbReptIters) { if (contextStack->forName && fileInfo->iters[0] <= contextStack->nbReptIters) {
contextStack->forValue += contextStack->forStep; contextStack->forValue += contextStack->forStep;
struct Symbol *sym = sym_AddSet(contextStack->forName, struct Symbol *sym = sym_AddVar(contextStack->forName,
contextStack->forValue); contextStack->forValue);
/* This error message will refer to the current iteration */ /* This error message will refer to the current iteration */
if (sym->type != SYM_SET) if (sym->type != SYM_VAR)
fatalerror("Failed to update FOR symbol value\n"); fatalerror("Failed to update FOR symbol value\n");
} }
/* Advance to the next iteration */ /* Advance to the next iteration */
@@ -478,9 +478,9 @@ void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
dbgPrint("Running FOR(\"%s\", %" PRId32 ", %" PRId32 ", %" PRId32 ")\n", dbgPrint("Running FOR(\"%s\", %" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
symName, start, stop, step); symName, start, stop, step);
struct Symbol *sym = sym_AddSet(symName, start); struct Symbol *sym = sym_AddVar(symName, start);
if (sym->type != SYM_SET) if (sym->type != SYM_VAR)
return; return;
uint32_t count = 0; uint32_t count = 0;

View File

@@ -372,7 +372,7 @@ static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t
rpn_Number(&constExpr, constValue); rpn_Number(&constExpr, constValue);
rpn_BinaryOp(op, &newExpr, &oldExpr, &constExpr); rpn_BinaryOp(op, &newExpr, &oldExpr, &constExpr);
newValue = rpn_GetConstVal(&newExpr); newValue = rpn_GetConstVal(&newExpr);
sym_AddSet(symName, newValue); sym_AddVar(symName, newValue);
} }
static void initDsArgList(struct DsArgList *args) static void initDsArgList(struct DsArgList *args)
@@ -927,11 +927,11 @@ compoundeq : T_POP_ADDEQ { $$ = RPN_ADD; }
equ : T_LABEL T_POP_EQU const { sym_AddEqu($1, $3); } equ : T_LABEL T_POP_EQU const { sym_AddEqu($1, $3); }
; ;
set : T_LABEL T_POP_EQUAL const { sym_AddSet($1, $3); } set : T_LABEL T_POP_EQUAL const { sym_AddVar($1, $3); }
| T_LABEL compoundeq const { compoundAssignment($1, $2, $3); } | T_LABEL compoundeq const { compoundAssignment($1, $2, $3); }
| T_LABEL T_POP_SET const { | T_LABEL T_POP_SET const {
warning(WARNING_OBSOLETE, "`SET` is deprecated; use `=`\n"); warning(WARNING_OBSOLETE, "`SET` for variables is deprecated; use `=`\n");
sym_AddSet($1, $3); sym_AddVar($1, $3);
} }
; ;
@@ -940,19 +940,19 @@ equs : T_LABEL T_POP_EQUS string { sym_AddString($1, $3); }
rb : T_LABEL T_POP_RB rs_uconst { rb : T_LABEL T_POP_RB rs_uconst {
sym_AddEqu($1, sym_GetConstantValue("_RS")); sym_AddEqu($1, sym_GetConstantValue("_RS"));
sym_AddSet("_RS", sym_GetConstantValue("_RS") + $3); sym_AddVar("_RS", sym_GetConstantValue("_RS") + $3);
} }
; ;
rw : T_LABEL T_POP_RW rs_uconst { rw : T_LABEL T_POP_RW rs_uconst {
sym_AddEqu($1, sym_GetConstantValue("_RS")); sym_AddEqu($1, sym_GetConstantValue("_RS"));
sym_AddSet("_RS", sym_GetConstantValue("_RS") + 2 * $3); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 2 * $3);
} }
; ;
rl : T_LABEL T_Z80_RL rs_uconst { rl : T_LABEL T_Z80_RL rs_uconst {
sym_AddEqu($1, sym_GetConstantValue("_RS")); sym_AddEqu($1, sym_GetConstantValue("_RS"));
sym_AddSet("_RS", sym_GetConstantValue("_RS") + 4 * $3); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 4 * $3);
} }
; ;
@@ -1116,10 +1116,10 @@ macrodef : T_POP_MACRO {
} }
; ;
rsset : T_POP_RSSET uconst { sym_AddSet("_RS", $2); } rsset : T_POP_RSSET uconst { sym_AddVar("_RS", $2); }
; ;
rsreset : T_POP_RSRESET { sym_AddSet("_RS", 0); } rsreset : T_POP_RSRESET { sym_AddVar("_RS", 0); }
; ;
rs_uconst : %empty { $$ = 1; } rs_uconst : %empty { $$ = 1; }
@@ -1174,35 +1174,35 @@ def_equ : def_id T_POP_EQU const { sym_AddEqu($1, $3); }
redef_equ : redef_id T_POP_EQU const { sym_RedefEqu($1, $3); } redef_equ : redef_id T_POP_EQU const { sym_RedefEqu($1, $3); }
; ;
def_set : def_id T_POP_EQUAL const { sym_AddSet($1, $3); } def_set : def_id T_POP_EQUAL const { sym_AddVar($1, $3); }
| redef_id T_POP_EQUAL const { sym_AddSet($1, $3); } | redef_id T_POP_EQUAL const { sym_AddVar($1, $3); }
| def_id compoundeq const { compoundAssignment($1, $2, $3); } | def_id compoundeq const { compoundAssignment($1, $2, $3); }
| redef_id compoundeq const { compoundAssignment($1, $2, $3); } | redef_id compoundeq const { compoundAssignment($1, $2, $3); }
| def_id T_POP_SET const { | def_id T_POP_SET const {
warning(WARNING_OBSOLETE, "`SET` is deprecated; use `=`\n"); warning(WARNING_OBSOLETE, "`SET` for variables is deprecated; use `=`\n");
sym_AddSet($1, $3); sym_AddVar($1, $3);
} }
| redef_id T_POP_SET const { | redef_id T_POP_SET const {
warning(WARNING_OBSOLETE, "`SET` is deprecated; use `=`\n"); warning(WARNING_OBSOLETE, "`SET` for variables is deprecated; use `=`\n");
sym_AddSet($1, $3); sym_AddVar($1, $3);
} }
; ;
def_rb : def_id T_POP_RB rs_uconst { def_rb : def_id T_POP_RB rs_uconst {
sym_AddEqu($1, sym_GetConstantValue("_RS")); sym_AddEqu($1, sym_GetConstantValue("_RS"));
sym_AddSet("_RS", sym_GetConstantValue("_RS") + $3); sym_AddVar("_RS", sym_GetConstantValue("_RS") + $3);
} }
; ;
def_rw : def_id T_POP_RW rs_uconst { def_rw : def_id T_POP_RW rs_uconst {
sym_AddEqu($1, sym_GetConstantValue("_RS")); sym_AddEqu($1, sym_GetConstantValue("_RS"));
sym_AddSet("_RS", sym_GetConstantValue("_RS") + 2 * $3); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 2 * $3);
} }
; ;
def_rl : def_id T_Z80_RL rs_uconst { def_rl : def_id T_Z80_RL rs_uconst {
sym_AddEqu($1, sym_GetConstantValue("_RS")); sym_AddEqu($1, sym_GetConstantValue("_RS"));
sym_AddSet("_RS", sym_GetConstantValue("_RS") + 4 * $3); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 4 * $3);
} }
; ;
@@ -1312,13 +1312,13 @@ printv : T_POP_PRINTV const {
; ;
printi : T_POP_PRINTI const { printi : T_POP_PRINTI const {
warning(WARNING_OBSOLETE, "`PRINTI` is deprecated; use `PRINT` with `STRFMT`\n"); warning(WARNING_OBSOLETE, "`PRINTI` is deprecated; use `PRINT` with `STRFMT` \"%%d\"\n");
printf("%" PRId32, $2); printf("%" PRId32, $2);
} }
; ;
printf : T_POP_PRINTF const { printf : T_POP_PRINTF const {
warning(WARNING_OBSOLETE, "`PRINTF` is deprecated; use `PRINT` with `STRFMT`\n"); warning(WARNING_OBSOLETE, "`PRINTF` is deprecated; use `PRINT` with `STRFMT` \"%%f\"\n");
fix_Print($2); fix_Print($2);
} }
; ;

View File

@@ -77,8 +77,8 @@ within a string, called
This will paste the contents of This will paste the contents of
.Ql symbol .Ql symbol
as if they were part of the source file. as if they were part of the source file.
If it is a string equate, its characters are simply inserted as-is. If it is a string symbol, its characters are simply inserted as-is.
If it is a numerical symbol, its value is converted to hexadecimal notation with a dollar sign If it is a numeric symbol, its value is converted to hexadecimal notation with a dollar sign
.Sq $ .Sq $
prepended. prepended.
.Pp .Pp
@@ -97,7 +97,7 @@ Symbols can be
.Em interpolated .Em interpolated
even in the contexts that disable automatic even in the contexts that disable automatic
.Em expansion .Em expansion
of string equates: of string constants:
.Ql name .Ql name
will be expanded in all of will be expanded in all of
.Ql DEF({name}) , .Ql DEF({name}) ,
@@ -170,8 +170,8 @@ Examples:
.Bd -literal -offset indent .Bd -literal -offset indent
SECTION "Test", ROM0[2] SECTION "Test", ROM0[2]
X: ;\ This works with labels **whose address is known** X: ;\ This works with labels **whose address is known**
Y = 3 ;\ This also works with mutable constants Y = 3 ;\ This also works with variables
SUM equ X + Y ;\ Likewise with immutable constants SUM equ X + Y ;\ And likewise with numeric constants
; Prints "%0010 + $3 == 5" ; Prints "%0010 + $3 == 5"
PRINTLN "{#05b:X} + {#x:Y} == {d:SUM}" PRINTLN "{#05b:X} + {#x:Y} == {d:SUM}"
@@ -194,7 +194,7 @@ would be more approriate; see
further below. further below.
.Sh EXPRESSIONS .Sh EXPRESSIONS
An expression can be composed of many things. An expression can be composed of many things.
Numerical expressions are always evaluated using signed 32-bit math. Numeric expressions are always evaluated using signed 32-bit math.
Zero is considered to be the only "false" number, all non-zero numbers (including negative) are "true". Zero is considered to be the only "false" number, all non-zero numbers (including negative) are "true".
.Pp .Pp
An expression is said to be "constant" if An expression is said to be "constant" if
@@ -468,7 +468,7 @@ The result is not constant, since only RGBLINK can compute its value.
.It Fn DEF symbol Ta Returns TRUE (1) if .It Fn DEF symbol Ta Returns TRUE (1) if
.Ar symbol .Ar symbol
has been defined, FALSE (0) otherwise. has been defined, FALSE (0) otherwise.
String equates are not expanded within the parentheses. String constants are not expanded within the parentheses.
.It Fn HIGH arg Ta Returns the top 8 bits of the operand if Ar arg No is a label or constant, or the top 8-bit register if it is a 16-bit register. .It Fn HIGH arg Ta Returns the top 8 bits of the operand if Ar arg No is a label or constant, or the top 8-bit register if it is a 16-bit register.
.It Fn LOW arg Ta Returns the bottom 8 bits of the operand if Ar arg No is a label or constant, or the bottom 8-bit register if it is a 16-bit register Pq Cm AF No isn't a valid register for this function . .It Fn LOW arg Ta Returns the bottom 8 bits of the operand if Ar arg No is a label or constant, or the bottom 8-bit register if it is a 16-bit register Pq Cm AF No isn't a valid register for this function .
.It Fn ISCONST arg Ta Returns 1 if Ar arg Ap s value is known by RGBASM (e.g. if it can be an argument to .It Fn ISCONST arg Ta Returns 1 if Ar arg Ap s value is known by RGBASM (e.g. if it can be an argument to
@@ -756,12 +756,12 @@ or
.Ic FRAGMENT .Ic FRAGMENT
modifiers, as described below. modifiers, as described below.
.Ss Unionized Sections .Ss Unionized Sections
When you're tight on RAM, you may want to define overlapping blocks of variables, as explained in the When you're tight on RAM, you may want to define overlapping static memory allocations, as explained in the
.Sx Unions .Sx Unions
section. section.
However, the However, a
.Ic UNION .Ic UNION
keyword only works within a single file, which prevents e.g. defining temporary variables on a single memory area across several files. only works within a single file, so it can't be used e.g. to define temporary variables across several files, all of which use the same statically allocated memory.
Unionized sections solve this problem. Unionized sections solve this problem.
To declare an unionized section, add a To declare an unionized section, add a
.Ic UNION .Ic UNION
@@ -771,7 +771,7 @@ one; the declaration is otherwise not different.
Unionized sections follow some different rules from normal sections: Unionized sections follow some different rules from normal sections:
.Bl -bullet -offset indent .Bl -bullet -offset indent
.It .It
The same unionized section (= having the same name) can be declared several times per The same unionized section (i.e. having the same name) can be declared several times per
.Nm .Nm
invocation, and across several invocations. invocation, and across several invocations.
Different declarations are treated and merged identically whether within the same invocation, or different ones. Different declarations are treated and merged identically whether within the same invocation, or different ones.
@@ -852,15 +852,15 @@ last.
RGBDS supports several types of symbols: RGBDS supports several types of symbols:
.Bl -hang .Bl -hang
.It Sy Label .It Sy Label
Numerical symbol designating a memory location. Numeric symbol designating a memory location.
May or may not have a value known at assembly time. May or may not have a value known at assembly time.
.It Sy Constant .It Sy Constant
Numerical symbol whose value has to be known at assembly time. Numeric symbol whose value has to be known at assembly time.
.It Sy Macro .It Sy Macro
A block of A block of
.Nm .Nm
code that can be invoked later. code that can be invoked later.
.It Sy String equate .It Sy String
A text string that can be expanded later, similarly to a macro. A text string that can be expanded later, similarly to a macro.
.El .El
.Pp .Pp
@@ -987,52 +987,17 @@ and so on.
: ; referenced by "ld hl" : ; referenced by "ld hl"
dw $7FFF, $1061, $03E0, $58A5 dw $7FFF, $1061, $03E0, $58A5
.Ed .Ed
.Ss Immutable constants .Ss Variables
.Ic EQU An equal sign
is used to define numerical constant symbols.
Unlike
.Ic = .Ic =
below, constants defined this way cannot be redefined. is used to define mutable numeric symbols.
These constants can be used for unchanging values such as properties of the hardware. Unlike the other symbols described below, variables can be redefined.
.Bd -literal -offset indent This is useful for internal symbols in macros, for counters, etc.
def SCREEN_WIDTH equ 160 ;\ In pixels
def SCREEN_HEIGHT equ 144
.Ed
.Pp
Note that colons
.Ql \&:
following the name are not allowed.
.Pp
If you
.Em really
need to, the
.Ic REDEF
keyword will define or redefine a constant symbol.
This can be used, for example, to update a constant using a macro, without making it mutable in general.
.Bd -literal -offset indent
def NUM_ITEMS equ 0
MACRO add_item
redef NUM_ITEMS equ NUM_ITEMS + 1
def ITEM_{02x:NUM_ITEMS} equ \[rs]1
ENDM
add_item 1
add_item 4
add_item 9
add_item 16
assert NUM_ITEMS == 4
assert ITEM_04 == 16
.Ed
.Ss Mutable constants
.Ic =
is used to define numerical symbols like
.Ic EQU ,
but these symbols can be redefined.
This is useful for variables in macros, for counters, etc.
.Bd -literal -offset indent .Bd -literal -offset indent
DEF ARRAY_SIZE EQU 4 DEF ARRAY_SIZE EQU 4
DEF COUNT = 2 DEF COUNT = 2
DEF COUNT = 3 DEF COUNT = 3
REDEF COUNT = ARRAY_SIZE + COUNT DEF COUNT = ARRAY_SIZE + COUNT
COUNT = COUNT*2 COUNT = COUNT*2
;\ COUNT now has the value 14 ;\ COUNT now has the value 14
.Ed .Ed
@@ -1041,7 +1006,7 @@ Note that colons
.Ql \&: .Ql \&:
following the name are not allowed. following the name are not allowed.
.Pp .Pp
Mutable constants can be conveniently redefined by compound assignment operators like in C: Variables can be conveniently redefined by compound assignment operators like in C:
.Bl -column -offset indent "*= /= %=" .Bl -column -offset indent "*= /= %="
.It Sy Operator Ta Sy Meaning .It Sy Operator Ta Sy Meaning
.It Li += -= Ta Compound plus/minus .It Li += -= Ta Compound plus/minus
@@ -1059,6 +1024,42 @@ DEF y *= 2 ; y == 20
DEF y >>= 1 ; y == 10 DEF y >>= 1 ; y == 10
DEF x ^= y ; x == 1 DEF x ^= y ; x == 1
.Ed .Ed
.Ss Numeric constants
.Ic EQU
is used to define immutable numeric symbols.
Unlike
.Ic =
above, constants defined this way cannot be redefined.
These constants can be used for unchanging values such as properties of the hardware.
.Bd -literal -offset indent
def SCREEN_WIDTH equ 160 ;\ In pixels
def SCREEN_HEIGHT equ 144
.Ed
.Pp
Note that colons
.Ql \&:
following the name are not allowed.
.Pp
If you
.Em really
need to, the
.Ic REDEF
keyword will define or redefine a numeric constant symbol.
(It can also be used for variables, although it's not necessary since they are mutable.)
This can be used, for example, to update a constant using a macro, without making it mutable in general.
.Bd -literal -offset indent
def NUM_ITEMS equ 0
MACRO add_item
redef NUM_ITEMS equ NUM_ITEMS + 1
def ITEM_{02x:NUM_ITEMS} equ \[rs]1
ENDM
add_item 1
add_item 4
add_item 9
add_item 16
assert NUM_ITEMS == 4
assert ITEM_04 == 16
.Ed
.Ss Offset constants .Ss Offset constants
The RS group of commands is a handy way of defining structure offsets: The RS group of commands is a handy way of defining structure offsets:
.Bd -literal -offset indent .Bd -literal -offset indent
@@ -1096,10 +1097,10 @@ is omitted, it's assumed to be 1.
Note that colons Note that colons
.Ql \&: .Ql \&:
following the name are not allowed. following the name are not allowed.
.Ss String equates .Ss String constants
.Ic EQUS .Ic EQUS
is used to define string equate symbols. is used to define string constant symbols.
Wherever the assembler reads a string equate, it gets Wherever the assembler reads a string constant, it gets
.Em expanded : .Em expanded :
the symbol's name is replaced with its contents. the symbol's name is replaced with its contents.
If you are familiar with C, you can think of it as similar to If you are familiar with C, you can think of it as similar to
@@ -1110,7 +1111,7 @@ This expansion is disabled in a few contexts:
.Ql PURGE name , .Ql PURGE name ,
and and
.Ql MACRO name .Ql MACRO name
will not expand string equates in their names. will not expand string constants in their names.
.Bd -literal -offset indent .Bd -literal -offset indent
DEF COUNTREG EQUS "[hl+]" DEF COUNTREG EQUS "[hl+]"
ld a,COUNTREG ld a,COUNTREG
@@ -1125,7 +1126,7 @@ This will be interpreted as:
db "John" db "John"
.Ed .Ed
.Pp .Pp
String equates can also be used to define small one-line macros: String constants can also be used to define small one-line macros:
.Bd -literal -offset indent .Bd -literal -offset indent
DEF pusha EQUS "push af\[rs]npush bc\[rs]npush de\[rs]npush hl\[rs]n" DEF pusha EQUS "push af\[rs]npush bc\[rs]npush de\[rs]npush hl\[rs]n"
.Ed .Ed
@@ -1134,14 +1135,12 @@ Note that colons
.Ql \&: .Ql \&:
following the name are not allowed. following the name are not allowed.
.Pp .Pp
String equates can't be exported or imported. String constants can't be exported or imported.
.Pp .Pp
String equates, like String constants, like numeric constants, cannot be redefined.
.Ic EQU
constants, cannot be redefined.
However, the However, the
.Ic REDEF .Ic REDEF
keyword will define or redefine a string symbol. keyword will define or redefine a string constant symbol.
For example: For example:
.Bd -literal -offset indent .Bd -literal -offset indent
DEF s EQUS "Hello, " DEF s EQUS "Hello, "
@@ -1151,11 +1150,7 @@ PRINTLN "{s}\n"
.Ed .Ed
.Pp .Pp
.Sy Important note : .Sy Important note :
An When a string constant is expanded, its expansion may contain another string constant, which will be expanded as well.
.Ic EQUS
can be expanded to a string that contains another
.Ic EQUS
and it will be expanded as well.
If this creates an infinite loop, If this creates an infinite loop,
.Nm .Nm
will error out once a certain depth is will error out once a certain depth is
@@ -1164,9 +1159,7 @@ See the
.Fl r .Fl r
command-line option in command-line option in
.Xr rgbasm 1 . .Xr rgbasm 1 .
Also, a macro can contain an The same problem can occur if the expansion of a macro invokes another macro, recursively.
.Ic EQUS
which calls the same macro, which causes the same problem.
.Pp .Pp
The examples above for The examples above for
.Ql EQU , .Ql EQU ,
@@ -1178,9 +1171,7 @@ and
.Ql EQUS .Ql EQUS
all start with all start with
.Ql DEF . .Ql DEF .
(An (A variable definition may start with
.Ql =
definition may start with
.Ql REDEF .Ql REDEF
instead, since they are redefinable.) instead, since they are redefinable.)
You may use the older syntax without You may use the older syntax without
@@ -1194,7 +1185,7 @@ will treat it as a macro invocation.
Furthermore, without the Furthermore, without the
.Ql DEF .Ql DEF
keyword, keyword,
string equates may be expanded for the name. string constants may be expanded for the name.
This can lead to surprising results: This can lead to surprising results:
.Bd -literal -offset indent .Bd -literal -offset indent
X EQUS "Y" X EQUS "Y"
@@ -1218,7 +1209,7 @@ ENDM
The example above defines The example above defines
.Ql MyMacro .Ql MyMacro
as a new macro. as a new macro.
String equates are not expanded within the name of the macro. String constants are not expanded within the name of the macro.
You may use the older syntax You may use the older syntax
.Ql MyMacro: MACRO .Ql MyMacro: MACRO
instead of instead of
@@ -1226,7 +1217,7 @@ instead of
with a single colon with a single colon
.Ql \&: .Ql \&:
following the macro's name. following the macro's name.
With the older syntax, string equates may be expanded for the name. With the older syntax, string constants may be expanded for the name.
.Pp .Pp
Macros can't be exported or imported. Macros can't be exported or imported.
.Pp .Pp
@@ -1320,14 +1311,14 @@ allows you to completely remove a symbol from the symbol table as if it had neve
I can't stress this enough, I can't stress this enough,
.Sy you seriously need to know what you are doing . .Sy you seriously need to know what you are doing .
DON'T purge a symbol that you use in expressions the linker needs to calculate. DON'T purge a symbol that you use in expressions the linker needs to calculate.
When not sure, it's probably not safe to purge anything other than string symbols, macros, and constants. When not sure, it's probably not safe to purge anything other than variables, numeric or string constants, or macros.
.Bd -literal -offset indent .Bd -literal -offset indent
DEF Kamikaze EQUS "I don't want to live anymore" DEF Kamikaze EQUS "I don't want to live anymore"
DEF AOLer EQUS "Me too" DEF AOLer EQUS "Me too"
PURGE Kamikaze, AOLer PURGE Kamikaze, AOLer
.Ed .Ed
.Pp .Pp
String equates are not expanded within the symbol names. String constants are not expanded within the symbol names.
.Ss Predeclared Symbols .Ss Predeclared Symbols
The following symbols are defined by the assembler: The following symbols are defined by the assembler:
.Bl -column -offset indent "EQUS" "__ISO_8601_LOCAL__" .Bl -column -offset indent "EQUS" "__ISO_8601_LOCAL__"
@@ -1360,16 +1351,16 @@ environment variable if that is defined as a UNIX timestamp.
Refer to the spec at Refer to the spec at
.Lk https://reproducible-builds.org/docs/source-date-epoch/ . .Lk https://reproducible-builds.org/docs/source-date-epoch/ .
.Sh DEFINING DATA .Sh DEFINING DATA
.Ss Declaring variables in a RAM section .Ss Statically allocating space in RAM
.Ic DS .Ic DS
allocates a number of empty bytes. statically allocates a number of empty bytes.
This is the preferred method of allocating space in a RAM section. This is the preferred method of allocating space in a RAM section.
You can also use You can also use
.Ic DB , DW .Ic DB , DW
and and
.Ic DL .Ic DL
without any arguments instead (see without any arguments instead (see
.Sx Defining constant data .Sx Defining constant data in ROM
below). below).
.Bd -literal -offset indent .Bd -literal -offset indent
DS 42 ;\ Allocates 42 bytes DS 42 ;\ Allocates 42 bytes
@@ -1380,7 +1371,7 @@ In ROM sections, it will be filled with the value passed to the
.Fl p .Fl p
command-line option, except when using overlays with command-line option, except when using overlays with
.Fl O . .Fl O .
.Ss Defining constant data .Ss Defining constant data in ROM
.Ic DB .Ic DB
defines a list of bytes that will be stored in the final image. defines a list of bytes that will be stored in the final image.
Ideal for tables and text. Ideal for tables and text.
@@ -1465,7 +1456,7 @@ INCBIN "data.bin",78,256
The length argument is optional. The length argument is optional.
If only the start position is specified, the bytes from the start position until the end of the file will be included. If only the start position is specified, the bytes from the start position until the end of the file will be included.
.Ss Unions .Ss Unions
Unions allow multiple memory allocations to overlap, like unions in C. Unions allow multiple static memory allocations to overlap, like unions in C.
This does not increase the amount of memory available, but allows re-using the same memory region for different purposes. This does not increase the amount of memory available, but allows re-using the same memory region for different purposes.
.Pp .Pp
A union starts with a A union starts with a
@@ -1513,7 +1504,7 @@ Nesting unions is possible, with each inner union's size being considered as des
Unions may be used in any section, but inside them may only be Unions may be used in any section, but inside them may only be
.Ic DS - .Ic DS -
like commands (see like commands (see
.Sx Declaring variables in a RAM section ) . .Sx Statically allocating space in RAM ) .
.Sh THE MACRO LANGUAGE .Sh THE MACRO LANGUAGE
.Ss Invoking macros .Ss Invoking macros
You execute the macro by inserting its name. You execute the macro by inserting its name.
@@ -1600,7 +1591,7 @@ The generated code will then reset all bytes in this range.
LoopyMacro MyVars,54 LoopyMacro MyVars,54
.Ed .Ed
.Pp .Pp
Arguments are passed as string equates, although there's no need to enclose them in quotes. Arguments are passed as string constants, although there's no need to enclose them in quotes.
Thus, an expression will not be evaluated first but kind of copy-pasted. Thus, an expression will not be evaluated first but kind of copy-pasted.
This means that it's probably a very good idea to use brackets around This means that it's probably a very good idea to use brackets around
.Ic \[rs]1 .Ic \[rs]1
@@ -1649,7 +1640,7 @@ also does not need escaping because string literals work as usual inside macro a
Since there are only nine digits, you can only access the first nine macro arguments like this. Since there are only nine digits, you can only access the first nine macro arguments like this.
To use the rest, you need to put the multi-digit argument number in angle brackets, like To use the rest, you need to put the multi-digit argument number in angle brackets, like
.Ql \[rs]<10> . .Ql \[rs]<10> .
This bracketed syntax supports decimal numbers and numeric symbol names. This bracketed syntax supports decimal numbers and numeric constant symbols.
For example, For example,
.Ql \[rs]<_NARG> .Ql \[rs]<_NARG>
will get the last argument. will get the last argument.
@@ -1765,7 +1756,7 @@ Everything between
and the matching and the matching
.Ic ENDR .Ic ENDR
will be repeated for each value of a given symbol. will be repeated for each value of a given symbol.
String equates are not expanded within the symbol name. String constants are not expanded within the symbol name.
For example, this code will produce a table of squared values from 0 to 255: For example, this code will produce a table of squared values from 0 to 255:
.Bd -literal -offset indent .Bd -literal -offset indent
FOR N, 256 FOR N, 256
@@ -1879,16 +1870,18 @@ Syntax examples are given below:
.Bd -literal -offset indent .Bd -literal -offset indent
Function: Function:
xor a xor a
ASSERT LOW(Variable) == 0 ASSERT LOW(MyByte) == 0
ld h, HIGH(Variable) ld h, HIGH(MyByte)
ld l, a ld l, a
ld a, [hli] ld a, [hli]
; You can also indent this! ; You can also indent this!
ASSERT BANK(OtherFunction) == BANK(Function) ASSERT BANK(OtherFunction) == BANK(Function)
call OtherFunction call OtherFunction
; Lowercase also works ; Lowercase also works
assert Variable + 1 == OtherVariable ld hl, FirstByte
ld c, [hl] ld a, [hli]
assert FirstByte + 1 == SecondByte
ld b, [hl]
ret ret
\&.end \&.end
; If you specify one, a message will be printed ; If you specify one, a message will be printed

View File

@@ -477,13 +477,13 @@ struct Symbol *sym_RedefString(char const *symName, char const *value)
/* /*
* Alter a mutable symbol's value * Alter a mutable symbol's value
*/ */
struct Symbol *sym_AddSet(char const *symName, int32_t value) struct Symbol *sym_AddVar(char const *symName, int32_t value)
{ {
struct Symbol *sym = sym_FindExactSymbol(symName); struct Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = createsymbol(symName);
} else if (sym_IsDefined(sym) && sym->type != SYM_SET) { } else if (sym_IsDefined(sym) && sym->type != SYM_VAR) {
error("'%s' already defined as %s at ", error("'%s' already defined as %s at ",
symName, sym->type == SYM_LABEL ? "label" : "constant"); symName, sym->type == SYM_LABEL ? "label" : "constant");
dumpFilename(sym); dumpFilename(sym);
@@ -493,7 +493,7 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value)
updateSymbolFilename(sym); updateSymbolFilename(sym);
} }
sym->type = SYM_SET; sym->type = SYM_VAR;
sym->value = value; sym->value = value;
return sym; return sym;
@@ -741,7 +741,7 @@ void sym_Init(time_t now)
__FILE__Symbol->type = SYM_EQUS; __FILE__Symbol->type = SYM_EQUS;
__FILE__Symbol->strCallback = Callback__FILE__; __FILE__Symbol->strCallback = Callback__FILE__;
sym_AddSet("_RS", 0)->isBuiltin = true; sym_AddVar("_RS", 0)->isBuiltin = true;
#define addNumber(name, val) sym_AddEqu(name, val)->isBuiltin = true #define addNumber(name, val) sym_AddEqu(name, val)->isBuiltin = true
#define addString(name, val) sym_AddString(name, val)->isBuiltin = true #define addString(name, val) sym_AddString(name, val)->isBuiltin = true