1/* 2 * memmove routine for Z8000 3 * Copyright (C) 2004 Christian Groessler <chris@groessler.org> 4 * 5 * Permission to use, copy, modify, and distribute this file 6 * for any purpose is hereby granted without fee, provided that 7 * the above copyright notice and this notice appears in all 8 * copies. 9 * 10 * This file is distributed WITHOUT ANY WARRANTY; without even the implied 11 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 */ 13 14/* void *memmove(void *dest, const void *src, size_t length); 15 */ 16 17#include <picolibc.h> 18 19 name "memmove.S" 20 21 .text 22 even 23global _memmove 24 25_memmove: 26 27#ifdef __Z8001__ 28 segm 29 30#ifdef __STD_CALL__ 31 ldl rr6,rr14(#4) 32 ldl rr4,rr14(#8) 33 ldl rr2,rr14(#12) 34#else 35 pushl @rr14,rr6 36#endif 37 38/* rr2 - length (high word ignored) 39 * rr4 - src 40 * rr6 - dest 41 */ 42 43 testl rr2 44 jr z,finish 45 46/* check for destructive overlap (src < dest && dest < src + length) */ 47 48 cpl rr6,rr4 49 jp ule,memmove_entry /* non-destructive, let memcpy do the work */ 50 ldl rr0,rr2 51 addl rr0,rr4 /* rr0 = src + length */ 52 cpl rr0,rr6 53 jp ult,memmove_entry /* non-destructive, let memcpy do the work */ 54 55/* set-up pointers to copy backwards, add (length - 1) */ 56 addl rr4,rr2 /* src + length */ 57 addl rr6,rr2 /* dest + length */ 58 subl rr4,#1 59 subl rr6,#1 60 61/* check alignment */ 62 bitb rl7,#0 /* odd destination address? */ 63 jr z,testsrc 64 bitb rl5,#0 /* odd source address? */ 65 jr z,odd_copy 66 jr even_copy 67 68testsrc: 69 bitb rl5,#0 70 jr nz,odd_copy /* src even, dest odd */ 71 lddb @rr6,@rr4,r3 72 jr ov,finish /* jump if r5 is zero now */ 73 74/* copy words */ 75even_copy: 76 ld r2,r3 /* remember length */ 77 srl r3,#1 78/* jr z,no_words it cannot be zero here */ 79 80 dec r5,#1 81 dec r7,#1 82 lddr @rr6,@rr4,r3 83 84no_words: 85 bitb rl2,#0 /* odd length? */ 86 jr z,finish 87 inc r5,#1 88 inc r7,#1 89 lddb @rr6,@rr4,r2 /* yes, copy last byte */ 90 jr finish 91 92/* copy bytes */ 93odd_copy: 94 lddrb @rr6,@rr4,r3 95 96finish: 97#ifdef __STD_CALL__ 98 ldl rr6,rr14(#4) 99#else 100 popl rr2,@rr14 101#endif 102 103 104#else /* above Z8001, below Z8002 */ 105 106 107 unsegm 108 109#ifdef __STD_CALL__ 110 ld r7,r15(#2) 111 ld r6,r15(#4) 112 ld r5,r15(#6) 113#else 114 ld r2,r7 /* buffer pointer return value */ 115#endif 116 117/* r5 - length 118 * r6 - src 119 * r7 - dest 120 */ 121 test r5 122 jr z,finish 123 124/* check for destructive overlap (src < dest && dest < src + length) */ 125 126 cp r7,r6 127 jp ule,memmove_entry /* non-destructive, let memcpy do the work */ 128 ld r0,r5 129 add r0,r6 /* r0 = src + length */ 130 cp r0,r7 131 jp ult,memmove_entry /* non-destructive, let memcpy do the work */ 132 133/* set-up pointers to copy backwards, add (length - 1) */ 134 add r6,r5 /* src + length */ 135 add r7,r5 /* dest + length */ 136 dec r6,#1 137 dec r7,#1 138 139/* check alignment */ 140 bitb rl7,#0 /* odd destination address? */ 141 jr z,testsrc 142 bitb rl6,#0 /* odd source address? */ 143 jr z,odd_copy 144 jr even_copy 145 146testsrc: 147 bitb rl6,#0 148 jr nz,odd_copy /* src even, dest odd */ 149 lddb @r7,@r6,r5 150 jr ov,finish /* jump if r5 is zero now */ 151 152/* copy words */ 153even_copy: 154 ld r4,r5 /* remember length */ 155 srl r5,#1 156/* jr z,no_words it cannot be zero here */ 157 158 dec r6,#1 159 dec r7,#1 160 lddr @r7,@r6,r5 161 162no_words: 163 bitb rl4,#0 /* odd length? */ 164 jr z,finish 165 inc r6,#1 166 inc r7,#1 167 lddb @r7,@r6,r4 /* yes, copy last byte */ 168 jr finish 169 170/* copy bytes */ 171odd_copy: 172 lddrb @r7,@r6,r5 173 174finish: 175#ifdef __STD_CALL__ 176 ld r7,r15(#2) 177#endif 178 179#endif /* Z8002 */ 180 181 ret 182 .end 183