diff options
Diffstat (limited to 'lib/arm/divmodsi4.S')
| -rw-r--r-- | lib/arm/divmodsi4.S | 47 | 
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/arm/divmodsi4.S b/lib/arm/divmodsi4.S new file mode 100644 index 0000000000000..cec39a7926f95 --- /dev/null +++ b/lib/arm/divmodsi4.S @@ -0,0 +1,47 @@ +/*===-- divmodsi4.S - 32-bit signed integer divide and modulus ------------===// + * + *                     The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===// + * + * This file implements the __divmodsi4 (32-bit signed integer divide and + * modulus) function for the ARM architecture.  A naive digit-by-digit + * computation is employed for simplicity. + * + *===----------------------------------------------------------------------===*/ + +#include "../assembly.h" + +#define ESTABLISH_FRAME    \ +    push   {r4-r7, lr}   ;\ +    add     r7,     sp, #12 +#define CLEAR_FRAME_AND_RETURN \ +    pop    {r4-r7, pc} + +.syntax unified +.align 3 +DEFINE_COMPILERRT_FUNCTION(__divmodsi4) +    ESTABLISH_FRAME +//  Set aside the sign of the quotient and modulus, and the address for the +//  modulus. +    eor     r4,     r0, r1 +    mov     r5,     r0 +    mov     r6,     r2 +//  Take the absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). +    eor     ip,     r0, r0, asr #31 +    eor     lr,     r1, r1, asr #31 +    sub     r0,     ip, r0, asr #31 +    sub     r1,     lr, r1, asr #31 +//  Unsigned divmod: +    bl      SYMBOL_NAME(__udivmodsi4) +//  Apply the sign of quotient and modulus +    ldr     r1,    [r6] +    eor     r0,     r0, r4, asr #31 +    eor     r1,     r1, r5, asr #31 +    sub     r0,     r0, r4, asr #31 +    sub     r1,     r1, r5, asr #31 +    str     r1,    [r6] +    CLEAR_FRAME_AND_RETURN  | 
