|
|
1.1 ! root 1: .file "swap.s.vax" ! 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. If to_run is not a new child, it simply returns. ! 22: # If running_task is TERMINATED, then we don't need to do a save. ! 23: ! 24: .globl _swap ! 25: .align 1 ! 26: _swap: ! 27: .word 0xfc0 # entry mask; save all user regs (r11-r6) ! 28: movl 8(ap),r2 # r2 = to_run ! 29: movl 16(ap),r1 # r1 = running_is_terminated ! 30: cmpl $1,r1 # if running is TERMINATED ! 31: jeql .L_RESTORE # skip save ! 32: movl 4(ap),r1 # r1 = running ! 33: ! 34: # save state of running task ! 35: movl fp,20(r1) # running->t_framep = fp ! 36: movl 52(r1),r0 # r0 = running->t_mode ! 37: cmpl $2,r0 # if running->t_mode == SHARED ! 38: jneq .L_RESTORE ! 39: # the code here to save the t_size is the same as for sswap ! 40: ! 41: subl3 sp,32(r1),r0 # r0 = running->t_basep - sp ! 42: # (size in bytes) ! 43: divl3 $4,r0,36(r1) # running->t_size = r0 / 4 (int) ! 44: ! 45: .L_RESTORE: ! 46: movl 12(ap),r1 # r1 = is_new_child ! 47: ! 48: # restore state of to_run_task ! 49: movl 20(r2),fp # fp = to_run->t_framep ! 50: ! 51: # if is_new_child, restore registers ! 52: tstl r1 ! 53: jeql .L_RET ! 54: # new child task effectively returns from task::task, so we need ! 55: # to set the return value to "this" ! 56: movl 24(r2),r0 # r0 = to_run->th ! 57: moval _New_task_regs,r2 # r2 = address of New_task_regs ! 58: movl 0(r2),r6 ! 59: movl 4(r2),r7 ! 60: movl 8(r2),r8 ! 61: movl 12(r2),r9 ! 62: movl 16(r2),r10 ! 63: movl 20(r2),r11 ! 64: .L_RET: ! 65: ret ! 66: ! 67: # swap of SHARED ! 68: # sswap(*running, *prevOnStack, *to_run, is_new_child, running_is_terminated) ! 69: # This routine saves the fp in running's t_framep and the stack size in t_size. ! 70: # Then it copies out the target stack to prevOnStack's t_savearea. ! 71: # If to_run is not a new child, it then copies the saved stack of to_run ! 72: # (from t_savearea) to the target stack, and then restores to_run's t_framep ! 73: # to be the current fp. We don't need to restore state of a child ! 74: # to_run object, because it's already in place. ! 75: # If running_task is TERMINATED, then we don't need to do a save, ! 76: # and if running_task is TERMINATED and equals prevOnStack, then we don't ! 77: # have to do the stack copy. ! 78: .globl _sswap ! 79: .align 1 ! 80: _sswap: ! 81: .word 0xfc0 # entry mask; save all user regs (r11-r6) ! 82: movl 4(ap),r1 # r1 = running ! 83: movl 8(ap),r11 # r11 = prevOnStack ! 84: movl 20(ap),r0 # r0 = running_is_terminated ! 85: cmpl $1,r0 # if running is TERMINATED ! 86: jeql .L_SKIP # skip save ! 87: #save hw state of running ! 88: movl fp,20(r1) # running->t_framep = fp ! 89: subl3 sp,32(r1),r0 # r0 = running->t_basep - sp ! 90: # (size in bytes) ! 91: divl3 $4,r0,36(r1) # running->t_size = r0 / 4 (int) ! 92: jmp .L_SAVE ! 93: ! 94: .L_SKIP: #if running is TERMINATED and running == prevOnStack, ! 95: #then we can skip the stack copy too ! 96: cmpl r1,r11 # if running == prevOnStack ! 97: jeql .L_REST # skip save ! 98: ! 99: .L_SAVE: #copy out target stack to prevOnStack->t_savearea ! 100: movl 36(r11),r10 # r10 = prevOnStack->t_size (count) ! 101: pushl r10 ! 102: calls $1,_swap_call_new # get count bytes of storage ! 103: ashl $2,r10,r10 # scale r10 to bytes ! 104: addl2 r10,r0 # r0 = base of new space, plus 1 ! 105: subl2 $4,r0 # r0 = base of new stack (to) ! 106: movl r0,40(r11) # prevOnStack->t_savearea = r0 (to) ! 107: movl 32(r11),r2 # r2 = prevOnStack->t_basep (from) ! 108: movl 36(r11),r10 # r10 = prevOnStack->t_size (count) ! 109: .L1: #copy out loop ! 110: tstl r10 # while (count > 0) ! 111: jeql .L2 ! 112: decl r10 # count-- ! 113: movl (r2),(r0) # to = from ! 114: cmpl -(r2),-(r0) # to--, from-- ! 115: jmp .L1 ! 116: .L2: ! 117: .L_REST: ! 118: movl 16(ap),r1 # r1 = is_new_child ! 119: cmpl $1,r1 # if is_new_child == 1 ! 120: jeql .L6 # skip the copy-in loop ! 121: #copy into target stack from to_run->t_savearea ! 122: movl 12(ap),r11 # r11 = to_run ! 123: movl 32(r11),r0 # r0 = to_run->t_basep (to) ! 124: movl 36(r11),r10 # r10 = to_run->t_size (count) ! 125: # Kick up the %sp if new stack will be taller than current. ! 126: ashl $2,r10,r2 # r2 = new stack height in bytes. ! 127: subl3 r2,r0,r1 # r1 = target sp ! 128: subl2 sp,r1 # r1 = r1 - sp ! 129: cmpl r1,$0 # if r1 < 0, kick up sp ! 130: jgeq .L3 ! 131: addl2 r1,sp ! 132: .L3: movl 40(r11),r2 # r2 = to_run->t_savearea (from) ! 133: .L4: # copy in loop ! 134: tstl r10 # while (count > 0) ! 135: jeql .L5 ! 136: decl r10 # count-- ! 137: movl (r2),(r0) # to = from ! 138: cmpl -(r2),-(r0) # --to, --from ! 139: jmp .L4 ! 140: ! 141: .L5: # restore state of to_run ! 142: movl 20(r11),fp # fp = to_run->t_framep ! 143: # finally, delete to_run's t_savearea ! 144: movl 36(r11),r1 # r1 = to_run->t_size ! 145: ashl $2,r1,r1 # scale size to bytes ! 146: movl 40(r11),r2 # r2 = to_run->t_savearea ! 147: subl2 r1,r2 # get low address of savearea ! 148: addl2 $4,r2 ! 149: pushl r2 ! 150: calls $1,_swap_call_delete ! 151: movl $0,40(r11) # to_run->t_savearea = 0 ! 152: .L6: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.