summaryrefslogtreecommitdiff
path: root/sys/lib/libkern/arch/m88k/bzero.S
blob: 20ecefaf583fbb4d37b727b2c9fafee2ea9d70bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*	$OpenBSD: bzero.S,v 1.4 2022/12/06 18:51:00 guenther Exp $	*/
/*
 * Mach Operating System
 * Copyright (c) 1993-1992 Carnegie Mellon University
 * Copyright (c) 1991 OMRON Corporation
 * Copyright (c) 1996 Nivas Madhur
 * Copyright (c) 1998 Steve Murphree, Jr.
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

#include <machine/asm.h>

/*######################################################################*/

/*
 * April 1990, Omron Corporation
 * jfriedl@nff.ncl.omron.co.jp
 *
 * void bzero(destination, length)
 *
 * Clear (set to zero) LENGTH bytes of memory starting at DESTINATION.
 * Note that there is no return value.
 *
 * This is fast. Really fast. Especially for long lengths.
 */
#define R_dest			%r2
#define R_len			%r3

#define R_bytes			%r4
#define R_mark_address		%r5
#define R_addr			%r6	/* R_addr && R_temp SHARE */
#define R_temp			%r6	/* R_addr && R_temp SHARE */

ENTRY(bzero)
	/*
	 * If the destination is not word aligned, we'll word align
	 * it first to make things easier.
	 *
	 * We'll check to see first if bit #0 is set and then bit #1
	 * (of the destination address). If either are set, it's
	 * not word aligned.
	 */
	bb1	0, R_dest, not_initially_word_aligned
	bb1	1, R_dest, not_initially_word_aligned

ASLOCAL(now_word_aligned)
	/*
	 * before we get into the main loop, grab the
	 * address of the label "mark" below.
	 */
	or.u	R_mark_address, %r0, %hi16(mark)
	or	R_mark_address, R_mark_address, %lo16(mark)

ASLOCAL(top_of_main_loop)
#define MAX_AT_ONE_TIME 128
	/*
	 * Now we find out how many words we can zero-fill in a row.
	 * We do this by doing something like:
	 *
	 *	bytes &= 0xfffffffc;
	 *	if (bytes > MAX_AT_ONE_TIME)
	 *		bytes = MAX_AT_ONE_TIME;
	 */

	/*
	 * Clear lower two bits of length to give us the number of bytes
	 * ALIGNED TO THE WORD LENGTH remaining to move.
	 */
	clr	R_bytes, R_len, 2<0>

	/* if we're done clearing WORDS, jump out */
	bcnd	eq0, R_bytes, done_doing_words

	/* if the number of bytes > MAX_AT_ONE_TIME, do only the max */
	cmp	R_temp, R_bytes, MAX_AT_ONE_TIME
	bb1	lt, R_temp, 1f

	/*
	 * Since we're doing the max, we know exactly where we're
	 * jumping (the first one in the list!), so we can jump
	 * right there.  However, we've still got to adjust
	 * the length, so we'll jump to where we adjust the length
	 * which just happens to fall through to the first store zero
	 * in the list.
	 *
	 * Note, however, that we're jumping to an instruction that
	 * would be in the delay slot for the jump in front of it,
	 * so if you change things here, WATCH OUT.
	 */
	br.n	do_max
	 or	R_bytes, %r0, MAX_AT_ONE_TIME

1:
	/*
	 * Now we have the number of bytes to zero during this iteration,
	 * (which, as it happens, is the last iteration if we're here).
	 * We'll calculate the proper place to jump and then jump there,
	 * after adjusting the length.  NOTE that there is a label between
	 * the "jmp.n" and the "subu" below... the "subu" is NOT always
	 * executed in the delay slot of the "jmp.n".
 	 */
	subu	R_addr, R_mark_address, R_bytes

	/* and go there (after adjusting the length via ".n") */
	jmp.n	R_addr
ASLOCAL(do_max)
	  subu	R_len, R_len, R_bytes	/* NOTE: this is in the delay slot! */

	st	%r0, R_dest, 0x7c	/* 128 */
	st	%r0, R_dest, 0x78	/* 124 */
	st	%r0, R_dest, 0x74	/* 120 */
	st	%r0, R_dest, 0x70	/* 116 */
	st	%r0, R_dest, 0x6c	/* 112 */
	st	%r0, R_dest, 0x68	/* 108 */
	st	%r0, R_dest, 0x64	/* 104 */
	st	%r0, R_dest, 0x60	/* 100 */
	st	%r0, R_dest, 0x5c	/*  96 */
	st	%r0, R_dest, 0x58	/*  92 */
	st	%r0, R_dest, 0x54	/*  88 */
	st	%r0, R_dest, 0x50	/*  84 */
	st	%r0, R_dest, 0x4c	/*  80 */
	st	%r0, R_dest, 0x48	/*  76 */
	st	%r0, R_dest, 0x44	/*  72 */
	st	%r0, R_dest, 0x40	/*  68 */
	st	%r0, R_dest, 0x3c	/*  64 */
	st	%r0, R_dest, 0x38	/*  60 */
	st	%r0, R_dest, 0x34	/*  56 */
	st	%r0, R_dest, 0x30	/*  52 */
	st	%r0, R_dest, 0x2c	/*  44 */
	st	%r0, R_dest, 0x28	/*  40 */
	st	%r0, R_dest, 0x24	/*  36 */
	st	%r0, R_dest, 0x20	/*  32 */
	st	%r0, R_dest, 0x1c	/*  28 */
	st	%r0, R_dest, 0x18	/*  24 */
	st	%r0, R_dest, 0x14	/*  20 */
	st	%r0, R_dest, 0x10	/*  16 */
	st	%r0, R_dest, 0x0c	/*  12 */
	st	%r0, R_dest, 0x08	/*   8 */
	st	%r0, R_dest, 0x04	/*   4 */
	st	%r0, R_dest, 0x00	/*   0 */

ASLOCAL(mark)
	br.n	top_of_main_loop
	 addu	R_dest, R_dest, R_bytes	/* bump up the dest address */

ASLOCAL(done_doing_words)
	bcnd	ne0, R_len, 1f
	jmp	%r1

1:
	subu	R_len, R_len, 1
	bcnd.n	ne0, R_len, 1b
	 st.b	%r0, R_dest, R_len
1:
	jmp	%r1

ASLOCAL(not_initially_word_aligned)
	/*
	 * Bzero to word-align the address (at least if the length allows it).
	 */
	bcnd	eq0, R_len, 1b
	st.b	%r0, R_dest, 0
	addu	R_dest, R_dest, 1
	mask	R_temp, R_dest, 0x3
	bcnd.n	eq0, R_temp, now_word_aligned
	 subu	R_len, R_len, 1
	br	not_initially_word_aligned

#undef	R_dest
#undef	R_len
#undef	R_bytes
#undef	R_mark_address
#undef	R_addr
#undef	R_temp
#undef	MAX_AT_ONE_TIME