|
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 #include "xptcprivate.h" |
|
7 #include "xptiprivate.h" |
|
8 |
|
9 #ifndef __AARCH64EL__ |
|
10 #error "Only little endian compatibility was tested" |
|
11 #endif |
|
12 |
|
13 /* |
|
14 * This is for AArch64 ABI |
|
15 * |
|
16 * When we're called, the "gp" registers are stored in gprData and |
|
17 * the "fp" registers are stored in fprData. Each array has 8 regs |
|
18 * but first reg in gprData is a placeholder for 'self'. |
|
19 */ |
|
20 extern "C" nsresult |
|
21 PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args, |
|
22 uint64_t *gprData, double *fprData) |
|
23 { |
|
24 #define PARAM_BUFFER_COUNT 16 |
|
25 #define PARAM_GPR_COUNT 8 |
|
26 #define PARAM_FPR_COUNT 8 |
|
27 |
|
28 nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; |
|
29 nsXPTCMiniVariant* dispatchParams = NULL; |
|
30 const nsXPTMethodInfo* info; |
|
31 nsresult result = NS_ERROR_FAILURE; |
|
32 |
|
33 NS_ASSERTION(self,"no self"); |
|
34 |
|
35 self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); |
|
36 NS_ASSERTION(info,"no method info"); |
|
37 |
|
38 uint32_t paramCount = info->GetParamCount(); |
|
39 |
|
40 // setup variant array pointer |
|
41 if (paramCount > PARAM_BUFFER_COUNT) { |
|
42 dispatchParams = new nsXPTCMiniVariant[paramCount]; |
|
43 } else { |
|
44 dispatchParams = paramBuffer; |
|
45 } |
|
46 NS_ASSERTION(dispatchParams,"no place for params"); |
|
47 |
|
48 uint64_t* ap = args; |
|
49 uint32_t next_gpr = 1; // skip first arg which is 'self' |
|
50 uint32_t next_fpr = 0; |
|
51 for (uint32_t i = 0; i < paramCount; i++) { |
|
52 const nsXPTParamInfo& param = info->GetParam(i); |
|
53 const nsXPTType& type = param.GetType(); |
|
54 nsXPTCMiniVariant* dp = &dispatchParams[i]; |
|
55 |
|
56 if (param.IsOut() || !type.IsArithmetic()) { |
|
57 if (next_gpr < PARAM_GPR_COUNT) { |
|
58 dp->val.p = (void*)gprData[next_gpr++]; |
|
59 } else { |
|
60 dp->val.p = (void*)*ap++; |
|
61 } |
|
62 continue; |
|
63 } |
|
64 |
|
65 switch (type) { |
|
66 case nsXPTType::T_I8: |
|
67 if (next_gpr < PARAM_GPR_COUNT) { |
|
68 dp->val.i8 = (int8_t)gprData[next_gpr++]; |
|
69 } else { |
|
70 dp->val.i8 = (int8_t)*ap++; |
|
71 } |
|
72 break; |
|
73 |
|
74 case nsXPTType::T_I16: |
|
75 if (next_gpr < PARAM_GPR_COUNT) { |
|
76 dp->val.i16 = (int16_t)gprData[next_gpr++]; |
|
77 } else { |
|
78 dp->val.i16 = (int16_t)*ap++; |
|
79 } |
|
80 break; |
|
81 |
|
82 case nsXPTType::T_I32: |
|
83 if (next_gpr < PARAM_GPR_COUNT) { |
|
84 dp->val.i32 = (int32_t)gprData[next_gpr++]; |
|
85 } else { |
|
86 dp->val.i32 = (int32_t)*ap++; |
|
87 } |
|
88 break; |
|
89 |
|
90 case nsXPTType::T_I64: |
|
91 if (next_gpr < PARAM_GPR_COUNT) { |
|
92 dp->val.i64 = (int64_t)gprData[next_gpr++]; |
|
93 } else { |
|
94 dp->val.i64 = (int64_t)*ap++; |
|
95 } |
|
96 break; |
|
97 |
|
98 case nsXPTType::T_U8: |
|
99 if (next_gpr < PARAM_GPR_COUNT) { |
|
100 dp->val.u8 = (uint8_t)gprData[next_gpr++]; |
|
101 } else { |
|
102 dp->val.u8 = (uint8_t)*ap++; |
|
103 } |
|
104 break; |
|
105 |
|
106 case nsXPTType::T_U16: |
|
107 if (next_gpr < PARAM_GPR_COUNT) { |
|
108 dp->val.u16 = (uint16_t)gprData[next_gpr++]; |
|
109 } else { |
|
110 dp->val.u16 = (uint16_t)*ap++; |
|
111 } |
|
112 break; |
|
113 |
|
114 case nsXPTType::T_U32: |
|
115 if (next_gpr < PARAM_GPR_COUNT) { |
|
116 dp->val.u32 = (uint32_t)gprData[next_gpr++]; |
|
117 } else { |
|
118 dp->val.u32 = (uint32_t)*ap++; |
|
119 } |
|
120 break; |
|
121 |
|
122 case nsXPTType::T_U64: |
|
123 if (next_gpr < PARAM_GPR_COUNT) { |
|
124 dp->val.u64 = (uint64_t)gprData[next_gpr++]; |
|
125 } else { |
|
126 dp->val.u64 = (uint64_t)*ap++; |
|
127 } |
|
128 break; |
|
129 |
|
130 case nsXPTType::T_FLOAT: |
|
131 if (next_fpr < PARAM_FPR_COUNT) { |
|
132 memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f)); |
|
133 } else { |
|
134 memcpy(&dp->val.f, ap++, sizeof(dp->val.f)); |
|
135 } |
|
136 break; |
|
137 |
|
138 case nsXPTType::T_DOUBLE: |
|
139 if (next_fpr < PARAM_FPR_COUNT) { |
|
140 memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d)); |
|
141 } else { |
|
142 memcpy(&dp->val.d, ap++, sizeof(dp->val.d)); |
|
143 } |
|
144 break; |
|
145 |
|
146 case nsXPTType::T_BOOL: |
|
147 if (next_gpr < PARAM_GPR_COUNT) { |
|
148 dp->val.b = (bool)gprData[next_gpr++]; |
|
149 } else { |
|
150 dp->val.b = (bool)*ap++; |
|
151 } |
|
152 break; |
|
153 |
|
154 case nsXPTType::T_CHAR: |
|
155 if (next_gpr < PARAM_GPR_COUNT) { |
|
156 dp->val.c = (char)gprData[next_gpr++]; |
|
157 } else { |
|
158 dp->val.c = (char)*ap++; |
|
159 } |
|
160 break; |
|
161 |
|
162 case nsXPTType::T_WCHAR: |
|
163 if (next_gpr < PARAM_GPR_COUNT) { |
|
164 dp->val.wc = (wchar_t)gprData[next_gpr++]; |
|
165 } else { |
|
166 dp->val.wc = (wchar_t)*ap++; |
|
167 } |
|
168 break; |
|
169 |
|
170 default: |
|
171 NS_ASSERTION(0, "bad type"); |
|
172 break; |
|
173 } |
|
174 } |
|
175 |
|
176 result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); |
|
177 |
|
178 if (dispatchParams != paramBuffer) { |
|
179 delete [] dispatchParams; |
|
180 } |
|
181 |
|
182 return result; |
|
183 } |
|
184 |
|
185 // Load w17 with the constant 'n' and branch to SharedStub(). |
|
186 # define STUB_ENTRY(n) \ |
|
187 __asm__ ( \ |
|
188 ".section \".text\" \n\t" \ |
|
189 ".align 2\n\t" \ |
|
190 ".if "#n" < 10 \n\t" \ |
|
191 ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ |
|
192 ".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ |
|
193 ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ |
|
194 "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ |
|
195 ".elseif "#n" < 100 \n\t" \ |
|
196 ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ |
|
197 ".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ |
|
198 ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ |
|
199 "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ |
|
200 ".elseif "#n" < 1000 \n\t" \ |
|
201 ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ |
|
202 ".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ |
|
203 ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ |
|
204 "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ |
|
205 ".else \n\t" \ |
|
206 ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ |
|
207 ".endif \n\t" \ |
|
208 "mov w17,#"#n" \n\t" \ |
|
209 "b SharedStub \n" \ |
|
210 ); |
|
211 |
|
212 #define SENTINEL_ENTRY(n) \ |
|
213 nsresult nsXPTCStubBase::Sentinel##n() \ |
|
214 { \ |
|
215 NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ |
|
216 return NS_ERROR_NOT_IMPLEMENTED; \ |
|
217 } |
|
218 |
|
219 #include "xptcstubsdef.inc" |