1 // SPDX-License-Identifier: MIT or Apache-2.0 or GPL-2.0-or-later 2 3 /// # Definition entry point 4 /// 5 /// Define a struct with a single field of type $type. Include public constants 6 /// for each element listed in braces. 7 /// 8 /// The unnamed element at the end, if present, can be used to enlarge the set 9 /// of valid bits. Bits that are valid but not listed are treated normally for 10 /// the purpose of arithmetic operations, and are printed with their hexadecimal 11 /// value. 12 /// 13 /// The struct implements the following traits: [`BitAnd`](std::ops::BitAnd), 14 /// [`BitOr`](std::ops::BitOr), [`BitXor`](std::ops::BitXor), 15 /// [`Not`](std::ops::Not), [`Sub`](std::ops::Sub); [`Debug`](std::fmt::Debug), 16 /// [`Display`](std::fmt::Display), [`Binary`](std::fmt::Binary), 17 /// [`Octal`](std::fmt::Octal), [`LowerHex`](std::fmt::LowerHex), 18 /// [`UpperHex`](std::fmt::UpperHex); [`From`]`<type>`/[`Into`]`<type>` where 19 /// type is the type specified in the definition. 20 /// 21 /// ## Example 22 /// 23 /// ``` 24 /// # use bits::bits; 25 /// bits! { 26 /// pub struct Colors(u8) { 27 /// BLACK = 0, 28 /// RED = 1, 29 /// GREEN = 1 << 1, 30 /// BLUE = 1 << 2, 31 /// WHITE = (1 << 0) | (1 << 1) | (1 << 2), 32 /// } 33 /// } 34 /// ``` 35 /// 36 /// ``` 37 /// # use bits::bits; 38 /// # bits! { pub struct Colors(u8) { BLACK = 0, RED = 1, GREEN = 1 << 1, BLUE = 1 << 2, } } 39 /// 40 /// bits! { 41 /// pub struct Colors8(u8) { 42 /// BLACK = 0, 43 /// RED = 1, 44 /// GREEN = 1 << 1, 45 /// BLUE = 1 << 2, 46 /// WHITE = (1 << 0) | (1 << 1) | (1 << 2), 47 /// 48 /// _ = 255, 49 /// } 50 /// } 51 /// 52 /// // The previously defined struct ignores bits not explicitly defined. 53 /// assert_eq!( 54 /// Colors::from(255).into_bits(), 55 /// (Colors::RED | Colors::GREEN | Colors::BLUE).into_bits() 56 /// ); 57 /// 58 /// // Adding "_ = 255" makes it retain other bits as well. 59 /// assert_eq!(Colors8::from(255).into_bits(), 255); 60 /// 61 /// // all() does not include the additional bits, valid_bits() does 62 /// assert_eq!(Colors8::all().into_bits(), Colors::all().into_bits()); 63 /// assert_eq!(Colors8::valid_bits().into_bits(), 255); 64 /// ``` 65 /// 66 /// # Evaluation entry point 67 /// 68 /// Return a constant corresponding to the boolean expression `$expr`. 69 /// Identifiers in the expression correspond to values defined for the 70 /// type `$type`. Supported operators are `!` (unary), `-`, `&`, `^`, `|`. 71 /// 72 /// ## Examples 73 /// 74 /// ``` 75 /// # use bits::bits; 76 /// bits! { 77 /// pub struct Colors(u8) { 78 /// BLACK = 0, 79 /// RED = 1, 80 /// GREEN = 1 << 1, 81 /// BLUE = 1 << 2, 82 /// // same as "WHITE = 7", 83 /// WHITE = bits!(Self as u8: RED | GREEN | BLUE), 84 /// } 85 /// } 86 /// 87 /// let rgb = bits! { Colors: RED | GREEN | BLUE }; 88 /// assert_eq!(rgb, Colors::WHITE); 89 /// ``` 90 #[macro_export] 91 macro_rules! bits { 92 { 93 $(#[$struct_meta:meta])* 94 $struct_vis:vis struct $struct_name:ident($field_vis:vis $type:ty) { 95 $($(#[$const_meta:meta])* $const:ident = $val:expr),+ 96 $(,_ = $mask:expr)? 97 $(,)? 98 } 99 } => { 100 $(#[$struct_meta])* 101 #[derive(Clone, Copy, PartialEq, Eq)] 102 #[repr(transparent)] 103 $struct_vis struct $struct_name($field_vis $type); 104 105 impl $struct_name { 106 $( #[allow(dead_code)] $(#[$const_meta])* 107 pub const $const: $struct_name = $struct_name($val); )+ 108 109 #[doc(hidden)] 110 const VALID__: $type = $( Self::$const.0 )|+ $(|$mask)?; 111 112 #[allow(dead_code)] 113 #[inline(always)] 114 pub const fn empty() -> Self { 115 Self(0) 116 } 117 118 #[allow(dead_code)] 119 #[inline(always)] 120 pub const fn all() -> Self { 121 Self($( Self::$const.0 )|+) 122 } 123 124 #[allow(dead_code)] 125 #[inline(always)] 126 pub const fn valid_bits() -> Self { 127 Self(Self::VALID__) 128 } 129 130 #[allow(dead_code)] 131 #[inline(always)] 132 pub const fn valid(val: $type) -> bool { 133 (val & !Self::VALID__) == 0 134 } 135 136 #[allow(dead_code)] 137 #[inline(always)] 138 pub const fn any_set(self, mask: Self) -> bool { 139 (self.0 & mask.0) != 0 140 } 141 142 #[allow(dead_code)] 143 #[inline(always)] 144 pub const fn all_set(self, mask: Self) -> bool { 145 (self.0 & mask.0) == mask.0 146 } 147 148 #[allow(dead_code)] 149 #[inline(always)] 150 pub const fn none_set(self, mask: Self) -> bool { 151 (self.0 & mask.0) == 0 152 } 153 154 #[allow(dead_code)] 155 #[inline(always)] 156 pub const fn from_bits(value: $type) -> Self { 157 $struct_name(value) 158 } 159 160 #[allow(dead_code)] 161 #[inline(always)] 162 pub const fn into_bits(self) -> $type { 163 self.0 164 } 165 166 #[allow(dead_code)] 167 #[inline(always)] 168 pub fn set(&mut self, rhs: Self) { 169 self.0 |= rhs.0; 170 } 171 172 #[allow(dead_code)] 173 #[inline(always)] 174 pub fn clear(&mut self, rhs: Self) { 175 self.0 &= !rhs.0; 176 } 177 178 #[allow(dead_code)] 179 #[inline(always)] 180 pub fn toggle(&mut self, rhs: Self) { 181 self.0 ^= rhs.0; 182 } 183 184 #[allow(dead_code)] 185 #[inline(always)] 186 pub const fn intersection(self, rhs: Self) -> Self { 187 $struct_name(self.0 & rhs.0) 188 } 189 190 #[allow(dead_code)] 191 #[inline(always)] 192 pub const fn difference(self, rhs: Self) -> Self { 193 $struct_name(self.0 & !rhs.0) 194 } 195 196 #[allow(dead_code)] 197 #[inline(always)] 198 pub const fn symmetric_difference(self, rhs: Self) -> Self { 199 $struct_name(self.0 ^ rhs.0) 200 } 201 202 #[allow(dead_code)] 203 #[inline(always)] 204 pub const fn union(self, rhs: Self) -> Self { 205 $struct_name(self.0 | rhs.0) 206 } 207 208 #[allow(dead_code)] 209 #[inline(always)] 210 pub const fn invert(self) -> Self { 211 $struct_name(self.0 ^ Self::VALID__) 212 } 213 } 214 215 impl ::std::fmt::Binary for $struct_name { 216 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 217 // If no width, use the highest valid bit 218 let width = f.width().unwrap_or((Self::VALID__.ilog2() + 1) as usize); 219 write!(f, "{:0>width$.precision$b}", self.0, 220 width = width, 221 precision = f.precision().unwrap_or(width)) 222 } 223 } 224 225 impl ::std::fmt::LowerHex for $struct_name { 226 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 227 <$type as ::std::fmt::LowerHex>::fmt(&self.0, f) 228 } 229 } 230 231 impl ::std::fmt::Octal for $struct_name { 232 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 233 <$type as ::std::fmt::Octal>::fmt(&self.0, f) 234 } 235 } 236 237 impl ::std::fmt::UpperHex for $struct_name { 238 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 239 <$type as ::std::fmt::UpperHex>::fmt(&self.0, f) 240 } 241 } 242 243 impl ::std::fmt::Debug for $struct_name { 244 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 245 write!(f, "{}({})", stringify!($struct_name), self) 246 } 247 } 248 249 impl ::std::fmt::Display for $struct_name { 250 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 251 use ::std::fmt::Display; 252 let mut first = true; 253 let mut left = self.0; 254 $(if Self::$const.0.is_power_of_two() && (self & Self::$const).0 != 0 { 255 if first { first = false } else { Display::fmt(&'|', f)?; } 256 Display::fmt(stringify!($const), f)?; 257 left -= Self::$const.0; 258 })+ 259 if first { 260 Display::fmt(&'0', f) 261 } else if left != 0 { 262 write!(f, "|{left:#x}") 263 } else { 264 Ok(()) 265 } 266 } 267 } 268 269 impl ::std::cmp::PartialEq<$type> for $struct_name { 270 fn eq(&self, rhs: &$type) -> bool { 271 self.0 == *rhs 272 } 273 } 274 275 impl ::std::ops::BitAnd<$struct_name> for &$struct_name { 276 type Output = $struct_name; 277 fn bitand(self, rhs: $struct_name) -> Self::Output { 278 $struct_name(self.0 & rhs.0) 279 } 280 } 281 282 impl ::std::ops::BitAndAssign<$struct_name> for $struct_name { 283 fn bitand_assign(&mut self, rhs: $struct_name) { 284 self.0 = self.0 & rhs.0 285 } 286 } 287 288 impl ::std::ops::BitXor<$struct_name> for &$struct_name { 289 type Output = $struct_name; 290 fn bitxor(self, rhs: $struct_name) -> Self::Output { 291 $struct_name(self.0 ^ rhs.0) 292 } 293 } 294 295 impl ::std::ops::BitXorAssign<$struct_name> for $struct_name { 296 fn bitxor_assign(&mut self, rhs: $struct_name) { 297 self.0 = self.0 ^ rhs.0 298 } 299 } 300 301 impl ::std::ops::BitOr<$struct_name> for &$struct_name { 302 type Output = $struct_name; 303 fn bitor(self, rhs: $struct_name) -> Self::Output { 304 $struct_name(self.0 | rhs.0) 305 } 306 } 307 308 impl ::std::ops::BitOrAssign<$struct_name> for $struct_name { 309 fn bitor_assign(&mut self, rhs: $struct_name) { 310 self.0 = self.0 | rhs.0 311 } 312 } 313 314 impl ::std::ops::Sub<$struct_name> for &$struct_name { 315 type Output = $struct_name; 316 fn sub(self, rhs: $struct_name) -> Self::Output { 317 $struct_name(self.0 & !rhs.0) 318 } 319 } 320 321 impl ::std::ops::SubAssign<$struct_name> for $struct_name { 322 fn sub_assign(&mut self, rhs: $struct_name) { 323 self.0 = self.0 - rhs.0 324 } 325 } 326 327 impl ::std::ops::Not for &$struct_name { 328 type Output = $struct_name; 329 fn not(self) -> Self::Output { 330 $struct_name(self.0 ^ $struct_name::VALID__) 331 } 332 } 333 334 impl ::std::ops::BitAnd<$struct_name> for $struct_name { 335 type Output = Self; 336 fn bitand(self, rhs: Self) -> Self::Output { 337 $struct_name(self.0 & rhs.0) 338 } 339 } 340 341 impl ::std::ops::BitXor<$struct_name> for $struct_name { 342 type Output = Self; 343 fn bitxor(self, rhs: Self) -> Self::Output { 344 $struct_name(self.0 ^ rhs.0) 345 } 346 } 347 348 impl ::std::ops::BitOr<$struct_name> for $struct_name { 349 type Output = Self; 350 fn bitor(self, rhs: Self) -> Self::Output { 351 $struct_name(self.0 | rhs.0) 352 } 353 } 354 355 impl ::std::ops::Sub<$struct_name> for $struct_name { 356 type Output = Self; 357 fn sub(self, rhs: Self) -> Self::Output { 358 $struct_name(self.0 & !rhs.0) 359 } 360 } 361 362 impl ::std::ops::Not for $struct_name { 363 type Output = Self; 364 fn not(self) -> Self::Output { 365 $struct_name(self.0 ^ Self::VALID__) 366 } 367 } 368 369 impl From<$struct_name> for $type { 370 fn from(x: $struct_name) -> $type { 371 x.0 372 } 373 } 374 375 impl From<$type> for $struct_name { 376 fn from(x: $type) -> Self { 377 $struct_name(x & Self::VALID__) 378 } 379 } 380 }; 381 382 { $type:ty: $expr:expr } => { 383 ::qemu_api_macros::bits_const_internal! { $type @ ($expr) } 384 }; 385 386 { $type:ty as $int_type:ty: $expr:expr } => { 387 (::qemu_api_macros::bits_const_internal! { $type @ ($expr) }.into_bits()) as $int_type 388 }; 389 } 390 391 #[cfg(test)] 392 mod test { 393 bits! { 394 pub struct InterruptMask(u32) { 395 OE = 1 << 10, 396 BE = 1 << 9, 397 PE = 1 << 8, 398 FE = 1 << 7, 399 RT = 1 << 6, 400 TX = 1 << 5, 401 RX = 1 << 4, 402 DSR = 1 << 3, 403 DCD = 1 << 2, 404 CTS = 1 << 1, 405 RI = 1 << 0, 406 407 E = bits!(Self as u32: OE | BE | PE | FE), 408 MS = bits!(Self as u32: RI | DSR | DCD | CTS), 409 } 410 } 411 412 #[test] test_not()413 pub fn test_not() { 414 assert_eq!( 415 !InterruptMask::from(InterruptMask::RT.0), 416 InterruptMask::E | InterruptMask::MS | InterruptMask::TX | InterruptMask::RX 417 ); 418 } 419 420 #[test] test_and()421 pub fn test_and() { 422 assert_eq!( 423 InterruptMask::from(0), 424 InterruptMask::MS & InterruptMask::OE 425 ) 426 } 427 428 #[test] test_or()429 pub fn test_or() { 430 assert_eq!( 431 InterruptMask::E, 432 InterruptMask::OE | InterruptMask::BE | InterruptMask::PE | InterruptMask::FE 433 ); 434 } 435 436 #[test] test_xor()437 pub fn test_xor() { 438 assert_eq!( 439 InterruptMask::E ^ InterruptMask::BE, 440 InterruptMask::OE | InterruptMask::PE | InterruptMask::FE 441 ); 442 } 443 } 444