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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 .file "memcpy.s" 27 28/* 29 * memcpy(s1, s2, len) 30 * 31 * Copy s2 to s1, always copy n bytes. 32 * Note: this does not work for overlapped copies, bcopy() does 33 * 34 * Fast assembler language version of the following C-program for memcpy 35 * which represents the `standard' for the C-library. 36 * 37 * void * 38 * memcpy(void *s, const void *s0, size_t n) 39 * { 40 * if (n != 0) { 41 * char *s1 = s; 42 * const char *s2 = s0; 43 * do { 44 * *s1++ = *s2++; 45 * } while (--n != 0); 46 * } 47 * return (s); 48 * } 49 */ 50 51#include "SYS.h" 52 53 ANSI_PRAGMA_WEAK(memcpy,function) 54 55 ENTRY(memcpy) 56 ENTRY(__align_cpy_1) 57 st %o0, [%sp + 68] ! save des address for return val 58 cmp %o2, 17 ! for small counts copy bytes 59 bleu .dbytecp 60 andcc %o1, 3, %o5 ! is src word aligned 61 bz .aldst 62 cmp %o5, 2 ! is src half-word aligned 63 be .s2algn 64 cmp %o5, 3 ! src is byte aligned 65.s1algn:ldub [%o1], %o3 ! move 1 or 3 bytes to align it 66 inc 1, %o1 67 stb %o3, [%o0] ! move a byte to align src 68 inc 1, %o0 69 bne .s2algn 70 dec %o2 71 b .ald ! now go align dest 72 andcc %o0, 3, %o5 73 74.s2algn:lduh [%o1], %o3 ! know src is 2 byte alinged 75 inc 2, %o1 76 srl %o3, 8, %o4 77 stb %o4, [%o0] ! have to do bytes, 78 stb %o3, [%o0 + 1] ! don't know dst alingment 79 inc 2, %o0 80 dec 2, %o2 81 82.aldst: andcc %o0, 3, %o5 ! align the destination address 83.ald: bz .w4cp 84 cmp %o5, 2 85 bz .w2cp 86 cmp %o5, 3 87.w3cp: ld [%o1], %o4 88 inc 4, %o1 89 srl %o4, 24, %o5 90 stb %o5, [%o0] 91 bne .w1cp 92 inc %o0 93 dec 1, %o2 94 andn %o2, 3, %o3 ! o3 is aligned word count 95 dec 4, %o3 ! avoid reading beyond tail of src 96 sub %o1, %o0, %o1 ! o1 gets the difference 97 981: sll %o4, 8, %g1 ! save residual bytes 99 ld [%o1+%o0], %o4 100 deccc 4, %o3 101 srl %o4, 24, %o5 ! merge with residual 102 or %o5, %g1, %g1 103 st %g1, [%o0] 104 bnz 1b 105 inc 4, %o0 106 sub %o1, 3, %o1 ! used one byte of last word read 107 and %o2, 3, %o2 108 b 7f 109 inc 4, %o2 110 111.w1cp: srl %o4, 8, %o5 112 sth %o5, [%o0] 113 inc 2, %o0 114 dec 3, %o2 115 andn %o2, 3, %o3 ! o3 is aligned word count 116 dec 4, %o3 ! avoid reading beyond tail of src 117 sub %o1, %o0, %o1 ! o1 gets the difference 118 1192: sll %o4, 24, %g1 ! save residual bytes 120 ld [%o1+%o0], %o4 121 deccc 4, %o3 122 srl %o4, 8, %o5 ! merge with residual 123 or %o5, %g1, %g1 124 st %g1, [%o0] 125 bnz 2b 126 inc 4, %o0 127 sub %o1, 1, %o1 ! used three bytes of last word read 128 and %o2, 3, %o2 129 b 7f 130 inc 4, %o2 131 132.w2cp: ld [%o1], %o4 133 inc 4, %o1 134 srl %o4, 16, %o5 135 sth %o5, [%o0] 136 inc 2, %o0 137 dec 2, %o2 138 andn %o2, 3, %o3 ! o3 is aligned word count 139 dec 4, %o3 ! avoid reading beyond tail of src 140 sub %o1, %o0, %o1 ! o1 gets the difference 141 1423: sll %o4, 16, %g1 ! save residual bytes 143 ld [%o1+%o0], %o4 144 deccc 4, %o3 145 srl %o4, 16, %o5 ! merge with residual 146 or %o5, %g1, %g1 147 st %g1, [%o0] 148 bnz 3b 149 inc 4, %o0 150 sub %o1, 2, %o1 ! used two bytes of last word read 151 and %o2, 3, %o2 152 b 7f 153 inc 4, %o2 154 155.w4cp: andn %o2, 3, %o3 ! o3 is aligned word count 156 sub %o1, %o0, %o1 ! o1 gets the difference 157 1581: ld [%o1+%o0], %o4 ! read from address 159 deccc 4, %o3 ! decrement count 160 st %o4, [%o0] ! write at destination address 161 bgu 1b 162 inc 4, %o0 ! increment to address 163 b 7f 164 and %o2, 3, %o2 ! number of leftover bytes, if any 165 166 ! 167 ! differenced byte copy, works with any alignment 168 ! 169.dbytecp: 170 b 7f 171 sub %o1, %o0, %o1 ! o1 gets the difference 172 1734: stb %o4, [%o0] ! write to address 174 inc %o0 ! inc to address 1757: deccc %o2 ! decrement count 176 bgeu,a 4b ! loop till done 177 ldub [%o1+%o0], %o4 ! read from address 178 retl 179 ld [%sp + 68], %o0 ! return s1, destination address 180 181 SET_SIZE(memcpy) 182