shift.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. use int::{DInt, HInt, Int};
  2. trait Ashl: DInt {
  3. /// Returns `a << b`, requires `b < Self::BITS`
  4. fn ashl(self, shl: u32) -> Self {
  5. let n_h = Self::H::BITS;
  6. if shl & n_h != 0 {
  7. // we only need `self.lo()` because `self.hi()` will be shifted out entirely
  8. (self.lo() << (shl - n_h)).widen_hi()
  9. } else if shl == 0 {
  10. self
  11. } else {
  12. Self::from_lo_hi(
  13. self.lo() << shl,
  14. self.lo().logical_shr(n_h - shl) | (self.hi() << shl),
  15. )
  16. }
  17. }
  18. }
  19. impl Ashl for u32 {}
  20. impl Ashl for u64 {}
  21. impl Ashl for u128 {}
  22. trait Ashr: DInt {
  23. /// Returns arithmetic `a >> b`, requires `b < Self::BITS`
  24. fn ashr(self, shr: u32) -> Self {
  25. let n_h = Self::H::BITS;
  26. if shr & n_h != 0 {
  27. Self::from_lo_hi(
  28. self.hi() >> (shr - n_h),
  29. // smear the sign bit
  30. self.hi() >> (n_h - 1),
  31. )
  32. } else if shr == 0 {
  33. self
  34. } else {
  35. Self::from_lo_hi(
  36. self.lo().logical_shr(shr) | (self.hi() << (n_h - shr)),
  37. self.hi() >> shr,
  38. )
  39. }
  40. }
  41. }
  42. impl Ashr for i32 {}
  43. impl Ashr for i64 {}
  44. impl Ashr for i128 {}
  45. trait Lshr: DInt {
  46. /// Returns logical `a >> b`, requires `b < Self::BITS`
  47. fn lshr(self, shr: u32) -> Self {
  48. let n_h = Self::H::BITS;
  49. if shr & n_h != 0 {
  50. self.hi().logical_shr(shr - n_h).zero_widen()
  51. } else if shr == 0 {
  52. self
  53. } else {
  54. Self::from_lo_hi(
  55. self.lo().logical_shr(shr) | (self.hi() << (n_h - shr)),
  56. self.hi().logical_shr(shr),
  57. )
  58. }
  59. }
  60. }
  61. impl Lshr for u32 {}
  62. impl Lshr for u64 {}
  63. impl Lshr for u128 {}
  64. intrinsics! {
  65. #[maybe_use_optimized_c_shim]
  66. pub extern "C" fn __ashlsi3(a: u32, b: u32) -> u32 {
  67. a.ashl(b)
  68. }
  69. #[maybe_use_optimized_c_shim]
  70. #[arm_aeabi_alias = __aeabi_llsl]
  71. pub extern "C" fn __ashldi3(a: u64, b: u32) -> u64 {
  72. a.ashl(b)
  73. }
  74. pub extern "C" fn __ashlti3(a: u128, b: u32) -> u128 {
  75. a.ashl(b)
  76. }
  77. #[maybe_use_optimized_c_shim]
  78. pub extern "C" fn __ashrsi3(a: i32, b: u32) -> i32 {
  79. a.ashr(b)
  80. }
  81. #[maybe_use_optimized_c_shim]
  82. #[arm_aeabi_alias = __aeabi_lasr]
  83. pub extern "C" fn __ashrdi3(a: i64, b: u32) -> i64 {
  84. a.ashr(b)
  85. }
  86. pub extern "C" fn __ashrti3(a: i128, b: u32) -> i128 {
  87. a.ashr(b)
  88. }
  89. #[maybe_use_optimized_c_shim]
  90. pub extern "C" fn __lshrsi3(a: u32, b: u32) -> u32 {
  91. a.lshr(b)
  92. }
  93. #[maybe_use_optimized_c_shim]
  94. #[arm_aeabi_alias = __aeabi_llsr]
  95. pub extern "C" fn __lshrdi3(a: u64, b: u32) -> u64 {
  96. a.lshr(b)
  97. }
  98. pub extern "C" fn __lshrti3(a: u128, b: u32) -> u128 {
  99. a.lshr(b)
  100. }
  101. pub extern "C" fn __rust_i128_shlo(a: i128, b: u128) -> (i128, bool) {
  102. (__ashlti3(a as _, b as _) as _, b >= 128)
  103. }
  104. pub extern "C" fn __rust_u128_shlo(a: u128, b: u128) -> (u128, bool) {
  105. (__ashlti3(a, b as _), b >= 128)
  106. }
  107. pub extern "C" fn __rust_i128_shro(a: i128, b: u128) -> (i128, bool) {
  108. (__ashrti3(a, b as _), b >= 128)
  109. }
  110. pub extern "C" fn __rust_u128_shro(a: u128, b: u128) -> (u128, bool) {
  111. (__lshrti3(a, b as _), b >= 128)
  112. }
  113. }