⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hipe_sparc_glue.s

📁 OTP是开放电信平台的简称
💻 S
字号:
/* $Id$ */#include "hipe_sparc_asm.h"#include "hipe_literals.h"#define ASM#include "hipe_mode_switch.h"	.section ".text"	.align	4/* * Return to the calling C function. * The return value is in TEMP0. * * .flush_exit saves NSP and other cached P state. * .suspend_exit also saves RA */.suspend_exit:	/* save RA, so we can be resumed */	st	RA, [P+P_NRA].flush_exit:	/* restore C return address (hoisted to avoid stall) */	ld	[%sp+96], %i7	/* flush cached P state */	st	FCALLS, [P+P_FCALLS]	st	NSP, [P+P_NSP]	st	HP, [P+P_HP]	/* restore callee-save registers, drop frame, return */	jmp	%i7+8				! ret	restore	%g0,TEMP0,%o0/* * int sparc_call_to_native(Process *p); * Emulated code recursively calls native code. */	.align	4	.global	sparc_call_to_native	.type	sparc_call_to_native,#function	.proc	04sparc_call_to_native:	save %sp,-112,%sp		! shifts %o0 to %i0, and P == %i0	st %i7,[%sp+96]			! save C return address	ld [P+P_ARG0],ARG0			! Arg0	ld [P+P_ARG1],ARG1			! Arg1	ld [P+P_ARG2],ARG2			! Arg2	ld [P+P_ARG3],ARG3			! Arg3	ld [P+P_ARG4],ARG4			! Arg4	ld [P+P_ARG5],ARG5			! Arg5	ld [P+P_FCALLS],FCALLS			! fcalls	ld [P+P_NSP],NSP			! nstop	ld [P+P_NSP_LIMIT],NSP_LIMIT		! nstack_max	ld [P+P_HP],HP				! htop	ld [P+P_HP_LIMIT],HP_LIMIT		! heap_margin	ld [P+P_NCALLEE],TEMP0			! call address	/* FALLTHROUGH * * We export this return address so that hipe_mode_switch() can discover * when native code tailcalls emulated code. * Note: this is SPARC, so the value in the return address register * is the address of the call/jmpl instruction itself. */	.global nbif_returnnbif_return:	jmpl TEMP0,RA				! Call native code	nop/* FALLTHROUGH * * This is where native code returns to emulated code. * XXX:	Needs fix for multiple return values.	 */	st %o0,[P+P_ARG0]			! save retval	ba .flush_exit	mov HIPE_MODE_SWITCH_RES_RETURN,TEMP0/* * Native code calls emulated code via a linker-generated * stub which should look as follows: (see compiler's sparc_loader.erl) * * stub for f/N: *	sethi %hi(f's BEAM code address), TEMP0 *	mov RA, TEMP2		! because the call below clobbers RA (%o7) *	or TEMP0, %lo(f's BEAM code address), TEMP0 *	call nbif_callemu	! clobbers RA! *	mov N, TEMP1 */	.global nbif_callemunbif_callemu:	/* TEMP0  contains callee's BEAM code address	 * TEMP1 contains callee's arity	 * TEMP2 contains native RA (current RA/%o7 contains junk)	 */	st TEMP0,[P+P_BEAM_IP]			! callee	st TEMP1,[P+P_ARITY]			! arity	st TEMP2,[P+P_NRA]			! native return address	st ARG0,[P+P_ARG0]			! Arg0	st ARG1,[P+P_ARG1]			! Arg1	st ARG2,[P+P_ARG2]			! Arg2	st ARG3,[P+P_ARG3]			! Arg3	st ARG4,[P+P_ARG4]			! Arg4	st ARG5,[P+P_ARG5]			! Arg5	ba .flush_exit	mov HIPE_MODE_SWITCH_RES_CALL,TEMP0/* * nbif_apply */	.global	nbif_applynbif_apply:	st	ARG0, [P+P_ARG0]	st	ARG1, [P+P_ARG1]	st	ARG2, [P+P_ARG2]	ba	.suspend_exit	mov	HIPE_MODE_SWITCH_RES_APPLY, TEMP0/* * Native code calls an emulated-mode closure via a stub defined below. * * The closure is appended as the last actual parameter, and parameters * beyond the first 5 are pushed onto the stack in left-to-right order. * Hence, the location of the closure parameter only depends on the number * of parameters in registers, not the total number of parameters. */	.global nbif_ccallemu6	.global nbif_ccallemu5	.global nbif_ccallemu4	.global nbif_ccallemu3	.global nbif_ccallemu2	.global nbif_ccallemu1	.global nbif_ccallemu0nbif_ccallemu6:	ld [NSP-4], TEMP0	ba .args5	st TEMP0,[P+P_CLOSURE]nbif_ccallemu5:	ba .args4	st ARG5,[P+P_CLOSURE]	nbif_ccallemu4:	ba .args3	st ARG4,[P+P_CLOSURE]nbif_ccallemu3:	ba .args2	st ARG3,[P+P_CLOSURE]nbif_ccallemu2:	ba .args1	st ARG2,[P+P_CLOSURE]nbif_ccallemu1:	ba .args0	st ARG1,[P+P_CLOSURE]nbif_ccallemu0:	ba .ccall	st ARG0,[P+P_CLOSURE].args5:		st ARG5,[P+P_ARG5].args4:		st ARG4,[P+P_ARG4].args3:		st ARG3,[P+P_ARG3].args2:		st ARG2,[P+P_ARG2].args1:		st ARG1,[P+P_ARG1].args0:		st ARG0,[P+P_ARG0].ccall:		ba .suspend_exit		mov HIPE_MODE_SWITCH_RES_CALL_CLOSURE,TEMP0/* * This is where native code suspends. */	.align 4	.global nbif_suspend_0nbif_suspend_0:	ba .suspend_exit	mov HIPE_MODE_SWITCH_RES_SUSPEND,TEMP0/* * Suspend from a receive (waiting for a message) */	.align 4	.global nbif_suspend_msgnbif_suspend_msg:	ba .suspend_exit	mov HIPE_MODE_SWITCH_RES_WAIT,TEMP0/* * Suspend from a receive with a timeout (waiting for a message) *	if (!(p->flags & F_TIMO)) { suspend } *	else { return 0; } */	.align 4	.global nbif_suspend_msg_timeoutnbif_suspend_msg_timeout:	ld [P+P_FLAGS],TEMP1			! Check if timeout	!! this relies on F_TIMO (1<<2) fitting in an immediate...	andcc TEMP1,F_TIMO,%g0			! F_TIMO set?	bz,a .suspend_exit			! if not set, suspend	mov HIPE_MODE_SWITCH_RES_WAIT_TIMEOUT,TEMP0 ! .. and set C retval	!! timeout has occurred	jmp RA+8				! retl	mov 0,%o0/* * int sparc_return_to_native(Process *p); * Emulated code returns to its native code caller. */	.align	4	.global	sparc_return_to_native	.type	sparc_return_to_native,#function	.proc	04sparc_return_to_native:	save %sp,-112,%sp	ld [P+P_NRA],RA				! XXX: was CALL_ADDRESS	st %i7,[%sp+96]			! save C return address	ld [P+P_FCALLS],FCALLS			! fcalls	ld [P+P_NSP],NSP			! nstop	ld [P+P_NSP_LIMIT],NSP_LIMIT		! nstack_max	ld [P+P_HP],HP				! htop	ld [P+P_HP_LIMIT],HP_LIMIT		! heap_margin	ld [P+P_ARG0],%o0			! retval	jmp RA+8				! retl to native code	nop/* * int sparc_tailcall_to_native(Process *); * Emulated code tailcalls native code. */	.align	4	.global	sparc_tailcall_to_native	.type	sparc_tailcall_to_native,#function	.proc	04sparc_tailcall_to_native:	save %sp,-112,%sp	st %i7,[%sp+96]			! save C return address	ld [P+P_NCALLEE],TEMP0			! call address	ld [P+P_FCALLS],FCALLS			! fcalls	ld [P+P_NSP],NSP			! nstop	ld [P+P_NSP_LIMIT],NSP_LIMIT		! nstack_max	ld [P+P_HP],HP				! htop	ld [P+P_HP_LIMIT],HP_LIMIT		! heap_margin	ld [P+P_ARG0],ARG0			! Arg0	ld [P+P_ARG1],ARG1			! Arg1	ld [P+P_ARG2],ARG2			! Arg2	ld [P+P_ARG3],ARG3			! Arg3	ld [P+P_ARG4],ARG4			! Arg4	ld [P+P_NRA],RA				! native return address	jmp TEMP0				! Call native code	ld [P+P_ARG5],ARG5			! Arg5/* * int sparc_throw_to_native(Process *p); * Emulated code throws an exception to its native code caller. */	.align	4	.global	sparc_throw_to_native	.type	sparc_throw_to_native,#function	.proc	04sparc_throw_to_native:	save %sp,-112,%sp	st %i7,[%sp+96]			! save C return address	ld [P+P_NCALLEE],TEMP0			! handler address	ld [P+P_FCALLS],FCALLS			! fcalls	ld [P+P_NSP],NSP			! nstop	ld [P+P_NSP_LIMIT],NSP_LIMIT		! nstack_max	ld [P+P_HP],HP				! htop	ld [P+P_HP_LIMIT],HP_LIMIT		! heap_margin	jmp TEMP0				! invoke the handler	nop/* * This is the default exception handler for native code. */	.global	nbif_failnbif_fail:	ba	.flush_exit	mov	HIPE_MODE_SWITCH_RES_THROW, TEMP0/* * We end up here when a BIF called from native signals an * exceptional condition, and RESCHEDULE cannot occur. * FCALLS was just read from P. * HP has not been read from P. * NSP has not been saved in P. * TEMP3 contains the native return address. */	.global	nbif_1_simple_exception	.global	nbif_2_simple_exception	.global	nbif_3_simple_exception	.align	4nbif_1_simple_exception:	ba	.nbif_simple_exception	mov	1,ARG4nbif_2_simple_exception:	ba	.nbif_simple_exception	mov	2,ARG4nbif_3_simple_exception:	mov	3,ARG4	!! FALLTHROUGH.nbif_simple_exception:	ld	[P+P_FREASON],ARG1	st	NSP,[P+P_NSP].nbif_simple_exception2:	cmp	ARG1,FREASON_TRAP	beq	.handle_trap	nop	/*	 * Find and invoke catch handler (it must exist).	 * FCALLS was just read from P.	 * HP has not been read from P.	 * NSP has been saved in P.	 * TEMP3 should contain the current call's return address.	 */	/* find and prepare to invoke the handler */	st	TEMP3, [P+P_NRA]  	! TEMP3 = RetAdr, save to find current sdesc	call	hipe_handle_exception	mov	P, %o0                  ! (delayslot)	ld	[P+P_HP],HP		! hipe_handle_exception() conses	ld	[P+P_FCALLS],FCALLS	! updated by hipe_handle_exception()	/* now invoke the handler */	ld	[P+P_NCALLEE], %o1	! updated by hipe_find_handler()	ld	[P+P_NSP], NSP		! updated by hipe_find_handler()	jmp	%o1	nop	/*	 * A BIF failed with freason TRAP:	 * - the BIF stored the callee's Export* in p->def_arg_reg[3]	 * - the BIF stored the callee's parameters in p->def_arg_reg[0..2]	 * - the BIF's arity is in ARG4	 * - the native RA was saved in TEMP3 before the BIF call	 * - FCALLS was just read from P	 * - HP has not been read from P	 * - NSP has been saved in P	 */.handle_trap:	mov	HIPE_MODE_SWITCH_RES_TRAP, TEMP0.bif_exit:	/* restore C return address (hoisted to avoid stall) */	ld	[%sp+96], %i7	st	ARG4, [P+P_ARITY]	st	TEMP3, [P+P_NRA]		! RA	jmp	%i7+8	restore	%g0,TEMP0,%o0/* * We end up here when a BIF called from native signals an * exceptional condition, and RESCHEDULE _CAN_ occur. * TEMP3 contains the native return address. * FCALLS was just read from P. * HP has not been read from P. * NSP has not been saved in P. * TEMP0 contains the address of the nbif which failed * TEMP1 contains the first actual parameter * TEMP2 contains the second actual parameter (if it is defined) * ARG4 contains the number of parameters (1 or 2) */	.align	4	.global	nbif_hairy_exceptionnbif_hairy_exception:	ld	[P+P_FREASON],ARG1	st	NSP,[P+P_NSP]	cmp	ARG1,FREASON_RESCHEDULE	bne	.nbif_simple_exception2	nop	/* handle reschedule */	st	TEMP0,[P+P_NCALLEE]	st	TEMP1,[P+P_ARG0]	st	TEMP2,[P+P_ARG1]	ba	.bif_exit	mov	HIPE_MODE_SWITCH_RES_RESCHEDULE, TEMP0/* * nbif_stack_trap_ra: trap return address for maintaining * the gray/white stack boundary * XXX:	Fix for multiple returnvalues.	 */	.global	nbif_stack_trap_ra	.align	4nbif_stack_trap_ra:			! a return address, not a function	nop                             ! Simulate ret adr	nop	mov %o0,TEMP1			! save retval	mov P,%o0	!! Save registers and call the C function	call hipe_handle_stack_trap	! must not cons	st NSP,[P+P_NSP]                !  (delayslot)	mov %o0, TEMP0	                ! original RA    	!! Restore registers and return	!! We only restore argument1	jmpl TEMP0+8,%g0                ! resume at original RA	mov TEMP1,%o0			! restore retval/*   This procedure is called when nativecode runs out of stack. *   There is a special calling convention for this function *   in order to minimize code duplication. *   Each non-leaf function may have to call this procedure. *   The call is done by storing the previous returnaddress *   in TEMP2.  *   This procedure is responsible of storing the *   argumentents in ARG0 to ARG15 and restoring them afterwards. *   It assumes that hipe_inc_nstack dont use local reg  *   (true as long as hipe_inc_nstack is implemented in C and *    uses register windows.) *		 *   !!! THIS procedure may not use TEMP2 */	.align	4	.global	nbif_inc_stack_6args		.global	nbif_inc_stack_5args	.global	nbif_inc_stack_4args	.global	nbif_inc_stack_3args		.global	nbif_inc_stack_2args		.global	nbif_inc_stack_1args		.global	nbif_inc_stack_0args		nbif_inc_stack_6args:		st ARG5,[P+P_ARG5]nbif_inc_stack_5args:		st ARG4,[P+P_ARG4]nbif_inc_stack_4args:		st ARG3,[P+P_ARG3]nbif_inc_stack_3args:		st ARG2,[P+P_ARG2]nbif_inc_stack_2args:	st ARG1,[P+P_ARG1]nbif_inc_stack_1args:		st ARG0,[P+P_ARG0]nbif_inc_stack_0args:	!! save RA	mov RA, TEMP1	!! The argument to hipe_inc_stack is the PCB.	mov P, %o0		!! Save registers and call the C function	call hipe_inc_nstack	st NSP,[P+P_NSP]       !! Delayslot	!! Restore registers and return	ld [P+P_NSP_LIMIT],NSP_LIMIT	!! We restore all arguments, even unused ones. 		ld [P+P_ARG5], ARG5	ld [P+P_ARG4], ARG4	ld [P+P_ARG3], ARG3	ld [P+P_ARG2], ARG2	ld [P+P_ARG1], ARG1	ld [P+P_ARG0], ARG0	jmpl TEMP1+8,%g0	ld [P+P_NSP],NSP

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -