

.. _target-specifics:

****************
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 ``--target`` the 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-code`` and ``--copy-initialize`` options.

The installation comes with header files, pre-built target specific
board support link libraries and linker control files.

.. index:: board support; enabling, enabling; board support

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:

.. code-block:: sh

   $ ln6502  --target=x16  cx16-plain.scm  [object-files]

For a MEGA65 target you would specify:

.. code-block:: sh

   $ 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.

.. table:: Board support definitions
 :widths: 2 3 2 2 2 2
 :column-dividers: none single single single single single none
 :column-alignment: left left left left left left



 +--------------+---------------+---------+-------------+-------------------+-------------+
 | ``--target`` | name          |  core   |  kernel/OS  |  ``.scm`` prefix  | PRG entry   |
 +==============+===============+=========+=============+===================+=============+
 | C64          | Commodore 64  | 6502    | Kernal      | ``c64-``          | ``0x801``   |
 +--------------+---------------+---------+-------------+-------------------+-------------+
 | MEGA65       | MEGA65        | 45GS02  | Kernel      | ``mega65-``       | ``0x2001``  |
 +--------------+---------------+---------+-------------+-------------------+-------------+
 | CX16         | Commander X16 | 65C02   | Kernel      | ``cx16-``         | ``0x801``   |
 +--------------+---------------+---------+-------------+-------------------+-------------+

.. index:: Commodore 64

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 <https://github.com/hth313/Calypsi-6502-Commodore>`_
project. The current variant is built from commit hash
``d9c0ff8d5a4dae6937e58a88ced346e645182b5a``.

The header files come from the
`LLVM MOS SDK <https://github.com/hth313/llvm-mos-sdk>`_
project. The current variant is built from commit hash
``a1ae3437888ef0a597f69019611390eb8159c2e4``.

Header files
------------

The supplied header files are:

.. table:: Commodore 64 header files
 :widths: 2 3
 :column-dividers: none single single none
 :column-alignment: left left

 +-------------------------------+------------------------------------------+
 | include path                  |  description                             |
 +===============================+==========================================+
 | ``#include <c64.h>``          | Includes all Commodore 64 headers        |
 +-------------------------------+------------------------------------------+
 | ``#include <_6526.h>``        | 6526 Complex Interface Adapter           |
 +-------------------------------+------------------------------------------+
 | ``#include <_sid.h>``         | SID sound chip                           |
 +-------------------------------+------------------------------------------+
 | ``#include <_vic2.h>``        | 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:

.. code-block:: sh

   $ 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``
^^^^^^^^^^^^^^^^^

.. code-block:: hex

    (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:

.. code-block:: C

   #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.



.. index:: MEGA65

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 <https://github.com/hth313/Calypsi-6502-Commodore>`_
project. The current variant is built from commit hash
``d9c0ff8d5a4dae6937e58a88ced346e645182b5a``.

The header files come from the
`LLVM MOS SDK <https://github.com/hth313/llvm-mos-sdk>`_
project. The current variant is built from commit hash
``a1ae3437888ef0a597f69019611390eb8159c2e4``.

Header files
------------

The supplied header files are:

.. table:: MEGA65 header files
 :widths: 2 3
 :column-dividers: none single single none
 :column-alignment: left left

 +-------------------------------+------------------------------------------+
 | include path                  |  description                             |
 +===============================+==========================================+
 | ``#include <mega65.h>``       | Includes all MEGA65 headers              |
 +-------------------------------+------------------------------------------+
 | ``#include <_sid.h>``         | SID sound chip                           |
 +-------------------------------+------------------------------------------+
 | ``#include <_vic2.h>``        | VIC-II graphics chip                     |
 +-------------------------------+------------------------------------------+
 | ``#include <_vic3.h>``        | VIC-III graphics chip                    |
 +-------------------------------+------------------------------------------+
 | ``#include <_vic4.h>``        | VIC-IV graphics chip                     |
 +-------------------------------+------------------------------------------+
 | ``#include <_6526.h>``        | 6526 Complex Interface Adapter           |
 +-------------------------------+------------------------------------------+
 | ``#include <_45E100.h>``      | 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:

.. code-block:: sh

   $ 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``
^^^^^^^^^^^^^^^^^^^^

.. code-block:: hex

    (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``
^^^^^^^^^^^^^^^^^^^^^

.. code-block:: hex

    (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:

.. code-block:: C

   #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.

.. index:: Commander X16

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 <https://github.com/hth313/Calypsi-6502-Commodore>`_
project. The current variant is built from commit hash
``d9c0ff8d5a4dae6937e58a88ced346e645182b5a``.

The header files come from the
`LLVM MOS SDK <https://github.com/hth313/llvm-mos-sdk>`_
project. The current variant is built from commit hash
``a1ae3437888ef0a597f69019611390eb8159c2e4``.

Header files
------------

The supplied header files are:

.. table:: Commander X16 header files
 :widths: 2 3
 :column-dividers: none single single none
 :column-alignment: left left

 +-------------------------------+------------------------------------------+
 | include path                  |  description                             |
 +===============================+==========================================+
 | ``#include <cx16.h>``         | Includes all Commander X16 headers       |
 +-------------------------------+------------------------------------------+
 | ``#include <_6522.h>``        | 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:

.. code-block:: sh

   $ 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``
^^^^^^^^^^^^^^^^^^

.. code-block:: hex

    (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``
^^^^^^^^^^^^^^^^^^^

.. code-block:: hex

    (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.


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.

.. index:: banking, code banking, data banking

Banked linking
==============

Banked memory can be set up using the scatter-to property of a memory.
See :ref:`scatter-to` 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 :ref:`section-pragma`.

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 :ref:`controlling-inline-expansion`.
