michael@0: /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Platform specific code to invoke XPCOM methods on native objects michael@0: michael@0: // The purpose of NS_InvokeByIndex() is to map a platform michael@0: // indepenpent call to the platform ABI. To do that, michael@0: // NS_InvokeByIndex() has to determine the method to call via vtable michael@0: // access. The parameters for the method are read from the michael@0: // nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC michael@0: // ABI this means that the first 8 integral and floating point michael@0: // parameters are passed in registers. michael@0: michael@0: #include "xptcprivate.h" michael@0: michael@0: // 8 integral parameters are passed in registers michael@0: #define GPR_COUNT 8 michael@0: michael@0: // With hardfloat support 8 floating point parameters are passed in registers, michael@0: // floats are promoted to doubles when passed in registers michael@0: // In Softfloat mode, everything is handled via gprs michael@0: #ifndef __NO_FPRS__ michael@0: #define FPR_COUNT 8 michael@0: #endif michael@0: extern "C" uint32_t michael@0: invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) michael@0: { michael@0: return uint32_t(((paramCount * 2) + 3) & ~3); michael@0: } michael@0: michael@0: extern "C" void michael@0: invoke_copy_to_stack(uint32_t* d, michael@0: uint32_t paramCount, michael@0: nsXPTCVariant* s, michael@0: uint32_t* gpregs, michael@0: double* fpregs) michael@0: { michael@0: uint32_t gpr = 1; // skip one GP reg for 'that' michael@0: #ifndef __NO_FPRS__ michael@0: uint32_t fpr = 0; michael@0: #endif michael@0: uint32_t tempu32; michael@0: uint64_t tempu64; michael@0: michael@0: for(uint32_t i = 0; i < paramCount; i++, s++) { michael@0: if(s->IsPtrData()) { michael@0: if(s->type == nsXPTType::T_JSVAL) michael@0: tempu32 = (uint32_t) &s->ptr; michael@0: else michael@0: tempu32 = (uint32_t) s->ptr; michael@0: } michael@0: else { michael@0: switch(s->type) { michael@0: case nsXPTType::T_FLOAT: break; michael@0: case nsXPTType::T_DOUBLE: break; michael@0: case nsXPTType::T_I8: tempu32 = s->val.i8; break; michael@0: case nsXPTType::T_I16: tempu32 = s->val.i16; break; michael@0: case nsXPTType::T_I32: tempu32 = s->val.i32; break; michael@0: case nsXPTType::T_I64: tempu64 = s->val.i64; break; michael@0: case nsXPTType::T_U8: tempu32 = s->val.u8; break; michael@0: case nsXPTType::T_U16: tempu32 = s->val.u16; break; michael@0: case nsXPTType::T_U32: tempu32 = s->val.u32; break; michael@0: case nsXPTType::T_U64: tempu64 = s->val.u64; break; michael@0: case nsXPTType::T_BOOL: tempu32 = s->val.b; break; michael@0: case nsXPTType::T_CHAR: tempu32 = s->val.c; break; michael@0: case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break; michael@0: default: tempu32 = (uint32_t) s->val.p; break; michael@0: } michael@0: } michael@0: michael@0: if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { michael@0: #ifndef __NO_FPRS__ michael@0: if (fpr < FPR_COUNT) michael@0: fpregs[fpr++] = s->val.d; michael@0: #else michael@0: if (gpr & 1) michael@0: gpr++; michael@0: if ((gpr + 1) < GPR_COUNT) { michael@0: *((double*) &gpregs[gpr]) = s->val.d; michael@0: gpr += 2; michael@0: } michael@0: #endif michael@0: else { michael@0: if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack michael@0: *((double*) d) = s->val.d; michael@0: d += 2; michael@0: } michael@0: } michael@0: else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { michael@0: #ifndef __NO_FPRS__ michael@0: if (fpr < FPR_COUNT) michael@0: fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles michael@0: #else michael@0: if (gpr < GPR_COUNT) michael@0: *((float*) &gpregs[gpr++]) = s->val.f; michael@0: #endif michael@0: else michael@0: *((float*) d++) = s->val.f; michael@0: } michael@0: else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64 michael@0: || s->type == nsXPTType::T_U64)) { michael@0: if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 michael@0: if ((gpr + 1) < GPR_COUNT) { michael@0: *((uint64_t*) &gpregs[gpr]) = tempu64; michael@0: gpr += 2; michael@0: } michael@0: else { michael@0: if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack michael@0: *((uint64_t*) d) = tempu64; michael@0: d += 2; michael@0: } michael@0: } michael@0: else { michael@0: if (gpr < GPR_COUNT) michael@0: gpregs[gpr++] = tempu32; michael@0: else michael@0: *d++ = tempu32; michael@0: } michael@0: michael@0: } michael@0: } michael@0: michael@0: extern "C" michael@0: EXPORT_XPCOM_API(nsresult) michael@0: NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, michael@0: uint32_t paramCount, nsXPTCVariant* params);