1 @ libgcc1 routines for ARM cpu.
2 @ Division routines
, written by Richard Earnshaw
, (rearnsha
@armltd.co.uk
)
4 /* Copyright
(C
) 1995, 1996, 1998 Free Software Foundation
, Inc.
6 This file is free software
; you can redistribute it and/or modify it
7 under the terms of the GNU General
Public License as published by the
8 Free Software Foundation
; either version 2, or (at your option) any
11 In addition to the permissions
in the GNU General
Public License
, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of
this file with other programs
, and to distribute
14 those programs without any restriction coming from the use of
this
15 file.
(The General
Public License restrictions do apply
in other
16 respects
; for example, they cover modification of the file, and
17 distribution when
not linked
into another program.
)
19 This file is distributed
in the hope that it will be useful
, but
20 WITHOUT ANY WARRANTY
; without even the implied warranty of
21 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General
Public License for more details.
24 You should have received a copy of the GNU General
Public License
25 along with
this program
; see the file COPYING. If not, write to
26 the Free Software Foundation
, 59 Temple Place
- Suite
330,
27 Boston
, MA
02111-1307, USA.
*/
29 /* As a special exception
, if you link
this library with other files
,
30 some of which are compiled with GCC
, to produce an executable
,
31 this library does
not by itself cause the resulting executable
32 to be covered by the GNU General
Public License.
33 This exception does
not however invalidate any other reasons why
34 the executable file might be covered by the GNU General
Public License.
*/
38 #define RETc
(x
) mov##x##s
42 #define RETc
(x
) mov##x
46 #ifndef __USER_LABEL_PREFIX__
47 #error __USER_LABEL_PREFIX__
not defined
50 /* ANSI concatenation macros.
*/
52 #define CONCAT1
(a
, b
) CONCAT2
(a
, b
)
53 #define CONCAT2
(a
, b
) a ## b
55 /* Use the right prefix for
global labels.
*/
57 #define SYM
(x
) CONCAT1
(__USER_LABEL_PREFIX__
, x
)
61 #define
TYPE(x
) .
type SYM
(x
),function
62 #define
SIZE(x
) .
size SYM
(x
), .
- SYM
(x
)
81 .globl SYM
(__udivsi3
)
93 @ Unless the divisor is very big
, shift it up
in multiples of
94 @ four bits
, since
this is the amount of unwinding
in the main
95 @ division
loop. Continue shifting until the divisor is
96 @ larger than the dividend.
97 cmp divisor
, #
0x10000000
98 cmpcc divisor
, dividend
99 movcc divisor
, divisor
, lsl #
4
100 movcc curbit
, curbit
, lsl #
4
104 @ For very big divisors
, we must shift it a bit at a time
, or
105 @ we will be
in danger of overflowing.
106 cmp divisor
, #
0x80000000
107 cmpcc divisor
, dividend
108 movcc divisor
, divisor
, lsl #
1
109 movcc curbit
, curbit
, lsl #
1
113 @
Test for possible subtractions
, and note which bits
114 @ are done
in the result. On the final pass
, this may subtract
115 @ too much from the dividend
, but the result will be ok
, since the
116 @
"bit" will have been shifted
out at the bottom.
117 cmp dividend
, divisor
118 subcs dividend
, dividend
, divisor
119 orrcs result
, result
, curbit
120 cmp dividend
, divisor
, lsr #
1
121 subcs dividend
, dividend
, divisor
, lsr #
1
122 orrcs result
, result
, curbit
, lsr #
1
123 cmp dividend
, divisor
, lsr #
2
124 subcs dividend
, dividend
, divisor
, lsr #
2
125 orrcs result
, result
, curbit
, lsr #
2
126 cmp dividend
, divisor
, lsr #
3
127 subcs dividend
, dividend
, divisor
, lsr #
3
128 orrcs result
, result
, curbit
, lsr #
3
129 cmp dividend
, #
0 @ Early termination
?
130 movnes curbit
, curbit
, lsr #
4 @ No
, any more bits to do
?
131 movne divisor
, divisor
, lsr #
4
139 bl SYM
(__div0
) __PLT__
140 mov r0
, #
0 @ about as wrong as it could be
141 ldmia
sp!, {pc}RETCOND
145 #endif
/* L_udivsi3
*/
159 .globl SYM
(__umodsi3
)
167 cmp dividend
, divisor
170 @ Unless the divisor is very big
, shift it up
in multiples of
171 @ four bits
, since
this is the amount of unwinding
in the main
172 @ division
loop. Continue shifting until the divisor is
173 @ larger than the dividend.
174 cmp divisor
, #
0x10000000
175 cmpcc divisor
, dividend
176 movcc divisor
, divisor
, lsl #
4
177 movcc curbit
, curbit
, lsl #
4
181 @ For very big divisors
, we must shift it a bit at a time
, or
182 @ we will be
in danger of overflowing.
183 cmp divisor
, #
0x80000000
184 cmpcc divisor
, dividend
185 movcc divisor
, divisor
, lsl #
1
186 movcc curbit
, curbit
, lsl #
1
190 @
Test for possible subtractions. On the final pass
, this may
191 @ subtract too much from the dividend
, so keep track of which
192 @ subtractions are done
, we can fix them up afterwards...
194 cmp dividend
, divisor
195 subcs dividend
, dividend
, divisor
196 cmp dividend
, divisor
, lsr #
1
197 subcs dividend
, dividend
, divisor
, lsr #
1
198 orrcs overdone
, overdone
, curbit
, ror #
1
199 cmp dividend
, divisor
, lsr #
2
200 subcs dividend
, dividend
, divisor
, lsr #
2
201 orrcs overdone
, overdone
, curbit
, ror #
2
202 cmp dividend
, divisor
, lsr #
3
203 subcs dividend
, dividend
, divisor
, lsr #
3
204 orrcs overdone
, overdone
, curbit
, ror #
3
206 cmp dividend
, #
0 @ Early termination
?
207 movnes curbit
, curbit
, lsr #
4 @ No
, any more bits to do
?
208 movne divisor
, divisor
, lsr #
4
211 @ Any subtractions that we should
not have done will be recorded
in
212 @ the top three bits of
"overdone". Exactly which were
not needed
213 @ are governed by the position of the bit
, stored
in ip.
214 @ If we terminated early
, because dividend became zero
,
215 @ then none of the below will match
, since the bit
in ip will
not be
216 @
in the bottom nibble.
217 ands overdone
, overdone
, #
0xe0000000
218 RETc
(eq) pc
, lr @ No fixups needed
219 tst overdone
, ip
, ror #
3
220 addne dividend
, dividend
, divisor
, lsr #
3
221 tst overdone
, ip
, ror #
2
222 addne dividend
, dividend
, divisor
, lsr #
2
223 tst overdone
, ip
, ror #
1
224 addne dividend
, dividend
, divisor
, lsr #
1
229 bl SYM
(__div0
) __PLT__
230 mov r0
, #
0 @ about as wrong as it could be
231 ldmia
sp!, {pc}RETCOND
235 #endif
/* L_umodsi3
*/
249 .globl SYM
(__divsi3
)
254 eor ip
, dividend
, divisor @ Save the sign of the result.
258 rsbmi divisor
, divisor
, #
0 @ Loops below use unsigned.
261 rsbmi dividend
, dividend
, #
0
262 cmp dividend
, divisor
266 @ Unless the divisor is very big
, shift it up
in multiples of
267 @ four bits
, since
this is the amount of unwinding
in the main
268 @ division
loop. Continue shifting until the divisor is
269 @ larger than the dividend.
270 cmp divisor
, #
0x10000000
271 cmpcc divisor
, dividend
272 movcc divisor
, divisor
, lsl #
4
273 movcc curbit
, curbit
, lsl #
4
277 @ For very big divisors
, we must shift it a bit at a time
, or
278 @ we will be
in danger of overflowing.
279 cmp divisor
, #
0x80000000
280 cmpcc divisor
, dividend
281 movcc divisor
, divisor
, lsl #
1
282 movcc curbit
, curbit
, lsl #
1
286 @
Test for possible subtractions
, and note which bits
287 @ are done
in the result. On the final pass
, this may subtract
288 @ too much from the dividend
, but the result will be ok
, since the
289 @
"bit" will have been shifted
out at the bottom.
290 cmp dividend
, divisor
291 subcs dividend
, dividend
, divisor
292 orrcs result
, result
, curbit
293 cmp dividend
, divisor
, lsr #
1
294 subcs dividend
, dividend
, divisor
, lsr #
1
295 orrcs result
, result
, curbit
, lsr #
1
296 cmp dividend
, divisor
, lsr #
2
297 subcs dividend
, dividend
, divisor
, lsr #
2
298 orrcs result
, result
, curbit
, lsr #
2
299 cmp dividend
, divisor
, lsr #
3
300 subcs dividend
, dividend
, divisor
, lsr #
3
301 orrcs result
, result
, curbit
, lsr #
3
302 cmp dividend
, #
0 @ Early termination
?
303 movnes curbit
, curbit
, lsr #
4 @ No
, any more bits to do
?
304 movne divisor
, divisor
, lsr #
4
314 bl SYM
(__div0
) __PLT__
315 mov r0
, #
0 @ about as wrong as it could be
316 ldmia
sp!, {pc}RETCOND
320 #endif
/* L_divsi3
*/
334 .globl SYM
(__modsi3
)
341 rsbmi divisor
, divisor
, #
0 @ Loops below use unsigned.
343 @ Need to save the sign of the dividend
, unfortunately
, we need
344 @ ip later on
; this is faster than pushing lr and using that.
345 str dividend
, [sp, #
-4]!
347 rsbmi dividend
, dividend
, #
0
348 cmp dividend
, divisor
352 @ Unless the divisor is very big
, shift it up
in multiples of
353 @ four bits
, since
this is the amount of unwinding
in the main
354 @ division
loop. Continue shifting until the divisor is
355 @ larger than the dividend.
356 cmp divisor
, #
0x10000000
357 cmpcc divisor
, dividend
358 movcc divisor
, divisor
, lsl #
4
359 movcc curbit
, curbit
, lsl #
4
363 @ For very big divisors
, we must shift it a bit at a time
, or
364 @ we will be
in danger of overflowing.
365 cmp divisor
, #
0x80000000
366 cmpcc divisor
, dividend
367 movcc divisor
, divisor
, lsl #
1
368 movcc curbit
, curbit
, lsl #
1
372 @
Test for possible subtractions. On the final pass
, this may
373 @ subtract too much from the dividend
, so keep track of which
374 @ subtractions are done
, we can fix them up afterwards...
376 cmp dividend
, divisor
377 subcs dividend
, dividend
, divisor
378 cmp dividend
, divisor
, lsr #
1
379 subcs dividend
, dividend
, divisor
, lsr #
1
380 orrcs overdone
, overdone
, curbit
, ror #
1
381 cmp dividend
, divisor
, lsr #
2
382 subcs dividend
, dividend
, divisor
, lsr #
2
383 orrcs overdone
, overdone
, curbit
, ror #
2
384 cmp dividend
, divisor
, lsr #
3
385 subcs dividend
, dividend
, divisor
, lsr #
3
386 orrcs overdone
, overdone
, curbit
, ror #
3
388 cmp dividend
, #
0 @ Early termination
?
389 movnes curbit
, curbit
, lsr #
4 @ No
, any more bits to do
?
390 movne divisor
, divisor
, lsr #
4
393 @ Any subtractions that we should
not have done will be recorded
in
394 @ the top three bits of
"overdone". Exactly which were
not needed
395 @ are governed by the position of the bit
, stored
in ip.
396 @ If we terminated early
, because dividend became zero
,
397 @ then none of the below will match
, since the bit
in ip will
not be
398 @
in the bottom nibble.
399 ands overdone
, overdone
, #
0xe0000000
401 tst overdone
, ip
, ror #
3
402 addne dividend
, dividend
, divisor
, lsr #
3
403 tst overdone
, ip
, ror #
2
404 addne dividend
, dividend
, divisor
, lsr #
2
405 tst overdone
, ip
, ror #
1
406 addne dividend
, dividend
, divisor
, lsr #
1
410 rsbmi dividend
, dividend
, #
0
415 bl SYM
(__div0
) __PLT__
416 mov r0
, #
0 @ about as wrong as it could be
417 ldmia
sp!, {pc}RETCOND
421 #endif
/* L_modsi3
*/
433 #endif
/* L_divmodsi_tools
*/
436 @ GNU
/Linux division
-by zero handler. Used
in place of L_dvmd_tls
438 #
include <asm
/unistd.h
>
440 #define SIGFPE
8 @ cant use
<asm
/signal.h
> as it
441 @ contains too much C rubbish
449 ldmhsfd
sp!, {r1, pc}RETCOND @
not much we can do
452 ldmfd
sp!, {r1, pc}RETCOND
456 #endif
/* L_dvmd_lnx
*/
458 /* These next two sections are here despite the fact that they contain Thumb
459 assembler because their presence allows interworked code to be linked even
460 when the GCC library is
this one.
*/
464 /* These labels
& instructions are used by the Arm
/Thumb interworking code.
465 The address of function to be called is loaded
into a register
and then
466 one of these labels is called via a
BL instruction.
This puts the
467 return address
into the link register with the bottom bit set
, and the
468 code here switches to the correct mode before executing the function.
*/
473 .
macro call_via register
474 .globl SYM
(_call_via_
\register
)
475 TYPE (_call_via_
\register
)
477 SYM
(_call_via_
\register
):
481 SIZE (_call_via_
\register
)
500 #endif
/* L_call_via_rX
*/
502 #ifdef L_interwork_call_via_rX
504 /* These labels
& instructions are used by the Arm
/Thumb interworking code
,
505 when the target address is
in an unknown instruction set. The address
506 of function to be called is loaded
into a register
and then one of these
507 labels is called via a
BL instruction.
This puts the return address
508 into the link register with the bottom bit set
, and the code here
509 switches to the correct mode before executing the function. Unfortunately
510 the target code cannot be relied upon to return via a
BX instruction
, so
511 instead we have to store the resturn address on the stack
and allow the
512 called function to return here instead. Upon return we recover the real
513 return address
and use a
BX to get back to Thumb mode.
*/
525 .
macro interwork register
527 .globl SYM
(_interwork_call_via_
\register
)
528 TYPE (_interwork_call_via_
\register
)
530 SYM
(_interwork_call_via_
\register
):
535 .globl .Lchange_
\register
539 adreq lr
, _arm_return
542 SIZE (_interwork_call_via_
\register
)
560 /* The lr case has to be handled a little differently...
*/
562 .globl SYM
(_interwork_call_via_lr
)
563 TYPE (_interwork_call_via_lr
)
565 SYM
(_interwork_call_via_lr
):
575 adreq lr
, _arm_return
578 SIZE (_interwork_call_via_lr
)
580 #endif
/* L_interwork_call_via_rX
*/