|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.