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