|
|
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: /* Copyright (c) 1992 by NeXT Computer, Inc.
25: *
26: * File: memcpy.c
27: *
28: * HISTORY
29: * 16-Aug-93 John Immordino at NeXT
30: * Created (stolen from mk/machdep/i386/libc/memcpy.c)
31: */
32:
33: #import <driverkit/driverTypes.h>
34:
35: /*
36: * 486 Facts:
37: * - if (move <= 16 bytes) use unrolled mem-mem mov instructions
38: * - if (move > 16 bytes) use "rep movs" [this avoids prefetch stalls]
39: * - Aligned read is better than aligned write. Both aligned is even better.
40: */
41:
42: #define MIN_TO_ALIGN 16
43:
44: /*
45: * Convert a void * into a unsigned int so arithmetic can be done
46: * (Technically, the gnu C compiler is tolerant of arithmetic
47: * on void *, but ansi isn't; so we do this.)
48: */
49: #define UNS(voidp) ((unsigned int)(voidp))
50:
51: /*
52: * Number of bytes addr is past an integer alignment
53: */
54: #define BYTES_PAST_ALIGNMENT(voidp, boundary) (UNS(voidp) & (boundary - 1))
55:
56: #if defined(NX_CURRENT_COMPILER_RELEASE) && (NX_CURRENT_COMPILER_RELEASE < 320)
57: #define SIREG "e"
58: #else
59: #define SIREG "S"
60: #endif
61:
62: #define CHAR(voidp, offset) (*(char *)(UNS(voidp) + (offset)))
63:
64: static __inline__ void
65: simple_fwd_char_copy(void *dst, const void *src, int len)
66: {
67: asm("rep; movsb"
68: : /* no outputs */
69: : "&c" (len), "D" (dst), SIREG (src)
70: : "ecx", "esi", "edi");
71: }
72:
73: static __inline__ void
74: simple_fwd_short_copy(void *dst, const void *src, int len)
75: {
76: asm("rep; movsw"
77: : /* no outputs */
78: : "&c" (len>>1), "D" (dst), SIREG (src)
79: : "ecx", "esi", "edi");
80: }
81:
82: static __inline__ void
83: simple_fwd_int_copy(void *dst, const void *src, int len)
84: {
85: asm("rep; movsl"
86: : /* no outputs */
87: : "&c" (len>>2), "D" (dst), SIREG (src)
88: : "ecx", "esi", "edi");
89: }
90:
91:
92: void _IOCopyMemory(char *src, char *dst, unsigned copyLen,
93: unsigned copyUnitSize)
94: {
95: int need_to_move;
96:
97: if (src == NULL || dst == NULL || src == dst || copyLen == 0)
98: return;
99:
100: /*
101: * Sanity check copyUnitSize
102: */
103: if (copyUnitSize == 0)
104: copyUnitSize = 1;
105: if (copyUnitSize > 2)
106: copyUnitSize = 4;
107:
108: /*
109: * Always do a forward copy. See if we need
110: * a byte-size copy.
111: */
112: if (copyUnitSize == 1) {
113: simple_fwd_char_copy(dst, src, (int)copyLen);
114: return;
115: }
116:
117: /*
118: * Copy bytes up to a copyUnitSize boundary.
119: */
120: if (need_to_move = BYTES_PAST_ALIGNMENT(src, copyUnitSize)) {
121: need_to_move = copyUnitSize - need_to_move;
122: simple_fwd_char_copy(dst, src, need_to_move);
123: copyLen -= need_to_move;
124: UNS(dst) += need_to_move;
125: UNS(src) += need_to_move;
126: }
127:
128: /*
129: * Copy what we can at maximum specified size.
130: */
131: if (copyUnitSize == 2)
132: simple_fwd_short_copy(dst, src, (int)copyLen);
133: else
134: simple_fwd_int_copy(dst, src, (int)copyLen);
135:
136: /*
137: * Get the leftovers.
138: */
139: if (need_to_move = (copyLen & (copyUnitSize - 1))) {
140: UNS(src) += (copyLen & ~(copyUnitSize - 1));
141: UNS(dst) += (copyLen & ~(copyUnitSize - 1));
142: switch(need_to_move) {
143: case 3: CHAR(dst, 2) = CHAR(src, 2);
144: case 2: CHAR(dst, 1) = CHAR(src, 1);
145: case 1: CHAR(dst, 0) = CHAR(src, 0);
146: }
147: }
148: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.