Skip to content

Instantly share code, notes, and snippets.

@bharrisau
Forked from bgamari/register.rs
Last active August 29, 2015 14:03
Show Gist options
  • Save bharrisau/ad44404a781c4bced351 to your computer and use it in GitHub Desktop.
Save bharrisau/ad44404a781c4bced351 to your computer and use it in GitHub Desktop.
#![feature(unsafe_destructor)]
use std::ty::Unsafe;
use std::kinds::marker::InvariantType;
/// This represents a register
struct RegValue<Packed, Unpacked> {
value: Unsafe<Packed>,
}
/// This represents the value of a particular register named AReg1 and
/// can be used to manipulate the fields of this register atomically
struct AReg1<'a> {
value: u32,
mask: u32,
// this may need to turn into a raw pointer due to unsafe destructors
reg: *mut u32,
}
impl<'a> AReg1<'a> {
/// bit 0
pub fn set_field1<'b>(&'b mut self, value: bool) -> &'b mut AReg1<'a> {
self.value = (!(1<<0) & self.value) | ((value as u32 & 1) << 0);
self.mask = self.mask | 1;
self
}
/// bits 1..4
pub fn set_field2<'b>(&'b mut self, value: u32) -> &'b mut AReg1<'a> {
self.value = (!(7<<1) & self.value) | ((value as u32 & 0x7) << 1);
self.mask = self.mask | (7<<1);
self
}
}
/*
impl<'b> Deref<AReg1<'b>> for RegValue<u32, AReg1<'b>> {
fn deref<'a>(&'a self) -> &'a AReg1<'a> {
&AReg1 {value: *self.value.get(), mask: 0, reg: self}
}
}
*/
impl<'a> RegValue<u32, AReg1<'a>> {
pub fn get_field1(&mut self) -> bool {
unsafe {
(*self.value.get() >> 0) & 1 != 0
}
}
pub fn set_field1(&mut self, val: bool) -> AReg1<'a> {
let val = if val { 1 } else { 0 };
unsafe {
AReg1 {value: val, mask: 1<<0, reg: self.value.get()}
}
}
pub fn get_field2(&mut self) -> u32 {
unsafe {
(*self.value.get() >> 1) & 7
}
}
pub fn set_field2(&mut self, val: u32) -> AReg1<'a> {
let val = (val & 7) << 1;
unsafe {
AReg1 {value: val, mask: 7<<1, reg: self.value.get()}
}
}
}
#[unsafe_destructor]
impl<'a> Drop for AReg1<'a> {
fn drop(&mut self) {
unsafe {
*self.reg = self.value | (*self.reg & !self.mask);
}
}
}
static mut areg1: RegValue<u32, AReg1<'static>> =
RegValue { value: Unsafe {value: 0,
marker1: InvariantType }};
fn main() {
unsafe {
areg1
.set_field1(true)
.set_field2(5);
println!("field1 = {}", areg1.get_field1());
println!("field2 = {}", areg1.get_field2());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment