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
PrepareAndDispatch(nsXPTCStubBase * self,uint32_t methodIndex,uint64_t * args,uint64_t * gprData,double * fprData)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"
220