|
|
1.1 root 1: | .file "swap.s.68k"
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 movem to restore the regs saved in
22: | the stack.
23: | If to_run is not a new child, it restores all the registers saved in
24: | the frame on returning.
25: | If running_task is TERMINATED, then we don't need to do a save.
26: | NOTE: assumes all functions return values in d0.
27:
28: | The following constants are displacements of elements in class task:
29: | t_framep, th, t_basep, t_size, t_savearea, and t_mode.
30: TFRAME = 20
31: TH = 24
32: TBASEP = 32
33: TSIZE = 36
34: TSAVE = 40
35: TMODE = 52
36:
37: | The following constants are displacements from the fp to function args.
38: ARG1 = 8
39: ARG2 = 12
40: ARG3 = 16
41: ARG4 = 20
42: ARG5 = 24
43:
44: .text
45: .globl _swap
46: _swap:
47: link a6,#-40
48: moveml #0x3cfc,sp@ | save all user regs (d2-d7, a2-a5)
49: movl a6@(ARG2),a1 | a1 = to_run
50: movl a6@(ARG4),d0 | d0 = running_is_terminated
51: bnes L_RESTORE | if running is TERMINATED
52: | skip the save
53: movl a6@(ARG1),a0 | a0 = running
54:
55: | save state of running task
56: movl a6,a0@(TFRAME) | running->t_framep = fp (a6)
57: movl a0@(TMODE),d0 | d0 = running->t_mode
58: cmpl #2,d0 | if running->t_mode == SHARED
59: bnes L_RESTORE
60: | the code here to save the t_size is the same as for sswap
61: movl a0@(TBASEP),d0 | d0 = running->t_basep
62: subl sp,d0 | d0 = running->t_basep - sp
63: addql #4,d0 | (size in bytes)
64: asrl #2,d0 | d0 /= 4 (size in ints)
65: movl d0,a0@(TSIZE) | running->t_size = d0
66:
67: L_RESTORE:
68: movl a6@(ARG3),d1 | d1 = is_new_child
69:
70: | restore state of to_run task
71: movl a1@(TFRAME),a6 | a6 (fp) = to_run->t_framep
72:
73: | if is_new_child, restore registers
74: tstl d1
75: beqs L_RET
76: | new child task effectively returns from task::task, so we need
77: | to set the return value to "this"
78: movl a1@(TH),d0 | d0 = to_run->th
79: lea _New_task_regs,a1 | a1 = address of New_task_regs
80: movl a1@,d2
81: movl a1@(4),d3
82: movl a1@(8),d4
83: movl a1@(12),d5
84: movl a1@(16),d6
85: movl a1@(20),d7
86: movl a1@(32),a2
87: movl a1@(36),a3
88: movl a1@(40),a4
89: movl a1@(44),a5
90: unlk a6 | NOTE: movem not needed here.
91: rts
92: L_RET:
93: moveml a6@(-40),#0x3cfc | restore all user regs (d2-d7, a2-a5)
94: unlk a6
95: rts
96:
97:
98: | swap of SHARED
99: | sswap(*running, *prevOnStack, *to_run, is_new_child, running_is_terminated)
100: | This routine saves the fp in running's t_framep and the stack size in t_size.
101: | Then it copies out the target stack to prevOnStack's t_savearea.
102: | If to_run is not a new child, it then copies the saved stack of to_run
103: | (from t_savearea) to the target stack, and then restores to_run's t_framep
104: | to be the current fp. We don't need to restore state of a child
105: | to_run object, because it's already in place.
106: | If running_task is TERMINATED, then we don't need to do a save,
107: | and if running_task is TERMINATED and equals prevOnStack, then we don't
108: | have to do the stack copy.
109: | NOTE: assumes all functions return values in d0.
110: .text
111: .globl _sswap
112: _sswap:
113: link a6,#-40
114: moveml #0x3cfc,sp@ | save all user regs (d2-d7, a2-a5)
115:
116: movl a6@(ARG1),a1 | a1 = running
117: movl a6@(ARG2),a2 | a2 = prevOnStack
118: movl a6@(ARG5),d0 | d0 = running_is_terminated
119: bnes L_SKIP | if running is TERMINATED
120: | skip the save
121: |save hw state of running
122: movl a6,a1@(TFRAME) | running->t_framep = fp (a6)
123: movl a1@(TBASEP),d0 | d0 = running->t_basep
124: subl sp,d0 | d0 = running->t_basep - sp
125: addql #4,d0 | (size in bytes)
126: asrl #2,d0 | d0 /= 4 (size in ints)
127: movl d0,a1@(TSIZE) | running->t_size = d0
128: bra L_SAVE
129: L_SKIP:
130: cmpl a1,a2 | if running == prevOnStack
131: beq L_REST | skip prevOnStack save
132:
133: L_SAVE: |copy out target stack to prevOnStack->t_savearea
134: movl a2@(TSIZE),d2 | d2 = prevOnStack->t_size (count)
135: movl d2,sp@- | push count arg on stack
136: jsr _swap_call_new | get count bytes of storage
137: addql #4,sp | pop arg off stack
138: asll #2,d2 | scale d2 to bytes
139: addl d2,d0 | d0 = base of new stack, plus 1 long
140: subql #4,d0 | d0 = base of new stack
141: movl d0,a0 | a0 = base of new stack (to)
142: movl a0,a2@(TSAVE) | prevOnStack->t_savearea = a0 (to)
143: movl a2@(TBASEP),a1 | a1 = prevOnStack->t_basep (from)
144: addql #4,a0 | prepare for predecrement
145: addql #4,a1 | ditto
146: movl a2@(TSIZE),d0 | d0 = prevOnStack->t_size (count)
147: tstl d0
148: beqs L2 | if size == 0, goto L2
149: subql #1,d0 | for dbra
150: L1: | copy out loop
151: movl a1@-,a0@- | *--to = *--from
152: dbra d0,L1 | if --d0 != 0, goto L1
153: L2:
154: L_REST:
155: movl a6@(ARG4),d0 | d0 = is_new_child
156: bnes L6 | if is_new_child != 0
157: | skip the copy-in loop
158: |copy into target stack from to_run->t_savearea
159: movl a6@(ARG3),a2 | a2 = to_run
160: movl a2@(TBASEP),a0 | a0 = to_run->t_basep (to)
161: movl a2@(TSIZE),d0 | d0 = to_run->t_size (count)
162: | Kick up the sp if new stack will be taller than current.
163: asll #2,d0 | d0 = new stack height in bytes
164: subl d0,a0 | a0 = target sp
165: subl sp,a0 | a0 = a0 - sp
166: tstl a0
167: bges L3 | if a0 < 0
168: addl a0,sp | kick up sp
169: L3: movl a2@(TBASEP),a0 | a0 = to_run->t_basep (to)
170: movl a2@(TSAVE),a1 | a1 = to_run->t_savearea (from)
171: addql #4,a1 | prepare for predecrement
172: addql #4,a0 | ditto
173: movl a2@(TSIZE),d0 | d0 = to_run->t_size (count)
174: tstl d0
175: beqs L5 | if size == 0, goto L5
176: subql #1,d0 | for dbra
177: L4: | copy in loop
178: movl a1@-,a0@- | *--to = *--from
179: dbra d0,L4 | if --d0 != 0, goto L4
180: L5:
181: | restore state of to_run
182: movl a2@(TFRAME),a6 | fp (a6) = to_run->t_framep
183: | finally, delete to_run's t_savearea
184: movl a2@(TSIZE),d1 | d1 = to_run->t_size
185: asll #2,d1 | scale size to bytes
186: movl a2@(TSAVE),a0 | a0 = to_run->t_savearea
187: subl d1,a0 | get low address of savearea
188: addql #4,a0
189: movl a0,sp@- | push pointer to savearea on stack
190: jsr _swap_call_delete | delete to_run->t_savearea
191: addql #4,sp | pop arg off stack
192: movl #0,a2@(TSAVE) | to_run->t_savearea = 0
193: L6: moveml a6@(-40),#0x3cfc | restore all user regs (d2-d7, a2-a5)
194: unlk a6
195: rts
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.