xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/arm/divsi3.S (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric//===-- divsi3.S - 32-bit signed integer divide ---------------------------===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file implements the __divsi3 (32-bit signed integer divide) function
100b57cec5SDimitry Andric// for the ARM architecture as a wrapper around the unsigned routine.
110b57cec5SDimitry Andric//
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric#include "../assembly.h"
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric#define ESTABLISH_FRAME \
170b57cec5SDimitry Andric    push   {r4, r7, lr}    ;\
180b57cec5SDimitry Andric    add     r7,     sp, #4
190b57cec5SDimitry Andric#define CLEAR_FRAME_AND_RETURN \
200b57cec5SDimitry Andric    pop    {r4, r7, pc}
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric   .syntax unified
230b57cec5SDimitry Andric   .text
240b57cec5SDimitry Andric   DEFINE_CODE_STATE
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric	.p2align 3
270b57cec5SDimitry Andric// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
280b57cec5SDimitry AndricDEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3)
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric@ int __divsi3(int divident, int divisor)
310b57cec5SDimitry Andric@   Calculate and return the quotient of the (signed) division.
320b57cec5SDimitry Andric
330b57cec5SDimitry AndricDEFINE_COMPILERRT_FUNCTION(__divsi3)
340b57cec5SDimitry Andric#if __ARM_ARCH_EXT_IDIV__
350b57cec5SDimitry Andric   tst     r1,r1
360b57cec5SDimitry Andric   beq     LOCAL_LABEL(divzero)
370b57cec5SDimitry Andric   sdiv    r0, r0, r1
380b57cec5SDimitry Andric   bx      lr
390b57cec5SDimitry AndricLOCAL_LABEL(divzero):
40*06c3fb27SDimitry Andric   // Use movs for compatibility with v8-m.base.
41*06c3fb27SDimitry Andric   movs    r0,#0
420b57cec5SDimitry Andric   bx      lr
430b57cec5SDimitry Andric#else
440b57cec5SDimitry AndricESTABLISH_FRAME
450b57cec5SDimitry Andric//  Set aside the sign of the quotient.
460b57cec5SDimitry Andric#  if defined(USE_THUMB_1)
470b57cec5SDimitry Andric    movs    r4,     r0
480b57cec5SDimitry Andric    eors    r4,     r1
490b57cec5SDimitry Andric#  else
500b57cec5SDimitry Andric    eor     r4,     r0, r1
510b57cec5SDimitry Andric#  endif
520b57cec5SDimitry Andric//  Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
530b57cec5SDimitry Andric#  if defined(USE_THUMB_1)
540b57cec5SDimitry Andric    asrs    r2,     r0, #31
550b57cec5SDimitry Andric    asrs    r3,     r1, #31
560b57cec5SDimitry Andric    eors    r0,     r2
570b57cec5SDimitry Andric    eors    r1,     r3
580b57cec5SDimitry Andric    subs    r0,     r0, r2
590b57cec5SDimitry Andric    subs    r1,     r1, r3
600b57cec5SDimitry Andric#  else
610b57cec5SDimitry Andric    eor     r2,     r0, r0, asr #31
620b57cec5SDimitry Andric    eor     r3,     r1, r1, asr #31
630b57cec5SDimitry Andric    sub     r0,     r2, r0, asr #31
640b57cec5SDimitry Andric    sub     r1,     r3, r1, asr #31
650b57cec5SDimitry Andric#  endif
660b57cec5SDimitry Andric//  abs(a) / abs(b)
670b57cec5SDimitry Andric    bl      SYMBOL_NAME(__udivsi3)
680b57cec5SDimitry Andric//  Apply sign of quotient to result and return.
690b57cec5SDimitry Andric#  if defined(USE_THUMB_1)
700b57cec5SDimitry Andric    asrs    r4,     #31
710b57cec5SDimitry Andric    eors    r0,     r4
720b57cec5SDimitry Andric    subs    r0,     r0, r4
730b57cec5SDimitry Andric#  else
740b57cec5SDimitry Andric    eor     r0,     r0, r4, asr #31
750b57cec5SDimitry Andric    sub     r0,     r0, r4, asr #31
760b57cec5SDimitry Andric#  endif
770b57cec5SDimitry Andric    CLEAR_FRAME_AND_RETURN
780b57cec5SDimitry Andric#endif
790b57cec5SDimitry AndricEND_COMPILERRT_FUNCTION(__divsi3)
800b57cec5SDimitry Andric
810b57cec5SDimitry AndricNO_EXEC_STACK_DIRECTIVE
820b57cec5SDimitry Andric
83