summary refs log tree commit diff
path: root/lisc/ABI
blob: 0eaa7c7208340a931bddcab05f9e9005f815b9c8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
System V ABI for calls on x64
=============================

Data classes of interest as defined by the ABI:
 - INTEGER
 - SSE
 - MEMORY

Unions are treated like structures with the alignment
of their most demanding member, and the size of their
largest member.

Classification:
1. The size of each argument gets rounded up to eightbytes.
   (It keeps the stack always 8 bytes aligned.)
2. _Bool, char, short, int, long, long long and pointers
   are in the INTEGER class.
3. float and double are in the SSE class.
4. If the size of an object is larger than two eightbytes
   or if contains unaligned fields, it has class MEMORY.
5. Otherwise, recursively classify fields and determine
   the class of the two eightbytes using the classes of
   their components.  If any of them is MEMORY the result
   is MEMORY (but I don't think it can happen), if any is
   INTEGER the result is INTEGER, otherwise the result
   is SSE.

Passing:
 - Classify arguments in order.
 - INTEGER arguments use in order %rdi %rsi %rdx %rcx
   %r8 %r9.
 - SSE arguments use in order %xmm0 - %xmm7.
 - MEMORY gets passed on the stack.
 - When we run out of registers for an aggregate, revert
   the assignment for the first eightbytes and pass it
   on the stack.
 - When all registers are taken, write arguments on the
   stack from right to left.
 - When calling a variadic function, %al stores the number
   of vector registers used to pass arguments (it must be
   an upper bound and does not have to be exact).
 - Registers %rbx, %r12 - %r15 are callee-save.

Returning:
 - Classify the return type.
 - Use %rax and %rdx in order for INTEGER return values.
 - Use %xmm0 and %xmm1 in order for SSE return values.
 - I the return value's class is MEMORY, the first
   argument of the function %rdi was a pointer to an
   area big enough to fit the return value.  The function
   writes the return value there and returns the address
   (that was in %rdi) in %rax.