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