

*******************
Extended attributes
*******************

An *attribute* is a property attachable to functions, data objects,
or types, specified as a keyword. Standard C includes built-in
keywords like ``const`` and ``volatile``.

Extended attributes provide access to behaviors or properties beyond
Standard C. They are either target-specific or useful for embedded
systems.

.. index:: attributes, extended attributes

Overview
========

Attributes can be applied with either keyword syntax (e.g.,
``__zpage``) or attribute syntax (e.g.,
``__attribute__((zpage))``). Both are functionally equivalent,
but the C parser may not accept the keyword form in some situations.

Usage is largely a matter of preference. Preprocessor macros can rename
attributes for portability, enabling them to be toggled off for other
targets or renamed to match different compilers or targets.

.. note::

   The C parser sometimes produces unexpected errors with the keyword
   form of attributes (e.g., ``__zpage``). If this occurs,
   use the ``__attribute__((zpage))`` form instead.

Using attributes
================

Type attributes can be applied to type declarations, following the same
syntax as type qualifiers like ``const`` and ``volatile``.

Syntax for data objects
-----------------------

You can apply attributes to data objects as follows:

.. code-block:: C

   __attribute__((zpage)) int a, b;
   int __zpage c, d;

When applied to an object, the attribute's location is irrelevant.
The example above applies the Zero page attribute to all
defined objects (``a``, ``b``, ``c``, and ``d``).

Syntax for pointer types
------------------------

Attributes can also be applied to pointer types, where their location
is significant. This determines whether the pointer itself is constant
or what it points to is constant.

The easiest way to decipher attributes in function types is to read the
type from right to left.

.. code-block:: C

   int __attribute__((zpage)) * p1;
   long * __attribute__((zpage)) p2;

Here, ``p1`` is a pointer stored in default memory that points to an
``int`` in Zero page memory. ``p2`` is a pointer stored
in Zero page memory that points to a ``long`` in default
memory.

Attribute reference
===================

This section goes through all available extension keywords and
attributes.

Summary of attributes
---------------------

The following table summarizes available attributes. For the keyword
form, prefix with two underscores (e.g., ``__zpage``). For
attribute syntax, use the attribute name with ``__attribute__`` (e.g.,
``__attribute__((zpage))``).

.. table:: Extended attributes summary
 :widths: 1 3
 :column-dividers: none single none
 :column-alignment: left left

 +--------------------------+----------------------------------------------+
 |Attribute name            |Description                                   |
 +==========================+==============================================+
 | ``aligned(nn)``          | Specifies alignment for data objects or      |
 |                          | functions                                    |
 +--------------------------+----------------------------------------------+
 | ``section("name")``      | Specifies the section name for a data        |
 |                          | object or function                           |
 +--------------------------+----------------------------------------------+
 | ``zpage``                | Controls storage of data objects to the      |
 |                          | zero page                                    |
 +--------------------------+----------------------------------------------+
 | ``interrupt``            | Defines an interrupt function                |
 +--------------------------+----------------------------------------------+
 | ``kernal_interrupt``     | Defines a Commodore 64 kernal-friendly       |
 |                          | interrupt                                    |
 +--------------------------+----------------------------------------------+
 | ``intrinsic``            | Declares an intrinsic function               |
 +--------------------------+----------------------------------------------+
 | ``task``                 | Relaxes preserving registers                 |
 +--------------------------+----------------------------------------------+
 | ``far``                  | Controls storage of data objects to far      |
 |                          | memory (MEGA65 only)                         |
 +--------------------------+----------------------------------------------+
 | ``huge``                 | Controls storage of data object to huge      |
 |                          | memory (MEGA65 only)                         |
 +--------------------------+----------------------------------------------+


Description of attributes
-------------------------

This section describes each attribute in detail.

.. index:: aligned; attribute, attribute; aligned, alignment

``aligned``
^^^^^^^^^^^

This attribute can be applied to functions, global and static data
objects to force a certain minimal alignment.

The ``aligned`` attribute takes an argument which is the alignment to
use:

.. code-block:: C

   __attribute__((aligned(16))) struct sprite ship;

.. note::

   Certain data types may impose an alignment by themselves. The
   actual alignment is choosen so that all alignment constraints are
   satisfied.

.. index:: section; attribute, attribute; section

``section``
^^^^^^^^^^^

This attribute can be applied to functions, global and static data
objects to control the name of the section it is placed in.

The ``section`` attribute takes an argument which is the section name
to use:

.. code-block:: C

   // Place in vram
   __attribute__((section("vram")))
   const char tiles[256] = { .. };

   __attribute__((section("trueCode")))
   long foo () {
     return 42;
   }

See :ref:`section-pragma` for how you can specify a section for multiple
functions,
global and static data objects.

.. index:: zpage; attribute, attribute; zpage, zero page

``zpage``
^^^^^^^^^

Specifies a data object or a pointer to a data object residing in the
*zero page*. Zero page addressing yields shorter, faster code and is
particularly efficient for 6502 pointer operations.

.. note::

   Auto variables are typically allocated to registers or zero page
   pseudo-registers, automatically providing the benefits of zero page
   addressing. The ``zpage`` attribute is best suited for smaller,
   frequently used static data objects.

.. index:: far; attribute, attribute; far

``far``
^^^^^^^^^

The ``far`` attribute specifies data in memory beyond the 64K provided
by the base 6502. It is available only when the MEGA65 is enabled.

On the MEGA65, the 45GS02 CPU provides additional addressing
capabilities. The amount of ``far`` data objects is limited only by
available memory.
A single ``far`` object can be at most 65535 bytes large.

.. index:: huge; attribute, attribute; huge

``huge``
^^^^^^^^^

The ``huge`` attribute specifies data in memory beyond the 64K provided
by the base 6502. It is available only when the MEGA65 is enabled.

On the MEGA65, the 45GS02 CPU provides additional addressing
capabilities. The amount of ``huge`` data objects is limited only by
available memory.

.. note::

   The ``huge`` attribute typically generates larger applications than
   the ``far`` attribute. Use ``huge`` only if absolutely necessary.

.. index:: interrupt; attribute, attribute; interrupt

``interrupt``
^^^^^^^^^^^^^

An interrupt function serves as an interrupt handler and has the
following effects:

 #. An interrupt function cannot take parameters

 #. It preserves all registers used.

 #. Exiting the interrupt function uses a different instruction
    sequence than normal functions

 #. The interrupt attribute may optionally be given a vector address
    as an argument

.. index:: interrupt;  vector

The interrupt vector is specified as an argument to the interrupt
attribute:

.. code-block:: C

   int counter;

   __attribute__((interrupt(0xfffe)))
   void irq () {
     counter++;
   }

.. note::

   The vector argument is optional. Omitting it results in no vector
   section entry being generated for that interrupt function. All vector
   sections can also be suppressed using the ``--no-vector-sections``
   command-line option.

.. note::

   It is strongly recommended to keep interrupt functions small and
   simple. Avoid making function calls from an interrupt function, as this
   requires preserving scratch registers, which is costly. If function
   calls are necessary, consider forcing them to be inline expanded. See
   :ref:`inline` for more information.

.. index:: interrupt; Commodore 64 kernal, attribute; kernal_interrupt
.. index:: kernal; interrupt
.. index:: Commodore 64; interrupt
.. index:: Commander X16; interrupt

``kernal_interrupt``
^^^^^^^^^^^^^^^^^^^^

The ``kernal_interrupt`` attribute defines an interrupt function for
the Commodore 64 kernal. It can also be used by Commander X16, as they
share the same mechanism.

Kernal interrupt functions must be installed using the
``_Kernal_set_interrupt_handler()`` function, included in the C
library.

.. code-block:: C

   #include <kernal/interrupt.h>

   __attribute__((kernal_interrupt))
   void myirq () {
     counter++;
   }

   int main () {
     __kernal_vector_t old_vector;

     old_vector = _Kernal_set_interrupt_handler(myirq);

     ... application code

     _Kernal_restore_interrupt_handler(old_vector);
     return 0;
   }

Installing a new vector writes it to location ``0x0314`` and saves the
previous one in a library-internal variable. The kernal interrupt
function exits by jumping via this saved pointer.

Before exiting your application, restore the old vector.


.. index:: intrinsic; attribute, attribute; intrinsic

``intrinsic``
^^^^^^^^^^^^^

The ``intrinsic`` attribute declares built-in functions. This applies
only to intrinsic functions already known to the compiler. Typically,
you use this by including the ``calypsi/intrinsics6502.h`` file, which
contains all such valid declarations.

.. index:: task; attribute, attribute; task

``task``
^^^^^^^^

The ``task`` attribute can be applied to functions like ``main``, which
mark the application entry point. Such functions are typically not
called from C code. Applying the ``task`` attribute relaxes register
preservation, potentially saving stack space and reducing application
size by a small amount.
