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