/* -*- Mode: asm; 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 * Stuart Parmenter */ /* This code is for MIPS using the O32 ABI. */ #include #include .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" 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