|
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* Platform specific code to invoke XPCOM methods on native objects */ |
|
7 |
|
8 #include "xptcprivate.h" |
|
9 |
|
10 #if !defined(__aarch64__) |
|
11 #error "This code is for Linux AArch64 only." |
|
12 #endif |
|
13 |
|
14 |
|
15 /* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections |
|
16 * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the |
|
17 * needed information. |
|
18 * |
|
19 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf |
|
20 */ |
|
21 |
|
22 #ifndef __AARCH64EL__ |
|
23 #error "Only little endian compatibility was tested" |
|
24 #endif |
|
25 |
|
26 /* |
|
27 * Allocation of integer function arguments initially to registers r1-r7 |
|
28 * and then to stack. Handling of 'that' argument which goes to register r0 |
|
29 * is handled separately and does not belong here. |
|
30 * |
|
31 * 'ireg_args' - pointer to the current position in the buffer, |
|
32 * corresponding to the register arguments |
|
33 * 'stack_args' - pointer to the current position in the buffer, |
|
34 * corresponding to the arguments on stack |
|
35 * 'end' - pointer to the end of the registers argument |
|
36 * buffer. |
|
37 */ |
|
38 static inline void alloc_word(uint64_t* &ireg_args, |
|
39 uint64_t* &stack_args, |
|
40 uint64_t* end, |
|
41 uint64_t data) |
|
42 { |
|
43 if (ireg_args < end) { |
|
44 *ireg_args = data; |
|
45 ireg_args++; |
|
46 } else { |
|
47 *stack_args = data; |
|
48 stack_args++; |
|
49 } |
|
50 } |
|
51 |
|
52 static inline void alloc_double(double* &freg_args, |
|
53 uint64_t* &stack_args, |
|
54 double* end, |
|
55 double data) |
|
56 { |
|
57 if (freg_args < end) { |
|
58 *freg_args = data; |
|
59 freg_args++; |
|
60 } else { |
|
61 memcpy(stack_args, &data, sizeof(data)); |
|
62 stack_args++; |
|
63 } |
|
64 } |
|
65 |
|
66 static inline void alloc_float(double* &freg_args, |
|
67 uint64_t* &stack_args, |
|
68 double* end, |
|
69 float data) |
|
70 { |
|
71 if (freg_args < end) { |
|
72 memcpy(freg_args, &data, sizeof(data)); |
|
73 freg_args++; |
|
74 } else { |
|
75 memcpy(stack_args, &data, sizeof(data)); |
|
76 stack_args++; |
|
77 } |
|
78 } |
|
79 |
|
80 |
|
81 extern "C" void |
|
82 invoke_copy_to_stack(uint64_t* stk, uint64_t *end, |
|
83 uint32_t paramCount, nsXPTCVariant* s) |
|
84 { |
|
85 uint64_t *ireg_args = stk; |
|
86 uint64_t *ireg_end = ireg_args + 8; |
|
87 double *freg_args = (double *)ireg_end; |
|
88 double *freg_end = freg_args + 8; |
|
89 uint64_t *stack_args = (uint64_t *)freg_end; |
|
90 |
|
91 // leave room for 'that' argument in x0 |
|
92 ++ireg_args; |
|
93 |
|
94 for (uint32_t i = 0; i < paramCount; i++, s++) { |
|
95 if (s->IsPtrData()) { |
|
96 alloc_word(ireg_args, stack_args, ireg_end, (uint64_t)s->ptr); |
|
97 continue; |
|
98 } |
|
99 // According to the ABI, integral types that are smaller than 8 bytes |
|
100 // are to be passed in 8-byte registers or 8-byte stack slots. |
|
101 switch (s->type) { |
|
102 case nsXPTType::T_FLOAT: |
|
103 alloc_float(freg_args, stack_args, freg_end, s->val.f); |
|
104 break; |
|
105 case nsXPTType::T_DOUBLE: |
|
106 alloc_double(freg_args, stack_args, freg_end, s->val.d); |
|
107 break; |
|
108 case nsXPTType::T_I8: alloc_word(ireg_args, stk, end, s->val.i8); break; |
|
109 case nsXPTType::T_I16: alloc_word(ireg_args, stk, end, s->val.i16); break; |
|
110 case nsXPTType::T_I32: alloc_word(ireg_args, stk, end, s->val.i32); break; |
|
111 case nsXPTType::T_I64: alloc_word(ireg_args, stk, end, s->val.i64); break; |
|
112 case nsXPTType::T_U8: alloc_word(ireg_args, stk, end, s->val.u8); break; |
|
113 case nsXPTType::T_U16: alloc_word(ireg_args, stk, end, s->val.u16); break; |
|
114 case nsXPTType::T_U32: alloc_word(ireg_args, stk, end, s->val.u32); break; |
|
115 case nsXPTType::T_U64: alloc_word(ireg_args, stk, end, s->val.u64); break; |
|
116 case nsXPTType::T_BOOL: alloc_word(ireg_args, stk, end, s->val.b); break; |
|
117 case nsXPTType::T_CHAR: alloc_word(ireg_args, stk, end, s->val.c); break; |
|
118 case nsXPTType::T_WCHAR: alloc_word(ireg_args, stk, end, s->val.wc); break; |
|
119 default: |
|
120 // all the others are plain pointer types |
|
121 alloc_word(ireg_args, stack_args, ireg_end, |
|
122 reinterpret_cast<uint64_t>(s->val.p)); |
|
123 break; |
|
124 } |
|
125 } |
|
126 } |
|
127 |
|
128 extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, |
|
129 uint32_t paramCount, nsXPTCVariant* params); |
|
130 |
|
131 EXPORT_XPCOM_API(nsresult) |
|
132 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, |
|
133 uint32_t paramCount, nsXPTCVariant* params) |
|
134 { |
|
135 return _NS_InvokeByIndex(that, methodIndex, paramCount, params); |
|
136 } |