File:  [Atari MiNT] / MiNT / src / asm / context.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

;

; routines for saving/restoring user contexts

;

; long build_context(struct context *sav):

;	Called from an interrupt handler (such as the trap #1 routine

;	for system calls) saves the context of the interrupted

;	routine. Assumes that no user registers have been changed

;	since the interrupt, and that the PC and status register

;	are still on the stack. Returns the stack pointer being used

;	at the time of the interrupt **in register a1**.

;

; long save_context(struct context *sav):

;	Saves the context of the calling routine in the area pointed

;	to by sav. Save_context always returns 0 when initially called;

;	this is so processes can (by suitably manipulating the

;	saved registers) tell when the return from save_context is

;	actually caused by restoring the context, e.g.:

;		if (save_context(sav) == 0) {		<<-- L1

;			/* do some stuff */

;			sav.regs[D0] = 1;	/* for restore context */

;			restore_context(sav);	/* goes back to L1 */

;		}

;		else /* this is the second time through */

;

; void restore_context(struct context *sav):

;	Restores a context previously saved by build_context or save_context.

;	Since the program counter is part of the context, this function

;	will never return (it's like longjmp()).

;

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

; Revision 1.6  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.5  1992/03/31  13:55:28  AGK

; Checked in MiNT 0.93 sources

;

; Revision 1.4  1991/05/31  15:55:00  AGK

; Tested only a byte in the save frame, not a word (my mistake). Bumped FPU

; frame size up to 216 bytes, the 68882 manual is wrong (thanks Motorola!)

;

; Revision 1.3  1991/05/31  09:58:44  AGK

; Fixed stack frame format manipulation so we use d1, not d0, which is

; needed later for super/user mode determination.

;

; Revision 1.2  1991/05/31  09:48:06  AGK

; Changes to accomodate longer stack frames etc.

;

; Revision 1.1  1991/05/30  17:22:02  AGK

; Initial revision

;

	SECTION	TEXT

	

	XDEF	_build_context

	XDEF 	_save_context

	XDEF	_restore_context

	XREF	_fpu

	XREF	_m68010

	

_build_context:

	move.l	a0,-(sp)	; save a0; we'll use it for scratch

	move.l	8(sp),a0	; get address of save area



; if running with a true coprocessor we need to save the FPU state



	tst.w	_fpu		; is there a true FPU in the system

	beq.s	nofpu

	fsave	78(a0)		; save internal state frame

	tst.b	78(a0)		; if NULL frame then the FPU is not in use

	beq.s	nofpu		; skip programmer's model save

	fmovem.x	fp0-fp7,294(a0)		; save data registers

	fmovem.l	fpcr/fpsr/fpiar,390(a0)	; and control registers

nofpu:

	movem.l	d0-d7/a0-a6,(a0)	; save registers D0-D7/A0-A6

	move.l	14(sp),66(a0)	; save PC of context

	move.w	12(sp),d0	; get SR of context

	move.w	d0,64(a0)	; save it 

	tst.w	($59e).w	; test longframe (AKP)

	beq.s	short1		; short

	lea	20(sp),a1	; else long

	

	move.w	18(sp),d1	; fetch frame format word

	move.w	d1,402(a0)	; and stash it away for later

	tst.w	_m68010		; are we on a 68010?

	bne.s	short2		; yes -- so it's a simple interrupt frame

; note: in order to have got to this point in the code we must be

; running on an 020/030 hence we can use the extra processor instructions

	bftst	d1{16:4}	; is it the simple interrupt frame ?

	beq.s	short2		; yes so just dump the stack contents

	movem.l	(a1)+,d1-d3	; instruction address/4 internal words

	movem.l	d1-d3,404(a0)

	bra.s	short2

short1:

	lea	18(sp),a1	; save supervisor stack pointer

short2:				; note that it should be pointing above the PC

	move.l	a1,70(a0)

	move.l	usp,a1		; save user stack pointer

	move.l	a1,60(a0)

	btst	#13,d0		; check for supervisor mode

	beq.s	L_CONT1		; user mode; we already have stack in a1

L_SUPER1:

; note: this was lea a0@(18), but moving from the save state buffer 

; means not testing longframe again. (AKP)

	move.l	70(a0),a1	; was using super stack pointer before interrupt

				; 

L_CONT1:

	move.l	($408).w,74(a0)	; save GEMDOS terminate vector

	move.l	(sp)+,32(a0)	; save old register a0

	rts



_save_context:

	move.l	a0,-(sp)	; save a0

	move.l	8(sp),a0	; get address of context save area



; if running with a true coprocessor we need to save the FPU state



	tst.w	_fpu		; is there a true FPU in the system

	beq.s	nofpu2

	fsave	78(a0)		; save internal state frame

	tst.b	78(a0)		; if NULL frame then the FPU is not in use

	beq.s	nofpu2		; skip programmer's model save

	fmovem.x	fp0-fp7,294(a0)		; save data registers

	fmovem.l	fpcr/fpsr/fpiar,390(a0)	; and control registers

nofpu2:

; note: I am somewhat unsure of this assumption, viz that save_context

; can never be called in a situation where a co-processor

; mid-instruction stack frame would be required. I suspect this is a

; valid assumption, in which case the above FPU code is redundant, the

; next line is not however!



	clr.w	402(a0)		; mark as a 4 word stack frame



	movem.l	d0-d7/a0-a6,(a0)	; save D0-D7/A0-A6

	lea	8(sp),a1

	move.l	a1,70(a0)	; save supervisor stack pointer

				; note that it should be pointing above the PC

	move.l	-4(a1),66(a0)	; save PC

	move.l	usp,a1

	move.l	a1,60(a0)	; save user stack pointer

	move.w	sr,d0

	move.w	d0,64(a0)	; save status register

	move.l	($408).w,74(a0)	; save GEMDOS terminate vector

	move.l	(sp)+,32(a0)	; save old a0

	moveq.l	#0,d0		; return 0

	rts



_restore_context:

	ori.w	#$0700,sr	; mask interrupts

	move.l	4(sp),a0	; address of context save area

	move.l	70(a0),sp	; supervisor stack pointer

	move.l	60(a0),a1

	move.l	a1,usp		; set user stack pointer

	move.l	74(a0),($408).w	; restore GEMDOS terminate vector



	tst.w	($59e).w	; test longframe (AKP)

	beq.s	short3



	move.w	402(a0),d0	; fetch frame format word

	tst.w	_m68010

	bne.s	just0



; again, we reach here only on an 020/030



	bftst	d0{16:4}	; is it the simple interrupt frame ?

	beq.s	just0		; yes so just push a zero

	movem.l	404(a0),d1-d3	; saved instruction address/4 internal words

	movem.l	d1-d3,-(sp)

just0:	move.w	d0,-(sp)

	

short3:

	move.l	66(a0),-(sp)	; push the PC

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

	move.w	d0,-(sp)	; push the status register



; if running with a true coprocessor we need to restore the FPU state



	tst.w	_fpu		; is there a true FPU in the system

	beq.s	nofpu3

	tst.b	78(a0)		; if NULL frame then the FPU is not in use

	beq.s	short7		; skip programmer's model restore

	fmovem.l	390(a0),fpcr/fpsr/fpiar	; restore control registers

	fmovem.x	294(a0),fp0-fp7		; and data registers

short7:	frestore	78(a0)			; finally the internal state



nofpu3:

	movem.l	(a0),d0-d7/a0-a6 ; restore registers d0-d7/a0-a6

	rte			; jump back to old context



	END


unix.superglobalmegacorp.com

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