home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
mint
/
mint095s
/
context.s
< prev
next >
Wrap
Text File
|
1993-08-03
|
6KB
|
161 lines
|
| 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