xref: /minix3/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/modsi3.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc/*===-- modsi3.S - 32-bit signed integer 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 __modsi3 (32-bit signed integer modulus) 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@ int __modsi3(int divident, int divisor)
30*0a6a1f1dSLionel Sambuc@   Calculate and return the remainder of the (signed) division.
31*0a6a1f1dSLionel Sambuc
32*0a6a1f1dSLionel Sambuc	.p2align 3
33*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION(__modsi3)
34*0a6a1f1dSLionel Sambuc#if __ARM_ARCH_EXT_IDIV__
35*0a6a1f1dSLionel Sambuc	tst     r1, r1
36*0a6a1f1dSLionel Sambuc	beq     LOCAL_LABEL(divzero)
37*0a6a1f1dSLionel Sambuc	sdiv	r2, r0, r1
38*0a6a1f1dSLionel Sambuc	mls 	r0, r2, r1, r0
39*0a6a1f1dSLionel Sambuc	bx      lr
40*0a6a1f1dSLionel SambucLOCAL_LABEL(divzero):
41*0a6a1f1dSLionel Sambuc	mov     r0, #0
42*0a6a1f1dSLionel Sambuc	bx      lr
43*0a6a1f1dSLionel Sambuc#else
44*0a6a1f1dSLionel Sambuc    ESTABLISH_FRAME
45*0a6a1f1dSLionel Sambuc    //  Set aside the sign of the dividend.
46*0a6a1f1dSLionel Sambuc    mov     r4,     r0
47*0a6a1f1dSLionel Sambuc    //  Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
48*0a6a1f1dSLionel Sambuc    eor     r2,     r0, r0, asr #31
49*0a6a1f1dSLionel Sambuc    eor     r3,     r1, r1, asr #31
50*0a6a1f1dSLionel Sambuc    sub     r0,     r2, r0, asr #31
51*0a6a1f1dSLionel Sambuc    sub     r1,     r3, r1, asr #31
52*0a6a1f1dSLionel Sambuc    //  abs(a) % abs(b)
53*0a6a1f1dSLionel Sambuc    bl     SYMBOL_NAME(__umodsi3)
54*0a6a1f1dSLionel Sambuc    //  Apply sign of dividend to result and return.
55*0a6a1f1dSLionel Sambuc    eor     r0,     r0, r4, asr #31
56*0a6a1f1dSLionel Sambuc    sub     r0,     r0, r4, asr #31
57*0a6a1f1dSLionel Sambuc    CLEAR_FRAME_AND_RETURN
58*0a6a1f1dSLionel Sambuc#endif
59*0a6a1f1dSLionel SambucEND_COMPILERRT_FUNCTION(__modsi3)
60