#################################################################
#								#
#	Copyright 2007, 2012 Fidelity Information Services, Inc	#
#								#
#	This source code contains the intellectual property	#
#	of its copyright holder(s), and is made available	#
#	under a license.  If you do not know the terms of	#
#	the license, please stop and do not read further.	#
#								#
#################################################################

#	PAGE	,132
	.title	op_exfun.s

#	.386
#	.MODEL	FLAT, C

.include "g_msf.si"
.include "linkage.si"

	.sbttl	op_exfun
#	PAGE	+
#	call op_exfun with the following stack:
#
#		return PC
#		ret_value address
#		offset from our return address to where this stackframe needs to return
# 		mask
#		actualcnt
#		actual1 address
#		actual2 address
#		...

	.DATA
.extern	ERR_GTMCHECK
.extern	dollar_truth
.extern	frame_pointer

	.text
.extern	exfun_frame
.extern	push_parm
.extern	rts_error

arg2_off	=	-72
arg1_off	=	-64
arg0_off	=	-56
act_cnt		=	-48
mask_arg	=	-44
ret_val		=	-40
rtn_pc		=	-32

sav_esi		=	-8
sav_ebx		=	-16
sav_msf		=	-24

# PUBLIC	op_exfun
ENTRY op_exfun
	pushq	REG_XFER_TABLE
	enter	$80,$0
	movq	16(REG_FRAME_POINTER), REG64_SCRATCH1			# above enter makes pushes old rbp and copies old SP to rbp
									# get the return address from rbp which is offset 16
	movq	REG64_SCRATCH1,rtn_pc(REG_FRAME_POINTER) 		# Save return address
	movq	REG64_ARG0,ret_val(REG_FRAME_POINTER)			# Save incoming arguments
	movl	REG32_ARG2,mask_arg(REG_FRAME_POINTER)
	movl	REG32_ARG3,act_cnt(REG_FRAME_POINTER)
	movq	REG64_ARG4,arg0_off(REG_FRAME_POINTER)
	movq	REG64_ARG5,arg1_off(REG_FRAME_POINTER)
	movq	frame_pointer(REG_IP),REG64_ARG2
	movq	rtn_pc(REG_FRAME_POINTER),REG64_ACCUM			# Verify the immediate instruction after
	cmpb	$JMP_Jv,(REG64_ACCUM)					# this function call
	je	long

error:	movl	ERR_GTMCHECK(REG_IP),REG32_ARG1
	movl	$1,REG32_ARG0
	movb	$0,REG8_ACCUM             # variable length argument
	call	rts_error
	jmp	retlab

long:	movq	REG64_ACCUM,msf_mpc_off(REG64_ARG2)
	addl	REG32_ARG1, msf_mpc_off(REG64_ARG2)
cont:	call	exfun_frame

	movl	act_cnt(REG_FRAME_POINTER),REG32_ACCUM
	cmpl	$0,REG32_ACCUM                          #arg0, arg1, arg2 are stored in rbp
	je	no_arg
	cmpl	$1,REG32_ACCUM				#We have only one register free for push_param args
	je	arg0
	cmpl	$2,REG32_ACCUM
	je	arg1
	cltq
	leaq	(REG_FRAME_POINTER,REG64_ACCUM,8),REG64_SCRATCH1
again:	pushq	(REG64_SCRATCH1)
	subq	$8,REG64_SCRATCH1
	subl	$1,REG32_ACCUM
	cmpl	$2,REG32_ACCUM
	jg	again
arg1:	pushq	arg1_off(REG_FRAME_POINTER)
arg0:	movq	arg0_off(REG_FRAME_POINTER),REG64_ARG5  #Only one argument which can be fitted into REG5
no_arg:	movl	act_cnt(REG_FRAME_POINTER), REG32_ARG4	#Actual Arg cnt
	movl	mask_arg(REG_FRAME_POINTER),REG32_ARG3	#Mask
	movq	ret_val(REG_FRAME_POINTER), REG64_ARG2	#ret_value
	movl	dollar_truth(REG_IP),REG32_ACCUM
	andl	$1,REG32_ACCUM
	movl	REG32_ACCUM,REG32_ARG1			#$T
	movl	act_cnt(REG_FRAME_POINTER),REG32_ACCUM
	addl	$4,REG32_ACCUM
	movl	REG32_ACCUM, REG32_ARG0			#Totalcount = Act count +4
	movb	$0,REG8_ACCUM				# variable length argument
	call	push_parm				# push_parm (total, $T, ret_value, mask, argc [,arg1, arg2, ...]);
done:	movq    frame_pointer(REG_IP),REG64_SCRATCH1
	movq	msf_temps_ptr_off(REG64_SCRATCH1),REG_FRAME_TMP_PTR
retlab:	leave
	movq    REG64_SCRATCH1,REG_FRAME_POINTER
	popq	REG_XFER_TABLE
	ret
# op_exfun ENDP

# END
