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