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