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

📄 bcopy.s

📁 开放源码实时操作系统源码.
💻 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 + -