OpenWrt – Rev 4

Subversion Repositories:
Rev:
/* # 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
        .globl   __umodsi3
        .type  __umodsi3       ,function
        .align 0
 __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" */