mirror of
https://github.com/Museum-of-Art-and-Digital-Entertainment/macross.git
synced 2024-11-26 22:51:04 +00:00
98a36557e4
MD5 (macross.tar.gz) = 4ecb4a6e015b11fef043fe78d1eedb61
2263 lines
70 KiB
Plaintext
2263 lines
70 KiB
Plaintext
.ds [ \s+1\z[\h'1p'\z[\h'-1p'\s-1\0
|
|
.ds ] \s+1\z]\h'-1p'\z]\s-1\0
|
|
.ds Z \s+1\z]\h'-1p'\z]\h'3p'\z*\s-1\0
|
|
.TL
|
|
\s+6Macross 68000\s-6
|
|
\"Macross
|
|
.AU
|
|
an assembler for people who hate assembly language
|
|
by
|
|
Chip Morningstar
|
|
.AI
|
|
Lucasfilm Ltd. Games Division
|
|
\\*(DY
|
|
.ds LH Macross
|
|
.ds CH \\*(DY
|
|
.ds RH 68000 Version
|
|
.ds LF Lucasfilm Ltd. Proprietary Information
|
|
.ds CF - % -
|
|
.ds RF CONFIDENTIAL
|
|
.AB
|
|
This document describes the 68000 version of \fIMacross\fR, a super-duper
|
|
cross-assembler that has but to be used!
|
|
.AE
|
|
.SH
|
|
\s+3Introduction\s-3
|
|
\"Introduction
|
|
.PP
|
|
\fIMacross\fR is a generic cross assembler for a variety of different
|
|
microprocessors. This document describes the 68000 version of \fIMacross\fR.
|
|
\fIMacross\fR differs from many macro assemblers in that it provides a number
|
|
of ``higher level'' constructs not traditionally found in assembly language.
|
|
These include block-structured flow-of-control statements (\fBif\fR,
|
|
\fBwhile\fR, etc.) and the ability to define record-oriented data structures
|
|
(\fBstruct\fR). In addition, it contains a powerful macro capability that is
|
|
based on syntactic structural manipulations rather than simple text
|
|
substitution. \fIMacross\fR is, in fact, a complete block-structured
|
|
programming language in its own right which is interpreted at assembly time.
|
|
.SH
|
|
\s+3General Form of \fIMacross\fP Statements\s-3
|
|
\"General Form of \fIMacross\fP Statements
|
|
.PP
|
|
Stylistically, much of \fIMacross\fR is patterned after \fBC\fR. In
|
|
particular, the form of many keywords and of block structured entities is
|
|
derived from \fBC\fR. Unlike \fBC\fR however, \fIMacross\fR follows the
|
|
convention of more traditional assemblers that statements are delimited by
|
|
line boundaries (i.e., one statement per line, with the end of a line ending a
|
|
statement).
|
|
.PP
|
|
In general, spaces and tabs are treated as whitespace characters and are
|
|
ignored. Therefore, such characters may be used as the assembly language
|
|
programmer desires to format his or her program according to personal taste.
|
|
For the convenience of the programmer, \fIMacross\fR relaxes the syntax rule
|
|
that newlines always end a statement: newlines may also be treated as
|
|
whitespace characters (again, for purposes of formatting) in places where it
|
|
would be syntactically unambiguous to do so (i.e., where a statement obviously
|
|
cannot terminate, such as after a comma). For example:
|
|
.nf
|
|
|
|
\fBbyte 1, 2, 3, 4,
|
|
5, 6, 7, 8\fR
|
|
|
|
.fi
|
|
is allowed and is equivalent to
|
|
.nf
|
|
|
|
\fBbyte 1, 2, 3, 4, 5, 6, 7, 8
|
|
|
|
.fi
|
|
.PP
|
|
Comments begin with a semicolon (``\fB;\fR'') and continue to the end of the
|
|
line, as is common in many assemblers. In addition, \fIMacross\fR supports
|
|
\fBC\fR style comments bracketed by ``\fB/*\fR'' and ``\fB*/\fR''.
|
|
.PP
|
|
As with most assemblers, \fIMacross\fR statements are allowed to begin with a
|
|
label (or several labels, if you like). A label is denoted by an identifier
|
|
followed by a colon (``\fB:\fR''). There is no requirement that the label
|
|
start in column 1, or anything like that. Labels, if present, merely must
|
|
precede anything else in a statement.
|
|
.PP
|
|
An identifier is just what you'd expect from all your years of programming
|
|
experience: a string of letters and digits that must begin with a letter. As
|
|
is traditional in Unix*
|
|
.FS *
|
|
Unix is a footnote of Bell Laboratories.
|
|
.FE
|
|
land, the underscore character (``\fB_\fR'') is considered to be a letter
|
|
(smacks of hubris that, but tradition is tradition). Departing from Unix
|
|
tradition, upper- and lower-case characters are not distinct from each other
|
|
for purposes of distinguishing identifiers. If you use mixed case for
|
|
stylistic reasons, \fIMacross\fR will remember the case of the letters in an
|
|
identifier when it was first defined, so that symbol table dumps and
|
|
cross-reference listings will retain whatever case usage style you've adopted.
|
|
There is, in principle, no restriction imposed upon the length of identifiers.
|
|
.SH
|
|
\s+3The Language\s-3
|
|
.PP
|
|
In what follows, things in \fBboldface\fR are keywords and characters that are
|
|
used literally. Things in \fIitalics\fR are other kinds of syntactic
|
|
entities. Double brackets (``\*['' and ``\*]'') enclose things that are
|
|
optional, while brackets followed by an asterisk (``*'') enclose things that
|
|
may be optionally repeated zero or more times.
|
|
.NH 1
|
|
The Instruction Statement
|
|
.PP
|
|
The most elementary \fIMacross\fR statement is the instruction statement,
|
|
wherein the programmer specifies a machine instruction to be assembled. The
|
|
instruction statement is
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fIopcode\fR \*[ \fIoperand\fR \*[ \fB,\fR \fIoperand\fR \*Z \*]
|
|
|
|
.fi
|
|
just like every assembler ever made (except \fBa65\fR, of course).
|
|
\fIOpcode\fR is an identifier which is either a machine instruction mnemonic
|
|
(a list of which mnemonics are accepted by \fIMacross\fR is given in
|
|
\fBAppendix B\fR at the end of this document) or a macro name. For example:
|
|
.nf
|
|
|
|
\fBandb foobar, d3\fR
|
|
\fBsomeMacro foo, bar, baz, bletch\fR
|
|
|
|
.fi
|
|
.PP
|
|
The operands of an instruction may be any of the various types of operands
|
|
allowed by the various address modes of the target processor. In the case
|
|
of the 68000, these are:
|
|
.NH 2
|
|
\fRRegister mode
|
|
.PP
|
|
Register operands take one of the forms
|
|
.nf
|
|
|
|
\fBd\fIn\fR
|
|
\fBa\fIn\fR
|
|
\fBsp\fR
|
|
|
|
.fi
|
|
where \fIn\fR is a digit from \fB0\fR to \fB7\fR. \fBd\fIn\fR of course
|
|
represents a data register and \fBa\fIn\fR represents an address register.
|
|
\fBsp\fR is equivalent to \fBa7\fR.
|
|
.NH 2
|
|
\fRRegister indirect mode
|
|
.PP
|
|
Register indirect mode operands take the form
|
|
.nf
|
|
|
|
\fB\s-1[\s+1\fBa\fIn\fB\s-1]\s+1\fR
|
|
|
|
.fi
|
|
where \fBa\fIn\fR is some address register.
|
|
.NH 2
|
|
\fRPostincrement mode
|
|
.PP
|
|
Postincrement mode operands take the form
|
|
.nf
|
|
|
|
\fB\s-1[\s+1\fBa\fIn\fB\s-1]\s+1+\fR
|
|
|
|
.fi
|
|
where \fBa\fIn\fR is some address register.
|
|
.NH 2
|
|
\fRPredecrement mode
|
|
.PP
|
|
Predecrement mode operands take the form
|
|
.nf
|
|
|
|
\fB-\s-1[\s+1\fBa\fIn\fB\s-1]\s+1\fR
|
|
|
|
.fi
|
|
where \fBa\fIn\fR is some address register.
|
|
.NH 2
|
|
\fRNormal mode
|
|
.PP
|
|
Normal mode addresses take the form
|
|
.nf
|
|
|
|
\fIexpression\fR
|
|
|
|
.fi
|
|
and are used in a couple of different ways. First, normal mode addresses are
|
|
used by instructions that require relative addresses (such as branch
|
|
instructions; the offset is computed automatically by \fIMacross\fR). Second,
|
|
the normal mode form of addresses is a shorthand way of refering to locations
|
|
for which \fIMacross\fR selects an appropriate address mode to use (PC
|
|
relative if it can, otherwise absolute).
|
|
.NH 2
|
|
\fRAbsolute mode
|
|
.PP
|
|
Absolute addresses take one of these two forms
|
|
.nf
|
|
|
|
\fIexpression\fB . w\fR
|
|
\fIexpression\fB . l\fR
|
|
|
|
.fi
|
|
with the \fBw\fR or \fBl\fR indicating whether to generate a short (16 bit) or
|
|
a long (32 bit) address.
|
|
.NH 2
|
|
\fRImmediate mode
|
|
.PP
|
|
Immediate mode operands take the form
|
|
.nf
|
|
|
|
\fB#\fR \fIexpression\fR
|
|
|
|
.fi
|
|
Generally speaking, in the 68000 immediate mode operands are restricted to
|
|
sixteen bit quantities. Depending upon the particular instruction involved,
|
|
the size may be even more restricted. \fIMacross\fR will give an error
|
|
message if the operand value is larger than allowed.
|
|
.NH 2
|
|
\fRDisplacement mode
|
|
.PP
|
|
Displacement mode operands take the form
|
|
.nf
|
|
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBa\fIn\fR \fB\s-1]\s+1\fR
|
|
|
|
.fi
|
|
where \fIexpression\fR is an offset off of the address register \fBa\fIn\fR.
|
|
These displacement values are limited to 16 bit quantities in the 68000.
|
|
.PP
|
|
An alternate form of displacment mode addressing which is supported by
|
|
\fIMacross\fR allows the symbolic selection of a field of a \fBstruct\fR
|
|
pointed to by an address register
|
|
.nf
|
|
|
|
\fBa\fIn\fR \fB.\fR \fIidentifier\fR \*[ \fB.\fR \fIidentifier\fR \*Z
|
|
|
|
.fi
|
|
This is explained in greater detail in the sections on \fBstruct\fRs and
|
|
expressions below.
|
|
.NH 2
|
|
\fRIndexed mode
|
|
.PP
|
|
Indexed mode addressing is specified by operands of the form
|
|
.nf
|
|
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBa\fIn\fR \fB,\fR \fIrn\fR \fB. w \s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBa\fIn\fR \fB,\fR \fIrn\fR \fB. l \s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBa\fIn\fR \fB,\fR \fIrn\fR \fB\s-1]\s+1\fR
|
|
|
|
.fi
|
|
where \fIexpression\fR is an offset off of address register \fBa\fIn\fR and
|
|
another register \fIrn\fR which may be any data or address register. The
|
|
Offset is restricted to an 8-bit quantity. The \fBw\fR or \fBl\fR indicates
|
|
whether the offset value in \fIrn\fR is to be taken as a word (16 bit) value
|
|
or as a long (32 bit) value (if omitted it defaults to long).
|
|
.PP
|
|
As with ordinary displacment addressing, there is a form of indexed addressing
|
|
which uses \fBstruct\fR fields
|
|
.nf
|
|
|
|
\fBa\fIn\fR \fB\s-1[\s+1\fR \fIrn\fR \fB. w \fB\s-1]\s+1\fR \fB.\fR \fIidentifier\fR \*[ \fB.\fR \fIidentifier\fR \*Z
|
|
\fBa\fIn\fR \fB\s-1[\s+1\fR \fIrn\fR \fB. l \fB\s-1]\s+1\fR \fB.\fR \fIidentifier\fR \*[ \fB.\fR \fIidentifier\fR \*Z
|
|
\fBa\fIn\fR \fB\s-1[\s+1\fR \fIrn\fR \fB\s-1]\s+1\fR \fB.\fR \fIidentifier\fR \*[ \fB.\fR \fIidentifier\fR \*Z
|
|
|
|
.fi
|
|
.NH 2
|
|
\fRProgram counter displacement mode
|
|
.PP
|
|
Program counter displacement mode operands take the form
|
|
.nf
|
|
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBpc\fR \fB\s-1]\s+1\fR
|
|
|
|
.fi
|
|
where \fIexpression\fR is an offset off of the program counter. These
|
|
displacement values are limited to 16 bit quantities in the 68000.
|
|
.NH 2
|
|
\fRProgram counter indexed mode
|
|
.PP
|
|
Program counter indexed mode addressing is specified by operands of the form
|
|
.nf
|
|
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBpc\fR \fB,\fR \fIrn\fR \fB. w \s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBpc\fR \fB,\fR \fIrn\fR \fB. l \s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBpc\fR \fB,\fR \fIrn\fR \fB\s-1]\s+1\fR
|
|
|
|
.fi
|
|
where \fIexpression\fR is an offset off of the program counter and another
|
|
register \fIrn\fR which may be any data or address register. The Offset is
|
|
restricted to an 8-bit quantity. The \fBw\fR or \fBl\fR indicates whether the
|
|
offset value in \fIrn\fR is to be taken as a word (16 bit) value or as a long
|
|
(32 bit) value (if omitted it defaults to long).
|
|
.NH 2
|
|
\fRControl register mode
|
|
.PP
|
|
The various control register of the 68000 are sometimes used as operands
|
|
.nf
|
|
|
|
\fBccr\fR
|
|
\fBsr\fR
|
|
\fBusp\fR
|
|
\fBsfc\fR
|
|
\fBdfc\fR
|
|
\fBvbr\fR
|
|
|
|
.fi
|
|
where \fBccr\fR represents the condition code register, \fBsr\fR represents
|
|
the status register, \fBusp\fR represents the user stack pointer, \fBsfc\fR
|
|
represents the source function code register, \fBdfc\fR represents the
|
|
destination function code register, and \fBvbr\fR represents the vector base
|
|
register.
|
|
.NH 2
|
|
\fRText operands
|
|
.PP
|
|
For the sake of macros, text strings may also be used as operands
|
|
.nf
|
|
|
|
\fB"\fIany string you like\fB"\fR
|
|
|
|
.fi
|
|
The same conventions regarding escaped characters (using ``\fB\\\fR'') that
|
|
are followed by \fBC\fR are followed by \fIMacross\fR. These are documented
|
|
in \fBAppendix F\fR. Note that on many target machines the codes that these
|
|
escape sequences stand for are meaningless. They are provided primarily as a
|
|
convenience for writing calls to \fBprintf()\fR.
|
|
.NH 1
|
|
The Flow of Control Statements
|
|
.PP
|
|
\fIMacross\fR provides a number of statements which allow program flow of
|
|
control to be specified in a \fBC\fR-like block structured fashion. This
|
|
include a conditional execution statement (\fBif\fR) and three conditional
|
|
loop statements (\fBwhile\fR, \fBdo-while\fR and \fBdo-until\fR). These
|
|
statements assemble into the appropriate conditional branches and jumps to
|
|
realize the desired construct.
|
|
.NH 2
|
|
If\fR statement
|
|
.PP
|
|
The \fBif\fR statement has the following form
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBif\fR \fB(\fR \fIcondition\fR \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \*[ \fBelseif\fR \fB(\fR \fIcondition\fR \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \*Z \*[ \fBelse\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \*]
|
|
|
|
.fi
|
|
\fIcondition\fR is either the name of one of the target processor's hardware
|
|
condition codes such as can be tested for in a conditional branch instruction
|
|
(e.g., \fBcarry\fR, \fBoverflow\fR, etc.\*- the complete list is in
|
|
\fBAppendix C\fR) or one either of these negated using the ``logical not''
|
|
operator (``\fB!\fR''). The condition is used to determine the appropriate
|
|
type of branch instruction to use. For example,
|
|
.nf
|
|
|
|
\fBif (overflow) {\fR
|
|
\fIstatements-1\fR
|
|
\fB} elseif (carry) {\fR
|
|
\fIstatements-2\fR
|
|
\fB} else {\fR
|
|
\fIstatements-3\fR
|
|
\fB}\fR
|
|
|
|
.fi
|
|
expands into this (the labels are made up for illustrative purposes only):
|
|
.nf
|
|
|
|
\fBbvc temp1
|
|
\fIstatements-1
|
|
\fBjmp temp3
|
|
temp1: bcc temp2
|
|
\fIstatements-3
|
|
\fBjmp temp3
|
|
temp2: \fIstatements-3
|
|
\fBtemp3: \fIwhatever follows\fR
|
|
|
|
.fi
|
|
The keyword \fBelseif\fR may be used as shown, or specified as two separate
|
|
keywords, \fBelse if\fR, depending on the programmer's whim.
|
|
.NH 2
|
|
While\fR statement
|
|
.PP
|
|
The \fBwhile\fR statement has the following form
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBwhile\fR \fB(\fR \fIcondition\fR \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR
|
|
|
|
.fi
|
|
\fIcondition\fR is as described above for the \fBif\fR statement. An example
|
|
of the \fBwhile\fR statement would be
|
|
.nf
|
|
|
|
\fBwhile (!carry) {\fR
|
|
\fIstatements\fR
|
|
\fB}\fR
|
|
|
|
.fi
|
|
which would turn into
|
|
.nf
|
|
|
|
\fBtemp2: bcs temp1
|
|
\fIstatements
|
|
\fBjmp temp2
|
|
temp1: \fIwhatever follows\fR
|
|
|
|
.fi
|
|
.NH 2
|
|
Do-while\fR statement
|
|
.PP
|
|
The \fBdo-while\fR statement is similar to the \fBwhile\fR statement except
|
|
that the condition is tested at the bottom of the loop. It has the form
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBdo\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \fBwhile\fR \fB(\fR \fIcondition\fR \fB)\fR
|
|
|
|
.fi
|
|
For example
|
|
.nf
|
|
|
|
\fBdo {\fR
|
|
\fIstatements\fR
|
|
\fB} while (equal)\fR
|
|
|
|
.fi
|
|
which is equivalent to
|
|
.nf
|
|
|
|
\fBtemp: \fIstatements
|
|
\fBbeq temp\fR
|
|
|
|
.fi
|
|
.NH 2
|
|
Do-until\fR statement
|
|
.PP
|
|
The \fBdo-until\fR statement is the same as the \fBdo-while\fR statement
|
|
except that the sense of the condition is negated. It has the form
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBdo\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \fBuntil\fR \fB(\fR \fIcondition\fR \fB)\fR
|
|
|
|
.fi
|
|
For example
|
|
.nf
|
|
|
|
\fBdo {\fR
|
|
\fIstatements\fR
|
|
\fB} until (equal)\fR
|
|
|
|
.fi
|
|
which is equivalent to
|
|
.nf
|
|
|
|
\fBtemp: \fIstatements
|
|
\fBbne temp\fR
|
|
|
|
.fi
|
|
.NH 1
|
|
The Data Statements
|
|
.PP
|
|
The data statements allow the allocation of memory space and the storage of
|
|
constant data. These statements are like the ones found in most assemblers.
|
|
There are several different forms, each for a different type of data.
|
|
.NH 2
|
|
Block\fR statement
|
|
.PP
|
|
The \fBblock\fR statement allocates blocks of memory without initializing the
|
|
bytes to any particular value (actually, the loader will in all likelihood
|
|
initialize these to 0, but it is probably not really wise to rely on this).
|
|
It has the form
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBblock\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
|
|
.fi
|
|
The \fIexpression\fRs are the sizes of the blocks to reserve, expressed in
|
|
bytes.
|
|
.NH 2
|
|
Align\fR statement
|
|
.PP
|
|
The \fBalign\fR statement aligns the current location counter to an integer
|
|
multiple of some value (e.g., to align with a word boundary). It has the form
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBalign\fR \fIexpression\fR
|
|
|
|
.fi
|
|
The \fIexpression\fR is the multiple to which the current location counter is
|
|
to be aligned. For example,
|
|
.nf
|
|
|
|
\fBalign 2\fR
|
|
|
|
.fi
|
|
would align the current location to a word boundary, while
|
|
.nf
|
|
|
|
\fBalign 0x100\fR
|
|
|
|
.fi
|
|
would align to a page boundary.
|
|
.NH 2
|
|
Constrain\fR statement
|
|
.PP
|
|
The \fBconstrain\fR statement provides a means of constraining a portion of
|
|
code or data to be located within a region of memory bounded by addresses of
|
|
integer multiples of some value (e.g., within a page). Its form is
|
|
.nf
|
|
|
|
\fBconstrain\fR \fB(\fR \fIboundary\fR \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR
|
|
|
|
.fi
|
|
\fIBoundary\fR may be any expression which evaluates to a number. The
|
|
\fIstatement\fRs are assembled normally. If assembling in absolute mode, an
|
|
error message is issued if the current location counter crosses an integer
|
|
multiple of \fIboundary\fR. If assembling in relocatable mode, information
|
|
about the constraint will be output in the object file and the contents of the
|
|
constrained block will be relocated as needed to satisfy the constraint (note
|
|
that this means that it is unsafe to assume that the things in the assembly
|
|
source immediately before the \fBconstrain\fR statement, the contents of the
|
|
constrain block itself, and the things in the assembly source immediately
|
|
after the \fBconstrain\fR statement will be located in contiguous locations in
|
|
the eventual target machine address space). For example,
|
|
.nf
|
|
|
|
\fBconstrain (0x100) {\fR
|
|
\fIstatements\fR
|
|
\fB}\fR
|
|
|
|
.fi
|
|
constrains the given statements to all fit within a page.
|
|
.NH 2
|
|
Word\fR statement
|
|
.PP
|
|
The \fBword\fR statement allocates words, i.e., two byte chunks, of memory.
|
|
It takes the form
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBword\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
|
|
.fi
|
|
The \fIexpression\fRs must evaluate to quantities that can be contained in 16
|
|
bits, of course. For example,
|
|
.nf
|
|
|
|
\fBword 0x1234, foobar\fR
|
|
|
|
.fi
|
|
would allocate two words, the first of which would be initialized to the
|
|
hexadecimal value 0x1234 and the second to whatever the value of \fBfoobar\fR
|
|
is.
|
|
.NH 2
|
|
Dbyte\fR statement
|
|
.PP
|
|
The \fBdbyte\fR statement is just like the \fBword\fR statement, except that
|
|
the word is byte-swapped in memory. Its form is
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBdbyte\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
.fi
|
|
.NH 2
|
|
Long\fR statement
|
|
.PP
|
|
The \fBlong\fR statement allocates longwords, i.e., four byte chunks, of
|
|
memory. It takes the form
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBlong\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
|
|
.fi
|
|
The \fIexpression\fRs must evaluate to quantities that can be contained in 32
|
|
bits, of course. For example,
|
|
.nf
|
|
|
|
\fBword 0x12345678, foobar\fR
|
|
|
|
.fi
|
|
would allocate two longwords, the first of which would be initialized to the
|
|
hexadecimal value 0x12345678 and the second to whatever the value of
|
|
\fBfoobar\fR is.
|
|
.NH 2
|
|
Byte\fR statement
|
|
.PP
|
|
The \fBbyte\fR statement is similar to the \fBword\fR and \fBdbyte\fR
|
|
statements, except that it allocates single byte chunks. Its form is
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBbyte\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
|
|
.fi
|
|
An \fIexpression\fR, in this case, is either an ordinary expression (see
|
|
\fBExpressions\fR, below) which must evaluate to an 8-bit quantity, indicating
|
|
the value for a single byte to be reserved, or a string (see above, under the
|
|
discussion of text operands), indicating that the characters in the string
|
|
should be placed in memory at the current location.
|
|
.NH 2
|
|
String\fR statement
|
|
.PP
|
|
The \fBstring\fR statement is much like the \fBbyte\fR statement, except that
|
|
the values indicated are followed in memory by a zero byte. This enables the
|
|
convenient declaration and allocation of NULL terminated character strings.
|
|
This feature is of little use in the 68000 version of \fIMacross\fR but is
|
|
provided for compatability with future versions targeted at more sophisticated
|
|
processors. The form of the \fBstring\fR statement is
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBstring\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
.fi
|
|
.NH 2
|
|
Struct\fR statement
|
|
.PP
|
|
The \fBstruct\fR statement enables the declaration and allocation of
|
|
record-oriented data structures. There are two forms of the \fBstruct\fR
|
|
statement, the first of which declares a \fBstruct\fR record type, and the
|
|
second of which causes space to be set aside in memory for a \fBstruct\fR that
|
|
has already been declared. The form of the first type of \fBstruct\fR
|
|
statement is
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBstruct\fR \fB{\fR
|
|
\*[ \fIdataStatement\fR \*Z
|
|
\fB}\fR \fIname\fR
|
|
|
|
.fi
|
|
\fIdataStatement\fRs are any of the data statements described in this section
|
|
(section 3). \fIName\fR becomes the name of the \fBstruct\fR. Any labels
|
|
inside the \fBstruct\fR become \fIfields\fR of the data structure which may be
|
|
referred to later in expressions using the ``\fB.\fR'' operator, as in
|
|
\fBC\fR. A more complete description of the semantics of \fBstruct\fRs is
|
|
given in the section below on expressions.
|
|
.PP
|
|
The first form of the \fBstruct\fR statement, called a ``\fBstruct\fR
|
|
definition'', lays out the constituent parts of a data structure and gives
|
|
those names to those parts. The second form of the \fBstruct\fR statement,
|
|
called a ``\fBstruct\fR instantiation'',
|
|
.nf
|
|
|
|
\*[ \fIlabel\fR \*Z \fBstruct\fR \fIname\fR
|
|
|
|
.fi
|
|
causes storage for the \fBstruct\fR named by \fIname\fR to be allocated. A
|
|
\fBstruct\fR definition \fImay not\fR contain another \fBstruct\fR definition,
|
|
but it \fImay\fR contain a \fBstruct\fR instantiation. For example,
|
|
.nf
|
|
|
|
\fBstruct {
|
|
pointer: block 2
|
|
class: block 1
|
|
} fooThing\fR
|
|
|
|
.fi
|
|
would create a \fBstruct\fR called \fBfooThing\fR. Then,
|
|
.nf
|
|
|
|
\fBfooLabel: struct fooThing\fR
|
|
|
|
.fi
|
|
would allocate one at the current location at the address labeled
|
|
\fBfooLabel\fR. This could then be used as follows:
|
|
.nf
|
|
|
|
\fBandb fooLabel.class, d0
|
|
jmp fooLabel.pointer\fR
|
|
|
|
.fi
|
|
which would AND \fBd0\fR with the \fBclass\fR field of the \fBstruct\fR and
|
|
then jump to wherever the \fBpointer\fR field pointed to. If the \fBx\fR
|
|
address register \fBa4\fR already contained the address of this \fBstruct\fR,
|
|
then one could say
|
|
.nf
|
|
|
|
\fBandb a4.class, d0\fR
|
|
|
|
.fi
|
|
.NH 1
|
|
The Symbol Definition Statements
|
|
.PP
|
|
The various symbol definition statements allow the declaration of symbolic
|
|
variables and values and the definition of macros and functions.
|
|
.NH 2
|
|
Define\fR statement
|
|
.PP
|
|
The \fBdefine\fR statement enables the programmer to create symbolic names for
|
|
values. It has two forms. The first
|
|
.nf
|
|
|
|
\fBdefine\fR \fIsymbolname\fR
|
|
|
|
.fi
|
|
creates a new symbol, \fIsymbolname\fR (an identifier), and gives it the
|
|
special value \fBunassigned\fR. Any attempt to take the value of an
|
|
unassigned symbol will cause an error message from the assembler. The symbol
|
|
will, however, cause the \fBisDefined()\fR built-in function (see
|
|
\fBExpressions\fR, below) to return \fBTRUE\fR if passed as an argument. It
|
|
is also an error to \fBdefine\fR a symbol that has already been \fBdefine\fRd.
|
|
.PP
|
|
The second form of the \fBdefine\fR statement
|
|
.nf
|
|
|
|
\fBdefine\fR \fIsymbolname\fR \fB=\fR \fIexpression\fR
|
|
|
|
.fi
|
|
creates the symbol and gives it the value obtained by evaluating
|
|
\fIexpression\fR (see \fBExpressions\fR, below). Actually, what \fBdefine\fR
|
|
does is create a symbolic name for \fIexpression\fR and the save this
|
|
expression away in a secret place. This means that symbols in
|
|
\fIexpression\fR may be forward references, e.g., labels that haven't been
|
|
encountered yet. It is also possible to forward reference to symbols that are
|
|
defined by future \fBdefine\fR statements, for example:
|
|
.nf
|
|
|
|
\fBdefine foo = bar + 2
|
|
define bar = 47\fR
|
|
|
|
.fi
|
|
effectively defines \fBfoo\fR to be \fB49\fR. Beware, however, as there is no
|
|
way for the assembler to detect mutually recursive references of this sort, so
|
|
that
|
|
.nf
|
|
|
|
\fBdefine foo = bar + 2
|
|
define bar = foo + 2\fR
|
|
|
|
.fi
|
|
will be happily swallowed without complaint, until you actually try to use
|
|
\fBfoo\fR or \fBbar\fR in an instruction, whereupon \fIMacross\fR's expression
|
|
evaluator will go into infinite recursion until it runs out of stack space and
|
|
crashes the assembler (it looks to see what \fBfoo\fR is and sees that it's
|
|
\fBbar + 2\fR, so it looks to see what \fBbar\fR and see that it's \fBfoo +
|
|
2\fR, so it looks to see what \fBfoo\fR is... To have the assembler detect
|
|
and signal this error would, in the general case, add much complication and
|
|
inefficiency (read: make your programs assemble a lot more slowly) for little
|
|
return).
|
|
.PP
|
|
The scope of symbols defined in either of these two ways extends in time from
|
|
the definition itself to the end of the assembly.
|
|
.NH 2
|
|
Variable\fR statement
|
|
.PP
|
|
The \fBvariable\fR statement enables the programmer to declare symbolic
|
|
variables for future use. Similar to the \fBdefine\fR statement, it has two
|
|
forms. The first
|
|
.nf
|
|
|
|
\fBvariable\fR \fIsymbolname\fR
|
|
|
|
.fi
|
|
creates a variable named \fIsymbolname\fR and gives it the special value
|
|
\fBunassigned\fR, just like the analogous \fBdefine\fR statement.
|
|
.PP
|
|
The second form of the \fBvariable\fR statement
|
|
.nf
|
|
|
|
\fBvariable\fR \fIsymbolname\fR \fB=\fR \fIexpression\fR
|
|
|
|
.fi
|
|
creates the variable and gives it the value obtained by evaluating
|
|
\fIexpression\fR. The scope of variables defined in either of these two ways
|
|
extends from the \fBvariable\fR statement itself to the end of the assembly
|
|
(i.e., the variable is global).
|
|
.PP
|
|
The difference between the \fBdefine\fR statement and the \fBvariable\fR
|
|
statement is that the \fBdefine\fR statement creates what is in essence a
|
|
constant whereas the \fBvariable\fR statement creates a true variable. The
|
|
value of a variable may change (e.g., it may be assigned to) during the course
|
|
of assembly. In addition, the expression which establishes a symbol's value
|
|
in a \fBdefine\fR statement may contain forward references (i.e., labels whose
|
|
values are unknown because they haven't been encountered yet) whereas the
|
|
expression assigning an initial value to a variable must be made up of terms
|
|
all of whose values are known at the time the \fBvariable\fR statement is
|
|
encountered in the assembly.
|
|
.NH 2
|
|
Macro\fR statement
|
|
.PP
|
|
The \fBmacro\fR statement is used to define macros (surprise!). Its syntax is
|
|
.nf
|
|
|
|
\fBmacro\fR \fImacroname\fR \*[ \fIargumentname\fR \*[ \fB,\fR \fIargumentname\fR \*Z \*] \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR
|
|
|
|
.fi
|
|
where \fImacroname\fR is just that and the \fIargumentname\fRs are identifiers
|
|
corresponding to the formal parameters of the macro (in the classical
|
|
fashion). When the macro is called, the call arguments are bound to these
|
|
symbols and then \fIMacross\fR assembles the \fIstatement\fRs which form the
|
|
macro body. The scope of these symbols is limited to the inside of the macro
|
|
body and their values go away when the macro expansion is completed. The
|
|
\fIstatement\fRs may be any valid \fIMacross\fR statements except for
|
|
\fBmacro\fR statements and \fBfunction\fR statements (i.e., macro and function
|
|
definitions may not be nested).
|
|
.PP
|
|
Statement labels used inside macros can be made local to the macro by
|
|
preceding the label identifier with a dollar sign (``\fB$\fR''). For
|
|
example,
|
|
.nf
|
|
|
|
\fBmacro fooMac arg {
|
|
jmp $foo
|
|
word arg
|
|
$foo: nop
|
|
}\fR
|
|
|
|
.fi
|
|
defines a macro named \fBfooMac\fR that emits a word of data that gets jumped
|
|
over. The label \fB$foo\fR is local to the macro: both the reference to it
|
|
in the first line of the macro and its definition on the third will only be
|
|
seen inside the macro. Each time the macro is called, the \fBjmp\fR will
|
|
refer to the location two instructions ahead, and any other macros that might
|
|
contain \fB$foo\fR will not affect this nor will they be affected by this.
|
|
.NH 2
|
|
Function\fR statement
|
|
.PP
|
|
The \fBfunction\fR statement is used to define functions. Its syntax is
|
|
.nf
|
|
|
|
\fBfunction\fR \fIfuncname\fR \fB(\fR \*[ \fIargumentname\fR \*[ \fB,\fR \fIargumentname\fR \*Z \*] \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR
|
|
|
|
.fi
|
|
where \fIfuncname\fR is the name of the function and the \fIargumentname\fRs
|
|
are identifiers corresponding to the formal parameters of the function. When
|
|
the function is called, the call arguments are evaluated and then bound to
|
|
these symbols and then \fIMacross\fR assembles the \fIstatement\fRs which form
|
|
the function body. The scope of these symbols is limited to the inside of the
|
|
function body and their values go away when the function evaluation is
|
|
completed. As with macro definitions, the \fIstatement\fRs may be any valid
|
|
\fIMacross\fR statements except for the \fBmacro\fR and \fBfunction\fR
|
|
statements. A function may return a value using the \fBfreturn\fR statement,
|
|
which is described below.
|
|
.NH 2
|
|
Undefine\fR statement
|
|
.PP
|
|
The \fBundefine\fR statement allows symbol and macro definitions to be removed
|
|
from \fIMacross\fR' symbol table. It takes the form
|
|
.nf
|
|
|
|
\fBundefine\fR \fIsymbolname\fR \*[ \fB,\fR \fIsymbolname\fR \*Z
|
|
|
|
.fi
|
|
The named symbols go away as if they never were \*- they are free to be
|
|
defined again and the \fBisDefined()\fR built-in function will return
|
|
\fBFALSE\fR if passed one of them as an argument.
|
|
.NH 1
|
|
Macro Body Statements
|
|
.PP
|
|
\fIMacross\fR provides several statements which are primarily intended to
|
|
manage the flow of control (or, rather, the ``flow of assembly'') within a
|
|
macro or function definition. Some of these statements are analogs to the
|
|
flow of control statements described above in section 2. However, one should
|
|
keep in mind that these statements are executed interpretively at assembly
|
|
time, whereas the previously described statements result in machine code in
|
|
the target-processor-executable output of the assembly process.
|
|
.PP
|
|
Although these statements are intended primarily for use within macros and
|
|
functions, their use is not restricted and they may be used at any point in a
|
|
program. In particular, the \fBmif\fR statement (to be described shortly) is
|
|
the means by which conditional assembly may be realized.
|
|
.NH 2
|
|
\fRBlocks
|
|
.PP
|
|
The construct
|
|
.nf
|
|
|
|
\fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR
|
|
|
|
.fi
|
|
is called a \fIblock\fR and is in fact a valid \fIMacross\fR statement type in
|
|
its own right. Blocks are used extensively in \fIMacross\fR to form the
|
|
bodies of flow-of-control statements, flow-of-assembly statements and macros.
|
|
.NH 2
|
|
Mdefine\fR statement
|
|
.PP
|
|
The \fBmdefine\fR statement
|
|
.nf
|
|
|
|
\fBmdefine\fR \fIsymbolname\fR
|
|
or
|
|
\fBmdefine\fR \fIsymbolname\fR \fB=\fR \fIexpression\fR
|
|
|
|
.fi
|
|
operates like (and is syntactically congruent with) the \fBdefine\fR
|
|
statement, except that the scope of the symbol definition is restricted to the
|
|
body block of the macro or function in which the \fBmdefine\fR appears. The
|
|
symbol definition is invisible outside that block, though it \fIis\fR visible
|
|
inside any blocks that may themselves be contained within the macro or
|
|
function.
|
|
.NH 2
|
|
Mvariable\fR statement
|
|
.PP
|
|
The \fBmvariable\fR statement
|
|
.nf
|
|
|
|
\fBmvariable\fR \fIsymbolname\fR
|
|
or
|
|
\fBmvariable\fR \fIsymbolname\fR \fB=\fR \fIexpression\fR
|
|
|
|
.fi
|
|
bears exactly the same relationship to the \fBvariable\fR statement that the
|
|
\fBmdefine\fR statement does to the \fBdefine\fR statement. It declares a
|
|
variable whose scope is limited to the function or macro in whose definition
|
|
it appears.
|
|
.NH 2
|
|
Mif\fR statement
|
|
.PP
|
|
The \fBmif\fR statement conditionally assembles the statements contained in
|
|
the block following it:
|
|
.nf
|
|
|
|
\fBmif\fR \fB(\fR \fIcondition\fR \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \*[ \fBmelseif\fR \fB(\fR \fIcondition\fR \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \*Z \*[ \fBmelse\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \*]
|
|
|
|
.fi
|
|
unlike the \fBif\fR statement, the \fIcondition\fR may be any expression
|
|
whatsoever. \fIMacross\fR follows the \fBC\fR convention that the value 0
|
|
represents \fBFALSE\fR and any other value represents \fBTRUE\fR (in fact, the
|
|
symbols \fBTRUE\fR and \fBFALSE\fR are ``predefined'' by the assembler to
|
|
have the values 1 and 0 respectively). The meaning of the \fBmif\fR construct
|
|
is the obvious one, but keep in mind that it is interpreted at assembly time
|
|
and has no direct bearing on the execution of the resulting assembled program.
|
|
.NH 2
|
|
Mwhile\fR statement
|
|
.PP
|
|
The \fBmwhile\fR statement repetitively assembles a block of statements so
|
|
long as a given condition remains true. Its form is
|
|
.nf
|
|
|
|
\fBmwhile\fR \fB(\fR \fIcondition\fR \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR
|
|
|
|
.fi
|
|
As with \fBmif\fR, the \fIcondition\fR may be any valid \fIMacross\fR
|
|
expression and the interpretation is what it seems.
|
|
.NH 2
|
|
Mdo-while\fR statement
|
|
.PP
|
|
The \fBmdo-while\fR statement provides an alternative to the \fBmwhile\fR
|
|
statement by testing at the bottom of the loop instead of at the top. Its
|
|
form is
|
|
.nf
|
|
|
|
\fBmdo\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \fBwhile\fR \fB(\fR \fIcondition\fR \fB)\fR
|
|
.fi
|
|
.NH 2
|
|
Mdo-until\fR statement
|
|
.PP
|
|
The \fBmdo-until\fR statement is the same as the \fBmdo-while\fR statement
|
|
except that the sense of the condition is negated. It has the form
|
|
.nf
|
|
|
|
\fBmdo\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \fBuntil\fR \fB(\fR \fIcondition\fR \fB)\fR
|
|
.fi
|
|
.NH 2
|
|
Mfor\fR statement
|
|
.PP
|
|
The \fBmfor\fR statement provides a more general looping construct analogous
|
|
to the \fBC\fR \fBfor\fR loop. Its form is
|
|
.nf
|
|
|
|
\fBmfor\fR \fB(\fR \fIexpression-1\fR \fB,\fR \fIexpression-2\fR \fB,\fR \fIexpression-3\fR \fB)\fR \fB{\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR
|
|
|
|
.fi
|
|
where \fIexpression-1\fR is an initialization expression, \fIexpression-2\fR
|
|
is a test to see if looping should continue, and \fIexpression-3\fR is
|
|
executed at the bottom of the loop to set up for the next time around, just as
|
|
in \fBC\fR. Note that, unlike \fBC\fR, the \fIexpression\fRs are separated by
|
|
commas, not semicolons. This is because semicolons are used to delimit line
|
|
comments.
|
|
.PP
|
|
The \fBmfor\fR statement is equivalent to
|
|
.nf
|
|
|
|
\fIexpression-1\fR
|
|
\fBmwhile (\fIexpression-2\fB ) {\fR
|
|
\fIstatements\fR
|
|
\fIexpression-3\fR
|
|
\fB}\fR
|
|
.fi
|
|
.NH 2
|
|
Mswitch\fR statement
|
|
.PP
|
|
The \fBmswitch\fR statement provides a means of selecting one of a number of
|
|
blocks of code for assembly depending upon the value of some expression. Its
|
|
form is:
|
|
.nf
|
|
|
|
\fBmswitch ( \fIselectionExpression \fB) {\fR
|
|
\*[ \fBmcase ( \fIexpression\fR \*[ \fB,\fI expression\fR \*Z \fB) {\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \*Z
|
|
\*[ \fBmdefault {\fR
|
|
\*[ \fIstatement\fR \*Z
|
|
\fB}\fR \*]
|
|
\fB}\fR
|
|
|
|
.fi
|
|
The way this works is as follows (it's actually easier to use than to
|
|
explain): \fIselectionExpression\fR is evaluated. Each of the
|
|
\fIexpression\fRs associated with the various \fBmcase\fR clauses (if any) is
|
|
then evaluated in turn and the resulting value compared to that of
|
|
\fIselectionExpression\fR. When and if one of these values ``matches'' the
|
|
value of \fIselectionExpression\fR the block of \fIstatement\fRs associated
|
|
with the corresponding \fBmcase\fR clause is immediately assembled and
|
|
execution of the \fBmswitch\fR statement is complete. If no such value
|
|
matches and there is an \fBmdefault\fR clause, the block of \fIstatement\fRs
|
|
associated with the \fBmdefault\fR clause is assembled. If no value matches
|
|
and there is no \fBmdefault\fR clause then nothing is assembled as a result of
|
|
the \fBmswitch\fR. When we say the values ``match'', we mean that either
|
|
the expressions evaluate to the same number or to strings which are identical
|
|
except for the case of alphabetic characters. For example:
|
|
.nf
|
|
|
|
\fBmswitch (foo) {
|
|
mcase ("hello", "fnord") {
|
|
\fIstatements-1\fB
|
|
}
|
|
mcase ("ZAP!") {
|
|
\fIstatements-2\fB
|
|
}
|
|
mdefault {
|
|
\fIstatements-3\fR
|
|
}
|
|
}\fR
|
|
|
|
.fi
|
|
would switch on the value of the symbol \fBfoo\fR. If the value of \fBfoo\fR
|
|
was \fB"hello"\fR, \fIstatements-1\fR would be assembled. If the value of
|
|
\fBfoo\fR was \fB"zap!"\fR, \fIstatements-2\fR would be assembled (since the
|
|
string comparison is done independent of case). If the value of \fBfoo\fR was
|
|
\fB"cromfelter"\fR or \fB47\fR, then \fIstatements-3\fR would be assembled by
|
|
default.
|
|
.NH 2
|
|
Freturn\fR statement
|
|
.PP
|
|
A \fIMacross\fR function may (and probably will) be called from an expression
|
|
in the traditional manner of functions throughout the annals of computer
|
|
science. In such a situation, the programmer may wish to have a function
|
|
return a value. The \fBfreturn\fR statement enables this. Its form is
|
|
.nf
|
|
|
|
\fBfreturn\fR \*[ \fIexpression\fR \*]
|
|
|
|
.fi
|
|
where \fIexpression\fR is any permissible \fIMacross\fR expression as
|
|
described below under \fBExpressions\fR. If no \fIexpression\fR is given, the
|
|
macro simply returns without having a value as its result. Any attempt to use
|
|
the (non-existent) value returned by a call to function which doesn't return a
|
|
value will result in an error message from the assembler. Function calls will
|
|
automatically return without a value upon reaching the end of the block that
|
|
forms the body of the function.
|
|
.NH 1
|
|
Miscellaneous Statements
|
|
.PP
|
|
Various useful statements don't fall into any of the above categories.
|
|
.NH 2
|
|
Include\fR statement
|
|
.PP
|
|
The \fBinclude\fR statement allows the text in other files to be included in
|
|
the source program being assembled, in the time-honored fashion. Its form is
|
|
.nf
|
|
|
|
\fBinclude\fR \fIfilename\fR
|
|
|
|
.fi
|
|
where \fIfilename\fR is a string value giving the name of the file to be
|
|
included. \fBInclude\fRd files may themselves contain \fBinclude\fR
|
|
statements to any number of levels of recursion (within reason).
|
|
.NH 2
|
|
Extern\fR statement
|
|
.PP
|
|
The \fBextern\fR statement allows you to declare symbols to be visible to the
|
|
linker outside of the file in which they are found. Its use:
|
|
.nf
|
|
|
|
\fBextern\fR \fIsymbol\fR \*[ \fB,\fR \fIsymbol\fR \*Z
|
|
.fi
|
|
.NH 2
|
|
Start\fR statement
|
|
.PP
|
|
The \fBstart\fR statement declares the starting address of a program.
|
|
.nf
|
|
|
|
\fBstart\fR \fIexpression\fR
|
|
|
|
.fi
|
|
where the \fIexpression\fR indicates the start address. There should be no
|
|
more than one \fBstart\fR statement in a program. If no start address is
|
|
specified, the object file will be produced without a start address entry.
|
|
.NH 2
|
|
Assert\fR statement
|
|
.PP
|
|
The \fBassert\fR statement provides a means of testing assembly time
|
|
conditions and generating programmer specified error messages if those
|
|
conditions are not satisfied. Its syntax is:
|
|
.nf
|
|
|
|
\fBassert (\fIcondition\fB)\fR \*[ \fItextString\fR \*]
|
|
|
|
.fi
|
|
where \fIcondition\fR is an expression such as those used in the \fBmif\fR
|
|
statement. This condition is evaluated and if \fBFALSE\fR then the message
|
|
\fItextString\fR, if given, is written to the standard output. The message is
|
|
written in the form of a conventional \fIMacross\fR error message, giving the
|
|
file and line number on which the failed assertion occured. If
|
|
\fItextString\fR is omitted then a simple error message to the effect that the
|
|
assert failed will be output. For example,
|
|
.nf
|
|
|
|
\fBassert (foo == 1) "Hey! You blew it."\fR
|
|
|
|
.fi
|
|
would check to see that the value of the symbol \fBfoo\fR is \fB1\fR, and if
|
|
it isn't would issue an error message containing the string \fB"Hey! You blew
|
|
it."\fR.
|
|
.NH 2
|
|
Org\fR statement
|
|
.PP
|
|
The \fBorg\fR statement adjusts the current location counter and tells the
|
|
assembler to start locating instructions and data in absolute memory
|
|
locations.
|
|
.nf
|
|
|
|
\fBorg\fR \fIexpression\fR
|
|
|
|
.fi
|
|
The \fIexpression\fR indicates the new current location. If this is an
|
|
absolute address, \fIMacross\fR starts assembling at the specified
|
|
absolute memory location. If, on the other hand, it is relative to a
|
|
relocatable address or to the current location counter, the current location
|
|
counter is simply adjusting accordingly.
|
|
.NH 2
|
|
Rel\fR statement
|
|
.PP
|
|
The \fBrel\fR statement restores \fIMacross\fR to assembling code in a
|
|
relocatable fashion, if it was not already doing so. The relocatable location
|
|
resumes from wherever it was left the last time an absolute \fBorg\fR stopped
|
|
relocatable code assembly. \fI((explain this better))\fR
|
|
.NH 2
|
|
Target\fR statement
|
|
.PP
|
|
The \fBtarget\fR statement
|
|
.nf
|
|
|
|
\fBtarget\fR \fIexpression\fR
|
|
|
|
.fi
|
|
tells the assembler to assemble as if it had been \fBorg\fRed to a particular
|
|
address without actually performing the \fBorg\fR. The \fIexpression\fR
|
|
indicates the location to start assembling from. This must be an absolute
|
|
address (and the \fBtarget\fR statement may only be used when assembling in
|
|
absolute mode).
|
|
.PP
|
|
The result of the \fBtarget\fR statement is that assembly proceeds from the
|
|
current location but labels will be defined as if it was proceeding from the
|
|
location specified by \fIexpression\fR and references to the current location
|
|
counter will be offset by the difference between the actual current location
|
|
counter value and the value of \fIexpression\fR. This effect will persist until the next \fBorg\fR or \fBtarget\fR statement. For example
|
|
.nf
|
|
|
|
\fBorg 0x1000
|
|
target 0x0800
|
|
foo: rts
|
|
bar: word 0x1234
|
|
word here
|
|
org someplaceElse\fR
|
|
|
|
.fi
|
|
would first set the current location counter to \fB0x1000\fR. At location
|
|
\fB0x1000\fR it would assemble an \fBrts\fR instruction while giving the label
|
|
\fBfoo\fR the value \fB0x800\fR. Then, at location \fB0x1002\fR it would
|
|
deposit the word value \fB0x1234\fR while giving the label \fBbar\fR the
|
|
value \fB0x802\fR. At location \fB0x1004\fR it would deposit the word value
|
|
\fB0x804\fR. Finally, the second \fBorg\fR would set the current location
|
|
counter to \fBsomeplaceElse\fR and the effects of the \fBtarget\fR statement
|
|
would cease.
|
|
.SH
|
|
\s+3Expressions\s-3
|
|
.PP
|
|
The expression syntax of \fIMacross\fR was chosen to be as close to that of
|
|
\fBC\fR as possible. \fIMacross\fR recognizes the same set of operators as
|
|
\fBC\fR with few exceptions, and the operators have the same precedence with
|
|
respect to each other that everyone is used to.
|
|
.PP
|
|
Another important feature of expressions in \fIMacross\fR is that expressions
|
|
by themselves on a line are valid statements. Assignment expressions, uses of
|
|
the post- and pre-increment and decrement operators (``\fB++\fR'' and
|
|
``\fB--\fR''), and calls to functions used like procedures are the most
|
|
useful applications of this. For example
|
|
.nf
|
|
|
|
\fBfoo = 5\fR
|
|
\fBbar++\fR
|
|
\fBprintf("Hello world\\n")\fR
|
|
|
|
.fi
|
|
are all valid statements.
|
|
.NH 0
|
|
\fRPrimitive expressions
|
|
.PP
|
|
The most primitive expressions are identifiers, numbers, characters, character
|
|
strings, and function calls.
|
|
.PP
|
|
Identifiers have already been described, in the section \fBGeneral Form of
|
|
\fIMacross\fB Statements\fR above. The only thing to add here is that the
|
|
special identifier \fBhere\fR denotes the value of the current location
|
|
counter.
|
|
.PP
|
|
Numbers may be decimal, octal, hexadecimal, binary or quarters. The form of
|
|
the first three of these is as in \fBC\fR: decimal numbers are denoted by a
|
|
sequence of decimal digits that does not begin with a ``\fB0\fR''; octal
|
|
numbers by a sequence of octal digits that \fIdoes\fR begin with a
|
|
``\fB0\fR''; and hexadecimal numbers by a sequence of hexadecimal digits
|
|
(the decimal digits plus the letters ``\fBa\fR'' through ``\fBf\fR'', in
|
|
either upper or lower case), preceded by ``\fB0x\fR'' or ``\fB0X\fR''.
|
|
Binary numbers and quarters are represented analogously. Binary numbers are
|
|
represented by a sequence of ``\fB0\fR''s and ``\fB1\fR''s preceded by
|
|
``\fB0b\fR'' or ``\fB0B\fR''. Quarters are base-four numbers (for two-bit
|
|
entities like Atari pixels) and are represented by the sequences of the digits
|
|
\fB0\fR through \fB3\fR preceded by ``\fB0q\fR'' or ``\fB0Q\fR'' (the
|
|
credit for this idea goes to Charlie Kellner).
|
|
.PP
|
|
Character constants are denoted the same as in \fBC\fR: by a single character
|
|
enclosed in apostrophes (``\fB'\fR''). The same conventions about
|
|
characters escaped with a backslash (``\fB\\\fR'') also apply. Strings may
|
|
be of varying lengths and are enclosed in quotation marks (``\fB"\fR''),
|
|
as discussed above in the explanation of instruction operands.
|
|
.PP
|
|
A function call, in \fIMacross\fR, is syntactically the same as in \fBC\fR:
|
|
the name of the function being called followed by a comma-separated argument
|
|
list in parenthesis. The argument list, as in \fBC\fR, may be empty. The
|
|
arguments themselves may be arbitrary instruction operands (described above in
|
|
section 1). A number of built-in functions are provided by \fIMacross\fR to
|
|
perform a variety of useful operations. These are discussed in \fBAppendix
|
|
D\fR.
|
|
.NH 1
|
|
\fROperators
|
|
.PP
|
|
Expressions may be constructed from the primitive elements described above and
|
|
from other expressions using a variety of unary and binary operators. The
|
|
operator set is patterned after \fBC\fR's. The only \fBC\fR operators not
|
|
supported are:
|
|
.IP
|
|
[1] ``\fB?:\fR'' (arithmetic if) \*- not supported for reasons of syntactic
|
|
confusion on both the part of the parser attempting to parse it and the
|
|
programmer attempting to use it.
|
|
.IP
|
|
[2] ``\fB,\fR'' (comma) \*- used in \fIMacross\fR as an important separator
|
|
and thus not available.
|
|
.IP
|
|
[3] unary ``\fB*\fR'' and ``\fB&\fR'', \fBsizeof\fR, casts and
|
|
``\fB->\fR'' \*- not relevant here.
|
|
.LP
|
|
All of the assignment operators (``\fB+=\fR'', ``\fB-=\fR'', etc.)
|
|
\fIare\fR supported by \fIMacross\fR.
|
|
.LP
|
|
\fIMacross\fR reinterprets the \fB.\fR operator in that ``\fIexpression\fB .
|
|
\fIstructfieldname\fR'' is interpreted as adding the offset value implied by
|
|
\fIstructfieldname\fR (i.e., the distance in bytes into a \fBstruct\fR to
|
|
reach the named field) to the address that is the value of \fIexpression\fR.
|
|
.LP
|
|
\fIMacross\fR adds to the operator set the following:
|
|
.IP
|
|
[1] ``\fB?\fR'' \*- as a unary operator, takes the high order byte of the
|
|
word value that is its argument.
|
|
.IP
|
|
[2] ``\fB/\fR'' \*- as a unary operator, takes the low order byte of the
|
|
word value that is its argument.
|
|
.IP
|
|
[3] ``\fB^^\fR'' \*- a binary operator, denotes logical exclusive-OR. This
|
|
is simply an orthogonal extension for the sake of completeness.
|
|
.LP
|
|
Of course, parenthesis can be used at any point to override the normal
|
|
precedence of the various operators. A full list of all the operators that
|
|
\fIMacross\fR understands is given in \fBAppendix E\fR.
|
|
.NH 1
|
|
\fRExpression evaluation
|
|
.PP
|
|
In order to make the most effective use of expressions in the \fIMacross\fR
|
|
environment, it is helpful (and at times necessary) to understand how and when
|
|
\fIMacross\fR evaluates them.
|
|
.PP
|
|
When \fIMacross\fR evaluates an expression, it may have one of three sorts of
|
|
results. These are \fIsuccess\fR, \fIundefined\fR, and \fIfailure\fR. A
|
|
\fIsuccess\fR result means that \fIMacross\fR encountered no problems
|
|
evaluating the expression, and whatever value it evaluated to is just used as
|
|
needed. A \fIfailure\fR result indicates that there was a problem of some
|
|
sort. Usually this is a result of some user error. In any case, an
|
|
appropriate diagnostic message will be issued by the assembler and the
|
|
statement in which the expression was found will not be assembled.
|
|
.PP
|
|
An \fIundefined\fR result is where the complications, if any, arise. An
|
|
expression will evaluate to an \fIundefined\fR result if one or more of the
|
|
terms of the expression are undefined symbols. Usually these are labels which
|
|
simply haven't been encountered yet (i.e., they are forward references). In
|
|
certain contexts, such as the operand of a machine instruction, this is a
|
|
legitimate thing to do, and in certain others, such as the condition of a
|
|
\fBmif\fR statement, this is not allowed at all. In the latter case, an
|
|
\fIundefined\fR result is just like a \fIfailure\fR result. In the former
|
|
case, the assembler is forced to get fancy in order to make it all work right.
|
|
.PP
|
|
What \fIMacross\fR does is squirrel away a copy of the expression along with a
|
|
pointer as to where in the object code the value of the expression is supposed
|
|
to go. At the end of assembly, the undefined label will presumably now be
|
|
defined, and \fIMacross\fR evaluates the saved expression and pokes the result
|
|
into the appropriate location. (If, at this point, the undefined label is
|
|
still undefined, an error message to that effect is issued). Clearly, if an
|
|
expression has side effects (such as changing the value of some global
|
|
variable), this can result in some confusing behavior. The \fIMacross\fR
|
|
assembler is smart enough to not let you do anything that has overt side
|
|
effects in an expression that is being saved away for future evaluation. The
|
|
things which are disallowed in such a case are assignments and uses of the
|
|
post- and pre-increment and decrement operators (``\fB++\fR'' and
|
|
``\fB--\fR''). Functions, however, may have side effects and \fIMacross\fR
|
|
does not try to prevent you from using function calls in expressions that get
|
|
saved for later evaluation. It can, and will, detect some, but not all, side
|
|
effects during the later evaluation and give a suitable error message. This
|
|
is because it is perfectly legitimate to use a function call to a function
|
|
that doesn't have side effects in an expression containing forward references.
|
|
.PP
|
|
If you are now totally confused, the only thing you need remember is: \fBDon't
|
|
ever use a call to a function that has side effects in an expression
|
|
containing a forward reference.\fR
|
|
.bp
|
|
.CD
|
|
\s+5\fBAppendix A \*- Macross 68000 Grammar\fR\s-5
|
|
\"\s+4\fBAppendix A \*- Macross 68000 Grammar\fR\s-4
|
|
.DE
|
|
.LP
|
|
.nf
|
|
\fR\fIprogram\fR:
|
|
\*[ \fIstatement\fR Newline \*Z Endfile
|
|
|
|
\fIstatement\fR:
|
|
\*[ \fIlabel\fR \*Z \fIopcode\fR \*[ \fIoperand\fR \*[ \fB,\fR \fIoperand\fR \*Z \*]
|
|
\*[ \fIlabel\fR \*Z \fBif\fR \fB(\fR \fIcondition\fR \fB)\fR \fIblock\fR
|
|
\*[ \fBelseif\fR \fB(\fR \fIcondition\fR \fB)\fR \fIblock\fR \*Z
|
|
\*[ \fBelse\fR \fIblock\fR \*]
|
|
\*[ \fIlabel\fR \*Z \fBwhile\fR \fB(\fR \fIcondition\fR \fB)\fR \fIblock\fR
|
|
\*[ \fIlabel\fR \*Z \fBdo\fR \fIblock\fR \fBwhile\fR \fB(\fR \fIcondition\fR \fB)\fR
|
|
\*[ \fIlabel\fR \*Z \fBdo\fR \fIblock\fR \fBuntil\fR \fB(\fR \fIcondition\fR \fB)\fR
|
|
\fIdataStatement\fR
|
|
\fBdefine\fR \fIidentifier\fR \*[ \fB=\fR \fIexpression\fR \*]
|
|
\fBvariable\fR \fIidentifier\fR \*[ \fB=\fR \fIexpression\fR \*]
|
|
\fBmacro\fR \fIidentifier\fR \*[ \fIidentifier\fR \*[ \fB,\fR \fIidentifier\fR \*Z \*] \fIblock\fR
|
|
\fBfunction\fR \fIidentifier\fR \fB(\fR \*[ \fIidentifier\fR \*[ \fB,\fR \fIidentifier\fR \*Z \*] \fB)\fR \fIblock\fR
|
|
\fBundefine\fR \fIidentifier\fR \*[ \fB,\fR \fIidentifier\fR \*Z
|
|
\*[ \fIlabel\fR \*Z \fIblock\fR
|
|
\fBmdefine\fR \fIidentifier\fR \*[ \fB=\fR \fIexpression\fR \*]
|
|
\fBmif\fR \fB(\fR \fIexpression\fR \fB)\fR \fIblock\fR
|
|
\*[ \fBmelseif\fR \fB(\fR \fIexpression\fR \fB)\fR \fIblock\fR \*Z
|
|
\*[ \fBmelse\fR \fIblock\fR \*]
|
|
\fBmwhile\fR \fB(\fR \fIexpression\fR \fB)\fR \fIblock\fR
|
|
\fBmdo\fR \fIblock\fR \fBwhile\fR \fB(\fR \fIexpression\fR \fB)\fR
|
|
\fBmdo\fR \fIblock\fR \fBuntil\fR \fB(\fR \fIexpression\fR \fB)\fR
|
|
\fBfreturn\fR \*[ \fIexpression\fR \*]
|
|
\fBmfor\fR \fB(\fR \fIexpression\fR \fB,\fR \fIexpression\fR \fB,\fR \fIexpression\fR \fB)\fR \fIblock\fR
|
|
\fBmswitch ( \fIselectionExpression \fB) {\fR
|
|
\*[ \fBmcase ( \fIexpression\fR \*[ \fB,\fI expression\fR \*Z \fB)\fI block\fR \*Z
|
|
\*[ \fBmdefault\fI block\fR \*]
|
|
\fB}\fR
|
|
\fBconstrain\fR \fB(\fR \fIexpression\fR \fB)\fR \fIblock\fR
|
|
\fBassert\fR \fB(\fR \fIexpression\fR \fB)\fR \*[ \fIexpression\fR \*]
|
|
\fBinclude\fR \fItextString\fR
|
|
\fBextern\fR \fIidentifier\fR \*[ \fB,\fR \fIidentifier\fR \*Z
|
|
\fBstart\fR \fIexpression\fR
|
|
\fBorg\fR \fIexpression\fR
|
|
\fBtarget\fR \fIexpression\fR
|
|
\fIexpression\fR
|
|
|
|
\fIdataStatement\fR:
|
|
\*[ \fIlabel\fR \*Z \fBblock\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
\*[ \fIlabel\fR \*Z \fBalign\fR \fIexpression\fR
|
|
\*[ \fIlabel\fR \*Z \fBword\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
\*[ \fIlabel\fR \*Z \fBlong\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
\*[ \fIlabel\fR \*Z \fBdbyte\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
\*[ \fIlabel\fR \*Z \fBbyte\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
\*[ \fIlabel\fR \*Z \fBstring\fR \fIexpression\fR \*[ \fB,\fR \fIexpression\fR \*Z
|
|
\*[ \fIlabel\fR \*Z \fBstruct\fR \fB{\fR \*[ \fIdataStatement\fR \*Z \fB}\fR \fIidentifier\fR
|
|
\*[ \fIlabel\fR \*Z \fBstruct\fR \fIidentifier\fR
|
|
|
|
\fIlabel\fR: \fIidentifier\fR \fB:\fR
|
|
|
|
\fIoperand\fR:
|
|
\fBd\fIn\fR
|
|
\fBa\fIn\fR
|
|
\fBsp\fR
|
|
\fB\s-1[\s+1\fR \fBa\fIn\fR \fB\s-1]\s+1\fR
|
|
\fB\s-1[\s+1\fR \fBa\fIn\fR \fB\s-1]\s+1+\fR
|
|
\fB-\s-1[\s+1\fR \fBa\fIn\fR \fB\s-1]\s+1\fR
|
|
\fIexpression\fR
|
|
\fIexpression\fB . w\fR
|
|
\fIexpression\fB . l\fR
|
|
\fB#\fR \fIexpression\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBa\fIn\fR \fB\s-1]\s+1\fR
|
|
\fBa\fIn\fR \fB.\fR \fIidentifier\fR \*[ \fB.\fR \fIidentifier\fR \*Z
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBa\fIn\fR \fB,\fR \fIrn\fR \fB. w \s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBa\fIn\fR \fB,\fR \fIrn\fR \fB. l \s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBa\fIn\fR \fB,\fR \fIrn\fR \fB\s-1]\s+1\fR
|
|
\fBa\fIn\fR \fB\s-1[\s+1\fR \fIrn\fR \fB. w \fB\s-1]\s+1\fR \fB.\fR \fIidentifier\fR \*[ \fB.\fR \fIidentifier\fR \*Z
|
|
\fBa\fIn\fR \fB\s-1[\s+1\fR \fIrn\fR \fB. l \fB\s-1]\s+1\fR \fB.\fR \fIidentifier\fR \*[ \fB.\fR \fIidentifier\fR \*Z
|
|
\fBa\fIn\fR \fB\s-1[\s+1\fR \fIrn\fR \fB\s-1]\s+1\fR \fB.\fR \fIidentifier\fR \*[ \fB.\fR \fIidentifier\fR \*Z
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBpc\fR \fB\s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBpc\fR \fB,\fR \fIrn\fR \fB. w \s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBpc\fR \fB,\fR \fIrn\fR \fB. l \s-1]\s+1\fR
|
|
\fIexpression\fR \fB\s-1[\s+1\fR \fBpc\fR \fB,\fR \fIrn\fR \fB\s-1]\s+1\fR
|
|
\fBccr\fR
|
|
\fBsr\fR
|
|
\fBusp\fR
|
|
\fBsfc\fR
|
|
\fBdfc\fR
|
|
\fBvbr\fR
|
|
\fItextString\fR
|
|
|
|
\fIblock\fR: \fB{\fR \*[ \fIstatement\fR Newline \*Z \fB}\fR
|
|
|
|
\fItextString\fR:
|
|
\fB" \fIany string you like \fB"\fR
|
|
|
|
\fIcondition\fR:
|
|
\fIconditionCode\fR
|
|
\fB!\fR \fIconditionCode\fR
|
|
|
|
\fIexpression\fR:
|
|
\fIidentifier\fR
|
|
\fIidentifier\fR \fB(\fR \*[ \fIoperand\fR \*[ \fB,\fR \fIoperand\fR \*Z \*] \fB)\fR
|
|
\fInumber\fR
|
|
\fBhere\fR
|
|
\fItextString\fR
|
|
\fB(\fR \fIexpression\fR \fB)\fR
|
|
\fB-\fR \fIexpression\fR
|
|
\fB!\fR \fIexpression\fR
|
|
\fB~\fR \fIexpression\fR
|
|
\fB?\fR \fIexpression\fR
|
|
\fB/\fR \fIexpression\fR
|
|
\fIexpression\fR \fB*\fR \fIexpression\fR
|
|
\fIexpression\fR \fB/\fR \fIexpression\fR
|
|
\fIexpression\fR \fB%\fR \fIexpression\fR
|
|
\fIexpression\fR \fB-\fR \fIexpression\fR
|
|
\fIexpression\fR \fB+\fR \fIexpression\fR
|
|
\fIexpression\fR \fB<<\fR \fIexpression\fR
|
|
\fIexpression\fR \fB>>\fR \fIexpression\fR
|
|
\fIexpression\fR \fB<\fR \fIexpression\fR
|
|
\fIexpression\fR \fB>\fR \fIexpression\fR
|
|
\fIexpression\fR \fB<=\fR \fIexpression\fR
|
|
\fIexpression\fR \fB>=\fR \fIexpression\fR
|
|
\fIexpression\fR \fB==\fR \fIexpression\fR
|
|
\fIexpression\fR \fB!=\fR \fIexpression\fR
|
|
\fIexpression\fR \fB&\fR \fIexpression\fR
|
|
\fIexpression\fR \fB|\fR \fIexpression\fR
|
|
\fIexpression\fR \fB^\fR \fIexpression\fR
|
|
\fIexpression\fR \fB&&\fR \fIexpression\fR
|
|
\fIexpression\fR \fB||\fR \fIexpression\fR
|
|
\fIexpression\fR \fB^^\fR \fIexpression\fR
|
|
\fIexpression\fR \fB.\fR \fIidentifier\fR
|
|
\fIidentifier\fR \fB=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB+=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB-=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB*=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB/=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB%=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB&=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB|=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB^=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB<<=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB>>=\fR \fIexpression\fR
|
|
\fIidentifier\fR \fB++\fR
|
|
\fIidentifier\fR \fB--\fR
|
|
\fB++\fR \fIidentifier\fR
|
|
\fB--\fR \fIidentifier\fR
|
|
|
|
\fIidentifier\fR:
|
|
\*[\fBa\fR-\fBzA\fR-\fBZ_\fR\*]\*[\fBa\fR-\fBzA\fR-\fBZ_0\fR-\fB9\fR\*Z
|
|
|
|
\fInumber\fR:
|
|
\fIdecimalNumber\fR
|
|
\fIoctalNumber\fR
|
|
\fIbinaryNumber\fR
|
|
\fIhexadecimalNumber\fR
|
|
\fIquarter\fR
|
|
|
|
\fIdecimalNumber\fR:
|
|
\*[\fB1\fR-\fB9\fR\*]\*[\fB0\fR-\fB9\fR\*Z
|
|
|
|
\fIoctalNumber\fR:
|
|
\fB0\fR\*[\fB0\fR-\fB7\fR\*Z
|
|
|
|
\fIbinaryNumber\fR:
|
|
\fB0b\fR\*[\fB01\fR\*]\*[\fB01\fR\*Z
|
|
|
|
\fIhexadecimalNumber\fR:
|
|
\fB0x\fR\*[\fB0\fR-\fB9a\fR-\fBf\fR\*]\*[\fB0\fR-\fB9a\fR-\fBf\fR\*Z
|
|
|
|
\fIquarter\fR:
|
|
\fB0q\fR\*[\fB0\fR-\fB3\fR\*]\*[\fB0\fR-\fB3\fR\*Z
|
|
|
|
.fi
|
|
.bp
|
|
.CD
|
|
\s+5\fBAppendix B \*- Recognized Opcode Mnemonics\fR\s-5
|
|
\"\s+4\fBAppendix B \*- Recognized Opcode Mnemonics\fR\s-4
|
|
.sp 1
|
|
\s+3\fB(68000 version)\fR\s-3
|
|
.DE
|
|
.PP
|
|
These are the 68000 opcode mnemonics recognized by \fIMacross\fR:
|
|
.2C
|
|
.nf
|
|
\fBabcd
|
|
addb
|
|
addl
|
|
addqb
|
|
addql
|
|
addqw
|
|
addw
|
|
addxb
|
|
addxl
|
|
addxw
|
|
andb
|
|
andl
|
|
andw
|
|
aslb
|
|
asll
|
|
aslw
|
|
asrb
|
|
asrl
|
|
asrw
|
|
bcc
|
|
bchg
|
|
bclr
|
|
bcs
|
|
beq
|
|
bge
|
|
bgt
|
|
bhi
|
|
ble
|
|
bls
|
|
blt
|
|
bmi
|
|
bne
|
|
bpl
|
|
bra
|
|
bset
|
|
bsr
|
|
btst
|
|
bvc
|
|
bvs
|
|
chk
|
|
clrb
|
|
clrl
|
|
clrw
|
|
cmpb
|
|
cmpl
|
|
cmpmb
|
|
cmpml
|
|
cmpmw
|
|
cmpw
|
|
dbcc
|
|
dbcs
|
|
dbeq
|
|
dbf
|
|
dbge
|
|
dbgt
|
|
dbhi
|
|
dble
|
|
dbls
|
|
dblt
|
|
dbmi
|
|
dbne
|
|
dbpl
|
|
dbra
|
|
dbt
|
|
dbvc
|
|
dbvs
|
|
divs
|
|
divu
|
|
eorb
|
|
eorl
|
|
eorw
|
|
exg
|
|
extl
|
|
extw
|
|
illegal
|
|
jmp
|
|
jsr
|
|
lea
|
|
link
|
|
lslb
|
|
lsll
|
|
lslw
|
|
lsrb
|
|
lsrl
|
|
lsrw
|
|
movb
|
|
moveb
|
|
movel
|
|
moveml
|
|
movemw
|
|
movepl
|
|
movepw
|
|
moveq
|
|
movesb
|
|
movesl
|
|
movesw
|
|
movew
|
|
movl
|
|
movml
|
|
movmw
|
|
movpl
|
|
movpw
|
|
movq
|
|
movsb
|
|
movsl
|
|
movsw
|
|
movw
|
|
muls
|
|
mulu
|
|
nbcd
|
|
negb
|
|
negl
|
|
negw
|
|
negxb
|
|
negxl
|
|
negxw
|
|
nop
|
|
notb
|
|
notl
|
|
notw
|
|
orb
|
|
orl
|
|
orw
|
|
pea
|
|
reset
|
|
rolb
|
|
roll
|
|
rolw
|
|
rorb
|
|
rorl
|
|
rorw
|
|
roxlb
|
|
roxll
|
|
roxlw
|
|
roxrb
|
|
roxrl
|
|
roxrw
|
|
rtd
|
|
rte
|
|
rtr
|
|
rts
|
|
sbcd
|
|
scc
|
|
scs
|
|
seq
|
|
sf
|
|
sge
|
|
sgt
|
|
shi
|
|
sle
|
|
sls
|
|
slt
|
|
smi
|
|
sne
|
|
spl
|
|
st
|
|
stop
|
|
subb
|
|
subl
|
|
subqb
|
|
subql
|
|
subqw
|
|
subw
|
|
subxb
|
|
subxl
|
|
subxw
|
|
svc
|
|
svs
|
|
swap
|
|
tas
|
|
trap
|
|
trapv
|
|
tstb
|
|
tstl
|
|
tstw
|
|
unlk
|
|
.fi
|
|
.1C
|
|
.CD
|
|
\s+5\fBAppendix C \*- Condition Codes\fR\s-5
|
|
\"\s+4\fBAppendix C \*- Condition Codes\fR\s-4
|
|
.sp 1
|
|
\s+3\fB(68000 version)\fR\s-3
|
|
.DE
|
|
.PP
|
|
The \fIMacross\fR \fBif\fR, \fBwhile\fR, \fBdo-while\fR and \fBdo-until\fR
|
|
statements make use of symbols denoting the hardware condition codes of the
|
|
target processor which may be used as the conditions upon which conditional
|
|
branches are base. In the 68000 version of \fIMacross\fR, these are the
|
|
recognized condition code symbols:
|
|
.LP
|
|
.nf
|
|
\fBcarry\fR
|
|
\fBequal\fR
|
|
\fBgeq\fR
|
|
\fBgreater\fR
|
|
\fBgt\fR
|
|
\fBhigh\fR
|
|
\fBhigh_same\fR
|
|
\fBhs\fR
|
|
\fBless\fR
|
|
\fBleq\fR
|
|
\fBlow\fR
|
|
\fBlow_same\fR
|
|
\fBls\fR
|
|
\fBlt\fR
|
|
\fBminus\fR
|
|
\fBnegative\fR
|
|
\fBneq\fR
|
|
\fBoverflow\fR
|
|
\fBplus\fR
|
|
\fBpositive\fR
|
|
\fBzero\fR
|
|
|
|
.fi
|
|
.bp
|
|
.CD
|
|
\s+5\fBAppendix D \*- Built-In Functions\fR\s-5
|
|
\"\s+4\fBAppendix D \*- Built-In Functions\fR\s-4
|
|
.DE
|
|
.PP
|
|
Certain predefined built-in functions are supported by \fIMacross\fR for
|
|
reasons of convenience or syntactic or semantic irregularity. They are:
|
|
.nf
|
|
|
|
\fBaddressMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number whose value indicates which addressing mode \fIoperand\fR
|
|
represents \fI((define these values))\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBapply(\fImacname\fR \*[ \fB, \fIarg\fR \*Z \fB)\fR
|
|
.fi
|
|
.RS
|
|
Assembles the macro whose name is specified by the \fBstring\fR \fImacname\fR
|
|
with the macro arguments (if any) given by the \fIarg\fRs.
|
|
.RE
|
|
.nf
|
|
|
|
\fBgetAddressRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number from 0 to 7 indicating which address register is used in
|
|
\fIoperand\fR (assuming that the address mode of \fIoperand\fR is address
|
|
register, register indirect, postincrement, predecrement, displacement or
|
|
indexed).
|
|
.RE
|
|
.nf
|
|
|
|
\fBgetDataRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number from 0 to 7 indicating which data register is used in
|
|
\fIoperand\fR (assuming that the address mode of \fIoperand\fR is data
|
|
register).
|
|
.RE
|
|
.nf
|
|
|
|
\fBgetIndexRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number from 0 to 15 indicating which register is used as the index
|
|
register in \fIoperand\fR (assuming that the address mode of operand is
|
|
indexed or program counter indexed). The values 0 through 7 indicate the
|
|
address registers \fBa0\fR through \fBa7\fR and the values 8 through 15
|
|
indicate the data registers \fBd0\fR through \fBd7\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBgetRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number from 0 to 15 indicating which register is used in
|
|
\fIoperand\fR. The values 0 through 7 indicate the address registers \fBa0\fR
|
|
through \fBa7\fR and the values 8 through 15 indicate the data registers
|
|
\fBd0\fR through \fBd7\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBgetWL(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number 0 or 1 indicatng whether \fIoperand\fR is a word operand or a
|
|
long operand (assuming that the address mode of \fIoperand\fR is absolute,
|
|
indexed or program counter indexed).
|
|
.RE
|
|
.nf
|
|
|
|
\fBisAbsoluteLongMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if the address mode of \fIoperand\fR is
|
|
absolute long, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisAbsoluteMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if the address mode of \fIoperand\fR is
|
|
absolute (short or long), otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisAbsoluteShortMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if the address mode of \fIoperand\fR is
|
|
absolute short, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisAbsoluteValue(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is an absolute (i.e.,
|
|
non-relocatable) value, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.bp
|
|
.nf
|
|
\fBisARegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is an address register,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisBlock(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is a block, otherwise
|
|
\fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisBuiltInFunction(\fIsymbol\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIsymbol\fR is a built-in function,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisCCRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is the condition code
|
|
register, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisConditionCode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is a condition code,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisControlRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is a control register
|
|
(\fBusp\fR, \fBdfc\fR, \fBsfc\fR, or \fBvbr\fR), otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisDefined(\fIsymbol\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIsymbol\fR has been defined, otherwise
|
|
\fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisDFCRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is the destination function
|
|
code register, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisDRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is a data register, otherwise
|
|
\fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisDisplacementMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if the address mode of \fIoperand\fR
|
|
displacment, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisExternal(\fIsymbol\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIsymbol\fR is external (i.e., visible
|
|
outside the file in which it is defined), otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisField(\fIsymbol\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIsymbol\fR is a field of a struct,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisFunction(\fIsymbol\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIsymbol\fR is a user defined function,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisImmediateMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if the address mode of \fIoperand\fR is
|
|
\fIimmediate\fR, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisIndexedMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if the address mode of \fIoperand\fR is an
|
|
indexed mode, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisPostincrementMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if the address mode of \fIoperand\fR is
|
|
postincrement, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisPredecrementMode(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if the address mode of \fIoperand\fR is
|
|
predecrement, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisRelocatableValue(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is a relocatable value,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisSFCRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is the source function code
|
|
register, otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisStatusRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is the status register,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisString(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is a string, otherwise
|
|
\fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisStruct(\fIsymbol\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIsymbol\fR is the name of a struct,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisSymbol(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is a symbol (as opposed to an
|
|
expression or a number, for example), otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisUSP(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is the user stack pointer,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBisVBRegister(\fIoperand\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns \fBTRUE\fR if and only if \fIoperand\fR is the vector base register,
|
|
otherwise \fBFALSE\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBlistingOff()\fR
|
|
.fi
|
|
.RS
|
|
If assembly listing has been enabled using the \fB-l\fR command line flag,
|
|
turn listing off temporarily. Otherwise, no effect.
|
|
.RE
|
|
.nf
|
|
|
|
\fBlistingOn()\fR
|
|
.fi
|
|
.RS
|
|
If assembly listing was turned off using the \fBlistingOff()\fR function, turn
|
|
it back on again. If listings have been globally disabled by not specifying
|
|
the \fB-l\fR command line flag, this function has no effect. The
|
|
\fBlistingOff()\fR and \fBlistingOn()\fR functions are intended to be used to
|
|
together to control assembly listings of large programs. They can be used to
|
|
suppress listing of large and uninteresting sections such as header files full
|
|
of definitions of global values. These functions may nest: in effect
|
|
\fBlistingOff()\fR increments a counter and \fBlistingOn()\fR decrements it.
|
|
Only when the counter is zero (i.e., the number of \fBlistingOn()\fRs matches
|
|
the number of \fBlistingOff()\fRs) does listing actually occur.
|
|
.RE
|
|
.nf
|
|
|
|
\fBprintf(\fIformat\fR \*[ \fB, \fIarg\fR \*Z \fB)\fR
|
|
.fi
|
|
.RS
|
|
A formatted print routine just like the Unix system subroutine of the same
|
|
name.
|
|
.RE
|
|
.nf
|
|
|
|
\fBstrcat(\fIstring1\fB, \fIstring2\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a string which is the concatenation of the two operands, which must
|
|
themselves be strings.
|
|
.RE
|
|
.nf
|
|
|
|
\fBstrcmp(\fIstring1\fB, \fIstring2\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number which is less than, equal to, or greater than 0 depending
|
|
upon whether \fIstring1\fR is lexically less than, equal to, or greater than
|
|
\fIstring2\fR. The ASCII character set is used. The two operands, of course,
|
|
must be strings.
|
|
.RE
|
|
.nf
|
|
|
|
\fBstrcmplc(\fIstring1\fB, \fIstring2\fB)\fR
|
|
.fi
|
|
.RS
|
|
Essentially the same as \fBstrcmp()\fR except that alphabetic characters are
|
|
converted to lower case before being compared. The result is a
|
|
case-independent string comparison. This is useful for comparing two
|
|
identifier name strings to see if they represent the same symbols.
|
|
.RE
|
|
.nf
|
|
|
|
\fBstrlen(\fIstring\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number which is the length, in characters, of \fIstring\fR.
|
|
.RE
|
|
.nf
|
|
|
|
\fBsubstr(\fIstring\fB, \fIstartPos\fR \*[\fB , \fIlength\fR \*] \fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a substring of the string \fIstring\fR starting from the character at
|
|
start position \fIstartPos\fR (counting the first character from 0) and
|
|
continuing for \fIlength\fR characters. If \fIstartPos\fR is negative, the
|
|
start position is counted from right to left (with the rightmost character
|
|
position being indicated by -1) instead of the more usual left to right. If
|
|
\fIlength\fR is negative, \fIstartPos\fR in essence denotes the end of the
|
|
desired substring and \fIlength\fR characters up to that position are
|
|
returned. If \fIlength\fR is omitted, the substring from \fIstartPos\fR to
|
|
the end of the string is returned, if \fIstartPos\fR is positive, or to the
|
|
beginning of the string, if \fIstartPos\fR is negative. If any of the indices
|
|
cause the substring bounds to go off the end of \fIstring\fR an error results.
|
|
For example,
|
|
.nf
|
|
\fBsubstr("hello there", 6, 3)\fR yields \fB"the"\fR
|
|
\fBsubstr("hello there", -8, 2)\fR yields \fB"lo"\fR
|
|
\fBsubstr("hello there", 6, -3)\fR yields \fB"o t"\fR
|
|
\fBsubstr("hello there", -8, -4)\fR yields \fB"hell"\fR
|
|
\fBsubstr("hello there", 6)\fR yields \fB"there"\fR
|
|
\fBsubstr("hello there", -7)\fR yields \fB"hello"\fR
|
|
.fi
|
|
.RE
|
|
.nf
|
|
|
|
\fBsymbolLookup(\fIstring\fB)\fR
|
|
.fi
|
|
.RS
|
|
A call to this function with a string operand is equivalent to a reference to
|
|
the symbol that the string represents. For example,
|
|
.nf
|
|
\fBand symbolLookup("foo")\fR
|
|
.fi
|
|
is equivalent to
|
|
.nf
|
|
\fBand foo\fR
|
|
.fi
|
|
.RE
|
|
.nf
|
|
|
|
\fBsymbolName(\fIsymbol\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a string which is the name of the symbol \fIsymbol\fR. For example,
|
|
\fBsymbolName(foo)\fR would return \fB"foo"\fR. This can be used in
|
|
conjunction with the \fBsymbolLookup\fR function so that the following:
|
|
.nf
|
|
\fBand symbolLookup(strcat(symbolName(foo), "bar"))\fR
|
|
.fi
|
|
is equivalent to
|
|
.nf
|
|
\fBand foobar\fR
|
|
.fi
|
|
.RE
|
|
.nf
|
|
|
|
\fBsymbolUsage(\fIsymbol\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number whose value indicates what sort of symbol \fIsymbol\fR is
|
|
(i.e., label, function, struct field, etc.). \fI((define these values))\fR
|
|
.RE
|
|
.nf
|
|
|
|
\fBvalueType(\fIthing\fB)\fR
|
|
.fi
|
|
.RS
|
|
Returns a number whose value indicates the type of \fIthing\fR (i.e., symbol,
|
|
condition code, number, block, etc.). \fI((define these values))\fR
|
|
.RE
|
|
|
|
.fi
|
|
.bp
|
|
.CD
|
|
\s+5\fBAppendix E \*- Operator Set\fR\s-5
|
|
\"\s+4\fBAppendix E \*- Operator Set\fR\s-4
|
|
.DE
|
|
.PP
|
|
This appendix describes the (\fBC\fR derived) operators supported by
|
|
\fIMacross\fR.
|
|
.nf
|
|
|
|
\fB-\fR \fIexpression\fR integer negation
|
|
\fB!\fR \fIexpression\fR logical negation (0 goes to 1, all other values go to 0)
|
|
\fB~\fR \fIexpression\fR bitwise negation (ones complement)
|
|
\fB?\fR \fIexpression\fR high byte
|
|
\fB/\fR \fIexpression\fR low byte
|
|
\fIexpression\fR \fB*\fR \fIexpression\fR integer multiplication
|
|
\fIexpression\fR \fB/\fR \fIexpression\fR integer division
|
|
\fIexpression\fR \fB%\fR \fIexpression\fR integer modulus (remainder)
|
|
\fIexpression\fR \fB-\fR \fIexpression\fR integer subtraction
|
|
\fIexpression\fR \fB+\fR \fIexpression\fR integer addition
|
|
\fIexpression\fR \fB<<\fR \fIexpression\fR left shift
|
|
\fIexpression\fR \fB>>\fR \fIexpression\fR right shift
|
|
\fIexpression\fR \fB<\fR \fIexpression\fR less than
|
|
\fIexpression\fR \fB>\fR \fIexpression\fR greater than
|
|
\fIexpression\fR \fB<=\fR \fIexpression\fR less than or equal to
|
|
\fIexpression\fR \fB>=\fR \fIexpression\fR greater than or equal to
|
|
\fIexpression\fR \fB==\fR \fIexpression\fR equal to
|
|
\fIexpression\fR \fB!=\fR \fIexpression\fR not equal to
|
|
\fIexpression\fR \fB&\fR \fIexpression\fR bitwise AND
|
|
\fIexpression\fR \fB|\fR \fIexpression\fR bitwise OR
|
|
\fIexpression\fR \fB^\fR \fIexpression\fR bitwise XOR
|
|
\fIexpression\fR \fB&&\fR \fIexpression\fR logical AND
|
|
\fIexpression\fR \fB||\fR \fIexpression\fR logical OR
|
|
\fIexpression\fR \fB^^\fR \fIexpression\fR logical XOR
|
|
\fIexpression\fR \fB.\fR \fIidentifier\fR struct field selection
|
|
\fIidentifier\fR \fB=\fR \fIexpression\fR assignment
|
|
\fIidentifier\fR \fB+=\fR \fIexpression\fR assignment with addition
|
|
\fIidentifier\fR \fB-=\fR \fIexpression\fR assignment with subtraction
|
|
\fIidentifier\fR \fB*=\fR \fIexpression\fR assignment with multiplication
|
|
\fIidentifier\fR \fB/=\fR \fIexpression\fR assignment with division
|
|
\fIidentifier\fR \fB%=\fR \fIexpression\fR assignment with modulus
|
|
\fIidentifier\fR \fB&=\fR \fIexpression\fR assignment with AND
|
|
\fIidentifier\fR \fB|=\fR \fIexpression\fR assignment with OR
|
|
\fIidentifier\fR \fB^=\fR \fIexpression\fR assignment with XOR
|
|
\fIidentifier\fR \fB<<=\fR \fIexpression\fR assignment with left shift
|
|
\fIidentifier\fR \fB>>=\fR \fIexpression\fR assignment with right shift
|
|
\fIidentifier\fR \fB++\fR post-increment
|
|
\fIidentifier\fR \fB--\fR post-decrement
|
|
\fB++\fR \fIidentifier\fR pre-increment
|
|
\fB--\fR \fIidentifier\fR pre-decrement
|
|
|
|
.fi
|
|
.bp
|
|
.CD
|
|
\s+5\fB Appendix F \*- Character Escape Codes\fR\s-5
|
|
\"\s+4\fB Appendix F \*- Character Escape Codes\fR\s-4
|
|
.DE
|
|
.PP
|
|
Like \fBC\fR, \fIMacross\fR enables you to use the ``\fB\\\fR'' character as
|
|
an escape to embed quotation marks, formatting characters (such as newline)
|
|
and other non-printing characters in character strings and character
|
|
constants. The recognized codes are:
|
|
.nf
|
|
|
|
\fB\\n\fR newline
|
|
\fB\\t\fR horizontal tab
|
|
\fB\\b\fR backspace
|
|
\fB\\r\fR carriage return
|
|
\fB\\f\fR form feed
|
|
\fB\\e\fR escape
|
|
\fB\\\\\fR backslash
|
|
\fB\\'\fR apostrophe
|
|
\fB\\"\fR quote
|
|
\fB\\^\fIc\fR CONTROL-\fIc\fR (where \fIc\fR is any character).
|
|
\fB\\\fIddd\fR arbitrary byte (where \fIddd\fR is one, two or three octal digits).
|
|
.fi
|