|
|
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: .globl _build_context ! 60: ! 61: .globl _save_context ! 62: ! 63: .globl _restore_context ! 64: ! 65: .globl _fpu ! 66: ! 67: .globl _m68010 ! 68: ! 69: ! 70: ! 71: _build_context: ! 72: ! 73: movel a0, sp@- | save a0; we'll use it for scratch ! 74: ! 75: movel sp@(8), a0 | get address of save area ! 76: ! 77: tstw _fpu | is there a real FPU in the system? ! 78: ! 79: beq nofpu | no -- we can skip the FPU save ! 80: ! 81: fsave a0@(78) | save internal state frame ! 82: ! 83: tstb a0@(78) | if NULL frame then FPU not in use ! 84: ! 85: beq nofpu ! 86: ! 87: fmovemx fp0-fp7,a0@(294) | save data registers ! 88: ! 89: fmoveml fpcr/fpsr/fpi,a0@(390) | and control registers ! 90: ! 91: nofpu: ! 92: ! 93: moveml d0-d7/a0-a6, a0@ | save registers D0-D7/A0-A6 ! 94: ! 95: movel sp@(14), a0@(66) | save PC of context ! 96: ! 97: movew sp@(12), d0 | get SR of context ! 98: ! 99: movew d0, a0@(64) | save it ! 100: ! 101: tstw 0x59e | test longframe (AKP) ! 102: ! 103: beq short1 | short ! 104: ! 105: lea sp@(20), a1 | else long ! 106: ! 107: movew sp@(18), d1 | fetch frame format word ! 108: ! 109: movew d1, a0@(402) | stash it away for later ! 110: ! 111: tstw _m68010 | are we running on a 68010? ! 112: ! 113: bne short2 | yes -- definitely a simple interrupt frame ! 114: ! 115: | ! 116: ! 117: | note: in order to have got to this point in the code we must be ! 118: ! 119: | running on an 020/030 ! 120: ! 121: | ! 122: ! 123: bftst d1{#16:#4} | is it the simple interrupt frame? ! 124: ! 125: beq short2 | yes -- just dump the stack contents ! 126: ! 127: moveml a1@+, d1-d3 | get instruction address/4 internal words ! 128: ! 129: moveml d1-d3, a0@(404) | save them ! 130: ! 131: bra short2 ! 132: ! 133: short1: ! 134: ! 135: lea sp@(18), a1 | save supervisor stack pointer ! 136: ! 137: short2: | note that it should be pointing above the PC ! 138: ! 139: movel a1, a0@(70) ! 140: ! 141: movel usp, a1 | save user stack pointer ! 142: ! 143: movel a1, a0@(60) ! 144: ! 145: btst #13, d0 | check for supervisor mode ! 146: ! 147: beq L_CONT1 | user mode; we already have stack in a1 ! 148: ! 149: L_SUPER1: ! 150: ! 151: | note: this was lea a0@(18), but moving from the save state buffer ! 152: ! 153: | means not testing longframe again. (AKP) ! 154: ! 155: movel a0@(70), a1 | was using super stack pointer before interrupt ! 156: ! 157: | ! 158: ! 159: L_CONT1: ! 160: ! 161: movel 0x408, a0@(74) | save GEMDOS terminate vector ! 162: ! 163: movel sp@+, a0@(32) | save old register a0 ! 164: ! 165: rts ! 166: ! 167: ! 168: ! 169: _save_context: ! 170: ! 171: movel a0, sp@- | save a0 ! 172: ! 173: movel sp@(8), a0 | get address of context save area ! 174: ! 175: ! 176: ! 177: | if running with a true coprocessor we need to save the FPU state ! 178: ! 179: ! 180: ! 181: tstw _fpu | is there a true FPU in the system ! 182: ! 183: beq nofpu2 ! 184: ! 185: fsave a0@(78) | save internal state frame ! 186: ! 187: tstb a0@(78) | if NULL frame then the FPU is not in use ! 188: ! 189: beq nofpu2 | skip programmer's model save ! 190: ! 191: fmovemx fp0-fp7,a0@(294) | save data registers ! 192: ! 193: fmoveml fpcr/fpsr/fpi,a0@(390) | and control registers ! 194: ! 195: nofpu2: ! 196: ! 197: | AGK: I am somewhat unsure of this assumption, viz that save_context ! 198: ! 199: | can never be called in a situation where a co-processor ! 200: ! 201: | mid-instruction stack frame would be required. I suspect this is a ! 202: ! 203: | valid assumption, in which case the above FPU code is redundant, the ! 204: ! 205: | next line is not however! ! 206: ! 207: ! 208: ! 209: clrw a0@(402) | mark as a 4 word stack frame ! 210: ! 211: ! 212: ! 213: moveml d0-d7/a0-a6, a0@ | save D0-D7/A0-A6 ! 214: ! 215: lea sp@(8), a1 ! 216: ! 217: movel a1, a0@(70) | save supervisor stack pointer ! 218: ! 219: | note that it should be pointing above the PC ! 220: ! 221: movel a1@(-4), a0@(66) | save PC ! 222: ! 223: movel usp, a1 ! 224: ! 225: movel a1, a0@(60) | save user stack pointer ! 226: ! 227: movew sr, d0 ! 228: ! 229: movew d0, a0@(64) | save status register ! 230: ! 231: movel 0x408, a0@(74) | save GEMDOS terminate vector ! 232: ! 233: movel sp@+, a0@(32) | save old a0 ! 234: ! 235: moveql #0, d0 | return 0 ! 236: ! 237: rts ! 238: ! 239: ! 240: ! 241: _restore_context: ! 242: ! 243: orw #0x0700, sr | mask interrupts ! 244: ! 245: movel sp@(4), a0 | address of context save area ! 246: ! 247: movel a0@(70), sp | supervisor stack pointer ! 248: ! 249: movel a0@(60), a1 ! 250: ! 251: movel a1, usp | set user stack pointer ! 252: ! 253: movel a0@(74), 0x408 | restore GEMDOS terminate vector ! 254: ! 255: ! 256: ! 257: tstw 0x59e | test longframe (AKP) ! 258: ! 259: beq short3 ! 260: ! 261: ! 262: ! 263: movew a0@(402),d0 | fetch frame format word ! 264: ! 265: tstw _m68010 | are we on a 68010? ! 266: ! 267: bne just0 | yes, so it's a simple interrupt frame ! 268: ! 269: ! 270: ! 271: bftst d0{#16:#4} | is it the simple interrupt frame ? ! 272: ! 273: beq just0 | yes so just push a zero ! 274: ! 275: moveml a0@(404),d1-d3 | saved instruction address/4 internal words ! 276: ! 277: moveml d1-d3,sp@- ! 278: ! 279: just0: movew d0,sp@- ! 280: ! 281: ! 282: ! 283: short3: ! 284: ! 285: movel a0@(66), sp@- | push the PC ! 286: ! 287: movew a0@(64), d0 | get status register ! 288: ! 289: movew d0, sp@- | push the status register ! 290: ! 291: ! 292: ! 293: | if running with a true co-processor we need to restore the FPU state ! 294: ! 295: ! 296: ! 297: tstw _fpu ! 298: ! 299: beq nofpu3 ! 300: ! 301: tstb a0@(78) | if NULL frame then FPU not in use ! 302: ! 303: beq short7 | skip programmer's model restore ! 304: ! 305: fmoveml a0@(390), fpcr/fpsr/fpi | restore control registers ! 306: ! 307: fmovemx a0@(294), fp0-fp7 | and data registers ! 308: ! 309: short7: frestore a0@(78) | finally the internal state ! 310: ! 311: ! 312: ! 313: nofpu3: ! 314: ! 315: moveml a0@, d0-d7/a0-a6 | restore registers d0-d7/a0-a6 ! 316: ! 317: rte | jump back to old context ! 318: ! 319: ! 320:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.