|
|
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.