71 lines · plain
1//===-- divmodsi4.S - 32-bit signed integer divide and modulus ------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the __divmodsi4 (32-bit signed integer divide and10// modulus) function for the ARM architecture. A naive digit-by-digit11// computation is employed for simplicity.12//13//===----------------------------------------------------------------------===//14 15#include "../assembly.h"16 17#define ESTABLISH_FRAME \18 push {r4-r7, lr} ;\19 add r7, sp, #1220#define CLEAR_FRAME_AND_RETURN \21 pop {r4-r7, pc}22 23 .syntax unified24 .text25 DEFINE_CODE_STATE26 27@ int __divmodsi4(int divident, int divisor, int *remainder)28@ Calculate the quotient and remainder of the (signed) division. The return29@ value is the quotient, the remainder is placed in the variable.30 31 .p2align 332DEFINE_COMPILERRT_FUNCTION(__divmodsi4)33#if __ARM_ARCH_EXT_IDIV__34 tst r1, r135 beq LOCAL_LABEL(divzero)36 mov r3, r037 sdiv r0, r3, r138 mls r1, r0, r1, r339 str r1, [r2]40 bx lr41LOCAL_LABEL(divzero):42 mov r0, #043 bx lr44#else45 ESTABLISH_FRAME46// Set aside the sign of the quotient and modulus, and the address for the47// modulus.48 eor r4, r0, r149 mov r5, r050 mov r6, r251// Take the absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).52 eor ip, r0, r0, asr #3153 eor lr, r1, r1, asr #3154 sub r0, ip, r0, asr #3155 sub r1, lr, r1, asr #3156// Unsigned divmod:57 bl SYMBOL_NAME(__udivmodsi4)58// Apply the sign of quotient and modulus59 ldr r1, [r6]60 eor r0, r0, r4, asr #3161 eor r1, r1, r5, asr #3162 sub r0, r0, r4, asr #3163 sub r1, r1, r5, asr #3164 str r1, [r6]65 CLEAR_FRAME_AND_RETURN66#endif67END_COMPILERRT_FUNCTION(__divmodsi4)68 69NO_EXEC_STACK_DIRECTIVE70 71