зеркало из https://github.com/mozilla/gecko-dev.git
Adding xptcinvoke code for the MIPS O32 ABI. r=pavlov sr=brendan
This commit is contained in:
Родитель
e2a1e61fca
Коммит
ad816e444f
|
@ -0,0 +1,168 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* Version: MPL 1.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 Corp, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/* This code is for MIPS using the O32 ABI. */
|
||||
|
||||
#include <sys/regdef.h>
|
||||
#include <sys/asm.h>
|
||||
|
||||
.text
|
||||
.globl invoke_count_words
|
||||
.globl invoke_copy_to_stack
|
||||
|
||||
# We need a variable number of words allocated from the stack for copies of
|
||||
# the params, and this space must come between the high frame (where ra, gp,
|
||||
# and s0 are saved) and the low frame (where a0-a3 are saved by the callee
|
||||
# functions we invoke).
|
||||
|
||||
LOCALSZ=4 # s0, s1, ra, gp
|
||||
NARGSAVE=4 # a0, a1, a2, a3
|
||||
HIFRAMESZ=(LOCALSZ*SZREG)
|
||||
LOFRAMESZ=(NARGSAVE*SZREG)
|
||||
FRAMESZ=(HIFRAMESZ+LOFRAMESZ+ALSZ)&ALMASK
|
||||
|
||||
# XXX these 2*SZREG, etc. are very magic -- we *know* that ALSZ&ALMASK cause
|
||||
# FRAMESZ to be 0 mod 8, in this case to be 16 and not 12.
|
||||
RAOFF=FRAMESZ - (2*SZREG)
|
||||
GPOFF=FRAMESZ - (3*SZREG)
|
||||
S0OFF=FRAMESZ - (4*SZREG)
|
||||
S1OFF=FRAMESZ - (5*SZREG)
|
||||
|
||||
# These are not magic -- they are just our argsave slots in the caller frame.
|
||||
A0OFF=FRAMESZ
|
||||
A1OFF=FRAMESZ + (1*SZREG)
|
||||
A2OFF=FRAMESZ + (2*SZREG)
|
||||
A3OFF=FRAMESZ + (3*SZREG)
|
||||
|
||||
#
|
||||
# _XPTC_InvokeByIndex(that, methodIndex, paramCount, params)
|
||||
# a0 a1 a2 a3
|
||||
|
||||
NESTED(_XPTC_InvokeByIndex, FRAMESZ, ra)
|
||||
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
.set reorder
|
||||
|
||||
subu sp, FRAMESZ
|
||||
|
||||
# specify the save register mask -- XXX do we want the a0-a3 here, given
|
||||
# our "split" frame where the args are saved below a dynamicly allocated
|
||||
# region under the high frame?
|
||||
#
|
||||
# 10010000000000010000000011110000
|
||||
.mask 0x900100F0, -((NARGSAVE+LOCALSZ)*SZREG)
|
||||
# thou shalt not use .cprestore if yer frame has variable size...
|
||||
# .cprestore GPOFF
|
||||
|
||||
REG_S ra, RAOFF(sp)
|
||||
# this happens automatically with .cprestore, but we cannot use that op...
|
||||
REG_S gp, GPOFF(sp)
|
||||
REG_S s0, S0OFF(sp)
|
||||
REG_S s1, S1OFF(sp)
|
||||
|
||||
REG_S a0, A0OFF(sp)
|
||||
REG_S a1, A1OFF(sp)
|
||||
REG_S a2, A2OFF(sp)
|
||||
REG_S a3, A3OFF(sp)
|
||||
|
||||
# invoke_count_words(paramCount, params)
|
||||
move a0, a2
|
||||
move a1, a3
|
||||
|
||||
jal invoke_count_words
|
||||
lw gp, GPOFF(sp)
|
||||
|
||||
# save the old sp so we can pop the param area and any "low frame"
|
||||
# needed as an argsave area below the param block for callees that
|
||||
# we invoke.
|
||||
move s0, sp
|
||||
|
||||
REG_L a1, A2OFF(sp) # a1 = paramCount
|
||||
REG_L a2, A3OFF(sp) # a2 = params
|
||||
|
||||
# we define a word as 4 bytes, period end of story!
|
||||
sll v0, 2 # 4 bytes * result of invoke_copy_words
|
||||
subu v0, LOFRAMESZ # but we take back the argsave area built into
|
||||
# our stack frame -- SWEET!
|
||||
subu sp, sp, v0 # make room
|
||||
move a0, sp # a0 = param stack address
|
||||
move s1, a0 # save it for later -- it should be safe here
|
||||
|
||||
# the old sp is still saved in s0, but we now need another argsave
|
||||
# area ("low frame") for the invoke_copy_to_stack call.
|
||||
subu sp, sp, LOFRAMESZ
|
||||
|
||||
# copy the param into the stack areas
|
||||
# invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
|
||||
# nsXPTCVariant* s)
|
||||
jal invoke_copy_to_stack
|
||||
lw gp, GPOFF(s0)
|
||||
|
||||
move sp, s0 # get orig sp back, popping params and argsave
|
||||
|
||||
REG_L a0, A0OFF(sp) # a0 = set "that" to be "this"
|
||||
|
||||
# XXX why not directly load t1 with A1OFF(sp) and then just shift it?
|
||||
# .. 1 register access instead of 2!
|
||||
REG_L a1, A1OFF(sp) # a1 = methodIndex
|
||||
|
||||
# t1 = methodIndex * 4
|
||||
# (use shift instead of mult)
|
||||
sll t1, a1, 2
|
||||
|
||||
# calculate the function we need to jump to,
|
||||
# which must then be saved in t9
|
||||
lw t9, 0(a0)
|
||||
addu t9, t9, t1
|
||||
lw t9, 8(t9)
|
||||
|
||||
# a1..a3 and f13..f14 should now be set to what
|
||||
# invoke_copy_to_stack told us. skip a0 and f12
|
||||
# because that is the "this" pointer
|
||||
|
||||
REG_L a1, 1*SZREG(s1)
|
||||
REG_L a2, 2*SZREG(s1)
|
||||
REG_L a3, 3*SZREG(s1)
|
||||
|
||||
l.d $f13, 8(s1)
|
||||
l.d $f14, 16(s1)
|
||||
|
||||
# Create the stack pointer for the function, which must have 4 words
|
||||
# of space for callee-saved args. invoke_count_words allocated space
|
||||
# for a0 starting at s1, so we just move s1 into sp.
|
||||
move sp, s1
|
||||
|
||||
jalr ra, t9
|
||||
lw gp, GPOFF(s0)
|
||||
|
||||
move sp, s0
|
||||
|
||||
REG_L ra, RAOFF(sp)
|
||||
REG_L s0, S0OFF(sp)
|
||||
addu sp, FRAMESZ
|
||||
j ra
|
||||
.end _XPTC_InvokeByIndex
|
|
@ -0,0 +1,107 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* Version: MPL 1.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 Corp, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
*
|
||||
*/
|
||||
|
||||
/* This code is for MIPS using the O32 ABI. */
|
||||
|
||||
/* Platform specific code to invoke XPCOM methods on native objects */
|
||||
|
||||
#include "xptcprivate.h"
|
||||
|
||||
|
||||
extern "C" uint32
|
||||
invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
|
||||
{
|
||||
// Count a word for a0 even though it's never stored or loaded
|
||||
// We do this only for alignment of register pairs.
|
||||
PRUint32 result = 1;
|
||||
for (PRUint32 i = 0; i < paramCount; i++, s++)
|
||||
{
|
||||
result++;
|
||||
|
||||
if (s->IsPtrData())
|
||||
continue;
|
||||
|
||||
switch(s->type)
|
||||
{
|
||||
case nsXPTType::T_I64 :
|
||||
case nsXPTType::T_U64 :
|
||||
case nsXPTType::T_DOUBLE :
|
||||
if (result & 1)
|
||||
result++;
|
||||
result++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (result + 1) & ~(PRUint32)1;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
|
||||
nsXPTCVariant* s)
|
||||
{
|
||||
// Skip the unused a0 slot, which we keep only for register pair alignment.
|
||||
d++;
|
||||
|
||||
for (PRUint32 i = 0; i < paramCount; i++, d++, s++)
|
||||
{
|
||||
if (s->IsPtrData())
|
||||
{
|
||||
*((void**)d) = s->ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
*((void**)d) = s->val.p;
|
||||
|
||||
switch(s->type)
|
||||
{
|
||||
case nsXPTType::T_I64 :
|
||||
if ((PRWord)d & 4) d++;
|
||||
*((PRInt64*) d) = s->val.i64; d++;
|
||||
break;
|
||||
case nsXPTType::T_U64 :
|
||||
if ((PRWord)d & 4) d++;
|
||||
*((PRUint64*) d) = s->val.u64; d++;
|
||||
break;
|
||||
case nsXPTType::T_DOUBLE :
|
||||
if ((PRWord)d & 4) d++;
|
||||
*((double*) d) = s->val.d; d++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
|
||||
PRUint32 paramCount,
|
||||
nsXPTCVariant* params);
|
||||
|
||||
extern "C"
|
||||
XPTC_PUBLIC_API(nsresult)
|
||||
XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
|
||||
PRUint32 paramCount, nsXPTCVariant* params)
|
||||
{
|
||||
return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче