181 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			181 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
/*
 | 
						|
 * memmove routine for Z8000
 | 
						|
 * Copyright (C) 2004 Christian Groessler <chris@groessler.org>
 | 
						|
 *
 | 
						|
 * Permission to use, copy, modify, and distribute this file
 | 
						|
 * for any purpose is hereby granted without fee, provided that
 | 
						|
 * the above copyright notice and this notice appears in all
 | 
						|
 * copies.
 | 
						|
 *
 | 
						|
 * This file is distributed WITHOUT ANY WARRANTY; without even the implied
 | 
						|
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | 
						|
 */
 | 
						|
 | 
						|
/* void *memmove(void *dest, const void *src, size_t length);
 | 
						|
 */
 | 
						|
 | 
						|
	name	"memmove.S"
 | 
						|
 | 
						|
	.text
 | 
						|
	even
 | 
						|
global	_memmove
 | 
						|
 | 
						|
_memmove:
 | 
						|
 | 
						|
#ifdef __Z8001__
 | 
						|
	segm
 | 
						|
 | 
						|
#ifdef __STD_CALL__
 | 
						|
	ldl	rr6,rr14(#4)
 | 
						|
	ldl	rr4,rr14(#8)
 | 
						|
	ldl	rr2,rr14(#12)
 | 
						|
#else
 | 
						|
	pushl	@rr14,rr6
 | 
						|
#endif
 | 
						|
 | 
						|
/* rr2  - length	(high word ignored)
 | 
						|
 * rr4  - src
 | 
						|
 * rr6  - dest
 | 
						|
 */
 | 
						|
 | 
						|
	testl	rr2
 | 
						|
	jr	z,finish
 | 
						|
 | 
						|
/*  check for destructive overlap (src < dest && dest < src + length) */
 | 
						|
 | 
						|
	cpl	rr6,rr4
 | 
						|
	jp	ule,memmove_entry	/* non-destructive, let memcpy do the work */
 | 
						|
	ldl	rr0,rr2
 | 
						|
	addl	rr0,rr4			/* rr0 = src + length */
 | 
						|
	cpl	rr0,rr6
 | 
						|
	jp	ult,memmove_entry	/* non-destructive, let memcpy do the work */
 | 
						|
 | 
						|
/* set-up pointers to copy backwards, add (length - 1) */
 | 
						|
	addl	rr4,rr2			/* src + length */
 | 
						|
	addl	rr6,rr2			/* dest + length */
 | 
						|
	subl	rr4,#1
 | 
						|
	subl	rr6,#1
 | 
						|
 | 
						|
/* check alignment */
 | 
						|
	bitb	rl7,#0		/* odd destination address? */
 | 
						|
	jr	z,testsrc
 | 
						|
	bitb	rl5,#0		/* odd source address? */
 | 
						|
	jr	z,odd_copy
 | 
						|
	jr	even_copy
 | 
						|
 | 
						|
testsrc:
 | 
						|
	bitb	rl5,#0
 | 
						|
	jr	nz,odd_copy	/* src even, dest odd */
 | 
						|
	lddb	@rr6,@rr4,r3
 | 
						|
	jr	ov,finish	/* jump if r5 is zero now */
 | 
						|
 | 
						|
/* copy words */
 | 
						|
even_copy:
 | 
						|
	ld	r2,r3			/* remember length */
 | 
						|
	srl	r3,#1
 | 
						|
/*	jr	z,no_words	   it cannot be zero here */
 | 
						|
 | 
						|
	dec	r5,#1
 | 
						|
	dec	r7,#1
 | 
						|
	lddr	@rr6,@rr4,r3
 | 
						|
 | 
						|
no_words:
 | 
						|
	bitb	rl2,#0		/* odd length? */
 | 
						|
	jr	z,finish
 | 
						|
	inc	r5,#1
 | 
						|
	inc	r7,#1
 | 
						|
	lddb	@rr6,@rr4,r2	/* yes, copy last byte */
 | 
						|
	jr	finish
 | 
						|
 | 
						|
/* copy bytes */
 | 
						|
odd_copy:
 | 
						|
	lddrb	@rr6,@rr4,r3
 | 
						|
 | 
						|
finish:
 | 
						|
#ifdef __STD_CALL__
 | 
						|
	ldl	rr6,rr14(#4)
 | 
						|
#else
 | 
						|
	popl	rr2,@rr14
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
#else		/* above Z8001, below Z8002 */
 | 
						|
 | 
						|
 | 
						|
	unsegm
 | 
						|
 | 
						|
#ifdef __STD_CALL__
 | 
						|
	ld	r7,r15(#2)
 | 
						|
	ld	r6,r15(#4)
 | 
						|
	ld	r5,r15(#6)
 | 
						|
#else
 | 
						|
	ld	r2,r7		/* buffer pointer return value */
 | 
						|
#endif
 | 
						|
 | 
						|
/* r5  - length
 | 
						|
 * r6  - src
 | 
						|
 * r7  - dest
 | 
						|
 */
 | 
						|
	test	r5
 | 
						|
	jr	z,finish
 | 
						|
 | 
						|
/*  check for destructive overlap (src < dest && dest < src + length) */
 | 
						|
 | 
						|
	cp	r7,r6
 | 
						|
	jp	ule,memmove_entry	/* non-destructive, let memcpy do the work */
 | 
						|
	ld	r0,r5
 | 
						|
	add	r0,r6			/* r0 = src + length */
 | 
						|
	cp	r0,r7
 | 
						|
	jp	ult,memmove_entry	/* non-destructive, let memcpy do the work */
 | 
						|
 | 
						|
/* set-up pointers to copy backwards, add (length - 1) */
 | 
						|
	add	r6,r5			/* src + length */
 | 
						|
	add	r7,r5			/* dest + length */
 | 
						|
	dec	r6,#1
 | 
						|
	dec	r7,#1
 | 
						|
 | 
						|
/* check alignment */
 | 
						|
	bitb	rl7,#0		/* odd destination address? */
 | 
						|
	jr	z,testsrc
 | 
						|
	bitb	rl6,#0		/* odd source address? */
 | 
						|
	jr	z,odd_copy
 | 
						|
	jr	even_copy
 | 
						|
 | 
						|
testsrc:
 | 
						|
	bitb	rl6,#0
 | 
						|
	jr	nz,odd_copy	/* src even, dest odd */
 | 
						|
	lddb	@r7,@r6,r5
 | 
						|
	jr	ov,finish	/* jump if r5 is zero now */
 | 
						|
 | 
						|
/* copy words */
 | 
						|
even_copy:
 | 
						|
	ld	r4,r5		/* remember length */
 | 
						|
	srl	r5,#1
 | 
						|
/*	jr	z,no_words	   it cannot be zero here */
 | 
						|
 | 
						|
	dec	r6,#1
 | 
						|
	dec	r7,#1
 | 
						|
	lddr	@r7,@r6,r5
 | 
						|
 | 
						|
no_words:
 | 
						|
	bitb	rl4,#0		/* odd length? */
 | 
						|
	jr	z,finish
 | 
						|
	inc	r6,#1
 | 
						|
	inc	r7,#1
 | 
						|
	lddb	@r7,@r6,r4	/* yes, copy last byte */
 | 
						|
	jr	finish
 | 
						|
 | 
						|
/* copy bytes */
 | 
						|
odd_copy:
 | 
						|
	lddrb	@r7,@r6,r5
 | 
						|
 | 
						|
finish:
 | 
						|
#ifdef __STD_CALL__
 | 
						|
	ld	r7,r15(#2)
 | 
						|
#endif
 | 
						|
 | 
						|
#endif	/* Z8002 */
 | 
						|
 | 
						|
	ret
 | 
						|
	.end
 |