|
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 // 8 floating point parameters are passed in registers, floats are |
|
22 // promoted to doubles when passed in registers |
|
23 #define FPR_COUNT 8 |
|
24 |
|
25 extern "C" uint32_t |
|
26 invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) |
|
27 { |
|
28 return uint32_t(((paramCount * 2) + 3) & ~3); |
|
29 } |
|
30 |
|
31 extern "C" void |
|
32 invoke_copy_to_stack(uint32_t* d, |
|
33 uint32_t paramCount, |
|
34 nsXPTCVariant* s, |
|
35 uint32_t* gpregs, |
|
36 double* fpregs) |
|
37 { |
|
38 uint32_t gpr = 1; // skip one GP reg for 'that' |
|
39 uint32_t fpr = 0; |
|
40 uint32_t tempu32; |
|
41 uint64_t tempu64; |
|
42 |
|
43 for(uint32_t i = 0; i < paramCount; i++, s++) { |
|
44 if(s->IsPtrData()) { |
|
45 if(s->type == nsXPTType::T_JSVAL) |
|
46 tempu32 = (uint32_t) &(s->ptr); |
|
47 else |
|
48 tempu32 = (uint32_t) s->ptr; |
|
49 } else { |
|
50 switch(s->type) { |
|
51 case nsXPTType::T_FLOAT: break; |
|
52 case nsXPTType::T_DOUBLE: break; |
|
53 case nsXPTType::T_I8: tempu32 = s->val.i8; break; |
|
54 case nsXPTType::T_I16: tempu32 = s->val.i16; break; |
|
55 case nsXPTType::T_I32: tempu32 = s->val.i32; break; |
|
56 case nsXPTType::T_I64: tempu64 = s->val.i64; break; |
|
57 case nsXPTType::T_U8: tempu32 = s->val.u8; break; |
|
58 case nsXPTType::T_U16: tempu32 = s->val.u16; break; |
|
59 case nsXPTType::T_U32: tempu32 = s->val.u32; break; |
|
60 case nsXPTType::T_U64: tempu64 = s->val.u64; break; |
|
61 case nsXPTType::T_BOOL: tempu32 = s->val.b; break; |
|
62 case nsXPTType::T_CHAR: tempu32 = s->val.c; break; |
|
63 case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break; |
|
64 default: tempu32 = (uint32_t) s->val.p; break; |
|
65 } |
|
66 } |
|
67 |
|
68 if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { |
|
69 if (fpr < FPR_COUNT) |
|
70 fpregs[fpr++] = s->val.d; |
|
71 else { |
|
72 if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack |
|
73 *((double*) d) = s->val.d; |
|
74 d += 2; |
|
75 } |
|
76 } |
|
77 else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { |
|
78 if (fpr < FPR_COUNT) |
|
79 fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles |
|
80 else |
|
81 *((float*) d++) = s->val.f; |
|
82 } |
|
83 else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64 |
|
84 || s->type == nsXPTType::T_U64)) { |
|
85 if ((gpr + 1) < GPR_COUNT) { |
|
86 if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 |
|
87 *((uint64_t*) &gpregs[gpr]) = tempu64; |
|
88 gpr += 2; |
|
89 } |
|
90 else { |
|
91 if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack |
|
92 *((uint64_t*) d) = tempu64; |
|
93 d += 2; |
|
94 } |
|
95 } |
|
96 else { |
|
97 if (gpr < GPR_COUNT) |
|
98 gpregs[gpr++] = tempu32; |
|
99 else |
|
100 *d++ = tempu32; |
|
101 } |
|
102 |
|
103 } |
|
104 } |
|
105 |
|
106 extern "C" |
|
107 EXPORT_XPCOM_API(nsresult) |
|
108 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, |
|
109 uint32_t paramCount, nsXPTCVariant* params); |