|
1 /* -*- Mode: C -*- */ |
|
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 #include "xptcprivate.h" |
|
7 #include "xptiprivate.h" |
|
8 |
|
9 /* Under the Mac OS X PowerPC ABI, the first 8 integer and 13 floating point |
|
10 * parameters are delivered in registers and are not on the stack, although |
|
11 * stack space is allocated for them. The integer parameters are delivered |
|
12 * in GPRs r3 through r10. The first 8 words of the parameter area on the |
|
13 * stack shadow these registers. A word will either be in a register or on |
|
14 * the stack, but not in both. Although the first floating point parameters |
|
15 * are passed in floating point registers, GPR space and stack space is |
|
16 * reserved for them as well. |
|
17 * |
|
18 * SharedStub has passed pointers to the parameter section of the stack |
|
19 * and saved copies of the GPRs and FPRs used for parameter passing. We |
|
20 * don't care about the first parameter (which is delivered here as the self |
|
21 * pointer), so SharedStub pointed us past that. argsGPR thus points to GPR |
|
22 * r4 (corresponding to the first argument after the self pointer) and |
|
23 * argsStack points to the parameter section of the caller's stack frame |
|
24 * reserved for the same argument. This way, it is possible to reference |
|
25 * either argsGPR or argsStack with the same index. |
|
26 * |
|
27 * Contrary to the assumption made by the previous implementation, the |
|
28 * Mac OS X PowerPC ABI doesn't impose any special alignment restrictions on |
|
29 * parameter sections of stacks. Values that are 64 bits wide appear on the |
|
30 * stack without any special padding. |
|
31 * |
|
32 * See also xptcstubs_asm_ppc_darwin.s.m4:_SharedStub. |
|
33 * |
|
34 * ABI reference: |
|
35 * http://developer.apple.com/documentation/DeveloperTools/Conceptual/ |
|
36 * MachORuntime/PowerPCConventions/chapter_3_section_1.html */ |
|
37 |
|
38 extern "C" nsresult ATTRIBUTE_USED |
|
39 PrepareAndDispatch( |
|
40 nsXPTCStubBase *self, |
|
41 uint32_t methodIndex, |
|
42 uint32_t *argsStack, |
|
43 uint32_t *argsGPR, |
|
44 double *argsFPR) { |
|
45 #define PARAM_BUFFER_COUNT 16 |
|
46 #define PARAM_FPR_COUNT 13 |
|
47 #define PARAM_GPR_COUNT 7 |
|
48 |
|
49 nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; |
|
50 nsXPTCMiniVariant *dispatchParams = nullptr; |
|
51 const nsXPTMethodInfo *methodInfo; |
|
52 uint8_t paramCount; |
|
53 uint8_t i; |
|
54 nsresult result = NS_ERROR_FAILURE; |
|
55 uint32_t argIndex = 0; |
|
56 uint32_t fprIndex = 0; |
|
57 |
|
58 typedef struct { |
|
59 uint32_t hi; |
|
60 uint32_t lo; |
|
61 } DU; |
|
62 |
|
63 NS_ASSERTION(self, "no self"); |
|
64 |
|
65 self->mEntry->GetMethodInfo(uint16_t(methodIndex), &methodInfo); |
|
66 NS_ASSERTION(methodInfo, "no method info"); |
|
67 |
|
68 paramCount = methodInfo->GetParamCount(); |
|
69 |
|
70 if(paramCount > PARAM_BUFFER_COUNT) { |
|
71 dispatchParams = new nsXPTCMiniVariant[paramCount]; |
|
72 } |
|
73 else { |
|
74 dispatchParams = paramBuffer; |
|
75 } |
|
76 NS_ASSERTION(dispatchParams,"no place for params"); |
|
77 |
|
78 for(i = 0; i < paramCount; i++, argIndex++) { |
|
79 const nsXPTParamInfo ¶m = methodInfo->GetParam(i); |
|
80 const nsXPTType &type = param.GetType(); |
|
81 nsXPTCMiniVariant *dp = &dispatchParams[i]; |
|
82 uint32_t theParam; |
|
83 |
|
84 if(argIndex < PARAM_GPR_COUNT) |
|
85 theParam = argsGPR[argIndex]; |
|
86 else |
|
87 theParam = argsStack[argIndex]; |
|
88 |
|
89 if(param.IsOut() || !type.IsArithmetic()) |
|
90 dp->val.p = (void *) theParam; |
|
91 else { |
|
92 switch(type) { |
|
93 case nsXPTType::T_I8: |
|
94 dp->val.i8 = (int8_t) theParam; |
|
95 break; |
|
96 case nsXPTType::T_I16: |
|
97 dp->val.i16 = (int16_t) theParam; |
|
98 break; |
|
99 case nsXPTType::T_I32: |
|
100 dp->val.i32 = (int32_t) theParam; |
|
101 break; |
|
102 case nsXPTType::T_U8: |
|
103 dp->val.u8 = (uint8_t) theParam; |
|
104 break; |
|
105 case nsXPTType::T_U16: |
|
106 dp->val.u16 = (uint16_t) theParam; |
|
107 break; |
|
108 case nsXPTType::T_U32: |
|
109 dp->val.u32 = (uint32_t) theParam; |
|
110 break; |
|
111 case nsXPTType::T_I64: |
|
112 case nsXPTType::T_U64: |
|
113 ((DU *)dp)->hi = (uint32_t) theParam; |
|
114 if(++argIndex < PARAM_GPR_COUNT) |
|
115 ((DU *)dp)->lo = (uint32_t) argsGPR[argIndex]; |
|
116 else |
|
117 ((DU *)dp)->lo = (uint32_t) argsStack[argIndex]; |
|
118 break; |
|
119 case nsXPTType::T_BOOL: |
|
120 dp->val.b = (bool) theParam; |
|
121 break; |
|
122 case nsXPTType::T_CHAR: |
|
123 dp->val.c = (char) theParam; |
|
124 break; |
|
125 case nsXPTType::T_WCHAR: |
|
126 dp->val.wc = (wchar_t) theParam; |
|
127 break; |
|
128 case nsXPTType::T_FLOAT: |
|
129 if(fprIndex < PARAM_FPR_COUNT) |
|
130 dp->val.f = (float) argsFPR[fprIndex++]; |
|
131 else |
|
132 dp->val.f = *(float *) &argsStack[argIndex]; |
|
133 break; |
|
134 case nsXPTType::T_DOUBLE: |
|
135 if(fprIndex < PARAM_FPR_COUNT) |
|
136 dp->val.d = argsFPR[fprIndex++]; |
|
137 else |
|
138 dp->val.d = *(double *) &argsStack[argIndex]; |
|
139 argIndex++; |
|
140 break; |
|
141 default: |
|
142 NS_ERROR("bad type"); |
|
143 break; |
|
144 } |
|
145 } |
|
146 } |
|
147 |
|
148 result = self->mOuter-> |
|
149 CallMethod((uint16_t)methodIndex, methodInfo, dispatchParams); |
|
150 |
|
151 if(dispatchParams != paramBuffer) |
|
152 delete [] dispatchParams; |
|
153 |
|
154 return result; |
|
155 } |
|
156 |
|
157 #define STUB_ENTRY(n) |
|
158 #define SENTINEL_ENTRY(n) \ |
|
159 nsresult nsXPTCStubBase::Sentinel##n() \ |
|
160 { \ |
|
161 NS_ERROR("nsXPTCStubBase::Sentinel called"); \ |
|
162 return NS_ERROR_NOT_IMPLEMENTED; \ |
|
163 } |
|
164 |
|
165 #include "xptcstubsdef.inc" |