⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bcopy.s

📁 eCos操作系统源码
💻 S
📖 第 1 页 / 共 3 页
字号:
	fildq	48(%esi)
	fildq	56(%esi)
	fistpq	56(%edi)
	fistpq	48(%edi)
	fistpq	40(%edi)
	fistpq	32(%edi)
	fistpq	24(%edi)
	fistpq	16(%edi)
	fistpq	8(%edi)
	fistpq	0(%edi)
	addl	$64,%esi
	addl	$64,%edi
	subl	$64,%ecx
	cmpl	$64,%ecx
	jae	large_i586_bcopy_loop
	popl	%eax
	addl	%eax,%ecx
	cmpl	$64,%ecx
	jae	4b

	cmpl	$0,_npxproc
	je	i586_bc2
	frstor	0(%esp)
	addl	$108,%esp
i586_bc2:
	lmsw	%dx
	movb	$0xfe,kernel_fpu_lock

/*
 * This is a duplicate of the main part of generic_bcopy.  See the comments
 * there.  Jumping into generic_bcopy would cost a whole 0-1 cycles and
 * would mess up high resolution profiling.
 */
	ALIGN_TEXT
small_i586_bcopy:
	shrl	$2,%ecx
	cld
	rep
	movsl
	movl	20(%esp),%ecx
	andl	$3,%ecx
	rep
	movsb
	popl	%edi
	popl	%esi
	ret

	ALIGN_TEXT
1:
	addl	%ecx,%edi
	addl	%ecx,%esi
	decl	%edi
	decl	%esi
	andl	$3,%ecx
	std
	rep
	movsb
	movl	20(%esp),%ecx
	shrl	$2,%ecx
	subl	$3,%esi
	subl	$3,%edi
	rep
	movsl
	popl	%edi
	popl	%esi
	cld
	ret
#endif /* I586_CPU && NNPX > 0 */

/*
 * Note: memcpy does not support overlapping copies
 */
ENTRY(memcpy)
	pushl	%edi
	pushl	%esi
	movl	12(%esp),%edi
	movl	16(%esp),%esi
	movl	20(%esp),%ecx
	movl	%edi,%eax
	shrl	$2,%ecx				/* copy by 32-bit words */
	cld					/* nope, copy forwards */
	rep
	movsl
	movl	20(%esp),%ecx
	andl	$3,%ecx				/* any bytes left? */
	rep
	movsb
	popl	%esi
	popl	%edi
	ret


/*****************************************************************************/
/* copyout and fubyte family                                                 */
/*****************************************************************************/
/*
 * Access user memory from inside the kernel. These routines and possibly
 * the math- and DOS emulators should be the only places that do this.
 *
 * We have to access the memory with user's permissions, so use a segment
 * selector with RPL 3. For writes to user space we have to additionally
 * check the PTE for write permission, because the 386 does not check
 * write permissions when we are executing with EPL 0. The 486 does check
 * this if the WP bit is set in CR0, so we can use a simpler version here.
 *
 * These routines set curpcb->onfault for the time they execute. When a
 * protection violation occurs inside the functions, the trap handler
 * returns to *curpcb->onfault instead of the function.
 */

/* copyout(from_kernel, to_user, len) */
ENTRY(copyout)
	MEXITCOUNT
	jmp	*_copyout_vector

ENTRY(generic_copyout)
	movl	_curpcb,%eax
	movl	$copyout_fault,PCB_ONFAULT(%eax)
	pushl	%esi
	pushl	%edi
	pushl	%ebx
	movl	16(%esp),%esi
	movl	20(%esp),%edi
	movl	24(%esp),%ebx
	testl	%ebx,%ebx			/* anything to do? */
	jz	done_copyout

	/*
	 * Check explicitly for non-user addresses.  If 486 write protection
	 * is being used, this check is essential because we are in kernel
	 * mode so the h/w does not provide any protection against writing
	 * kernel addresses.
	 */

	/*
	 * First, prevent address wrapping.
	 */
	movl	%edi,%eax
	addl	%ebx,%eax
	jc	copyout_fault
/*
 * XXX STOP USING VM_MAXUSER_ADDRESS.
 * It is an end address, not a max, so every time it is used correctly it
 * looks like there is an off by one error, and of course it caused an off
 * by one error in several places.
 */
	cmpl	$VM_MAXUSER_ADDRESS,%eax
	ja	copyout_fault

#if defined(I386_CPU)

#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
	cmpl	$CPUCLASS_386,_cpu_class
	jne	3f
#endif
/*
 * We have to check each PTE for user write permission.
 * The checking may cause a page fault, so it is important to set
 * up everything for return via copyout_fault before here.
 */
	/* compute number of pages */
	movl	%edi,%ecx
	andl	$PAGE_MASK,%ecx
	addl	%ebx,%ecx
	decl	%ecx
	shrl	$IDXSHIFT+2,%ecx
	incl	%ecx

	/* compute PTE offset for start address */
	movl	%edi,%edx
	shrl	$IDXSHIFT,%edx
	andb	$0xfc,%dl

1:
	/* check PTE for each page */
	leal	_PTmap(%edx),%eax
	shrl	$IDXSHIFT,%eax
	andb	$0xfc,%al
	testb	$PG_V,_PTmap(%eax)		/* PTE page must be valid */
	je	4f
	movb	_PTmap(%edx),%al
	andb	$PG_V|PG_RW|PG_U,%al		/* page must be valid and user writable */
	cmpb	$PG_V|PG_RW|PG_U,%al
	je	2f

4:
	/* simulate a trap */
	pushl	%edx
	pushl	%ecx
	shll	$IDXSHIFT,%edx
	pushl	%edx
	call	_trapwrite			/* trapwrite(addr) */
	popl	%edx
	popl	%ecx
	popl	%edx

	testl	%eax,%eax			/* if not ok, return EFAULT */
	jnz	copyout_fault

2:
	addl	$4,%edx
	decl	%ecx
	jnz	1b				/* check next page */
#endif /* I386_CPU */

	/* bcopy(%esi, %edi, %ebx) */
3:
	movl	%ebx,%ecx

#if defined(I586_CPU) && NNPX > 0
	ALIGN_TEXT
slow_copyout:
#endif
	shrl	$2,%ecx
	cld
	rep
	movsl
	movb	%bl,%cl
	andb	$3,%cl
	rep
	movsb

done_copyout:
	popl	%ebx
	popl	%edi
	popl	%esi
	xorl	%eax,%eax
	movl	_curpcb,%edx
	movl	%eax,PCB_ONFAULT(%edx)
	ret

	ALIGN_TEXT
copyout_fault:
	popl	%ebx
	popl	%edi
	popl	%esi
	movl	_curpcb,%edx
	movl	$0,PCB_ONFAULT(%edx)
	movl	$EFAULT,%eax
	ret

#if defined(I586_CPU) && NNPX > 0
ENTRY(i586_copyout)
	/*
	 * Duplicated from generic_copyout.  Could be done a bit better.
	 */
	movl	_curpcb,%eax
	movl	$copyout_fault,PCB_ONFAULT(%eax)
	pushl	%esi
	pushl	%edi
	pushl	%ebx
	movl	16(%esp),%esi
	movl	20(%esp),%edi
	movl	24(%esp),%ebx
	testl	%ebx,%ebx			/* anything to do? */
	jz	done_copyout

	/*
	 * Check explicitly for non-user addresses.  If 486 write protection
	 * is being used, this check is essential because we are in kernel
	 * mode so the h/w does not provide any protection against writing
	 * kernel addresses.
	 */

	/*
	 * First, prevent address wrapping.
	 */
	movl	%edi,%eax
	addl	%ebx,%eax
	jc	copyout_fault
/*
 * XXX STOP USING VM_MAXUSER_ADDRESS.
 * It is an end address, not a max, so every time it is used correctly it
 * looks like there is an off by one error, and of course it caused an off
 * by one error in several places.
 */
	cmpl	$VM_MAXUSER_ADDRESS,%eax
	ja	copyout_fault

	/* bcopy(%esi, %edi, %ebx) */
3:
	movl	%ebx,%ecx
	/*
	 * End of duplicated code.
	 */

	cmpl	$1024,%ecx
	jb	slow_copyout

	pushl	%ecx
	call	_fastmove
	addl	$4,%esp
	jmp	done_copyout
#endif /* I586_CPU && NNPX > 0 */

/* copyin(from_user, to_kernel, len) */
ENTRY(copyin)
	MEXITCOUNT
	jmp	*_copyin_vector

ENTRY(generic_copyin)
	movl	_curpcb,%eax
	movl	$copyin_fault,PCB_ONFAULT(%eax)
	pushl	%esi
	pushl	%edi
	movl	12(%esp),%esi			/* caddr_t from */
	movl	16(%esp),%edi			/* caddr_t to */
	movl	20(%esp),%ecx			/* size_t  len */

	/*
	 * make sure address is valid
	 */
	movl	%esi,%edx
	addl	%ecx,%edx
	jc	copyin_fault
	cmpl	$VM_MAXUSER_ADDRESS,%edx
	ja	copyin_fault

#if defined(I586_CPU) && NNPX > 0
	ALIGN_TEXT
slow_copyin:
#endif
	movb	%cl,%al
	shrl	$2,%ecx				/* copy longword-wise */
	cld
	rep
	movsl
	movb	%al,%cl
	andb	$3,%cl				/* copy remaining bytes */
	rep
	movsb

#if defined(I586_CPU) && NNPX > 0
	ALIGN_TEXT
done_copyin:
#endif
	popl	%edi
	popl	%esi
	xorl	%eax,%eax
	movl	_curpcb,%edx
	movl	%eax,PCB_ONFAULT(%edx)
	ret

	ALIGN_TEXT
copyin_fault:
	popl	%edi
	popl	%esi
	movl	_curpcb,%edx
	movl	$0,PCB_ONFAULT(%edx)
	movl	$EFAULT,%eax
	ret

#if defined(I586_CPU) && NNPX > 0
ENTRY(i586_copyin)
	/*
	 * Duplicated from generic_copyin.  Could be done a bit better.
	 */
	movl	_curpcb,%eax
	movl	$copyin_fault,PCB_ONFAULT(%eax)
	pushl	%esi
	pushl	%edi
	movl	12(%esp),%esi			/* caddr_t from */
	movl	16(%esp),%edi			/* caddr_t to */
	movl	20(%esp),%ecx			/* size_t  len */

	/*
	 * make sure address is valid
	 */
	movl	%esi,%edx
	addl	%ecx,%edx
	jc	copyin_fault
	cmpl	$VM_MAXUSER_ADDRESS,%edx
	ja	copyin_fault
	/*
	 * End of duplicated code.
	 */

	cmpl	$1024,%ecx
	jb	slow_copyin

	pushl	%ebx			/* XXX prepare for fastmove_fault */
	pushl	%ecx
	call	_fastmove
	addl	$8,%esp
	jmp	done_copyin
#endif /* I586_CPU && NNPX > 0 */

#if defined(I586_CPU) && NNPX > 0
/* fastmove(src, dst, len)
	src in %esi
	dst in %edi
	len in %ecx		XXX changed to on stack for profiling
	uses %eax and %edx for tmp. storage
 */
/* XXX use ENTRY() to get profiling.  fastmove() is actually a non-entry. */
ENTRY(fastmove)
	pushl	%ebp
	movl	%esp,%ebp
	subl	$PCB_SAVEFPU_SIZE+3*4,%esp

	movl	8(%ebp),%ecx
	cmpl	$63,%ecx
	jbe	fastmove_tail

	testl	$7,%esi	/* check if src addr is multiple of 8 */
	jnz	fastmove_tail

	testl	$7,%edi	/* check if dst addr is multiple of 8 */
	jnz	fastmove_tail

/* if (npxproc != NULL) { */
	cmpl	$0,_npxproc
	je	6f
/*    fnsave(&curpcb->pcb_savefpu); */
	movl	_curpcb,%eax
	fnsave	PCB_SAVEFPU(%eax)
/*   npxproc = NULL; */
	movl	$0,_npxproc
/* } */
6:
/* now we own the FPU. */

/*
 * The process' FP state is saved in the pcb, but if we get
 * switched, the cpu_switch() will store our FP state in the
 * pcb.  It should be possible to avoid all the copying for
 * this, e.g., by setting a flag to tell cpu_switch() to
 * save the state somewhere else.
 */
/* tmp = curpcb->pcb_savefpu; */
	movl	%ecx,-12(%ebp)
	movl	%esi,-8(%ebp)
	movl	%edi,-4(%ebp)
	movl	%esp,%edi
	movl	_curpcb,%esi
	addl	$PCB_SAVEFPU,%esi
	cld
	movl	$PCB_SAVEFPU_SIZE>>2,%ecx
	rep
	movsl
	movl	-12(%ebp),%ecx
	movl	-8(%ebp),%esi
	movl	-4(%ebp),%edi
/* stop_emulating(); */
	clts
/* npxproc = curproc; */
	movl	_curproc,%eax
	movl	%eax,_npxproc
	movl	_curpcb,%eax
	movl	$fastmove_fault,PCB_ONFAULT(%eax)
4:
	movl	%ecx,-12(%ebp)
	cmpl	$1792,%ecx
	jbe	2f
	movl	$1792,%ecx
2:
	subl	%ecx,-12(%ebp)
	cmpl	$256,%ecx
	jb	5f
	movl	%ecx,-8(%ebp)
	movl	%esi,-4(%ebp)
	ALIGN_TEXT
3:
	movl	0(%esi),%eax
	movl	32(%esi),%eax
	movl	64(%esi),%eax
	movl	96(%esi),%eax
	movl	128(%esi),%eax
	movl	160(%esi),%eax
	movl	192(%esi),%eax
	movl	224(%esi),%eax
	addl	$256,%esi
	subl	$256,%ecx
	cmpl	$256,%ecx
	jae	3b
	movl	-8(%ebp),%ecx
	movl	-4(%ebp),%esi
5:
	ALIGN_TEXT
fastmove_loop:
	fildq	0(%esi)
	fildq	8(%esi)
	fildq	16(%esi)
	fildq	24(%esi)
	fildq	32(%esi)
	fildq	40(%esi)
	fildq	48(%esi)
	fildq	56(%esi)
	fistpq	56(%edi)
	fistpq	48(%edi)
	fistpq	40(%edi)
	fistpq	32(%edi)
	fistpq	24(%edi)
	fistpq	16(%edi)
	fistpq	8(%edi)
	fistpq	0(%edi)
	addl	$-64,%ecx
	addl	$64,%esi
	addl	$64,%edi
	cmpl	$63,%ecx
	ja	fastmove_loop
	movl	-12(%ebp),%eax
	addl	%eax,%ecx
	cmpl	$64,%ecx
	jae	4b

/* curpcb->pcb_savefpu = tmp; */
	movl	%ecx,-12(%ebp)
	movl	%esi,-8(%ebp)
	movl	%edi,-4(%ebp)
	movl	_curpcb,%edi
	addl	$PCB_SAVEFPU,%edi
	movl	%esp,%esi
	cld
	movl	$PCB_SAVEFPU_SIZE>>2,%ecx
	rep
	movsl
	movl	-12(%ebp),%ecx
	movl	-8(%ebp),%esi
	movl	-4(%ebp),%edi

/* start_emulating(); */
	smsw	%ax
	orb	$CR0_TS,%al
	lmsw	%ax
/* npxproc = NULL; */
	movl	$0,_npxproc

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -