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