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 .file "memmove.s" 28 29#include <sys/asm_linkage.h> 30 31 ANSI_PRAGMA_WEAK(memmove,function) 32 33/* 34 * memmove(s1, s2, len) 35 * Copy s2 to s1, always copy n bytes. 36 * For overlapped copies it does the right thing. 37 */ 38 ENTRY(memmove) 39 save %sp, -SA(MINFRAME), %sp ! not a leaf routine any more 40 mov %i0, %l6 ! Save pointer to destination 41 cmp %i1, %i0 ! if from address is >= to use forward copy 42 bgeu,a %xcc, 2f ! else use backward if ... 43 cmp %i2, 17 ! delay slot, for small counts copy bytes 44 45 sub %i0, %i1, %i4 ! get difference of two addresses 46 cmp %i2, %i4 ! compare size and difference of addresses 47 bgu %xcc, ovbc ! if size is bigger, have to do overlapped copy 48 cmp %i2, 17 ! delay slot, for small counts copy bytes 49 ! 50 ! normal, copy forwards 51 ! 522: ble %xcc, dbytecp 53 andcc %i1, 3, %i5 ! is src word aligned 54 bz,pn %icc, aldst 55 cmp %i5, 2 ! is src half-word aligned 56 be,pn %icc, s2algn 57 cmp %i5, 3 ! src is byte aligned 58s1algn: ldub [%i1], %i3 ! move 1 or 3 bytes to align it 59 inc 1, %i1 60 stb %i3, [%i0] ! move a byte to align src 61 inc 1, %i0 62 bne,pn %icc, s2algn 63 dec %i2 64 b ald ! now go align dest 65 andcc %i0, 3, %i5 66 67s2algn: lduh [%i1], %i3 ! know src is 2 byte alinged 68 inc 2, %i1 69 srl %i3, 8, %i4 70 stb %i4, [%i0] ! have to do bytes, 71 stb %i3, [%i0 + 1] ! don't know dst alingment 72 inc 2, %i0 73 dec 2, %i2 74 75aldst: andcc %i0, 3, %i5 ! align the destination address 76ald: bz,pn %icc, w4cp 77 cmp %i5, 2 78 bz,pn %icc, w2cp 79 cmp %i5, 3 80w3cp: lduw [%i1], %i4 81 inc 4, %i1 82 srl %i4, 24, %i5 83 stb %i5, [%i0] 84 bne,pt %icc, w1cp 85 inc %i0 86 dec 1, %i2 87 andn %i2, 3, %i3 ! i3 is aligned word count 88 dec 4, %i3 ! avoid reading beyond tail of src 89 sub %i1, %i0, %i1 ! i1 gets the difference 90 911: sll %i4, 8, %g1 ! save residual bytes 92 lduw [%i1+%i0], %i4 93 deccc 4, %i3 94 srl %i4, 24, %i5 ! merge with residual 95 or %i5, %g1, %g1 96 st %g1, [%i0] 97 bnz,pt %xcc, 1b 98 inc 4, %i0 99 sub %i1, 3, %i1 ! used one byte of last word read 100 and %i2, 3, %i2 101 b 7f 102 inc 4, %i2 103 104w1cp: srl %i4, 8, %i5 105 sth %i5, [%i0] 106 inc 2, %i0 107 dec 3, %i2 108 andn %i2, 3, %i3 109 dec 4, %i3 ! avoid reading beyond tail of src 110 sub %i1, %i0, %i1 ! i1 gets the difference 111 1122: sll %i4, 24, %g1 ! save residual bytes 113 lduw [%i1+%i0], %i4 114 deccc 4, %i3 115 srl %i4, 8, %i5 ! merge with residual 116 or %i5, %g1, %g1 117 st %g1, [%i0] 118 bnz,pt %xcc, 2b 119 inc 4, %i0 120 sub %i1, 1, %i1 ! used three bytes of last word read 121 and %i2, 3, %i2 122 b 7f 123 inc 4, %i2 124 125w2cp: lduw [%i1], %i4 126 inc 4, %i1 127 srl %i4, 16, %i5 128 sth %i5, [%i0] 129 inc 2, %i0 130 dec 2, %i2 131 andn %i2, 3, %i3 ! i3 is aligned word count 132 dec 4, %i3 ! avoid reading beyond tail of src 133 sub %i1, %i0, %i1 ! i1 gets the difference 134 1353: sll %i4, 16, %g1 ! save residual bytes 136 lduw [%i1+%i0], %i4 137 deccc 4, %i3 138 srl %i4, 16, %i5 ! merge with residual 139 or %i5, %g1, %g1 140 st %g1, [%i0] 141 bnz,pt %xcc, 3b 142 inc 4, %i0 143 sub %i1, 2, %i1 ! used two bytes of last word read 144 and %i2, 3, %i2 145 b 7f 146 inc 4, %i2 147 148w4cp: andn %i2, 3, %i3 ! i3 is aligned word count 149 sub %i1, %i0, %i1 ! i1 gets the difference 150 1511: lduw [%i1+%i0], %i4 ! read from address 152 deccc 4, %i3 ! decrement count 153 st %i4, [%i0] ! write at destination address 154 bg,pt %xcc, 1b 155 inc 4, %i0 ! increment to address 156 b 7f 157 and %i2, 3, %i2 ! number of leftover bytes, if any 158 159 ! 160 ! differenced byte copy, works with any alignment 161 ! 162dbytecp: 163 b 7f 164 sub %i1, %i0, %i1 ! i1 gets the difference 165 1664: stb %i4, [%i0] ! write to address 167 inc %i0 ! inc to address 1687: deccc %i2 ! decrement count 169 bge,a %xcc, 4b ! loop till done 170 ldub [%i1+%i0], %i4 ! read from address 171 ret 172 restore %l6, %g0, %o0 ! return pointer to destination 173 174 ! 175 ! an overlapped copy that must be done "backwards" 176 ! 177ovbc: add %i1, %i2, %i1 ! get to end of source space 178 add %i0, %i2, %i0 ! get to end of destination space 179 sub %i1, %i0, %i1 ! i1 gets the difference 180 1815: dec %i0 ! decrement to address 182 ldub [%i1+%i0], %i3 ! read a byte 183 deccc %i2 ! decrement count 184 bg,pt %xcc, 5b ! loop until done 185 stb %i3, [%i0] ! write byte 186 ret 187 restore %l6, %g0, %o0 ! return pointer to destination 188 189 SET_SIZE(memmove) 190