risc_v_disassembler/
macros.rs

1/// Extracts bits from a number
2/// 
3/// # Arguments
4/// 
5/// * `num` - The number to extract bits from
6/// * `start` - The starting index of the bits to extract
7/// * `end` - The ending index of the bits to extract
8/// 
9/// # Returns
10/// 
11/// * `Ok(u<size>)` - The extracted bits
12/// * `Err(DisassemblerError)` - Error message
13/// 
14/// # Examples
15/// 
16/// ```
17/// use risc_v_disassembler::extract_bits;
18/// 
19/// let number: u32 = 0b1111_1111_1001_1111_1111_1111_1111_1010;
20/// let result = extract_bits!(number, 0, 3);
21/// assert_eq!(result, Ok(0b1010));
22/// 
23/// let result = extract_bits!(number, 4, 7);
24/// assert_eq!(result, Ok(0b1111));
25/// ```
26#[macro_export]
27macro_rules! extract_bits {
28    ($num:expr, $start:expr, $end:expr) => {{
29        let bit_size = std::mem::size_of_val(&$num) * 8;
30        if $start <0 || $end >= bit_size {
31            Err($crate::DisassemblerError::BitExtractionError("Index out of bounds"))
32        } else if $start > $end {
33            Err($crate::DisassemblerError::BitExtractionError("Start index must be less than or equal to end index"))
34        } else {
35            let mask = (1 << ($end - $start + 1)) - 1;
36            Ok(($num >> $start) & mask)
37        }
38    }};
39}
40
41/// Sign-extends a number from chosen sign bit to 32 bits
42/// 
43/// # Arguments
44/// 
45/// * `num` - The number to sign-extend
46/// * `curr_size` - The number of bits to consider for sign extension
47/// 
48/// # Returns
49/// 
50/// * `Ok(i32)` - The sign-extended number
51/// * `Err(DisassemblerError)` - Error message
52/// 
53/// # Examples
54/// 
55/// ```
56/// use risc_v_disassembler::sign_extend32;
57/// 
58/// let bits: u32 = 0b0010;
59/// let result = sign_extend32!(bits, 3).unwrap();
60/// assert_eq!(result, 2);
61/// 
62/// let bits: u32 = 0b1010;
63/// let result = sign_extend32!(bits, 4).unwrap();
64/// assert_eq!(result, -6);
65/// ```
66/// 
67#[macro_export]
68macro_rules! sign_extend32 {
69    ($num:expr, $curr_size:expr) => {{
70        if $curr_size > 32 {
71            Err($crate::DisassemblerError::BitExtensionError("Size exceeds 32 bits"))
72        } else {
73            let sign_bit: u32 = 1 << ($curr_size - 1);
74            let mask: u32 = (1 << $curr_size - 1) - 1; 
75            let sign_extended: u32 = if $num & sign_bit != 0 {
76                ($num as u32) | !mask
77            } else {
78                $num
79            };
80            Ok(sign_extended as i32)
81        }
82    }}; 
83}
84
85pub(crate) use {
86    extract_bits,
87    sign_extend32,
88};
89
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_extract_bits_from_u64() {
97        let number: u64 = 0b1101_1111_1001_1111_1111_1111_1111_1010_1110_1111_1001_1111_1111_1111_1111_1010;
98        let result = extract_bits!(number, 0, 3);
99        assert_eq!(result, Ok(0b1010));
100
101        let result = extract_bits!(number, 4, 7);
102        assert_eq!(result, Ok(0b1111));
103
104        let result = extract_bits!(number, 20, 23);
105        assert_eq!(result, Ok(0b1001));
106
107        let result = extract_bits!(number, 24, 31);
108        assert_eq!(result, Ok(0b1110_1111));
109
110        let result = extract_bits!(number, 56, 63);
111        assert_eq!(result, Ok(0b1101_1111));
112    }
113
114    #[test]
115    fn test_extract_bits_from_i64() {
116        let number: i64 = 0b101_1111_1001_1111_1111_1111_1111_1010_1110_1111_1001_1111_1111_1111_1111_1010;
117        let result = extract_bits!(number, 0, 3);
118        assert_eq!(result, Ok(0b1010));
119
120        let result = extract_bits!(number, 4, 7);
121        assert_eq!(result, Ok(0b1111));
122
123        let result = extract_bits!(number, 20, 23);
124        assert_eq!(result, Ok(0b1001));
125
126        let result = extract_bits!(number, 24, 31);
127        assert_eq!(result, Ok(0b1110_1111));
128
129        let result = extract_bits!(number, 56, 63);
130        assert_eq!(result, Ok(0b101_1111));
131    }
132    
133    #[test]
134    fn test_extract_bits_u32() {
135        let number: u32 = 0b1011_1111_1001_1111_1111_1111_1111_1010;
136        let result = extract_bits!(number, 0, 3);
137        assert_eq!(result, Ok(0b1010));
138
139        let result = extract_bits!(number, 4, 7);
140        assert_eq!(result, Ok(0b1111));
141
142        let result = extract_bits!(number, 20, 23);
143        assert_eq!(result, Ok(0b1001));
144
145        let result = extract_bits!(number, 24, 31);
146        assert_eq!(result, Ok(0b1011_1111));
147    }
148
149    #[test]
150    fn test_extract_bits_i32() {
151        let number: u32 = 0b011_1111_1001_1111_1111_1111_1111_1010;
152        let result = extract_bits!(number, 0, 3);
153        assert_eq!(result, Ok(0b1010));
154
155        let result = extract_bits!(number, 4, 7);
156        assert_eq!(result, Ok(0b1111));
157
158        let result = extract_bits!(number, 20, 23);
159        assert_eq!(result, Ok(0b1001));
160
161        let result = extract_bits!(number, 24, 31);
162        assert_eq!(result, Ok(0b011_1111));
163    }
164
165    #[test]
166    fn test_extract_bits_u16() {
167        let number: u16 = 0b1100_1111_1001_1111;
168        let result = extract_bits!(number, 0, 3);
169        assert_eq!(result, Ok(0b1111));
170
171        let result = extract_bits!(number, 4, 7);
172        assert_eq!(result, Ok(0b1001));
173
174        let result = extract_bits!(number, 8, 11);
175        assert_eq!(result, Ok(0b1111));
176
177        let result = extract_bits!(number, 12, 15);
178        assert_eq!(result, Ok(0b1100));
179    }
180
181    #[test]
182    fn test_extract_bits_i16() {
183        let number: u16 = 0b100_1111_1001_1111;
184        let result = extract_bits!(number, 0, 3);
185        assert_eq!(result, Ok(0b1111));
186
187        let result = extract_bits!(number, 4, 7);
188        assert_eq!(result, Ok(0b1001));
189
190        let result = extract_bits!(number, 8, 11);
191        assert_eq!(result, Ok(0b1111));
192
193        let result = extract_bits!(number, 12, 15);
194        assert_eq!(result, Ok(0b100));
195    }
196
197    #[test]
198    fn test_extract_bits_u8() {
199        let number: u8 = 0b1011_1010;
200        let result = extract_bits!(number, 0, 3);
201        assert_eq!(result, Ok(0b1010));
202
203        let result = extract_bits!(number, 4, 7);
204        assert_eq!(result, Ok(0b1011));
205    }
206
207    #[test]
208    fn test_extract_bits_i8() {
209        let number: u8 = 0b011_1010;
210        let result = extract_bits!(number, 0, 3);
211        assert_eq!(result, Ok(0b1010));
212
213        let result = extract_bits!(number, 4, 7);
214        assert_eq!(result, Ok(0b011));
215    }
216
217    #[test]
218    fn test_sign_extend32(){
219        let bits: u32 = 0b0010;
220        let result = sign_extend32!(bits, 3).unwrap();
221        assert_eq!(result, 2);
222
223        let bits: u32 = 0b1010;
224        let result = sign_extend32!(bits, 4).unwrap();
225        assert_eq!(result, -6);
226
227        let bits: u32 = 0b1010;
228        let result = sign_extend32!(bits, 5).unwrap();
229        assert_eq!(result, 10);
230    }
231
232}