]> git.saurik.com Git - apple/boot.git/blame - gen/libsa/memset.c
boot-111.tar.gz
[apple/boot.git] / gen / libsa / memset.c
CommitLineData
14c7c974
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
f083c6c3
A
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
13 * file.
14c7c974
A
14 *
15 * The Original Code and all software distributed under the License are
f083c6c3 16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14c7c974
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
f083c6c3
A
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.
14c7c974
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
26 *
27 * File: libc/i386/ansi/memset.c
28 * Author: Bruce Martin, NeXT Computer, Inc.
29 *
30 * This file contains machine dependent code for block compares
31 * on NeXT i386-based products. Currently tuned for the i486.
32 *
33 * This code is loosely based on some work done by Mike DeMoney
34 * for the m88k.
35 *
36 * HISTORY
37 * 14-Dec-93 Curtis Galloway
38 * Modified for the booter; simplified simple_char_set.
39 *
40 * 14-Aug-92 Bruce Martin (Bruce_Martin@NeXT.COM)
41 * Created.
42 */
43
44#define MIN_TO_ALIGN 32
45
46/*
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.)
50 */
51#define UNS(voidp) ((unsigned int)(voidp))
52
53/*
54 * Number of bytes addr is past an object of 'align' size.
55 */
56#define BYTES_PAST_ALIGNMENT(voidp, align) \
57 (UNS(voidp) & (align - 1))
58
59/*
60 * Bytes moved by an unrolled loop
61 */
62#define LOOP_STRIDE(type, unroll) ((unroll) * sizeof(type))
63
64
65/*
66 * Len modulo LOOP_STRIDE
67 */
68#define MODULO_LOOP_UNROLL(len, type, unroll) \
69 ((len) & (LOOP_STRIDE(type, unroll) - 1) & ~(sizeof(type) - 1))
70
71
72/*
73 * Convert a void * + offset into char, short, int, or long long reference
74 * based at that address
75 */
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)))
79
80
81
82static inline void
83simple_char_set(char *dst, int val, int len)
84{
85 asm("rep; stosb"
86 : /* no outputs */
87 : "&c" (len), "D" (dst), "a" (val)
88 : "ecx", "edi", "eax");
89}
90
91
92
93void *memset(void *, int, unsigned long);
94
95int bzero(void *dst, unsigned long ulen)
96{
97 (void) memset(dst, 0, ulen);
98 return 0;
99}
100
101
102void *memset(void *dst, int val, unsigned long ulen)
103{
104 int len = ulen;
105 void *orig_dst = dst;
106 int need_to_set;
107 int alignment;
108
109 val |= (val << 8);
110 val |= (val << 16);
111
112 /* Always do a forward copy */
113
114 if (len < MIN_TO_ALIGN) {
115 simple_char_set(dst, val, len);
116 return orig_dst;
117 }
118
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);
122 len -= need_to_set;
123 UNS(dst) += need_to_set;
124 }
125
126 alignment = MODULO_LOOP_UNROLL(len, int, 8);
127 UNS(dst) += alignment - LOOP_STRIDE(int, 8);
128 switch (alignment) {
129 do {
130 INT(dst, 0) = val;
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;
138 case 0:
139 UNS(dst) += LOOP_STRIDE(int, 8);
140 len -= LOOP_STRIDE(int, 8);
141 } while (len >= 0);
142 len &= sizeof(int) - 1;
143 }
144
145 switch (len) {
146 case 3: CHAR(dst, 2) = val;
147 case 2: CHAR(dst, 1) = val;
148 case 1: CHAR(dst, 0) = val;
149 }
150
151 return orig_dst;
152}