16bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon/*===-- divmodsi4.S - 32-bit signed integer divide and modulus ------------===//
26bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon *
36bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon *                     The LLVM Compiler Infrastructure
46bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon *
56bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon * This file is dual licensed under the MIT and the University of Illinois Open
66bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon * Source Licenses. See LICENSE.TXT for details.
76bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon *
86bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon *===----------------------------------------------------------------------===//
96bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon *
106bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon * This file implements the __divmodsi4 (32-bit signed integer divide and
116bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon * modulus) function for the ARM architecture.  A naive digit-by-digit
126bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon * computation is employed for simplicity.
136bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon *
146bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon *===----------------------------------------------------------------------===*/
156bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon
166bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon#include "../assembly.h"
176bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon
186bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon#define ESTABLISH_FRAME    \
196bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    push   {r4-r7, lr}   ;\
206bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    add     r7,     sp, #12
216bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon#define CLEAR_FRAME_AND_RETURN \
226bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    pop    {r4-r7, pc}
236bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon
245d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines	.syntax unified
255d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines	.text
265d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#if __ARM_ARCH_ISA_THUMB == 2
275d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines	.thumb
285d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#endif
295d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
305d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines	.p2align 3
316bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen CanonDEFINE_COMPILERRT_FUNCTION(__divmodsi4)
323a6eb8083c342da436df8c7d1809dfeb8834bc6dStephen Hines#if __ARM_ARCH_EXT_IDIV__
33a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	tst     r1, r1
34a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	beq     LOCAL_LABEL(divzero)
35a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	mov 	r3, r0
36a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	sdiv	r0, r3, r1
37a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	mls 	r1, r0, r1, r3
38a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	str 	r1, [r2]
39a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	bx  	lr
40a09d09d29e250e905bdfaf819979b9c3e9adc047Nick KledzikLOCAL_LABEL(divzero):
41a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	mov     r0, #0
42a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik	bx      lr
43a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik#else
446bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    ESTABLISH_FRAME
456bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon//  Set aside the sign of the quotient and modulus, and the address for the
466bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon//  modulus.
476bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    eor     r4,     r0, r1
486bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    mov     r5,     r0
496bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    mov     r6,     r2
506bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon//  Take the absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
516bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    eor     ip,     r0, r0, asr #31
526bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    eor     lr,     r1, r1, asr #31
536bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    sub     r0,     ip, r0, asr #31
546bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    sub     r1,     lr, r1, asr #31
556bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon//  Unsigned divmod:
56647fc7336b2bc302bb51e50022b27bf9b929071cAnton Korobeynikov    bl      SYMBOL_NAME(__udivmodsi4)
576bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon//  Apply the sign of quotient and modulus
586bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    ldr     r1,    [r6]
596bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    eor     r0,     r0, r4, asr #31
606bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    eor     r1,     r1, r5, asr #31
612caeeefe078e7c10170f02b717e4a5ab7623e554Stephen Canon    sub     r0,     r0, r4, asr #31
626bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    sub     r1,     r1, r5, asr #31
636bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    str     r1,    [r6]
646bbe0bb0856f7e7cabe11bc0a10c268db034142bStephen Canon    CLEAR_FRAME_AND_RETURN
65a09d09d29e250e905bdfaf819979b9c3e9adc047Nick Kledzik#endif
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesEND_COMPILERRT_FUNCTION(__divmodsi4)
67