1 | use crate::int::{DInt, HInt, Int}; |
2 | |
3 | trait 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 | |
21 | impl Ashl for u32 {} |
22 | impl Ashl for u64 {} |
23 | impl Ashl for u128 {} |
24 | |
25 | trait 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 | |
46 | impl Ashr for i32 {} |
47 | impl Ashr for i64 {} |
48 | impl Ashr for i128 {} |
49 | |
50 | trait 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 | |
67 | impl Lshr for u32 {} |
68 | impl Lshr for u64 {} |
69 | impl Lshr for u128 {} |
70 | |
71 | intrinsics! { |
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 | |