1//===-- modsi3.S - 32-bit signed integer 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-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file implements the __modsi3 (32-bit signed integer modulus) function 10// for the ARM architecture as a wrapper around the unsigned routine. 11// 12//===----------------------------------------------------------------------===// 13 14#include "../assembly.h" 15 16#define ESTABLISH_FRAME \ 17 push {r4, r7, lr} ;\ 18 add r7, sp, #4 19#define CLEAR_FRAME_AND_RETURN \ 20 pop {r4, r7, pc} 21 22 .syntax unified 23 .text 24 DEFINE_CODE_STATE 25 26@ int __modsi3(int divident, int divisor) 27@ Calculate and return the remainder of the (signed) division. 28 29 .p2align 3 30DEFINE_COMPILERRT_FUNCTION(__modsi3) 31#if __ARM_ARCH_EXT_IDIV__ 32 tst r1, r1 33 beq LOCAL_LABEL(divzero) 34 sdiv r2, r0, r1 35 mls r0, r2, r1, r0 36 bx lr 37LOCAL_LABEL(divzero): 38 mov r0, #0 39 bx lr 40#else 41 ESTABLISH_FRAME 42 // Set aside the sign of the dividend. 43 mov r4, r0 44 // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). 45 eor r2, r0, r0, asr #31 46 eor r3, r1, r1, asr #31 47 sub r0, r2, r0, asr #31 48 sub r1, r3, r1, asr #31 49 // abs(a) % abs(b) 50 bl SYMBOL_NAME(__umodsi3) 51 // Apply sign of dividend to result and return. 52 eor r0, r0, r4, asr #31 53 sub r0, r0, r4, asr #31 54 CLEAR_FRAME_AND_RETURN 55#endif 56END_COMPILERRT_FUNCTION(__modsi3) 57 58NO_EXEC_STACK_DIRECTIVE 59 60