|
|
1.1 ! root 1: ; ! 2: ! 3: ; routines for saving/restoring user contexts ! 4: ! 5: ; ! 6: ! 7: ; long build_context(struct context *sav): ! 8: ! 9: ; Called from an interrupt handler (such as the trap #1 routine ! 10: ! 11: ; for system calls) saves the context of the interrupted ! 12: ! 13: ; routine. Assumes that no user registers have been changed ! 14: ! 15: ; since the interrupt, and that the PC and status register ! 16: ! 17: ; are still on the stack. Returns the stack pointer being used ! 18: ! 19: ; at the time of the interrupt **in register a1**. ! 20: ! 21: ; ! 22: ! 23: ; long save_context(struct context *sav): ! 24: ! 25: ; Saves the context of the calling routine in the area pointed ! 26: ! 27: ; to by sav. Save_context always returns 0 when initially called; ! 28: ! 29: ; this is so processes can (by suitably manipulating the ! 30: ! 31: ; saved registers) tell when the return from save_context is ! 32: ! 33: ; actually caused by restoring the context, e.g.: ! 34: ! 35: ; if (save_context(sav) == 0) { <<-- L1 ! 36: ! 37: ; /* do some stuff */ ! 38: ! 39: ; sav.regs[D0] = 1; /* for restore context */ ! 40: ! 41: ; restore_context(sav); /* goes back to L1 */ ! 42: ! 43: ; } ! 44: ! 45: ; else /* this is the second time through */ ! 46: ! 47: ; ! 48: ! 49: ; void restore_context(struct context *sav): ! 50: ! 51: ; Restores a context previously saved by build_context or save_context. ! 52: ! 53: ; Since the program counter is part of the context, this function ! 54: ! 55: ; will never return (it's like longjmp()). ! 56: ! 57: ; ! 58: ! 59: ; $Log: context.s,v $ ! 60: ! 61: ; Revision 1.6 1992/03/31 14:02:08 AGK ! 62: ! 63: ; Fixed for real Motorola syntax (many thanks to ERS for keeping these ! 64: ! 65: ; files in step with the GAS ones). ! 66: ! 67: ; ! 68: ! 69: ; Revision 1.5 1992/03/31 13:55:28 AGK ! 70: ! 71: ; Checked in MiNT 0.93 sources ! 72: ! 73: ; ! 74: ! 75: ; Revision 1.4 1991/05/31 15:55:00 AGK ! 76: ! 77: ; Tested only a byte in the save frame, not a word (my mistake). Bumped FPU ! 78: ! 79: ; frame size up to 216 bytes, the 68882 manual is wrong (thanks Motorola!) ! 80: ! 81: ; ! 82: ! 83: ; Revision 1.3 1991/05/31 09:58:44 AGK ! 84: ! 85: ; Fixed stack frame format manipulation so we use d1, not d0, which is ! 86: ! 87: ; needed later for super/user mode determination. ! 88: ! 89: ; ! 90: ! 91: ; Revision 1.2 1991/05/31 09:48:06 AGK ! 92: ! 93: ; Changes to accomodate longer stack frames etc. ! 94: ! 95: ; ! 96: ! 97: ; Revision 1.1 1991/05/30 17:22:02 AGK ! 98: ! 99: ; Initial revision ! 100: ! 101: ; ! 102: ! 103: SECTION TEXT ! 104: ! 105: ! 106: ! 107: XDEF _build_context ! 108: ! 109: XDEF _save_context ! 110: ! 111: XDEF _restore_context ! 112: ! 113: XREF _fpu ! 114: ! 115: XREF _m68010 ! 116: ! 117: ! 118: ! 119: _build_context: ! 120: ! 121: move.l a0,-(sp) ; save a0; we'll use it for scratch ! 122: ! 123: move.l 8(sp),a0 ; get address of save area ! 124: ! 125: ! 126: ! 127: ; if running with a true coprocessor we need to save the FPU state ! 128: ! 129: ! 130: ! 131: tst.w _fpu ; is there a true FPU in the system ! 132: ! 133: beq.s nofpu ! 134: ! 135: fsave 78(a0) ; save internal state frame ! 136: ! 137: tst.b 78(a0) ; if NULL frame then the FPU is not in use ! 138: ! 139: beq.s nofpu ; skip programmer's model save ! 140: ! 141: fmovem.x fp0-fp7,294(a0) ; save data registers ! 142: ! 143: fmovem.l fpcr/fpsr/fpiar,390(a0) ; and control registers ! 144: ! 145: nofpu: ! 146: ! 147: movem.l d0-d7/a0-a6,(a0) ; save registers D0-D7/A0-A6 ! 148: ! 149: move.l 14(sp),66(a0) ; save PC of context ! 150: ! 151: move.w 12(sp),d0 ; get SR of context ! 152: ! 153: move.w d0,64(a0) ; save it ! 154: ! 155: tst.w ($59e).w ; test longframe (AKP) ! 156: ! 157: beq.s short1 ; short ! 158: ! 159: lea 20(sp),a1 ; else long ! 160: ! 161: ! 162: ! 163: move.w 18(sp),d1 ; fetch frame format word ! 164: ! 165: move.w d1,402(a0) ; and stash it away for later ! 166: ! 167: tst.w _m68010 ; are we on a 68010? ! 168: ! 169: bne.s short2 ; yes -- so it's a simple interrupt frame ! 170: ! 171: ; note: in order to have got to this point in the code we must be ! 172: ! 173: ; running on an 020/030 hence we can use the extra processor instructions ! 174: ! 175: bftst d1{16:4} ; is it the simple interrupt frame ? ! 176: ! 177: beq.s short2 ; yes so just dump the stack contents ! 178: ! 179: movem.l (a1)+,d1-d3 ; instruction address/4 internal words ! 180: ! 181: movem.l d1-d3,404(a0) ! 182: ! 183: bra.s short2 ! 184: ! 185: short1: ! 186: ! 187: lea 18(sp),a1 ; save supervisor stack pointer ! 188: ! 189: short2: ; note that it should be pointing above the PC ! 190: ! 191: move.l a1,70(a0) ! 192: ! 193: move.l usp,a1 ; save user stack pointer ! 194: ! 195: move.l a1,60(a0) ! 196: ! 197: btst #13,d0 ; check for supervisor mode ! 198: ! 199: beq.s L_CONT1 ; user mode; we already have stack in a1 ! 200: ! 201: L_SUPER1: ! 202: ! 203: ; note: this was lea a0@(18), but moving from the save state buffer ! 204: ! 205: ; means not testing longframe again. (AKP) ! 206: ! 207: move.l 70(a0),a1 ; was using super stack pointer before interrupt ! 208: ! 209: ; ! 210: ! 211: L_CONT1: ! 212: ! 213: move.l ($408).w,74(a0) ; save GEMDOS terminate vector ! 214: ! 215: move.l (sp)+,32(a0) ; save old register a0 ! 216: ! 217: rts ! 218: ! 219: ! 220: ! 221: _save_context: ! 222: ! 223: move.l a0,-(sp) ; save a0 ! 224: ! 225: move.l 8(sp),a0 ; get address of context save area ! 226: ! 227: ! 228: ! 229: ; if running with a true coprocessor we need to save the FPU state ! 230: ! 231: ! 232: ! 233: tst.w _fpu ; is there a true FPU in the system ! 234: ! 235: beq.s nofpu2 ! 236: ! 237: fsave 78(a0) ; save internal state frame ! 238: ! 239: tst.b 78(a0) ; if NULL frame then the FPU is not in use ! 240: ! 241: beq.s nofpu2 ; skip programmer's model save ! 242: ! 243: fmovem.x fp0-fp7,294(a0) ; save data registers ! 244: ! 245: fmovem.l fpcr/fpsr/fpiar,390(a0) ; and control registers ! 246: ! 247: nofpu2: ! 248: ! 249: ; note: I am somewhat unsure of this assumption, viz that save_context ! 250: ! 251: ; can never be called in a situation where a co-processor ! 252: ! 253: ; mid-instruction stack frame would be required. I suspect this is a ! 254: ! 255: ; valid assumption, in which case the above FPU code is redundant, the ! 256: ! 257: ; next line is not however! ! 258: ! 259: ! 260: ! 261: clr.w 402(a0) ; mark as a 4 word stack frame ! 262: ! 263: ! 264: ! 265: movem.l d0-d7/a0-a6,(a0) ; save D0-D7/A0-A6 ! 266: ! 267: lea 8(sp),a1 ! 268: ! 269: move.l a1,70(a0) ; save supervisor stack pointer ! 270: ! 271: ; note that it should be pointing above the PC ! 272: ! 273: move.l -4(a1),66(a0) ; save PC ! 274: ! 275: move.l usp,a1 ! 276: ! 277: move.l a1,60(a0) ; save user stack pointer ! 278: ! 279: move.w sr,d0 ! 280: ! 281: move.w d0,64(a0) ; save status register ! 282: ! 283: move.l ($408).w,74(a0) ; save GEMDOS terminate vector ! 284: ! 285: move.l (sp)+,32(a0) ; save old a0 ! 286: ! 287: moveq.l #0,d0 ; return 0 ! 288: ! 289: rts ! 290: ! 291: ! 292: ! 293: _restore_context: ! 294: ! 295: ori.w #$0700,sr ; mask interrupts ! 296: ! 297: move.l 4(sp),a0 ; address of context save area ! 298: ! 299: move.l 70(a0),sp ; supervisor stack pointer ! 300: ! 301: move.l 60(a0),a1 ! 302: ! 303: move.l a1,usp ; set user stack pointer ! 304: ! 305: move.l 74(a0),($408).w ; restore GEMDOS terminate vector ! 306: ! 307: ! 308: ! 309: tst.w ($59e).w ; test longframe (AKP) ! 310: ! 311: beq.s short3 ! 312: ! 313: ! 314: ! 315: move.w 402(a0),d0 ; fetch frame format word ! 316: ! 317: tst.w _m68010 ! 318: ! 319: bne.s just0 ! 320: ! 321: ! 322: ! 323: ; again, we reach here only on an 020/030 ! 324: ! 325: ! 326: ! 327: bftst d0{16:4} ; is it the simple interrupt frame ? ! 328: ! 329: beq.s just0 ; yes so just push a zero ! 330: ! 331: movem.l 404(a0),d1-d3 ; saved instruction address/4 internal words ! 332: ! 333: movem.l d1-d3,-(sp) ! 334: ! 335: just0: move.w d0,-(sp) ! 336: ! 337: ! 338: ! 339: short3: ! 340: ! 341: move.l 66(a0),-(sp) ; push the PC ! 342: ! 343: move.w 64(a0),d0 ; get status register ! 344: ! 345: move.w d0,-(sp) ; push the status register ! 346: ! 347: ! 348: ! 349: ; if running with a true coprocessor we need to restore the FPU state ! 350: ! 351: ! 352: ! 353: tst.w _fpu ; is there a true FPU in the system ! 354: ! 355: beq.s nofpu3 ! 356: ! 357: tst.b 78(a0) ; if NULL frame then the FPU is not in use ! 358: ! 359: beq.s short7 ; skip programmer's model restore ! 360: ! 361: fmovem.l 390(a0),fpcr/fpsr/fpiar ; restore control registers ! 362: ! 363: fmovem.x 294(a0),fp0-fp7 ; and data registers ! 364: ! 365: short7: frestore 78(a0) ; finally the internal state ! 366: ! 367: ! 368: ! 369: nofpu3: ! 370: ! 371: movem.l (a0),d0-d7/a0-a6 ; restore registers d0-d7/a0-a6 ! 372: ! 373: rte ; jump back to old context ! 374: ! 375: ! 376: ! 377: END ! 378:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.