File:  [Atari MiNT] / MiNT / src / gas / 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()).



	.globl	_build_context

	.globl 	_save_context

	.globl	_restore_context

	.globl	_fpu

	.globl	_m68010



_build_context:

	movel	a0, sp@-	| save a0; we'll use it for scratch

	movel	sp@(8), a0	| get address of save area

	tstw	_fpu		| is there a real FPU in the system?

	beq	nofpu		| no -- we can skip the FPU save

	fsave	a0@(78)		| save internal state frame

	tstb	a0@(78)		| if NULL frame then FPU not in use

	beq	nofpu

	fmovemx	fp0-fp7,a0@(294)		| save data registers

	fmoveml	fpcr/fpsr/fpi,a0@(390)	| and control registers

nofpu:

	moveml	d0-d7/a0-a6, a0@ | save registers D0-D7/A0-A6

	movel	sp@(14), a0@(66) | save PC of context

	movew	sp@(12), d0	| get SR of context

	movew	d0, a0@(64)	| save it 

	tstw	0x59e		| test longframe (AKP)

	beq	short1		| short

	lea	sp@(20), a1	| else long

	movew	sp@(18), d1	| fetch frame format word

	movew	d1, a0@(402)	| stash it away for later

	tstw	_m68010		| are we running on a 68010?

	bne	short2		| yes -- definitely a simple interrupt frame

|

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

| running on an 020/030

|

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

	beq	short2		| yes -- just dump the stack contents

	moveml	a1@+, d1-d3	| get instruction address/4 internal words

	moveml	d1-d3, a0@(404)	| save them

	bra	short2

short1:

	lea	sp@(18), a1	| save supervisor stack pointer

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

	movel	a1, a0@(70)

	movel	usp, a1		| save user stack pointer

	movel	a1, a0@(60)

	btst	#13, d0		| check for supervisor mode

	beq	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)

	movel	a0@(70), a1	| was using super stack pointer before interrupt

				| 

L_CONT1:

	movel	0x408, a0@(74)	| save GEMDOS terminate vector

	movel	sp@+, a0@(32)	| save old register a0

	rts



_save_context:

	movel	a0, sp@-	| save a0

	movel	sp@(8), a0	| get address of context save area



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



	tstw	_fpu		| is there a true FPU in the system

	beq	nofpu2

	fsave	a0@(78)		| save internal state frame

	tstb	a0@(78)		| if NULL frame then the FPU is not in use

	beq	nofpu2		| skip programmer's model save

	fmovemx	fp0-fp7,a0@(294)		| save data registers

	fmoveml	fpcr/fpsr/fpi,a0@(390)	| and control registers

nofpu2:

| AGK: 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!



	clrw	a0@(402)		| mark as a 4 word stack frame



	moveml	d0-d7/a0-a6, a0@	| save D0-D7/A0-A6

	lea	sp@(8), a1

	movel	a1, a0@(70)	| save supervisor stack pointer

				| note that it should be pointing above the PC

	movel	a1@(-4), a0@(66)	| save PC

	movel	usp, a1

	movel	a1, a0@(60)	| save user stack pointer

	movew	sr, d0

	movew	d0, a0@(64)	| save status register

	movel	0x408, a0@(74)	| save GEMDOS terminate vector

	movel	sp@+, a0@(32)	| save old a0

	moveql	#0, d0		| return 0

	rts



_restore_context:

	orw	#0x0700, sr	| mask interrupts

	movel	sp@(4), a0	| address of context save area

	movel	a0@(70), sp	| supervisor stack pointer

	movel	a0@(60), a1

	movel	a1, usp		| set user stack pointer

	movel	a0@(74), 0x408	| restore GEMDOS terminate vector



	tstw	0x59e		| test longframe (AKP)

	beq	short3



	movew	a0@(402),d0	| fetch frame format word

	tstw	_m68010		| are we on a 68010?

	bne	just0		| yes, so it's a simple interrupt frame



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

	beq	just0		| yes so just push a zero

	moveml	a0@(404),d1-d3	| saved instruction address/4 internal words

	moveml	d1-d3,sp@-

just0:	movew	d0,sp@-



short3:

	movel	a0@(66), sp@-	| push the PC

	movew	a0@(64), d0	| get status register

	movew	d0, sp@-	| push the status register



| if running with a true co-processor we need to restore the FPU state



	tstw	_fpu

	beq	nofpu3

	tstb	a0@(78)			| if NULL frame then FPU not in use

	beq	short7			| skip programmer's model restore

	fmoveml	a0@(390), fpcr/fpsr/fpi	| restore control registers

	fmovemx	a0@(294), fp0-fp7		| and data registers

short7: frestore a0@(78)			| finally the internal state



nofpu3:

	moveml	a0@, d0-d7/a0-a6 	| restore registers d0-d7/a0-a6

	rte				| jump back to old context




unix.superglobalmegacorp.com

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