Plan 9 from Bell Labs’s /usr/web/sources/contrib/steve/root/sys/src/c++/lib/task-3.03/386/swap.s

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/	.file "swap.s.386"
/	ident	"@(#)cls4:lib/task/task/swap.s.386	1.4"
/ ##############################################################################
/ 
/ C++ source for the C++ Language System, Release 3.0.  This product
/ is a new release of the original cfront developed in the computer
/ science research center of AT&T Bell Laboratories.
/
/ Copyright (c) 1993  UNIX System Laboratories, Inc.
/ Copyright (c) 1991, 1992   AT&T and UNIX System Laboratories, Inc.
/ Copyright (c) 1984, 1989, 1990 AT&T.  All Rights Reserved.
/
/ 
/ THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System
/ 	
/ Laboratories, Inc.  The copyright notice above does not evidence
/ any actual or intended publication of such source code.
/
/ 
/ ##############################################################################
/
/	swap of DEDICATED
/ call swap(*running_task, *to_run_task, is_new_child, running_is_terminated)
/ This routine saves the fp in running's t_framep.
/ If running is a SHARED task, we must save its stack size as well,
/ although the stack does not need to be copied out here.
/ It then restores to_run's t_framep to be the current fp.
/ If to_run is a new child, it explicitly restores the registers from
/ New_task_regs, and returns without restoring the regs saved in the stack.
/ If to_run is not a new child, it restores all the registers saved in
/ the frame on returning.
/ If running_task is TERMINATED, then we don't need to do a save.
/ NOTE:  assumes all functions return values in eax.

	.text
	.globl	swap
swap:
	pushl	%ebp			/ save caller's fp 
	movl	%esp,%ebp		/ fp = sp 
	pushl	%edi			/ save all user regs: edi, esi, ebx
	pushl	%esi
	pushl	%ebx
	movl	12(%ebp),%edx		/ edx = to_run
	movl	20(%ebp),%eax		/ eax = running_is_terminated
	cmpl	$1,%eax			/ if eax == 1
	je	.L_RESTORE		/ 	skip the save
	movl	8(%ebp),%eax		/ eax = running

	/ save state of running task
	movl	%ebp,20(%eax)		/ running->t_framep = fp (ebp)
	movl	52(%eax),%ecx		/ %ecx = running->t_mode
	cmpl	$2,%ecx			/ if running-t_mode == SHARED
	jne	.L_RESTORE
	/ the code here to save the t_size is the same as for sswap
	movl	32(%eax),%ecx		/ ecx = running->t_basep
	subl	%esp,%ecx		/ ecx = running->t_basep - sp
	addl	$4,%ecx			/ (size in bytes)
	shrl	$2,%ecx			/ ecx /= 4 (size in ints)
	movl	%ecx,36(%eax)		/ running->t_size = ecx

.L_RESTORE:
	movl	16(%ebp),%ecx		/ ecx = is_new_child

	/ restore state of to_run task
	movl	20(%edx),%ebp		/ ebp (fp) = to_run->t_framep

	/ if is_new_child, restore registers
	jcxz	.L_RET			/ if ecx==0; go to .L_RET
	/ new child task effectively returns from task::task, so we need
	/ to set the return value to "this"
	movl	24(%edx),%eax		/ eax = to_run->th
	leal	New_task_regs,%edx	/ edx = address of New_task_regs
	movl	0(%edx),%edi
	movl	4(%edx),%esi
	movl	8(%edx),%ebx
	/ Note: leave resets sp relative to fp, so don't need to reset sp
	/ for NEW_CHILD case.
	leave
	ret
.L_RET:
	/ The i386 restores registers relative to sp, so we need to reset
	/ to-runs's sp.  We add 3 words (n saved regs) to the fp to get the sp.
	movl	%ebp,%edx
	sub	$12,%edx
	movl	%edx,%esp
	/ restore all user regs: edi, esi, ebx
	popl	%ebx
	popl	%esi
	popl	%edi
	leave
	ret


/	swap of SHARED
/ sswap(*running, *prevOnStack, *to_run, is_new_child, running_is_terminated)
/ This routine saves the fp in running's t_framep and the stack size in t_size.
/ Then it copies out the target stack to prevOnStack's t_savearea.
/ If to_run is not a new child, it then copies the saved stack of to_run 
/ (from t_savearea) to the target stack, and then restores to_run's t_framep 
/ to be the current fp.  We don't need to restore state of a child 
/ to_run object, because it's already in place.
/ If running_task is TERMINATED, then we don't need to do a save,
/ NOTE:  assumes all functions return values in eax.
/ and if running_task is TERMINATED and equals prevOnStack, then we don't
/ have to do the stack copy.
	.text
	.globl	sswap
sswap:
	pushl	%ebp			/ save caller's fp 
	movl	%esp,%ebp		/ fp = sp 
	pushl	%edi			/ save all user regs: edi, esi, ebx
	pushl	%esi
	pushl	%ebx

	movl	8(%ebp),%eax		/ eax = running
	movl	12(%ebp),%edi		/ edi = prevOnStack
	movl	24(%ebp),%ecx		/ ecx = running_is_terminated
	cmpl	$1,%ecx			/ if ecx == 1
	je	.L_SKIP			/ 	skip the save
	/save hw state of running
	movl	%ebp,20(%eax)		/ running->t_framep = fp (ebp)
	movl	32(%eax),%ecx		/ ecx = running->t_basep
	subl	%esp,%ecx		/ ecx = running->t_basep - sp
	addl	$4,%ecx			/ (size in bytes)
	shrl	$2,%ecx			/ ecx /= 4 (size in ints)
	movl	%ecx,36(%eax)		/ running->t_size = ecx
	jmp	.L_SAVE

.L_SKIP:	/if running is TERMINATED and running == prevOnStack,
		/then we can skip the stack copy too
	cmpl	%eax,%edi		/ if running == prevOnStack
	je	.L_REST			/	skip save

.L_SAVE:	/copy out target stack to prevOnStack->t_savearea
	movl	36(%edi),%ecx		/ ecx = prevOnStack->t_size (count)
	pushl	%ecx			/ push count arg on stack
	call	swap_call_new		/ get count bytes of storage
	popl	%ecx			/ pop arg off stack
	sall	$2,%ecx			/ scale ecx to bytes
	addl	%ecx,%eax		/ eax = base of new stack, plus 1 long
	subl	$4,%eax			/ eax = base of new stack (to)
	movl	%eax,40(%edi)		/ prevOnStack->t_savearea = eax (to)
	movl	32(%edi),%esi		/ esi = prevOnStack->t_basep (from)
	movl	%eax,%edi		/ edi = to
	shrl	$2,%ecx			/ ecx /= 4 = size in ints (count)
	pushf				/ save old DF
	std				/ set DF for copy from hi to lo addr
	rep; smovl			/ copy words 
	popf				/ retore DF

.L_REST:
	movl	20(%ebp),%eax		/ eax = is_new_child
	testl	%eax,%eax		/ if is_new_child != 0
	jne	.L6			/	skip the copy-in loop

	/copy into target stack from to_run->t_savearea
	movl	16(%ebp),%ebx		/ ebx = to_run
	movl	32(%ebx),%eax		/ eax = to_run->t_basep (to)
	movl	36(%ebx),%ecx		/ ecx = to_run->t_size (count)
	/ Kick up the sp if new stack will be taller than current.
	sall	$2,%ecx			/ ecx = new stack height in bytes
	subl	%ecx,%eax		/ eax = base - size = target sp (+ 1)
	subl	%esp,%eax		/ eax = eax - sp
	testl	%eax,%eax
	jge	.L3			/ if eax < 0
	addl	%eax,%esp		/	kick up sp
.L3:
	movl	32(%ebx),%edi		/ edi = to_run->t_basep (to)
	movl	36(%ebx),%ecx		/ ecx = to_run->t_size (count)
	movl	40(%ebx),%esi		/ esi = to_run->t_savearea (from)
	pushf				/ save old DF
	std				/ set DF for copy from hi to lo addr
	rep; smovl			/ copy words 
	popf				/ retore DF

	/ restore state of to_run
	movl	20(%ebx),%ebp		/ fp (a6) = to_run->t_framep
	/ to (edi) points to one word beyond new sp
	addl	$4,%edi
	movl	%edi,%esp		/ reset sp, so regs can be restored
	/ finally, delete to_run's t_savearea
	movl	36(%ebx),%ecx		/ ecx = to_run->t_size
	sall	$2,%ecx			/ scale size to bytes
	movl	40(%ebx),%eax		/ eax = to_run->t_savearea
	subl	%ecx,%eax		/ get low address of savearea
	addl	$4,%eax
	pushl	%eax			/ push pointer to savearea on stack
	call	swap_call_delete	/ delete to_run->t_savearea
	popl	%eax			/ pop arg off stack
	movl	$0,40(%ebx)		/ to_run->t_savearea = 0
/ sp should be correct here, for both is and is not new child cases
.L6:	/ restore all user regs: edi, esi, ebx
	popl	%ebx
	popl	%esi
	popl	%edi
	leave
	ret

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.