MIPS ABI Changes in GCC 3.4

GCC 3.4 fixes several cases in which earlier releases would not follow the MIPS calling conventions. This document describes each fix and the kind of code it will affect. In each case, GCC 3.4 will not be binary compatible with earlier releases.

Most of the fixes are related to the handling of structure and union types. In the summary below, "aggregate" refers to both structures and unions.

Note that IRIX 6 configurations used to work around B and E by providing wrappers for certain libc functions. These wrappers are not needed for 3.4 and have been removed. It should be possible to link code generated by GCC 3.4 directly with code generated by SGI's compilers.

A. Small aggregate arguments (1)

Affected ABIs o32
Endianness little
Conditions
  • An aggregate argument is passed in a register; and
  • that argument is smaller than 4 bytes.
Old behavior The register was padded at the least significant end.
New behavior The register is padded at the most significant end.
Example
struct s { char c[2]; };
void f (struct s x);

x is passed in argument register $4, which is laid out as follows:

7-0 15-8 23-16 31-24
Old behavior padding padding c[0] c[1]
New behavior c[0] c[1] padding padding

B. Small aggregate arguments (2)

Affected ABIs n32 and n64
Endianness big
Conditions
  • An aggregate argument is passed in a register; and
  • that argument is smaller than 8 bytes.
Old behavior The register was padded at the most significant end.
New behavior The register is padded at the least significant end.
Example
struct s { char c[2]; };
void f (struct s x);

x is passed in argument register $4, which is laid out as follows:

63-56 55-48 47-40 39-32 31-24 23-16 15-8 7-0
Old behavior padding padding padding padding padding padding c[0] c[1]
New behavior c[0] c[1] padding padding padding padding padding padding

C. Large aggregate arguments

Affected ABIs n32 and n64
Endianness big
Conditions
  • An aggregate argument is passed to a function;
  • the aggregate's size is not a multiple of 8 bytes; and
  • there are enough argument registers to hold some of the aggregate, but not enough to hold all of it.
Old behavior The argument was passed by reference.
New behavior The argument is passed by value.
Example
struct s { int i[17]; };
void f (struct s x);

It would take 9 registers to hold x, but only 8 argument registers are available. Since x's size is not a multiple of 8, previous releases passed it by reference (that is, they passed a pointer to x in $4).

The new behavior is to pass x by value. The first 8 words are passed in argument registers and the last is passed on the stack.

D. Single-field structure arguments

Affected ABIs o32, o64, n32 and n64
Endianness either
Conditions
  • A structure containing a single field is passed by value; and
  • that field has a floating-point type.
Old behavior The structure was treated like a scalar value of the same floating-point type. For example, a structure containing a float field was treated in the same way as a scalar float value.
New behavior There is no special treatment for such structures. Note however that the usual n32 and n64 rules still hold: naturally-aligned fields of type double are passed in floating-point registers.
Example
struct s { float f; };
void f (struct s x);

GCC used to pass x in $f12. Now it passes it in $4, just like any other structure.

E. Structure return values

Affected ABIs n32 and n64
Endianness big
Conditions
  • An aggregate is returned by value;
  • that aggregate is smaller than 16 bytes;
  • its size is not a multiple of 8 bytes; and
  • if it is a structure, either:
    1. it has more than two fields; or
    2. it has at least one non-floating-point field.
Old behavior The return register was padded at the most significant end.
New behavior The return register is padded at the least significant end.
Example
struct s { char c[3]; };
struct s f ();

f() returns its value in $2, which is laid out as follows:

63-56 55-48 47-40 39-32 31-24 23-16 15-8 7-0
Old behavior padding padding padding padding padding c[0] c[1] c[2]
New behavior c[0] c[1] c[2] padding padding padding padding padding

F. Complex return values

Affected ABIs n32 and n64
Endianness either
Conditions A function returns a complex float or double.
Old behavior The value was returned in $f0 and $f1.
New behavior The value is returned in $f0 and $f2.
Example
_Complex float f ();