208 lines
4.1 KiB
ArmAsm
Executable File
208 lines
4.1 KiB
ArmAsm
Executable File
/*
|
|
* linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
|
|
*
|
|
* Author: Nicolas Pitre <nico@fluxnic.net>
|
|
* - contributed to gcc-3.4 on Sep 30, 2003
|
|
* - adapted for the Linux kernel on Oct 2, 2003
|
|
*/
|
|
|
|
//for 1008M
|
|
#define STANDBY_COEFFICIENT (17)
|
|
|
|
.text
|
|
.globl standby_delay
|
|
standby_delay:
|
|
push {r0-r3}
|
|
ldr r1, =STANDBY_COEFFICIENT
|
|
mov r3, r0
|
|
standby_delay_loop2:
|
|
subs r0, r0, #1
|
|
bhi standby_delay_loop2
|
|
mov r0, r3
|
|
subs r1, r1, #1
|
|
bhi standby_delay_loop2
|
|
|
|
pop {r0-r3}
|
|
mov pc, lr
|
|
|
|
.text
|
|
.globl standby_delay_cycle
|
|
standby_delay_cycle:
|
|
standby_delay_cycle_loop3:
|
|
subs r0, r0, #1
|
|
bhi standby_delay_cycle_loop3
|
|
mov pc, lr
|
|
|
|
.macro ARM_DIV_BODY dividend, divisor, result, curbit
|
|
|
|
clz \curbit, \divisor
|
|
clz \result, \dividend
|
|
sub \result, \curbit, \result
|
|
mov \curbit, #1
|
|
mov \divisor, \divisor, lsl \result
|
|
mov \curbit, \curbit, lsl \result
|
|
mov \result, #0
|
|
|
|
@ Division loop
|
|
1: cmp \dividend, \divisor
|
|
subhs \dividend, \dividend, \divisor
|
|
orrhs \result, \result, \curbit
|
|
cmp \dividend, \divisor, lsr #1
|
|
subhs \dividend, \dividend, \divisor, lsr #1
|
|
orrhs \result, \result, \curbit, lsr #1
|
|
cmp \dividend, \divisor, lsr #2
|
|
subhs \dividend, \dividend, \divisor, lsr #2
|
|
orrhs \result, \result, \curbit, lsr #2
|
|
cmp \dividend, \divisor, lsr #3
|
|
subhs \dividend, \dividend, \divisor, lsr #3
|
|
orrhs \result, \result, \curbit, lsr #3
|
|
cmp \dividend, #0 @ Early termination?
|
|
movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
|
|
movne \divisor, \divisor, lsr #4
|
|
bne 1b
|
|
|
|
.endm
|
|
|
|
|
|
.macro ARM_DIV2_ORDER divisor, order
|
|
clz \order, \divisor
|
|
rsb \order, \order, #31
|
|
.endm
|
|
|
|
|
|
.macro ARM_MOD_BODY dividend, divisor, order, spare
|
|
clz \order, \divisor
|
|
clz \spare, \dividend
|
|
sub \order, \order, \spare
|
|
mov \divisor, \divisor, lsl \order
|
|
|
|
@ Perform all needed substractions to keep only the reminder.
|
|
@ Do comparisons in batch of 4 first.
|
|
subs \order, \order, #3 @ yes, 3 is intended here
|
|
blt 2f
|
|
|
|
1: cmp \dividend, \divisor
|
|
subhs \dividend, \dividend, \divisor
|
|
cmp \dividend, \divisor, lsr #1
|
|
subhs \dividend, \dividend, \divisor, lsr #1
|
|
cmp \dividend, \divisor, lsr #2
|
|
subhs \dividend, \dividend, \divisor, lsr #2
|
|
cmp \dividend, \divisor, lsr #3
|
|
subhs \dividend, \dividend, \divisor, lsr #3
|
|
cmp \dividend, #1
|
|
mov \divisor, \divisor, lsr #4
|
|
subges \order, \order, #4
|
|
bge 1b
|
|
|
|
tst \order, #3
|
|
teqne \dividend, #0
|
|
beq 5f
|
|
|
|
@ Either 1, 2 or 3 comparison/substractions are left.
|
|
2: cmn \order, #2
|
|
blt 4f
|
|
beq 3f
|
|
cmp \dividend, \divisor
|
|
subhs \dividend, \dividend, \divisor
|
|
mov \divisor, \divisor, lsr #1
|
|
3: cmp \dividend, \divisor
|
|
subhs \dividend, \dividend, \divisor
|
|
mov \divisor, \divisor, lsr #1
|
|
4: cmp \dividend, \divisor
|
|
subhs \dividend, \dividend, \divisor
|
|
5:
|
|
.endm
|
|
|
|
.text
|
|
.globl Ldiv0
|
|
Ldiv0:
|
|
str lr, [sp, #-8]!
|
|
bl __mem_div0
|
|
mov r0, #0 @ About as wrong as it could be.
|
|
ldr pc, [sp], #8
|
|
|
|
.text
|
|
.globl __aeabi_uidiv
|
|
__aeabi_uidiv:
|
|
subs r2, r1, #1
|
|
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, #1
|
|
movne r0, #0
|
|
mov pc, lr
|
|
|
|
12: ARM_DIV2_ORDER r1, r2
|
|
|
|
mov r0, r0, lsr r2
|
|
mov pc, lr
|
|
|
|
|
|
.text
|
|
.globl __aeabi_idiv
|
|
__aeabi_idiv:
|
|
cmp r1, #0
|
|
eor ip, r0, r1 @ save the sign of the result.
|
|
beq Ldiv0
|
|
rsbmi r1, r1, #0 @ loops below use unsigned.
|
|
subs r2, r1, #1 @ division by 1 or -1 ?
|
|
beq 10f
|
|
movs r3, r0
|
|
rsbmi r3, r0, #0 @ positive dividend value
|
|
cmp r3, r1
|
|
bls 11f
|
|
tst r1, r2 @ divisor is power of 2 ?
|
|
beq 12f
|
|
|
|
ARM_DIV_BODY r3, r1, r0, r2
|
|
|
|
cmp ip, #0
|
|
rsbmi r0, r0, #0
|
|
mov pc, lr
|
|
|
|
10: teq ip, r0 @ same sign ?
|
|
rsbmi r0, r0, #0
|
|
mov pc, lr
|
|
|
|
11: movlo r0, #0
|
|
moveq r0, ip, asr #31
|
|
orreq r0, r0, #1
|
|
mov pc, lr
|
|
|
|
12: ARM_DIV2_ORDER r1, r2
|
|
|
|
cmp ip, #0
|
|
mov r0, r3, lsr r2
|
|
rsbmi r0, r0, #0
|
|
mov pc, lr
|
|
|
|
.text
|
|
.globl __aeabi_uidivmod
|
|
__aeabi_uidivmod:
|
|
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
|
|
|
|
.text
|
|
.globl __aeabi_idivmod
|
|
__aeabi_idivmod:
|
|
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
|
|
|