9. Target specifics¶
This chapter describes the built-in target-specific support.
The support is enabled using the --target option which has the
following effects:
Select a suitable default
--core.Enable preprocessor macros to identify the target and core used. This can be used for conditional compilation, in both the compiler and the assembler.
Additional target specific header files can be included using
#include <file.h>.Enable certain language extensions to suit the target, if applicable. This will also affect certain aspects of the code generator to take advantage of extensions and capabilities of the target.
When using
--targetthe linker will assume a RAM based system where a program is loaded into memory and data sections are initialized by loading the data in place. This is a sensible default, but can be controlled using the--rom-codeand--copy-initializeoptions.
The installation comes with header files, pre-built target specific board support link libraries and linker control files.
9.1. Board support¶
Enabling board support in the linker requires two conditions:
First, specify the appropriate --target option. Second, use a supplied
linker control file whose name corresponds to the board support.
For example, this means that to select to link with a Commander X16 board support you need to specify:
$ ln6502 --target=x16 cx16-plain.scm [object-files]
For a MEGA65 target you would specify:
$ ln6502 --target=mega65 mega65-plain.scm [object-files]
Note
If you need to alter the supplied linker rules file or create your
own, name it with the same prefix name as the board support one.
The linker will first look in the current directory for the
.scm file, then in the installation directory.
The following table gives an overview of the board support definition.
|
name |
core |
kernel/OS |
|
PRG entry |
|---|---|---|---|---|---|
C64 |
Commodore 64 |
6502 |
Kernal |
|
|
MEGA65 |
MEGA65 |
45GS02 |
Kernel |
|
|
CX16 |
Commander X16 |
65C02 |
Kernel |
|
|
9.2. Commodore 64¶
The Commodore 64 is a well-known classic computer using the 6502
core. The Calypsi C compiler tool chain supports creating Commodore 64 friendly interrupt
functions using the kernal_interrupt attribute.
While the Commodore 64 has the ability to swap in and out overlayed
ROMs, it is otherwise a plain 64K addressed machine.
Board support¶
The board support includes C header files, a link library and linker
control files. They originate from
Commodore 64 board support
project. The current variant is built from commit hash
d9c0ff8d5a4dae6937e58a88ced346e645182b5a.
The header files come from the
LLVM MOS SDK
project. The current variant is built from commit hash
a1ae3437888ef0a597f69019611390eb8159c2e4.
Header files¶
The supplied header files are:
include path |
description |
|---|---|
|
Includes all Commodore 64 headers |
|
6526 Complex Interface Adapter |
|
SID sound chip |
|
VIC-II graphics chip |
Pre-built library¶
The Commodore 64 library, which includes startup code, exit handling, and I/O
adaption between the C library and the C64 Kernal, comes pre-built.
Your application is automatically linked with it if you specify
--target=64 and use a linker rules file starting with the c64-
prefix:
$ ln6502 --target=c64 c64-plain.scm [object-files]
The installation provides several library variants to accommodate different
compiler settings, such as double size. The linker automatically selects a
compatible variant for your application.
Linker rules¶
The linker rules use the c64- prefix. If you create your own linker
rules file, naming it with this prefix ensures automatic linking with the
supplied pre-built Commodore 64 library.
c64-plain.scm¶
(define memories
'((memory program
(address (#x801 . #x9fff)) (type any)
(section (programStart #x801) (startup #x80e)))
(memory zeroPage (address (#x2 . #xff)) (type ram) (qualifier zpage))
(memory stackPage (address (#x100 . #x1ff)) (type ram))
(memory freeSpace (address (#x02a7 . #x02ff)) (section zpsave))
(memory upperdata
(address (#xc000 . #xcfff))
(section cstack zdata heap))
))
This memory system uses the full BASIC RAM area, allowing data to reside
in the 0xc000 to 0xcfff area.
Preserving the zero page¶
The C compiler runtime reserves approximately 50 bytes of zero page space. On a Commodore 64, the BASIC runtime reserves most of the zero page. Returning to BASIC with a corrupted state can make the BASIC runtime unstable.
If your application needs to return safely to BASIC, request these zero page locations be preserved. To enable preserving the C runtime zero page area, add the following line to your application:
#pragma require __preserve_zp
Note
If you run the application multiple times in RAM, non-zero static
storage variables are left with their previous value and are not
reinitialized when the --target=c64 option is used.
To properly initialize such variables on each run, you need to also
use the --rom-code option.
9.3. MEGA65¶
The MEGA65 is a new 8 bit computer inspired by the Commodore 65. It comes with a 45GS02 instruction set which is a superset of the 6502 instruction set. The 45GS02 provides both additional instructions as well as new addressing modes.
The cc6502 compiler can generate code for the 45GS02 instruction set and it can also make use of its additional addressing modes. The 45GS02 provides 32 bit addressing modes to allow access the full memory space. The alternative bank system provided by the MEGA65 is not used by cc6502 compiler when accessing data beyond 64K.
Code banking on the other hand makes use of an 8K slot and the
MAP instruction of the 45GS02.
The math co-processor on the MEGA65 is supported by the compiler which means it will inline integer multiply and unsigned divide. While the math unit is used, interrupts are disabled to prevent a potential race condition if an interrupt function also uses the math unit.
Board support¶
The board support includes C header files, a link library and linker
control files. They originate from
MEGA65 board support
project. The current variant is built from commit hash
d9c0ff8d5a4dae6937e58a88ced346e645182b5a.
The header files come from the
LLVM MOS SDK
project. The current variant is built from commit hash
a1ae3437888ef0a597f69019611390eb8159c2e4.
Header files¶
The supplied header files are:
include path |
description |
|---|---|
|
Includes all MEGA65 headers |
|
SID sound chip |
|
VIC-II graphics chip |
|
VIC-III graphics chip |
|
VIC-IV graphics chip |
|
6526 Complex Interface Adapter |
|
45E100 Fast Ethernet controller |
Pre-built library¶
The MEGA65 library includes startup code, exit handling and I/O
adaption between the C library and the MEGA65 kernel. It comes pre-built and
your application will automatically be linked with it if you specify
--target=mega65 and use a linker rules file starting with the
mega65- prefix:
$ ln6502 --target=mega65 mega65-plain.scm [object-files]
The installation provides several library variants to accommodate different
compiler settings, such as double size. The linker automatically selects a
compatible variant for your application.
Linker rules¶
The linker rules are named with the mega65- prefix. If you create your
own linker rules file, it is a good idea to name it with this prefix,
as this will make the linker automatically link with the supplied
pre-built MEGA65 library.
mega65-plain.scm¶
(define memories
'((memory program
(address (#x2001 . #x9fff)) (type any)
(section (programStart #x2001) (startup #x200e)))
(memory zeroPage (address (#x2 . #x7f)) (type ram) (qualifier zpage)
(section (registers #x2)))
(memory stackPage (address (#x100 . #x1ff)) (type ram))
(memory freeSpace (address (#x1600 . #x1eff)) (section zpsave))
))
This describes memory system that uses the full BASIC memory area and keeps everything in the first 64K bank.
mega65-banked.scm¶
(define memories
'((memory program
(address (#x2001 . #x9fff)) (type any)
(section (programStart #x2001) (startup #x200e)))
(memory zeroPage (address (#x2 . #x7f)) (type ram) (qualifier zpage)
(section (registers #x2)))
(memory stackPage (address (#x100 . #x1ff)) (type ram))
(memory freeSpace (address (#x1600 . #x1eff)) (section zpsave))
(memory bank1 (address (#x10000 . #x1ffff)) (type data) (qualifier far))
(memory bank45 (address (#x40000 . #x5ffff)) (type data) (qualifier far))
))
This describes memory system that uses the full BASIC memory area and allows Far data to be located in bank 1, 4 and 5.
Notes on 45GS02 instruction set¶
The assembler syntax used mostly follows the MEGA65 book. The 45GS02
uses some overloaded opcodes, e.g. for NOP and NEG
instructions which may change the meaning depending of the instruction that
follows. This is recognized and handled by the Calypsi tools.
Conditional long branch instruction deviates from the MEGA65 book in
that they are prefixed by an L character, e.g. LBCC for a long
branch on carry clear. This is done to distinguish them from the
normal short form.
Data beyond 64K¶
The memory space attributes provided by the cc6502 compiler allows
transparent access to the full memory. There are two pointer
attributes far and huge which allows access to the full system
memory. They differ in that far limits the object size to a single
bank which is 64K. Any far C object is allocated into one such
bank and is not allowed to cross a bank boundary.
If you need to use larger objects, then you can use the huge
memory space. A huge object can be as large as the system memory
allows.
Accessing data beyond 64K with either far or huge comes with
some additional cost in terms of code space and execution time.
Note
The reason that far uses fictive 64K banks is to give better
code generation as pointers arithmetics only need to update the
lower 16 bits rather than the full 32-bit address.
Code beyond 64K¶
To access code outside the 64K memory the MAP instruction in the
45GS02 is used. This allows for mapping an 8K bank of code at
a time to the slot at address 0xa000-0xbfff by default.
Preserving the zero page¶
The C compiler runtime reserves roughly 50 bytes of zero page space. On a MEGA65 the zero page is mostly reserved by the BASIC runtime. Returning to BASIC with a corrupted state can make the BASIC runtime unstable.
If your application needs to return safely to BASIC, request these zero page locations be preserved. To enable preserving the C runtime zero page area, add the following line to your application:
#pragma require __preserve_zp
Note
If you run the application multiple times in RAM, non-zero static
storage variables are left with their previous value and are not
reinitialized when the --target=mega65 option is used.
To properly initialize such variables on each run, you need to also
use the --rom-code option.
9.4. Commander X16¶
The Commander X16 system is based around a 64K memory space with RAM and ROM banking. The VERA graphics chip holds the keeps the video memory in a separate memory that is not directly addressable by the 65C02 CPU.
The Commander X16 board support currently do not provide mechanisms to automatically handle banked memory or the VERA video RAM.
The kernel used is based on the Commodore 64 kernel. There is support
for creating kernel friendly interrupt functions using the
kernal_interrupt attribute.
Board support¶
The board support includes C header files, a link library and linker
control files. They originate from
Commander X16 board support
project. The current variant is built from commit hash
d9c0ff8d5a4dae6937e58a88ced346e645182b5a.
The header files come from the
LLVM MOS SDK
project. The current variant is built from commit hash
a1ae3437888ef0a597f69019611390eb8159c2e4.
Header files¶
The supplied header files are:
include path |
description |
|---|---|
|
Includes all Commander X16 headers |
|
6522 Versatile Interface Adapter |
Pre-built library¶
The Commander X16 library includes startup code, exit handling and I/O
adaption between the C library and the Commander X16 kernel. It comes pre-built and
your application will automatically be linked with it if you specify
--target=x16 and use a linker rules file starting with the cx16-
prefix:
$ ln6502 --target=cx16 cx16-plain.scm [object-files]
The installation provides several library variants to accommodate different
compiler settings, such as double size. The linker automatically selects a
compatible variant for your application.
Linker rules¶
The linker rules are named with the cx16- prefix. If you create your
own linker rules file, it is a good idea to name it with this prefix,
as this will make the linker automatically link with the supplied
pre-built Commander X16 library.
cx16-plain.scm¶
(define memories
'((memory program
(address (#x801 . #x9fff)) (type any)
(section (programStart #x801) (startup #x80e)))
(memory zeroPage (address (#x2 . #x7f)) (type ram) (qualifier zpage)
(section (registers #x2)))
(memory stackPage (address (#x100 . #x1ff)) (type ram))
(memory VRAM (address (#x00000 . #x1ffff))
(section zvram vram))
))
This describes memory system that uses the full BASIC memory area.
cx16-banked.scm¶
(define memories
'((memory program
(address (#x801 . #x9fff)) (type any)
(section (programStart #x801) (startup #x80e)))
(memory zeroPage (address (#x2 . #x7f)) (type ram) (qualifier zpage)
(section (registers #x2)))
(memory stackPage (address (#x100 . #x1ff)) (type ram))
(memory VRAM (address (#x00000 . #x1ffff))
(section zvram vram))
(memory bankSlotRAM
(address (#xa000 . #xbfff))
(scatter-to RAM-banks)
:generate-instances
(section bankedcode))
(memory bankedRAM (address (#x2000 . #x1fffff))
(section RAM-banks))
))
This describes memory system that uses the full BASIC memory area
and allows for banked code in the 0xa000–0xbfff slot.
9.5. Linking¶
When linking for a system like the Commodore 64, MEGA65 or Commander X16 you will normally use a binary load format such as PRG, PGZ or RAW.
Such file is typically loaded from some storage media and doing this
can initialize data sections by as part of the load process. This is
enabled by either specifying the --target or the --hosted
command-line option.
You may want to place the application in a ROM or flash memory so that
it can be started either by turning on the computer or having it act like a
resident application invoked by some call mechanism from the operating
system. Use the --rom-code command-line option to get this
bevaior. This creates a ROM section with initializers that are copied
over to RAM as part of the initialization process before the
main() function is called.
Note
Loading a program from media that is compiled with --hosted (or
--target) and then restarting the program again will not
re-initialize static variables that are non-zero. They will keep
their values after the previous run. If you want to be able to
restart a loaded program, consider linking with the --rom-code
command-line option.
9.6. Banked linking¶
Banked memory can be set up using the scatter-to property of a memory. See Scatter for an overview.
To map in a memory bank in a slot in the 64K memory area the compiler translates the scatter-to (storage) address of the bank in a way that works with the bank system. This is done using a target dependent relocation operator. The low portion of the address are formed by combining the address of the slot and low portion of the address.
Somewhat simplified, once properly linked, the compiler runtime handles the bank system automatically.
Custom bank systems¶
Using scatter-to combined with manual manipulation of the bank mechanism also allows for making your own bank system. In such situations you probably need to control where functions are placed, which can be done using custom sections. see Description of pragma directives.
Clever management of section names allows for placing code together with data so that they appear in the same bank and are visible together when mapped into a block.
Note
For advanced custom bank system function inlining may cause
problems. This is because functions may be inlined in other
functions that belong in different sections. If data is being
stored together, you may want to prevent such inlining from
happening.
You can use the --inline-on-matching-custom-text-section
command-line option to prevent it,
see Controlling inline expansion.