1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
/* Adapted from an algorithm given in ARM System Developer's Guide (7.3.1.2)
for dividing a 30-bit value by a 15-bit value, with two operations per
iteration by storing quotient and remainder together and adding the previous
quotient bit during trial subtraction. Modified to work with any dividend
and divisor both less than 1 << 30, and skipping trials by calculating bits
in output.
*/
.macro ARM_DIV_31_BODY dividend, divisor, result, bits, curbit, quotient, remainder
mov \bits, #1
cmp \divisor, \dividend, lsr #16
movls \divisor, \divisor, lsl #16
addls \bits, \bits, #16
cmp \divisor, \dividend, lsr #8
movls \divisor, \divisor, lsl #8
addls \bits, \bits, #8
cmp \divisor, \dividend, lsr #4
movls \divisor, \divisor, lsl #4
addls \bits, \bits, #4
cmp \divisor, \dividend, lsr #2
movls \divisor, \divisor, lsl #2
addls \bits, \bits, #2
cmp \divisor, \dividend, lsr #1
movls \divisor, \divisor, lsl #1
addls \bits, \bits, #1
rsbs \divisor, \divisor, #0
beq 20f
adds \result, \dividend, \divisor
subcc \result, \result, \divisor
rsb \curbit, \bits, #31
add pc, pc, \curbit, lsl #3
nop
.rept 30
adcs \result, \divisor, \result, lsl #1
subcc \result, \result, \divisor
.endr
/* shift remainder/quotient left one, add final quotient bit */
adc \result, \result, \result
mov \remainder, \result, lsr \bits
eor \quotient, \result, \dividend, lsl \bits
.endm
#ifdef USE_IRAM
.section .icode,"ax",%progbits
#else
.text
#endif
.align
.global udiv32_arm
.type udiv32_arm,%function
udiv32_arm:
tst r0, r0
/* High bit must be unset, otherwise shift numerator right, caluclate,
and correct results. As this case is very uncommon we want to avoid
any other delays on the main path in handling it, so the long divide
calls the short divide as a function. */
bmi 10f
udiv31_arm:
ARM_DIV_31_BODY r0, r1, r2, r3, ip, r0, r1
bx lr
10:
/* store original numerator and divisor, we'll need them to correct the
result, */
stmdb sp, { r0, r1, lr }
/* Call __div0 here if divisor is zero, otherwise it would report the wrong
address.
*/
cmp r0, #0
beq 20f
bl udiv31_arm
ldmdb sp, { r2, r3, lr }
movs r2, r2, lsr #1
adc r1, r1, r1
subs r1, r1, r3
adc r0, r0, r0
bx lr
20:
stmdb sp!, { lr }
bl __div0
.size udiv32_arm, . - udiv32_arm
|