mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-11 07:34:31 +00:00
1251d51ca5
When CONFIG_SYS_THUMB_BUILD is defined these functions may be called from Thumb code. Add the required ENTRY and ENDPROC bracketing so that BLX is used to call these ARM functions, instead of plain BL, which will fail. Signed-off-by: Simon Glass <sjg@chromium.org> Reported-by: Pavel Machek <pavel@denx.de>
90 lines
2.7 KiB
ArmAsm
90 lines
2.7 KiB
ArmAsm
#include <linux/linkage.h>
|
|
|
|
/* # 1 "libgcc1.S" */
|
|
@ libgcc1 routines for ARM cpu.
|
|
@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
|
|
/* # 145 "libgcc1.S" */
|
|
dividend .req r0
|
|
divisor .req r1
|
|
overdone .req r2
|
|
curbit .req r3
|
|
/* ip .req r12 */
|
|
/* sp .req r13 */
|
|
/* lr .req r14 */
|
|
/* pc .req r15 */
|
|
.text
|
|
.type __umodsi3 ,function
|
|
.align 0
|
|
ENTRY(__umodsi3)
|
|
cmp divisor, #0
|
|
beq Ldiv0
|
|
mov curbit, #1
|
|
cmp dividend, divisor
|
|
movcc pc, lr
|
|
Loop1:
|
|
@ Unless the divisor is very big, shift it up in multiples of
|
|
@ four bits, since this is the amount of unwinding in the main
|
|
@ division loop. Continue shifting until the divisor is
|
|
@ larger than the dividend.
|
|
cmp divisor, #0x10000000
|
|
cmpcc divisor, dividend
|
|
movcc divisor, divisor, lsl #4
|
|
movcc curbit, curbit, lsl #4
|
|
bcc Loop1
|
|
Lbignum:
|
|
@ For very big divisors, we must shift it a bit at a time, or
|
|
@ we will be in danger of overflowing.
|
|
cmp divisor, #0x80000000
|
|
cmpcc divisor, dividend
|
|
movcc divisor, divisor, lsl #1
|
|
movcc curbit, curbit, lsl #1
|
|
bcc Lbignum
|
|
Loop3:
|
|
@ Test for possible subtractions. On the final pass, this may
|
|
@ subtract too much from the dividend, so keep track of which
|
|
@ subtractions are done, we can fix them up afterwards...
|
|
mov overdone, #0
|
|
cmp dividend, divisor
|
|
subcs dividend, dividend, divisor
|
|
cmp dividend, divisor, lsr #1
|
|
subcs dividend, dividend, divisor, lsr #1
|
|
orrcs overdone, overdone, curbit, ror #1
|
|
cmp dividend, divisor, lsr #2
|
|
subcs dividend, dividend, divisor, lsr #2
|
|
orrcs overdone, overdone, curbit, ror #2
|
|
cmp dividend, divisor, lsr #3
|
|
subcs dividend, dividend, divisor, lsr #3
|
|
orrcs overdone, overdone, curbit, ror #3
|
|
mov ip, curbit
|
|
cmp dividend, #0 @ Early termination?
|
|
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
|
|
movne divisor, divisor, lsr #4
|
|
bne Loop3
|
|
@ Any subtractions that we should not have done will be recorded in
|
|
@ the top three bits of "overdone". Exactly which were not needed
|
|
@ are governed by the position of the bit, stored in ip.
|
|
@ If we terminated early, because dividend became zero,
|
|
@ then none of the below will match, since the bit in ip will not be
|
|
@ in the bottom nibble.
|
|
ands overdone, overdone, #0xe0000000
|
|
moveq pc, lr @ No fixups needed
|
|
tst overdone, ip, ror #3
|
|
addne dividend, dividend, divisor, lsr #3
|
|
tst overdone, ip, ror #2
|
|
addne dividend, dividend, divisor, lsr #2
|
|
tst overdone, ip, ror #1
|
|
addne dividend, dividend, divisor, lsr #1
|
|
mov pc, lr
|
|
Ldiv0:
|
|
str lr, [sp, #-4]!
|
|
bl __div0 (PLT)
|
|
mov r0, #0 @ about as wrong as it could be
|
|
ldmia sp!, {pc}
|
|
.size __umodsi3 , . - __umodsi3
|
|
/* # 320 "libgcc1.S" */
|
|
/* # 421 "libgcc1.S" */
|
|
/* # 433 "libgcc1.S" */
|
|
/* # 456 "libgcc1.S" */
|
|
/* # 500 "libgcc1.S" */
|
|
/* # 580 "libgcc1.S" */
|
|
ENDPROC(__umodsi3)
|