ASDF is a cross-compiler toolchain for AmigaOS 1.2, based on GCC, vlink and the Newlib C standard library. Supported languages are C and assembly.
The idea is to use recent GCC and Binutils version to generate object code in ELF format and then link with vlink to generate Amiga Hunk executable files for AmigaOS (680x0).
Included components:
-
GNU Compiler Collection 7.5.0 For compiling C source code. GCC is licensed under GPL.
-
GNU Binutils 2.34 Includes assembler and various ELF file utilities. Binutils is licensed under GPL.
-
vlink 0.16c portable multi-format linker
vlink is a key component of this toolchain with its excellent multi-format support which allows for linking ELF object files to Amiga Hunk executables.
vlink is copyright Frank Wille. See the vlink web page or the document
vlink.pdf
for more information on license conditions. -
vasm 1.8g portable and retargetable assembler
vasm is copyright Frank Wille. See the vasm web page or the document
vasm.pdf
for more information on license conditions. -
newlib is an implementation of the C standard library intended for use on embedded systems.
The newlib source code is licensed under many different (open) licenses. See
newlib/COPYING.NEWLIB
in the Newlib source distribution for details. -
ASDF glue layer Implements the Newlib portability layer for AmigaOS and run-time startup code. Licensed under FreeBSD license.
-
Scripts and patches
Additional components, not distributed with the toolchain:
- Native Developer Kit for AmigaOS 3.9 contains support files for developing AmigaOS applications. Available for download from the copyright holders web-site, but with unknown distribution conditions. Copyright 1985-2001 Amiga, Inc.
This toolchain will probably not generate the fastest or smallest Amiga binaries. The goals are rather:
- Developer friendliness
- GCC 7 lint/warnings
- Binutils object file tools
- Standard compliance
- Newlib is serious about the standard
- Correctness
- GCC test suite.
ASDF is currently distributed in source code format.
ASDF is known to build successfully in the following environments:
- Debian GNU/Linux 8.8 (jessie)
- Debian GNU/Linux 9.1 (stretch)
- Debian GNU/Linux 10 (buster)
- FreeBSD 12.0
The following software has to be preinstalled in the system:
- curl
- lha
- Bash
- Tcl
- Texinfo
- Tex Live (
pdflatex
) - GNU make
- Compiler for build system (GCC or Clang)
- GCC build dependencies (see the document titled Installing GCC)
To Install prerequisites in FreeBSD 12.0:
$ pkg install curl lhasa bash tcl86 texinfo texlive-full gmake mpc
Use the following command to build ASDF from source:
$ ./scripts/build.sh all dist
Optionally, --nopdf
, can be given on the command line to prevent building
documentation in PDF format, and thus eliminating the pdflatex
dependency.
The toolchain is installed in the opt/asdf/
directory of the repository
top-level directory. This installation directory can be moved to any suitable
location or soft-linked. opt/asdf/bin/
should be added to the search path
with something like this:
$ PATH="$PWD/opt/asdf/bin:$PATH"
A tar.gz
archive is created for the installation and build log files are
located in the log/
directory.
For information on how to run the GCC test suite with vamos, see the file dejagnu/README.
The GCC front-end m68k-asdf-elf-gcc
can be used for most operations,
including compiling, assembling and linking.
To compile the source file main.c
into an (ELF) object file named main.o
:
$ m68k-asdf-elf-gcc -O2 -c main.c -o main.o
Link to an Amiga Hunk executable file with:
$ m68k-asdf-elf-gcc hello.o -o hello.hunk
To inspect how the compiler translates C code into assembly:
$ m68k-asdf-elf-gcc -O2 -S -fverbose-asm myfunc.c -o myfunc.s
Assembly source code can be assembled with the GNU assembler gas:
$ m68k-asdf-elf-as myfunc.s -o myfunc.o
or vasm:
$ asdf-vasm -phxass -Felf myfunc.s -o myfunc_elf.o
$ asdf-vasm -phxass -Fhunk myfunc.s -o myfunc_hunk.o
Standard GCC (m68k) options can be used:
-
-O0
,-O1
,-O2
,-O3
,-Os
,-Og
, etc.Control optimization.
-
-Wall
,-Wextra
,-pedantic
, etc.Request compiler warnings.
-
-mcpu=68020
,-mcpu=68040
,-mcpu=68060
, etc.Generate code for a specific processor.
-mcpu=68000
is used by default. -
-msoft-float
Do not use hardware floating-point instructions.
-
-std=89
,-std=c99
, etc.Specify language standard.
-
-fno-omit-frame-pointer
Put frame pointer in register
a6
in function prologues.-fomit-frame-pointer
is used by default. -
-Wl,option
Pass an
option
to the linker (vlink
). -
-S
Stop compiler before assembling. Can be used together with the
-fverbose-asm
option to annotate the assembly code with C source. -
-mshort
Use 16-bit integers (instead of 32-bit which is the default). Objects compiled for 16-bit integers should not be mixed with code compiled for 32-bit.
Options specific to ASDF:
-
-qnstart
Link application with nano startup code for small applications which do no require system realated C standard library services. This options is applicable to linking only.
Multilib version of Newlib and libgcc are provided for 68000/68020/68040/68060, with and without soft-float. To list all available multilibs, use:
$ m68k-asdf-elf-gcc -print-multi-lib
Adding the -v
option when compiling or linking gives more information on
search locations for headers and libraries.
Tools prefixed with m68k-asdf-elf-
in the asdf/bin
directory have short
names, prefixed with asdf-
. These are just soft links to the default names.
$ ls -l asdf-objdump | cut -d ' ' -f 9-
asdf-objdump -> m68k-asdf-elf-objdump
Documentation for the tools and C library is available in PDF format in the
opt/asdf/doc/
directory. Manual pages are also available, and should be
available when PATH
has been setup as described above. For example:
$ man m68k-asdf-elf-size
By default, applications are linked with a startup object named ustart.o
(u
for micro). It prepares a C run-time environment for use with Newlib, with
support for:
-
Dynamic memory allocation
malloc()
,realloc()
,free()
, etc. Memory is automatically deallocated at return frommain()
and whenexit()
orabort()
is called. -
File I/O
<stdio.h>
functions such asfopen()
,fwrite()
,fgetc()
,fseek()
, etc. Files opened with<stdio.h>
are closed on return frommain()
and when callingexit()
orabort()
. -
Time related functions
<time.h>
functions such astime()
and a limitedclock()
.dos.library/DateStamp()
is used internally. -
atexit()
By default, the C run-time is highly compatible with the C standard library.
The GCC front-end has been configured with knowledge of paths to NDK 3.9
includes and linker libraries (amiga.lib
and debug.lib
).
Standard startup is implemented in ustart.s and ustart_main.c.
An option to the full C run-time environment startup code is to link with the
nstart.o
startup object, which is selected with the GCC link option
-qnstart
.
The purpose of the nano startup is to support small applications.
nstart.o
does the following:
- Initializes
SysBase
- Calls
main()
- Returns to the shell when
main()
returns
AmigaOS library functions can be called as usual with amiga.lib
stubs and
Amiga library prototypes in <clib/[lib]_protos.h>
.
Some notable limitations when using the nstart.o
startup code:
argc
is0
andargv[argc]
isNULL
.- File I/O using
<stdio.h>
is not supported.dos.library
can be used. - C library dynamic memory allocation is not supported when using the nano
startup.
exec.library
functions such asAllocMem()
andFreeMem()
, can be used instead. Note also that many Newlib functions call dynamic memory functions internally, which means that functions such assnprintf()
can not be used with the nano startup and will likely end up in linker errors. exit()
,abort()
andatexit()
will not work.- The
main()
return value is interpreted as a 16-bit signed integer which is sign extended before passing it as return code (32-bit) to AmigaDOS.
Nano startup is implemented in nstart.s.
To create a custom startup module, link the application with -nostdlib
and
provide your own startup object file as the first object to the linker.
Startup code from Commodore-Amiga, Inc.
can be used.
With the compiler option -mshort
, the int
type becomes 16 bits wide instead
of 32 bits. This is useful on the 68000 processor which has a 16-bit data bus,
or as a general way to save data cache.
The function calling convention is different between compiling with and without
-mshort
: integer parameters occupy one 16-bit word on the stack instead of
one 32-bit longword. Thus it is not possible to link object files compiled with
and without -mshort
. One implication of this is that an application compiled
with -mshort
can not be linked with the Newlib libc.a
or libm.a
, since
they are compiled with 32-bit integers.
Furthermore, the compiler itself may generate calls to memcmp()
, memset()
,
memcpy()
and memmove()
in some situations, for example when copying objects
or initializing data structures on the stack. A workaround is to manually
provide -mshort
implementations for these functions when linking the
applicaton.
A safe way to link a 16-bit integer application is to use the options
-nostdlib
or -nodefaultlibs
and then resolve any missing references
manually.
Compiling Newlib with -mshort
does not seem to be supported.
The following compiler options are implied (GCC specs):
-fno-omit-frame-pointer
which prevents the compiler from reserving an address register for use as frame pointer. This can be reverted with-fno-omit-frame-pointer
.-fleading-underscore
which prefixes all symbol names with an underscore character, as per the Amiga symbol name convention. Assembly code is free to use non-prefixed symbol names, but these can not be referenced from C code.-isystem [toolchain]/m68k-asdf-elf/sys-root/include_h
for direct access to NDK includes.
For more details, see
$ m68k-asdf-elf-gcc -dumpspecs
The examples directory contains examples on how the toolchain can
be used. See the README
files in each subdirectory for more information.
- Starting applications from Workbench is not supported.
- Soft-float seems to be broken for the
long double
type. - GCC option
-fpic
, to generate position-independent code, does not work. - Inline prototypes for AmigaOS
proto/
are not yet available. However, see examples/takesys/xproto.h how it can be implemented.<clib/[lib]_protos.h>
andamiga.lib
stubs are supported. getenv()
andsetenv()
is available but the namespace is isolated from AmigaOS.signal()
andraise()
does nothing.clock()
does not tell the truth. The function returns the amount of time that has elapsed since some point in the past. Thus it can be used to measure wall-clock time. The value can be divided byCLOCKS_PER_SEC
to obtain the number of seconds.
For information on how to rebuild selected parts of the toolchain, see scripts/build.sh.