R5900 processor specific ABI (psABI) - frno7/linux GitHub Wiki
The R5900 is the main processor of the PlayStation 2. The R5900 processor specific application binary interface (ABI), the R5900 psABI, is part of the MIPS psABI and the Linux standard base. The R5900 is a 64-bit MIPS III instruction set architecture (ISA), except the instructions LL, SC, LLD and SCD, that therefore are emulated in software by the R5900 Linux kernel. The R5900 has additional PREFETCH and conditional move instructions from the MIPS IV ISA as well as R5900 specific three-operand multiply and multiply-accumulate (MAC) instructions. The R5900 also has a set of specific 128-bit multimedia instructions. The PlayStation 2 endianness is not configurable and is always little-endian. The R5900 does not implement the CP0.Status bits UX, SX, KX or PX.
In addition to the R5900 executable and linkable format (ELF), R5900 Linux also accepts generic MIPS I, MIPS II EABI32 and EABI64 ABIs and perhaps eventually MIPS III programs.
[!CAUTION] Due to the R5900 short loop erratum, generic MIPS programs and libraries must be compiled with the assembler and compiler option
-mfix-r5900to have the assembler and compiler generate code that does not cause undefined behaviour, including data corruption or crashes.
The MIPS II and MIPS III ISAs include floating point unit (FPU) instructions.
[!NOTE] The R5900 floating point unit (FPU) is not compliant with the IEEE 754 standard as required by the R5900 psABI. The R5900 Linux kernel therefore traps and emulates all FPU instructions in software to comply with IEEE 754. In practice low FPU performance is to be expected since as there is (at this time) no simple way around the IEEE 754 requirement. See issue #3 for details.
R5900 Linux currently implements the o32 ABI, but not yet the n32 ABI.
MIPS ABI History
Archived from https://www.linux-mips.org/wiki/MIPS_ABI_History:
The MIPS ABI took shape as a set of register usage and calling conventions established from the earliest days of MIPS CPUs. It picked up the ABI acronym and a defined binding to object code with the AT&T-inspired UnixSystem V document which is rooted with SVR4.
That process had coalesced as early as 1990 into much of the o32 ABI which is widely used today. By about 1994 the ABI was expanded to encompass position-independent code and the ELF object code syntax, and there have been no substantive and intentional changes since.
SGI pioneered 64-bit operating systems for MIPS in the early 1990s, and the o32 ABI was quite unsuitable for real 64-bit computing. SGI defined a 64-bit ABI called n64 suitable for the largest applications; and then — belatedly realising that n64’s 64-bit pointer and long types bloated programs and caused portability problems to many applications which didn’t need them — produced the very similar standard n32, which differs primarily in having 32-bit pointers.
From 1995 or so SGI used solely 64-bit-capable MIPS CPUs, so they had no need to revisit a 32-bit ABI. As a result the embedded MIPS world is still stuck on the 20-year-old o32 standard. A series of talks five years ago failed to come up with a replacement.
Meanwhile, the perceived deficiencies of o32 have led to the proliferation of variants and more narrowly-focussed alternatives, to the point where there are now as many as 15 incompatible MIPS ABIs. It may yet prove the least worst decision for us all to continue to use o32 forever: but escaping from o32 could noticeably improve performance and ease various kinds of compatibility. So MIPS Technologies has a proposal called NUBI to do this: but it won’t make sense unless we can take the community with us and end up with fewer ABIs — not just another family to add to the overlong list.
Relevance of the MIPS ABI to Linux
In its early days when Linux had relatively little software and Linux/MIPS an even smaller one the plan was to be compatible to the MIPS ABI. In practice this aim would have required numerous changes — how many wasn’t obvious at all back in those days, so they never happened. Also System ABI defines interfaces without mandating if they’re implemented in libraries or as syscalls, leaving the syscall interfaces up to the implementors. In reality this meant some RISC/os and IRIX kernel interfaces in a wild blend with the original Linux/i386 syscall interface became the Linux/MIPS syscall interface.
Today the MIPS ABI has largely been obsoleted. The former www.mips-abi.org site has been gone for several years, since all vendors of MIPS System V-based systems have dumped System V in favor of either Linux or Windows NT. The MIPS ABI heritage of Linux/MIPS is now more of a liability than useful, and occasionally a pain.
At the bottom line the only relevant parts that are left are the Tool Interface Standard Executable and Linking Format (ELF) Specification, dated May 1995, and portions of the System V Application Binary Interface: MIPS RISC Processor Supplement (3rd edition, February 1996). The most useful parts of this second document are the “Machine Interface” and “Function Calling Interface” sections, though portions of other sections are still relevant. Since those documents were created the ELF format has been enhanced in many ways by the developers of GNU binutils and libc.
The MIPSpro N32 ABI Handbook (version 005, October 2002) is an introduction to the N32 High Performance 32-bit Application Binary Interface (ABI).
MIPS EABI32 and EABI64
Archived from http://www.cygwin.com/ml/binutils/2003-06/msg00436.html:
From: Eric Christopher
To: binutils at sources dot redhat dot com
Date: 11 Jun 2003 13:40:52 -0700
Subject: mips eabi documentation...
This is it unfortunately... :)
MIPS EABI
=========
Sizes and alignments
--------------------
Type Size (bytes) Alignment (bytes)
char 1 1
short 2 2
int 4 4
unsigned 4 4
long 4 4 (32-bit mode)
8 8 (64-bit mode)
long long 8 8
float 4 4
double 8 8
pointers 4 4 (32-bit mode)
8 8 (64-bit mode)
* alignment within aggregates (structs and unions) is as above, with
padding added if needed
* aggregates have alignment equal to that of their most aligned
member
* aggregates have sizes which are a multiple of their alignment
Subroutine calls
----------------
Parameter registers:
general-purpose r4-r11
floating point f12-f19
Register usage:
fixed 0 value r0
volatile r1-r15, r24, r25
non-volatile r16-r23, r30
kernel reserved r26, r27
gp (SDA base) r28
stack pointer r29
frame pointer r30 (if needed)
return address r31
Stack alignment 8 bytes
Parameter register allocation integer/floating independently (see below)
Structures passed <= 32 bits as values, else as pointers
Homing area none
Stack Frame
-----------
+-----------------------+
| Saved Registers |
+-----------------------+
| ... |
+-----------------------+
| Local Variables |
+-----------------------+
| ... |
+-----------------------+
| Parameter Word 2 |
+-----------------------+
SP --> | Parameter Word 1 |
+-----------------------+
Parameter Assignment to Registers
---------------------------------
Consider the parameters in a function call as ordered from left (first
parameter) to right. In this algorithm, FR contains the number of the
next available floating-point register (or register pair for modes in
which floating-point registers hold only 32 bits). GR contains the
number of the next available general-purpose register. STARG is the
address of the next available stack parameter word.
INITIALIZE:
Set GR=r4, FR=f12, and STARG to point to parameter word 1.
SCAN:
If there are no more parameters, terminate.
Otherwise, select one of the following depending on the type
of the next parameter:
DOUBLE OR FLOAT:
If FR > f19, go to STACK. Otherwise, load the parameter value
into floating-point register FR and advance FR to the next
floating-point register (or register pair in 32-bit mode).
Then go to SCAN.
SIMPLE ARG:
A SIMPLE ARG is one of the following:
* One of the simple integer types which will fit into a
general-purpose register,
* A pointer to an object of any type,
* A struct or union small enough to fit in a register
(<= 32 bits in 32-bit mode, <= 64 bits in 64-bit mode)
* A larger struct or union, which shall be treated as a
pointer to the object or to a copy of the object.
(See below for when copies are made.)
If GR > r11, go to STACK. Otherwise, load the parameter
value into general-purpose register GR and advance GR
to the next general-purpose register. Values shorter than
the register size are sign-extended or zero-extended depending
on whether they are signed or unsigned. Then go to SCAN.
LONG LONG in 32-bit mode:
If GR > r10, go to STACK. Otherwise, if GR is odd, advance
GR to the next register. Load the 64-bit long long value into
register pair GR and GR+1. Advance GR to GR+2 and go to SCAN.
STACK:
Parameters not otherwise handled above are passed in the
parameter words of the caller's stack frame. SIMPLE ARGs,
as defined above, are considered to have size and alignment
equal to the size of a general-purpose register, with
simple argument types shorter than this sign- or zero-extended
to this width. float arguments are considered to have size
and alignment equal to the size of a floating-point register.
In 64-bit mode, floats are stored in the low-order 32 bits
of the 64-bit space allocated to them. double and long long
are considered to have 64-bit size and alignment. Round
STARG up to a multiple of the alignment requirement of
the parameter and copy the argument byte-for-byte into
STARG, STARG+1, ... STARG+size-1. Set STARG to STARG+size
and go to SCAN.
Structure passing
-----------------
As noted above, code which passes structures and unions by value is
implemented specially. (In this section, "struct" will refer to
structs and unions inclusively.) Structs small enough to fit in a
register are passed by value in a single register or in a stack frame
slot the size of a register. Larger structs are handled by passing
the address of the structure. In this case, a copy of the structure
will be made if necessary in order to preserve the pass-by-value
semantics.
Copies of large structs are made under the following rules:
ANSI mode K&R Mode
--------- --------
Normal param Callee copies if needed Caller copies
Varargs (...) param Caller copies Caller copies
In the case of normal (non-varargs) large-struct parameters in ANSI
mode, the callee is responsible for producing the same effect as if a
copy of the structure were passed, preserving the pass-by-value
semantics. This may be accomplished by having the callee make a copy,
but in some cases the callee may be able to determine that a copy is
not necessary in order to produce the same results. In such cases,
the callee may choose to avoid making a copy of the parameter.
Varargs handling
----------------
No special changes are needed for handling varargs parameters other
than the caller knowing that a copy is needed on struct parameters
larger than a register (see above).
The varargs macros set up a two-part register save area, one part for
the general-purpose registers and one part for floating-point
registers, and maintain separate pointers for these two areas and for
the stack parameter area. The register save area lies between the
caller and callee stack frame areas.
In the case of software floating-point only the general-purpose
registers need to be saved. Because the save area lies between the
two stack frames, the saved register parameters are contiguous with
parameters passed on the stack. This allows the varargs macros to be
much simpler. Only one pointer is needed, which advances from the
register save area into the caller's stack frame.
Function return values
----------------------
Type Register
---- --------
int r2
short r2
long r2
long long r2-r3 (32-bit mode)
r2 (64-bit mode)
float f0
double f0-f1 (32-bit mode)
f0 (64-bit mode)
struct/union see below
Structs/unions which will fit into two general-purpose registers are
returned in r2, or in r2-r3 if necessary. They are aligned within the
register according to the endianness of the processor; e.g. on a
big-endian processor the first byte of the struct is returned in the
most significant byte of r2, while on a little-endian processor the
first byte is returned in the least significant byte of r2. Larger
structs/unions are handled by the caller passing as a "hidden" first
argument a pointer to space allocated to receive the return value.
Software floating-point
-----------------------
For software floating-point implementations, floats shall be passed
and returned like ints, and doubles shall be passed and returned like
long longs.
This implies that, in 32-bit mode, floats will be passed in a single
integer register and doubles will be passed in an even/odd register
pair. Similarly, floats will be returned in a single register, r2,
and doubles will be returned in register pair r2-r3.