1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5# Darwin gives a leading '_' to symbols defined in C code.
6#ifdef XP_DARWIN
7#define SYM(x) _ ## x
8#else
9#define SYM(x) x
10#endif
11
12#define CFI_STARTPROC .cfi_startproc
13#define CFI_ENDPROC .cfi_endproc
14#define CFI_DEF_CFA_OFFSET(offset) .cfi_def_cfa_offset offset
15#define CFI_OFFSET(reg, offset) .cfi_offset reg, offset
16#define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
17#define CFI_DEF_CFA(reg, offset) .cfi_def_cfa reg, offset
18
19.intel_syntax noprefix
20
21# nsresult NS_InvokeByIndex(nsISupports* this, uint32_t aVtableIndex,
22#                           uint32_t argc, nsXPTCVariant* argv);
23.text
24.global SYM(NS_InvokeByIndex)
25#ifndef XP_DARWIN
26.type NS_InvokeByIndex, @function
27#endif
28.align 4
29SYM(NS_InvokeByIndex):
30  CFI_STARTPROC
31  push rbp
32  CFI_DEF_CFA_OFFSET(16)
33  CFI_OFFSET(6, -16)
34  mov rbp, rsp
35  CFI_DEF_CFA_REGISTER(6)
36
37# save r12 and r13 because we use them and they are callee saved.
38  push r12
39  push r13
40  CFI_OFFSET(12, -24)
41  CFI_OFFSET(13, -32)
42
43# save this and the vtable index because we need them after setting up the
44# stack.
45  mov r12, rdi
46  mov r13, rsi
47
48# allocate space for stack arguments, in theory we only need 8 * (argc - 5)
49# bytes because at least 5 arguments will go in registers, but for now it is
50# just simpler to allocate 8 * argc bytes.  Note that we treat the this
51# pointer specially.
52  lea eax, [edx * 8]
53  sub rsp, rax
54
55# If there is an odd number of args the stack can be misaligned so realign it.
56  and rsp, 0xfffffffffffffff0
57
58# pass the stack slot area to InvokeCopyToStack.
59  mov r8, rsp
60
61# setup space for the register slots: there are 5 integer ones and 8 floating
62# point ones.  So we need 104 bytes of space, but we allocate 112 to keep rsp
63# aligned to 16 bytes.
64  sub rsp, 112
65
66# the first argument to InvokeCopyToStack is the integer register area, and the
67# second is the floating point area.
68  mov rdi, rsp
69  lea rsi, [rsp + 40]
70
71# The 3rd and 4th arguments to InvokeCopyToStack are already in the right
72# registers.  So now we can just call InvokeCopyToStack.
73  call SYM(InvokeCopyToStack)
74
75# setup this
76  mov rdi, r12
77
78# copy the integer arguments into place.
79  mov rsi, [rsp]
80  mov rdx, [rsp + 8]
81  mov rcx, [rsp + 16]
82  mov r8, [rsp + 24]
83  mov r9, [rsp + 32]
84
85# copy the float arguments into place
86  movsd xmm0, [rsp + 40]
87  movsd xmm1, [rsp + 48]
88  movsd xmm2, [rsp + 56]
89  movsd xmm3, [rsp + 64]
90  movsd xmm4, [rsp + 72]
91  movsd xmm5, [rsp + 80]
92  movsd xmm6, [rsp + 88]
93  movsd xmm7, [rsp + 96]
94
95# get rid of the scratch space for registers
96  add rsp, 112
97
98# load the function pointer and call
99  lea eax, [r13d * 8]
100  add rax, [rdi]
101  call [rax]
102
103# r12 and r13 were pushed relative to the old stack pointer which is now the
104# frame pointer.
105  mov r12, [rbp - 0x8]
106  mov r13, [rbp - 0x10]
107
108  mov rsp, rbp
109  pop rbp
110  CFI_DEF_CFA(7, 8)
111  ret
112  CFI_ENDPROC
113
114#ifndef XP_DARWIN
115// Magic indicating no need for an executable stack
116.section .note.GNU-stack, "", @progbits ; .previous
117#endif
118