1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /* Implement shared vtbl methods. */
8 
9 #include "xptcprivate.h"
10 
11 static nsresult ATTRIBUTE_USED
PrepareAndDispatch(nsXPTCStubBase * self,uint32_t methodIndex,uint32_t * a_gpr,uint64_t * a_fpr,uint32_t * a_ov)12 PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
13                    uint32_t* a_gpr, uint64_t *a_fpr, uint32_t *a_ov)
14 {
15 #define PARAM_BUFFER_COUNT     16
16 
17     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
18     nsXPTCMiniVariant* dispatchParams = nullptr;
19     const nsXPTMethodInfo* info;
20     uint8_t paramCount;
21     uint8_t i;
22 
23     NS_ASSERTION(self,"no self");
24 
25     self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
26     NS_ASSERTION(info,"no info");
27 
28     paramCount = info->GetParamCount();
29 
30     // setup variant array pointer
31     if(paramCount > PARAM_BUFFER_COUNT)
32         dispatchParams = new nsXPTCMiniVariant[paramCount];
33     else
34         dispatchParams = paramBuffer;
35     NS_ASSERTION(dispatchParams,"no place for params");
36 
37     const uint8_t indexOfJSContext = info->IndexOfJSContext();
38 
39     uint32_t gpr = 1, fpr = 0;
40 
41     for(i = 0; i < paramCount; i++)
42     {
43         const nsXPTParamInfo& param = info->GetParam(i);
44         const nsXPTType& type = param.GetType();
45         nsXPTCMiniVariant* dp = &dispatchParams[i];
46 
47         if (i == indexOfJSContext) {
48             if (gpr < 5)
49                 a_gpr++, gpr++;
50             else
51                 a_ov++;
52         }
53 
54         if(param.IsOut() || !type.IsArithmetic())
55         {
56             if (gpr < 5)
57                 dp->val.p = (void*) *a_gpr++, gpr++;
58             else
59                 dp->val.p = (void*) *a_ov++;
60             continue;
61         }
62         // else
63         switch(type)
64         {
65         case nsXPTType::T_I8     :
66             if (gpr < 5)
67                 dp->val.i8  = *((int32_t*) a_gpr), a_gpr++, gpr++;
68             else
69                 dp->val.i8  = *((int32_t*) a_ov ), a_ov++;
70             break;
71         case nsXPTType::T_I16    :
72             if (gpr < 5)
73                 dp->val.i16 = *((int32_t*) a_gpr), a_gpr++, gpr++;
74             else
75                 dp->val.i16 = *((int32_t*) a_ov ), a_ov++;
76             break;
77         case nsXPTType::T_I32    :
78             if (gpr < 5)
79                 dp->val.i32 = *((int32_t*) a_gpr), a_gpr++, gpr++;
80             else
81                 dp->val.i32 = *((int32_t*) a_ov ), a_ov++;
82             break;
83         case nsXPTType::T_I64    :
84             if (gpr < 4)
85                 dp->val.i64 = *((int64_t*) a_gpr), a_gpr+=2, gpr+=2;
86             else
87                 dp->val.i64 = *((int64_t*) a_ov ), a_ov+=2, gpr=5;
88             break;
89         case nsXPTType::T_U8     :
90             if (gpr < 5)
91                 dp->val.u8  = *((uint32_t*)a_gpr), a_gpr++, gpr++;
92             else
93                 dp->val.u8  = *((uint32_t*)a_ov ), a_ov++;
94             break;
95         case nsXPTType::T_U16    :
96             if (gpr < 5)
97                 dp->val.u16 = *((uint32_t*)a_gpr), a_gpr++, gpr++;
98             else
99                 dp->val.u16 = *((uint32_t*)a_ov ), a_ov++;
100             break;
101         case nsXPTType::T_U32    :
102             if (gpr < 5)
103                 dp->val.u32 = *((uint32_t*)a_gpr), a_gpr++, gpr++;
104             else
105                 dp->val.u32 = *((uint32_t*)a_ov ), a_ov++;
106             break;
107         case nsXPTType::T_U64    :
108             if (gpr < 4)
109                 dp->val.u64 = *((uint64_t*)a_gpr), a_gpr+=2, gpr+=2;
110             else
111                 dp->val.u64 = *((uint64_t*)a_ov ), a_ov+=2, gpr=5;
112             break;
113         case nsXPTType::T_FLOAT  :
114             if (fpr < 2)
115                 dp->val.f   = *((float*)   a_fpr), a_fpr++, fpr++;
116             else
117                 dp->val.f   = *((float*)   a_ov ), a_ov++;
118             break;
119         case nsXPTType::T_DOUBLE :
120             if (fpr < 2)
121                 dp->val.d   = *((double*)  a_fpr), a_fpr++, fpr++;
122             else
123                 dp->val.d   = *((double*)  a_ov ), a_ov+=2;
124             break;
125         case nsXPTType::T_BOOL   :
126             if (gpr < 5)
127                 dp->val.b   = *((uint32_t*)a_gpr), a_gpr++, gpr++;
128             else
129                 dp->val.b   = *((uint32_t*)a_ov ), a_ov++;
130             break;
131         case nsXPTType::T_CHAR   :
132             if (gpr < 5)
133                 dp->val.c   = *((uint32_t*)a_gpr), a_gpr++, gpr++;
134             else
135                 dp->val.c   = *((uint32_t*)a_ov ), a_ov++;
136             break;
137         case nsXPTType::T_WCHAR  :
138             if (gpr < 5)
139                 dp->val.wc  = *((uint32_t*)a_gpr), a_gpr++, gpr++;
140             else
141                 dp->val.wc  = *((uint32_t*)a_ov ), a_ov++;
142             break;
143         default:
144             NS_ERROR("bad type");
145             break;
146         }
147     }
148 
149     nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
150                                                dispatchParams);
151 
152     if(dispatchParams != paramBuffer)
153         delete [] dispatchParams;
154 
155     return result;
156 }
157 
158 #define STUB_ENTRY(n) \
159 nsresult nsXPTCStubBase::Stub##n() \
160 {                             \
161     uint32_t a_gpr[4];        \
162     uint64_t a_fpr[2];        \
163     uint32_t *a_ov;           \
164                               \
165     __asm__ __volatile__      \
166     (                         \
167         "l     %0,0(15)\n\t"  \
168         "ahi   %0,96\n\t"     \
169         "stm   3,6,0(%3)\n\t" \
170         "std   0,%1\n\t"      \
171         "std   2,%2\n\t"      \
172         : "=&a" (a_ov),       \
173           "=m" (a_fpr[0]),    \
174           "=m" (a_fpr[1])     \
175         : "a" (a_gpr)         \
176        : "memory", "cc",      \
177          "3", "4", "5", "6"   \
178     );                        \
179                               \
180     return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
181 }
182 
183 #define SENTINEL_ENTRY(n) \
184 nsresult nsXPTCStubBase::Sentinel##n() \
185 { \
186     NS_ERROR("nsXPTCStubBase::Sentinel called"); \
187     return NS_ERROR_NOT_IMPLEMENTED; \
188 }
189 
190 #include "xptcstubsdef.inc"
191