!   "sparc.s" -- assembly language code for the SPARC architecture
! 
!   A SPARC context array is laid out like this:
! 
! 	saved %sp register -----------------------------|
! 	saved %fp					|
! 	saved %i7 (return addr)				|
! 	magic word for checking integrity		|
! 	unused stack space				| 
! 	current stack frame			<--- saved sp points here
! 	older stack data
!
!   For further information see the SPARC Architecture Manual, Version 8


	.seg	"text"

!   mpd_build_context(code,buf,bufsize,a1,a2,a3,a4) -- create a new context.
!
!   args passed in:  %i0  %i1  %i2   %i3 i4 i5 [%sp+64+4+24]
! 
!   code	 entry point of the code to be executed in the context
!   buf		 buffer for holding the context array
!   bufsize	 size of the buffer
!   a1 - a4	 four int-sized arguments to be passed to the code
!
!   We build a context that will execute the startup code, below,
!   when first activated.

	.global	MPD_BUILD_CONTEXT
MPD_BUILD_CONTEXT:
	save	%sp,-(96),%sp
	add	%i1,%i2,%l1		! end of buffer
	sub	%l1,(96),%l1		! initial stack pointer
	st	%l1,[%i1]		! set %sp
	st	%l1,[%i1+4]		! set also as %fp
	set	startup-8,%l2
	st	%l2,[%i1+8]		! set "return" address
	set	4073,%l3
	st	%l3,[%i1+12]		! set magic word
	st	%i3,[%l1+68]		! save args
	st	%i4,[%l1+68+4]
	st	%i5,[%l1+68+8]
	ld	[%fp+68+24],%l4
	st	%l4,[%l1+68+12]
	st	%i0,[%l1+68+16]		! save code address
	ret
	restore

startup:
	ld	[%sp+68+0],%o0		! reload arguments from stack frame
	ld	[%sp+68+4],%o1
	ld	[%sp+68+8],%o2
	ld	[%sp+68+12],%o3
	ld	[%sp+68+16],%l0
	call	%l0			! call the initial function
	nop
	ba	under			! return is an underflow error
	nop



!  mpd_chg_context(newctx,oldctx) -- switch to the specified context 
!
!  args passed in:  %i0     %i1 

	.global	MPD_CHG_CONTEXT
MPD_CHG_CONTEXT:
	save	%sp,-(96),%sp
	ta	3			! flush register windows
 	tst	%i1			! see if oldctx valid
	be	loadnew			! if zero, just load new context
	nop
	st	%sp,[%i1]		! save %sp
	st	%fp,[%i1+4]		! save %fp
	st	%i7,[%i1+8]		! save return addr
	ld	[%i0+12],%o2		! load magic word
	subcc	%o2,4073,%g0
	bne	bad			! if stack corrupted
	nop
loadnew:
	ld	[%i0],%sp		! load %sp
	ld	[%i0+4],%fp		! load %fp
	ld	[%i0+8],%i7		! load return addr
	ret				! return
	restore



!  mpd_check_stk(context) -- check that the stack is not overflowing
!
!  arg passed in  %o0  (we do not shift the register window)

	.global	MPD_CHECK_STK
MPD_CHECK_STK:
	inc	16,%o0			! lower bound for safe %sp
	cmp	%sp,%o0			! compare with actual stack pointer
	blu	over			! if overflow
	nop
	retl
	nop



!  stack problem handlers  (these calls do not return)

over:	ba	MPD_STK_OVERFLOW
	nop

under:	ba	MPD_STK_UNDERFLOW
	nop

bad:	ba	MPD_STK_CORRUPTED
	nop
