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 // Platform specific code to invoke XPCOM methods on native objects
7 
8 // The purpose of NS_InvokeByIndex() is to map a platform
9 // indepenpent call to the platform ABI. To do that,
10 // NS_InvokeByIndex() has to determine the method to call via vtable
11 // access. The parameters for the method are read from the
12 // nsXPTCVariant* and prepared for th native ABI.  For the Linux/PPC
13 // ABI this means that the first 8 integral and floating point
14 // parameters are passed in registers.
15 
16 #include "xptcprivate.h"
17 
18 // 8 integral parameters are passed in registers
19 #define GPR_COUNT     8
20 
21 // 8 floating point parameters are passed in registers, floats are
22 // promoted to doubles when passed in registers
23 #define FPR_COUNT     8
24 
25 extern "C" uint32_t
invoke_count_words(uint32_t paramCount,nsXPTCVariant * s)26 invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
27 {
28   return uint32_t(((paramCount * 2) + 3) & ~3);
29 }
30 
31 extern "C" void
invoke_copy_to_stack(uint32_t * d,uint32_t paramCount,nsXPTCVariant * s,uint32_t * gpregs,double * fpregs)32 invoke_copy_to_stack(uint32_t* d,
33                      uint32_t paramCount,
34                      nsXPTCVariant* s,
35                      uint32_t* gpregs,
36                      double* fpregs)
37 {
38     uint32_t gpr = 1; // skip one GP reg for 'that'
39     uint32_t fpr = 0;
40     uint32_t tempu32;
41     uint64_t tempu64;
42 
43     for(uint32_t i = 0; i < paramCount; i++, s++) {
44         if(s->IsPtrData()) {
45             if(s->type == nsXPTType::T_JSVAL)
46                tempu32 = (uint32_t) &(s->ptr);
47             else
48                tempu32 = (uint32_t) s->ptr;
49         } else {
50             switch(s->type) {
51             case nsXPTType::T_FLOAT:                                  break;
52             case nsXPTType::T_DOUBLE:                                 break;
53             case nsXPTType::T_I8:     tempu32 = s->val.i8;            break;
54             case nsXPTType::T_I16:    tempu32 = s->val.i16;           break;
55             case nsXPTType::T_I32:    tempu32 = s->val.i32;           break;
56             case nsXPTType::T_I64:    tempu64 = s->val.i64;           break;
57             case nsXPTType::T_U8:     tempu32 = s->val.u8;            break;
58             case nsXPTType::T_U16:    tempu32 = s->val.u16;           break;
59             case nsXPTType::T_U32:    tempu32 = s->val.u32;           break;
60             case nsXPTType::T_U64:    tempu64 = s->val.u64;           break;
61             case nsXPTType::T_BOOL:   tempu32 = s->val.b;             break;
62             case nsXPTType::T_CHAR:   tempu32 = s->val.c;             break;
63             case nsXPTType::T_WCHAR:  tempu32 = s->val.wc;            break;
64             default:                  tempu32 = (uint32_t) s->val.p;  break;
65             }
66         }
67 
68         if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
69             if (fpr < FPR_COUNT)
70                 fpregs[fpr++]    = s->val.d;
71             else {
72                 if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack
73                 *((double*) d) = s->val.d;
74                 d += 2;
75             }
76         }
77         else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
78             if (fpr < FPR_COUNT)
79                 fpregs[fpr++]   = s->val.f; // if passed in registers, floats are promoted to doubles
80             else
81                 *((float*) d++) = s->val.f;
82         }
83         else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
84                                      || s->type == nsXPTType::T_U64)) {
85             if ((gpr + 1) < GPR_COUNT) {
86                 if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
87                 *((uint64_t*) &gpregs[gpr]) = tempu64;
88                 gpr += 2;
89             }
90             else {
91                 if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack
92                 *((uint64_t*) d)            = tempu64;
93                 d += 2;
94             }
95         }
96         else {
97             if (gpr < GPR_COUNT)
98                 gpregs[gpr++] = tempu32;
99             else
100                 *d++          = tempu32;
101         }
102 
103     }
104 }
105 
106 extern "C"
107 EXPORT_XPCOM_API(nsresult)
108 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
109                  uint32_t paramCount, nsXPTCVariant* params);
110