xref: /openbsd/sys/lib/libkern/arch/m88k/bzero.S (revision 73471bf0)
1/*	$OpenBSD: bzero.S,v 1.2 2013/01/05 11:20:56 miod Exp $	*/
2/*
3 * Mach Operating System
4 * Copyright (c) 1993-1992 Carnegie Mellon University
5 * Copyright (c) 1991 OMRON Corporation
6 * Copyright (c) 1996 Nivas Madhur
7 * Copyright (c) 1998 Steve Murphree, Jr.
8 * All Rights Reserved.
9 *
10 * Permission to use, copy, modify and distribute this software and its
11 * documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the
13 * software, derivative works or modified versions, and any portions
14 * thereof, and that both notices appear in supporting documentation.
15 *
16 * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION.  CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23 *  School of Computer Science
24 *  Carnegie Mellon University
25 *  Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie the
28 * rights to redistribute these changes.
29 */
30
31#include <machine/asm.h>
32
33/*######################################################################*/
34
35/*
36 * April 1990, Omron Corporation
37 * jfriedl@nff.ncl.omron.co.jp
38 *
39 * void bzero(destination, length)
40 *
41 * Clear (set to zero) LENGTH bytes of memory starting at DESTINATION.
42 * Note that there is no return value.
43 *
44 * This is fast. Really fast. Especially for long lengths.
45 */
46#define R_dest			%r2
47#define R_len			%r3
48
49#define R_bytes			%r4
50#define R_mark_address		%r5
51#define R_addr			%r6	/* R_addr && R_temp SHARE */
52#define R_temp			%r6	/* R_addr && R_temp SHARE */
53
54ENTRY(bzero)
55	/*
56	 * If the destination is not word aligned, we'll word align
57	 * it first to make things easier.
58	 *
59	 * We'll check to see first if bit #0 is set and then bit #1
60	 * (of the destination address). If either are set, it's
61	 * not word aligned.
62	 */
63	bb1	0, R_dest, _ASM_LABEL(not_initially_word_aligned)
64	bb1	1, R_dest, _ASM_LABEL(not_initially_word_aligned)
65
66ASLOCAL(now_word_aligned)
67	/*
68	 * before we get into the main loop, grab the
69	 * address of the label "mark" below.
70	 */
71	or.u	R_mark_address, %r0, %hi16(_ASM_LABEL(mark))
72	or	R_mark_address, R_mark_address, %lo16(_ASM_LABEL(mark))
73
74ASLOCAL(top_of_main_loop)
75#define MAX_AT_ONE_TIME 128
76	/*
77	 * Now we find out how many words we can zero-fill in a row.
78	 * We do this by doing something like:
79	 *
80	 *	bytes &= 0xfffffffc;
81	 *	if (bytes > MAX_AT_ONE_TIME)
82	 *		bytes = MAX_AT_ONE_TIME;
83	 */
84
85	/*
86	 * Clear lower two bits of length to give us the number of bytes
87	 * ALIGNED TO THE WORD LENGTH remaining to move.
88	 */
89	clr	R_bytes, R_len, 2<0>
90
91	/* if we're done clearing WORDS, jump out */
92	bcnd	eq0, R_bytes, _ASM_LABEL(done_doing_words)
93
94	/* if the number of bytes > MAX_AT_ONE_TIME, do only the max */
95	cmp	R_temp, R_bytes, MAX_AT_ONE_TIME
96	bb1	lt, R_temp, 1f
97
98	/*
99	 * Since we're doing the max, we know exactly where we're
100	 * jumping (the first one in the list!), so we can jump
101	 * right there.  However, we've still got to adjust
102	 * the length, so we'll jump to where we ajust the length
103	 * which just happens to fall through to the first store zero
104	 * in the list.
105	 *
106	 * Note, however, that we're jumping to an instruction that
107	 * would be in the delay slot for the jump in front of it,
108	 * so if you change things here, WATCH OUT.
109	 */
110	br.n	do_max
111	 or	R_bytes, %r0, MAX_AT_ONE_TIME
112
1131:
114	/*
115	 * Now we have the number of bytes to zero during this iteration,
116	 * (which, as it happens, is the last iteration if we're here).
117	 * We'll calculate the proper place to jump and then jump there,
118	 * after adjusting the length.  NOTE that there is a label between
119	 * the "jmp.n" and the "subu" below... the "subu" is NOT always
120	 * executed in the delay slot of the "jmp.n".
121 	 */
122	subu	R_addr, R_mark_address, R_bytes
123
124	/* and go there (after adjusting the length via ".n") */
125	jmp.n	R_addr
126ASLOCAL(do_max)
127	  subu	R_len, R_len, R_bytes	/* NOTE: this is in the delay slot! */
128
129	st	%r0, R_dest, 0x7c	/* 128 */
130	st	%r0, R_dest, 0x78	/* 124 */
131	st	%r0, R_dest, 0x74	/* 120 */
132	st	%r0, R_dest, 0x70	/* 116 */
133	st	%r0, R_dest, 0x6c	/* 112 */
134	st	%r0, R_dest, 0x68	/* 108 */
135	st	%r0, R_dest, 0x64	/* 104 */
136	st	%r0, R_dest, 0x60	/* 100 */
137	st	%r0, R_dest, 0x5c	/*  96 */
138	st	%r0, R_dest, 0x58	/*  92 */
139	st	%r0, R_dest, 0x54	/*  88 */
140	st	%r0, R_dest, 0x50	/*  84 */
141	st	%r0, R_dest, 0x4c	/*  80 */
142	st	%r0, R_dest, 0x48	/*  76 */
143	st	%r0, R_dest, 0x44	/*  72 */
144	st	%r0, R_dest, 0x40	/*  68 */
145	st	%r0, R_dest, 0x3c	/*  64 */
146	st	%r0, R_dest, 0x38	/*  60 */
147	st	%r0, R_dest, 0x34	/*  56 */
148	st	%r0, R_dest, 0x30	/*  52 */
149	st	%r0, R_dest, 0x2c	/*  44 */
150	st	%r0, R_dest, 0x28	/*  40 */
151	st	%r0, R_dest, 0x24	/*  36 */
152	st	%r0, R_dest, 0x20	/*  32 */
153	st	%r0, R_dest, 0x1c	/*  28 */
154	st	%r0, R_dest, 0x18	/*  24 */
155	st	%r0, R_dest, 0x14	/*  20 */
156	st	%r0, R_dest, 0x10	/*  16 */
157	st	%r0, R_dest, 0x0c	/*  12 */
158	st	%r0, R_dest, 0x08	/*   8 */
159	st	%r0, R_dest, 0x04	/*   4 */
160	st	%r0, R_dest, 0x00	/*   0 */
161
162ASLOCAL(mark)
163	br.n	_ASM_LABEL(top_of_main_loop)
164	 addu	R_dest, R_dest, R_bytes	/* bump up the dest address */
165
166ASLOCAL(done_doing_words)
167	bcnd	ne0, R_len, 1f
168	jmp	%r1
169
1701:
171	subu	R_len, R_len, 1
172	bcnd.n	ne0, R_len, 1b
173	 st.b	%r0, R_dest, R_len
1741:
175	jmp	%r1
176
177ASLOCAL(not_initially_word_aligned)
178	/*
179	 * Bzero to word-align the address (at least if the length allows it).
180	 */
181	bcnd	eq0, R_len, 1b
182	st.b	%r0, R_dest, 0
183	addu	R_dest, R_dest, 1
184	mask	R_temp, R_dest, 0x3
185	bcnd.n	eq0, R_temp, _ASM_LABEL(now_word_aligned)
186	 subu	R_len, R_len, 1
187	br	_ASM_LABEL(not_initially_word_aligned)
188
189#undef	R_dest
190#undef	R_len
191#undef	R_bytes
192#undef	R_mark_address
193#undef	R_addr
194#undef	R_temp
195#undef	MAX_AT_ONE_TIME
196