ashrdi3.S 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  2. // See https://llvm.org/LICENSE.txt for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "../assembly.h"
  5. // di_int __ashrdi3(di_int input, int count);
  6. #ifdef __i386__
  7. #ifdef __SSE2__
  8. .text
  9. .balign 4
  10. DEFINE_COMPILERRT_FUNCTION(__ashrdi3)
  11. movd 12(%esp), %xmm2 // Load count
  12. movl 8(%esp), %eax
  13. #ifndef TRUST_CALLERS_USE_64_BIT_STORES
  14. movd 4(%esp), %xmm0
  15. movd 8(%esp), %xmm1
  16. punpckldq %xmm1, %xmm0 // Load input
  17. #else
  18. movq 4(%esp), %xmm0 // Load input
  19. #endif
  20. psrlq %xmm2, %xmm0 // unsigned shift input by count
  21. testl %eax, %eax // check the sign-bit of the input
  22. jns 1f // early out for positive inputs
  23. // If the input is negative, we need to construct the shifted sign bit
  24. // to or into the result, as xmm does not have a signed right shift.
  25. pcmpeqb %xmm1, %xmm1 // -1ULL
  26. psrlq $58, %xmm1 // 0x3f
  27. pandn %xmm1, %xmm2 // 63 - count
  28. pcmpeqb %xmm1, %xmm1 // -1ULL
  29. psubq %xmm1, %xmm2 // 64 - count
  30. psllq %xmm2, %xmm1 // -1 << (64 - count) = leading sign bits
  31. por %xmm1, %xmm0
  32. // Move the result back to the general purpose registers and return
  33. 1: movd %xmm0, %eax
  34. psrlq $32, %xmm0
  35. movd %xmm0, %edx
  36. ret
  37. END_COMPILERRT_FUNCTION(__ashrdi3)
  38. #else // Use GPRs instead of SSE2 instructions, if they aren't available.
  39. .text
  40. .balign 4
  41. DEFINE_COMPILERRT_FUNCTION(__ashrdi3)
  42. movl 12(%esp), %ecx // Load count
  43. movl 8(%esp), %edx // Load high
  44. movl 4(%esp), %eax // Load low
  45. testl $0x20, %ecx // If count >= 32
  46. jnz 1f // goto 1
  47. shrdl %cl, %edx, %eax // right shift low by count
  48. sarl %cl, %edx // right shift high by count
  49. ret
  50. 1: movl %edx, %eax // Move high to low
  51. sarl $31, %edx // clear high
  52. sarl %cl, %eax // shift low by count - 32
  53. ret
  54. END_COMPILERRT_FUNCTION(__ashrdi3)
  55. #endif // __SSE2__
  56. #endif // __i386__
  57. NO_EXEC_STACK_DIRECTIVE