73 lines
1.8 KiB
Rust
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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|