; This file belongs to FreeMiNT.  It's not in the original MiNT 1.12
; distribution.  See the file Changes.MH for a detailed log of changes.

; This file is dedicated to the FreeMiNT project.
; It's not allowed to use this file for other projects without my
; explicit permission.

; slb_util.spp dated 00/05/02
;
; Author:
; Thomas Binder
; (gryf@hrzpub.tu-darmstadt.de)
;
; Purpose:
; Contains assembler subroutines needed for Slbopen(), Slbclose(), ...
;
; History:
; 00/05/02: - slb_exec now reads *tosbp to get the basepage address (Gryf)
; 99/08/18: - Changed slb_exec to pass the basepage of the calling process,
;             instead of its PID (Gryf)
; 99/08/11-
; 99/08/17: - Creation (Gryf)

%include "../magic/magic.i"

	TEXT

; slb_open
;
; Fake routine for returning from Slbopen(). Calls the library's open()
; function in user mode and in the context of the calling process.
;
; Input:
; 0(sp): Pointer to shared library header
; 4(sp): Pointer to basepage of current process
; 8(sp): Pointer to name of shared library structure
;
; Returns:
; d0: Version number of the shared library, or GEMDOS error code

	XDEF	_slb_open

_slb_open:	move.l	(sp),a0
	move.l	4(sp),d0
	move.l	d0,-(sp)
	move.l	SH_OPEN(a0),a1
	jsr	(a1)
	addq.l	#4,sp
	tst.l	d0
	bmi.s	failed
	move.l	8(sp),a0
	lea	SL_NAME(a0),a0
	clr.l	-(sp)
	clr.l	-(sp)
	clr.l	-(sp)
	clr.l	-(sp)
	move.l	a0,-(sp)
	move.w	#$0016,-(sp)
	trap	#1
	lea	34(sp),sp
	rts

failed:	move.l	8(sp),a0
	move.l	d0,-(sp)
	move.l	a0,-(sp)
	move.w	#$0017,-(sp)
	trap	#1
	addq.l	#6,sp
	move.l	(sp)+,d0
	lea	12(sp),sp
	rts

; slb_close
;
; Fake routine for returning from Slbclose(). Calls the library's close()
; function in user mode and in the context of the calling process.
;
; Input:
; 0(sp): Pointer to basepage of current process
; 4(sp): Pointer to shared library structure, as passed to Slbclose()
;
; Returns:
; d0: Version number of the shared library, or GEMDOS error code

	XDEF	_slb_close

_slb_close:	move.l	4(sp),a0
	move.l	SL_HEAD(a0),a0
	move.l	SH_CLOSE(a0),a0
	move.l	(sp),d0
	move.l	d0,-(sp)
	jsr	(a0)
	addq.l	#4,sp
	move.l	4(sp),a0
	move.l	a0,-(sp)
	move.w	#$0017,-(sp)
	trap	#1
	lea	14(sp),sp
	rts

; slb_close_and_pterm
;
; Like slb_close(), but instead of calling Slbclose() again, Pterm() is called.
; This function is used when a process exited without calling Slbclose().

	XDEF	_slb_close_and_pterm

_slb_close_and_pterm:
	move.l	d0,-(sp)
	move.l	8(sp),a0
	move.l	SL_HEAD(a0),a0
	move.l	SH_CLOSE(a0),a0
	move.l	4(sp),d0
	move.l	d0,-(sp)
	jsr	(a0)
	addq.l	#4,sp
	move.l	(sp)+,d0
	addq.l	#8,sp
	move.w	d0,-(sp)
	move.w	#$004c,-(sp)
	trap	#1
	addq.l	#4,sp
	rts

; slb_exec
;
; Helper function to call an SLB's function from within an application.
;
; Input:
; 4(sp): Pointer to shared library structure
; 8(sp): Function number (long)
; 12(sp): Number of arguments (short)
; 14(sp): arguments (if any)
;
; Returns:
; d0: EINVFN: Function not implemented (or function number out of range)
;     Otherwise: Return code of function

; slb_fast is an alternative stub which avoids trapping to
; GEMDOS at each library call.

	XDEF	_slb_exec
%ifdef SLB_EXT
	XDEF	_slb_fast
%endif
	XREF	_tosbp

_slb_exec:
	move.l	_tosbp,a0
	move.l	(a0),d1

%ifdef SLB_EXT
	bra.s	slbcont
_slb_fast:
	clr.l	d1
slbcont:
%endif

	move.l	8(sp),d0
	bmi.s	einvfn
	move.l	4(sp),a0
	move.l	SL_HEAD(a0),a0
	cmp.l	SH_NO_FUNCS(a0),d0
	bcc.s	einvfn
%ifdef ONLY030
	move.l	SH_FUNCTIONS(a0,d0.l*4),d0
%else
	lsl.l	#2,d0
	move.l	SH_FUNCTIONS(a0,d0.l),d0
%endif
	beq.s	einvfn
	move.l	d0,a0
	move.l	d1,4(sp)
	jmp	(a0)

einvfn:
	moveq	#-32,d0
	rts

; Search for the $SLBPATH value (draco)

	XDEF	_getslbpath
	XREF	_slbpath

_getslbpath	move.l	4(sp),a0		; deep philosophy, really
	move.l	$002c(a0),a0
L_loop	lea	_slbpath,a1
	moveq	#$08,d0
L_strncmp	cmpm.b	(a0)+,(a1)+
	bne.s	L_nope
	subq.w	#$01,d0
	bne.s	L_strncmp
	move.l	a0,d0
	bne.s	L_got
L_nope	clr.l	d0
L_zs	tst.b	(a0)+
	bne.s	L_zs
	tst.b	(a0)
	bne.s	L_loop
L_got	rts

; Following are some MiNT-GEMDOS-calls

	XDEF	_P_kill

_P_kill:	move.l	4(sp),-(sp)
	move.w	#$0111,-(sp)
	trap	#1
	addq.l	#6,sp
	rts

	XDEF	_P_sigsetmask

_P_sigsetmask:	move.l	4(sp),-(sp)
	move.w	#$0117,-(sp)
	trap	#1
	addq.l	#6,sp
	rts

	XDEF	_P_setpgrp

_P_setpgrp:	move.l	4(sp),-(sp)
	move.w	#$010e,-(sp)
	trap	#1
	addq.l	#6,sp
	rts

	XDEF	_P_domain

_P_domain:	move.w	4(sp),-(sp)
	move.w	#$0119,-(sp)
	trap	#1
	addq.l	#4,sp
	rts

; EOF
