In addition to the GNU Assembler, the GCC4TI package also includes
the A68k assembler by Charlie Gibbs (slightly modified Amiga version). Although GCC4TI also includes
the GNU assembler used by GCC, A68k is included here because many old assembly programs for the
TI-89 and TI-92+ are created with this assembler (so including it in the package allows compiling
existing ASM programs as well), and because, while it is inferior to the GNU assembler in some
aspects, it also has advantages, mainly easier syntax, but also support for binary include files for
example.
The A68k assembler was developed long before the TIGCC and GCC4TI projects were even started, so it
is somewhat inconsistent with the rest of the project, though some effort has been made to integrate
it into TIGCC/GCC4TI. For example, you can now call a function from a static library using a simple
bsr
or jsr
instruction.
This assembler comes with its own set of header files. All of them are included mainly for
compatibility reasons (note that some of them are deprecated, obsolete, inconsistent
or even obscure), so they will not be described here. Information about them may be
found in various ASM tutorials for TI-89 and TI-92+ (also deprecated, but note that
nearly 95% of all ASM programs for TI-89 and TI-92+ are written using a now deprecated
way, because a lot of information about the system was not available at the time
when these programs were created). We recommend using only OS.h
, which contains a
list of equates for ROM_CALL
s (but the ROM_CALL
macros are not very
optimized and should thus be avoided), and functions from TIGCCLIB, which need no header file at all
(for example, bsr GrayOn
is enough to call the GrayOn function). What will be presented here is the original A68k documentation, written by Charlie Gibbs himself. We have however annotated it in some places
to reflect the changes made in recent versions, and we have added 2 chapters: the list of
supported assembler directives, which was missing, and the history, which was kept in a separate file.
Let's get these out of the way first:
The verification file '-v' option is not supported. Diagnostic messages always appear on the console. They also appear in the listing file, however (see extensions below). You can produce an error file by redirecting console output to a file - the line number counter and final summary are displayed on stderr so you can still see what's happening.
(TIGCC/GCC4TI) | WARNING: The new -v switch introduced in v.2.71.F3c is NOT the same as this one! |
The file names in the INCLUDE
directory list '-i' must be
separated by commas. The list may not be enclosed in quotes.
Labels assigned by EQUR
and REG
directives are case-sensitive.
Strange things will happen if your source code (including
INCLUDE
files and macro expansions) exceeds 32,766 lines.
Tough darts. Break up your source file. Can you actually
read that monster?
(TIGCC/GCC4TI) | The maximum has been increased from 32,766 to 2,147,483,646 for 32-bit operating systems starting from version 2.71.F3s. |
Directives OFFSET
, NOPAGE
, LLEN
, PLEN
,
NOOBJ
, FAIL
, FORMAT
, NOFORMAT
and
MASK2
are not supported, and will be flagged
as invalid op-codes.
I feel that NOPAGE
, LLEN
, and PLEN
should not be
defined within a source module. It doesn't make sense to me to have to change
your program just because you want to print your listings on
different paper. The command-line switch '-p' (see below) can
be used as a replacement for PLEN
; setting it to a high value
(like 32767) is a good substitute for NOPAGE
. The effect of
LLEN
can be obtained by running the listing file through an
appropriate filter.
Now for the good stuff:
Labels can be any length that will fit onto one source line (currently 127 characters maximum). Since labels are stored on the heap, the number of labels that can be processed is limited only by available memory.
(TIGCC/GCC4TI) | The maximum has been increased from 127 to 256 (for Win32, starting from 2.71.F3a, for GNU/Linux, starting from 2.71.F3c, for all other platforms, starting from 2.71.F3s). |
The first character of a label can be '@'
if the next character
is not numeric (this avoids confusion with octal constants).
This provides compatibility with the Lattice C compiler.
Since section data and user macro definitions are stored in the symbol table (see above), they too are limited only by available memory (actually, there is a hard-coded limit of 32,767 sections, but I doubt anyone will run into that one).
The only values a label cannot take are the register names - A68k can distinguish between the same name used as a label, instruction name or directive, macro name, or section name.
Section and user macro names appear in the symbol table dump, and will also be cross-referenced. Their names can be the same as any label (see above); they will be listed separately.
INCLUDE
s and macro calls can be nested indefinitely, limited
only by available memory. The message "Secondary heap
overflow - assembly terminated" will be displayed if memory
is exhausted. You can increase the size of this heap using
the '-w' switch (see below). Recursive macros are supported;
recursive INCLUDE
s will, of course, result in a loop that
will be broken only when the heap overflows.
The EVEN
directive forces alignment on a word (2-byte)
boundary. It does the same thing as CNOP 0,2
(this one is left over from the original code).
Backward references to labels within the current CODE
section
will be converted to PC-relative addressing with displacement
if this mode is legal for the instruction. This feature is
disabled by the '-n' switch.
If a MOVEM
instruction only specifies one register, it is
converted to the corresponding MOVE
instruction. Instructions
such as MOVEM D0-D0,label
will not be converted, however.
This feature is disabled by the '-n' switch.
(TIGCC/GCC4TI) | Starting from v.2.71.F3c, this feature can now also be disabled by using the '-rm' switch. |
ADD
, SUB
, and MOVE
instructions will be converted to
ADDQ
, SUBQ
, and MOVEQ
respectively if possible.
Instructions coded explicitly (e.g. ADDA
or ADDI
) will not be converted. This
feature is disabled by the '-n' switch.
ADD
, CMP
, SUB
, and MOVE
to an address register are
converted to ADDA
, CMPA
, SUBA
, and MOVEA
respectively, unless (for ADD
, SUB
, or MOVE
)
they have already been converted to quick form.
ADD
, AND
, CMP
, EOR
, OR
, and
SUB
of an immediate value are
converted to ADDI
, ANDI
, CMPI
, EORI
,
ORI
, and SUBI
respectively (unless the address register or quick
conversion above has already been done).
(TIGCC/GCC4TI) |
Starting from v.2.71.F3c, ADDA and SUBA (or ADD and SUB
to an address register) will now be converted to LEA if
possible. This feature can be disabled using the '-n'
switch (disables all optimizations) or the '-ra' switch
(disables just this single optimization). |
(TIGCC/GCC4TI) |
Starting from v.2.71.F3c, LEA n(an),an will now be converted to ADDQ or SUBQ if
possible. This feature can be disabled using the '-n'
switch (disables all optimizations) or the '-rl' switch
(disables just this single optimization). |
If both operands of a CMP
instruction are postincrement mode,
the instruction is converted to CMPM
.
Operands of the form '0(An)'
will be treated as '(An)'
except for
the MOVEP
instruction, which always requires a displacement.
This feature is disabled by the '-n' switch.
The SECTION
directive allows a third parameter. This can be
specified as either CHIP
or FAST
(upper or lower case). If
this parameter is present, the hunk will be written with the
MEMF_CHIP
or MEMF_FAST
bit set. This allows you to produce
"pre-ATOMized" object modules.
The synonyms DATA
and BSS
are accepted for SECTION
directives
starting data or BSS
hunks. The CHIP
and FAST
options (see
above) can also be used, e.g. BSS name,CHIP
.
The following synonyms have been implemented for compatibility with the Aztec assembler:
CSEG
is treated the same as CODE
or SECTION name,CODE
.
DSEG
is treated the same as DATA
or SECTION name,DATA
.
PUBLIC
is treated as either XDEF
or XREF
, depending on
whether or not the symbol in question has been defined in the current source module.
A single PUBLIC
directive can name a mixture of internally- and externally-defined symbols.
The ability to produce Motorola S-records is retained from the original code. The '-s' switch causes the assembler to produce S-format instead of AmigaDOS format. Relocatable code cannot be produced in this format.
Error messages consist of three parts.
The position of the offending line is given as a line
number within the current module. If the line is within a
macro expansion or INCLUDE
file, the position of the macro
call or INCLUDE
statement in the outer module is given as
well. This process is repeated until the outermost source
module is reached.
Next, the offending source line itself is listed.
Finally, the errors for that line are displayed. A flag
'^'
is placed under the column where the error was detected.
Named local labels are supported. These work the same as the
local labels supported by the Metacomco assembler (nnn$
) but
are formed in the same manner as normal labels, except that
they must be preceded by a backslash ('\'
).
The following synonyms have been implemented for compatibility with the Assempro assembler:
ENDIF
is treated the same as ENDC
.
'='
is treated the same as EQU
.
'|'
is treated the same as '!'
(logical OR).
Quotation marks ("
) can be used as string delimiters
as well as apostrophes ('
). Any given string must begin
and end with the same delimiter. This allows such statements
as the following:
MOVEQ "'",D0 DC.B "This is Charlie's assembler."
Note that you can still define an apostrophe within a string delimited by apostrophes if you double it, e.g.
MOVEQ '''',D0 DC.B 'This is Charlie''s assembler.'
If any errors are found in the assembly, the object code file will be scratched, unless you include the '-k' (keep) flag on the command line.
The symbols .A68K
, .a68k
, .a68K
, and .A68k
are automatically
defined as SET
symbols having absolute values of 1.
This enables a source program to determine whether it is
being assembled by this assembler, and is effectively
insensitive as to whether or not it is checked in upper case.
A zeroth positional macro parameter '\0'
is supported. It
is replaced by the length of the macro call (B
, W
, or L
,
defaulting to W
). For instance, given the macro:
moov MACRO move.\0 \1,\2 ENDM
the macro call
moov.l d0,d1
would be expanded as
move.l d0,d1
If an INCLUDE
file doesn't generate any code and no listing
file is required (including suppression of the listing using
NOLIST
), it won't be read again in pass 2. The statement
numbers will be bumped to keep in proper alignment. This
can really speed up assemblies that INCLUDE
lots of EQU
ates.
The ORG
directive is supported. It works like RORG
, except
that it takes the actual address to be jumped to, rather
than an offset from the start of the current section.
The given address must be in the current section.
As far as A68k is concerned, the only real difference
between ORG
and RORG
is that the ORG
value must be
relocatable, while the RORG value must be absolute.
Branch (Bcc
, including BRA
and BSR
) instructions will be
converted to short form if possible. Shortening a branch
may bring other branches within range of shortening - this
can set up a ripple effect, and A68k may not catch all
branches that could theoretically be optimized. Any branches
which A68k misses (there shouldn't be too many under normal
circumstances) can be displayed by specifying the '-f' switch
(see below). Branch optimization is disabled by the '-n' switch.
The INCBIN
directive allows the contents of any file to be
included in A68k's object code output. Its format is the same
as the INCLUDE
directive, but the file can contain any data
at all, printable or not. Rather than being processed as
source code by the assembler, the entire contents of the file
is copied directly to the current position in the object code
output file with no reformatting whatsoever. The effect is
the same as if DC
statements whose constants represent the
file's contents were inserted in place of the INCBIN
directive.
The opcode TTL
is accepted as a synonym for TITLE
.
A command-line option '-g' causes A68k to treat any undefined
symbol as XREF
.
The register list in a MOVEM
instruction can be an
immediate operand which specifies the actual mask bits.
(TIGCC/GCC4TI) |
The following synonyms are also supported: Starting from 2.71.F3a:
Starting from 2.71.F3c:
|
Note: This section has been written entirely by the TIGCC Team. Part of the information comes from direct.txt
by Mathieu Lacage, but the whole text is completely rewritten and contains more details. Also, some of the directives listed here are not documented in direct.txt
.
The A68k
assembler supports the following assembler directives:
arithmetic operators |
Arithmetic operators can be used exactly like their C counterparts, except that spaces are not allowed in an expression. But ((1+2)>>3)/4 is a perfectly legitimate A68k expression. Of course, you can not use anything other than + or - on labels
and you cannot use arithmetic on registers at all - you will have to use the corresponding
assembly instructions.
|
INCLUDE "filename.h" | Includes the file given as a parameter at the current source position. The file is read in as assembly source code, as if it was part of the current assembly source. |
INCBIN "filename.bin" | Includes the binary content of the file given as a parameter as-is at the current location in the object file output. The file will NOT be assembled, but included as binary data. |
EVEN |
Forces alignment on an even address. The next instruction will be guaranteed to be placed at an even address. This is especially important for dc.w or dc.l directives, since accessing a word or longword at an odd address causes an address error.
|
CNOP displacement,alignment | Forces alignment on an address which is the sum of displacement, which has to be even, and a multiple of alignment, which has to be a power of 2. |
XDEF label |
Exports the label given as an argument to other object files or to the linker. This also allows linker directives like xdef _nostub .
|
XREF label | Imports the label given as an argument. This allows to access variables from other object files even if the '-g' switch is not specified. Since GCC4TI specifies '-g' by default, there is no real need for this directive. |
PUBLIC label |
Imports or exports the label given as an argument, depending on whether it is part of the current source file or not. We recommend using XDEF or XREF instead when possible, since they clearly specify what is meant. But PUBLIC is useful when used in a common header file for multiple source files.
|
SECTION "sectname" |
Sets the section the following code will be written to. This is especially useful to make A68k use the same section as GCC : .data , in order to make sure the linking order of GCC files first is respected. (Note: You can deliberately NOT specify SECTION ".data" if you want the A68k file to be the main file.)
|
BSS |
Specifies the section the following code will be written to as a "BSS section", a section which will not be initialized at runtime, so it can contain only storage place which does not need to be initialized. Also, BSS sections are not allowed in _nostub mode.
|
CSEG |
Creates a section called "CODE " where the code will be written to. This directive is not really useful in GCC4TI, since both code and data are written to the .data section by GCC and GNU as .
|
DSEG |
Creates a section called "DATA " where the code will be written to. Do not use this directive in GCC4TI. Instead, specify SECTION .data , which is the section name used by GCC and GNU as for data sections.
|
END | Marks the end of the source file. This directive is now optional since v.2.71.F3c. |
DC.{B|W|L} data1,data2,... |
(Define Constant(s)) Will insert all the arguments as immediate data into the object file. For example, DC.L $12345678 will insert the bytes 0x12 , 0x34 , 0x56 and 0x78 into the resulting object file. DC.B 'Hello, World!',0 will insert the null-terminated string "Hello, World!" into the resulting object file.
|
DS.{B|W|L} n |
(Define Storage) Will insert n bytes, words or longwords (depending on the size specified) of zeros (0 , NOT '0' ) into the resulting object file.
|
DCB.{B|W|L} n,data |
(Define Constant Block) Will act as n times the DC.B data instruction. It will insert the immediated data specified by data n times into the resulting object file.
|
macroName MACRO |
This declares a macro so that macroName can be used as if it was an instruction, with
the difference that unlike opcodes, macro names are case-sensitive. You can also pass
arguments to a macro. Those are referenced by a macro as \n , where n
is the number of the argument, starting from 1. \0 indicates the instruction size. \@ indicates the number of the current macro, which is useful to create unique labels of the form \@label or \\@localLbl .
Therefore:
PUSH MACRO MOVE.\0 \1,-(a7) ENDM (defined in "OS.h") allows you to use: |
<expression> | Makes sure expression will be treated as a single macro parameter, even if it contains separators like commas, semicolons or whitespace. |
constant EQU value OR: constant = value | Defines a symbolic constant. Wherever constant is encountered in the code, it will be replaced by value. Note that value can also be an expression, not only a single number. |
regAlias EQUR register |
Defines an alias for a register. For example, if you are using a5 to hold the address
of the jump table in your whole program, you can write jumpTbl EQUR a5 , and then
use jumpTbl wherever you would use a5 .
|
regListAlias EQUR regList |
Defines an alias for a list of registers, for use in the MOVEM instruction. The syntax of regList is the same as in the MOVEM instruction.
For example, if you are frequently using MOVEM.L d0-d7/a0-a6,-(a7) and MOVEM.L (a7)+,d0-d7/a0-a6 , you might define: all REG d0-d7/a0-a6 , and then
use all wherever you would use d0-d7/a0-a6 .
|
variable SET value |
Defines a symbolic variable. Wherever variable is encountered in the code, it will be
replaced by value. But contrary to an EQU constant, a SET
variable can be modified. It can therefore be used as a counter for example, as in: counter SET counter+1 .
|
IFEQ value |
The instructions in the block will be parsed and assembled if and only if value equals 0. You can also write ENDIF as a synonym for ENDC .
|
IFNE value |
The instructions in the block will be parsed and assembled if and only if value does not equal 0. You can also write ENDIF as a synonym for ENDC .
|
IFGE value |
The instructions in the block will be parsed and assembled if and only if value is greater than or equal to 0. You can also write ENDIF as a synonym for ENDC .
|
IFGT value |
The instructions in the block will be parsed and assembled if and only if value is greater than 0. You can also write ENDIF as a synonym for ENDC .
|
IFLE value |
The instructions in the block will be parsed and assembled if and only if value is less than or equal to 0. You can also write ENDIF as a synonym for ENDC .
|
IFLT value |
The instructions in the block will be parsed and assembled if and only if value is less than 0. You can also write ENDIF as a synonym for ENDC .
|
IFC string1,string2 |
The instructions in the block will be parsed and assembled if and only if string1 and string2 are identical (after expansion of EQU constants). You can also write ENDIF as a synonym for ENDC .
|
IFNC string1,string2 |
The instructions in the block will be parsed and assembled if and only if string1 and string2 are different (after expansion of EQU constants). You can also write ENDIF as a synonym for ENDC .
|
IFD value |
The instructions in the block will be parsed and assembled if and only if value is a defined symbol. You can also write ENDIF as a synonym for ENDC .
|
IFND value |
The instructions in the block will be parsed and assembled if and only if value is not a defined symbol. You can also write ENDIF as a synonym for ENDC .
|
NEAR [register] | Enables the small code and data model. |
FAR |
Disables the small code and data model after a NEAR directive.
|
ORG expression |
Places the code following the directive at the address specified by expression, which must be relocatable (that is, of the form label+number , where label is a backward reference, not a forward reference). If that address is located before the current position, the code previously generated there will be overwritten. If that adress is located after the current position, the space will be filled with zeros (0 , NOT '0' ).
|
RORG offset |
Places the code following the directive at the offset offset, which must be a number, from the beginning of the current object file section. If that address is located before the current position, the code previously generated there will be overwritten. If that adress is located after the current position, the space will be filled with zeros (0 , NOT '0' ). However, if RORG is specified before the first executable instruction and in the default section (before any SECTION , BSS , CSEG or DSEG directive), no spacing will be generated, so it has the effect of adding the number address to all absolute references, thereby pre-relocating the code to that fixed address. But such an use of this directive is not useful in GCC4TI, as assembly programs on the TI-89/92+ can be at any place in memory, and the linker always generates a relocation table which allows AMS to take care of the relocation automatically.
|
NOLIST | The code following this directive will not appear in the listing file created when the '-l' or '-x' switch is specified. |
LIST |
Reenables the listing of code after a NOLIST directive.
|
PAGE | Inserts a form feed into the listing file created when the '-l' or '-x' switch is specified. |
SPC [n] | Skips n lines, or 1 line if n is omitted, in the listing file created when the '-l' or '-x' switch is specified. |
TTL string OR: TITLE string | Sets the title on the pages of the listing file created when the '-l' or '-x' switch is specified to string. Also begins a new page when specified on the middle of a page. |
IDNT "name" | Sets the program unit name in the S-record generated when the '-s' switch is specified, to name. The quotes can be omitted. This directive is not useful in GCC4TI, since GCC4TI does not use S-records. |
\localLbl | Defines a local label, a label which can be accessed only in the space between the 2 global labels surrounding it. This mainly serves to avoid name conflicts: 2 or more local labels can have the same name as long as they are separated by a global label. |
\localLbl@labelNum |
Defines a local enumeration label, invented mainly for use in macros. The idea is that labelNum can be a variable name which can be expanded while keeping localLbl unchanged. But it is usually a better idea to use \@label or \\@localLbl instead, which will automatically generate unique labels.
|
Version 2.4 implements a rudimentary small code/data model. It consists of converting any data reference to one of the following three addressing modes:
address register indirect with displacement using a
specified address register, defaulting to A4
(for references to the DATA
or BSS
section);
program counter indirect with displacement
(for references to the CODE
section);
absolute word (for absolute and 16-bit relocatable values).
These conversions do not take place unless a NEAR
directive is
encountered. The NEAR
directive can take one operand, which
must be either an address register or a symbol which has been
equated (using EQUR
) to an address register. Register A7
(SP
)
may not be used. If no register is given, A4
is assumed.
Conversion is done for all operands until a FAR
directive
is encountered. NEAR
and FAR
directives can occur any number
of times, enabling conversion to be turned on and off at will.
Backward references which cannot be converted (e.g. external
labels declared as XREF
) will remain as absolute long addressing.
All forward references are assumed to be convertible, since during
pass 1 A68k
has no way of telling whether conversion is possible.
If conversion turns out to be impossible, invalid object code will
be generated - an error message ("Invalid forward reference") will
indicate when this occurs.
Although the small code/data model can greatly reduce the
size of assembled programs, several restrictions apply:
Small code and small data models are active simultaneously.
You can't have one without the other, since during pass 1
A68k doesn't know whether forward references are to CODE
or to DATA
/BSS
.
Programs can consist of a maximum of two sections,
one CODE
, the other DATA
or BSS
. If you try to define
a third section, the message "Too many SECTIONs" will
be displayed. The NEAR
directive is active only within
the CODE
section.
While the NEAR
directive is active, external labels (XREF
)
must be declared before they are used, CODE
section references
must be with 32K of the current position (i.e. expressible as
PC-relative), and DATA
/BSS
section references must be in the
first 64K of the DATA
/BSS
section (i.e. expressible as
address register indirect with displacement). Any instructions
which do not satisfy these requirements cannot be detected in
pass 1, so A68k has no choice but to display an error message
in pass 2 ("Invalid forward reference") which in this case
indicates that invalid code has been generated. To properly
assemble such instructions, you can temporarily disable
conversion with a FAR
directive, then resume afterwards
with another NEAR
directive.
Conversion cannot be done for references between modules. All external references must be left as absolute long.
A68k
assumes that the base register (normally A4
) points to
the start of the DATA
/BSS
section plus 32768 bytes (this
assumed offset can be changed by the '-m' command-line parameter).
The register must be preloaded with this value before executing
any code converted by the NEAR
directive. One way to do this
is to code the instruction that loads the register prior to
the NEAR
directive. Another way is to use a MOVE.L
with
immediate mode, which is never converted. Here are examples
of the two methods:
LEA data+32768,a4 NEAR NEAR ;defaults to A4 MOVE.L #data+32768,a4 <remainder of code> <remainder of code> BSS BSS data: data: <data areas> <data areas> END END
I'll be the first to admit that this is a very crude and ugly implementation. I hope to improve it in future versions.
A68k
uses the following files:
The source code file - this file contains the program to be
assembled. This file is an ASCII text file whose last line
must be an END
statement.
(TIGCC/GCC4TI) |
This END statement is no longer necessary starting
from v.2.71.F3c.Moreover, the assembler will no longer accept an END
statement in include files or macros, since it did
never expect that and caused bugs. |
The object code file - this file is created by A68k
, replacing
any previous version which may exist. If any errors are
encountered during the assembly, this file will be scratched,
unless the '-k' (keep) switch is specified (see below).
Although this file is normally written in AmigaDOS format,
the '-s' switch (see below) will cause it to be written in
Motorola S-record format instead.
The listing file - this file is optionally created by A68k
and contains a listing complete with page headings (including
form feeds), generated object code, and error messages if any.
It is suitable for feeding to a printer.
An equate file - this file is optionally created by A68k
and consists of a leading comment line followed by EQU
statements, one for each symbol encountered by A68k
whose
value is absolute. This file is only created if the '-e'
command-line switch is specified (see below).
A header file - if requested, this file is read by A68k
immediately prior to the source code file. It treated
exactly as if it were requested by an INCLUDE
statement
at the front of the source file, but is selected only if
the '-h' command-line switch is specified (see below).
Include files are selected by INCLUDE
directives within the
source file, and are inserted in the source code in place
of the INCLUDE
directive itself. A68k
first searches the
current directory for INCLUDE
files; the '-i' command-line
switch (see below) specifies additional directories which
can be searched.
The names of the above files can be explicitly specified.
However, A68k
will generate default file names in the following cases:
If the '-o' switch is omitted, a default name will be assigned to the object code file.
If the '-e' switch is specified with no file name, a default name will be assigned to the equate file.
If the '-l' or '-x' switch is specified with no file name, a default name will be assigned to the listing file.
A default name is generated by deriving a stem name from the source
code file name, and appending '.o'
for an object code file name ('.s'
if the '-s' switch is specified to produce Motorola S-records), '.equ'
for an equate file name, or '.lst'
for a listing file name. The stem
name consists of all characters of the source file name up to the
last period (or the entire source file name if it contains no period).
Here are some examples of default names:
Source file | Object file | Equate file | Listing file |
myprog.asm | myprog.o | myprog.equ | myprog.lst |
myprog | myprog.o | myprog.equ | myprog.lst |
new.prog.asm | new.prog.o | new.prog.equ | new.prog.lst |
The command-line syntax to run the assembler is as follows:
a68k <source file name> [<object file name>] [<listing file name>] (TIGCC/GCC4TI) [-a] [-d[[!]<prefix>]] [-e[<equate file name>]] [-f] [-g] [-h<header file name>] [-i<include directory list>] [-k] [-l[<listing file name>]] [-m<small data offset>] [-n] [-o<object file name>] [-p<page depth>] [-q[<quiet interval>]] (TIGCC/GCC4TI) [-r[a][l][m]] [-s] [-t] (TIGCC/GCC4TI) [-u] (TIGCC/GCC4TI) [-v<name>[,<value>] [-w[<hash table size>][,<secondary heap size>]] [-x[<listing file name>]] [-y] [-z[<debug start line>][,<debug end line>]]
These options can be given in any order. Any parameter which is not
a switch (denoted by a leading hyphen) is assumed to be a file name;
up to three file names (assumed to be source, object, and listing file
names respectively) can be given. A source file name is always required.
If a switch is being given a value, that value must immediately follow
the switch letter with no intervening spaces. For instance, to specify
a page depth of 40 lines, the specification '-p40' should be used;
'-p 40' will be rejected.
Switches perform the following actions:
-a
Causes all relocs to be emitted, even PC-relative relocs within a section. It also emits address differences in a special TIGCC/GCC4TI-specific format. This will allow more aggressive linker-side optimization.
-d
Causes symbol table entries (hunk_symbol) to be written
to the object module for the use of symbolic debuggers.
If the switch is followed by a string of characters, only
those symbols beginning with that prefix string will be
written. This can be used to suppress internal symbols
generated by compilers. If the first character is an
exclamation mark ('!'
), only symbols which do not begin
with the following characters are written out. Here are some examples:
-d | writes all symbols |
-dabc | writes only symbols beginning with "abc" |
-d!x | writes symbols which do not begin with "x" |
-e
Causes an equate file (see above) to be produced. A file name can be specified; otherwise a default name will be used.
-f
Causes any branches (Bcc
, BRA
, BSR
) that could be converted
to short form to be flagged. A68k
will convert as many
branches as possible to short form (unless the '-n' switch is
is specified), but certain combinations of instructions may
set up a ripple effect where shortening one branch brings
another one into range. This switch will cause A68k
to
flag any branches that it may have missed; during pass 2
it is possible to tell this, although during pass 1 it might
not be. If the '-n' switch (see below) is specified along
with this switch (suppressing all optimization), no branches
will be shortened, but all branches which could be shortened
will be flagged.
-g
Causes any undefined symbols to be treated as if they were
externally defined (XREF
), rather than being flagged as errors.
-h
Causes a header file to be read prior to the source code file.
A file name must be given. The action is the same as if the
first statement of the source file were an INCLUDE
statement
naming the header file. To find the header file, the same
directories will be searched as for INCLUDE
files (see the
'-i' switch below).
-i
Specifies directories to be searched for INCLUDE
files in
addition to the current directory. Several names, separated
by commas, may be specified. No embedded blanks are allowed.
For example, the specification
-imylib,df1:another.lib
will cause INCLUDE
files to be searched for first in the
current directory, then in "mylib", then in "df1:another.lib".
-k
Causes the object file to be kept even if any errors were found. Otherwise, it will be scratched if any errors occur.
-l
Causes a listing file to be produced. If you want the listing file to include a symbol table dump and cross-reference, use the '-x' switch instead (see below).
-m
Changes the assumed offset from the start of the DATA
/BSS
section to the base register used when the small code/data
option is activated by the NEAR
directive.
If this parameter is not specified, the offset defaults
to 32768.
-n
Causes all object code optimization (see above) to be disabled.
-o
Allows the default name for the object code file (see above) to be overridden.
-p
Causes the page depth to be set to the specified value.
This takes the place of the PLEN
directive in the Metacomco
assembler. Page depth defaults to 60 lines ('-p60').
-q
Changes the interval at which A68k
displays the line number
it has reached in its progress through the assembly. The
default is to display every 100 lines ('-q100'). Specifying
larger values reduces console I/O, making assemblies run
slightly faster.
If you specify a negative number (e.g. '-q-10'), line numbers
will be displayed at an interval equal to the absolute value
of the specified number, but will be given as positions
within the current module (source, macro, or INCLUDE
) rather
than as a total statement count - the module name will also
be displayed.
A special case is the value zero ('-q0' or just '-q') - this
will cause all console output, except for error messages,
to be suppressed.
(TIGCC/GCC4TI) -r
Allows to disable specific optimizations:
-rm Disable the MOVEM
-> MOVE
optimization
-ra Disable the ADD(A)/SUB(A)
-> LEA
optimization
-rl Disable the LEA
-> ADDQ/SUBQ
optimization
You might use more than one -r switch (as in "-rm -ra") or combine them into a single switch (as in "-rma").
-s
Causes the object file to be written in Motorola S-record
format, rather than AmigaDOS format. The default name for
an S-record file ends with '.s'
rather than '.o
; this can
still be overridden with the '-o' switch, though.
-t
Allows tabs in the source file to be passed through to the listing file, rather than being expanded. In addition, tabs will be generated in the listing file to skip from the object code to the source statement, etc. This can greatly reduce the size of the listing file, as well as making it quicker to produce. Do not use this option if you will be displaying or listing the list file on a device which does not assume a tab stop at every 8th position.
(TIGCC/GCC4TI) -u
Disables automatic alignment of DC.W
,
DC.L
, DCB.W
, DCB.L
,
DS.W
, DS.L
and code.
(TIGCC/GCC4TI) -v
Allows to set a variable in the command line (like -d with
GCC
). The variable will be a SET
, not EQU
variable. Syntax:
"-v<name>[,<value>]" (without spaces, and without the
quotes). Note that <value> can only be a NUMBER at the
moment. (We might support symbols as values in a future
version.) The default value of <value> is 1.
-w
Specifies the sizes of fixed memory areas that A68k
allocates
for its own use. You should normally never have to specify
this switch, but it may be useful for tuning.
The first parameter gives the number of entries that the hash
table (used for searching the symbol table) will contain.
The default value of 2047 should be enough for all but the
very largest programs. The assembly will not fail if this
value is too small, but may slow down if too many long hash
chains must be searched. The hashing statistics displayed by
the '-y' switch (see below) can be used to tune this parameter.
I've heard that you should really specify a prime number for
this parameter, but I haven't gone into hashing theory enough
to know whether it's actually necessary.
The second parameter of the '-w' switch specifies the size (in
bytes) of the secondary heap, which is used to store nested
macro and INCLUDE
file information (see below). It defaults
to 1024, which should be enough unless you use very deeply
nested macros and/or INCLUDE
files with long path names.
(TIGCC/GCC4TI) | The default sizes are 4095,2048 in the Win32 (since v.2.71.F3a) and GNU/Linux (since v.2.71.F3c) versions. |
-w4093 | secondary heap size remains at 1024 bytes |
-w,2000 | hash table size remains at 2047 entries |
-w4093,2000 | increases the size of both areas |
A68k
(e.g. the actual symbol
table) is allocated as required (currently in 8K chunks).
-x
Works the same as '-l' (see above), except that a symbol table dump, including cross-reference information, will be added to the end of the listing file.
-y
Causes hashing statistics to be displayed at the end of the assembly. First the number of symbols in the table is given, followed by a summary of hash chains by length. Chains with length zero denote unused hash table entries. Ideally (i.e. if there were no collisions) there should be as many chains with length 1 as there are symbols, and there should be no chains of length 2 or greater. I added this option to help me tune my hashing algorithm, but you can also use it to see whether you should allocate a larger hash table (using the first parameter of the '-w' switch, see above).
-z
This switch was provided to help debug A68k
itself. It causes A68k
to
list a range of source lines, complete with line number and
current location counter value, during both passes. Lines
are listed immediately after they have been read from the
source file, before any processing occurs. Here are some examples of the '-z' switch:
-z | lists all source lines |
-z100,200 | lists lines 100 through 200 |
-z100 | lists all lines starting at 100 |
-z,100 | lists the first 100 lines |
The actual symbol table entries (pointed to by the hash table,
colliding entries are linked together) are stored in 8K chunks which
are allocated as required. The first entry of each chunk is reserved
as a link to the next chunk (or NULL in the last chunk) - this makes
it easy to find all the chunks to free them when we're finished. All
symbol table entries are stored in pass 1. During pass 2, cross-
reference table entries are built in the same group of chunks,
immediately following the last symbol table entry. Additional chunks
will continue to be linked in if necessary.
Symbol names and macro text are stored in another series of linked
chunks. These chunks consist of a link pointer followed by strings
(terminated by nulls) laid end to end. Symbols are independent entries,
linked from the corresponding symbol table entry. Macros are stored as
consecutive strings, one per line - the end of the macro is indicated by
an ENDM
statement. If a macro spans two chunks, the last line in the
original chunk is followed by a newline character to indicate that the
macro is continued in the next chunk.
Relocation information is built during pass 2 in yet another
series of linked chunks. If more than one chunk is needed to hold one
section's relocation information, all additional chunks are released
at the end of the section.
The secondary heap is built from both ends, and it grows and
shrinks according to how many macros and INCLUDE
files are currently
open. At all times there will be at least one entry on the heap, for
the original source code file. The expression parser also uses the
secondary heap to store its working stacks - this space is freed as
soon as an expression has been evaluated.
The bottom of the heap holds the names of the source code file
and any macro or INCLUDE
files that are currently open. The full path
is given. A null string is stored for user macros. Macro arguments
are stored by additional strings, one for each argument in the macro
call line. All strings are stored in minimum space, similar to the
labels and user macro text on the primary heap. File names are
pointed to by the fixed table entries (see below) - macro arguments
are accessed by stepping past the macro name to the desired argument,
unless NARG would be exceeded.
The fixed portion of the heap is built down from the top. Each
entry occupies 16 bytes. Enough information is stored to return to
the proper position in the outer file once the current macro or
INCLUDE
file has been completely processed.
The diagram below illustrates the layout of the secondary heap.
Heap2 + maxheap2 -----------> ___________________________ | | | Input file table | struct InFCtl *InF ---------> |___________________________| | | | Parser operator stack | struct OpStack *Ops --------> |___________________________| | | | (unused space) | struct TermStack *Term -----> |___________________________| | | | Parser term stack | char *NextFNS --------------> |___________________________| | | | Input file name stack | char *Heap2 ----------------> |___________________________|
The "high-water mark" for NextFNS
is stored in char *High2
,
and the "low-water mark" (to stretch a metaphor) for InF
is stored
in struct InFCtl *LowInF
. These figures are used only to determine
the maximum heap usage.
And Finally...
Please send me any bug reports, flames, etc. I can be reached
on Mind Link (604/533-2312), at any meeting of the Commodore
Computer Club / Panorama (PAcific NORthwest AMiga Association),
or via Jeff Lydiatt or Larry Phillips. I don't have the time
or money to live on Compuserve or BIX, but my Usenet address is
Charlie_Gibbs@mindlink.UUCP (...uunet!van-bc!rsoft!mindlink!a218).
Charlie Gibbs
2121 Rindall Avenue
Port Coquitlam, B.C.
Canada
V3C 1T9
(GCC4TI) | Since, as far as we can tell, Charlie Gibbs is no longer maintaining A68k since 1991, you are better off filing a bug report to the GCC4TI project: http://trac.godzil.net/gcc4ti/ |
Note: This section has been added to the documentation by the TIGCC Team. It was in history.txt before.
Version 2.71.F3z (Lionel Debroux, July 29, 2009)
Bugfix: Fix moveq #$FFFFFFFE,dn on 64-bit platforms.
Version 2.71.F3y (Patrick Pelissier, June 27, 2009)
Improved: the maximum length of a line has been raised from 256 to 65536.
Bugfix: don't compile A68k statically, as it fails on multiple platforms in their out of the box configuration (Lionel Debroux).
Version 2.71.F3x (Manoel Trapier, December 23, 2008)
Added: OS X Makefile that generate an Universal Binary version.
Version 2.71.F3w (Kevin Kofler, July 27, 2006)
Bugfix: Fixed compilation on *BSD and recent versions of OS X.
Version 2.71.F3v (Kevin Kofler, July 31, 2005)
Bugfix: Don't crash on EQUs doing arithmetic with other EQUs which do arithmetic with undefined symbols, print an error instead.
Version 2.71.F3u (Kevin Kofler, February 2, 2005)
Bugfix: Fixed compilation with GCC 3.4.
Version 2.71.F3t (Kevin Kofler, January 31, 2005)
Added: NO_UNOPTIMIZABLE_RELOCS compile-time define (disabled by default) to allow generating AmigaOS-compatible object files again.
Improved: Branches explicitly coded as .w are now marked unoptimizable.
Improved: Label references explicitly coded as .l are now marked unoptimizable.
Bugfix: Emitting relocations for undefined symbols which are already in the symbol table due to the forward branch optimization code now works properly.
Version 2.71.F3s (Kevin Kofler, September 21, 2004)
Added: Support for the "unoptimizable reloc" flag, keeping the linker from corrupting some instructions when optimizing.
Improved: All platforms now use the same maximum line length and chunk sizes.
Improved: The line count limit has been raised from 32767 to INT_MAX.
Version 2.71.F3r (Kevin Kofler, July 19, 2004)
Bugfix: Fixed label(PC,Rn) addressing when "label" was in a different section (again) (reported by Julien Moutinho).
Version 2.71.F3q (Kevin Kofler, December 30, 2003)
Bugfix: Fixed label1-label2(an) in all-relocs mode (reported by hwti).
Added: (In all-relocs mode,) don't emit an address difference when the 2 labels are actually at the same address (or simply the same). This allows to keep optimizing label1-label1(an) into (an).
Bugfix: Fixed a bug when range-checking branches in all-relocs mode (reported by hwti).
Bugfix: Fixed a bug when range-checking short branches in all-relocs mode or to a different section (reported by hwti).
Version 2.71.F3p (Kevin Kofler, December 1, 2003)
Bugfix: Fixed label(PC,Rn) addressing in all-relocs mode or when "label" was in a different section (reported by Matthieu Gallet).
Version 2.71.F3o (Kevin Kofler, October 5, 2003)
Bugfix: Range checking now works correctly in all-relocs mode. (No more spurious out-of-range errors.)
Version 2.71.F3n (Kevin Kofler, September 28, 2003)
Bugfix: Local labels now work in all-relocs mode.
Version 2.71.F3m (Kevin Kofler, September 2, 2003)
Bugfix: PC-relative or indexed references to other sections didn't work.
Bugfix: x(PC,Dn) or x(PC,An) didn't work in all-relocs mode.
Version 2.71.F3l (Kevin Kofler, July 15, 2003)
Added: The -u switch now also allows unaligned code, which can be useful when the code will be copied somewhere else anyway.
Added: Short branches across hunks or object files are now allowed.
Added: -a (All relocs) switch, which tells A68k to emit all relocs, even PC-relative relocs within a section. It also emits address differences in a special TIGCC-specific format. This will allow more aggressive linker-side optimization.
Version 2.71.F3k (Kevin Kofler, May 17, 2003)
Bugfix: Increased the forward reference buffer in order to allow multiple labels at the same location, as used in PedroM.
Added: -u (Unaligned) switch, which disables automatic alignment of DC.W, DC.L, DCB.W, DCB.L, DS.W and DS.L.
Version 2.71.F3i (Kevin Kofler, February 1, 2002)
Bugfix: Local labels caused a "Pass 1 / Pass 2 phase error" when preceded by an include file which contained labels, but was skipped in pass 2 (such as OS.h).
Version 2.71.F3h (Kevin Kofler, January 23, 2002)
Bugfix: The TITLE (or TTL) directive did not work at all. It now works as it is supposed to.
Bugfix: No longer crashes when trying to generate a listing file with cross-references (using the -x switch).
Version 2.71.F3g (Kevin Kofler, January 22, 2002)
Bugfix: The RORG and PUBLIC directives are now recognized correctly even if the first letter is not capitalized. Thanks to Brandon Sterner for reporting the problem with the RORG directive.
Version 2.71.F3f (Kevin Kofler, January 8, 2002)
Now also accepts ";", and for the -v switch also "=", as
separator in command line arguments (wherever "," is
allowed), for compatibility with the "-WA," switch in
tigcc
.
Version 2.71.F3e (Kevin Kofler, August 3, 2001)
Bugfix: The SUB->LEA optimisation did not change the sign of the immediate value.
Version 2.71.F3d (Kevin Kofler, July 28, 2001)
Bugfix: The ADD(A)/SUB(A)->LEA and LEA->ADDQ/SUBQ optimizations caused "Pass 1 / Pass 2 phase errors" if an optimization was known to be possible only in pass 2 (i.e. if using forward references to labels in the instruction). A68k will not try to optimize those anymore. Maybe a future version will provide support for this kind of optimization, but it is very difficult to implement.
Bugfix: A68k did not compile correctly on Visual C++ because I had done a define in an incorrect way.
Version 2.71.F3c (Kevin Kofler, July 20, 2001)
Applied a few patches submitted by Paul Froissart:
A few more adaptations for compiling with Microsoft Visual C++. (Note that I still recommend using GCC for Mingw32.)
A new command line switch:
-v
Allows to set a variable in the command line (like -d with GCC). The variable will be a SET, not EQU variable. Syntax: "-v<name>[,<value>]" (without spaces, and without the quotes). Note that <value> can only be a NUMBER at the moment. (We might support symbols as values in a future version.) The default value of <value> is 1.
Improved the optimization:
made optional the optimization which changes MOVEM with a single register to MOVE
added an optional optimization which changes ADD(A) and SUB(A) to LEA when applicable
added an optional optimization which changes LEA to ADDQ or SUBQ when applicable
added a command line switch which allows you to selectively disable some optimizations:
-r
Allows to disable specific optimizations:
-rm | Disable the MOVEM -> MOVE optimization |
-ra | Disable the ADD(A)/SUB(A) -> LEA optimization |
-rl | Disable the LEA -> ADDQ/SUBQ optimization |
Added 2 more synonyms:
SLO = SCS
SHS = SCC
The END directive is now optional. If you do not use it, the assembly will automatically end at the end of your source file.
Also fixed a bug found by Paul Froissart involving the reporting of invalid flags with the SECTION directive. (Not that anyone would use those flags anyway.)
Adapted and applied a very old patch by John Antonishek, which allows you to define a symbol as XDEF even if it has been declared as XREF before. This is especially useful when using a common include file for globals.
Moreover, END is not allowed in macros or include files anymore since that was causing a few bugs because A68k simply did not expect anyone to use it there. The quickest remedy is to simply remove the END instruction, since it is now optional anyway.
Version 2.71.F3b (Kevin Kofler, July 12, 2001)
Bugfix: Now raises an error if an undefined local label is used.
Bugfix: Branches coded with an explicit length (.W or .L)
are not optimized (or flagged as optimizable)
anymore.
(In previous versions, .B or .S was not optimized,
but .W or .L could be optimized to a short branch.
Now, only branches without an explicit length will
be optimized.)
Bugfix: Quoted strings can now be passed as macro arguments without the need for '<' and '>', even if they contain spaces or separators (',' or ';'). You can still use '<' and '>', for example in order to pass strings like <129,' version'> (which will appear as "� version" on a TI-89/92/92+).
Version 2.71.F3a (Kevin Kofler, July 9, 2001)
Win32 port for the TIGCC project, compiled with GCC for
Mingw32.
Even though we recommend Mingw32, A68k should also compile
with Microsoft Visual C++, thanks to Paul Froissart.
(Please do NOT ask me questions about compiling with
Visual C++. I have just put in Paul Froissart's ifdefs.)
It also compiles with Cygwin, but since the result is
larger than the Mingw32 version, I do not see any benefit
in using it.
Bugfix: My Win32 port of v.2.71.F3 did not support labels or variable names which contain accented characters.
Bugfix: Now detects all errors in include files. All include files will be treated in pass 2 if an error is detected.
Bugfix by Paul Froissart: fixed a random crash bug due to a missing initialization
Bugfix by Julien Muchembled: allow odd displacements for words and longwords if the resulting address might be even
The Win32 version is now less greedy with the memory, so its limitations are less annoying:
lines can now be 256 bytes long (Paul Froissart)
filenames (with path) can now be 259 bytes long (the Win32 maximum)
the default heap sizes have also been increased (Paul Froissart)
Added the following synonyms:
BLO = BCS
BHS = BCC
DBLO = DBCS
DBHS = DBCC
ROLX = ROXL
RORX = ROXR
Version 2.71.F3 (David Ellsworth, July 11, 2000)
Fixed a bug introduced by my modifications that prevented branches from being optimized in Global XRef mode.
Version 2.71.F2 (David Ellsworth, January 22, 1998)
Made A68k properly differentiate between PC-relative and absolute references to external symbols. Allowed branches to reference external labels in Global XRef (-g parameter) mode.
Version 2.71.F1 (David Ellsworth, January 7, 1998)
Made changes so that combinations of EQU, XREF, and XDEF directives work better together. These changes were made in order for Fargo II library linking to be easier to do.
The F1 stands for Fargo patchlevel 1.
Version 2.71 (Charlie Gibbs, April 16, 1991)
The following bugs in version 2.62 have been corrected:
Enforcer checks were being generated if command-line parameters that took a numeric value had no value or the value was invalid. CalcValue was attempting to look up a label in the symbol table, which having not been allocated yet was causing a null pointer to be dereferenced. (Patrick Quaid)
The following enhancements have been added:
Function prototyping has been added. All function prototypes are in a new include file, protos.h, which is included by A68kdef.h. Prototyping can be disabled (for compilers which do not support it) by defining the symbol __NOPROTO; in this case old-style function declarations are generated instead.
Version 2.70 (Charlie Gibbs, February 25, 1991)
The following bugs in version 2.62 have been corrected:
The definition of tempstr in WriteSymTab (24 bytes) was being overrun in some cases, causing A68k to hang. Its length has been increased to MAXLINE. (Paul Gittings, John Antonishek)
If A7 was in a list of registers in the source operand of a MOVEM instruction, all registers would be moved (i.e. the mask was set to 0xFFFF). (Risto Kaivola)
Octal or binary values that set bit 31 were being flagged as overflow errors. (Harvey Taylor)
ORGs were unnecessarily restricted when the -s flag was specified. Everything should be absolute when S-records are generated, and any absolute ORG should be allowed.
The following enhancements have been added:
A new INCBIN directive has been added. It takes a single operand, a file name whose contents are included as is at the current position in the object code file. (Julian Gold, Colin Fox)
The opcode TTL is now accepted as a synonym for TITLE.
The file mode in the creat() call in xopen() has been changed from 1 to 0644; this provides a reasonable file mode when compiled on a Unix system. (Paul Gittings)
A new command-line keyword (-g) has been added. It causes all undefined symbols to be treated as XREF. (Paul Gittings, Steve Hawtin (who provided the code))
All initialized fields in opcodes.c have been made global for compatibilty with more compilers. (Steve Hawtin)
The register list in a MOVEM instruction can now be an immediate operand which specifies the actual mask bits. (Paul Gittings, who provided the code)
The default value for the -q option has been changed from 10 to 100.
Version 2.62 (Charlie Gibbs, March 19, 1990)
The following enhancements have been added:
A new command-line keyword (-m) has been added. It must be immediately followed by a number which specifies the offset from the beginning of a small data section to the base register specified in the NEAR directive (defaulting to A4). If this parameter is omitted, the offset defaults to 32768 bytes. This parameter is meaningful only if the NEAR directive is used. (Colin Fox)
Version 2.61 (Charlie Gibbs, January 11, 1990)
The following bugs in version 2.6 have been corrected:
ORG and RORG at the beginning of the program were being processed incorrectly. (Jukka Jarvinen)
A branch instruction to its own label, e.g.
lab bra lab
would cause phase errors; the instruction was being shortened on pass 2 but not on pass 1. (Kevin Hoare)
The following enhancements have been added:
Labels may begin with '@' if the next character is not numeric (to avoid confusion with octal constants). (Colin Fox)
Write errors now cause A68k to terminate gracefully with an appropriate error message.
Version 2.6 (Charlie Gibbs, November 2, 1989)
The following bugs in version 2.5 have been corrected:
If a space is left between a file keyword and the file name (e.g. A68k -l foo.lst foo.asm) the source file was scratched. (E. Lenz)
All code using post-increment addressing in references to toupper() has been reworked to avoid post-increment. Such code does not work correctly if toupper() is a macro. (John K. Antonishek)
The spelling of the include files A68kdef.h and A68kglb.h has been made correct as to case. This simplifies porting to case-sensitive file systems. (John K. Antonishek)
If comments immediately follow the operands of an XDEF, XREF, or PUBLIC statement with no intervening white space (as in any of the following statements), A68k would hang:
XDEF foo;comments XREF bar;comments PUBLIC blah;comments
(Bruce Dawson)
Numeric values (any radix) which do not fit into 32 bits were not being flagged. (E. Lenz)
DC statements with no operands were not being flagged. (E. Lenz)
The -f option was suggesting short branches where the displacement would be zero, which is illegal. (E. Lenz)
Branches outside the current section had the offset set to zero. (Matt Dillon, who provided a fix)
ADDI, ANDI, CMPI, EORI, ORI, and SUBI instructions whose source operand was not immediate were not being flagged. (E. Lenz)
Unary NOT of a byte or word immediate operand whose value was negative was being flagged as a size error. (John Aycock)
All forward branches were rejected when the NEAR directive was active. (Colin Fox)
The following enhancements have been added:
Single-byte immediate operands (e.g. MOVE.B #-1,(a0)) are now padded with a high-order byte of zero, rather than being sign-extended. (E. Lenz)
The message "Error in operand format." has been changed to "Addressing mode not allowed here." in places where the latter message is more appropriate.
If the -q option species a value of zero (or no value is given, defaulting to zero), all console output will be suppressed except for error messages, if any. (Matt Dillon)
The 128-byte restriction on constant length no longer applies to the entire code generated by a single DCB statement; statements such as
DCB.L 64,0
can now be handled. (Colin Fox)
Forward branches are now optimized. The occasional instruction may be missed due to ripple effects, but this shouldn't happen frequently. The -f switch will flag any such instructions.
The -d switch can now be followed by an optional prefix string (with or without a leading !) which specifies which symbols should or should not be included in the symbol table dump. (Lionel Hummel)
Version 2.5 (Charlie Gibbs, June 18, 1989)
The following bugs in version 2.42 have been corrected:
Upon normal termination, A68k occasionally crashed in quit_cleanup by trying to free the relocation table twice. (Jeff Lydiatt and D. McClelland, who worked out a fix)
MEMF_CHIP and MEMF_FAST bits were being set in the hunk length, rather than in the hunk type. (Richard Man)
BCHG.L, BCLR.L, BSET.L, and BTST.L were causing phase errors. The test to ignore the .L specification (added in version 1.21) was being skipped in pass 1 by an optimization added in version 2.4. (David Hankins)
PC-relative offset to a label was calculated as two bytes too great for MOVEM instructions. (Tony Parkhurst)
The following enhancements have been added:
If the length code on an opcode is not .B, .W, .L, .S, or omitted, it will be flagged as an error.
JMP.S and JSR.S are flagged as errors. (Jim Butterfield)
Operands of the form (xxxx).W and (xxxx).L are now supported. This enables absolute short or absolute long addressing to be explicitly specified.
All optimization can be disabled by the new -n switch. (David Hankins)
The NEAR directive can now take a single operand, which can be any address register (or equated symbol) except A7. If omitted, the register defaults to A4.
Instructions of the form BTST Dn,#nn are no longer flagged. This obscure variant is nonetheless legal.
Version 2.42 (Charlie Gibbs, January 10, 1989)
The following bugs in version 2.41 have been corrected:
Small code/data conversion was sometimes taking place when no NEAR directive was active. (Jeff Lydiatt)
Version 2.41 (Charlie Gibbs, January 6, 1989)
The following bugs in version 2.4 have been corrected:
The second operand of LINK instructions was being erroneously flagged.
If a macro was used before it was defined, it was being expanded during pass 2 but not during pass 1, causing severe phase errors. Attempts to use a macro before it is defined will now be flagged as invalid opcodes. (Colin Fox)
Version 2.4 (Charlie Gibbs, January 4, 1989)
The following bugs in version 2.31 have been corrected:
If comments immediately followed the operands of a DC statement with no intervening white space, A68k would hang. (Ulf Nordquist)
In the following command:
a68k -w 15000 myprog.asm
the space between the -w and 15000 would cause A68k to look for a source file called "15000", and to think that the object file is to be called "myprog.asm". When it can't find "15000" it would display an error message and scratch "myprog.asm". (Jeff Lydiatt)
If an INCLUDE file that is skipped on pass 2 contains a macro call, subsequent uses of \@ (macro sequence number are subsequently flagged. The macro counter must be bumped along with the line number when skipping an INCLUDE. (Colin Fox, Harvey Taylor)
The following enhancements have been added:
ORG and RORG are now fully implemented.
The SET symbols A68k, a68K, and a68k are defined in the same way as A68K, making it effectively case-insensitive. (Colin Fox)
MOVEM and REG now accept equated register names (EQUR) in register lists. (Bruce Dawson)
INCLUDE files will now be skipped on pass 2 even when a listing file is requested, if the listing has been turned off by a NOLIST directive before the INCLUDE, and is not turned on until after the end of the INCLUDE file has been reached. (Colin Fox)
A new switch (-f) causes forward branches (Bcc, BRA, BSR) that could be coded as short branches (Bcc.S etc.) to be flagged. This flag is not considered to be an error.
A limited small code / small data model has been provided. It is activated by a NEAR directive in the source code, and is de-activated by a FAR directive. External variables must be declared at the beginning of the program, which must consist of only two sections (CODE and DATA or BSS). All forward data references are assumed to be PC-relative if in the CODE section, A4-relative if in the DATA/BSS section, and absolute word if absolute values. Any forward references which cannot be resolved to one of these three in pass 2 will be flagged as errors, as will any attempt to define more than two sections. A4 is assumed to point to the start of the DATA/BSS section plus 32768 bytes, and must be loaded by a MOVE.L instruction using immediate mode unless this instruction is not enclosed within NEAR and FAR directives.
Miscellaneous optimizations, for speed, including: Most of the object code generator in pass 1 is bypassed. If GetValue gets a single term it takes a short cut. IsOperator now uses a table look-up. Instructions now only searches that portion of the opcode table whose opcodes start with the same letter as the OpCode being searched for.
Version 2.31 (Charlie Gibbs, November 30, 1988)
The following bugs in version 2.3 have been corrected:
Even though a macro definition was being skipped by IFxx/ENDC, its ENDM directive was still being detected, causing spurious diagnostics. (Harvey Taylor)
NOP was not being recognized. When moving all directives into the opcode table, NOL and NOLIST were placed after NOP, rather than before. (Colin Fox)
Symbols defined in the current module and declared as PUBLIC were not being written to the object code file when -d was specified. (Colin Fox)
Conversion of 0(An) to (An) (implemented in version 1.2) was causing errors in the MOVEP instruction, which requires a displacement even if it is zero. This conversion is now disabled for MOVEP instructions.
User macros containing invalid opcodes caused A68k to get lost when returning to the outer source file. (Colin Fox)
Large values of -w (over 6000 or so) would cause a visit from the Guru. The work field in HashIt was overflowing and going negative. Changing it to unsigned corrected the problem. (Colin Fox)
Although user macros are no longer displayed when -q is a negative number, the calling file's name was still being displayed at the end of the macro.
Version 2.3 (Charlie Gibbs, November 21, 1988)
The following enhancements have been added:
All file I/O has been rewritten to use level 1 I/O (open, creat, close, read, write, and lseek) instead of level 2 I/O. A68k now does its own buffering and unbuffering to reduce system overhead and increase speed. (Bruce Dawson)
All assembler directives have been incorporated into the opcode table. Since the opcode search now looks up directives as well, speed is increased.
Miscellaneous code optimization for additional speed.
Version 2.2 (Charlie Gibbs, November 4, 1988)
The following bugs in version 2.1 have been corrected:
Macro definitions within an INCLUDE file were disabling the test for skipping the file on pass 2.
Errors encountered in an INCLUDE file on pass 1 were not disabling the skip of the file on pass 2 - the pertinent error messages could not appear.
XDEF information and optional symbol table dumps were not being written to the object code file for any hunks that did not contain relocatable code or data. (Colin Fox)
The following enhancements have been added:
If the -q option is specified as a negative value, user macros are no longer included in line number displays, reducing clutter.
Some source code has been re-arranged to reduce size.
Version 2.1 (Charlie Gibbs, November 1, 1988)
The following bugs in version 2.00 have been corrected:
Macro definitions that span two chunks of memory were causing garbage and probably a crash when the macro was being expanded. Pointers were not being handled properly when linking the two chunks.
Statements such as EQU and SET were not being flagged as illegal forward references if referencing a label defined on the same line, e.g.
LABEL SET LABEL+1
The position within macros and INCLUDE files was sometimes out by one line when reported in error messages (and the new feature of the -q switch).
The following enhancements have been added:
If the -q option is specified as a negative value, line numbers will be displayed as positions within the current module (whose name is also displayed), rather than a total statement count. (Bruce Dawson)
INCLUDE files can be skipped on pass 2 even if they contain SET statements - the values of all symbols SET in the INCLUDE file are stored (as at the end of the file) in a separate table and are patched when the INCLUDE file is skipped. (Bruce Dawson)
Version 2.00 (Charlie Gibbs, October 26, 1988)
The following bugs in version 1.24 have been corrected:
The last digit of the statement number display (lengthened in version 1.24) was not being erased before displaying error messages.
A68k would go into a loop if a user macro was missing an ENDC directive. This error is now flagged (see below).
The following enhancements have been added:
The highest statement number displayed at the end of each pass is now left on the screen. This means that, at the end of pass 1, you can always see how many lines A68k will have to process in pass 2, giving an idea of how how much longer you have to wait. (Colin Fox)
The symbol table is now built using a hashing algorithm. This eliminates the slowdown that occurs in pass 1 as the symbol table grows, due to the old insertion process. (Bruce Dawson)
If A68k terminates abnormally for any reason (such as insufficient memory) the object file is scratched (unless the -k option is set). (Bruce Dawson)
Any INCLUDE files which cannot be found are flagged as errors in pass 1, and the assembly is aborted at the end of pass 1. (Bruce Dawson)
Missing ENDC directives are flagged in macro expansions. Also, missing or unpaired ENDC directives in user macros are flagged.
If an INCLUDE file doesn't generate any code and no listing file is required, it won't be read again in pass 2. The statement numbers will be bumped to keep in proper alignment. This can really speed up assemblies that INCLUDE lots of equates. (Colin Fox)
Version 1.24 (Charlie Gibbs, October 11, 1988)
The following bugs in version 1.23 have been corrected:
MOVEA to a data register was not being flagged, even though all other invalid addressing modes were.
Attempts to ORG out of the current hunk (including to an absolute address) were not being flagged. (E. Lenz)
If the size of the bottom of the primary heap (symbols and macro text) exceeded 32K, any further macro definitions would expand as endless garbage. (Colin Fox)
If the size of the bottom of the primary heap (symbols and macro text) exceeded 64K, any further external symbols (XDEF) would be flagged as relocatability errors upon each reference. (Colin Fox)
The following enhancements have been added:
Where statement numbers are displayed as fixed-length fields, their maximum length has been increased from 4 digits to 5. (Colin Fox)
The PUBLIC directive has been implemented. As with the Aztec assembler, any labels defined as PUBLIC will be treated as XDEF if defined within the current module, and XREF otherwise. (Jeff Lydiatt)
Version 1.23 (Charlie Gibbs, September 20, 1988)
The following bugs in version 1.22 have been corrected:
The test for a third operand was producing erroneous error messages on instructions whose second operand was in immediate mode. The '#' was not being taken into account, since it is not copied to DestOp.
Version 1.22 (Charlie Gibbs, August 31, 1988)
The following bugs in version 1.21 have been corrected:
Expressions of the form R-A, where R is a relocatable term or expression and A is an absolute term or expression, were being flagged as relocation errors. This was due to a bug in the routine which should (but did not) flag expressions of the form A-R. (David Ashley)
Instructions with three operands were not being flagged as errors. This can be caused by an extra comma being typed in the instruction, as in:
BTST #0,state+3,(a5)
The second comma should not be present. (David Ashley)
The following enhancements have been added:
Excess spacing has been removed from the listing file. These changes are similar to those already made to the console output (probably at about version 1.05).
If the first statement in the source file is TTL or PAGE, an empty page is no longer produced at the start of the listing.
Version 1.21 (Charlie Gibbs, July 29, 1988)
The following bugs in version 1.2 have been corrected:
The instruction
BTST.L #8,D0
had a long-word value generated for the bit number. This bug also applies to BSET, BCLR, and BCHG. The .L specification is now ignored. (Ulf Nordquist)
Version 1.2 (Charlie Gibbs, July 19, 1988)
The following bugs in version 1.12 have been corrected:
A reference to the label of the current instruction was being converted to PC-relative on pass 2 but not on pass 1. This was causing phase errors. The label hasn't been added to the symbol table at the time the instruction is processed. Conversion to PC-relative addressing will now not be attempted in this case, although references to * can and will be converted.
All string-type DC statements, regardless of length, were being treated as DC.B. For example, DC.L 'A' would generate only one byte of object code. (Gerald Hull)
DC.W and DC.B statements were not being checked to ensure that their values would fit into a word or a byte respectively.
If a comment line had white space preceding the asterisk, A68k would hang. Actually, it was interpreting the asterisk as an opcode and trying to open a macro file called "*". Since under AmigaDOS such a file is the console, A68k was actually waiting for console input.
If an instruction with no operands (such as RTS or NOP) followed MOVE.L #rel,D0 where "rel" was a relocatable symbol, the RTS (etc.) would have its nonexistent operands flagged as invalid.
SECTION names enclosed in quotes were not being handled correctly.
Source modules that did not generate any code, data, or BSS areas, but only defined symbols, such as
label equ 4 xdef label end
were generating incomplete object modules.
The following enhancements have been added:
Jeff's experimental hunk code (prefixing hunk names with a sequence number before adding to the symbol table) has been permanently incorporated. It seems to work better with BLink on programs that have hunks continued farther on in the source code. (Jeff Lydiatt)
The macro parameter \0, which is replaced by the size specification in the macro call (B, W, or L, defaulting to W) is now supported. (Gerald Hull)
Operands of the form 0(An) will be treated as (An). (Bruce Dawson)
Version 1.12 (Charlie Gibbs, May 25, 1988)
The following bugs in version 1.11 have been corrected:
If an instruction with no operands (e.g. RTS) followed a MOVE.L #label,D0 the RTS would be flagged with a relocatability error. Src.Mode and Dest.Mode were not being cleared. (Colin Fox)
Version 1.11 (Charlie Gibbs, April 6, 1988)
The following bugs in version 1.10 have been corrected:
A68k would go into a loop while processing the arguments of a macro call, if these arguments are followed by comments separated from the arguments by one or more tab characters, and the -t switch is specified on the command line. All tests for blanks have been replaced by calls to isspace().
The operand alignment checks added in version 1.06 were erroneously testing the following instructions:
BCHG
BCLR
BSET
BTST
NBCD
Scc
TAS
These instructions are now exempt from alignment checking.
The following enhancements have been added:
A listing file name can now be specified with the -x switch; it is no longer necessary to specify both the -l and -x switches to produce a cross- reference listing with a name other than the default.
DS statements with more than one operand are flagged and ignored (in case they should be DC).
A character string used as a numeric value is flagged and set to zero if it is more than four characters long.
Version 1.10 (Charlie Gibbs, March 20, 1988)
The following bugs in version 1.07 have been corrected:
BSS sections were not being written to the object code file except for a BSS section at the end of a program. This is due to a bug in the code added in version 1.05 to overwrite null sections.
If a source module contained a mixture of lengths (8, 16, or 32 bits) in external references (XREF) to the same label, all references were being treated as if they has the length of the first reference.
The following enhancements have been added:
DS operands that are either a forward references or relocatable are now flagged.
Short branches (Bcc.S, including BRA and BSR) to the next instruction (i.e. a displacement of zero) are illegal - the processor takes the displacement from the next word. Attempts to generate a short displacement of zero are now flagged.
Version 1.07 (Charlie Gibbs, March 11, 1988)
The following bugs in version 1.06 have been corrected:
Instructions that take no operands (such as RTS) were being flagged if they had comments that were not preceded by a semicolon.
The following enhancements have been added:
The following synonyms have been added:
CSEG for CODE (Aztec compatibility) DSEG for DATA " " ENDIF for ENDC (Assempro compatibility) = for EQU " " | for ! " "
Strings and character values may be delimited by either apostrophes (') or quotation marks ("). The character not used as a delimiter can be used within the string without doubling it. For example,
DC.B "This is Charlie's assembler"
produces the same code as
DC.B 'This is Charlie''s assembler';
The object code file will be scratched if any errors were found, unless the -k (keep) flag is set. (Bruce Dawson)
The symbol .A68K is automatically defined at the beginning of each assembly as a SET symbol with an absolute value of 1. This enables programs to check whether they're being assembled by this assembler. (Jeff Lydiatt)
The symbol table insertion routine has been greatly speeded up.
Version 1.06 (Charlie Gibbs, March 6, 1988)
The following bugs in version 1.05 have been corrected:
Lines skipped by IFxx/ENDC were not being counted in the line number given in error messages.
DATA and BSS sections may be unnamed, or have names the same as CODE sections. Honest, I thought section names had to be unique even across types.
CHIP and FAST options on the CODE, DATA, and BSS synonyms for the SECTION directive were not being handled correctly.
XDEF records and symbol table records (if desired) were not being produced for symbols defined ahead of the first object-code producing instruction.
The following enhancements have been added:
The CNOP instruction can now force alignment relative to any boundary up to 128 bytes. The second operand must still be a power of 2.
The -q switch has been added to change the frequency with which progress reports (current line number) are displayed on the console. The default remains at every 10 lines (-q10). If you specify -q (no interval) or -q0 the line number displays will be suppressed. This will make assemblies run slightly faster due to reduced console I/O. (Bill Henning)
The -t switch has been added to keep any tabs in the source file when producing the listing file, as well as generating tabs elsewhere whenever possible. This speeds up assemblies and gives smaller listing files, but such listing files cannot be displayed on devices that do not assume a tab stop in every 8th position. (Bruce Dawson)
Any single-operand instruction with two operands, and any no-operand instruction with any operands, will be flagged.
Relocatable 8- or 16-bit immediate operands will be flagged. They blow up BLink.
Named local labels are now supported. Their names are formed in the same way as normal labels, but are then preceded by a backslash. Their scope is the same as normal local labels (nnn$). (Colin Fox)
An alignment error will be flagged in the following cases:
Odd displacement on a LINK instruction
Bcc or DBcc to an odd address
In any word or long-word instruction, any operand using the following addressing modes:
Address register indirect with displacement
Address register indirect with index and displacement
Absolute short
Absolute long
Program counter indirect with displacement
Program counter indirect with index and displacement
LEA and PEA instructions are exempt from these tests.
If a section is found to contain no data, A68k will back up to its beginning and overwrite it with the next section. The result is that null sections will no longer appear in the object file.
Version 1.05 (Charlie Gibbs, October 30, 1987)
The following bugs in version 1.04 have been corrected:
If a section was continued later in the program, e.g.
SECTION prog,CODE <code> SECTION variables,BSS <DS statements> SECTION prog,CODE <more code>
bad relocation information was being generated for the continuation of the SECTION. This bug was left over from version 1.03.
The following enhancements have been added:
All console output except for error messages is now sent to stderr - this enables stdout to be redirected, producing an error file.
Console (stderr) output has been modified to require fewer lines on the screen.
If an error occurs while expanding a macro or INCLUDE file, the position of the call in each outer file is given along with the position in the current (innermost) file. Tracing continues until the outermost file (i.e. the original source file) is reached.
Version 1.04 (Charlie Gibbs, October 21, 1987)
The following bugs in version 1.03 have been corrected:
MOVE was being converted to MOVEQ regardless of operand size - this conversion is legal only for longword MOVEs.
Modifications to version 1.03 caused bad relocatable entries to be generated.
Version 1.03 (Charlie Gibbs, October 14, 1987)
The following bugs in version 1.02 have been corrected:
The following situation was causing phase errors:
xdef label bra label . <at least 128 bytes of object code> . label:
(The XDEF was fooling A68k into thinking that "label" was defined within 128 bytes of the BRA instruction on pass 1, although on pass 2 it knew better.
If the first operand of an two-operand executable instruction contained a character term containing a left or right parenthesis, it would generate error messages and be incorrectly evaluated.
Labels that don't begin in column 1 (denoted by a trailing colon) caused a Guru Meditation.
Certain ADD and SUB instructions using PC-relative addressing may cause phase errors. If the displacement is in the range 1 to 8 inclusive, the instruction was erroneously converted to ADDQ or SUBQ during pass 2.
The following enhancements have been added:
The -z option has been added to display the current source program line on stdout as it is read, optionally over a given range. This feature is provided for debugging purposes.
Bcc, BSR, and DBcc to labels in other than the current section is now supported. A 16-bit relocation entry will be generated for each such reference.
PC relative mode will be generated for backward references to labels within the current CODE section if legal for the current instruction. Forward references will not be converted, since there is no way of telling which section the label is in during pass 1.
The cumulative sizes of all sections by type (i.e. CODE, DATA, and BSS) will be displayed at the end of the listing file and the console display. (Bruce Dawson)
In the symbol table dump, section names will no longer be indicated just as SECTION, but rather as CODE, DATA, or BSS, depending on type.
Version 1.02 (Charlie Gibbs, September 9, 1987)
The following bugs in version 1.01 have been corrected:
Duplicate labels were not being flagged.
XDEF symbols were not being dumped to the object code file when the -d option was set.
The following enhancements have been added:
A header file is now supported. If the parameter -h<filespec> is included on the command line, the specified file will be included as if the source file's first line was " include <filespec>". The file specification may include a path name, although the include path names given by the -i parameter (if any) will also be searched.
An equate file can now be produced. If the parameter -e<filespec> is included on the command line, a file will be written containing EQU statements for any symbol whose value is absolute. If -e is specified without <filespec>, the name of the file will be formed in the same way as the list file, except with an extension of ".equ". (Bruce Dawson)
The following changes have been made to existing logic:
No symbol table dump will be produced unless the -x (cross-reference) switch is set. Formerly a symbol table dump was always produced, with only the cross-reference portion optional.
Version 1.01 (Charlie Gibbs, August 20, 1987)
The following bugs in version 1.00 have been corrected:
Long-word constants and storage areas were being aligned on a double-word boundary. The only place where double-word alignment is now forced is at a break between SECTIONs, since the length of an AmigaDOS hunk must be a multiple of 4 bytes. (CNOP 0,4 can still be used if double-word alignment is desired by the programmer.)
If a label on an END statement or the first statement of a SECTION was named in an XDEF statement, it would not be written to the object code file. The latter case includes both the label of a SECTION directive and the label of the first executable instruction in the absence of any SECTION directives (defaulting to an unnamed CODE section). In the final case (default unnamed CODE section), references to XREF symbols in the first statement would also not be written to the object code file.
If the last statement in the source file was not terminated with a newline character (premature EOF), it was being ignored altogether.
A register list as the source operand of a MOVE instruction was not being flagged as an error. (MOVE to a register list was being flagged, however.)
MOVE from USP was generating incorrect code. Also, MOVE from SR or CCR to an address register was generating incorrect code rather than being flagged.
Version 1.00 (Charlie Gibbs, June 18, 1987) - initial release