Minix1.5/lib/string/memmove.x

/* memmove.x
 *	void *memmove(void *s1, const void *s2, size_t n)
 *	void *memcpy(void *s1, const void *s2, size_t n)
 *
 *	Copy n characters from the object pointed to by s2 into the
 *	object pointed to by s1.  Copying takes place as if the n
 *	characters pointed to by s2 are first copied to a temporary
 *	area and then copied to the object pointed to by s1.
 *
 *	Per X3J11, memcpy may have undefined results if the objects
 *	overlap; since the performance penalty is insignificant, we
 *	use the safe memmove code for it as well.
 */

#define BYTE_LIMIT 10		/* if n is above this, work with words */

.define	_memmove, _memcpy
.text
_memmove:
_memcpy:
	mov	bx,si		/* save si and di */
	mov	dx,di
	mov	di,sp
	mov	cx,6(di)
	mov	si,4(di)
	mov	di,2(di)
	mov	ax,di		/* save a copy of s1 */
	jcxz	exit		/* early exit if n == 0 */
	sub	di,si
	je	exit		/* early exit if s1 == s2 */
	jb	left_to_right	/* left to right if s1 < s2 */
	cmp	di,cx
	jae	left_to_right	/* left to right if no overlap */
right_to_left:
	mov	di,ax		/* retrieve s1 */
	std
	add	si,cx		/* compute where objects end */
	dec	si
	add	di,cx
	dec	di
	cmp	cx,#BYTE_LIMIT
	jbe	byte_move
	test	si,#1		/* align source on word boundary */
	jnz	word_unaligned
	movb
	dec	cx
word_unaligned:
	dec	si		/* adjust to word boundary */
	dec	di
	shr	cx,#1		/* move words, not bytes */
	rep
	movw
	jnc	exit
#ifdef i8088
	inc	si		/* fix up addresses for right to left moves */
	inc	di
	movb			/* move leftover byte */
#else
	movb	cl,1(si)
	movb	1(di),cl	/* move leftover byte */
#endif
	jmp	exit
left_to_right:
	mov	di,ax		/* retrieve s1 */
	cld
	cmp	cx,#BYTE_LIMIT
	jbe	byte_move
	test	si,#1		/* align source on word boundary */
	jz	word_move
	movb
	dec	cx
word_move:
	shr	cx,#1		/* move words, not bytes */
	rep
	movw
	adc	cx,cx		/* set up to move leftover byte */
byte_move:
	rep
	movb
exit:
	cld			/* restore direction flag */
	mov	si,bx		/* restore si and di */
	mov	di,dx
	ret