

************
Data storage
************

This chapter discusses controlling data placement and its impact on
application efficiency.

The 68000 is a 32 bits architecture that can address a linear 4GB
address range which is shared by code and data.

As there is a good amount of storage registers and your statically
allocated data is probably not more than 64K, you can normally use
the Small data model which reserves one register as a base address for
addressing static data. This typically saves two bytes of program
space for every instruction that access static data.

Ways to store data
==================

Data can be allocated as *auto*, *static*, or on the *heap*. Variable
scope and the need for allocation during runtime determine placement.

As a general rule, use auto-allocated variables whenever possible.
This offers the compiler maximum flexibility for resource allocation
closest to the core, which typically results in the most efficient
data access.

.. index:: variables; auto, auto variables
.. index:: local variables, variables; local

Auto variables
--------------

Auto variables include function parameters and local variables not
defined with ``static``. The compiler attempts to allocate these in
processor registers; otherwise, the stack is used.

Auto variables are allocated only when used. Their registers can be
reused for other auto variables or temporary data once no longer
needed. This reuse also applies to stack locations.

Auto variables can have multiple *live ranges*; a variable with the
same name might be used in distinct parts of a function. Internally,
these are treated as different variables and may be allocated to
various locations, potentially not existing between live ranges.

All auto variables associated with a function are deallocated upon
function exit.

.. note::

   If you take the address of an auto variable, you can pass its
   pointer to other functions, which is useful for temporary storage.
   However, avoid using such pointers outside their scope, as auto
   variables are deallocated on function exit. Be aware that taking an
   address allocates the variable on the stack, potentially increasing
   access cost compared to other auto variables.

.. index:: variables; static, static variables
.. index:: variables; global, global variables

Static variables
-----------------

Global, module, or function static variables are allocated in global
memory, occupying space for the application's duration.

Their visibility varies. A global variable is universally visible but
requires ``extern`` for use. A module static variable, declared with
``static`` at file scope, is visible within one compilation unit.
A static local variable within a function's scope is only visible
there, retaining its value across function calls. Use ``static`` to
differentiate it from an auto variable.

.. index:: variables; dynamic

Dynamically allocated
----------------------

A dynamically allocated variable is retrieved from a *heap* using the
*malloc* function. This is useful when the required data size is
unknown at program startup.

.. note::

   Dynamically allocated variables are a potential problem in memory
   constrained systems if the program is left running for a long time
   due to heap fragmentation.

.. index:: address spaces

Address spaces
==============

The compiler provides multiple *address spaces*, which are addressable
memory areas with specific properties:

* Address width for pointers

* Width of the associated integral index type

* Different instruction sequences for accessing various address spaces

* An extension keyword or type attribute name

* Section names tied to the address space for linking control

Address space attributes are always active in the compiler.

The Calypsi C compiler tool chain for the 68000 provides two address spaces, near and far.

All pointers to data memory are 32 bits wide and occupy 4 bytes of
memory when stored in memory.
The keywords and address space attributes are intended to describe a
storage location to help placement in appropriate sections.

Near address space
------------------

The *near* address space is a memory area reachable from a base
address held in register ``A4``. This can be used in either the Small
or Large data models, but it is not available in the Far-only data
model.

You can have a maximum of 64K data in the near address space.
If you run out of space you may select a couple of larger data objects
and move them to the far address space (see below).
64K can be considered quite a lot of memory for storing reasonable
small static data objects.
Stack and heap allocated objects are allocated outside this 64K memory
range.

Far address space
-----------------

The *far* address space makes use of the full 32 bit address
range. The amount of static data objects can be up to 4GB. Direct
access to the far address space costs an additional two extra bytes
for each instruction compared to using the near address space.

.. note::

   While doing a direct access to a far object costs two extra bytes,
   there is no difference when using a pointer to the near or the far
   address area, they have the same cost.

Summary
-------

The following table summarizes the available address spaces.

.. index:: keywords; address spaces, address spaces

.. _AddressSpaces:
.. table:: Address spaces
 :widths: 1 1 2 1 1
 :column-dividers: none single single single single none
 :column-alignment: left left left left left

 +-------------+-------------+---------------------------------+-------------+------------+
 |Memory type  |Keyword      |Address range                    |Pointer size | Index type |
 +=============+=============+=================================+=============+============+
 | Near        | ``__near``  |``-0x8000`` to ``0x7fff``        |32 bits      |``int32_t`` |
 +-------------+-------------+---------------------------------+-------------+------------+
 | Far         | ``__far``   |``0x00000000`` to ``0xffffffff`` |32 bits      |``int32_t`` |
 +-------------+-------------+---------------------------------+-------------+------------+

.. note::

   The Near memory type allocates data in a 64K bytes large area pointed
   to by a base pointer held in register ``A4``. Pointers and address
   arithmetics are performed using 32 bit operations.


.. index:: address space; syntax, type qualifier

Syntax
------

An address space attribute keyword such as ``__far`` is
a type qualifier. Syntactically it works the same as other C language
defined type qualifier, e.g. ``const`` and ``volatile``.

The following declaration defines four variables in the
Far memory address space:

.. code-block:: C

   __far int a, b;
   int __far c, d;

The ``__far`` type qualifier applies to the closest type,
``int`` in this example. In C, the order between type qualifiers and
types does not matter; they convey the same meaning.

.. index:: pointers

Pointers
--------

A pointer in C points to something in memory. Both the pointer itself
and what it points to have types. As an example, the type ``char *``
is a pointer to a ``char``.

Pointer types are easier to understand if you read them from right to
left. The ``*`` is a pointer, so ``char *`` reads from right to left
as "pointer to char". This order of reading is especially useful when
you mix in type qualifiers in pointer types, as it makes it a lot
easier to read and understand  what the type means.

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

Structures
----------

You can place a structure in a specified address space. This means
that all its members are in that address space. You cannot override
individual structure members using an address space keyword. It is
however possible to have members of the structure that point to a
different address space.

.. code-block:: C

   struct tag {
     int __far * p;
     int value;
   };

   struct tag __far myTag;

This is however not allowed:

.. code-block:: C

   struct tag {
     int * __far p;     /* incorrect */
     int __far value;   /* incorrect */
   };
