|
|
1.1 root 1: / .file "swap.s.386"
2: / ident "%W%"
3: /##############################################################################
4: / Copyright (c) 1984 AT&T
5: / All Rights Reserved
6: /
7: / THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
8: /
9: / The copyright notice above does not evidence any
10: / actual or intended publication of such source code.
11: /
12: /##############################################################################
13:
14: / swap of DEDICATED
15: / call swap(*running_task, *to_run_task, is_new_child, running_is_terminated)
16: / This routine saves the fp in running's t_framep.
17: / If running is a SHARED task, we must save its stack size as well,
18: / although the stack does not need to be copied out here.
19: / It then restores to_run's t_framep to be the current fp.
20: / If to_run is a new child, it explicitly restores the registers from
21: / New_task_regs, and returns without restoring the regs saved in the stack.
22: / If to_run is not a new child, it restores all the registers saved in
23: / the frame on returning.
24: / If running_task is TERMINATED, then we don't need to do a save.
25: / NOTE: assumes all functions return values in eax.
26:
27: .text
28: .globl swap
29: swap:
30: pushl %ebp / save caller's fp
31: movl %esp,%ebp / fp = sp
32: pushl %edi / save all user regs: edi, esi, ebx
33: pushl %esi
34: pushl %ebx
35: movl 12(%ebp),%edx / edx = to_run
36: movl 20(%ebp),%eax / eax = running_is_terminated
37: cmpl $1,%eax / if eax == 1
38: je .L_RESTORE / skip the save
39: movl 8(%ebp),%eax / eax = running
40:
41: / save state of running task
42: movl %ebp,20(%eax) / running->t_framep = fp (ebp)
43: movl 52(%eax),%ecx / %ecx = running->t_mode
44: cmpw $2,%ecx / if running-t_mode == SHARED
45: jne .L_RESTORE
46: / the code here to save the t_size is the same as for sswap
47: movl 32(%eax),%ecx / ecx = running->t_basep
48: subl %esp,%ecx / ecx = running->t_basep - sp
49: addl $4,%ecx / (size in bytes)
50: shrl $2,%ecx / ecx /= 4 (size in ints)
51: movl %ecx,36(%eax) / running->t_size = ecx
52:
53: .L_RESTORE:
54: movl 16(%ebp),%ecx / ecx = is_new_child
55:
56: / restore state of to_run task
57: movl 20(%edx),%ebp / ebp (fp) = to_run->t_framep
58:
59: / if is_new_child, restore registers
60: jcxz .L_RET / if ecx==0; go to .L_RET
61: / new child task effectively returns from task::task, so we need
62: / to set the return value to "this"
63: movl 24(%edx),%eax / eax = to_run->th
64: leal New_task_regs,%edx / edx = address of New_task_regs
65: movl 0(%edx),%edi
66: movl 4(%edx),%esi
67: movl 8(%edx),%ebx
68: / Note: leave resets sp relative to fp, so don't need to reset sp
69: / for NEW_CHILD case.
70: leave
71: ret
72: .L_RET:
73: / The i386 restores registers relative to sp, so we need to reset
74: / to-runs's sp. We add 3 words (n saved regs) to the fp to get the sp.
75: movl %ebp,%edx
76: sub $12,%edx
77: movl %edx,%esp
78: / restore all user regs: edi, esi, ebx
79: popl %ebx
80: popl %esi
81: popl %edi
82: leave
83: ret
84:
85:
86: / swap of SHARED
87: / sswap(*running, *prevOnStack, *to_run, is_new_child, running_is_terminated)
88: / This routine saves the fp in running's t_framep and the stack size in t_size.
89: / Then it copies out the target stack to prevOnStack's t_savearea.
90: / If to_run is not a new child, it then copies the saved stack of to_run
91: / (from t_savearea) to the target stack, and then restores to_run's t_framep
92: / to be the current fp. We don't need to restore state of a child
93: / to_run object, because it's already in place.
94: / If running_task is TERMINATED, then we don't need to do a save,
95: / NOTE: assumes all functions return values in eax.
96: / and if running_task is TERMINATED and equals prevOnStack, then we don't
97: / have to do the stack copy.
98: .text
99: .globl sswap
100: sswap:
101: pushl %ebp / save caller's fp
102: movl %esp,%ebp / fp = sp
103: pushl %edi / save all user regs: edi, esi, ebx
104: pushl %esi
105: pushl %ebx
106:
107: movl 8(%ebp),%eax / eax = running
108: movl 12(%ebp),%edi / edi = prevOnStack
109: movl 24(%ebp),%ecx / ecx = running_is_terminated
110: cmpl $1,%ecx / if ecx == 1
111: je .L_SKIP / skip the save
112: /save hw state of running
113: movl %ebp,20(%eax) / running->t_framep = fp (ebp)
114: movl 32(%eax),%ecx / ecx = running->t_basep
115: subl %esp,%ecx / ecx = running->t_basep - sp
116: addl $4,%ecx / (size in bytes)
117: shrl $2,%ecx / ecx /= 4 (size in ints)
118: movl %ecx,36(%eax) / running->t_size = ecx
119: jmp .L_SAVE
120:
121: .L_SKIP: /if running is TERMINATED and running == prevOnStack,
122: /then we can skip the stack copy too
123: cmpl %eax,%edi / if running == prevOnStack
124: je .L_REST / skip save
125:
126: .L_SAVE: /copy out target stack to prevOnStack->t_savearea
127: movl 36(%edi),%ecx / ecx = prevOnStack->t_size (count)
128: pushl %ecx / push count arg on stack
129: call swap_call_new / get count bytes of storage
130: popl %ecx / pop arg off stack
131: sall $2,%ecx / scale ecx to bytes
132: addl %ecx,%eax / eax = base of new stack, plus 1 long
133: subl $4,%eax / eax = base of new stack (to)
134: movl %eax,40(%edi) / prevOnStack->t_savearea = eax (to)
135: movl 32(%edi),%edx / edx = prevOnStack->t_basep (from)
136: shrl $2,%ecx / ecx /= 4 = size in ints (count)
137: jmp .L2
138: .L1: / copy out loop
139: movl (%edx),%edi / edi = *from
140: movl %edi,(%eax) / *to = edi
141: subl $4,%edx / from--
142: subl $4,%eax / to--
143: decl %ecx / count--
144: .L2:
145: testl %ecx,%ecx / if count > 0
146: jg .L1 / jmp .L1
147: .L_REST:
148: movl 20(%ebp),%eax / eax = is_new_child
149: testl %eax,%eax / if is_new_child != 0
150: jne .L6 / skip the copy-in loop
151:
152: /copy into target stack from to_run->t_savearea
153: movl 16(%ebp),%esi / esi = to_run
154: movl 32(%esi),%eax / eax = to_run->t_basep (to)
155: movl 36(%esi),%ecx / ecx = to_run->t_size (count)
156: / Kick up the sp if new stack will be taller than current.
157: sall $2,%ecx / ecx = new stack height in bytes
158: subl %ecx,%eax / eax = base - size = target sp (+ 1)
159: subl %esp,%eax / eax = eax - sp
160: testl %eax,%eax
161: jge .L3 / if eax < 0
162: addl %eax,%esp / kick up sp
163: .L3:
164: movl 32(%esi),%eax / eax = to_run->t_basep (to)
165: movl 36(%esi),%ecx / ecx = to_run->t_size (count)
166: movl 40(%esi),%edx / edx = to_run->t_savearea (from)
167: jmp .L5
168: .L4: / copy in loop
169: movl (%edx),%edi / edi = *from
170: movl %edi,(%eax) / *to = edi
171: subl $4,%edx / from--
172: subl $4,%eax / to--
173: decl %ecx / count--
174: .L5:
175: testl %ecx,%ecx / if count > 0
176: jg .L4 / jmp .L4
177:
178: / restore state of to_run
179: movl 20(%esi),%ebp / fp (a6) = to_run->t_framep
180: / to (eax) points to one word beyond new sp
181: addl $4,%eax
182: movl %eax,%esp / reset sp, so regs can be restored
183: / finally, delete to_run's t_savearea
184: movl 36(%esi),%ecx / ecx = to_run->t_size
185: sall $2,%ecx / scale size to bytes
186: movl 40(%esi),%eax / eax = to_run->t_savearea
187: subl %ecx,%eax / get low address of savearea
188: addl $4,%eax
189: pushl %eax / push pointer to savearea on stack
190: call swap_call_delete / delete to_run->t_savearea
191: popl %eax / pop arg off stack
192: movl $0,40(%esi) / to_run->t_savearea = 0
193: / sp should be correct here, for both is and is not new child cases
194: .L6: / restore all user regs: edi, esi, ebx
195: popl %ebx
196: popl %esi
197: popl %edi
198: leave
199: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.