]>
git.saurik.com Git - apple/boot.git/blob - gen/libsa/memset.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
27 * File: libc/i386/ansi/memset.c
28 * Author: Bruce Martin, NeXT Computer, Inc.
30 * This file contains machine dependent code for block compares
31 * on NeXT i386-based products. Currently tuned for the i486.
33 * This code is loosely based on some work done by Mike DeMoney
37 * 14-Dec-93 Curtis Galloway
38 * Modified for the booter; simplified simple_char_set.
40 * 14-Aug-92 Bruce Martin (Bruce_Martin@NeXT.COM)
44 #define MIN_TO_ALIGN 32
47 * Convert a void * into a unsigned int so arithmetic can be done
48 * (Technically, the gnu C compiler is tolerant of arithmetic
49 * on void *, but ansi isn't; so we do this.)
51 #define UNS(voidp) ((unsigned int)(voidp))
54 * Number of bytes addr is past an object of 'align' size.
56 #define BYTES_PAST_ALIGNMENT(voidp, align) \
57 (UNS(voidp) & (align - 1))
60 * Bytes moved by an unrolled loop
62 #define LOOP_STRIDE(type, unroll) ((unroll) * sizeof(type))
66 * Len modulo LOOP_STRIDE
68 #define MODULO_LOOP_UNROLL(len, type, unroll) \
69 ((len) & (LOOP_STRIDE(type, unroll) - 1) & ~(sizeof(type) - 1))
73 * Convert a void * + offset into char, short, int, or long long reference
74 * based at that address
76 #define CHAR(voidp, offset) (*(char *)(UNS(voidp) + (offset)))
77 #define SHORT(voidp, offset) (*(short *)(UNS(voidp) + (offset)))
78 #define INT(voidp, offset) (*(int *)(UNS(voidp) + (offset)))
83 simple_char_set(char *dst
, int val
, int len
)
87 : "&c" (len
), "D" (dst
), "a" (val
)
88 : "ecx", "edi", "eax");
93 void *memset(void *, int, unsigned long);
95 int bzero(void *dst
, unsigned long ulen
)
97 (void) memset(dst
, 0, ulen
);
102 void *memset(void *dst
, int val
, unsigned long ulen
)
105 void *orig_dst
= dst
;
112 /* Always do a forward copy */
114 if (len
< MIN_TO_ALIGN
) {
115 simple_char_set(dst
, val
, len
);
119 if (need_to_set
= BYTES_PAST_ALIGNMENT(dst
, 2 * sizeof(int))) {
120 need_to_set
= (2 * sizeof(int)) - need_to_set
;
121 simple_char_set(dst
, val
, need_to_set
);
123 UNS(dst
) += need_to_set
;
126 alignment
= MODULO_LOOP_UNROLL(len
, int, 8);
127 UNS(dst
) += alignment
- LOOP_STRIDE(int, 8);
131 case 28: INT(dst
, 4) = val
;
132 case 24: INT(dst
, 8) = val
;
133 case 20: INT(dst
, 12) = val
;
134 case 16: INT(dst
, 16) = val
;
135 case 12: INT(dst
, 20) = val
;
136 case 8: INT(dst
, 24) = val
;
137 case 4: INT(dst
, 28) = val
;
139 UNS(dst
) += LOOP_STRIDE(int, 8);
140 len
-= LOOP_STRIDE(int, 8);
142 len
&= sizeof(int) - 1;
146 case 3: CHAR(dst
, 2) = val
;
147 case 2: CHAR(dst
, 1) = val
;
148 case 1: CHAR(dst
, 0) = val
;