use rumio::cpu::{RegisterRead, RegisterWrite};
use std::sync::atomic::{AtomicU64, Ordering};
const DEFAULT_REG_VALUE: u64 = 0b101;
thread_local! {
static REGISTER: AtomicU64 = AtomicU64::new(DEFAULT_REG_VALUE);
}
fn reset_register() {
REGISTER.with(|reg| reg.store(DEFAULT_REG_VALUE, Ordering::SeqCst))
}
fn assert_reg_eq(val: u64) {
REGISTER.with(|reg| assert_eq!(val, reg.load(Ordering::SeqCst)))
}
struct CpuRegister;
impl RegisterRead<u64> for CpuRegister {
fn read() -> u64 {
REGISTER.with(|reg| reg.load(Ordering::SeqCst))
}
}
impl RegisterWrite<u64> for CpuRegister {
fn write(val: u64) {
REGISTER.with(|reg| reg.store(val, Ordering::SeqCst))
}
fn set(mask: u64) {
rumio::impl_cpu_set!(Self, mask);
}
fn clear(mask: u64) {
rumio::impl_cpu_clear!(Self, mask);
}
}
rumio::define_cpu_register! { CpuRegister as u64 =>
rw MODE: 0..1 = enum Mode [
A = 0b00,
B = 0b01,
C = 0b10,
D = 0b11,
],
r FOO: 2,
rw BAR: 3,
rw BAZ: 4,
rw FLAGS: 5..8 = flags Flags [
A = 0b0001,
B = 0b0010,
C = 0b0100,
D = 0b1000,
],
w WRITE: 9,
}
#[test]
fn read_write_single_bit() {
reset_register();
assert_reg_eq(DEFAULT_REG_VALUE);
assert!(FOO::get());
assert!(!BAR::get());
assert!(!BAZ::get());
BAR::set(true);
assert_reg_eq(0b1101);
assert!(BAR::get());
assert!(!BAZ::get());
BAZ::set(true);
assert_reg_eq(0b11101);
assert!(BAZ::get());
}
#[test]
fn read_write_enum() {
reset_register();
assert_reg_eq(DEFAULT_REG_VALUE);
assert_eq!(MODE::get(), Some(Mode::B));
MODE::set(Mode::C);
assert_reg_eq(0b110);
assert_eq!(MODE::get(), Some(Mode::C));
}
#[test]
fn read_write_flags() {
reset_register();
assert_reg_eq(DEFAULT_REG_VALUE);
assert_eq!(FLAGS::get(), Flags::empty());
FLAGS::set(Flags::A | Flags::C);
assert_reg_eq(0b10100101);
assert_eq!(FLAGS::get(), Flags::A | Flags::C);
FLAGS::set(Flags::B | Flags::C);
assert_reg_eq(0b11000101);
assert_eq!(FLAGS::get(), Flags::B | Flags::C);
}
#[test]
fn modify_values() {
reset_register();
assert_reg_eq(DEFAULT_REG_VALUE);
let val = Mode::B | BAZ::SET | Flags::A | Flags::B;
modify(val);
assert_eq!(FLAGS::get(), Flags::A | Flags::B);
assert_eq!(MODE::get(), Some(Mode::B));
assert!(BAZ::get());
}
#[test]
fn read_fields() {
reset_register();
assert_reg_eq(DEFAULT_REG_VALUE);
let x = read(FOO::FIELD | Mode::field() | BAZ::FIELD);
assert_eq!(x, 0b101);
assert_reg_eq(DEFAULT_REG_VALUE);
BAZ::set(true);
let x = read(FOO::FIELD | Mode::field() | BAZ::FIELD);
assert_eq!(x, 0b10101);
}