Notes
(from the AMD64 SysV ABI)
Arguments are first classified into classes that have
corresponding amd64 registers.
These are:
| INTEGER |
- |
types that fit into general purpose registers |
| SSE |
- |
types that fit into vector registers |
| SSEUP |
- |
types that fit into the upper bytes of vector registers |
| MEMORY |
- |
types to be passed on the stack |
(n.b. there are more classes for more complex unimplemented types)
Classification:
Arguments are rounded up to 8 bytes (8-bytes from now on).
Scalars are assigned the following classes:
- char, short, int, long, long long and pointers
are classified as INTEGER
- float and double are classified as SSE
Classification of aggregate types:
- If the object is larger than four 8-bytes, or if it contains
unaligned fields it is classified as MEMORY.
- If the size of the object is larger than a single 8-byte then
each 8-byte gets classified individually. The initial class
of each 8-byte is set to NO_CLASS.
- The class of an 8-byte is determined by recursively combining
the classes of the fields of an object that overlap this 8-byte.
- If both classes are equal, this is the resulting class.
- If one class is NO_CLASS, the result is the other class.
- If one class is MEMORY, the result is MEMORY.
- If one class is INTEGER, the result is INTEGER.
- Otherwise the class is SSE.
Post-processing for aggregate types:
- If one of the classes is MEMORY then the entire argument
is passed in memory.
- If the size of the object is larger than two 8-bytes
and the first 8-byte isn't SSE and if any other 8-byte isn't
SSEUP then the whole object is passed in memory.
- If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE.
After classification arguments are assigned their registers in order.
- If the class is MEMORY, pass it on the stack.
- If the class is INTEGER, pick the next available register
from the list:
- %rdi, %rsi, %rdx, %rcx, %r8, %r9,
- If the class is SSE, pick the next available register
from %xmm0 to %xmm7
- If the class is SSEUP, pick the next available 8-byte in the
last used vector register.
- If there are no more registers available for any 8-byte of an
object, pass the entire object in memory. Previous register
assignments are discarded.
After registers are assigned, the arguments passed in memory get
pushed onto the stack in reverse order.
*** This is how I understood the ABI. Not necessarily correct.