File:  [Atari MiNT] / MiNT / src / asm / syscall.s
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:55:36 2018 UTC (8 years, 1 month ago) by root
Branches: mint, MAIN
CVS tags: mint095, HEAD
MiNT 0.95 pl13

;

; syscall: interface for system calls. The following entry points are

;    defined:

; _mint_bios:  entry point for the BIOS calls (trap #13)

; _mint_xbios: entry point for XBIOS calls (trap #14)

; _mint_dos:   entry point for GEMDOS calls (trap #1)

; _sig_return: user signal handlers return to this routine (see signal.c)

;              it is responsible for restoring the kernel's old context

;              via the Psigreturn() system call

; _lineA0:     calls the line A initialize routine

; _call_aes:   calls the GEM AES

; _callout:    calls an external function, after first saving all registers,

;              and restores the registers afterward

;

; external variables referenced:

; _bios_tab, _bios_max:

;    table of entry points for BIOS routines, max # of routine

; _xbios_tab, _xbios_max:

;    ditto for XBIOS

; _dos_tab, _dos_max:

;    ditto for GEMDOS

; _curproc:

;    pointer to current process table entry, and hence to save area for

;    context (this is always the first entry in the PROC table).

; _valid_return:

;    used to indicate to the kernel that a valid return from user mode

;    is taking place

;

; _bconbuf, _bconbsiz, _bconbdev:

;    256 byte buffer for Bconout() output. If _bconbsiz is non-zero,

;    there are that many bytes in _bconbuf waiting to be flushed. The

;    output is for device _bconbdev.

;

; The C function enter_kernel() is called on entry to the kernel, and the

; function leave_kernel() is called on exit. These functions are responsible

; for saving and restoring the various trap vectors, so that MiNT can trap

; out to TOS directly, but programs can only trap to MiNT.

;

; $Log: syscall.s,v $
; Revision 1.1.1.1  2018/04/24 17:55:36  root
; MiNT 0.95 pl13
;

; Revision 1.3  1992/03/31  14:02:08  AGK

; Fixed for real Motorola syntax (many thanks to ERS for keeping these

; files in step with the GAS ones).

;

; Revision 1.2  1992/03/31  13:55:28  AGK

; Checked in MiNT 0.93 sources

;

; Revision 1.1  1991/05/30  17:24:16  AGK

; Initial revision

;

	SECTION	TEXT

	

	XDEF	_mint_bios,_mint_xbios

	XDEF	_mint_dos

	XREF	_build_context

	XREF	_restore_context

	XREF	_proc_clock		; controls process' allocation of CPU time

	XREF	_enter_kernel

	XREF	_leave_kernel

	XREF	_preempt



	XREF	_curproc

	XREF	_bios_tab,_bios_max

	XREF	_xbios_tab,_xbios_max

	XREF	_dos_tab,_dos_max



	XREF	_bconbuf,_bconbsiz,_bconbdev

	XREF	_bflush

	

_mint_dos:

	move.l	#_dos_tab,syscall_tab

	move.w	_dos_max,syscall_max

	bra.s	_syscall



_mint_xbios:

	move.l	#_xbios_tab,syscall_tab

	move.w	_xbios_max,syscall_max

	bra.s	_syscall



_mint_bios:

;

; Bconout() is noticeably slower under MiNT, so we do a bit of a kludge

; and special case Bconout() so that it doesn't take so long. We

; do this by buffering Bconout calls until either another kind of

; system call or a context switch happens.

;

	tst.w	_bconbdev		; buffering on?

	bmi.s	L_bios			; if bconbdev < 0, no buffering

	btst	#13,(sp)		; test for user/super mode

	beq.s	L_usr			; 

	lea	6(sp),a1		; supervisor mode: args on stack

	tst.w	$59e			; test longframe

	beq.s	L_check

	addq.l	#2,a1			; stack is a bit bigger

	bra.s	L_check

L_usr:

	move.l	usp,a1			; user mode: args on user stack

L_check:

	move.w	(a1),d0			; check command

	cmp.w	#3,d0			; Bconout?

	beq	do_bconout		; yes -- take some shortcuts

					; no -- fall through to the normal code

L_bios:

	move.l	#_bios_tab,syscall_tab

	move.w	_bios_max,syscall_max



_syscall:

	move.l	_curproc,d0

	addq.l	#4,d0

	move.l	d0,-(sp)		; push pointer to syscall context save

	jsr	_build_context

;

; copy parameters onto process stack. a1 was set by _build_context

;

L_copy:

	move.l	_curproc,a0

	move.l	(a0),sp			; this puts us in our private stack

	move.l	24(a1),-(sp)		; a1 was set by build_context

	move.l	20(a1),-(sp)

	move.l	16(a1),-(sp)

	move.l	12(a1),-(sp)

	move.l	8(a1),-(sp)

	move.l	4(a1),-(sp)

	move.l	(a1),-(sp)

;

	jsr	_enter_kernel		; set up vectors appropriately

;

; check here to see if we need to flush the Bconout() buffer

;

	tst.w	_bconbsiz		; characters in buffer?

	beq.s	L_noflush		; no: OK to proceed

;

; make sure we save syscall_tab and syscall_max

;

	move.l	syscall_tab,-(sp)

	move.w	syscall_max,-(sp)

	jsr	_bflush			; flush the buffer

	move.w	(sp)+,syscall_max

	move.l	(sp)+,syscall_tab



L_noflush:

;

; figure out which routine to call

;

	clr.l	d0

	move.w	(sp),d0

	cmp.w	#-1,d0			; trapping with -1 means return

	bne.s	check_max		; the corresponding system table

	move.l	syscall_tab,d0

	bra.s	out

check_max:

	cmp.w	syscall_max,d0

	bge.s	error

	add.l	d0,d0

	add.l	d0,d0			; multiply by 4

	move.l	syscall_tab,a0

	add.l	d0,a0

	move.l	(a0),a0

	cmp.l	#0,a0			; null entry means invalid call

	beq.s	error

	addq.l	#2,sp			; pop function number off stack

	jsr	(a0)			; go do the call

out:

	move.l	_curproc,a0

	move.l	d0,4(a0)		; set d0 in the saved context

	tst.w	_proc_clock		; has process exceeded time slice?

	bne.s	nosleep			; no -- continue

	move.w	68(a0),d0		; get saved status register

	btst	#13,d0			; caller in supervisor mode?

	bne	nosleep			; yes -- don't interrupt

sleep:

	jsr	_preempt		; does a sleep(READY_Q)

nosleep:

	ori.w	#$0700,sr		; spl7()

	jsr	_leave_kernel		; restore vectors

	move.l	_curproc,a0

	pea	4(a0)

	jsr	_restore_context	; never returns



;

; we handle errors by calling through to GEMDOS or the BIOS/XBIOS,

; as appropriate, and letting them handle it -- that way, if the underlying

; system has functions we don't know about, they still work

;



error:

	move.l	syscall_tab,a0

	cmp.l	#_xbios_tab,a0

	bne.s	maybe_dos

	trap	#14

	bra.s	out

maybe_dos:

	cmp.l	#_dos_tab,a0

	beq.s	trap_1

	trap	#13

	bra.s	out

trap_1:

	trap	#1

	bra.s	out



;

; sig_return: user signal handlers return to us. At that point, the

; stack looks like this:

;    (sp)      (long) signal number -- was a parameter for user routine

;

	XDEF	_sig_return

	XREF	_valid_return

_sig_return:

	addq.l	#4,sp			; pop signal number

	move.w	#$11a,-(sp)		; Psigreturn() system call

	move.w	#1,_valid_return	; tell kernel it's us!

	trap	#1

; we had better not come back; if we did, something terrible

; happened, and we might as well terminate

	move.w	#-998,-(sp)

	move.w	#$4c,-(sp)		; Pterm()

	trap	#1

;

; bconout special code: on entry, a1 points to the stack the user

; was using. If possible, we just buffer the output until later.

;



do_bconout:

	move.w	2(a1),d0		; what device is this for?

	beq	L_bios			; don't buffer the printer

	cmp.w	_bconbdev,d0		; same device as is buffered?

	bne.s	new_dev			; no -- maybe we can't do this

put_buf:

	move.w	4(a1),d0		; get the character to output

	move.w	_bconbsiz,d1		; get index into buffer table

	cmp.w	#255,d1			; buffer full?

	beq	L_bios			; yes -- flush it out

	lea	_bconbuf,a0

	add.w	d1,a0

	move.b	d0,(a0)			; store the character

	addq.w	#1,d1

	move.w	d1,_bconbsiz

	moveq.l	#-1,d0			; return character output OK

	rte



new_dev:

	tst.w	_bconbsiz		; characters already in buffer?

	bne	L_bios			; yes: we can't buffer this one

	move.w	d0,_bconbdev		; no: OK, we have a new device

	bra.s	put_buf



;

; _lineA0: MiNT calls this to get the address of the line A variables

;

	XDEF	_lineA0

_lineA0:

	movem.l	d2/a2,-(sp)	; save scratch registers

	dc.w	$a000		; call the line A initialization routine

	movem.l	(sp)+,d2/a2

	rts



;

; _call_aes: calls the GEM AES, using the control block passed as

;            a parameter. Used only for doing appl_init(), to see

;	     if the AES is active yet

;

	XDEF	_call_aes

_call_aes:

	move.l	4(sp),d1	; fetch pointer to parameter block

	move.w	#$c8,d0		; magic number for AES

	movem.l	d2/a2,-(sp)	; save scratch registers

	trap	#2

	movem.l	(sp)+,d2/a2

	rts



;

; _callout: Call an external function, passing <32 bytes of arguments,

; and return the value from the function. NOTE: we must be careful

; to save all registers here!

;

	XDEF	_callout

_callout:

	lea	8(sp),a0		; pointer to args

	move.l	4(sp),a1		; pointer to function

	movem.l	d2-d7/a2-a6,-(sp)	; save registers

	movem.l	(a0),d0-d7		; copy parameters

	lea	-32(sp),sp		; NOTE: movem.l auto-decrement

 	movem.l	d0-d7,(sp)		;    changes the order of things

	move.l	(a1),a0			; get function address

	jsr	(a0)			; go do it

	add.l	#32,sp

	movem.l	(sp)+,d2-d7/a2-a6	; restore reggies

	rts



	SECTION	BSS

	XDEF	syscall_tab,syscall_max

	

syscall_tab	ds.l	1		; set to which table to use for the call

syscall_max	ds.l	1		; maximum valid number for this call

	END


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.