1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
/*
* 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
|