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