|
|
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/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-Aug-92 Bruce Martin ([email protected])
38: * Created.
39: */
40:
41: #define MIN_TO_ALIGN 32
42:
43: /*
44: * Convert a void * into a unsigned int so arithmetic can be done
45: * (Technically, the gnu C compiler is tolerant of arithmetic
46: * on void *, but ansi isn't; so we do this.)
47: */
48: #define UNS(voidp) ((unsigned int)(voidp))
49:
50: /*
51: * Number of bytes addr is past an object of 'align' size.
52: */
53: #define BYTES_PAST_ALIGNMENT(voidp, align) \
54: (UNS(voidp) & (align - 1))
55:
56: /*
57: * Bytes moved by an unrolled loop
58: */
59: #define LOOP_STRIDE(type, unroll) ((unroll) * sizeof(type))
60:
61:
62: /*
63: * Len modulo LOOP_STRIDE
64: */
65: #define MODULO_LOOP_UNROLL(len, type, unroll) \
66: ((len) & (LOOP_STRIDE(type, unroll) - 1) & ~(sizeof(type) - 1))
67:
68:
69: /*
70: * Convert a void * + offset into char, short, int, or long long reference
71: * based at that address
72: */
73: #define CHAR(voidp, offset) (*(char *)(UNS(voidp) + (offset)))
74: #define SHORT(voidp, offset) (*(short *)(UNS(voidp) + (offset)))
75: #define INT(voidp, offset) (*(int *)(UNS(voidp) + (offset)))
76:
77:
78:
79: static inline void
80: simple_char_set(char *dst, int val, int len)
81: {
82: switch (len) {
83: case 31: CHAR(dst, 30) = val;
84: case 30: SHORT(dst, 28) = val;
85: INT(dst, 24) = val;
86: INT(dst, 20) = val;
87: INT(dst, 16) = val;
88: INT(dst, 12) = val;
89: INT(dst, 8) = val;
90: INT(dst, 4) = val;
91: INT(dst, 0) = val;
92: break;
93: case 29: CHAR(dst, 28) = val;
94: case 28: INT(dst, 24) = val;
95: INT(dst, 20) = val;
96: INT(dst, 16) = val;
97: INT(dst, 12) = val;
98: INT(dst, 8) = val;
99: INT(dst, 4) = val;
100: INT(dst, 0) = val;
101: break;
102: case 27: CHAR(dst, 26) = val;
103: case 26: SHORT(dst, 24) = val;
104: INT(dst, 20) = val;
105: INT(dst, 16) = val;
106: INT(dst, 12) = val;
107: INT(dst, 8) = val;
108: INT(dst, 4) = val;
109: INT(dst, 0) = val;
110: break;
111: case 25: CHAR(dst, 24) = val;
112: case 24: INT(dst, 20) = val;
113: INT(dst, 16) = val;
114: INT(dst, 12) = val;
115: INT(dst, 8) = val;
116: INT(dst, 4) = val;
117: INT(dst, 0) = val;
118: break;
119: case 23: CHAR(dst, 22) = val;
120: case 22: SHORT(dst, 20) = val;
121: INT(dst, 16) = val;
122: INT(dst, 12) = val;
123: INT(dst, 8) = val;
124: INT(dst, 4) = val;
125: INT(dst, 0) = val;
126: break;
127: case 21: CHAR(dst, 20) = val;
128: case 20: INT(dst, 16) = val;
129: INT(dst, 12) = val;
130: INT(dst, 8) = val;
131: INT(dst, 4) = val;
132: INT(dst, 0) = val;
133: break;
134: case 19: CHAR(dst, 18) = val;
135: case 18: SHORT(dst, 16) = val;
136: INT(dst, 12) = val;
137: INT(dst, 8) = val;
138: INT(dst, 4) = val;
139: INT(dst, 0) = val;
140: break;
141: case 17: CHAR(dst, 16) = val;
142: case 16: INT(dst, 12) = val;
143: INT(dst, 8) = val;
144: INT(dst, 4) = val;
145: INT(dst, 0) = val;
146: break;
147: case 15: CHAR(dst, 14) = val;
148: case 14: SHORT(dst, 12) = val;
149: INT(dst, 8) = val;
150: INT(dst, 4) = val;
151: INT(dst, 0) = val;
152: break;
153: case 13: CHAR(dst, 12) = val;
154: case 12: INT(dst, 8) = val;
155: INT(dst, 4) = val;
156: INT(dst, 0) = val;
157: break;
158: case 11: CHAR(dst, 10) = val;
159: case 10: SHORT(dst, 8) = val;
160: INT(dst, 4) = val;
161: INT(dst, 0) = val;
162: break;
163: case 9: CHAR(dst, 8) = val;
164: case 8: INT(dst, 4) = val;
165: INT(dst, 0) = val;
166: break;
167: case 7: CHAR(dst, 6) = val;
168: case 6: SHORT(dst, 4) = val;
169: INT(dst, 0) = val;
170: break;
171: case 5: CHAR(dst, 4) = val;
172: case 4: INT(dst, 0) = val;
173: break;
174: case 3: CHAR(dst, 2) = val;
175: case 2: SHORT(dst, 0) = val;
176: break;
177: case 1: CHAR(dst, 0) = val;
178: }
179: return;
180: }
181:
182:
183:
184: void *memset(void *, int, unsigned long);
185:
186: void bzero(void *dst, unsigned long ulen)
187: {
188: (void) memset(dst, 0, ulen);
189: }
190:
191: void blkclr(void *dst, unsigned long ulen)
192: {
193: (void) memset(dst, 0, ulen);
194: }
195:
196:
197:
198: void *memset(void *dst, int val, unsigned long ulen)
199: {
200: int len = ulen;
201: void *orig_dst = dst;
202: int need_to_set;
203: int alignment;
204:
205: val |= (val << 8);
206: val |= (val << 16);
207:
208: /* Always do a forward copy */
209:
210: if (len < MIN_TO_ALIGN) {
211: simple_char_set(dst, val, len);
212: return orig_dst;
213: }
214:
215: if (need_to_set = BYTES_PAST_ALIGNMENT(dst, 2 * sizeof(int))) {
216: need_to_set = (2 * sizeof(int)) - need_to_set;
217: simple_char_set(dst, val, need_to_set);
218: len -= need_to_set;
219: UNS(dst) += need_to_set;
220: }
221:
222: alignment = MODULO_LOOP_UNROLL(len, int, 8);
223: UNS(dst) += alignment - LOOP_STRIDE(int, 8);
224: switch (alignment) {
225: do {
226: INT(dst, 0) = val;
227: case 28: INT(dst, 4) = val;
228: case 24: INT(dst, 8) = val;
229: case 20: INT(dst, 12) = val;
230: case 16: INT(dst, 16) = val;
231: case 12: INT(dst, 20) = val;
232: case 8: INT(dst, 24) = val;
233: case 4: INT(dst, 28) = val;
234: case 0:
235: UNS(dst) += LOOP_STRIDE(int, 8);
236: len -= LOOP_STRIDE(int, 8);
237: } while (len >= 0);
238: len &= sizeof(int) - 1;
239: }
240:
241: switch (len) {
242: case 3: CHAR(dst, 2) = val;
243: case 2: CHAR(dst, 1) = val;
244: case 1: CHAR(dst, 0) = val;
245: }
246:
247: return orig_dst;
248: }
249:
250: #import <mach/mach_types.h>
251: #import <sys/errno.h>
252:
253: /*
254: * Maintain the recover field in the thread_t structure
255: */
256: static inline void
257: set_recover(int (*vector)())
258: {
259: current_thread()->recover = (vm_offset_t)vector;
260: return;
261: }
262:
263: static inline void
264: clear_recover()
265: {
266: current_thread()->recover = 0;
267: }
268:
269: void *safe_memset(void *, int, unsigned long);
270:
271: int safe_bzero(void *dst, unsigned long ulen)
272: {
273: if (safe_memset(dst, 0, ulen) == (void *)(-1))
274: return EFAULT;
275: else
276: return 0;
277: }
278:
279:
280: void *safe_memset(void *dst, int val, unsigned long ulen)
281: {
282: int len = ulen;
283: void *orig_dst = dst;
284: int need_to_set;
285: int alignment;
286:
287: val |= (val << 8);
288: val |= (val << 16);
289:
290: set_recover(&&do_fault);
291:
292: /* Always do a forward copy */
293:
294: if (len < MIN_TO_ALIGN) {
295: simple_char_set(dst, val, len);
296: clear_recover();
297: return orig_dst;
298: }
299:
300: if (need_to_set = BYTES_PAST_ALIGNMENT(dst, 2 * sizeof(int))) {
301: need_to_set = (2 * sizeof(int)) - need_to_set;
302: simple_char_set(dst, val, need_to_set);
303: len -= need_to_set;
304: UNS(dst) += need_to_set;
305: }
306:
307: alignment = MODULO_LOOP_UNROLL(len, int, 8);
308: UNS(dst) += alignment - LOOP_STRIDE(int, 8);
309: switch (alignment) {
310: do {
311: INT(dst, 0) = val;
312: case 28: INT(dst, 4) = val;
313: case 24: INT(dst, 8) = val;
314: case 20: INT(dst, 12) = val;
315: case 16: INT(dst, 16) = val;
316: case 12: INT(dst, 20) = val;
317: case 8: INT(dst, 24) = val;
318: case 4: INT(dst, 28) = val;
319: case 0:
320: UNS(dst) += LOOP_STRIDE(int, 8);
321: len -= LOOP_STRIDE(int, 8);
322: } while (len >= 0);
323: len &= sizeof(int) - 1;
324: }
325:
326: switch (len) {
327: case 3: CHAR(dst, 2) = val;
328: case 2: CHAR(dst, 1) = val;
329: case 1: CHAR(dst, 0) = val;
330: }
331:
332: clear_recover();
333: return orig_dst;
334:
335: do_fault:
336: clear_recover();
337: return (void *)(-1);
338: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.