|
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 /* Implement shared vtbl methods. */ |
|
7 |
|
8 #include "xptcprivate.h" |
|
9 #include "xptiprivate.h" |
|
10 |
|
11 /* Prototype specifies unmangled function name and disables unused warning */ |
|
12 static nsresult |
|
13 PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) |
|
14 __asm__("PrepareAndDispatch") ATTRIBUTE_USED; |
|
15 |
|
16 static nsresult |
|
17 PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) |
|
18 { |
|
19 const uint8_t PARAM_BUFFER_COUNT = 16; |
|
20 const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer |
|
21 |
|
22 nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; |
|
23 nsXPTCMiniVariant* dispatchParams = nullptr; |
|
24 const nsXPTMethodInfo* info; |
|
25 uint8_t paramCount; |
|
26 uint8_t i; |
|
27 nsresult result = NS_ERROR_FAILURE; |
|
28 |
|
29 NS_ASSERTION(self,"no self"); |
|
30 |
|
31 self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); |
|
32 |
|
33 paramCount = info->GetParamCount(); |
|
34 |
|
35 // setup variant array pointer |
|
36 if(paramCount > PARAM_BUFFER_COUNT) |
|
37 dispatchParams = new nsXPTCMiniVariant[paramCount]; |
|
38 else |
|
39 dispatchParams = paramBuffer; |
|
40 |
|
41 NS_ASSERTION(dispatchParams,"no place for params"); |
|
42 if (!dispatchParams) |
|
43 return NS_ERROR_OUT_OF_MEMORY; |
|
44 |
|
45 // args[0] to args[NUM_ARG_REGS] hold floating point register values |
|
46 uint64_t* ap = args + NUM_ARG_REGS; |
|
47 for(i = 0; i < paramCount; i++, ap++) |
|
48 { |
|
49 const nsXPTParamInfo& param = info->GetParam(i); |
|
50 const nsXPTType& type = param.GetType(); |
|
51 nsXPTCMiniVariant* dp = &dispatchParams[i]; |
|
52 |
|
53 if(param.IsOut() || !type.IsArithmetic()) |
|
54 { |
|
55 dp->val.p = (void*) *ap; |
|
56 continue; |
|
57 } |
|
58 // else |
|
59 switch(type) |
|
60 { |
|
61 case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break; |
|
62 case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break; |
|
63 case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break; |
|
64 case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break; |
|
65 case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break; |
|
66 case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break; |
|
67 case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break; |
|
68 case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break; |
|
69 case nsXPTType::T_FLOAT : |
|
70 if(i < NUM_ARG_REGS) |
|
71 { |
|
72 // floats passed via registers are stored as doubles |
|
73 // in the first NUM_ARG_REGS entries in args |
|
74 dp->val.u64 = (uint64_t) args[i]; |
|
75 dp->val.f = (float) dp->val.d; // convert double to float |
|
76 } |
|
77 else |
|
78 dp->val.u32 = (uint32_t) *ap; |
|
79 break; |
|
80 case nsXPTType::T_DOUBLE : |
|
81 // doubles passed via registers are also stored |
|
82 // in the first NUM_ARG_REGS entries in args |
|
83 dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap; |
|
84 break; |
|
85 case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break; |
|
86 case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break; |
|
87 case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break; |
|
88 default: |
|
89 NS_ERROR("bad type"); |
|
90 break; |
|
91 } |
|
92 } |
|
93 |
|
94 result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); |
|
95 |
|
96 if(dispatchParams != paramBuffer) |
|
97 delete [] dispatchParams; |
|
98 |
|
99 return result; |
|
100 } |
|
101 |
|
102 /* |
|
103 * SharedStub() |
|
104 * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is |
|
105 * passed to this function via $1 to preserve the argument registers. |
|
106 */ |
|
107 __asm__( |
|
108 "#### SharedStub ####\n" |
|
109 ".text\n\t" |
|
110 ".align 5\n\t" |
|
111 ".ent SharedStub\n" |
|
112 "SharedStub:\n\t" |
|
113 ".frame $30,96,$26,0\n\t" |
|
114 ".mask 0x4000000,-96\n\t" |
|
115 "ldgp $29,0($27)\n" |
|
116 "$SharedStub..ng:\n\t" |
|
117 "subq $30,96,$30\n\t" |
|
118 "stq $26,0($30)\n\t" |
|
119 ".prologue 1\n\t" |
|
120 |
|
121 /* |
|
122 * Store arguments passed via registers to the stack. |
|
123 * Floating point registers are stored as doubles and converted |
|
124 * to floats in PrepareAndDispatch if necessary. |
|
125 */ |
|
126 "stt $f17,16($30)\n\t" /* floating point registers */ |
|
127 "stt $f18,24($30)\n\t" |
|
128 "stt $f19,32($30)\n\t" |
|
129 "stt $f20,40($30)\n\t" |
|
130 "stt $f21,48($30)\n\t" |
|
131 "stq $17,56($30)\n\t" /* integer registers */ |
|
132 "stq $18,64($30)\n\t" |
|
133 "stq $19,72($30)\n\t" |
|
134 "stq $20,80($30)\n\t" |
|
135 "stq $21,88($30)\n\t" |
|
136 |
|
137 /* |
|
138 * Call PrepareAndDispatch function. |
|
139 */ |
|
140 "bis $1,$1,$17\n\t" /* pass "methodIndex" */ |
|
141 "addq $30,16,$18\n\t" /* pass "args" */ |
|
142 "bsr $26,$PrepareAndDispatch..ng\n\t" |
|
143 |
|
144 "ldq $26,0($30)\n\t" |
|
145 "addq $30,96,$30\n\t" |
|
146 "ret $31,($26),1\n\t" |
|
147 ".end SharedStub" |
|
148 ); |
|
149 |
|
150 /* |
|
151 * nsresult nsXPTCStubBase::Stub##n() |
|
152 * Sets register $1 to "methodIndex" and jumps to SharedStub. |
|
153 */ |
|
154 #define STUB_MANGLED_ENTRY(n, symbol) \ |
|
155 "#### Stub"#n" ####" "\n\t" \ |
|
156 ".text" "\n\t" \ |
|
157 ".align 5" "\n\t" \ |
|
158 ".globl " symbol "\n\t" \ |
|
159 ".ent " symbol "\n" \ |
|
160 symbol ":" "\n\t" \ |
|
161 ".frame $30,0,$26,0" "\n\t" \ |
|
162 "ldgp $29,0($27)" "\n" \ |
|
163 "$" symbol "..ng:" "\n\t" \ |
|
164 ".prologue 1" "\n\t" \ |
|
165 "lda $1,"#n "\n\t" \ |
|
166 "br $31,$SharedStub..ng" "\n\t" \ |
|
167 ".end " symbol |
|
168 |
|
169 #define STUB_ENTRY(n) \ |
|
170 __asm__( \ |
|
171 ".if "#n" < 10" "\n\t" \ |
|
172 STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \ |
|
173 ".elseif "#n" < 100" "\n\t" \ |
|
174 STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \ |
|
175 ".elseif "#n" < 1000" "\n\t" \ |
|
176 STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \ |
|
177 ".else" "\n\t" \ |
|
178 ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \ |
|
179 ".endif" \ |
|
180 ); |
|
181 |
|
182 #define SENTINEL_ENTRY(n) \ |
|
183 nsresult nsXPTCStubBase::Sentinel##n() \ |
|
184 { \ |
|
185 NS_ERROR("nsXPTCStubBase::Sentinel called"); \ |
|
186 return NS_ERROR_NOT_IMPLEMENTED; \ |
|
187 } |
|
188 |
|
189 #include "xptcstubsdef.inc" |