|
|
1.1.1.2 ! root 1: ; ! 2: ! 3: ; Copyright 1992 Eric R. Smith ! 4: ! 5: ; Copyright 1992 Atari Corporation ! 6: ! 7: ; All rights reserved. ! 8: ! 9: ! 10: 1.1 root 11: %include "magic.i" 12: 13: ; 14: 15: ; routines for saving/restoring user contexts 16: 17: ; 18: 19: ; long build_context(struct context *sav, short fmt): 20: 21: ; Called from an interrupt handler (such as the trap #1 routine 22: 23: ; for system calls) saves the context of the interrupted 24: 25: ; routine. Assumes that no user registers have been changed 26: 27: ; since the interrupt, and that the PC and status register 28: 29: ; are still on the stack. Returns the stack pointer being used 30: 31: ; at the time of the interrupt **in register a1**. 32: 33: ; The fmt parameter is used on the 68000 to communicate the exception 34: 35: ; vector number; on >=68010 we use the vector offset from the frame. 36: 37: ; 38: 39: ; long save_context(struct context *sav): 40: 41: ; Saves the context of the calling routine in the area pointed 42: 43: ; to by sav. Save_context always returns 0 when initially called; 44: 45: ; this is so processes can (by suitably manipulating the 46: 47: ; saved registers) tell when the return from save_context is 48: 49: ; actually caused by restoring the context, e.g.: 50: 51: ; if (save_context(sav) == 0) { <<-- L1 52: 53: ; /* do some stuff */ 54: 55: ; sav.regs[D0] = 1; /* for restore context */ 56: 57: ; restore_context(sav); /* goes back to L1 */ 58: 59: ; } 60: 61: ; else /* this is the second time through */ 62: 63: ; 64: 65: ; void restore_context(struct context *sav): 66: 67: ; Restores a context previously saved by build_context or save_context. 68: 69: ; Since the program counter is part of the context, this function 70: 1.1.1.2 ! root 71: ; will never return (it's like longjmp()). NOTE: this function should ! 72: ! 73: ; be used only to change contexts _within_ the same program, since ! 74: ! 75: ; it does NOT flush the ATC. See change_context 1.1 root 76: 77: ; 78: 1.1.1.2 ! root 79: ; void change_context(struct context *sav): ! 80: ! 81: ; Restores a context previously saved by build_context or save_context ! 82: ! 83: ; for a different process. Unlike restore_context, this one *does* ! 84: ! 85: ; flush the ATC. ! 86: ! 87: ! 88: 1.1 root 89: TEXT 90: 91: 92: 93: XDEF _build_context 94: 95: XDEF _save_context 96: 97: XDEF _restore_context 98: 1.1.1.2 ! root 99: XDEF _change_context ! 100: ! 101: XDEF _set_mmu ! 102: ! 103: ! 104: 1.1 root 105: XREF _fpu 106: 107: XREF _framesizes 108: 109: XREF _new_trace ; from intr.s 110: 1.1.1.2 ! root 111: XREF _no_mem_prot ! 112: ! 113: ; ! 114: ! 115: ; set_mmu(crp,tc): called once, the first time a page table is built, to ! 116: ! 117: ; switch away from the MMU setup that came from the ROM and into the setup ! 118: ! 119: ; that we just built. The CRP is actually on the stack, and it's 8 bytes. ! 120: ! 121: ; The TC is four bytes at sp@(0xc). "Nulls" is here because we need to ! 122: ! 123: ; shove zeros into a few places. ! 124: ! 125: ; ! 126: ! 127: ; nulltc is in the data segment because otherwise GAS assembles PC-relative ! 128: ! 129: ; and that's not legal on 68030. ! 130: ! 131: ; ! 132: ! 133: DATA ! 134: ! 135: nulltc: dc.l 0 ! 136: ! 137: ! 138: ! 139: TEXT ! 140: ! 141: _set_mmu: ! 142: ! 143: pmove nulltc,tc ; turn off mmu ! 144: ! 145: dc.l $f0390800,nulltc ; pmove nulltc,tt0 ! 146: ! 147: dc.l $f0390c00,nulltc ; pmove nulltc,tt1 ! 148: ! 149: pmove 4(sp),crp ; caution: crp is 8 bytes ! 150: ! 151: pmove $c(sp),tc ! 152: ! 153: rts ! 154: ! 155: 1.1 root 156: 157: _build_context: 158: 159: move.l a0,-(sp) ; save a0; we'll use it for scratch 160: 161: move.l 8(sp),a0 ; get address of save area 162: 1.1.1.2 ! root 163: ! 164: ! 165: tst.w _no_mem_prot ; is there memory protection? ! 166: ! 167: bne.s noprot1 ! 168: ! 169: pmove crp,C_CRP(a0) ; save CRP from MMU ! 170: ! 171: pmove tc,C_TC(a0) ; save TC from MMU ! 172: ! 173: noprot1: ! 174: 1.1 root 175: movem.l d0-d7/a0-a6,(a0) ; save registers D0-D7/A0-A6 176: 177: clr.b C_PTRACE(a0) ; no pending traces, thanks! 178: 179: lea 12(sp),a1 ; start of the interesting stack area 180: 181: move.w (a1)+,d0 ; 68000 fake frame format 182: 1.1.1.2 ! root 183: ! 184: ! 185: %ifndef ONLY030 ! 186: 1.1 root 187: move.w ($59e).w,d7 ; get process frame flag 188: 189: bne.s nojunk ; we have some junk on the stack 190: 191: move.w d0,C_SFMT(a0) ; save fake frame format 192: 193: cmp.w #$8,d0 ; if bus error 194: 195: beq.s group0 196: 197: cmp.w #$c,d0 ; or address error 198: 199: bne.s nojunk 200: 201: group0: move.l (a1)+,C_INTERNAL(a0) ; stash it in the internal area 202: 203: move.l (a1)+,C_INTERNAL+4(a0) ; if a debugger's interested 204: 205: nojunk: 206: 1.1.1.2 ! root 207: %endif ! 208: 1.1 root 209: move.w (a1)+,d0 ; get SR of context 210: 211: move.w d0,C_SR(a0) ; save it 212: 213: move.l (a1)+,C_PC(a0) ; save PC of context 214: 1.1.1.2 ! root 215: %ifndef ONLY030 ! 216: 1.1 root 217: tst.w d7 ; test longframe (AKP) 218: 219: beq.s short1 ; short 220: 1.1.1.2 ! root 221: %endif ! 222: 1.1 root 223: tst.w _fpu ; is there a true FPU in the system 224: 225: beq.s nofpu 226: 227: fsave C_FSTATE(a0) ; save internal state frame 228: 229: tst.b C_FSTATE(a0) ; if NULL frame then the FPU is not in use 230: 231: beq.s nofpu ; skip programmer's model save 232: 233: fmovem.x fp0-fp7,C_FREGS(a0) ; save data registers 234: 235: fmovem.l fpcr/fpsr/fpiar,C_FCTRL(a0) ; and control registers 236: 237: nofpu: 238: 239: lea C_SFMT(a0),a2 240: 241: move.w (a1)+,d1 ; fetch frame format word 242: 243: move.w d1,(a2)+ ; and stash it away for later 244: 245: lsr.w #8,d1 ; isolate the frame format identifier 246: 247: lsr.w #4,d1 248: 249: lea _framesizes,a3 250: 251: move.b 0(a3,d1.w),d1 252: 253: bra.s bcover 254: 255: bcint: move.w (a1)+,(a2)+ ; copy CPU internal state 256: 257: bcover: dbf d1,bcint 258: 259: short1: 260: 261: move.l a1,C_SSP(a0) ; a1 now points above the state frame 262: 263: move.l usp,a1 ; save user stack pointer 264: 265: move.l a1,C_USP(a0) 266: 267: btst #13,d0 ; check for supervisor mode 268: 269: beq.s L_CONT1 ; user mode; we already have stack in a1 270: 271: L_SUPER1: 272: 273: ; moving from the save state buffer 274: 275: ; means not testing longframe again. (AKP) 276: 277: move.l C_SSP(a0),a1 ; was using super stack pointer before interrupt 278: 279: ; 280: 281: L_CONT1: 282: 283: move.l ($408).w,C_TERM(a0) ; save GEMDOS terminate vector 284: 285: move.l (sp)+,C_A0(a0) ; save old register a0 286: 287: rts 288: 289: 290: 1.1.1.2 ! root 291: ! 292: 1.1 root 293: _save_context: 294: 295: move.l a0,-(sp) ; save a0 296: 297: move.l 8(sp),a0 ; get address of context save area 298: 299: 300: 1.1.1.2 ! root 301: tst.w _no_mem_prot ! 302: ! 303: bne.s noprot2 ! 304: ! 305: pmove crp,C_CRP(a0) ; save the CRP from the MMU ! 306: ! 307: pmove tc,C_TC(a0) ; save the TC from the MMU ! 308: ! 309: noprot2: ! 310: ! 311: ! 312: 1.1 root 313: ; if running with a true coprocessor we need to save the FPU state 314: 315: tst.w _fpu ; is there a true FPU in the system 316: 317: beq.s nofpu2 318: 319: fsave C_FSTATE(a0) ; save internal state frame 320: 321: tst.b C_FSTATE(a0) ; if NULL frame then the FPU is not in use 322: 323: beq.s nofpu2 ; skip programmer's model save 324: 325: fmovem.x fp0-fp7,C_FREGS(a0) ; save data registers 326: 327: fmovem.l fpcr/fpsr/fpiar,C_FCTRL(a0) ; and control registers 328: 329: nofpu2: 330: 331: ; note: I am somewhat unsure of this assumption, viz that save_context 332: 333: ; can never be called in a situation where a co-processor 334: 335: ; mid-instruction stack frame would be required. I suspect this is a 336: 337: ; valid assumption, in which case the above FPU code is redundant, the 338: 339: ; next line is not however! 340: 341: 342: 343: clr.w C_SFMT(a0) ; mark as a 4 word stack frame 344: 345: clr.b C_PTRACE(a0) ; no pending traces, thanks! 346: 347: 348: 349: movem.l d0-d7/a0-a6,(a0) ; save D0-D7/A0-A6 350: 351: lea 8(sp),a1 352: 353: move.l a1,C_SSP(a0) ; save supervisor stack pointer 354: 355: ; note that it should be pointing above the PC 356: 357: move.l -4(a1),C_PC(a0) ; save PC 358: 359: move.l usp,a1 360: 361: move.l a1,C_USP(a0) ; save user stack pointer 362: 363: move.w sr,d0 364: 365: move.w d0,C_SR(a0) ; save status register 366: 367: move.l ($408).w,C_TERM(a0) ; save GEMDOS terminate vector 368: 369: move.l (sp)+,C_A0(a0) ; save old a0 370: 371: moveq.l #0,d0 ; return 0 372: 373: rts 374: 375: 376: 377: _restore_context: 378: 379: ori.w #$0700,sr ; mask interrupts 380: 381: move.l 4(sp),a0 ; address of context save area 382: 1.1.1.2 ! root 383: ! 384: ! 385: ; Switch stacks now - starting now ssp is in the memory space of ! 386: ! 387: ; the process we're switching to. Thus, we can change memory context ! 388: ! 389: ; to there. ! 390: ! 391: ! 392: 1.1 root 393: move.l C_SSP(a0),sp ; supervisor stack pointer 394: 395: move.l C_USP(a0),a1 396: 397: move.l a1,usp ; set user stack pointer 398: 399: move.l C_TERM(a0),($408).w ; restore GEMDOS terminate vector 400: 401: 402: 1.1.1.2 ! root 403: ; Set memory context now: actually, this isn't necessary, since ! 404: ! 405: ; we're coming back to a context in the same process as is running ! 406: ! 407: ; now. ! 408: ! 409: ; tst.w _no_mem_prot ! 410: ! 411: ; bne.s noprot3 ! 412: ! 413: ; pmove C_CRP(a0),crp ; restore MMU root pointer ! 414: ! 415: ; pmove C_TC(a0),tc ; restore MMU control register ! 416: ! 417: noprot3: ! 418: ! 419: ! 420: ! 421: %ifndef ONLY030 ! 422: 1.1 root 423: tst.w ($59e).w ; test longframe (AKP) 424: 425: beq.s short3 426: 1.1.1.2 ! root 427: %endif ! 428: ! 429: ; was moveq.l #0,d0, but I don't think that's what was desired */ ! 430: ! 431: moveq.l #0,d1 1.1 root 432: 433: lea C_SFMT(a0),a1 434: 435: move.w (a1)+,d0 ; fetch frame format word 436: 437: move.w d0,d1 ; copy it for later 438: 439: lsr.w #8,d1 ; isolate the frame format identifier 440: 441: lsr.w #4,d1 442: 443: lea _framesizes,a2 444: 445: move.b 0(a2,d1.w),d1 446: 447: sub.w d1,sp 448: 449: sub.w d1,sp 450: 451: move.l sp,a2 452: 453: bra.s rcover 454: 455: rcint: move.w (a1)+,(a2)+ 456: 457: rcover: dbf d1,rcint 458: 459: move.w d0,-(sp) ; frame format identifier 460: 461: ; if running with a true coprocessor we need to restore the FPU state 462: 463: 464: 465: tst.w _fpu ; is there a true FPU in the system 466: 467: beq.s short3 468: 469: tst.b C_FSTATE(a0) ; if NULL frame then the FPU is not in use 470: 1.1.1.2 ! root 471: beq.s short4 ; skip programmer's model restore 1.1 root 472: 473: fmovem.l C_FCTRL(a0),fpcr/fpsr/fpiar ; restore control registers 474: 475: fmovem.x C_FREGS(a0),fp0-fp7 ; and data registers 476: 1.1.1.2 ! root 477: short4: frestore C_FSTATE(a0) ; finally the internal state 1.1 root 478: 479: short3: 480: 481: move.l C_PC(a0),-(sp) ; push the PC 482: 483: move.w C_SR(a0),d0 ; fetch status register 484: 485: move.w d0,-(sp) ; push the status register 486: 487: tst.b C_PTRACE(a0) ; check for a pending trace 488: 489: movem.l (a0),d0-d7/a0-a6 ; restore registers d0-d7/a0-a6 490: 491: beq.s notrace 492: 493: jmp _new_trace 494: 495: notrace: 496: 497: rte ; jump back to old context 498: 499: 500: 1.1.1.2 ! root 501: ! 502: ! 503: _change_context: ! 504: ! 505: ori.w #$0700,sr ; mask interrupts ! 506: ! 507: move.l 4(sp),a0 ; address of context save area ! 508: ! 509: ! 510: ! 511: ; Switch stacks now - starting now ssp is in the memory space of ! 512: ! 513: ; the process we're switching to. Thus, we can change memory context ! 514: ! 515: ; to there. ! 516: ! 517: ! 518: ! 519: move.l C_SSP(a0),sp ; supervisor stack pointer ! 520: ! 521: move.l C_USP(a0),a1 ! 522: ! 523: move.l a1,usp ; set user stack pointer ! 524: ! 525: move.l C_TERM(a0),($408).w ; restore GEMDOS terminate vector ! 526: ! 527: ! 528: ! 529: ; Set memory context now ! 530: ! 531: tst.w _no_mem_prot ! 532: ! 533: bne.s noprot4 ! 534: ! 535: pmove C_CRP(a0),crp ; restore MMU root pointer ! 536: ! 537: pmove C_TC(a0),tc ; restore MMU control register ! 538: ! 539: noprot4: ! 540: ! 541: %ifndef ONLY030 ! 542: ! 543: tst.w ($59e).w ; test longframe (AKP) ! 544: ! 545: beq.s short6 ! 546: ! 547: %endif ! 548: ! 549: ; was moveq.l #0,d0, but I don't think that's what was desired */ ! 550: ! 551: moveq.l #0,d1 ! 552: ! 553: lea C_SFMT(a0),a1 ! 554: ! 555: move.w (a1)+,d0 ; fetch frame format word ! 556: ! 557: move.w d0,d1 ; copy it for later ! 558: ! 559: lsr.w #8,d1 ; isolate the frame format identifier ! 560: ! 561: lsr.w #4,d1 ! 562: ! 563: lea _framesizes,a2 ! 564: ! 565: move.b 0(a2,d1.w),d1 ! 566: ! 567: sub.w d1,sp ! 568: ! 569: sub.w d1,sp ! 570: ! 571: move.l sp,a2 ! 572: ! 573: bra.s rcover2 ! 574: ! 575: rcint2: move.w (a1)+,(a2)+ ! 576: ! 577: rcover2: dbf d1,rcint2 ! 578: ! 579: move.w d0,-(sp) ; frame format identifier ! 580: ! 581: ; if running with a true coprocessor we need to restore the FPU state ! 582: ! 583: ! 584: ! 585: tst.w _fpu ; is there a true FPU in the system ! 586: ! 587: beq.s short3 ! 588: ! 589: tst.b C_FSTATE(a0) ; if NULL frame then the FPU is not in use ! 590: ! 591: beq.s short5 ; skip programmer's model restore ! 592: ! 593: fmovem.l C_FCTRL(a0),fpcr/fpsr/fpiar ; restore control registers ! 594: ! 595: fmovem.x C_FREGS(a0),fp0-fp7 ; and data registers ! 596: ! 597: short5: frestore C_FSTATE(a0) ; finally the internal state ! 598: ! 599: short6: ! 600: ! 601: move.l C_PC(a0),-(sp) ; push the PC ! 602: ! 603: move.w C_SR(a0),d0 ; fetch status register ! 604: ! 605: move.w d0,-(sp) ; push the status register ! 606: ! 607: tst.b C_PTRACE(a0) ; check for a pending trace ! 608: ! 609: movem.l (a0),d0-d7/a0-a6 ; restore registers d0-d7/a0-a6 ! 610: ! 611: beq.s notrace2 ! 612: ! 613: jmp _new_trace ! 614: ! 615: notrace2: ! 616: ! 617: rte ; jump back to old context ! 618: ! 619: ! 620: 1.1 root 621: END 622:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.