1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
// Copyright (C) 2024 Intel Corporation.
// Author(s): Zhao Liu <zhai1.liu@intel.com>
// SPDX-License-Identifier: GPL-2.0-or-later
//! This module provides bit operation extensions to integer types.
//! It is usually included via the `qemu_api` prelude.
use std::ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign,
};
/// Trait for extensions to integer types
pub trait IntegerExt:
Add<Self, Output = Self> + AddAssign<Self> +
BitAnd<Self, Output = Self> + BitAndAssign<Self> +
BitOr<Self, Output = Self> + BitOrAssign<Self> +
BitXor<Self, Output = Self> + BitXorAssign<Self> +
Copy +
Div<Self, Output = Self> + DivAssign<Self> +
Eq +
Mul<Self, Output = Self> + MulAssign<Self> +
Not<Output = Self> + Ord + PartialOrd +
Rem<Self, Output = Self> + RemAssign<Self> +
Shl<Self, Output = Self> + ShlAssign<Self> +
Shl<u32, Output = Self> + ShlAssign<u32> + // add more as needed
Shr<Self, Output = Self> + ShrAssign<Self> +
Shr<u32, Output = Self> + ShrAssign<u32> // add more as needed
{
const BITS: u32;
const MAX: Self;
const MIN: Self;
const ONE: Self;
const ZERO: Self;
#[inline]
#[must_use]
fn bit(start: u32) -> Self
{
debug_assert!(start < Self::BITS);
Self::ONE << start
}
#[inline]
#[must_use]
fn mask(start: u32, length: u32) -> Self
{
/* FIXME: Implement a more elegant check with error handling support? */
debug_assert!(start < Self::BITS && length > 0 && length <= Self::BITS - start);
(Self::MAX >> (Self::BITS - length)) << start
}
#[inline]
#[must_use]
fn deposit<U: IntegerExt>(self, start: u32, length: u32,
fieldval: U) -> Self
where Self: From<U>
{
debug_assert!(length <= U::BITS);
let mask = Self::mask(start, length);
(self & !mask) | ((Self::from(fieldval) << start) & mask)
}
#[inline]
#[must_use]
fn extract(self, start: u32, length: u32) -> Self
{
let mask = Self::mask(start, length);
(self & mask) >> start
}
}
macro_rules! impl_num_ext {
($type:ty) => {
impl IntegerExt for $type {
const BITS: u32 = <$type>::BITS;
const MAX: Self = <$type>::MAX;
const MIN: Self = <$type>::MIN;
const ONE: Self = 1;
const ZERO: Self = 0;
}
};
}
impl_num_ext!(u8);
impl_num_ext!(u16);
impl_num_ext!(u32);
impl_num_ext!(u64);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deposit() {
assert_eq!(15u32.deposit(8, 8, 1u32), 256 + 15);
assert_eq!(15u32.deposit(8, 1, 255u8), 256 + 15);
}
#[test]
fn test_extract() {
assert_eq!(15u32.extract(2, 4), 3);
}
#[test]
fn test_bit() {
assert_eq!(u8::bit(7), 128);
assert_eq!(u32::bit(16), 0x10000);
}
#[test]
fn test_mask() {
assert_eq!(u8::mask(7, 1), 128);
assert_eq!(u32::mask(8, 8), 0xff00);
}
}
|