Project

General

Profile

Download (5.93 KB) Statistics
| Branch: | Tag: | Revision:
1
/*
2
 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
3
 *
4
 * Author: Nicolas Pitre <nico@cam.org>
5
 *   - contributed to gcc-3.4 on Sep 30, 2003
6
 *   - adapted for the Linux kernel on Oct 2, 2003
7
 */
8

    
9
/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
10

    
11
This file is free software; you can redistribute it and/or modify it
12
under the terms of the GNU General Public License as published by the
13
Free Software Foundation; either version 2, or (at your option) any
14
later version.
15

    
16
In addition to the permissions in the GNU General Public License, the
17
Free Software Foundation gives you unlimited permission to link the
18
compiled version of this file into combinations with other programs,
19
and to distribute those combinations without any restriction coming
20
from the use of this file.  (The General Public License restrictions
21
do apply in other respects; for example, they cover modification of
22
the file, and distribution when not linked into a combine
23
executable.)
24

    
25
This file is distributed in the hope that it will be useful, but
26
WITHOUT ANY WARRANTY; without even the implied warranty of
27
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28
General Public License for more details.
29

    
30
You should have received a copy of the GNU General Public License
31
along with this program; see the file COPYING.  If not, write to
32
the Free Software Foundation, 59 Temple Place - Suite 330,
33
Boston, MA 02111-1307, USA.  */
34

    
35

    
36
#include <asm/linkage.h>
37
#include <asm/assembler.h>
38

    
39

    
40
.macro ARM_DIV_BODY dividend, divisor, result, curbit
41

    
42
#if __LINUX_ARM_ARCH__ >= 5
43

    
44
	clz	\curbit, \divisor
45
	clz	\result, \dividend
46
	sub	\result, \curbit, \result
47
	mov	\curbit, #1
48
	mov	\divisor, \divisor, lsl \result
49
	mov	\curbit, \curbit, lsl \result
50
	mov	\result, #0
51
	
52
#else
53

    
54
	@ Initially shift the divisor left 3 bits if possible,
55
	@ set curbit accordingly.  This allows for curbit to be located
56
	@ at the left end of each 4 bit nibbles in the division loop
57
	@ to save one loop in most cases.
58
	tst	\divisor, #0xe0000000
59
	moveq	\divisor, \divisor, lsl #3
60
	moveq	\curbit, #8
61
	movne	\curbit, #1
62

    
63
	@ Unless the divisor is very big, shift it up in multiples of
64
	@ four bits, since this is the amount of unwinding in the main
65
	@ division loop.  Continue shifting until the divisor is 
66
	@ larger than the dividend.
67
1:	cmp	\divisor, #0x10000000
68
	cmplo	\divisor, \dividend
69
	movlo	\divisor, \divisor, lsl #4
70
	movlo	\curbit, \curbit, lsl #4
71
	blo	1b
72

    
73
	@ For very big divisors, we must shift it a bit at a time, or
74
	@ we will be in danger of overflowing.
75
1:	cmp	\divisor, #0x80000000
76
	cmplo	\divisor, \dividend
77
	movlo	\divisor, \divisor, lsl #1
78
	movlo	\curbit, \curbit, lsl #1
79
	blo	1b
80

    
81
	mov	\result, #0
82

    
83
#endif
84

    
85
	@ Division loop
86
1:	cmp	\dividend, \divisor
87
	subhs	\dividend, \dividend, \divisor
88
	orrhs	\result,   \result,   \curbit
89
	cmp	\dividend, \divisor,  lsr #1
90
	subhs	\dividend, \dividend, \divisor, lsr #1
91
	orrhs	\result,   \result,   \curbit,  lsr #1
92
	cmp	\dividend, \divisor,  lsr #2
93
	subhs	\dividend, \dividend, \divisor, lsr #2
94
	orrhs	\result,   \result,   \curbit,  lsr #2
95
	cmp	\dividend, \divisor,  lsr #3
96
	subhs	\dividend, \dividend, \divisor, lsr #3
97
	orrhs	\result,   \result,   \curbit,  lsr #3
98
	cmp	\dividend, #0			@ Early termination?
99
	movnes	\curbit,   \curbit,  lsr #4	@ No, any more bits to do?
100
	movne	\divisor,  \divisor, lsr #4
101
	bne	1b
102

    
103
.endm
104

    
105

    
106
.macro ARM_DIV2_ORDER divisor, order
107

    
108
#if __LINUX_ARM_ARCH__ >= 5
109

    
110
	clz	\order, \divisor
111
	rsb	\order, \order, #31
112

    
113
#else
114

    
115
	cmp	\divisor, #(1 << 16)
116
	movhs	\divisor, \divisor, lsr #16
117
	movhs	\order, #16
118
	movlo	\order, #0
119

    
120
	cmp	\divisor, #(1 << 8)
121
	movhs	\divisor, \divisor, lsr #8
122
	addhs	\order, \order, #8
123

    
124
	cmp	\divisor, #(1 << 4)
125
	movhs	\divisor, \divisor, lsr #4
126
	addhs	\order, \order, #4
127

    
128
	cmp	\divisor, #(1 << 2)
129
	addhi	\order, \order, #3
130
	addls	\order, \order, \divisor, lsr #1
131

    
132
#endif
133

    
134
.endm
135

    
136

    
137
.macro ARM_MOD_BODY dividend, divisor, order, spare
138

    
139
#if __LINUX_ARM_ARCH__ >= 5
140

    
141
	clz	\order, \divisor
142
	clz	\spare, \dividend
143
	sub	\order, \order, \spare
144
	mov	\divisor, \divisor, lsl \order
145

    
146
#else
147

    
148
	mov	\order, #0
149

    
150
	@ Unless the divisor is very big, shift it up in multiples of
151
	@ four bits, since this is the amount of unwinding in the main
152
	@ division loop.  Continue shifting until the divisor is 
153
	@ larger than the dividend.
154
1:	cmp	\divisor, #0x10000000
155
	cmplo	\divisor, \dividend
156
	movlo	\divisor, \divisor, lsl #4
157
	addlo	\order, \order, #4
158
	blo	1b
159

    
160
	@ For very big divisors, we must shift it a bit at a time, or
161
	@ we will be in danger of overflowing.
162
1:	cmp	\divisor, #0x80000000
163
	cmplo	\divisor, \dividend
164
	movlo	\divisor, \divisor, lsl #1
165
	addlo	\order, \order, #1
166
	blo	1b
167

    
168
#endif
169

    
170
	@ Perform all needed substractions to keep only the reminder.
171
	@ Do comparisons in batch of 4 first.
172
	subs	\order, \order, #3		@ yes, 3 is intended here
173
	blt	2f
174

    
175
1:	cmp	\dividend, \divisor
176
	subhs	\dividend, \dividend, \divisor
177
	cmp	\dividend, \divisor,  lsr #1
178
	subhs	\dividend, \dividend, \divisor, lsr #1
179
	cmp	\dividend, \divisor,  lsr #2
180
	subhs	\dividend, \dividend, \divisor, lsr #2
181
	cmp	\dividend, \divisor,  lsr #3
182
	subhs	\dividend, \dividend, \divisor, lsr #3
183
	cmp	\dividend, #1
184
	mov	\divisor, \divisor, lsr #4
185
	subges	\order, \order, #4
186
	bge	1b
187

    
188
	tst	\order, #3
189
	teqne	\dividend, #0
190
	beq	5f
191

    
192
	@ Either 1, 2 or 3 comparison/substractions are left.
193
2:	cmn	\order, #2
194
	blt	4f
195
	beq	3f
196
	cmp	\dividend, \divisor
197
	subhs	\dividend, \dividend, \divisor
198
	mov	\divisor,  \divisor,  lsr #1
199
3:	cmp	\dividend, \divisor
200
	subhs	\dividend, \dividend, \divisor
201
	mov	\divisor,  \divisor,  lsr #1
202
4:	cmp	\dividend, \divisor
203
	subhs	\dividend, \dividend, \divisor
204
5:
205
.endm
206

    
207

    
208

    
209
#ifdef CONFIG_AEABI
210

    
211
ENTRY(__aeabi_uidivmod)
212

    
213
	stmfd	sp!, {r0, r1, ip, lr}
214
	bl	__aeabi_uidiv
215
	ldmfd	sp!, {r1, r2, ip, lr}
216
	mul	r3, r0, r2
217
	sub	r1, r1, r3
218
	mov	pc, lr
219

    
220
ENTRY(__aeabi_idivmod)
221

    
222
	stmfd	sp!, {r0, r1, ip, lr}
223
	bl	__aeabi_idiv
224
	ldmfd	sp!, {r1, r2, ip, lr}
225
	mul	r3, r0, r2
226
	sub	r1, r1, r3
227
	mov	pc, lr
228

    
229
#endif
230

    
231
Ldiv0:
232

    
233
	str	lr, [sp, #-8]!
234
	bl	__div0
235
	mov	r0, #0			@ About as wrong as it could be.
236
	ldr	pc, [sp], #8
237

    
238
ENTRY(__div0)
239
	mov	pc, lr
(7-7/16)
Add picture from clipboard (Maximum size: 48.8 MB)