1 /* # 1 "libgcc1.S" */

2 @ libgcc1 routines for ARM cpu.

3 @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)

4 /* # 145 "libgcc1.S" */

5 dividend .req r0

6 divisor .req r1

7 overdone .req r2

8 curbit .req r3

9 /* ip .req r12 */

10 /* sp .req r13 */

11 /* lr .req r14 */

12 /* pc .req r15 */

13 .text

14 .globl __umodsi3

15 .type __umodsi3 ,function

16 .align 0

17 __umodsi3 :

18 cmp divisor, #0

19 beq Ldiv0

20 mov curbit, #1

21 cmp dividend, divisor

22 movcc pc, lr

23 Loop1:

24 @ Unless the divisor is very big, shift it up in multiples of

25 @ four bits, since this is the amount of unwinding in the main

26 @ division loop. Continue shifting until the divisor is

27 @ larger than the dividend.

28 cmp divisor, #0x10000000

29 cmpcc divisor, dividend

30 movcc divisor, divisor, lsl #4

31 movcc curbit, curbit, lsl #4

32 bcc Loop1

33 Lbignum:

34 @ For very big divisors, we must shift it a bit at a time, or

35 @ we will be in danger of overflowing.

36 cmp divisor, #0x80000000

37 cmpcc divisor, dividend

38 movcc divisor, divisor, lsl #1

39 movcc curbit, curbit, lsl #1

40 bcc Lbignum

41 Loop3:

42 @ Test for possible subtractions. On the final pass, this may

43 @ subtract too much from the dividend, so keep track of which

44 @ subtractions are done, we can fix them up afterwards...

45 mov overdone, #0

46 cmp dividend, divisor

47 subcs dividend, dividend, divisor

48 cmp dividend, divisor, lsr #1

49 subcs dividend, dividend, divisor, lsr #1

50 orrcs overdone, overdone, curbit, ror #1

51 cmp dividend, divisor, lsr #2

52 subcs dividend, dividend, divisor, lsr #2

53 orrcs overdone, overdone, curbit, ror #2

54 cmp dividend, divisor, lsr #3

55 subcs dividend, dividend, divisor, lsr #3

56 orrcs overdone, overdone, curbit, ror #3

57 mov ip, curbit

58 cmp dividend, #0 @ Early termination?

59 movnes curbit, curbit, lsr #4 @ No, any more bits to do?

60 movne divisor, divisor, lsr #4

61 bne Loop3

62 @ Any subtractions that we should not have done will be recorded in

63 @ the top three bits of "overdone". Exactly which were not needed

64 @ are governed by the position of the bit, stored in ip.

65 @ If we terminated early, because dividend became zero,

66 @ then none of the below will match, since the bit in ip will not be

67 @ in the bottom nibble.

68 ands overdone, overdone, #0xe0000000

69 moveq pc, lr @ No fixups needed

70 tst overdone, ip, ror #3

71 addne dividend, dividend, divisor, lsr #3

72 tst overdone, ip, ror #2

73 addne dividend, dividend, divisor, lsr #2

74 tst overdone, ip, ror #1

75 addne dividend, dividend, divisor, lsr #1

76 mov pc, lr

77 Ldiv0:

78 str lr, [sp, #-4]!

79 bl __div0 (PLT)

80 mov r0, #0 @ about as wrong as it could be

81 ldmia sp!, {pc}

82 .size __umodsi3 , . - __umodsi3

83 /* # 320 "libgcc1.S" */

84 /* # 421 "libgcc1.S" */

85 /* # 433 "libgcc1.S" */

86 /* # 456 "libgcc1.S" */

87 /* # 500 "libgcc1.S" */

88 /* # 580 "libgcc1.S" */