Line 0
Link Here
|
|
|
1 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 |
/* ***** BEGIN LICENSE BLOCK ***** |
3 |
* Version: NPL 1.1/GPL 2.0/LGPL 2.1 |
4 |
* |
5 |
* The contents of this file are subject to the Netscape Public License |
6 |
* Version 1.1 (the "License"); you may not use this file except in |
7 |
* compliance with the License. You may obtain a copy of the License at |
8 |
* http://www.mozilla.org/NPL/ |
9 |
* |
10 |
* Software distributed under the License is distributed on an "AS IS" basis, |
11 |
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
12 |
* for the specific language governing rights and limitations under the |
13 |
* License. |
14 |
* |
15 |
* The Original Code is mozilla.org code. |
16 |
* |
17 |
* The Initial Developer of the Original Code is |
18 |
* Netscape Communications Corporation. |
19 |
* Portions created by the Initial Developer are Copyright (C) 1999 |
20 |
* the Initial Developer. All Rights Reserved. |
21 |
* |
22 |
* Contributor(s): |
23 |
* Franz.Sirl-kernel@lauterbach.com (Franz Sirl) |
24 |
* beard@netscape.com (Patrick Beard) |
25 |
* waterson@netscape.com (Chris Waterson) |
26 |
* tom_gall@mac.com (Tom Gall) |
27 |
* |
28 |
* Alternatively, the contents of this file may be used under the terms of |
29 |
* either the GNU General Public License Version 2 or later (the "GPL"), or |
30 |
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
31 |
* in which case the provisions of the GPL or the LGPL are applicable instead |
32 |
* of those above. If you wish to allow use of your version of this file only |
33 |
* under the terms of either the GPL or the LGPL, and not to allow others to |
34 |
* use your version of this file under the terms of the NPL, indicate your |
35 |
* decision by deleting the provisions above and replace them with the notice |
36 |
* and other provisions required by the GPL or the LGPL. If you do not delete |
37 |
* the provisions above, a recipient may use your version of this file under |
38 |
* the terms of any one of the NPL, the GPL or the LGPL. |
39 |
* |
40 |
* ***** END LICENSE BLOCK ***** */ |
41 |
|
42 |
// Implement shared vtbl methods. |
43 |
|
44 |
#include "xptcprivate.h" |
45 |
|
46 |
// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral |
47 |
// parameters and the first 8 floating point parameters in registers |
48 |
// (r3-r10 and f1-f8), no stack space is allocated for these by the |
49 |
// caller. The rest of the parameters are passed in the callers stack |
50 |
// area. The stack pointer has to retain 16-byte alignment, longlongs |
51 |
// and doubles are aligned on 8-byte boundaries. |
52 |
|
53 |
#define PARAM_BUFFER_COUNT 16 |
54 |
#define GPR_COUNT 8 |
55 |
#define FPR_COUNT 8 |
56 |
|
57 |
// PrepareAndDispatch() is called by SharedStub() and calls the actual method. |
58 |
// |
59 |
// - 'args[]' contains the arguments passed on stack |
60 |
// - 'gprData[]' contains the arguments passed in integer registers |
61 |
// - 'fprData[]' contains the arguments passed in floating point registers |
62 |
// |
63 |
// The parameters are mapped into an array of type 'nsXPTCMiniVariant' |
64 |
// and then the method gets called. |
65 |
|
66 |
extern "C" nsresult |
67 |
PrepareAndDispatch(nsXPTCStubBase* self, |
68 |
PRUint32 methodIndex, |
69 |
PRUint32* args, |
70 |
PRUint64 *gprData, |
71 |
double *fprData) |
72 |
{ |
73 |
nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; |
74 |
nsXPTCMiniVariant* dispatchParams = NULL; |
75 |
nsIInterfaceInfo* iface_info = NULL; |
76 |
const nsXPTMethodInfo* info; |
77 |
PRUint32 paramCount; |
78 |
PRUint32 i; |
79 |
nsresult result = NS_ERROR_FAILURE; |
80 |
|
81 |
NS_ASSERTION(self,"no self"); |
82 |
|
83 |
self->GetInterfaceInfo(&iface_info); |
84 |
NS_ASSERTION(iface_info,"no interface info"); |
85 |
if (! iface_info) |
86 |
return NS_ERROR_UNEXPECTED; |
87 |
|
88 |
iface_info->GetMethodInfo(PRUint16(methodIndex), &info); |
89 |
NS_ASSERTION(info,"no method info"); |
90 |
if (! info) |
91 |
return NS_ERROR_UNEXPECTED; |
92 |
|
93 |
paramCount = info->GetParamCount(); |
94 |
|
95 |
// setup variant array pointer |
96 |
if(paramCount > PARAM_BUFFER_COUNT) |
97 |
dispatchParams = new nsXPTCMiniVariant[paramCount]; |
98 |
else |
99 |
dispatchParams = paramBuffer; |
100 |
|
101 |
NS_ASSERTION(dispatchParams,"no place for params"); |
102 |
if (! dispatchParams) |
103 |
return NS_ERROR_OUT_OF_MEMORY; |
104 |
|
105 |
PRUint32* ap = args; |
106 |
PRUint32 gpr = 1; // skip one GPR register |
107 |
PRUint32 fpr = 0; |
108 |
PRUint32 tempu32; |
109 |
PRUint64 tempu64; |
110 |
|
111 |
for(i = 0; i < paramCount; i++) { |
112 |
const nsXPTParamInfo& param = info->GetParam(i); |
113 |
const nsXPTType& type = param.GetType(); |
114 |
nsXPTCMiniVariant* dp = &dispatchParams[i]; |
115 |
|
116 |
if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { |
117 |
if (fpr < FPR_COUNT) |
118 |
dp->val.d = fprData[fpr++]; |
119 |
else { |
120 |
if ((PRUint32) ap & 4) ap++; // doubles are 8-byte aligned on stack |
121 |
dp->val.d = *(double*) ap; |
122 |
ap += 2; |
123 |
} |
124 |
continue; |
125 |
} |
126 |
else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { |
127 |
if (fpr < FPR_COUNT) |
128 |
dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles |
129 |
else |
130 |
dp->val.f = *(float*) ap++; |
131 |
continue; |
132 |
} |
133 |
else if (!param.IsOut() && (type == nsXPTType::T_I64 |
134 |
|| type == nsXPTType::T_U64)) { |
135 |
if (gpr < GPR_COUNT) { |
136 |
tempu64 = gprData[gpr++]; |
137 |
} |
138 |
else { |
139 |
if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack |
140 |
tempu64 = *(PRUint64*) ap; |
141 |
ap += 2; |
142 |
} |
143 |
} |
144 |
else { |
145 |
if (gpr < GPR_COUNT) |
146 |
tempu32 = gprData[gpr++]; |
147 |
else |
148 |
tempu32 = *ap++; |
149 |
} |
150 |
|
151 |
if(param.IsOut() || !type.IsArithmetic()) { |
152 |
dp->val.p = (void*) tempu32; |
153 |
continue; |
154 |
} |
155 |
|
156 |
switch(type) { |
157 |
case nsXPTType::T_I8: dp->val.i8 = (PRInt8) tempu32; break; |
158 |
case nsXPTType::T_I16: dp->val.i16 = (PRInt16) tempu32; break; |
159 |
case nsXPTType::T_I32: dp->val.i32 = (PRInt32) tempu32; break; |
160 |
case nsXPTType::T_I64: dp->val.i64 = (PRInt64) tempu64; break; |
161 |
case nsXPTType::T_U8: dp->val.u8 = (PRUint8) tempu32; break; |
162 |
case nsXPTType::T_U16: dp->val.u16 = (PRUint16) tempu32; break; |
163 |
case nsXPTType::T_U32: dp->val.u32 = (PRUint32) tempu32; break; |
164 |
case nsXPTType::T_U64: dp->val.u64 = (PRUint64) tempu64; break; |
165 |
case nsXPTType::T_BOOL: dp->val.b = (PRBool) tempu32; break; |
166 |
case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break; |
167 |
case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break; |
168 |
|
169 |
default: |
170 |
NS_ASSERTION(0, "bad type"); |
171 |
break; |
172 |
} |
173 |
} |
174 |
|
175 |
result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams); |
176 |
|
177 |
NS_RELEASE(iface_info); |
178 |
|
179 |
if (dispatchParams != paramBuffer) |
180 |
delete [] dispatchParams; |
181 |
|
182 |
return result; |
183 |
} |
184 |
|
185 |
// Load r11 with the constant 'n' and branch to SharedStub(). |
186 |
// |
187 |
// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; |
188 |
// however, it's quick, dirty, and'll break when the ABI changes on |
189 |
// us, which is what we want ;-). |
190 |
|
191 |
#if __GXX_ABI_VERSION < 100 |
192 |
// gcc-2 version |
193 |
# define STUB_ENTRY(n) \ |
194 |
__asm__ ( \ |
195 |
".section \".text\" \n\t" \ |
196 |
".align 4 \n\t" \ |
197 |
".globl Stub"#n"__14nsXPTCStubBase \n\t" \ |
198 |
".type Stub"#n"__14nsXPTCStubBase,@function \n\n" \ |
199 |
\ |
200 |
"Stub"#n"__14nsXPTCStubBase: \n\t" \ |
201 |
"li 11,"#n" \n\t" \ |
202 |
"b SharedStub@local \n" \ |
203 |
); |
204 |
#else |
205 |
// gcc-3 version |
206 |
// |
207 |
// As G++3 ABI contains the length of the functionname in the mangled |
208 |
// name, it is difficult to get a generic assembler mechanism like |
209 |
// in the G++ 2.95 case. |
210 |
// Create names would be like: |
211 |
// _ZN14nsXPTCStubBase5Stub1Ev |
212 |
// _ZN14nsXPTCStubBase6Stub12Ev |
213 |
// _ZN14nsXPTCStubBase7Stub123Ev |
214 |
// _ZN14nsXPTCStubBase8Stub1234Ev |
215 |
// etc. |
216 |
// Use assembler directives to get the names right... |
217 |
|
218 |
# define STUB_ENTRY(n) \ |
219 |
__asm__ ( \ |
220 |
".align 4 \n\t" \ |
221 |
".if "#n" < 10 \n\t" \ |
222 |
".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ |
223 |
".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ |
224 |
"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ |
225 |
\ |
226 |
".elseif "#n" < 100 \n\t" \ |
227 |
".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ |
228 |
".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ |
229 |
"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ |
230 |
\ |
231 |
".elseif "#n" < 1000 \n\t" \ |
232 |
".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ |
233 |
".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ |
234 |
"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ |
235 |
\ |
236 |
".else \n\t" \ |
237 |
".err \"stub number "#n" >= 1000 not yet supported\"\n" \ |
238 |
".endif \n\t" \ |
239 |
\ |
240 |
"li 11,"#n" \n\t" \ |
241 |
"b SharedStub \n" \ |
242 |
); |
243 |
#endif |
244 |
|
245 |
// "b SharedStub@local \n" |
246 |
|
247 |
#define SENTINEL_ENTRY(n) \ |
248 |
nsresult nsXPTCStubBase::Sentinel##n() \ |
249 |
{ \ |
250 |
NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ |
251 |
return NS_ERROR_NOT_IMPLEMENTED; \ |
252 |
} |
253 |
|
254 |
#include "xptcstubsdef.inc" |