GolemComputers/rust/src/components/core.rs

73 lines
1.8 KiB
Rust

use std::{mem::offset_of, sync::{mpsc, Arc}};
use bitfield_struct::bitfield;
use zerocopy::{
little_endian::{U32, U64},
FromBytes, IntoBytes, KnownLayout,
};
use crate::{component_name, core::CoreMessage, overlapping, unsync_cell::UnsyncCell};
use super::Component;
#[derive(Clone, Copy, FromBytes, IntoBytes, KnownLayout)]
#[repr(C)]
pub struct Registers {
pub reset_address: U64,
pub flags: U32,
}
#[bitfield(u32)]
pub struct Flags {
should_reset: bool,
#[bits(31)]
_reserved: u32,
}
pub struct CoreComponent {
registers: Arc<UnsyncCell<Registers>>,
message_sender: mpsc::Sender<CoreMessage>,
}
impl CoreComponent {
pub fn new(registers: Arc<UnsyncCell<Registers>>, message_sender: mpsc::Sender<CoreMessage>) -> Self {
Self {
registers,
message_sender,
}
}
}
impl Component for CoreComponent {
fn name() -> [u8; 0x30] {
component_name!(b"core")
}
fn memory_map_size(&self) -> u64 {
size_of::<Registers>() as u64
}
fn read(&self, _: &mut jni::JNIEnv, offset: u64, data: &mut [u8]) {
assert!((offset + data.len() as u64) < self.memory_map_size() as u64);
self.registers.read_into_byte_slice(offset as usize, data);
}
fn write(&self, _: &mut jni::JNIEnv, offset: u64, data: &[u8]) {
assert!((offset + data.len() as u64) < self.memory_map_size() as u64);
self.registers.write_from_byte_slice(offset as usize, data);
if overlapping(
&(offset..offset + data.len() as u64),
&(offset_of!(Registers, flags) as u64..size_of::<Registers>() as u64),
) {
let mut registers = self.registers.read();
let flags = Flags::from_bits(registers.flags.get());
if flags.should_reset() {
let _ = self.message_sender.send(CoreMessage::Reset);
registers.flags.set(flags.with_should_reset(false).into_bits());
self.registers.write(registers);
}
}
}
}