1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright (c) 1987-1995, by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27.ident "%Z%%M% %I% %E% SMI" 28 29 .file "%M%" 30 31#include <sys/asm_linkage.h> 32 33 ANSI_PRAGMA_WEAK(memmove,function) 34 35#include "synonyms.h" 36 37/* 38 * memmove(s1, s2, len) 39 * Copy s2 to s1, always copy n bytes. 40 * For overlapped copies it does the right thing. 41 */ 42 ENTRY(memmove) 43 save %sp, -SA(MINFRAME), %sp ! not a leaf routine any more 44 mov %i0, %l6 ! Save pointer to destination 45 cmp %i1, %i0 ! if from address is >= to use forward copy 46 bgeu,a 2f ! else use backward if ... 47 cmp %i2, 17 ! delay slot, for small counts copy bytes 48 49 sub %i0, %i1, %i4 ! get difference of two addresses 50 cmp %i2, %i4 ! compare size and difference of addresses 51 bgu ovbc ! if size is bigger, have do overlapped copy 52 cmp %i2, 17 ! delay slot, for small counts copy bytes 53 ! 54 ! normal, copy forwards 55 ! 562: ble dbytecp 57 andcc %i1, 3, %i5 ! is src word aligned 58 bz aldst 59 cmp %i5, 2 ! is src half-word aligned 60 be s2algn 61 cmp %i5, 3 ! src is byte aligned 62s1algn: ldub [%i1], %i3 ! move 1 or 3 bytes to align it 63 inc 1, %i1 64 stb %i3, [%i0] ! move a byte to align src 65 inc 1, %i0 66 bne s2algn 67 dec %i2 68 b ald ! now go align dest 69 andcc %i0, 3, %i5 70 71s2algn: lduh [%i1], %i3 ! know src is 2 byte alinged 72 inc 2, %i1 73 srl %i3, 8, %i4 74 stb %i4, [%i0] ! have to do bytes, 75 stb %i3, [%i0 + 1] ! don't know dst alingment 76 inc 2, %i0 77 dec 2, %i2 78 79aldst: andcc %i0, 3, %i5 ! align the destination address 80ald: bz w4cp 81 cmp %i5, 2 82 bz w2cp 83 cmp %i5, 3 84w3cp: ld [%i1], %i4 85 inc 4, %i1 86 srl %i4, 24, %i5 87 stb %i5, [%i0] 88 bne w1cp 89 inc %i0 90 dec 1, %i2 91 andn %i2, 3, %i3 ! i3 is aligned word count 92 dec 4, %i3 ! avoid reading beyond tail of src 93 sub %i1, %i0, %i1 ! i1 gets the difference 94 951: sll %i4, 8, %g1 ! save residual bytes 96 ld [%i1+%i0], %i4 97 deccc 4, %i3 98 srl %i4, 24, %i5 ! merge with residual 99 or %i5, %g1, %g1 100 st %g1, [%i0] 101 bnz 1b 102 inc 4, %i0 103 sub %i1, 3, %i1 ! used one byte of last word read 104 and %i2, 3, %i2 105 b 7f 106 inc 4, %i2 107 108w1cp: srl %i4, 8, %i5 109 sth %i5, [%i0] 110 inc 2, %i0 111 dec 3, %i2 112 andn %i2, 3, %i3 113 dec 4, %i3 ! avoid reading beyond tail of src 114 sub %i1, %i0, %i1 ! i1 gets the difference 115 1162: sll %i4, 24, %g1 ! save residual bytes 117 ld [%i1+%i0], %i4 118 deccc 4, %i3 119 srl %i4, 8, %i5 ! merge with residual 120 or %i5, %g1, %g1 121 st %g1, [%i0] 122 bnz 2b 123 inc 4, %i0 124 sub %i1, 1, %i1 ! used three bytes of last word read 125 and %i2, 3, %i2 126 b 7f 127 inc 4, %i2 128 129w2cp: ld [%i1], %i4 130 inc 4, %i1 131 srl %i4, 16, %i5 132 sth %i5, [%i0] 133 inc 2, %i0 134 dec 2, %i2 135 andn %i2, 3, %i3 ! i3 is aligned word count 136 dec 4, %i3 ! avoid reading beyond tail of src 137 sub %i1, %i0, %i1 ! i1 gets the difference 138 1393: sll %i4, 16, %g1 ! save residual bytes 140 ld [%i1+%i0], %i4 141 deccc 4, %i3 142 srl %i4, 16, %i5 ! merge with residual 143 or %i5, %g1, %g1 144 st %g1, [%i0] 145 bnz 3b 146 inc 4, %i0 147 sub %i1, 2, %i1 ! used two bytes of last word read 148 and %i2, 3, %i2 149 b 7f 150 inc 4, %i2 151 152w4cp: andn %i2, 3, %i3 ! i3 is aligned word count 153 sub %i1, %i0, %i1 ! i1 gets the difference 154 1551: ld [%i1+%i0], %i4 ! read from address 156 deccc 4, %i3 ! decrement count 157 st %i4, [%i0] ! write at destination address 158 bg 1b 159 inc 4, %i0 ! increment to address 160 b 7f 161 and %i2, 3, %i2 ! number of leftover bytes, if any 162 163 ! 164 ! differenced byte copy, works with any alignment 165 ! 166dbytecp: 167 b 7f 168 sub %i1, %i0, %i1 ! i1 gets the difference 169 1704: stb %i4, [%i0] ! write to address 171 inc %i0 ! inc to address 1727: deccc %i2 ! decrement count 173 bge,a 4b ! loop till done 174 ldub [%i1+%i0], %i4 ! read from address 175 ret 176 restore %l6, %g0, %o0 ! return pointer to destination 177 178 ! 179 ! an overlapped copy that must be done "backwards" 180 ! 181ovbc: add %i1, %i2, %i1 ! get to end of source space 182 add %i0, %i2, %i0 ! get to end of destination space 183 sub %i1, %i0, %i1 ! i1 gets the difference 184 1855: dec %i0 ! decrement to address 186 ldub [%i1+%i0], %i3 ! read a byte 187 deccc %i2 ! decrement count 188 bg 5b ! loop until done 189 stb %i3, [%i0] ! write byte 190 ret 191 restore %l6, %g0, %o0 ! return pointer to destination 192 193 SET_SIZE(memmove) 194