xref: /minix3/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/divmodsi4.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc/*===-- divmodsi4.S - 32-bit signed integer divide and modulus ------------===//
2*0a6a1f1dSLionel Sambuc *
3*0a6a1f1dSLionel Sambuc *                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc *
5*0a6a1f1dSLionel Sambuc * This file is dual licensed under the MIT and the University of Illinois Open
6*0a6a1f1dSLionel Sambuc * Source Licenses. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc *
8*0a6a1f1dSLionel Sambuc *===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc *
10*0a6a1f1dSLionel Sambuc * This file implements the __divmodsi4 (32-bit signed integer divide and
11*0a6a1f1dSLionel Sambuc * modulus) function for the ARM architecture.  A naive digit-by-digit
12*0a6a1f1dSLionel Sambuc * computation is employed for simplicity.
13*0a6a1f1dSLionel Sambuc *
14*0a6a1f1dSLionel Sambuc *===----------------------------------------------------------------------===*/
15*0a6a1f1dSLionel Sambuc
16*0a6a1f1dSLionel Sambuc#include "../assembly.h"
17*0a6a1f1dSLionel Sambuc
18*0a6a1f1dSLionel Sambuc#define ESTABLISH_FRAME    \
19*0a6a1f1dSLionel Sambuc    push   {r4-r7, lr}   ;\
20*0a6a1f1dSLionel Sambuc    add     r7,     sp, #12
21*0a6a1f1dSLionel Sambuc#define CLEAR_FRAME_AND_RETURN \
22*0a6a1f1dSLionel Sambuc    pop    {r4-r7, pc}
23*0a6a1f1dSLionel Sambuc
24*0a6a1f1dSLionel Sambuc	.syntax unified
25*0a6a1f1dSLionel Sambuc	.text
26*0a6a1f1dSLionel Sambuc#if __ARM_ARCH_ISA_THUMB == 2
27*0a6a1f1dSLionel Sambuc	.thumb
28*0a6a1f1dSLionel Sambuc#endif
29*0a6a1f1dSLionel Sambuc
30*0a6a1f1dSLionel Sambuc@ int __divmodsi4(int divident, int divisor, int *remainder)
31*0a6a1f1dSLionel Sambuc@   Calculate the quotient and remainder of the (signed) division.  The return
32*0a6a1f1dSLionel Sambuc@   value is the quotient, the remainder is placed in the variable.
33*0a6a1f1dSLionel Sambuc
34*0a6a1f1dSLionel Sambuc	.p2align 3
35*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION(__divmodsi4)
36*0a6a1f1dSLionel Sambuc#if __ARM_ARCH_EXT_IDIV__
37*0a6a1f1dSLionel Sambuc	tst     r1, r1
38*0a6a1f1dSLionel Sambuc	beq     LOCAL_LABEL(divzero)
39*0a6a1f1dSLionel Sambuc	mov 	r3, r0
40*0a6a1f1dSLionel Sambuc	sdiv	r0, r3, r1
41*0a6a1f1dSLionel Sambuc	mls 	r1, r0, r1, r3
42*0a6a1f1dSLionel Sambuc	str 	r1, [r2]
43*0a6a1f1dSLionel Sambuc	bx  	lr
44*0a6a1f1dSLionel SambucLOCAL_LABEL(divzero):
45*0a6a1f1dSLionel Sambuc	mov     r0, #0
46*0a6a1f1dSLionel Sambuc	bx      lr
47*0a6a1f1dSLionel Sambuc#else
48*0a6a1f1dSLionel Sambuc    ESTABLISH_FRAME
49*0a6a1f1dSLionel Sambuc//  Set aside the sign of the quotient and modulus, and the address for the
50*0a6a1f1dSLionel Sambuc//  modulus.
51*0a6a1f1dSLionel Sambuc    eor     r4,     r0, r1
52*0a6a1f1dSLionel Sambuc    mov     r5,     r0
53*0a6a1f1dSLionel Sambuc    mov     r6,     r2
54*0a6a1f1dSLionel Sambuc//  Take the absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
55*0a6a1f1dSLionel Sambuc    eor     ip,     r0, r0, asr #31
56*0a6a1f1dSLionel Sambuc    eor     lr,     r1, r1, asr #31
57*0a6a1f1dSLionel Sambuc    sub     r0,     ip, r0, asr #31
58*0a6a1f1dSLionel Sambuc    sub     r1,     lr, r1, asr #31
59*0a6a1f1dSLionel Sambuc//  Unsigned divmod:
60*0a6a1f1dSLionel Sambuc    bl      SYMBOL_NAME(__udivmodsi4)
61*0a6a1f1dSLionel Sambuc//  Apply the sign of quotient and modulus
62*0a6a1f1dSLionel Sambuc    ldr     r1,    [r6]
63*0a6a1f1dSLionel Sambuc    eor     r0,     r0, r4, asr #31
64*0a6a1f1dSLionel Sambuc    eor     r1,     r1, r5, asr #31
65*0a6a1f1dSLionel Sambuc    sub     r0,     r0, r4, asr #31
66*0a6a1f1dSLionel Sambuc    sub     r1,     r1, r5, asr #31
67*0a6a1f1dSLionel Sambuc    str     r1,    [r6]
68*0a6a1f1dSLionel Sambuc    CLEAR_FRAME_AND_RETURN
69*0a6a1f1dSLionel Sambuc#endif
70*0a6a1f1dSLionel SambucEND_COMPILERRT_FUNCTION(__divmodsi4)
71