diff options
| author | Peter Wemm <peter@FreeBSD.org> | 2003-12-13 21:35:43 +0000 | 
|---|---|---|
| committer | Peter Wemm <peter@FreeBSD.org> | 2003-12-13 21:35:43 +0000 | 
| commit | 7059589bd64b2a99cab6df938b191d4e9fce56bd (patch) | |
| tree | 5f08e61f528456c64e85212ca62872ad7f7214a6 /www/firefox15/files/patch-xptcall-amd64 | |
| parent | Port to amd64 (note: requires ld-elf.so bugfix to actually work) (diff) | |
Port to amd64 (note: needs ld-elf.so.1 bugfix to actually work)
I've taken a chance and split the sparc64 and alpha mega-diffs up because
sparc64 patched the result of alpha's patches, and amd64 needed to do the
same again - but it was sorted lexically before alpha/sparc64.  I've
grouped the xptcall patches together since they are standalone and split
up and merged the other infrastructure jumbo-patches.
I also attempted to sync up the nspr vs firebird diffs for sparc64 and
alpha because they disagreed.  HOWEVER... While this port 'depends'
on the nspr port, it doesn't actually *use* it.  It should probably
be removed from the LIB_DEPENDS list.
Note that the amd64 xptcall code came from SuSE via the mozilla bugzilla
database.
Notes
Notes:
    svn path=/head/; revision=95748
Diffstat (limited to 'www/firefox15/files/patch-xptcall-amd64')
| -rw-r--r-- | www/firefox15/files/patch-xptcall-amd64 | 386 | 
1 files changed, 386 insertions, 0 deletions
diff --git a/www/firefox15/files/patch-xptcall-amd64 b/www/firefox15/files/patch-xptcall-amd64 new file mode 100644 index 000000000000..3227cad02182 --- /dev/null +++ b/www/firefox15/files/patch-xptcall-amd64 @@ -0,0 +1,386 @@ +--- /dev/null	Wed Dec 31 16:00:00 1969 ++++ xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_freebsd.cpp	Thu Oct 16 22:59:43 2003 +@@ -0,0 +1,174 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++// Platform specific code to invoke XPCOM methods on native objects ++ ++#include "xptcprivate.h" ++ ++// 6 integral parameters are passed in registers ++const PRUint32 GPR_COUNT = 6; ++ ++// 8 floating point parameters are passed in SSE registers ++const PRUint32 FPR_COUNT = 8; ++ ++// Remember that these 'words' are 64-bit long ++static inline void ++invoke_count_words(PRUint32 paramCount, nsXPTCVariant * s, ++                   PRUint32 & nr_gpr, PRUint32 & nr_fpr, PRUint32 & nr_stack) ++{ ++    nr_gpr = 1; // skip one GP register for 'that' ++    nr_fpr = 0; ++    nr_stack = 0; ++ ++    /* Compute number of eightbytes of class MEMORY.  */ ++    for (uint32 i = 0; i < paramCount; i++, s++) { ++        if (!s->IsPtrData() ++            && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) { ++            if (nr_fpr < FPR_COUNT) ++                nr_fpr++; ++            else ++                nr_stack++; ++        } ++        else { ++            if (nr_gpr < GPR_COUNT) ++                nr_gpr++; ++            else ++                nr_stack++; ++        } ++    } ++} ++ ++static void ++invoke_copy_to_stack(PRUint64 * d, PRUint32 paramCount, nsXPTCVariant * s, ++                     PRUint64 * gpregs, double * fpregs) ++{ ++    PRUint32 nr_gpr = 1; // skip one GP register for 'that' ++    PRUint32 nr_fpr = 0; ++    PRUint64 value; ++ ++    for (uint32 i = 0; i < paramCount; i++, s++) { ++        if (s->IsPtrData()) ++            value = (PRUint64) s->ptr; ++        else { ++            switch (s->type) { ++            case nsXPTType::T_FLOAT:                                break; ++            case nsXPTType::T_DOUBLE:                               break; ++            case nsXPTType::T_I8:     value = s->val.i8;            break; ++            case nsXPTType::T_I16:    value = s->val.i16;           break; ++            case nsXPTType::T_I32:    value = s->val.i32;           break; ++            case nsXPTType::T_I64:    value = s->val.i64;           break; ++            case nsXPTType::T_U8:     value = s->val.u8;            break; ++            case nsXPTType::T_U16:    value = s->val.u16;           break; ++            case nsXPTType::T_U32:    value = s->val.u32;           break; ++            case nsXPTType::T_U64:    value = s->val.u64;           break; ++            case nsXPTType::T_BOOL:   value = s->val.b;             break; ++            case nsXPTType::T_CHAR:   value = s->val.c;             break; ++            case nsXPTType::T_WCHAR:  value = s->val.wc;            break; ++            default:                  value = (PRUint64) s->val.p;  break; ++            } ++        } ++ ++        if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { ++            if (nr_fpr < FPR_COUNT) ++                fpregs[nr_fpr++] = s->val.d; ++            else { ++                *((double *)d) = s->val.d; ++                d++; ++            } ++        } ++        else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { ++            if (nr_fpr < FPR_COUNT) ++                // The value in %xmm register is already prepared to ++                // be retrieved as a float. Therefore, we pass the ++                // value verbatim, as a double without conversion. ++                fpregs[nr_fpr++] = s->val.d; ++            else { ++                *((float *)d) = s->val.f; ++                d++; ++            } ++        } ++        else { ++            if (nr_gpr < GPR_COUNT) ++                gpregs[nr_gpr++] = value; ++            else ++                *d++ = value; ++        } ++    } ++} ++ ++extern "C" ++XPTC_PUBLIC_API(nsresult) ++XPTC_InvokeByIndex(nsISupports * that, PRUint32 methodIndex, ++                   PRUint32 paramCount, nsXPTCVariant * params) ++{ ++    PRUint32 nr_gpr, nr_fpr, nr_stack; ++    invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack); ++     ++    // Stack, if used, must be 16-bytes aligned ++    if (nr_stack) ++        nr_stack = (nr_stack + 1) & ~1; ++ ++    // Load parameters to stack, if necessary ++    PRUint64 *stack = (PRUint64 *) __builtin_alloca(nr_stack * 8); ++    PRUint64 gpregs[GPR_COUNT]; ++    double fpregs[FPR_COUNT]; ++    invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs); ++ ++    // Load FPR registers from fpregs[] ++    register double d0 asm("xmm0"); ++    register double d1 asm("xmm1"); ++    register double d2 asm("xmm2"); ++    register double d3 asm("xmm3"); ++    register double d4 asm("xmm4"); ++    register double d5 asm("xmm5"); ++    register double d6 asm("xmm6"); ++    register double d7 asm("xmm7"); ++ ++    switch (nr_fpr) { ++#define ARG_FPR(N) \ ++    case N+1: d##N = fpregs[N]; ++        ARG_FPR(7); ++        ARG_FPR(6); ++        ARG_FPR(5); ++        ARG_FPR(4); ++        ARG_FPR(3); ++        ARG_FPR(2); ++        ARG_FPR(1); ++        ARG_FPR(0); ++    case 0:; ++#undef ARG_FPR ++    } ++     ++    // Load GPR registers from gpregs[] ++    register PRUint64 a0 asm("rdi"); ++    register PRUint64 a1 asm("rsi"); ++    register PRUint64 a2 asm("rdx"); ++    register PRUint64 a3 asm("rcx"); ++    register PRUint64 a4 asm("r8"); ++    register PRUint64 a5 asm("r9"); ++     ++    switch (nr_gpr) { ++#define ARG_GPR(N) \ ++    case N+1: a##N = gpregs[N]; ++        ARG_GPR(5); ++        ARG_GPR(4); ++        ARG_GPR(3); ++        ARG_GPR(2); ++        ARG_GPR(1); ++    case 1: a0 = (PRUint64) that; ++    case 0:; ++#undef ARG_GPR ++    } ++ ++    // Ensure that assignments to SSE registers won't be optimized away ++    asm("" :: ++        "x" (d0), "x" (d1), "x" (d2), "x" (d3), ++        "x" (d4), "x" (d5), "x" (d6), "x" (d7)); ++     ++    // Get pointer to method ++    PRUint64 methodAddress = *((PRUint64 *)that); ++    methodAddress += 8 * methodIndex; ++    methodAddress = *((PRUint64 *)methodAddress); ++     ++    typedef PRUint32 (*Method)(PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, PRUint64); ++    PRUint32 result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5); ++    return result; ++} +--- /dev/null	Wed Dec 31 16:00:00 1969 ++++ xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_freebsd.cpp	Thu Oct 16 23:01:08 2003 +@@ -0,0 +1,206 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++ ++// Implement shared vtbl methods. ++ ++#include "xptcprivate.h" ++ ++// The Linux/x86-64 ABI passes the first 6 integral parameters and the ++// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx, ++// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the ++// caller.  The rest of the parameters are passed in the callers stack ++// area. ++ ++const PRUint32 PARAM_BUFFER_COUNT   = 16; ++const PRUint32 GPR_COUNT            = 6; ++const PRUint32 FPR_COUNT            = 8; ++ ++// PrepareAndDispatch() is called by SharedStub() and calls the actual method. ++// ++// - 'args[]' contains the arguments passed on stack ++// - 'gpregs[]' contains the arguments passed in integer registers ++// - 'fpregs[]' contains the arguments passed in floating point registers ++//  ++// The parameters are mapped into an array of type 'nsXPTCMiniVariant' ++// and then the method gets called. ++ ++extern "C" nsresult ++PrepareAndDispatch(nsXPTCStubBase * self, PRUint32 methodIndex, ++                   PRUint64 * args, PRUint64 * gpregs, double *fpregs) ++{ ++    nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; ++    nsXPTCMiniVariant* dispatchParams = NULL; ++    nsIInterfaceInfo* iface_info = NULL; ++    const nsXPTMethodInfo* info; ++    PRUint32 paramCount; ++    PRUint32 i; ++    nsresult result = NS_ERROR_FAILURE; ++ ++    NS_ASSERTION(self,"no self"); ++ ++    self->GetInterfaceInfo(&iface_info); ++    NS_ASSERTION(iface_info,"no interface info"); ++    if (! iface_info) ++        return NS_ERROR_UNEXPECTED; ++ ++    iface_info->GetMethodInfo(PRUint16(methodIndex), &info); ++    NS_ASSERTION(info,"no method info"); ++    if (! info) ++        return NS_ERROR_UNEXPECTED; ++ ++    paramCount = info->GetParamCount(); ++ ++    // setup variant array pointer ++    if(paramCount > PARAM_BUFFER_COUNT) ++        dispatchParams = new nsXPTCMiniVariant[paramCount]; ++    else ++        dispatchParams = paramBuffer; ++ ++    NS_ASSERTION(dispatchParams,"no place for params"); ++    if (! dispatchParams) ++        return NS_ERROR_OUT_OF_MEMORY; ++ ++    PRUint64* ap = args; ++    PRUint32 nr_gpr = 1;    // skip one GPR register for 'that' ++    PRUint32 nr_fpr = 0; ++    PRUint64 value; ++ ++    for(i = 0; i < paramCount; i++) { ++        const nsXPTParamInfo& param = info->GetParam(i); ++        const nsXPTType& type = param.GetType(); ++        nsXPTCMiniVariant* dp = &dispatchParams[i]; ++	 ++        if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { ++            if (nr_fpr < FPR_COUNT) ++                dp->val.d = fpregs[nr_fpr++]; ++            else ++                dp->val.d = *(double*) ap++; ++            continue; ++        } ++        else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { ++            if (nr_fpr < FPR_COUNT) ++                // The value in %xmm register is already prepared to ++                // be retrieved as a float. Therefore, we pass the ++                // value verbatim, as a double without conversion. ++                dp->val.d = *(double*) ap++; ++            else ++                dp->val.f = *(float*) ap++; ++            continue; ++        } ++        else { ++            if (nr_gpr < GPR_COUNT) ++                value = gpregs[nr_gpr++]; ++            else ++                value = *ap++; ++        } ++ ++        if (param.IsOut() || !type.IsArithmetic()) { ++            dp->val.p = (void*) value; ++            continue; ++        } ++ ++        switch (type) { ++        case nsXPTType::T_I8:      dp->val.i8  = (PRInt8)   value; break; ++        case nsXPTType::T_I16:     dp->val.i16 = (PRInt16)  value; break; ++        case nsXPTType::T_I32:     dp->val.i32 = (PRInt32)  value; break; ++        case nsXPTType::T_I64:     dp->val.i64 = (PRInt64)  value; break; ++        case nsXPTType::T_U8:      dp->val.u8  = (PRUint8)  value; break; ++        case nsXPTType::T_U16:     dp->val.u16 = (PRUint16) value; break; ++        case nsXPTType::T_U32:     dp->val.u32 = (PRUint32) value; break; ++        case nsXPTType::T_U64:     dp->val.u64 = (PRUint64) value; break; ++        case nsXPTType::T_BOOL:    dp->val.b   = (PRBool)   value; break; ++        case nsXPTType::T_CHAR:    dp->val.c   = (char)     value; break; ++        case nsXPTType::T_WCHAR:   dp->val.wc  = (wchar_t)  value; break; ++ ++        default: ++            NS_ASSERTION(0, "bad type"); ++            break; ++        } ++    } ++ ++    result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams); ++ ++    NS_RELEASE(iface_info); ++ ++    if (dispatchParams != paramBuffer) ++        delete [] dispatchParams; ++ ++    return result; ++} ++ ++#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */ ++// Linux/x86-64 uses gcc >= 3.1 ++#define STUB_ENTRY(n) \ ++asm(".section	\".text\"\n\t" \ ++    ".align	2\n\t" \ ++    ".if	" #n " < 10\n\t" \ ++    ".globl	_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ ++    ".type	_ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \ ++    "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \ ++    ".elseif	" #n " < 100\n\t" \ ++    ".globl	_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ ++    ".type	_ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \ ++    "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \ ++    ".elseif    " #n " < 1000\n\t" \ ++    ".globl     _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ ++    ".type      _ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \ ++    "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \ ++    ".else\n\t" \ ++    ".err	\"stub number " #n " >= 1000 not yet supported\"\n\t" \ ++    ".endif\n\t" \ ++    "movl	$" #n ", %eax\n\t" \ ++    "jmp	SharedStub\n\t" \ ++    ".if	" #n " < 10\n\t" \ ++    ".size	_ZN14nsXPTCStubBase5Stub" #n "Ev,.-_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ ++    ".elseif	" #n " < 100\n\t" \ ++    ".size	_ZN14nsXPTCStubBase6Stub" #n "Ev,.-_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ ++    ".else\n\t" \ ++    ".size	_ZN14nsXPTCStubBase7Stub" #n "Ev,.-_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ ++    ".endif"); ++ ++// static nsresult SharedStub(PRUint32 methodIndex) ++asm(".section   \".text\"\n\t" ++    ".align     2\n\t" ++    ".type      SharedStub,@function\n\t" ++    "SharedStub:\n\t" ++    // make room for gpregs (48), fpregs (64) ++    "pushq      %rbp\n\t" ++    "movq       %rsp,%rbp\n\t" ++    "subq       $112,%rsp\n\t" ++    // save GP registers ++    "movq       %rdi,-112(%rbp)\n\t" ++    "movq       %rsi,-104(%rbp)\n\t" ++    "movq       %rdx, -96(%rbp)\n\t" ++    "movq       %rcx, -88(%rbp)\n\t" ++    "movq       %r8 , -80(%rbp)\n\t" ++    "movq       %r9 , -72(%rbp)\n\t" ++    "leaq       -112(%rbp),%rcx\n\t" ++    // save FP registers ++    "movsd      %xmm0,-64(%rbp)\n\t" ++    "movsd      %xmm1,-56(%rbp)\n\t" ++    "movsd      %xmm2,-48(%rbp)\n\t" ++    "movsd      %xmm3,-40(%rbp)\n\t" ++    "movsd      %xmm4,-32(%rbp)\n\t" ++    "movsd      %xmm5,-24(%rbp)\n\t" ++    "movsd      %xmm6,-16(%rbp)\n\t" ++    "movsd      %xmm7, -8(%rbp)\n\t" ++    "leaq       -64(%rbp),%r8\n\t" ++    // rdi has the 'self' pointer already ++    "movl       %eax,%esi\n\t" ++    "leaq       16(%rbp),%rdx\n\t" ++    "call       PrepareAndDispatch\n\t" ++    "leave\n\t" ++    "ret\n\t" ++    ".size      SharedStub,.-SharedStub"); ++ ++#define SENTINEL_ENTRY(n) \ ++nsresult nsXPTCStubBase::Sentinel##n() \ ++{ \ ++    NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ ++    return NS_ERROR_NOT_IMPLEMENTED; \ ++} ++ ++#include "xptcstubsdef.inc" ++ ++#else ++#error "can't find a compiler to use" ++#endif /* __GNUC__ */  | 
