xref: /minix3/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/divsi3.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc/*===-- divsi3.S - 32-bit signed integer divide ---------------------------===//
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 __divsi3 (32-bit signed integer divide) function
11*0a6a1f1dSLionel Sambuc * for the ARM architecture as a wrapper around the unsigned routine.
12*0a6a1f1dSLionel Sambuc *
13*0a6a1f1dSLionel Sambuc *===----------------------------------------------------------------------===*/
14*0a6a1f1dSLionel Sambuc
15*0a6a1f1dSLionel Sambuc#include "../assembly.h"
16*0a6a1f1dSLionel Sambuc
17*0a6a1f1dSLionel Sambuc#define ESTABLISH_FRAME \
18*0a6a1f1dSLionel Sambuc    push   {r4, r7, lr}    ;\
19*0a6a1f1dSLionel Sambuc    add     r7,     sp, #4
20*0a6a1f1dSLionel Sambuc#define CLEAR_FRAME_AND_RETURN \
21*0a6a1f1dSLionel Sambuc    pop    {r4, r7, pc}
22*0a6a1f1dSLionel Sambuc
23*0a6a1f1dSLionel Sambuc	.syntax unified
24*0a6a1f1dSLionel Sambuc	.text
25*0a6a1f1dSLionel Sambuc#if __ARM_ARCH_ISA_THUMB == 2
26*0a6a1f1dSLionel Sambuc	.thumb
27*0a6a1f1dSLionel Sambuc#endif
28*0a6a1f1dSLionel Sambuc
29*0a6a1f1dSLionel Sambuc	.p2align 3
30*0a6a1f1dSLionel Sambuc// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
31*0a6a1f1dSLionel SambucDEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3)
32*0a6a1f1dSLionel Sambuc
33*0a6a1f1dSLionel Sambuc@ int __divsi3(int divident, int divisor)
34*0a6a1f1dSLionel Sambuc@   Calculate and return the quotient of the (signed) division.
35*0a6a1f1dSLionel Sambuc
36*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION(__divsi3)
37*0a6a1f1dSLionel Sambuc#if __ARM_ARCH_EXT_IDIV__
38*0a6a1f1dSLionel Sambuc   tst     r1,r1
39*0a6a1f1dSLionel Sambuc   beq     LOCAL_LABEL(divzero)
40*0a6a1f1dSLionel Sambuc   sdiv    r0, r0, r1
41*0a6a1f1dSLionel Sambuc   bx      lr
42*0a6a1f1dSLionel SambucLOCAL_LABEL(divzero):
43*0a6a1f1dSLionel Sambuc   mov     r0,#0
44*0a6a1f1dSLionel Sambuc   bx      lr
45*0a6a1f1dSLionel Sambuc#else
46*0a6a1f1dSLionel SambucESTABLISH_FRAME
47*0a6a1f1dSLionel Sambuc//  Set aside the sign of the quotient.
48*0a6a1f1dSLionel Sambuc    eor     r4,     r0, r1
49*0a6a1f1dSLionel Sambuc//  Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
50*0a6a1f1dSLionel Sambuc    eor     r2,     r0, r0, asr #31
51*0a6a1f1dSLionel Sambuc    eor     r3,     r1, r1, asr #31
52*0a6a1f1dSLionel Sambuc    sub     r0,     r2, r0, asr #31
53*0a6a1f1dSLionel Sambuc    sub     r1,     r3, r1, asr #31
54*0a6a1f1dSLionel Sambuc//  abs(a) / abs(b)
55*0a6a1f1dSLionel Sambuc    bl      SYMBOL_NAME(__udivsi3)
56*0a6a1f1dSLionel Sambuc//  Apply sign of quotient to result and return.
57*0a6a1f1dSLionel Sambuc    eor     r0,     r0, r4, asr #31
58*0a6a1f1dSLionel Sambuc    sub     r0,     r0, r4, asr #31
59*0a6a1f1dSLionel Sambuc    CLEAR_FRAME_AND_RETURN
60*0a6a1f1dSLionel Sambuc#endif
61*0a6a1f1dSLionel SambucEND_COMPILERRT_FUNCTION(__divsi3)
62