|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved. ! 26: * ! 27: * File: libc/i386/ansi/memcpy.c ! 28: * Author: Bruce Martin, NeXT Computer, Inc. ! 29: * ! 30: * This file contains machine dependent code for block copies ! 31: * on NeXT i386-based products. Currently tuned for the i486. ! 32: * ! 33: * HISTORY ! 34: * 12-Aug-92 Bruce Martin ([email protected]) ! 35: * Created. ! 36: */ ! 37: ! 38: ! 39: /* ! 40: * 486 Factoids: ! 41: * - if (move <= 16 bytes) use unrolled mem-mem mov instructions ! 42: * - if (move > 16 bytes) use "rep movs" [this avoids prefetch stalls] ! 43: * - Aligned read is better than aligned write. Both aligned is even better. ! 44: */ ! 45: ! 46: ! 47: #define MIN_TO_ALIGN 16 ! 48: ! 49: /* ! 50: * Convert a void * into a unsigned int so arithmetic can be done ! 51: * (Technically, the gnu C compiler is tolerant of arithmetic ! 52: * on void *, but ansi isn't; so we do this.) ! 53: */ ! 54: #define UNS(voidp) ((unsigned int)(voidp)) ! 55: ! 56: /* ! 57: * Number of bytes addr is past an integer alignment ! 58: */ ! 59: #define BYTES_PAST_INT_ALIGNMENT(voidp) (UNS(voidp) & (sizeof(int) - 1)) ! 60: ! 61: ! 62: #define CHAR(voidp, offset) (*(char *)(UNS(voidp) + (offset))) ! 63: ! 64: #if defined(NX_CURRENT_COMPILER_RELEASE) && (NX_CURRENT_COMPILER_RELEASE < 320) ! 65: #define SIREG "e" ! 66: #else ! 67: #define SIREG "S" ! 68: #endif ! 69: ! 70: ! 71: static __inline__ void ! 72: simple_fwd_char_copy(void *dst, const void *src, int len) ! 73: { ! 74: asm("rep; movsb" ! 75: : /* no outputs */ ! 76: : "&c" (len), "D" (dst), SIREG (src) ! 77: : "ecx", "esi", "edi"); ! 78: } ! 79: ! 80: static __inline__ void ! 81: simple_fwd_short_copy(void *dst, const void *src, int len) ! 82: { ! 83: asm("rep; movsw" ! 84: : /* no outputs */ ! 85: : "&c" (len>>1), "D" (dst), SIREG (src) ! 86: : "ecx", "esi", "edi"); ! 87: } ! 88: ! 89: static __inline__ void ! 90: simple_fwd_int_copy(void *dst, const void *src, int len) ! 91: { ! 92: asm("rep; movsl" ! 93: : /* no outputs */ ! 94: : "&c" (len>>2), "D" (dst), SIREG (src) ! 95: : "ecx", "esi", "edi"); ! 96: } ! 97: ! 98: ! 99: void *memcpy(void *, const void *, unsigned long); ! 100: ! 101: void *memcpy(void *dst, const void *src, unsigned long ulen) ! 102: { ! 103: int len = ulen; ! 104: int need_to_move; ! 105: void *orig_dst = dst; ! 106: ! 107: /* Always do a forward copy */ ! 108: ! 109: if (len < MIN_TO_ALIGN) { ! 110: simple_fwd_char_copy(dst, src, len); ! 111: return orig_dst; ! 112: } ! 113: ! 114: if (need_to_move = BYTES_PAST_INT_ALIGNMENT(src)) { ! 115: need_to_move = sizeof(int) - need_to_move; ! 116: simple_fwd_char_copy(dst, src, need_to_move); ! 117: len -= need_to_move; ! 118: UNS(dst) += need_to_move; ! 119: UNS(src) += need_to_move; ! 120: } ! 121: ! 122: simple_fwd_int_copy(dst, src, len); ! 123: ! 124: if (need_to_move = (len & 3)) { ! 125: UNS(src) += (len & ~3); ! 126: UNS(dst) += (len & ~3); ! 127: switch(need_to_move) { ! 128: case 3: CHAR(dst, 2) = CHAR(src, 2); ! 129: case 2: CHAR(dst, 1) = CHAR(src, 1); ! 130: case 1: CHAR(dst, 0) = CHAR(src, 0); ! 131: } ! 132: } ! 133: return orig_dst; ! 134: } ! 135: ! 136: ! 137: /* ! 138: * Exactly the same as memcpy, except for the use of a 16-bit word ! 139: * move in the inner loop. ! 140: */ ! 141: void bcopy16(const void *src, void *dst, unsigned long ulen) ! 142: { ! 143: int len = ulen; ! 144: int need_to_move; ! 145: ! 146: /* Always do a forward copy */ ! 147: ! 148: if (len < MIN_TO_ALIGN) { ! 149: simple_fwd_char_copy(dst, src, len); ! 150: return; ! 151: } ! 152: ! 153: if (need_to_move = BYTES_PAST_INT_ALIGNMENT(src)) { ! 154: need_to_move = sizeof(int) - need_to_move; ! 155: simple_fwd_char_copy(dst, src, need_to_move); ! 156: len -= need_to_move; ! 157: UNS(dst) += need_to_move; ! 158: UNS(src) += need_to_move; ! 159: } ! 160: ! 161: simple_fwd_short_copy(dst, src, len); ! 162: ! 163: if (need_to_move = (len & 1)) { ! 164: UNS(src) += (len & ~1); ! 165: UNS(dst) += (len & ~1); ! 166: if (need_to_move) { ! 167: CHAR(dst, 0) = CHAR(src, 0); ! 168: } ! 169: } ! 170: return; ! 171: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.