mirror of
https://github.com/autc04/Retro68.git
synced 2024-11-28 05:51:04 +00:00
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
|