1353358Sdim//===-- divsi3.S - 32-bit signed integer divide ---------------------------===//
2353358Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353358Sdim//
7353358Sdim//===----------------------------------------------------------------------===//
8353358Sdim//
9353358Sdim// This file implements the __divsi3 (32-bit signed integer divide) function
10353358Sdim// for the ARM architecture as a wrapper around the unsigned routine.
11353358Sdim//
12353358Sdim//===----------------------------------------------------------------------===//
13276789Sdim
14276789Sdim#include "../assembly.h"
15276789Sdim
16276789Sdim#define ESTABLISH_FRAME \
17276789Sdim    push   {r4, r7, lr}    ;\
18276789Sdim    add     r7,     sp, #4
19276789Sdim#define CLEAR_FRAME_AND_RETURN \
20276789Sdim    pop    {r4, r7, pc}
21276789Sdim
22316005Sdim   .syntax unified
23316005Sdim   .text
24327952Sdim   DEFINE_CODE_STATE
25276789Sdim
26276789Sdim	.p2align 3
27276789Sdim// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
28276789SdimDEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3)
29276789Sdim
30276789Sdim@ int __divsi3(int divident, int divisor)
31276789Sdim@   Calculate and return the quotient of the (signed) division.
32276789Sdim
33276789SdimDEFINE_COMPILERRT_FUNCTION(__divsi3)
34276789Sdim#if __ARM_ARCH_EXT_IDIV__
35276789Sdim   tst     r1,r1
36276789Sdim   beq     LOCAL_LABEL(divzero)
37276789Sdim   sdiv    r0, r0, r1
38276789Sdim   bx      lr
39276789SdimLOCAL_LABEL(divzero):
40276789Sdim   mov     r0,#0
41276789Sdim   bx      lr
42276789Sdim#else
43276789SdimESTABLISH_FRAME
44276789Sdim//  Set aside the sign of the quotient.
45327952Sdim#  if defined(USE_THUMB_1)
46314564Sdim    movs    r4,     r0
47314564Sdim    eors    r4,     r1
48314564Sdim#  else
49276789Sdim    eor     r4,     r0, r1
50314564Sdim#  endif
51276789Sdim//  Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
52327952Sdim#  if defined(USE_THUMB_1)
53314564Sdim    asrs    r2,     r0, #31
54314564Sdim    asrs    r3,     r1, #31
55314564Sdim    eors    r0,     r2
56314564Sdim    eors    r1,     r3
57314564Sdim    subs    r0,     r0, r2
58314564Sdim    subs    r1,     r1, r3
59314564Sdim#  else
60276789Sdim    eor     r2,     r0, r0, asr #31
61276789Sdim    eor     r3,     r1, r1, asr #31
62276789Sdim    sub     r0,     r2, r0, asr #31
63276789Sdim    sub     r1,     r3, r1, asr #31
64314564Sdim#  endif
65276789Sdim//  abs(a) / abs(b)
66276789Sdim    bl      SYMBOL_NAME(__udivsi3)
67276789Sdim//  Apply sign of quotient to result and return.
68316005Sdim#  if defined(USE_THUMB_1)
69314564Sdim    asrs    r4,     #31
70314564Sdim    eors    r0,     r4
71314564Sdim    subs    r0,     r0, r4
72314564Sdim#  else
73276789Sdim    eor     r0,     r0, r4, asr #31
74276789Sdim    sub     r0,     r0, r4, asr #31
75314564Sdim#  endif
76276789Sdim    CLEAR_FRAME_AND_RETURN
77276789Sdim#endif
78276789SdimEND_COMPILERRT_FUNCTION(__divsi3)
79309124Sdim
80309124SdimNO_EXEC_STACK_DIRECTIVE
81309124Sdim
82