10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 56812Sraf * Common Development and Distribution License (the "License"). 66812Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 216812Sraf 220Sstevel@tonic-gate/* 236812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 246812Sraf * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 27*7298SMark.J.Nelson@Sun.COM .file "memmove.s" 280Sstevel@tonic-gate 290Sstevel@tonic-gate#include <sys/asm_linkage.h> 300Sstevel@tonic-gate 310Sstevel@tonic-gate ANSI_PRAGMA_WEAK(memmove,function) 320Sstevel@tonic-gate 330Sstevel@tonic-gate/* 340Sstevel@tonic-gate * memmove(s1, s2, len) 350Sstevel@tonic-gate * Copy s2 to s1, always copy n bytes. 360Sstevel@tonic-gate * For overlapped copies it does the right thing. 370Sstevel@tonic-gate */ 380Sstevel@tonic-gate ENTRY(memmove) 390Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp ! not a leaf routine any more 400Sstevel@tonic-gate mov %i0, %l6 ! Save pointer to destination 410Sstevel@tonic-gate cmp %i1, %i0 ! if from address is >= to use forward copy 420Sstevel@tonic-gate bgeu,a 2f ! else use backward if ... 430Sstevel@tonic-gate cmp %i2, 17 ! delay slot, for small counts copy bytes 440Sstevel@tonic-gate 450Sstevel@tonic-gate sub %i0, %i1, %i4 ! get difference of two addresses 460Sstevel@tonic-gate cmp %i2, %i4 ! compare size and difference of addresses 470Sstevel@tonic-gate bgu ovbc ! if size is bigger, have do overlapped copy 480Sstevel@tonic-gate cmp %i2, 17 ! delay slot, for small counts copy bytes 490Sstevel@tonic-gate ! 500Sstevel@tonic-gate ! normal, copy forwards 510Sstevel@tonic-gate ! 520Sstevel@tonic-gate2: ble dbytecp 530Sstevel@tonic-gate andcc %i1, 3, %i5 ! is src word aligned 540Sstevel@tonic-gate bz aldst 550Sstevel@tonic-gate cmp %i5, 2 ! is src half-word aligned 560Sstevel@tonic-gate be s2algn 570Sstevel@tonic-gate cmp %i5, 3 ! src is byte aligned 580Sstevel@tonic-gates1algn: ldub [%i1], %i3 ! move 1 or 3 bytes to align it 590Sstevel@tonic-gate inc 1, %i1 600Sstevel@tonic-gate stb %i3, [%i0] ! move a byte to align src 610Sstevel@tonic-gate inc 1, %i0 620Sstevel@tonic-gate bne s2algn 630Sstevel@tonic-gate dec %i2 640Sstevel@tonic-gate b ald ! now go align dest 650Sstevel@tonic-gate andcc %i0, 3, %i5 660Sstevel@tonic-gate 670Sstevel@tonic-gates2algn: lduh [%i1], %i3 ! know src is 2 byte alinged 680Sstevel@tonic-gate inc 2, %i1 690Sstevel@tonic-gate srl %i3, 8, %i4 700Sstevel@tonic-gate stb %i4, [%i0] ! have to do bytes, 710Sstevel@tonic-gate stb %i3, [%i0 + 1] ! don't know dst alingment 720Sstevel@tonic-gate inc 2, %i0 730Sstevel@tonic-gate dec 2, %i2 740Sstevel@tonic-gate 750Sstevel@tonic-gatealdst: andcc %i0, 3, %i5 ! align the destination address 760Sstevel@tonic-gateald: bz w4cp 770Sstevel@tonic-gate cmp %i5, 2 780Sstevel@tonic-gate bz w2cp 790Sstevel@tonic-gate cmp %i5, 3 800Sstevel@tonic-gatew3cp: ld [%i1], %i4 810Sstevel@tonic-gate inc 4, %i1 820Sstevel@tonic-gate srl %i4, 24, %i5 830Sstevel@tonic-gate stb %i5, [%i0] 840Sstevel@tonic-gate bne w1cp 850Sstevel@tonic-gate inc %i0 860Sstevel@tonic-gate dec 1, %i2 870Sstevel@tonic-gate andn %i2, 3, %i3 ! i3 is aligned word count 880Sstevel@tonic-gate dec 4, %i3 ! avoid reading beyond tail of src 890Sstevel@tonic-gate sub %i1, %i0, %i1 ! i1 gets the difference 900Sstevel@tonic-gate 910Sstevel@tonic-gate1: sll %i4, 8, %g1 ! save residual bytes 920Sstevel@tonic-gate ld [%i1+%i0], %i4 930Sstevel@tonic-gate deccc 4, %i3 940Sstevel@tonic-gate srl %i4, 24, %i5 ! merge with residual 950Sstevel@tonic-gate or %i5, %g1, %g1 960Sstevel@tonic-gate st %g1, [%i0] 970Sstevel@tonic-gate bnz 1b 980Sstevel@tonic-gate inc 4, %i0 990Sstevel@tonic-gate sub %i1, 3, %i1 ! used one byte of last word read 1000Sstevel@tonic-gate and %i2, 3, %i2 1010Sstevel@tonic-gate b 7f 1020Sstevel@tonic-gate inc 4, %i2 1030Sstevel@tonic-gate 1040Sstevel@tonic-gatew1cp: srl %i4, 8, %i5 1050Sstevel@tonic-gate sth %i5, [%i0] 1060Sstevel@tonic-gate inc 2, %i0 1070Sstevel@tonic-gate dec 3, %i2 1080Sstevel@tonic-gate andn %i2, 3, %i3 1090Sstevel@tonic-gate dec 4, %i3 ! avoid reading beyond tail of src 1100Sstevel@tonic-gate sub %i1, %i0, %i1 ! i1 gets the difference 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate2: sll %i4, 24, %g1 ! save residual bytes 1130Sstevel@tonic-gate ld [%i1+%i0], %i4 1140Sstevel@tonic-gate deccc 4, %i3 1150Sstevel@tonic-gate srl %i4, 8, %i5 ! merge with residual 1160Sstevel@tonic-gate or %i5, %g1, %g1 1170Sstevel@tonic-gate st %g1, [%i0] 1180Sstevel@tonic-gate bnz 2b 1190Sstevel@tonic-gate inc 4, %i0 1200Sstevel@tonic-gate sub %i1, 1, %i1 ! used three bytes of last word read 1210Sstevel@tonic-gate and %i2, 3, %i2 1220Sstevel@tonic-gate b 7f 1230Sstevel@tonic-gate inc 4, %i2 1240Sstevel@tonic-gate 1250Sstevel@tonic-gatew2cp: ld [%i1], %i4 1260Sstevel@tonic-gate inc 4, %i1 1270Sstevel@tonic-gate srl %i4, 16, %i5 1280Sstevel@tonic-gate sth %i5, [%i0] 1290Sstevel@tonic-gate inc 2, %i0 1300Sstevel@tonic-gate dec 2, %i2 1310Sstevel@tonic-gate andn %i2, 3, %i3 ! i3 is aligned word count 1320Sstevel@tonic-gate dec 4, %i3 ! avoid reading beyond tail of src 1330Sstevel@tonic-gate sub %i1, %i0, %i1 ! i1 gets the difference 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate3: sll %i4, 16, %g1 ! save residual bytes 1360Sstevel@tonic-gate ld [%i1+%i0], %i4 1370Sstevel@tonic-gate deccc 4, %i3 1380Sstevel@tonic-gate srl %i4, 16, %i5 ! merge with residual 1390Sstevel@tonic-gate or %i5, %g1, %g1 1400Sstevel@tonic-gate st %g1, [%i0] 1410Sstevel@tonic-gate bnz 3b 1420Sstevel@tonic-gate inc 4, %i0 1430Sstevel@tonic-gate sub %i1, 2, %i1 ! used two bytes of last word read 1440Sstevel@tonic-gate and %i2, 3, %i2 1450Sstevel@tonic-gate b 7f 1460Sstevel@tonic-gate inc 4, %i2 1470Sstevel@tonic-gate 1480Sstevel@tonic-gatew4cp: andn %i2, 3, %i3 ! i3 is aligned word count 1490Sstevel@tonic-gate sub %i1, %i0, %i1 ! i1 gets the difference 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate1: ld [%i1+%i0], %i4 ! read from address 1520Sstevel@tonic-gate deccc 4, %i3 ! decrement count 1530Sstevel@tonic-gate st %i4, [%i0] ! write at destination address 1540Sstevel@tonic-gate bg 1b 1550Sstevel@tonic-gate inc 4, %i0 ! increment to address 1560Sstevel@tonic-gate b 7f 1570Sstevel@tonic-gate and %i2, 3, %i2 ! number of leftover bytes, if any 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate ! 1600Sstevel@tonic-gate ! differenced byte copy, works with any alignment 1610Sstevel@tonic-gate ! 1620Sstevel@tonic-gatedbytecp: 1630Sstevel@tonic-gate b 7f 1640Sstevel@tonic-gate sub %i1, %i0, %i1 ! i1 gets the difference 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate4: stb %i4, [%i0] ! write to address 1670Sstevel@tonic-gate inc %i0 ! inc to address 1680Sstevel@tonic-gate7: deccc %i2 ! decrement count 1690Sstevel@tonic-gate bge,a 4b ! loop till done 1700Sstevel@tonic-gate ldub [%i1+%i0], %i4 ! read from address 1710Sstevel@tonic-gate ret 1720Sstevel@tonic-gate restore %l6, %g0, %o0 ! return pointer to destination 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate ! 1750Sstevel@tonic-gate ! an overlapped copy that must be done "backwards" 1760Sstevel@tonic-gate ! 1770Sstevel@tonic-gateovbc: add %i1, %i2, %i1 ! get to end of source space 1780Sstevel@tonic-gate add %i0, %i2, %i0 ! get to end of destination space 1790Sstevel@tonic-gate sub %i1, %i0, %i1 ! i1 gets the difference 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate5: dec %i0 ! decrement to address 1820Sstevel@tonic-gate ldub [%i1+%i0], %i3 ! read a byte 1830Sstevel@tonic-gate deccc %i2 ! decrement count 1840Sstevel@tonic-gate bg 5b ! loop until done 1850Sstevel@tonic-gate stb %i3, [%i0] ! write byte 1860Sstevel@tonic-gate ret 1870Sstevel@tonic-gate restore %l6, %g0, %o0 ! return pointer to destination 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate SET_SIZE(memmove) 190