|
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 // The purpose of NS_InvokeByIndex() is to map a platform |
|
9 // indepenpent call to the platform ABI. To do that, |
|
10 // NS_InvokeByIndex() has to determine the method to call via vtable |
|
11 // access. The parameters for the method are read from the |
|
12 // nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC |
|
13 // ABI this means that the first 8 integral and floating point |
|
14 // parameters are passed in registers. |
|
15 |
|
16 #include "xptcprivate.h" |
|
17 |
|
18 // 8 integral parameters are passed in registers |
|
19 #define GPR_COUNT 8 |
|
20 |
|
21 // With hardfloat support 8 floating point parameters are passed in registers, |
|
22 // floats are promoted to doubles when passed in registers |
|
23 // In Softfloat mode, everything is handled via gprs |
|
24 #ifndef __NO_FPRS__ |
|
25 #define FPR_COUNT 8 |
|
26 #endif |
|
27 extern "C" uint32_t |
|
28 invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) |
|
29 { |
|
30 return uint32_t(((paramCount * 2) + 3) & ~3); |
|
31 } |
|
32 |
|
33 extern "C" void |
|
34 invoke_copy_to_stack(uint32_t* d, |
|
35 uint32_t paramCount, |
|
36 nsXPTCVariant* s, |
|
37 uint32_t* gpregs, |
|
38 double* fpregs) |
|
39 { |
|
40 uint32_t gpr = 1; // skip one GP reg for 'that' |
|
41 #ifndef __NO_FPRS__ |
|
42 uint32_t fpr = 0; |
|
43 #endif |
|
44 uint32_t tempu32; |
|
45 uint64_t tempu64; |
|
46 |
|
47 for(uint32_t i = 0; i < paramCount; i++, s++) { |
|
48 if(s->IsPtrData()) { |
|
49 if(s->type == nsXPTType::T_JSVAL) |
|
50 tempu32 = (uint32_t) &s->ptr; |
|
51 else |
|
52 tempu32 = (uint32_t) s->ptr; |
|
53 } |
|
54 else { |
|
55 switch(s->type) { |
|
56 case nsXPTType::T_FLOAT: break; |
|
57 case nsXPTType::T_DOUBLE: break; |
|
58 case nsXPTType::T_I8: tempu32 = s->val.i8; break; |
|
59 case nsXPTType::T_I16: tempu32 = s->val.i16; break; |
|
60 case nsXPTType::T_I32: tempu32 = s->val.i32; break; |
|
61 case nsXPTType::T_I64: tempu64 = s->val.i64; break; |
|
62 case nsXPTType::T_U8: tempu32 = s->val.u8; break; |
|
63 case nsXPTType::T_U16: tempu32 = s->val.u16; break; |
|
64 case nsXPTType::T_U32: tempu32 = s->val.u32; break; |
|
65 case nsXPTType::T_U64: tempu64 = s->val.u64; break; |
|
66 case nsXPTType::T_BOOL: tempu32 = s->val.b; break; |
|
67 case nsXPTType::T_CHAR: tempu32 = s->val.c; break; |
|
68 case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break; |
|
69 default: tempu32 = (uint32_t) s->val.p; break; |
|
70 } |
|
71 } |
|
72 |
|
73 if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { |
|
74 #ifndef __NO_FPRS__ |
|
75 if (fpr < FPR_COUNT) |
|
76 fpregs[fpr++] = s->val.d; |
|
77 #else |
|
78 if (gpr & 1) |
|
79 gpr++; |
|
80 if ((gpr + 1) < GPR_COUNT) { |
|
81 *((double*) &gpregs[gpr]) = s->val.d; |
|
82 gpr += 2; |
|
83 } |
|
84 #endif |
|
85 else { |
|
86 if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack |
|
87 *((double*) d) = s->val.d; |
|
88 d += 2; |
|
89 } |
|
90 } |
|
91 else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { |
|
92 #ifndef __NO_FPRS__ |
|
93 if (fpr < FPR_COUNT) |
|
94 fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles |
|
95 #else |
|
96 if (gpr < GPR_COUNT) |
|
97 *((float*) &gpregs[gpr++]) = s->val.f; |
|
98 #endif |
|
99 else |
|
100 *((float*) d++) = s->val.f; |
|
101 } |
|
102 else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64 |
|
103 || s->type == nsXPTType::T_U64)) { |
|
104 if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 |
|
105 if ((gpr + 1) < GPR_COUNT) { |
|
106 *((uint64_t*) &gpregs[gpr]) = tempu64; |
|
107 gpr += 2; |
|
108 } |
|
109 else { |
|
110 if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack |
|
111 *((uint64_t*) d) = tempu64; |
|
112 d += 2; |
|
113 } |
|
114 } |
|
115 else { |
|
116 if (gpr < GPR_COUNT) |
|
117 gpregs[gpr++] = tempu32; |
|
118 else |
|
119 *d++ = tempu32; |
|
120 } |
|
121 |
|
122 } |
|
123 } |
|
124 |
|
125 extern "C" |
|
126 EXPORT_XPCOM_API(nsresult) |
|
127 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, |
|
128 uint32_t paramCount, nsXPTCVariant* params); |