Bug 482759 - xulrunner mips n32 ABI patch. r=timeless

This commit is contained in:
Zhang Le 2010-02-27 18:46:00 +01:00
parent fa7fb4a591
commit 0d538d7036
5 changed files with 704 additions and 0 deletions

View File

@ -315,8 +315,13 @@ endif
ifeq ($(OS_ARCH),Linux)
ifneq (,$(findstring mips, $(OS_TEST)))
ifneq (,$(findstring mips64, $(OS_TEST)))
CPPSRCS := xptcinvoke_mips64.cpp xptcstubs_mips64.cpp
ASFILES := xptcinvoke_asm_mips64.s xptcstubs_asm_mips64.s
else
CPPSRCS := xptcinvoke_mips.cpp xptcstubs_mips.cpp
ASFILES := xptcinvoke_asm_mips.s xptcstubs_asm_mips.s
endif
ASFLAGS += -I$(DIST)/include -x assembler-with-cpp
endif
endif

View File

@ -0,0 +1,159 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* ZHANG Le <r0bertz@gentoo.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <sys/regdef.h>
#include <sys/asm.h>
.text
.globl invoke_count_words
.globl invoke_copy_to_stack
LOCALSZ=7 # a0, a1, a2, a3, s0, ra, gp
FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
RAOFF=FRAMESZ-(1*SZREG)
A0OFF=FRAMESZ-(2*SZREG)
A1OFF=FRAMESZ-(3*SZREG)
A2OFF=FRAMESZ-(4*SZREG)
A3OFF=FRAMESZ-(5*SZREG)
S0OFF=FRAMESZ-(6*SZREG)
GPOFF=FRAMESZ-(7*SZREG)
#
# _NS_InvokeByIndex_P(that, methodIndex, paramCount, params)
# a0 a1 a2 a3
NESTED(_NS_InvokeByIndex_P, FRAMESZ, ra)
PTR_SUBU sp, FRAMESZ
SETUP_GP64(GPOFF, _NS_InvokeByIndex_P)
REG_S ra, RAOFF(sp)
REG_S a0, A0OFF(sp)
REG_S a1, A1OFF(sp)
REG_S a2, A2OFF(sp)
REG_S a3, A3OFF(sp)
REG_S s0, S0OFF(sp)
# invoke_count_words(paramCount, params)
move a0, a2
move a1, a3
jal invoke_count_words
# invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
# nsXPTCVariant* s, PRUint32 *reg)
REG_L a1, A2OFF(sp) # a1 - paramCount
REG_L a2, A3OFF(sp) # a2 - params
# save sp before we copy the params to the stack
move t0, sp
# assume full size of 16 bytes per param to be safe
sll v0, 4 # 16 bytes * num params
subu sp, sp, v0 # make room
move a0, sp # a0 - param stack address
# create temporary stack space to write int and fp regs
subu sp, 64 # 64 = 8 regs of 8 bytes
move a3, sp
# save the old sp and save the arg stack
subu sp, sp, 16
REG_S t0, 0(sp)
REG_S a0, 8(sp)
# copy the param into the stack areas
jal invoke_copy_to_stack
REG_L t3, 8(sp) # get previous a0
REG_L sp, 0(sp) # get orig sp back
REG_L a0, A0OFF(sp) # a0 - that
REG_L a1, A1OFF(sp) # a1 - methodIndex
# t1 = methodIndex * pow(2, PTRLOG)
# (use shift instead of mult)
sll t1, a1, PTRLOG
# calculate the function we need to jump to,
# which must then be saved in t9
lw t9, 0(a0)
addu t9, t9, t1
#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
lw t9, (t9)
#else /* not G++ V3 ABI */
lw t9, 2*PTRSIZE(t9)
#endif /* G++ V3 ABI */
# get register save area from invoke_copy_to_stack
subu t1, t3, 64
# a1..a7 and f13..f19 should now be set to what
# invoke_copy_to_stack told us. skip a0 and f12
# because that's the "this" pointer
REG_L a1, 0(t1)
REG_L a2, 8(t1)
REG_L a3, 16(t1)
REG_L a4, 24(t1)
REG_L a5, 32(t1)
REG_L a6, 40(t1)
REG_L a7, 48(t1)
l.d $f13, 0(t1)
l.d $f14, 8(t1)
l.d $f15, 16(t1)
l.d $f16, 24(t1)
l.d $f17, 32(t1)
l.d $f18, 40(t1)
l.d $f19, 48(t1)
# save away our stack pointer and create
# the stack pointer for the function
move s0, sp
move sp, t3
jalr t9
move sp, s0
RESTORE_GP64
REG_L ra, RAOFF(sp)
REG_L s0, S0OFF(sp)
PTR_ADDU sp, FRAMESZ
j ra
.end _NS_InvokeByIndex_P

View File

@ -0,0 +1,173 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* ZHANG Le <r0bertz@gentoo.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Platform specific code to invoke XPCOM methods on native objects */
#include "xptcprivate.h"
#if (_MIPS_SIM != _ABIN32)
#error "This code is for MIPS N32 only"
#endif
extern "C" uint32
invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
{
return paramCount;
}
extern "C" void
invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount,
nsXPTCVariant* s, PRUint64 *regs)
{
#define N_ARG_REGS 7 /* 8 regs minus 1 for "this" ptr */
for (PRUint32 i = 0; i < paramCount; i++, s++)
{
if (s->IsPtrData()) {
if (i < N_ARG_REGS)
regs[i] = (PRUint64)s->ptr;
else
*d++ = (PRUint64)s->ptr;
continue;
}
switch (s->type) {
//
// signed types first
//
case nsXPTType::T_I8:
if (i < N_ARG_REGS)
((PRInt64*)regs)[i] = s->val.i8;
else
*d++ = s->val.i8;
break;
case nsXPTType::T_I16:
if (i < N_ARG_REGS)
((PRInt64*)regs)[i] = s->val.i16;
else
*d++ = s->val.i16;
break;
case nsXPTType::T_I32:
if (i < N_ARG_REGS)
((PRInt64*)regs)[i] = s->val.i32;
else
*d++ = s->val.i32;
break;
case nsXPTType::T_I64:
if (i < N_ARG_REGS)
((PRInt64*)regs)[i] = s->val.i64;
else
*d++ = s->val.i64;
break;
//
// unsigned types next
//
case nsXPTType::T_U8:
if (i < N_ARG_REGS)
regs[i] = s->val.u8;
else
*d++ = s->val.u8;
break;
case nsXPTType::T_U16:
if (i < N_ARG_REGS)
regs[i] = s->val.u16;
else
*d++ = s->val.u16;
break;
case nsXPTType::T_U32:
if (i < N_ARG_REGS)
regs[i] = s->val.u32;
else
*d++ = s->val.u32;
break;
case nsXPTType::T_U64:
if (i < N_ARG_REGS)
regs[i] = s->val.u64;
else
*d++ = s->val.u64;
break;
case nsXPTType::T_FLOAT:
if (i < N_ARG_REGS)
*(float*)&regs[i] = s->val.f;
else
*(float*)d++ = s->val.f;
break;
case nsXPTType::T_DOUBLE:
if (i < N_ARG_REGS)
*(double*)&regs[i] = s->val.d;
else
*(double*)d++ = s->val.d;
break;
case nsXPTType::T_BOOL:
if (i < N_ARG_REGS)
regs[i] = s->val.b;
else
*d++ = s->val.b;
break;
case nsXPTType::T_CHAR:
if (i < N_ARG_REGS)
regs[i] = s->val.c;
else
*d++ = s->val.c;
break;
case nsXPTType::T_WCHAR:
if (i < N_ARG_REGS)
regs[i] = s->val.wc;
else
*d++ = s->val.wc;
break;
default:
// all the others are plain pointer types
if (i < N_ARG_REGS)
regs[i] = (PRUint64)s->val.p;
else
*d++ = (PRUint64)s->val.p;
break;
}
}
}
extern "C" nsresult _NS_InvokeByIndex_P(nsISupports* that, PRUint32 methodIndex,
PRUint32 paramCount,
nsXPTCVariant* params);
EXPORT_XPCOM_API(nsresult)
NS_InvokeByIndex_P(nsISupports* that, PRUint32 methodIndex,
PRUint32 paramCount, nsXPTCVariant* params)
{
return _NS_InvokeByIndex_P(that, methodIndex, paramCount, params);
}

View File

@ -0,0 +1,149 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* ZHANG Le <r0bertz@gentoo.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <sys/regdef.h>
#include <sys/asm.h>
LOCALSZ=16
FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
A1OFF=FRAMESZ-(9*SZREG)
A2OFF=FRAMESZ-(8*SZREG)
A3OFF=FRAMESZ-(7*SZREG)
A4OFF=FRAMESZ-(6*SZREG)
A5OFF=FRAMESZ-(5*SZREG)
A6OFF=FRAMESZ-(4*SZREG)
A7OFF=FRAMESZ-(3*SZREG)
GPOFF=FRAMESZ-(2*SZREG)
RAOFF=FRAMESZ-(1*SZREG)
F13OFF=FRAMESZ-(16*SZREG)
F14OFF=FRAMESZ-(15*SZREG)
F15OFF=FRAMESZ-(14*SZREG)
F16OFF=FRAMESZ-(13*SZREG)
F17OFF=FRAMESZ-(12*SZREG)
F18OFF=FRAMESZ-(11*SZREG)
F19OFF=FRAMESZ-(10*SZREG)
#define SENTINEL_ENTRY(n) /* defined in cpp file, not here */
#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
#define STUB_ENTRY(x) \
.if x < 10; \
MAKE_STUB(x, _ZN14nsXPTCStubBase5Stub ##x ##Ev); \
.elseif x < 100; \
MAKE_STUB(x, _ZN14nsXPTCStubBase6Stub ##x ##Ev); \
.elseif x < 1000; \
MAKE_STUB(x, _ZN14nsXPTCStubBase7Stub ##x ##Ev); \
.else; \
.err; \
.endif
#else /* not G++ V3 ABI */
#define STUB_ENTRY(x) \
MAKE_STUB(x, Stub ##x ##__14nsXPTCStubBase)
#endif /* G++ V3 ABI */
#define MAKE_STUB(x, name) \
.globl name; \
.type name,@function; \
.aent name,0; \
name:; \
PTR_SUBU sp,FRAMESZ; \
SETUP_GP64(GPOFF, name); \
li t0,x; \
b sharedstub; \
#
# open a dummy frame for the function entries
#
.text
.align 2
.type dummy,@function
.ent dummy, 0
dummy:
.frame sp, FRAMESZ, ra
.mask 0x90000FF0, RAOFF-FRAMESZ
.fmask 0x000FF000, F19OFF-FRAMESZ
#include "xptcstubsdef.inc"
sharedstub:
REG_S a1, A1OFF(sp)
REG_S a2, A2OFF(sp)
REG_S a3, A3OFF(sp)
REG_S a4, A4OFF(sp)
REG_S a5, A5OFF(sp)
REG_S a6, A6OFF(sp)
REG_S a7, A7OFF(sp)
REG_S ra, RAOFF(sp)
s.d $f13, F13OFF(sp)
s.d $f14, F14OFF(sp)
s.d $f15, F15OFF(sp)
s.d $f16, F16OFF(sp)
s.d $f17, F17OFF(sp)
s.d $f18, F18OFF(sp)
s.d $f19, F19OFF(sp)
# t0 is methodIndex
move a1, t0
# a2 is stack address where extra function params
# are stored that do not fit in registers
move a2, sp
addi a2, FRAMESZ
# a3 is stack address of a1..a7
move a3, sp
addi a3, A1OFF
# a4 is stack address of f13..f19
move a4, sp
addi a4, F13OFF
# PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs)
# a0 a1 a2 a3 a4
#
jal PrepareAndDispatch
REG_L ra, RAOFF(sp)
RESTORE_GP64
PTR_ADDU sp, FRAMESZ
j ra
END(dummy)

View File

@ -0,0 +1,218 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* ZHANG Le <r0bertz@gentoo.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "xptcprivate.h"
#include "xptiprivate.h"
#if (_MIPS_SIM != _ABIN32)
#error "This code is for MIPS N32 only"
#endif
/*
* This is for MIPS N32 ABI
*
* When we're called, the "gp" registers are stored in gprData and
* the "fp" registers are stored in fprData. There are 8 regs
* available which correspond to the first 7 parameters of the
* function and the "this" pointer. If there are additional parms,
* they are stored on the stack at address "args".
*
*/
extern "C" nsresult
PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint64* args,
PRUint64 *gprData, double *fprData)
{
#define PARAM_BUFFER_COUNT 16
#define PARAM_GPR_COUNT 7
#define PARAM_FPR_COUNT 7
nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
nsXPTCMiniVariant* dispatchParams = NULL;
const nsXPTMethodInfo* info;
PRUint8 paramCount;
PRUint8 i;
nsresult result = NS_ERROR_FAILURE;
NS_ASSERTION(self,"no self");
self->mEntry->GetMethodInfo(PRUint16(methodIndex), &info);
NS_ASSERTION(info,"no method info");
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");
PRUint64* ap = args;
PRUint32 iCount = 0;
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.IsArithmetic())
{
if (iCount < PARAM_GPR_COUNT)
dp->val.p = (void*)gprData[iCount++];
else
dp->val.p = (void*)*ap++;
continue;
}
// else
switch(type)
{
case nsXPTType::T_I8:
if (iCount < PARAM_GPR_COUNT)
dp->val.i8 = (PRInt8)gprData[iCount++];
else
dp->val.i8 = (PRInt8)*ap++;
break;
case nsXPTType::T_I16:
if (iCount < PARAM_GPR_COUNT)
dp->val.i16 = (PRInt16)gprData[iCount++];
else
dp->val.i16 = (PRInt16)*ap++;
break;
case nsXPTType::T_I32:
if (iCount < PARAM_GPR_COUNT)
dp->val.i32 = (PRInt32)gprData[iCount++];
else
dp->val.i32 = (PRInt32)*ap++;
break;
case nsXPTType::T_I64:
if (iCount < PARAM_GPR_COUNT)
dp->val.i64 = (PRInt64)gprData[iCount++];
else
dp->val.i64 = (PRInt64)*ap++;
break;
case nsXPTType::T_U8:
if (iCount < PARAM_GPR_COUNT)
dp->val.u8 = (PRUint8)gprData[iCount++];
else
dp->val.u8 = (PRUint8)*ap++;
break;
case nsXPTType::T_U16:
if (iCount < PARAM_GPR_COUNT)
dp->val.u16 = (PRUint16)gprData[iCount++];
else
dp->val.u16 = (PRUint16)*ap++;
break;
case nsXPTType::T_U32:
if (iCount < PARAM_GPR_COUNT)
dp->val.u32 = (PRUint32)gprData[iCount++];
else
dp->val.u32 = (PRUint32)*ap++;
break;
case nsXPTType::T_U64:
if (iCount < PARAM_GPR_COUNT)
dp->val.u64 = (PRUint64)gprData[iCount++];
else
dp->val.u64 = (PRUint64)*ap++;
break;
case nsXPTType::T_FLOAT:
if (iCount < PARAM_FPR_COUNT)
dp->val.f = (double)fprData[iCount++];
else
dp->val.f = *((double*)ap++);
break;
case nsXPTType::T_DOUBLE:
if (iCount < PARAM_FPR_COUNT)
dp->val.d = (double)fprData[iCount++];
else
dp->val.d = *((double*)ap++);
break;
case nsXPTType::T_BOOL:
if (iCount < PARAM_GPR_COUNT)
dp->val.b = (PRBool)gprData[iCount++];
else
dp->val.b = (PRBool)*ap++;
break;
case nsXPTType::T_CHAR:
if (iCount < PARAM_GPR_COUNT)
dp->val.c = (char)gprData[iCount++];
else
dp->val.c = (char)*ap++;
break;
case nsXPTType::T_WCHAR:
if (iCount < PARAM_GPR_COUNT)
dp->val.wc = (wchar_t)gprData[iCount++];
else
dp->val.wc = (wchar_t)*ap++;
break;
default:
NS_ASSERTION(0, "bad type");
break;
}
}
result = self->mOuter->CallMethod((PRUint16)methodIndex, info, dispatchParams);
if(dispatchParams != paramBuffer)
delete [] dispatchParams;
return result;
}
#define STUB_ENTRY(n) /* defined in the assembly file */
#define SENTINEL_ENTRY(n) \
nsresult nsXPTCStubBase::Sentinel##n() \
{ \
NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
return NS_ERROR_NOT_IMPLEMENTED; \
}
#include "xptcstubsdef.inc"