|
|
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/memmove.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: * 9-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: ! 48: #define MIN_TO_ALIGN 16 ! 49: ! 50: /* ! 51: * Convert a void * into a unsigned int so arithmetic can be done ! 52: * (Technically, the gnu C compiler is tolerant of arithmetic ! 53: * on void *, but ansi isn't; so we do this.) ! 54: */ ! 55: #define UNS(voidp) ((unsigned int)(voidp)) ! 56: ! 57: /* ! 58: * Number of bytes addr is past an integer alignment ! 59: */ ! 60: #define BYTES_PAST_INT_ALIGNMENT(voidp) (UNS(voidp) & (sizeof(int) - 1)) ! 61: ! 62: #if defined(NX_CURRENT_COMPILER_RELEASE) && (NX_CURRENT_COMPILER_RELEASE < 320) ! 63: #define SIREG "e" ! 64: #else ! 65: #define SIREG "S" ! 66: #endif ! 67: ! 68: ! 69: static inline void ! 70: simple_fwd_char_copy(void *dst, const void *src, int len) ! 71: { ! 72: asm("rep; movsb" ! 73: : /* no outputs */ ! 74: : "&c" (len), "D" (dst), SIREG (src) ! 75: : "ecx", "esi", "edi"); ! 76: } ! 77: ! 78: static inline void ! 79: simple_bkwd_char_copy(void *dst, const void *src, int len) ! 80: { ! 81: /* NOTE: assumes DF flag is set */ ! 82: UNS(src)--; ! 83: UNS(dst)--; ! 84: asm("rep; movsb" ! 85: : /* no outputs */ ! 86: : "&c" (len), "D" (dst), SIREG (src) ! 87: : "ecx", "esi", "edi"); ! 88: } ! 89: ! 90: ! 91: static inline void ! 92: simple_fwd_int_copy(void *dst, const void *src, int len) ! 93: { ! 94: asm("rep; movsl" ! 95: : /* no outputs */ ! 96: : "&c" (len>>2), "D" (dst), SIREG (src) ! 97: : "ecx", "esi", "edi"); ! 98: } ! 99: ! 100: static inline void ! 101: simple_bkwd_int_copy(void *dst, const void *src, int len) ! 102: { ! 103: /* NOTE: assumes DF flag is set */ ! 104: UNS(dst) -= sizeof(int); ! 105: UNS(src) -= sizeof(int); ! 106: asm("rep; movsl" ! 107: : /* no outputs */ ! 108: : "&c" (len>>2), "D" (dst), SIREG (src) ! 109: : "ecx", "esi", "edi"); ! 110: } ! 111: ! 112: ! 113: void *memmove(void *, const void *, unsigned long); ! 114: ! 115: void bcopy(const void *src, void *dst, unsigned long ulen) ! 116: { ! 117: (void) memmove(dst, src, ulen); ! 118: } ! 119: ! 120: void ovbcopy(const void *src, void *dst, unsigned long ulen) ! 121: { ! 122: (void) memmove(dst, src, ulen); ! 123: } ! 124: ! 125: ! 126: void *memmove(void *dst, const void *src, unsigned long ulen) ! 127: { ! 128: int len = ulen; ! 129: int need_to_move; ! 130: void *orig_dst = dst; ! 131: ! 132: if ((dst <= src) || (src + ulen <= dst)) { ! 133: /* Forward copy */ ! 134: ! 135: if (len < MIN_TO_ALIGN) { ! 136: simple_fwd_char_copy(dst, src, len); ! 137: return orig_dst; ! 138: } ! 139: ! 140: if (need_to_move = BYTES_PAST_INT_ALIGNMENT(src)) { ! 141: need_to_move = sizeof(int) - need_to_move; ! 142: simple_fwd_char_copy(dst, src, need_to_move); ! 143: len -= need_to_move; ! 144: UNS(dst) += need_to_move; ! 145: UNS(src) += need_to_move; ! 146: } ! 147: ! 148: simple_fwd_int_copy(dst, src, len); ! 149: ! 150: if (need_to_move = (len & 3)) { ! 151: UNS(src) += (len & ~3); ! 152: UNS(dst) += (len & ~3); ! 153: simple_fwd_char_copy(dst, src, need_to_move); ! 154: } ! 155: } else { ! 156: /* Backward copy */ ! 157: ! 158: UNS(src) += len; ! 159: UNS(dst) += len; ! 160: ! 161: /* Set decrement bit */ ! 162: asm("std"); ! 163: ! 164: if (len <= MIN_TO_ALIGN) { ! 165: simple_bkwd_char_copy(dst, src, len); ! 166: /* Clear decrement bit */ ! 167: asm("cld"); ! 168: return orig_dst; ! 169: } ! 170: ! 171: if (need_to_move = BYTES_PAST_INT_ALIGNMENT(src)) { ! 172: simple_bkwd_char_copy(dst, src, need_to_move); ! 173: len -= need_to_move; ! 174: UNS(dst) -= need_to_move; ! 175: UNS(src) -= need_to_move; ! 176: } ! 177: ! 178: simple_bkwd_int_copy(dst, src, len); ! 179: ! 180: if (need_to_move = (len & 3)) { ! 181: UNS(src) -= (len & ~3); ! 182: UNS(dst) -= (len & ~3); ! 183: simple_bkwd_char_copy(dst, src, need_to_move); ! 184: } ! 185: ! 186: /* Clear decrement bit */ ! 187: asm("cld"); ! 188: } ! 189: return orig_dst; ! 190: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.