clzdi2.S 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. //===-- clzdi2.c - Implement __clzdi2 -------------------------------------===//
  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 count leading zeros for 64bit arguments.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "../assembly.h"
  13. .syntax unified
  14. .text
  15. DEFINE_CODE_STATE
  16. .p2align 2
  17. DEFINE_COMPILERRT_FUNCTION(__clzdi2)
  18. #ifdef __ARM_FEATURE_CLZ
  19. #ifdef __ARMEB__
  20. cmp r0, 0
  21. itee ne
  22. clzne r0, r0
  23. clzeq r0, r1
  24. addeq r0, r0, 32
  25. #else
  26. cmp r1, 0
  27. itee ne
  28. clzne r0, r1
  29. clzeq r0, r0
  30. addeq r0, r0, 32
  31. #endif
  32. JMP(lr)
  33. #else
  34. // Assumption: n != 0
  35. // r0: n
  36. // r1: upper half of n, overwritten after check
  37. // r1: count of leading zeros in n + 1
  38. // r2: scratch register for shifted r0
  39. #ifdef __ARMEB__
  40. cmp r0, 0
  41. moveq r0, r1
  42. #else
  43. cmp r1, 0
  44. movne r0, r1
  45. #endif
  46. movne r1, 1
  47. moveq r1, 33
  48. // Basic block:
  49. // if ((r0 >> SHIFT) == 0)
  50. // r1 += SHIFT;
  51. // else
  52. // r0 >>= SHIFT;
  53. // for descending powers of two as SHIFT.
  54. #define BLOCK(shift) \
  55. lsrs r2, r0, shift; \
  56. movne r0, r2; \
  57. addeq r1, shift \
  58. BLOCK(16)
  59. BLOCK(8)
  60. BLOCK(4)
  61. BLOCK(2)
  62. // The basic block invariants at this point are (r0 >> 2) == 0 and
  63. // r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1.
  64. //
  65. // r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1)
  66. // ---+----------------+----------------+------------+--------------
  67. // 1 | 1 | 0 | 0 | 1
  68. // 2 | 0 | 1 | -1 | 0
  69. // 3 | 0 | 1 | -1 | 0
  70. //
  71. // The r1's initial value of 1 compensates for the 1 here.
  72. sub r0, r1, r0, lsr #1
  73. JMP(lr)
  74. #endif // __ARM_FEATURE_CLZ
  75. END_COMPILERRT_FUNCTION(__clzdi2)
  76. NO_EXEC_STACK_DIRECTIVE