modsi3.S 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  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. #include "../assembly.h"
  14. #define ESTABLISH_FRAME \
  15. push {r4, r7, lr} ;\
  16. add r7, sp, #4
  17. #define CLEAR_FRAME_AND_RETURN \
  18. pop {r4, r7, pc}
  19. .syntax unified
  20. .text
  21. DEFINE_CODE_STATE
  22. @ int __modsi3(int divident, int divisor)
  23. @ Calculate and return the remainder of the (signed) division.
  24. .p2align 3
  25. DEFINE_COMPILERRT_FUNCTION(__modsi3)
  26. #if __ARM_ARCH_EXT_IDIV__
  27. tst r1, r1
  28. beq LOCAL_LABEL(divzero)
  29. sdiv r2, r0, r1
  30. mls r0, r2, r1, r0
  31. bx lr
  32. LOCAL_LABEL(divzero):
  33. mov r0, #0
  34. bx lr
  35. #else
  36. ESTABLISH_FRAME
  37. // Set aside the sign of the dividend.
  38. mov r4, r0
  39. // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
  40. eor r2, r0, r0, asr #31
  41. eor r3, r1, r1, asr #31
  42. sub r0, r2, r0, asr #31
  43. sub r1, r3, r1, asr #31
  44. // abs(a) % abs(b)
  45. bl SYMBOL_NAME(__umodsi3)
  46. // Apply sign of dividend to result and return.
  47. eor r0, r0, r4, asr #31
  48. sub r0, r0, r4, asr #31
  49. CLEAR_FRAME_AND_RETURN
  50. #endif
  51. END_COMPILERRT_FUNCTION(__modsi3)
  52. NO_EXEC_STACK_DIRECTIVE