1/* $NetBSD: memcpy.S,v 1.1 2020/08/16 06:43:43 isaki Exp $ */ 2 3/* 4 * Copyright (C) 2020 Tetsuya Isaki. All rights reserved. 5 * Copyright (C) 2020 Y.Sugahara (moveccr). All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29/* 30 * Size optimized (but slow) version for primary bootloader. 31 */ 32 33#include <machine/asm.h> 34 35| 36| void bcopy(const void *src, void *dst, size_t len); 37| 38ASENTRY_NOPROFILE(bcopy) 39 moveml %sp@,%d0-%d1/%a0-%a1 | %d0: (return address) 40 | %d1: src 41 | %a0: dst 42 | %a1: count 43 jbra memmove_common 44| 45| void *memcpy(void *dst, const void *src, size_t count); 46| void *memmove(void *dst, const void *src, size_t count); 47| 48ASENTRY_NOPROFILE(memcpy) 49ASENTRY_NOPROFILE(memmove) 50 moveml %sp@,%d0-%d1/%a0-%a1 | %d0: (return address) 51 | %d1: dst 52 | %a0: src 53 | %a1: count 54 55 exg %d1,%a0 | %d1: src 56 | %a0: dst 57 | %a1: count 58memmove_common: 59 exg %d1,%a1 | %d1: count 60 | %a0: dst 61 | %a1: src 62 moveql #0,%d0 63 | %d0: offset in forward mode. 64 | %d1: offset in backward mode 65 | and also loop counter. 66 jbra 2f 67loop: 68 | if src(=%a1) > dst(=%a0), then this is forward copy, 69 | %d0 is already forward offset. 70 | Otherwise backward copy. Copy %d1(backward offset) to %d0. 71 cmpl %a1,%a0 72 jcs 1f 73 movel %d1,%d0 741: 75 moveb %a1@(%d0.l),%a0@(%d0.l) | %d0: offset 76 addql #1,%d0 | increment forward counter, 77 | though it's pointless in 78 | backward mode 792: 80 subql #1,%d1 | if (--count < 0) 81 jcc loop | goto exit 82exit: 83 rts | %a0 holds return value (=dst) 84 85 86#if defined(SELFTEST) 87#include "iocscall.h" 88 .macro PRINT msg 89 leal \msg,%a1 90 IOCS(__B_PRINT) 91 .endm 92 93 .macro TEST name 94 leal \name,%a2 95 jbsr test 96 .endm 97 98ASENTRY_NOPROFILE(selftest_memmove) 99 moveml %d2-%d7/%a2-%a6,%sp@- 100 PRINT %pc@(msg_testname) 101 102 TEST test1 103 TEST test2 104 TEST test3 105 TEST test4 106 107 PRINT %pc@(msg_crlf) 108 moveml %sp@+,%d2-%d7/%a2-%a6 109 rts 110 111test: 112 movel %a2@+,buf:W | initial contents of buffer 113 movew %a2@+,(buf+4):W | (6 bytes total) 114 movel %a2@+,%sp@- | push len 115 movel %a2@+,%sp@- | push src 116 movel %a2@+,%a3 | keep dst and 117 movel %a3,%sp@- | push dst 118 jbsr memmove 119 leal %sp@(12),%sp 120 121 cmpal %a3,%a0 | compare return value 122 jne fail 123 movel %a2@+,%d0 | compare buf[0..3] 124 cmpl buf:W,%d0 125 jne fail 126 movew %a2@+,%d0 | compare buf[4..5] 127 cmpw (buf+4):W,%d0 | compare buf[4..5] 128 jne fail 129 PRINT %pc@(msg_ok) 130 rts 131fail: 132 PRINT %pc@(msg_fail) 133 rts 134 135test1: 136 | src=buf+1: 1 2 3 4 5 6 137 | \ \ 138 | dst=buf+2: 1 2 2 3 5 6 139 .byte 1, 2, 3, 4, 5, 6 | initial buf 140 .long 2 | len 141 .long buf+1 | src 142 .long buf+2 | dst 143 .byte 1, 2, 2, 3, 5, 6 | expected buf 144 145test2: 146 | src=buf+2: 1 2 3 4 5 6 147 | / / 148 | dst=buf+1: 1 3 4 4 5 6 149 .byte 1, 2, 3, 4, 5, 6 | initial buf 150 .long 2 | len 151 .long buf+2 | src 152 .long buf+1 | dst 153 .byte 1, 3, 4, 4, 5, 6 | expected buf 154 155test3: 156 | src == dst 157 .byte 1, 2, 3, 4, 5, 6 | initial buf 158 .long 2 | len 159 .long buf+1 | src 160 .long buf+1 | dst 161 .byte 1, 2, 3, 4, 5, 6 | expected buf 162 163test4: 164 | len == 0 165 .byte 1, 2, 3, 4, 5, 6 | initial buf 166 .long 0 | len 167 .long buf+1 | src 168 .long buf+1 | dst 169 .byte 1, 2, 3, 4, 5, 6 | expected buf 170 171msg_testname: 172 .asciz "memmove" 173msg_ok: 174 .asciz " ok" 175msg_fail: 176 .asciz " fail" 177msg_crlf: 178 .asciz "\r\n" 179 180 BSS(buf, 8) 181#endif 182