

*******************
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.,
``__far``) or attribute syntax (e.g.,
``__attribute__((far))``). 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., ``__far``). If this occurs,
   use the ``__attribute__((far))`` 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__((far)) int a, b;
   int __far c, d;

When applied to an object, the attribute's location is irrelevant.
The example above applies the Far memory 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__((far)) * p1;
   long * __attribute__((far)) p2;

Here, ``p1`` is a pointer stored in default memory that points to an
``int`` in Far memory memory. ``p2`` is a pointer stored
in Far memory 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., ``__far``). For
attribute syntax, use the attribute name with ``__attribute__`` (e.g.,
``__attribute__((far))``).

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

 +--------------------------+----------------------------------------------+
 |Attribute name            |Description                                   |
 +==========================+==============================================+
 | ``aligned(nn)``          | Specify alignment of data object or function |
 +--------------------------+----------------------------------------------+
 | ``section("name")``      | Specify section name to use for a data       |
 |                          | object or function                           |
 +--------------------------+----------------------------------------------+
 | ``near``                 | Control storage of data object to near area  |
 +--------------------------+----------------------------------------------+
 | ``far``                  | Control storage of data object to far area   |
 +--------------------------+----------------------------------------------+
 | ``interrupt``            | Used to define an interrupt function         |
 +--------------------------+----------------------------------------------+
 | ``amiga_interrupt``      | Amiga style interrupt function               |
 +--------------------------+----------------------------------------------+
 | ``intrinsic``            | Used to declare an intrinsic function        |
 +--------------------------+----------------------------------------------+
 | ``saveds``               | Entry point that needs to initialize         |
 |                          | the base pointer in register ``A4``          |
 +--------------------------+----------------------------------------------+
 | ``task``                 | Relaxes preserving registers                 |
 +--------------------------+----------------------------------------------+


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:: near; attribute, attribute; near

``near``
^^^^^^^^

This specifies a data object or a pointer to a data object that
resides in a Near area. Accessing a global or static object in this
area saves two bytes for each machine instruction used compared to the
Far area.

Register ``A4`` is reserved to hold a base pointer to this area.

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

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

This specifies a data object or a pointer to a data object that can
reside anywhere in memory.

The code needed to access Far memory tend to be slightly larger
compared to the Near memory.

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

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

An interrupt function is meant to serve as an interrupt handler. The
interrupt attribute has the following effects:

 #. An interrupt function cannot take any parameters

 #. An interrupt function will preserve all registers used

 #. Leaving the interrupt function uses a different instruction
    sequence compared to normal functions

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

.. index:: interrupt;  vector

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

.. code-block:: C

   int counter;

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

.. note::

   The vector argument is optional. Omitting it means that there will be
   no vector section entry generated for that interrupt function.
   You can also suppress all vector sections from being generated by
   using the ``--no-vector-sections`` command-line option.

.. index:: interrupt; Amiga style, Amiga; interrupt

``amiga_interrupt``
^^^^^^^^^^^^^^^^^^^

The ``amiga_interrupt`` attribute defines an interrupt function
intended to be used with the Amiga operating system. The
Amiga interrupt has the following effects:

 #. An Amiga interrupt function cannot take any parameters

 #. Follows the register convention of an Amiga interrupt, registers
    ``D0``, ``D1``, ``A0``, ``A1``, ``A5`` and ``A6`` are considered
    scratch registers.

 #. The return type should be ``int`` and you normally want to return
    ``0`` to allow interrupt processing further interrupt chain.

Here is a simple example of how an Amiga interrupt definition may look:

.. code-block:: C

   int counter;

   __attribute__((amiga_interrupt))
   int irq () {
     counter++;
     return 0;
   }

.. note::

  There is no interrupt vector associated with an Amiga interrupt
  definition. You need to use the Amiga operating system calls to
  install the interrupt handler.

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

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

The intrinsic attribute is used to declare intrinsic built-in
functions. This can only be done on intrinsic functions that is
already known to the compiler. Normally you use this by including the
``calypsi/intrinsics68000.h`` file which contains all such valid declarations.

.. index:: saveds; attribute, attribute; saveds

``saveds``
^^^^^^^^^^

A ``saveds`` function sets up the ``A4`` base address upon entry and
restores the previous value of ``A4`` when returning. This is useful
for API functions called from another context where ``A4`` may
point to another base area or used for another purpose.

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

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

A ``task`` attribute can be used on functions such as ``main`` which
is the start of the application. You will not normally call such
functions from any C code. In that case you can apply the ``task``
attribute which relaxes preserving registers that would otherwise be
saved on the stack. This can save a little stack space and will make
the application a tiny bit smaller.
