[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

4. M68k/Coldfire Backend

This chapter documents the backend for the M68k and Coldfire processor families.

4.1 Additional options

This backend provides the following additional options:


Generate code for cpu n (e.g. -cpu=68020), default: 68000.


Generate code for fpu n (e.g. -fpu=68881), default: 0.


Use small data model (see below).


Use small code model (see below).


Insert code for profiling.


By default constant data will be placed in the code section (and therefore is accessable with faster pc-relative addressing modes). Using this option it will be placed in the data section.

This could e.g. be useful if you want to use small data and small code, but your code gets too big with all the constant data.

Note that on operating systems with memory protection this option will disable write-protection of constant data.


By default automatic variables are addressed through a7 instead of a5. This generates slightly better code, because the function entry and exit overhead is reduced and a5 can be used as register variable etc.

However this may be a bit confusing when debugging and you can force vbcc to use a5 as a fixed framepointer.


Do not perform peephole-optimizations.


By default arguments of function calls are not always popped from the stack immediately after the call, so that the arguments of several calls may be popped at once. With this option vbcc can be forced to pop them after every function call. This may simplify debugging and reduce the stack size needed by the compiled program.


Create output suitable for the GNU assembler.


Do not return floats and doubles in floating-point registers even if code for an fpu is generated.


Do not use multiple registers to return types that do not fit into a single register. This is mainly for backwards compatibility with certain libraries.


When creating debug-output (‘-g’ option) create Amiga debug hunks rather than DWARF2. Does not work with ‘-gas’.


When generating code for FPU do quick&dirty conversions from floating-point to integer. The code may be somewhat faster but will not correctly round to zero. Only use it if you know what you are doing.


Use real common symbols instead of bss symbols for non-initialized external variables.

4.2 ABI

The current version generates assembler output for use with the vasmm68k_mot. Most peephole optimizations are done by the assembler so vbcc only does some that the assembler cannot make. The generated executables will probably only work with OS2.0 or higher.

With ‘-gas’ assembler output suitable for the GNU assembler is generated (the version must understand the Motorola syntax - some old ones do not). The output is only slightly modified from the vasm-output and will therefore result in worse code on gas.

The register names provided by this backend are:

         a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7
         d0,  d1,  d2,  d3,  d4,  d5,  d6,  d7
        fp0, fp1, fp2, fp3, fp4, fp5, fp6, fp7

The registers a0 - a7 are supported to hold pointer types. d0 - d7 can be used for integers types excluding long long, pointers and float if no FPU code is generated. fp0 - fp7 can be used for all floating point types if FPU code is generated.

Additionally the following register pairs can be used for long long:

        d0/d1, d2/d3, d4/d5, d6/d7

The registers d0, d1, a0, a1, fp0 and fp1 are used as scratch registers (i.e. they can be destroyed in function calls), all other registers are preserved.

By default, all function arguments are passed on the stack.

All scalar types up to 4 bytes are returned in register d0, long long is returned in d0/d1. If compiled for FPU, floating point values are returned in fp0 unless ‘-no-fpreturn’ is specified. Types which are 8, 12 or 16 bytes large will be returned in several registers (d0/d1/a0/a1) unless ‘-no-mreg-return’ is specified. All other types are returned by passing the function the address of the result as a hidden argument - such a function must not be called without a proper declaration in scope.

Objects which have been compiled with different settings must not be linked together.

a7 is used as stack pointer. If ‘-sd’ is used, a4 will be used as small data pointer. If ‘-use-framepointer’ is used, a5 will be used as frame pointer. All other registers will be used by the register allocator and can be used for register parameters.

The size of the stack frame is limited to 32KB for early members of the 68000 family prior to 68020.

The basic data types are represented like:

    type        size in bits        alignment in bytes

    char                8                       1
    short              16                       2
    int                32                       2
    long               32                       2
    long long          64                       2
    all pointers       32                       2
    float(fpu)         32                       2       see below
    double(fpu)        64                       2       see below
    long double(fpu)   64                       2       see below

4.3 Small data

vbcc can access static data in two ways. By default all such data will be accessed with full 32bit addresses (large data model). However there is a second way. You can set up an address register (a4) to point into the data segment and then address data with a 16bit offset through this register.

The advantages of the small data model are that the program will usually be smaller (because the 16bit offsets use less space and no relocation information is needed) and faster.

The disadvantages are that one address register cannot be used by the compiler and that it can only be used if all static data occupies less than 64kb. Also object modules and libraries that have been compiled with different data models must not be mixed (it is possible to call functions compiled with large data model from object files compiled with small data model, but not vice versa and only functions can be called that way - other data cannot be accessed).

If small data is used with functions which are called from functions which have not been compiled with vbcc or without the small data model then those functions must be declared with the __saveds attribute or call geta4() as the first statement (do not use automatic initializations prior to the call to geta4). Note that geta4() must not be called through a function pointer!

4.4 Small code

In the small code model calls to external functions (i.e. from libraries or other object files) are done with 16bit offsets through the program counter rather than with absolute 32bit addresses.

The advantage is slightly smaller and faster code. The disadvantages are that all the code (including library functions) must be small enough. Objects/libraries can be linked together if they have been compiled with different code models.

4.5 CPUs

The values of ‘-cpu=n’ have those effects:


Code for the Coldfire family is generated.


Code for the 68k family is generated.


4.6 FPUs

At the moment the values of -fpu=n have those effects:


Floating point calculations are done using the FPU.


Instructions that have to be emulated on these FPUs will not be used; at the moment this only includes the fintrz instruction in case of the 040.

4.7 Math

Long multiply on CPUs <68020 uses inline routines. This may increase code size a bit, but it should be significantly faster, because function call overhead is not necessary. Long division and modulo is handled by calls to library functions. (Some operations involving constants (e.g. powers of two) are always implemented by more efficient inline code.)

If no FPU is specified floating point math is done using math libraries. 32bit IEEE format is used for float and 64bit IEEE for double and long double.

If floating point math is done with the FPU floating point values are kept in registers and therefore may have extended precision sometimes. This is not ANSI compliant but will usually cause no harm. When floating point values are stored in memory they use the same IEEE formats as without FPU. Return values are passed in fp0.

Note that you must not link object files together if they were not compiled with the same -fpu settings and that a proper math library must be linked.

4.8 Target-Specific Variable Attributes

This backend offers the following variable attributes:


Load the pointer to the small data segment at function-entry. Applicable only to functions.


Place variable in chip-memory. Only applicable on AmigaOS to variables with static storage-duration.


Do not place this variable in the small-data segment in small data mode. No effect in large data mode. Only applicable to variables with static storage-duration.


Currently ignored.


This is used to declare interrupt-handlers. The function using this attribute will save all registers it destroys (including scratch-registers) and return with rte rather than rts.


Used to write interrupt-handlers for AmigaOS. Stack-checking for a function with this attribute will be disabled and if a value is returned in d0, the condition codes will be set accordingly.


Places the variable/function in a section named according to the argument.

4.9 Predefined Macros

This backend defines the following macros:


(Depending on the settings of ‘-cpu’, e.g. __M68020.)


(If a Coldfire CPU is selected.)


(If ‘-fpu=68881’ is selected.)


(If code for another FPU is selected; ‘-fpu=68040’ or ‘-fpu=68060’ will set __M68882.)


Is set to the size of the int type. Either 16 (vbccm68ks) or 32 (vbccm68k).

4.10 Stack

If the ‘-stack-check’ option is used, every function-prologue will call the function __stack_check with the stacksize needed by the current function on the stack. This function has to consider its own stacksize and must restore all registers.

If the compiler is able to calculate the maximum stack-size of a function including all callees, it will add a comment in the generated assembly-output (subject to change to labels).

4.11 Stdarg

A possible ‘<stdarg.h>’ could look like this:

typedef unsigned char *va_list;

#define __va_align(type) (__alignof(type)>=4?__alignof(type):4)

#define __va_do_align(vl,type) ((vl)=(char *)((((unsigned int)(vl))+__va_align(type)-1)/__va_align(type)*__va_align(type)))

#define __va_mem(vl,type) (__va_do_align((vl),type),(vl)+=sizeof(type),((type*)(vl))[-1])

#define va_start(ap, lastarg) ((ap)=(va_list)(&lastarg+1))
#define va_arg(vl,type) __va_mem(vl,type)
#define va_end(vl) ((vl)=0)

#define va_copy(new,old) ((new)=(old))


4.12 Known problems

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by vb on January 3, 2015 using texi2html 1.82.