|
|
1.1 ! root 1: %include "magic.i" ! 2: ! 3: ; ! 4: ! 5: ; routines for saving/restoring user contexts ! 6: ! 7: ; ! 8: ! 9: ; long build_context(struct context *sav, short fmt): ! 10: ! 11: ; Called from an interrupt handler (such as the trap #1 routine ! 12: ! 13: ; for system calls) saves the context of the interrupted ! 14: ! 15: ; routine. Assumes that no user registers have been changed ! 16: ! 17: ; since the interrupt, and that the PC and status register ! 18: ! 19: ; are still on the stack. Returns the stack pointer being used ! 20: ! 21: ; at the time of the interrupt **in register a1**. ! 22: ! 23: ; The fmt parameter is used on the 68000 to communicate the exception ! 24: ! 25: ; vector number; on >=68010 we use the vector offset from the frame. ! 26: ! 27: ; ! 28: ! 29: ; long save_context(struct context *sav): ! 30: ! 31: ; Saves the context of the calling routine in the area pointed ! 32: ! 33: ; to by sav. Save_context always returns 0 when initially called; ! 34: ! 35: ; this is so processes can (by suitably manipulating the ! 36: ! 37: ; saved registers) tell when the return from save_context is ! 38: ! 39: ; actually caused by restoring the context, e.g.: ! 40: ! 41: ; if (save_context(sav) == 0) { <<-- L1 ! 42: ! 43: ; /* do some stuff */ ! 44: ! 45: ; sav.regs[D0] = 1; /* for restore context */ ! 46: ! 47: ; restore_context(sav); /* goes back to L1 */ ! 48: ! 49: ; } ! 50: ! 51: ; else /* this is the second time through */ ! 52: ! 53: ; ! 54: ! 55: ; void restore_context(struct context *sav): ! 56: ! 57: ; Restores a context previously saved by build_context or save_context. ! 58: ! 59: ; Since the program counter is part of the context, this function ! 60: ! 61: ; will never return (it's like longjmp()). ! 62: ! 63: ; ! 64: ! 65: TEXT ! 66: ! 67: ! 68: ! 69: XDEF _build_context ! 70: ! 71: XDEF _save_context ! 72: ! 73: XDEF _restore_context ! 74: ! 75: XREF _fpu ! 76: ! 77: XREF _framesizes ! 78: ! 79: XREF _new_trace ; from intr.s ! 80: ! 81: ! 82: ! 83: _build_context: ! 84: ! 85: move.l a0,-(sp) ; save a0; we'll use it for scratch ! 86: ! 87: move.l 8(sp),a0 ; get address of save area ! 88: ! 89: movem.l d0-d7/a0-a6,(a0) ; save registers D0-D7/A0-A6 ! 90: ! 91: clr.b C_PTRACE(a0) ; no pending traces, thanks! ! 92: ! 93: lea 12(sp),a1 ; start of the interesting stack area ! 94: ! 95: move.w (a1)+,d0 ; 68000 fake frame format ! 96: ! 97: move.w ($59e).w,d7 ; get process frame flag ! 98: ! 99: bne.s nojunk ; we have some junk on the stack ! 100: ! 101: move.w d0,C_SFMT(a0) ; save fake frame format ! 102: ! 103: cmp.w #$8,d0 ; if bus error ! 104: ! 105: beq.s group0 ! 106: ! 107: cmp.w #$c,d0 ; or address error ! 108: ! 109: bne.s nojunk ! 110: ! 111: group0: move.l (a1)+,C_INTERNAL(a0) ; stash it in the internal area ! 112: ! 113: move.l (a1)+,C_INTERNAL+4(a0) ; if a debugger's interested ! 114: ! 115: nojunk: ! 116: ! 117: move.w (a1)+,d0 ; get SR of context ! 118: ! 119: move.w d0,C_SR(a0) ; save it ! 120: ! 121: move.l (a1)+,C_PC(a0) ; save PC of context ! 122: ! 123: tst.w d7 ; test longframe (AKP) ! 124: ! 125: beq.s short1 ; short ! 126: ! 127: tst.w _fpu ; is there a true FPU in the system ! 128: ! 129: beq.s nofpu ! 130: ! 131: fsave C_FSTATE(a0) ; save internal state frame ! 132: ! 133: tst.b C_FSTATE(a0) ; if NULL frame then the FPU is not in use ! 134: ! 135: beq.s nofpu ; skip programmer's model save ! 136: ! 137: fmovem.x fp0-fp7,C_FREGS(a0) ; save data registers ! 138: ! 139: fmovem.l fpcr/fpsr/fpiar,C_FCTRL(a0) ; and control registers ! 140: ! 141: nofpu: ! 142: ! 143: lea C_SFMT(a0),a2 ! 144: ! 145: move.w (a1)+,d1 ; fetch frame format word ! 146: ! 147: move.w d1,(a2)+ ; and stash it away for later ! 148: ! 149: lsr.w #8,d1 ; isolate the frame format identifier ! 150: ! 151: lsr.w #4,d1 ! 152: ! 153: lea _framesizes,a3 ! 154: ! 155: move.b 0(a3,d1.w),d1 ! 156: ! 157: bra.s bcover ! 158: ! 159: bcint: move.w (a1)+,(a2)+ ; copy CPU internal state ! 160: ! 161: bcover: dbf d1,bcint ! 162: ! 163: short1: ! 164: ! 165: move.l a1,C_SSP(a0) ; a1 now points above the state frame ! 166: ! 167: move.l usp,a1 ; save user stack pointer ! 168: ! 169: move.l a1,C_USP(a0) ! 170: ! 171: btst #13,d0 ; check for supervisor mode ! 172: ! 173: beq.s L_CONT1 ; user mode; we already have stack in a1 ! 174: ! 175: L_SUPER1: ! 176: ! 177: ; moving from the save state buffer ! 178: ! 179: ; means not testing longframe again. (AKP) ! 180: ! 181: move.l C_SSP(a0),a1 ; was using super stack pointer before interrupt ! 182: ! 183: ; ! 184: ! 185: L_CONT1: ! 186: ! 187: move.l ($408).w,C_TERM(a0) ; save GEMDOS terminate vector ! 188: ! 189: move.l (sp)+,C_A0(a0) ; save old register a0 ! 190: ! 191: rts ! 192: ! 193: ! 194: ! 195: _save_context: ! 196: ! 197: move.l a0,-(sp) ; save a0 ! 198: ! 199: move.l 8(sp),a0 ; get address of context save area ! 200: ! 201: ! 202: ! 203: ; if running with a true coprocessor we need to save the FPU state ! 204: ! 205: tst.w _fpu ; is there a true FPU in the system ! 206: ! 207: beq.s nofpu2 ! 208: ! 209: fsave C_FSTATE(a0) ; save internal state frame ! 210: ! 211: tst.b C_FSTATE(a0) ; if NULL frame then the FPU is not in use ! 212: ! 213: beq.s nofpu2 ; skip programmer's model save ! 214: ! 215: fmovem.x fp0-fp7,C_FREGS(a0) ; save data registers ! 216: ! 217: fmovem.l fpcr/fpsr/fpiar,C_FCTRL(a0) ; and control registers ! 218: ! 219: nofpu2: ! 220: ! 221: ; note: I am somewhat unsure of this assumption, viz that save_context ! 222: ! 223: ; can never be called in a situation where a co-processor ! 224: ! 225: ; mid-instruction stack frame would be required. I suspect this is a ! 226: ! 227: ; valid assumption, in which case the above FPU code is redundant, the ! 228: ! 229: ; next line is not however! ! 230: ! 231: ! 232: ! 233: clr.w C_SFMT(a0) ; mark as a 4 word stack frame ! 234: ! 235: clr.b C_PTRACE(a0) ; no pending traces, thanks! ! 236: ! 237: ! 238: ! 239: movem.l d0-d7/a0-a6,(a0) ; save D0-D7/A0-A6 ! 240: ! 241: lea 8(sp),a1 ! 242: ! 243: move.l a1,C_SSP(a0) ; save supervisor stack pointer ! 244: ! 245: ; note that it should be pointing above the PC ! 246: ! 247: move.l -4(a1),C_PC(a0) ; save PC ! 248: ! 249: move.l usp,a1 ! 250: ! 251: move.l a1,C_USP(a0) ; save user stack pointer ! 252: ! 253: move.w sr,d0 ! 254: ! 255: move.w d0,C_SR(a0) ; save status register ! 256: ! 257: move.l ($408).w,C_TERM(a0) ; save GEMDOS terminate vector ! 258: ! 259: move.l (sp)+,C_A0(a0) ; save old a0 ! 260: ! 261: moveq.l #0,d0 ; return 0 ! 262: ! 263: rts ! 264: ! 265: ! 266: ! 267: _restore_context: ! 268: ! 269: ori.w #$0700,sr ; mask interrupts ! 270: ! 271: move.l 4(sp),a0 ; address of context save area ! 272: ! 273: move.l C_SSP(a0),sp ; supervisor stack pointer ! 274: ! 275: move.l C_USP(a0),a1 ! 276: ! 277: move.l a1,usp ; set user stack pointer ! 278: ! 279: move.l C_TERM(a0),($408).w ; restore GEMDOS terminate vector ! 280: ! 281: ! 282: ! 283: tst.w ($59e).w ; test longframe (AKP) ! 284: ! 285: beq.s short3 ! 286: ! 287: moveq.l #0,d0 ! 288: ! 289: lea C_SFMT(a0),a1 ! 290: ! 291: move.w (a1)+,d0 ; fetch frame format word ! 292: ! 293: move.w d0,d1 ; copy it for later ! 294: ! 295: lsr.w #8,d1 ; isolate the frame format identifier ! 296: ! 297: lsr.w #4,d1 ! 298: ! 299: lea _framesizes,a2 ! 300: ! 301: move.b 0(a2,d1.w),d1 ! 302: ! 303: sub.w d1,sp ! 304: ! 305: sub.w d1,sp ! 306: ! 307: move.l sp,a2 ! 308: ! 309: bra.s rcover ! 310: ! 311: rcint: move.w (a1)+,(a2)+ ! 312: ! 313: rcover: dbf d1,rcint ! 314: ! 315: move.w d0,-(sp) ; frame format identifier ! 316: ! 317: ; if running with a true coprocessor we need to restore the FPU state ! 318: ! 319: ! 320: ! 321: tst.w _fpu ; is there a true FPU in the system ! 322: ! 323: beq.s short3 ! 324: ! 325: tst.b C_FSTATE(a0) ; if NULL frame then the FPU is not in use ! 326: ! 327: beq.s short7 ; skip programmer's model restore ! 328: ! 329: fmovem.l C_FCTRL(a0),fpcr/fpsr/fpiar ; restore control registers ! 330: ! 331: fmovem.x C_FREGS(a0),fp0-fp7 ; and data registers ! 332: ! 333: short7: frestore C_FSTATE(a0) ; finally the internal state ! 334: ! 335: short3: ! 336: ! 337: move.l C_PC(a0),-(sp) ; push the PC ! 338: ! 339: move.w C_SR(a0),d0 ; fetch status register ! 340: ! 341: move.w d0,-(sp) ; push the status register ! 342: ! 343: tst.b C_PTRACE(a0) ; check for a pending trace ! 344: ! 345: movem.l (a0),d0-d7/a0-a6 ; restore registers d0-d7/a0-a6 ! 346: ! 347: beq.s notrace ! 348: ! 349: jmp _new_trace ! 350: ! 351: notrace: ! 352: ! 353: rte ; jump back to old context ! 354: ! 355: ! 356: ! 357: END ! 358:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.