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 
10 /*
11  * This is for AArch64 ABI
12  *
13  * When we're called, the "gp" registers are stored in gprData and
14  * the "fp" registers are stored in fprData. Each array has 8 regs
15  * but first reg in gprData is a placeholder for 'self'.
16  */
17 extern "C" nsresult
PrepareAndDispatch(nsXPTCStubBase * self,uint32_t methodIndex,uint64_t * args,uint64_t * gprData,double * fprData)18 PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
19                    uint64_t *gprData, double *fprData)
20 {
21 #define PARAM_GPR_COUNT            8
22 #define PARAM_FPR_COUNT            8
23 
24     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
25     const nsXPTMethodInfo* info;
26 
27     NS_ASSERTION(self,"no self");
28 
29     self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
30     NS_ASSERTION(info,"no method info");
31 
32     uint32_t paramCount = info->GetParamCount();
33 
34     const uint8_t indexOfJSContext = info->IndexOfJSContext();
35 
36     uint64_t* ap = args;
37     uint32_t next_gpr = 1; // skip first arg which is 'self'
38     uint32_t next_fpr = 0;
39     for (uint32_t i = 0; i < paramCount; i++) {
40         const nsXPTParamInfo& param = info->GetParam(i);
41         const nsXPTType& type = param.GetType();
42         nsXPTCMiniVariant* dp = &paramBuffer[i];
43 
44         if (i == indexOfJSContext) {
45             if (next_gpr < PARAM_GPR_COUNT)
46                 next_gpr++;
47             else
48                 ap++;
49         }
50 
51         if (param.IsOut() || !type.IsArithmetic()) {
52             if (next_gpr < PARAM_GPR_COUNT) {
53                 dp->val.p = (void*)gprData[next_gpr++];
54             } else {
55                 dp->val.p = (void*)*ap++;
56             }
57             continue;
58         }
59 
60         switch (type) {
61             case nsXPTType::T_I8:
62                 if (next_gpr < PARAM_GPR_COUNT) {
63                     dp->val.i8  = (int8_t)gprData[next_gpr++];
64                 } else {
65                     dp->val.i8  = (int8_t)*ap++;
66                 }
67                 break;
68 
69             case nsXPTType::T_I16:
70                 if (next_gpr < PARAM_GPR_COUNT) {
71                     dp->val.i16  = (int16_t)gprData[next_gpr++];
72                 } else {
73                     dp->val.i16  = (int16_t)*ap++;
74                 }
75                 break;
76 
77             case nsXPTType::T_I32:
78                 if (next_gpr < PARAM_GPR_COUNT) {
79                     dp->val.i32  = (int32_t)gprData[next_gpr++];
80                 } else {
81                     dp->val.i32  = (int32_t)*ap++;
82                 }
83                 break;
84 
85             case nsXPTType::T_I64:
86                 if (next_gpr < PARAM_GPR_COUNT) {
87                     dp->val.i64  = (int64_t)gprData[next_gpr++];
88                 } else {
89                     dp->val.i64  = (int64_t)*ap++;
90                 }
91                 break;
92 
93             case nsXPTType::T_U8:
94                 if (next_gpr < PARAM_GPR_COUNT) {
95                     dp->val.u8  = (uint8_t)gprData[next_gpr++];
96                 } else {
97                     dp->val.u8  = (uint8_t)*ap++;
98                 }
99                 break;
100 
101             case nsXPTType::T_U16:
102                 if (next_gpr < PARAM_GPR_COUNT) {
103                     dp->val.u16  = (uint16_t)gprData[next_gpr++];
104                 } else {
105                     dp->val.u16  = (uint16_t)*ap++;
106                 }
107                 break;
108 
109             case nsXPTType::T_U32:
110                 if (next_gpr < PARAM_GPR_COUNT) {
111                     dp->val.u32  = (uint32_t)gprData[next_gpr++];
112                 } else {
113                     dp->val.u32  = (uint32_t)*ap++;
114                 }
115                 break;
116 
117             case nsXPTType::T_U64:
118                 if (next_gpr < PARAM_GPR_COUNT) {
119                     dp->val.u64  = (uint64_t)gprData[next_gpr++];
120                 } else {
121                     dp->val.u64  = (uint64_t)*ap++;
122                 }
123                 break;
124 
125             case nsXPTType::T_FLOAT:
126                 if (next_fpr < PARAM_FPR_COUNT) {
127                     memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f));
128                 } else {
129                     memcpy(&dp->val.f, ap++, sizeof(dp->val.f));
130                 }
131                 break;
132 
133             case nsXPTType::T_DOUBLE:
134                 if (next_fpr < PARAM_FPR_COUNT) {
135                     memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d));
136                 } else {
137                     memcpy(&dp->val.d, ap++, sizeof(dp->val.d));
138                 }
139                 break;
140 
141             case nsXPTType::T_BOOL:
142                 if (next_gpr < PARAM_GPR_COUNT) {
143                     dp->val.b  = (bool)(uint8_t)gprData[next_gpr++];
144                 } else {
145                     dp->val.b  = (bool)(uint8_t)*ap++;
146                 }
147                 break;
148 
149             case nsXPTType::T_CHAR:
150                 if (next_gpr < PARAM_GPR_COUNT) {
151                     dp->val.c  = (char)gprData[next_gpr++];
152                 } else {
153                     dp->val.c  = (char)*ap++;
154                 }
155                 break;
156 
157             case nsXPTType::T_WCHAR:
158                 if (next_gpr < PARAM_GPR_COUNT) {
159                     dp->val.wc  = (wchar_t)gprData[next_gpr++];
160                 } else {
161                     dp->val.wc  = (wchar_t)*ap++;
162                 }
163                 break;
164 
165             default:
166                 NS_ASSERTION(0, "bad type");
167                 break;
168         }
169     }
170 
171     nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
172                                                paramBuffer);
173 
174     return result;
175 }
176 
177 #define STUB_ENTRY(n)  /* defined in the assembly file */
178 
179 #define SENTINEL_ENTRY(n) \
180 nsresult nsXPTCStubBase::Sentinel##n() \
181 { \
182     NS_ERROR("nsXPTCStubBase::Sentinel called"); \
183     return NS_ERROR_NOT_IMPLEMENTED; \
184 }
185 
186 #include "xptcstubsdef.inc"
187