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