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