.macro ARM_DIV_BODY dividend, divisor, result, curbit
clz \curbit, \divisor
clz \result, \dividend
sub \result, \curbit, \result
mov \curbit,
mov \divisor, \divisor, lsl \result
mov \curbit, \curbit, lsl \result
mov \result,
@ Initially shift the divisor left 3 bits if possible,
@ set curbit accordingly. This allows for curbit to be located
@ at the left end of each 4 bit nibbles in the division loop
@ to save one loop in most cases.
tst \divisor,
moveq \divisor, \divisor, lsl
moveq \curbit,
movne \curbit,
@ 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.
1: cmp \divisor,
cmplo \divisor, \dividend
movlo \divisor, \divisor, lsl
movlo \curbit, \curbit, lsl
blo 1b
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
1: cmp \divisor,
cmplo \divisor, \dividend
movlo \divisor, \divisor, lsl
movlo \curbit, \curbit, lsl
blo 1b
mov \result,
@ Division loop
1: cmp \dividend, \divisor
subhs \dividend, \dividend, \divisor
orrhs \result, \result, \curbit
cmp \dividend, \divisor, lsr
subhs \dividend, \dividend, \divisor, lsr
orrhs \result, \result, \curbit, lsr
cmp \dividend, \divisor, lsr
subhs \dividend, \dividend, \divisor, lsr
orrhs \result, \result, \curbit, lsr
cmp \dividend, \divisor, lsr
subhs \dividend, \dividend, \divisor, lsr
orrhs \result, \result, \curbit, lsr
cmp \dividend,
movnes \curbit, \curbit, lsr
movne \divisor, \divisor, lsr
bne 1b
.endm
.macro ARM_DIV2_ORDER divisor, order
clz \order, \divisor
rsb \order, \order,
cmp \divisor,
movhs \divisor, \divisor, lsr
movhs \order,
movlo \order,
cmp \divisor,
movhs \divisor, \divisor, lsr
addhs \order, \order,
cmp \divisor,
movhs \divisor, \divisor, lsr
addhs \order, \order,
cmp \divisor,
addhi \order, \order,
addls \order, \order, \divisor, lsr
.endm
.macro ARM_MOD_BODY dividend, divisor, order, spare
clz \order, \divisor
clz \spare, \dividend
sub \order, \order, \spare
mov \divisor, \divisor, lsl \order
mov \order,
@ 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.
1: cmp \divisor,
cmplo \divisor, \dividend
movlo \divisor, \divisor, lsl
addlo \order, \order,
blo 1b
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
1: cmp \divisor,
cmplo \divisor, \dividend
movlo \divisor, \divisor, lsl
addlo \order, \order,
blo 1b
@ Perform all needed substractions to keep only the reminder.
@ Do comparisons in batch of 4 first.
subs \order, \order,
blt 2f
1: cmp \dividend, \divisor
subhs \dividend, \dividend, \divisor
cmp \dividend, \divisor, lsr
subhs \dividend, \dividend, \divisor, lsr
cmp \dividend, \divisor, lsr
subhs \dividend, \dividend, \divisor, lsr
cmp \dividend, \divisor, lsr
subhs \dividend, \dividend, \divisor, lsr
cmp \dividend,
mov \divisor, \divisor, lsr
subges \order, \order,
bge 1b
tst \order,
teqne \dividend,
beq 5f
@ Either 1, 2 or 3 comparison/substractions are left.
2: cmn \order,
blt 4f
beq 3f
cmp \dividend, \divisor
subhs \dividend, \dividend, \divisor
mov \divisor, \divisor, lsr
3: cmp \dividend, \divisor
subhs \dividend, \dividend, \divisor
mov \divisor, \divisor, lsr
4: cmp \dividend, \divisor
subhs \dividend, \dividend, \divisor
5:
.endm
ENTRY(__udivsi3)
ENTRY(__aeabi_uidiv)
UNWIND(.fnstart)
subs r2, r1,
moveq pc, lr
bcc Ldiv0
cmp r0, r1
bls 11f
tst r1, r2
beq 12f
ARM_DIV_BODY r0, r1, r2, r3
mov r0, r2
mov pc, lr
11: moveq r0,
movne r0,
mov pc, lr
12: ARM_DIV2_ORDER r1, r2
mov r0, r0, lsr r2
mov pc, lr
UNWIND(.fnend)
ENDPROC(__udivsi3)
ENDPROC(__aeabi_uidiv)
ENTRY(__umodsi3)
UNWIND(.fnstart)
subs r2, r1,
bcc Ldiv0
cmpne r0, r1 @ compare dividend with divisor
moveq r0,
tsthi r1, r2 @ see if divisor is power of 2
andeq r0, r0, r2
movls pc, lr
ARM_MOD_BODY r0, r1, r2, r3
mov pc, lr
UNWIND(.fnend)
ENDPROC(__umodsi3)
ENTRY(__divsi3)
ENTRY(__aeabi_idiv)
UNWIND(.fnstart)
cmp r1,
eor ip, r0, r1 @ save the sign of the result.
beq Ldiv0
rsbmi r1, r1,
subs r2, r1,
beq 10f
movs r3, r0
rsbmi r3, r0,
cmp r3, r1
bls 11f
tst r1, r2 @ divisor is power of 2 ?
beq 12f
ARM_DIV_BODY r3, r1, r0, r2
cmp ip,
rsbmi r0, r0,
mov pc, lr
10: teq ip, r0 @ same sign ?
rsbmi r0, r0,
mov pc, lr
11: movlo r0,
moveq r0, ip, asr
orreq r0, r0,
mov pc, lr
12: ARM_DIV2_ORDER r1, r2
cmp ip,
mov r0, r3, lsr r2
rsbmi r0, r0,
mov pc, lr
UNWIND(.fnend)
ENDPROC(__divsi3)
ENDPROC(__aeabi_idiv)
ENTRY(__modsi3)
UNWIND(.fnstart)
cmp r1,
beq Ldiv0
rsbmi r1, r1,
movs ip, r0 @ preserve sign of dividend
rsbmi r0, r0,
subs r2, r1,
cmpne r0, r1 @ compare dividend with divisor
moveq r0,
tsthi r1, r2 @ see if divisor is power of 2
andeq r0, r0, r2
bls 10f
ARM_MOD_BODY r0, r1, r2, r3
10: cmp ip,
rsbmi r0, r0,
mov pc, lr
UNWIND(.fnend)
ENDPROC(__modsi3)
ENTRY(__aeabi_uidivmod)
UNWIND(.fnstart)
UNWIND(.save {r0, r1, ip, lr} )
stmfd sp!, {r0, r1, ip, lr}
bl __aeabi_uidiv
ldmfd sp!, {r1, r2, ip, lr}
mul r3, r0, r2
sub r1, r1, r3
mov pc, lr
UNWIND(.fnend)
ENDPROC(__aeabi_uidivmod)
ENTRY(__aeabi_idivmod)
UNWIND(.fnstart)
UNWIND(.save {r0, r1, ip, lr} )
stmfd sp!, {r0, r1, ip, lr}
bl __aeabi_idiv
ldmfd sp!, {r1, r2, ip, lr}
mul r3, r0, r2
sub r1, r1, r3
mov pc, lr
UNWIND(.fnend)
ENDPROC(__aeabi_idivmod)
Ldiv0:
UNWIND(.fnstart)
UNWIND(.pad
UNWIND(.save {lr})
str lr, [sp,
bl __div0
mov r0,
ldr pc, [sp],
UNWIND(.fnend)
ENDPROC(Ldiv0)