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: // independent 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 the native ABI. michael@0: michael@0: // The PowerPC64 platform ABI can be found here: michael@0: // http://www.freestandards.org/spec/ELF/ppc64/ michael@0: // and in particular: michael@0: // http://www.freestandards.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-CALL michael@0: michael@0: #include michael@0: #include "xptcprivate.h" michael@0: michael@0: // 8 integral parameters are passed in registers, not including 'that' michael@0: #define GPR_COUNT 7 michael@0: michael@0: // 8 floating point parameters are passed in registers, floats are michael@0: // promoted to doubles when passed in registers michael@0: #define FPR_COUNT 13 michael@0: 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(uint64_t* gpregs, michael@0: double* fpregs, michael@0: uint32_t paramCount, michael@0: nsXPTCVariant* s, michael@0: uint64_t* d) michael@0: { 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: tempu64 = (uint64_t) s->ptr; 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: tempu64 = s->val.i8; break; michael@0: case nsXPTType::T_I16: tempu64 = s->val.i16; break; michael@0: case nsXPTType::T_I32: tempu64 = s->val.i32; break; michael@0: case nsXPTType::T_I64: tempu64 = s->val.i64; break; michael@0: case nsXPTType::T_U8: tempu64 = s->val.u8; break; michael@0: case nsXPTType::T_U16: tempu64 = s->val.u16; break; michael@0: case nsXPTType::T_U32: tempu64 = s->val.u32; break; michael@0: case nsXPTType::T_U64: tempu64 = s->val.u64; break; michael@0: case nsXPTType::T_BOOL: tempu64 = s->val.b; break; michael@0: case nsXPTType::T_CHAR: tempu64 = s->val.c; break; michael@0: case nsXPTType::T_WCHAR: tempu64 = s->val.wc; break; michael@0: default: tempu64 = (uint64_t) s->val.p; break; michael@0: } michael@0: } michael@0: michael@0: if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { michael@0: if (i < FPR_COUNT) michael@0: fpregs[i] = s->val.d; michael@0: else michael@0: *(double *)d = s->val.d; michael@0: } michael@0: else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { michael@0: if (i < FPR_COUNT) { michael@0: fpregs[i] = s->val.f; // if passed in registers, floats are promoted to doubles michael@0: } else { michael@0: float *p = (float *)d; michael@0: #ifndef __LITTLE_ENDIAN__ michael@0: p++; michael@0: #endif michael@0: *p = s->val.f; michael@0: } michael@0: } michael@0: else { michael@0: if (i < GPR_COUNT) michael@0: gpregs[i] = tempu64; michael@0: else michael@0: *d = tempu64; michael@0: } michael@0: if (i >= 7) michael@0: d++; michael@0: } michael@0: } michael@0: michael@0: EXPORT_XPCOM_API(nsresult) michael@0: NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, michael@0: uint32_t paramCount, nsXPTCVariant* params); michael@0: