1use serde::{Deserialize, Serialize};
31use std::convert::TryInto;
32use std::fmt;
33use std::ops::{Add, BitAnd, BitOr, BitXor, Neg, Not, Shl, Shr, Sub};
34use std::u128;
35
36use super::{bzhi_u128, bzhi_u64, BV};
37use crate::error::ExecError;
38
39#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
40pub struct B64 {
41 pub len: u32,
42 pub bits: u64,
43}
44
45impl fmt::LowerHex for B64 {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(f, "{:x}", self.bits)
48 }
49}
50
51impl fmt::UpperHex for B64 {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "{:x}", self.bits)
54 }
55}
56
57impl fmt::Display for B64 {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 if self.len % 4 == 0 {
60 write!(f, "#x")?
61 } else {
62 write!(f, "#b")?
63 }
64 write_bits!(f, self.bits, self.len)
65 }
66}
67
68impl TryInto<u64> for B64 {
69 type Error = ExecError;
70
71 fn try_into(self) -> Result<u64, ExecError> {
72 Ok(self.bits)
73 }
74}
75
76impl Not for B64 {
77 type Output = B64;
78
79 fn not(self) -> Self::Output {
80 B64 { len: self.len, bits: bzhi_u64(!self.bits, self.len) }
81 }
82}
83
84impl BitXor for B64 {
85 type Output = Self;
86
87 fn bitxor(self, rhs: Self) -> Self::Output {
88 B64 { len: self.len, bits: self.bits ^ rhs.bits }
89 }
90}
91
92impl BitOr for B64 {
93 type Output = Self;
94
95 fn bitor(self, rhs: Self) -> Self::Output {
96 B64 { len: self.len, bits: self.bits | rhs.bits }
97 }
98}
99
100impl BitAnd for B64 {
101 type Output = Self;
102
103 fn bitand(self, rhs: Self) -> Self::Output {
104 B64 { len: self.len, bits: self.bits & rhs.bits }
105 }
106}
107
108impl Neg for B64 {
109 type Output = B64;
110
111 fn neg(self) -> Self::Output {
112 B64 { len: self.len, bits: bzhi_u64((-(self.bits as i64)) as u64, self.len) }
113 }
114}
115
116impl Add<B64> for B64 {
117 type Output = B64;
118
119 fn add(self, rhs: Self) -> Self::Output {
120 B64 { len: self.len, bits: bzhi_u64(self.bits.wrapping_add(rhs.bits), self.len) }
121 }
122}
123
124impl Sub<B64> for B64 {
125 type Output = B64;
126
127 fn sub(self, rhs: Self) -> Self::Output {
128 B64 { len: self.len, bits: bzhi_u64(self.bits.wrapping_sub(rhs.bits), self.len) }
129 }
130}
131
132impl Shl<B64> for B64 {
133 type Output = B64;
134
135 fn shl(self, rhs: Self) -> Self::Output {
136 if rhs.bits >= 64 {
137 B64 { len: self.len, bits: 0 }
138 } else {
139 B64 { len: self.len, bits: bzhi_u64(self.bits << rhs.bits, self.len) }
140 }
141 }
142}
143
144impl Shr<B64> for B64 {
145 type Output = B64;
146
147 fn shr(self, rhs: Self) -> Self::Output {
148 if rhs.bits >= 64 {
149 B64 { len: self.len, bits: 0 }
150 } else {
151 B64 { len: self.len, bits: bzhi_u64(self.bits >> rhs.bits, self.len) }
152 }
153 }
154}
155
156impl BV for B64 {
157 const BIT_ONE: Self = B64 { len: 1, bits: 1 };
158 const BIT_ZERO: Self = B64 { len: 1, bits: 0 };
159 const MAX_WIDTH: u32 = 64;
160
161 fn new(bits: u64, len: u32) -> Self {
162 assert!(len <= 64);
163 B64 { len, bits }
164 }
165
166 fn lower_u64(self) -> u64 {
167 self.bits
168 }
169
170 fn lower_u8(self) -> u8 {
171 (self.bits & 0xFF) as u8
172 }
173
174 fn is_zero(self) -> bool {
175 self.bits == 0
176 }
177
178 fn zeros(len: u32) -> Self {
179 assert!(len <= 64);
180 B64 { len, bits: 0 }
181 }
182
183 fn ones(len: u32) -> Self {
184 assert!(len <= 64);
185 B64 { len, bits: bzhi_u64(0xFFFF_FFFF_FFFF_FFFF, len) }
186 }
187
188 fn leading_zeros(self) -> u32 {
189 self.bits.leading_zeros() - (64 - self.len)
190 }
191
192 fn from_u8(value: u8) -> Self {
193 B64 { len: 8, bits: value as u64 }
194 }
195
196 fn from_u16(value: u16) -> Self {
197 B64 { len: 16, bits: value as u64 }
198 }
199
200 fn from_u32(value: u32) -> Self {
201 B64 { len: 32, bits: value as u64 }
202 }
203
204 fn from_u64(value: u64) -> Self {
205 B64 { len: 64, bits: value }
206 }
207
208 fn from_bytes(bytes: &[u8]) -> Self {
209 assert!(bytes.len() <= 8);
210 let mut bits: u64 = 0;
211 for byte in bytes {
212 bits = (bits << 8) | (*byte as u64)
213 }
214 B64 { len: bytes.len() as u32 * 8, bits }
215 }
216
217 fn to_le_bytes(self) -> Vec<u8> {
218 assert!(self.len % 8 == 0);
219 self.bits.to_le_bytes()[..self.len as usize / 8].to_vec()
220 }
221
222 fn to_be_bytes(self) -> Vec<u8> {
223 assert!(self.len % 8 == 0);
224 self.bits.to_be_bytes()[8 - self.len as usize / 8..].to_vec()
225 }
226
227 fn from_str(bv: &str) -> Option<Self> {
228 if bv.len() <= 2 || !(bv.starts_with('#') || bv.starts_with('0')) {
229 return None;
230 }
231
232 match bv.chars().nth(1) {
233 Some('x') => {
234 let hex = &bv[2..];
235 let len = hex.len();
236 if len <= 16 {
237 Some(B64 { len: len as u32 * 4, bits: u64::from_str_radix(hex, 16).ok()? })
238 } else {
239 None
240 }
241 }
242 Some('b') => {
243 let bin = &bv[2..];
244 let len = bin.len();
245 if len <= 64 {
246 Some(B64 { len: len as u32, bits: u64::from_str_radix(bin, 2).ok()? })
247 } else {
248 None
249 }
250 }
251 _ => None,
252 }
253 }
254
255 fn len(self) -> u32 {
256 self.len
257 }
258
259 fn add_i128(self, op: i128) -> Self {
260 B64 { len: self.len, bits: bzhi_u64(self.bits.wrapping_add(op as u64), self.len) }
261 }
262
263 fn zero_extend(self, new_len: u32) -> Self {
264 assert!(self.len <= new_len && new_len <= 64);
265 B64 { len: new_len, bits: self.bits }
266 }
267
268 fn sign_extend(self, new_len: u32) -> Self {
269 assert!(self.len <= new_len && new_len <= 64);
270 if self.len > 0 {
271 if (self.bits >> (self.len - 1)) & 0b1 == 0b1 {
272 let top = bzhi_u64(0xFFFF_FFFF_FFFF_FFFF, new_len) & !bzhi_u64(0xFFFF_FFFF_FFFF_FFFF, self.len);
273 B64 { len: new_len, bits: self.bits | top }
274 } else {
275 B64 { len: new_len, bits: self.bits }
276 }
277 } else {
278 B64 { len: new_len, bits: 0 }
279 }
280 }
281
282 fn unsigned(self) -> i128 {
283 i128::from(self.bits)
284 }
285
286 fn signed(self) -> i128 {
287 i128::from(self.sign_extend(64).bits as i64)
288 }
289
290 fn slice(self, from: u32, len: u32) -> Option<Self> {
291 if from + len <= self.len {
292 Some(B64 { len, bits: bzhi_u64(self.bits >> from, len) })
293 } else {
294 None
295 }
296 }
297
298 fn set_slice(self, n: u32, update: Self) -> Self {
299 let mask = !bzhi_u64(0xFFFF_FFFF_FFFF_FFFF << n, n + update.len);
300 let update = update.bits << n;
301 B64 { len: self.len, bits: (self.bits & mask) | update }
302 }
303
304 fn set_slice_int(int: i128, n: u32, update: Self) -> i128 {
305 let mask = !bzhi_u128(u128::max_value() << n, n as u32 + update.len());
306 let update = (update.bits as u128) << n;
307 ((int as u128 & mask) | update) as i128
308 }
309
310 fn get_slice_int(len: u32, int: i128, n: u32) -> Self {
311 let slice = bzhi_u64((int >> n) as u64, len);
312 Self::new(slice, len)
313 }
314}
315
316#[cfg(test)]
317mod tests {
318 use super::*;
319
320 #[test]
321 fn test_write_bits64() {
322 assert_eq!(format!("{}", B64::zeros(4)), "#x0");
323 assert_eq!(format!("{}", B64::zeros(8)), "#x00");
324 assert_eq!(format!("{}", B64::zeros(12)), "#x000");
325 assert_eq!(format!("{}", B64::zeros(16)), "#x0000");
326
327 assert_eq!(format!("{}", B64::ones(4)), "#xf");
328 assert_eq!(format!("{}", B64::ones(8)), "#xff");
329 assert_eq!(format!("{}", B64::ones(12)), "#xfff");
330 assert_eq!(format!("{}", B64::ones(16)), "#xffff");
331
332 assert_eq!(format!("{}", B64::from_u32(0xDEAD_BEEFu32)), "#xdeadbeef");
333
334 assert_eq!(format!("{}", B64::new(0b101, 3)), "#b101");
335 assert_eq!(format!("{}", B64::new(0b100, 3)), "#b100");
336 assert_eq!(format!("{}", B64::new(0b001, 3)), "#b001");
337
338 assert_eq!(format!("{}", B64::new(0x0000_0000_0000_0000, 64)), "#x0000000000000000");
339 }
340
341 #[test]
342 fn test_from_bytes() {
343 assert_eq!(B64::from_bytes(&[0xABu8, 0xCDu8]), B64::from_u16(0xABCDu16));
344 assert_eq!(B64::from_bytes(&[0xABu8, 0xCDu8, 0xEFu8]), B64::new(0xABCDEF, 24));
345 }
346
347 #[test]
348 fn test_add() {
349 assert_eq!(B64::new(0xFFFF_FFFF_FFFF_FFFF, 64) + B64::new(1, 64), B64::new(0, 64));
350 assert_eq!(B64::new(0xFF, 8) + B64::new(2, 8), B64::new(1, 8));
351 }
352
353 #[test]
354 fn test_neg() {
355 assert!(-B64::new(0b000, 3) == B64::new(0b000, 3));
356 assert!(-B64::new(0b001, 3) == B64::new(0b111, 3));
357 assert!(-B64::new(0b010, 3) == B64::new(0b110, 3));
358 assert!(-B64::new(0xFF, 8) == B64::new(0x1, 8));
359 assert!(-B64::new(0xFFFF_FFFF_FFFF_FFFF, 64) == B64::new(0x1, 64));
360 }
361
362 #[test]
363 fn test_shl() {
364 assert!(B64::new(0b001, 3) << B64::new(2, 3) == B64::new(0b100, 3));
365 assert!(B64::new(0b001, 3) << B64::new(3, 3) == B64::new(0b000, 3));
366 assert!(B64::new(0x0000_0000_0000_0001, 64) << B64::new(64, 64) == B64::new(0, 64));
367 assert!(B64::new(0x0000_0000_0000_0001, 64) << B64::new(65, 64) == B64::new(0, 64));
368 assert!(B64::new(0xFFFF_FFFF_FFFF_FFFF, 64) << B64::new(64, 64) == B64::new(0, 64));
369 assert!(B64::new(0xFFFF_FFFF_FFFF_FFFF, 64) << B64::new(66, 64) == B64::new(0, 64));
370 }
371
372 #[test]
373 fn test_shr() {
374 assert!(B64::new(0b100, 3) >> B64::new(2, 3) == B64::new(0b001, 3));
375 assert!(B64::new(0b100, 3) >> B64::new(3, 3) == B64::new(0b000, 3));
376 assert!(B64::new(0xFFFF_FFFF_FFFF_FFFF, 64) >> B64::new(64, 64) == B64::new(0, 64));
377 assert!(B64::new(0xFFFF_FFFF_FFFF_FFFF, 64) >> B64::new(66, 64) == B64::new(0, 64));
378 }
379
380 #[test]
381 fn test_zero_extend() {
382 assert!(B64::new(0b100, 3).zero_extend(3) == B64::new(0b100, 3));
383 assert!(B64::new(0b100, 3).zero_extend(6) == B64::new(0b000100, 6));
384 }
385
386 #[test]
387 fn test_sign_extend() {
388 assert!(B64::new(0b100, 3).sign_extend(6) == B64::new(0b111100, 6));
389 assert!(B64::new(0b010, 3).sign_extend(6) == B64::new(0b000010, 6));
390 assert!(B64::new(0b110, 3).sign_extend(3) == B64::new(0b110, 3));
391 assert!(B64::new(0b010, 3).sign_extend(3) == B64::new(0b010, 3));
392 assert!(B64::new(0xF, 4).sign_extend(8) == B64::new(0xFF, 8));
393 }
394
395 #[test]
396 fn test_append() {
397 let sbits_max = B64::new(0xFFFF_FFFF_FFFF_FFFF, 64);
398 assert!(B64::new(0, 0).append(sbits_max) == Some(sbits_max));
399 assert!(sbits_max.append(B64::new(0, 0)) == Some(sbits_max));
400 assert!(sbits_max.append(sbits_max) == None);
401 assert!(B64::new(0xCAFECAFE, 32).append(B64::new(0x1234ABCD, 32)) == Some(B64::new(0xCAFECAFE1234ABCD, 64)));
402 }
403
404 #[test]
405 fn test_slice() {
406 let sbits = B64::new(0xCAFE_F00D_1234_ABCD, 64);
407 assert!(sbits.slice(0, 32) == Some(B64::new(0x1234_ABCD, 32)));
408 assert!(sbits.slice(32, 32) == Some(B64::new(0xCAFE_F00D, 32)));
409 assert!(sbits.slice(16, 16) == Some(B64::new(0x1234, 16)));
410 }
411
412 #[test]
413 fn test_extract() {
414 let sbits = B64::new(0xCAFE_F00D_1234_ABCD, 64);
415 assert!(sbits.extract(31, 0) == Some(B64::new(0x1234_ABCD, 32)));
416 assert!(sbits.extract(63, 32) == Some(B64::new(0xCAFE_F00D, 32)));
417 assert!(sbits.extract(7, 0) == Some(B64::new(0xCD, 8)));
418 }
419
420 #[test]
421 fn test_truncate_lsb() {
422 let sbits = B64::new(0xCAFE_F00D_1234_ABCD, 64);
423 assert!(sbits.truncate_lsb(16) == Some(B64::new(0xCAFE, 16)));
424 assert!(sbits.truncate_lsb(64) == Some(sbits));
425 assert!(sbits.truncate_lsb(0) == Some(B64::new(0, 0)));
426 }
427
428 #[test]
429 fn test_signed() {
430 assert!(B64::new(0b100, 3).signed() == -4);
431 assert!(B64::new(0b011, 3).signed() == 3);
432 assert!(B64::new(0b111, 3).signed() == -1);
433 assert!(B64::new(0b000, 3).signed() == 0);
434 assert!(B64::new(0b1, 1).signed() == -1);
435 }
436
437 #[test]
438 fn test_unsigned() {
439 assert!(B64::new(0b100, 3).unsigned() == 4);
440 assert!(B64::new(0b011, 3).unsigned() == 3);
441 assert!(B64::new(0b111, 3).unsigned() == 7);
442 assert!(B64::new(0b000, 3).unsigned() == 0);
443 assert!(B64::new(0b1, 1).unsigned() == 1);
444 }
445
446 #[test]
447 fn test_replicate() {
448 assert!(B64::new(0b101, 3).replicate(0) == Some(B64::new(0, 0)));
449 assert!(B64::new(0b10, 2).replicate(3) == Some(B64::new(0b101010, 6)));
450 assert!(B64::new(0xCAFE, 16).replicate(4) == Some(B64::new(0xCAFECAFECAFECAFE, 64)));
451 assert!(B64::new(0b1, 1).replicate(128) == None);
452 }
453
454 #[test]
455 fn test_set_slice() {
456 assert!(B64::new(0b000, 3).set_slice(1, B64::new(0b1, 1)) == B64::new(0b010, 3));
457 assert!(B64::new(0b111, 3).set_slice(1, B64::new(0b0, 1)) == B64::new(0b101, 3));
458 assert!(B64::new(0b111, 3).set_slice(1, B64::new(0b1, 1)) == B64::new(0b111, 3));
459 assert!(B64::new(0b000, 3).set_slice(1, B64::new(0b0, 1)) == B64::new(0b000, 3));
460 assert!(B64::new(0xCAFE, 16).set_slice(4, B64::new(0x0, 4)) == B64::new(0xCA0E, 16));
461 assert!(B64::new(0xFFFF, 16).set_slice(12, B64::new(0x0, 4)) == B64::new(0x0FFF, 16));
462 assert!(B64::new(0xFFFF, 16).set_slice(8, B64::new(0x0, 4)) == B64::new(0xF0FF, 16));
463 assert!(B64::new(0xFFFF, 16).set_slice(4, B64::new(0x0, 4)) == B64::new(0xFF0F, 16));
464 assert!(B64::new(0xFFFF, 16).set_slice(0, B64::new(0x0, 4)) == B64::new(0xFFF0, 16));
465 }
466
467 #[test]
468 fn test_leading_zeros() {
469 assert_eq!(B64::new(0b001, 3).leading_zeros(), 2);
470 assert_eq!(B64::new(0b010, 3).leading_zeros(), 1);
471 assert_eq!(B64::new(0b00001, 5).leading_zeros(), 4);
472 assert_eq!(B64::new(0, 32).leading_zeros(), 32);
473 assert_eq!(B64::new(0, 64).leading_zeros(), 64);
474 assert_eq!(B64::new(0xFFFF_FFFF_FFFF_FFFF, 64).leading_zeros(), 0);
475 }
476
477 #[test]
478 fn test_set_slice_int() {
479 assert!(B64::set_slice_int(15, 1, B64::new(0, 2)) == 9)
480 }
481
482 #[test]
483 fn test_arith_shiftr() {
484 assert_eq!(B64::new(0b100, 3).arith_shiftr(0), B64::new(0b100, 3));
485 assert_eq!(B64::new(0b100, 3).arith_shiftr(1), B64::new(0b110, 3));
486 assert_eq!(B64::new(0b100, 3).arith_shiftr(2), B64::new(0b111, 3));
487 assert_eq!(B64::new(0b100, 3).arith_shiftr(3), B64::new(0b111, 3));
488 assert_eq!(B64::new(0b100, 3).arith_shiftr(4), B64::new(0b111, 3));
489
490 assert_eq!(B64::new(0b0110, 4).arith_shiftr(2), B64::new(0b0001, 4));
491 }
492
493 #[test]
494 fn test_to_bytes() {
495 assert_eq!(B64::new(0x123456, 24).to_le_bytes(), [0x56, 0x34, 0x12]);
496 assert_eq!(B64::new(0x123456, 24).to_be_bytes(), [0x12, 0x34, 0x56]);
497 }
498}