1*0Sstevel@tonic-gate/* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate/* 23*0Sstevel@tonic-gate * Copyright 1987-2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate .ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate .file "%M%" 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate/* 32*0Sstevel@tonic-gate * memcpy(s1, s2, len) 33*0Sstevel@tonic-gate * 34*0Sstevel@tonic-gate * Copy s2 to s1, always copy n bytes. 35*0Sstevel@tonic-gate * Note: this does not work for overlapped copies, bcopy() does 36*0Sstevel@tonic-gate * 37*0Sstevel@tonic-gate * Fast assembler language version of the following C-program for memcpy 38*0Sstevel@tonic-gate * which represents the `standard' for the C-library. 39*0Sstevel@tonic-gate * 40*0Sstevel@tonic-gate * void * 41*0Sstevel@tonic-gate * memcpy(void *s, const void *s0, size_t n) 42*0Sstevel@tonic-gate * { 43*0Sstevel@tonic-gate * if (n != 0) { 44*0Sstevel@tonic-gate * char *s1 = s; 45*0Sstevel@tonic-gate * const char *s2 = s0; 46*0Sstevel@tonic-gate * do { 47*0Sstevel@tonic-gate * *s1++ = *s2++; 48*0Sstevel@tonic-gate * } while (--n != 0); 49*0Sstevel@tonic-gate * } 50*0Sstevel@tonic-gate * return (s); 51*0Sstevel@tonic-gate * } 52*0Sstevel@tonic-gate */ 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate#include <sys/asm_linkage.h> 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate ANSI_PRAGMA_WEAK(memcpy,function) 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate#include "synonyms.h" 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate .weak _private_memcpy 61*0Sstevel@tonic-gate .type _private_memcpy, #function 62*0Sstevel@tonic-gate _private_memcpy = memcpy 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate ENTRY(memcpy) 65*0Sstevel@tonic-gate st %o0, [%sp + 68] ! save des address for return val 66*0Sstevel@tonic-gate cmp %o2, 17 ! for small counts copy bytes 67*0Sstevel@tonic-gate bleu .dbytecp 68*0Sstevel@tonic-gate andcc %o1, 3, %o5 ! is src word aligned 69*0Sstevel@tonic-gate bz .aldst 70*0Sstevel@tonic-gate cmp %o5, 2 ! is src half-word aligned 71*0Sstevel@tonic-gate be .s2algn 72*0Sstevel@tonic-gate cmp %o5, 3 ! src is byte aligned 73*0Sstevel@tonic-gate.s1algn:ldub [%o1], %o3 ! move 1 or 3 bytes to align it 74*0Sstevel@tonic-gate inc 1, %o1 75*0Sstevel@tonic-gate stb %o3, [%o0] ! move a byte to align src 76*0Sstevel@tonic-gate inc 1, %o0 77*0Sstevel@tonic-gate bne .s2algn 78*0Sstevel@tonic-gate dec %o2 79*0Sstevel@tonic-gate b .ald ! now go align dest 80*0Sstevel@tonic-gate andcc %o0, 3, %o5 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate.s2algn:lduh [%o1], %o3 ! know src is 2 byte alinged 83*0Sstevel@tonic-gate inc 2, %o1 84*0Sstevel@tonic-gate srl %o3, 8, %o4 85*0Sstevel@tonic-gate stb %o4, [%o0] ! have to do bytes, 86*0Sstevel@tonic-gate stb %o3, [%o0 + 1] ! don't know dst alingment 87*0Sstevel@tonic-gate inc 2, %o0 88*0Sstevel@tonic-gate dec 2, %o2 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate.aldst: andcc %o0, 3, %o5 ! align the destination address 91*0Sstevel@tonic-gate.ald: bz .w4cp 92*0Sstevel@tonic-gate cmp %o5, 2 93*0Sstevel@tonic-gate bz .w2cp 94*0Sstevel@tonic-gate cmp %o5, 3 95*0Sstevel@tonic-gate.w3cp: ld [%o1], %o4 96*0Sstevel@tonic-gate inc 4, %o1 97*0Sstevel@tonic-gate srl %o4, 24, %o5 98*0Sstevel@tonic-gate stb %o5, [%o0] 99*0Sstevel@tonic-gate bne .w1cp 100*0Sstevel@tonic-gate inc %o0 101*0Sstevel@tonic-gate dec 1, %o2 102*0Sstevel@tonic-gate andn %o2, 3, %o3 ! o3 is aligned word count 103*0Sstevel@tonic-gate dec 4, %o3 ! avoid reading beyond tail of src 104*0Sstevel@tonic-gate sub %o1, %o0, %o1 ! o1 gets the difference 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate1: sll %o4, 8, %g1 ! save residual bytes 107*0Sstevel@tonic-gate ld [%o1+%o0], %o4 108*0Sstevel@tonic-gate deccc 4, %o3 109*0Sstevel@tonic-gate srl %o4, 24, %o5 ! merge with residual 110*0Sstevel@tonic-gate or %o5, %g1, %g1 111*0Sstevel@tonic-gate st %g1, [%o0] 112*0Sstevel@tonic-gate bnz 1b 113*0Sstevel@tonic-gate inc 4, %o0 114*0Sstevel@tonic-gate sub %o1, 3, %o1 ! used one byte of last word read 115*0Sstevel@tonic-gate and %o2, 3, %o2 116*0Sstevel@tonic-gate b 7f 117*0Sstevel@tonic-gate inc 4, %o2 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate.w1cp: srl %o4, 8, %o5 120*0Sstevel@tonic-gate sth %o5, [%o0] 121*0Sstevel@tonic-gate inc 2, %o0 122*0Sstevel@tonic-gate dec 3, %o2 123*0Sstevel@tonic-gate andn %o2, 3, %o3 ! o3 is aligned word count 124*0Sstevel@tonic-gate dec 4, %o3 ! avoid reading beyond tail of src 125*0Sstevel@tonic-gate sub %o1, %o0, %o1 ! o1 gets the difference 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate2: sll %o4, 24, %g1 ! save residual bytes 128*0Sstevel@tonic-gate ld [%o1+%o0], %o4 129*0Sstevel@tonic-gate deccc 4, %o3 130*0Sstevel@tonic-gate srl %o4, 8, %o5 ! merge with residual 131*0Sstevel@tonic-gate or %o5, %g1, %g1 132*0Sstevel@tonic-gate st %g1, [%o0] 133*0Sstevel@tonic-gate bnz 2b 134*0Sstevel@tonic-gate inc 4, %o0 135*0Sstevel@tonic-gate sub %o1, 1, %o1 ! used three bytes of last word read 136*0Sstevel@tonic-gate and %o2, 3, %o2 137*0Sstevel@tonic-gate b 7f 138*0Sstevel@tonic-gate inc 4, %o2 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate.w2cp: ld [%o1], %o4 141*0Sstevel@tonic-gate inc 4, %o1 142*0Sstevel@tonic-gate srl %o4, 16, %o5 143*0Sstevel@tonic-gate sth %o5, [%o0] 144*0Sstevel@tonic-gate inc 2, %o0 145*0Sstevel@tonic-gate dec 2, %o2 146*0Sstevel@tonic-gate andn %o2, 3, %o3 ! o3 is aligned word count 147*0Sstevel@tonic-gate dec 4, %o3 ! avoid reading beyond tail of src 148*0Sstevel@tonic-gate sub %o1, %o0, %o1 ! o1 gets the difference 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate3: sll %o4, 16, %g1 ! save residual bytes 151*0Sstevel@tonic-gate ld [%o1+%o0], %o4 152*0Sstevel@tonic-gate deccc 4, %o3 153*0Sstevel@tonic-gate srl %o4, 16, %o5 ! merge with residual 154*0Sstevel@tonic-gate or %o5, %g1, %g1 155*0Sstevel@tonic-gate st %g1, [%o0] 156*0Sstevel@tonic-gate bnz 3b 157*0Sstevel@tonic-gate inc 4, %o0 158*0Sstevel@tonic-gate sub %o1, 2, %o1 ! used two bytes of last word read 159*0Sstevel@tonic-gate and %o2, 3, %o2 160*0Sstevel@tonic-gate b 7f 161*0Sstevel@tonic-gate inc 4, %o2 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate.w4cp: andn %o2, 3, %o3 ! o3 is aligned word count 164*0Sstevel@tonic-gate sub %o1, %o0, %o1 ! o1 gets the difference 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate1: ld [%o1+%o0], %o4 ! read from address 167*0Sstevel@tonic-gate deccc 4, %o3 ! decrement count 168*0Sstevel@tonic-gate st %o4, [%o0] ! write at destination address 169*0Sstevel@tonic-gate bgu 1b 170*0Sstevel@tonic-gate inc 4, %o0 ! increment to address 171*0Sstevel@tonic-gate b 7f 172*0Sstevel@tonic-gate and %o2, 3, %o2 ! number of leftover bytes, if any 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate ! 175*0Sstevel@tonic-gate ! differenced byte copy, works with any alignment 176*0Sstevel@tonic-gate ! 177*0Sstevel@tonic-gate.dbytecp: 178*0Sstevel@tonic-gate b 7f 179*0Sstevel@tonic-gate sub %o1, %o0, %o1 ! o1 gets the difference 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate4: stb %o4, [%o0] ! write to address 182*0Sstevel@tonic-gate inc %o0 ! inc to address 183*0Sstevel@tonic-gate7: deccc %o2 ! decrement count 184*0Sstevel@tonic-gate bgeu,a 4b ! loop till done 185*0Sstevel@tonic-gate ldub [%o1+%o0], %o4 ! read from address 186*0Sstevel@tonic-gate retl 187*0Sstevel@tonic-gate ld [%sp + 68], %o0 ! return s1, destination address 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate SET_SIZE(memcpy) 190