Support hypothetical big-endian users
This commit is contained in:
+78
-7
@@ -39,11 +39,12 @@ impl MemoryClient {
|
||||
MemoryView { region }
|
||||
}
|
||||
|
||||
pub fn write<T: bytemuck::NoUninit>(&self, sim: SimId, address: u32, data: &T) {
|
||||
let data = bytemuck::bytes_of(data).to_vec();
|
||||
pub fn write<T: MemoryValue>(&self, sim: SimId, address: u32, data: &T) {
|
||||
let mut buffer = vec![];
|
||||
data.to_bytes(&mut buffer);
|
||||
let (tx, _) = oneshot::channel();
|
||||
self.client
|
||||
.send_command(EmulatorCommand::WriteMemory(sim, address, data, tx));
|
||||
.send_command(EmulatorCommand::WriteMemory(sim, address, buffer, tx));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,17 +75,87 @@ pub struct MemoryRef<'a> {
|
||||
inner: RwLockReadGuard<'a, BoxBytes>,
|
||||
}
|
||||
|
||||
pub trait MemoryValue {
|
||||
fn from_bytes(bytes: &[u8]) -> Self;
|
||||
fn to_bytes(&self, buffer: &mut Vec<u8>);
|
||||
}
|
||||
|
||||
macro_rules! primitive_memory_value_impl {
|
||||
($T:ty, $L: expr) => {
|
||||
impl MemoryValue for $T {
|
||||
#[inline]
|
||||
fn from_bytes(bytes: &[u8]) -> Self {
|
||||
let bytes: [u8; std::mem::size_of::<$T>()] = std::array::from_fn(|i| bytes[i]);
|
||||
<$T>::from_le_bytes(bytes)
|
||||
}
|
||||
#[inline]
|
||||
fn to_bytes(&self, buffer: &mut Vec<u8>) {
|
||||
buffer.extend_from_slice(&self.to_le_bytes())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
primitive_memory_value_impl!(u8, 1);
|
||||
primitive_memory_value_impl!(u16, 2);
|
||||
primitive_memory_value_impl!(u32, 4);
|
||||
|
||||
impl<const N: usize, T: MemoryValue> MemoryValue for [T; N] {
|
||||
#[inline]
|
||||
fn from_bytes(bytes: &[u8]) -> Self {
|
||||
std::array::from_fn(|i| {
|
||||
T::from_bytes(&bytes[i * std::mem::size_of::<T>()..(i + 1) * std::mem::size_of::<T>()])
|
||||
})
|
||||
}
|
||||
#[inline]
|
||||
fn to_bytes(&self, buffer: &mut Vec<u8>) {
|
||||
for item in self {
|
||||
item.to_bytes(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemoryIter<'a, T> {
|
||||
bytes: &'a [u8],
|
||||
index: usize,
|
||||
_phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T> MemoryIter<'a, T> {
|
||||
fn new(bytes: &'a [u8]) -> Self {
|
||||
Self {
|
||||
bytes,
|
||||
index: 0,
|
||||
_phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MemoryValue> Iterator for MemoryIter<'_, T> {
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index >= self.bytes.len() {
|
||||
return None;
|
||||
}
|
||||
let bytes = &self.bytes[self.index..self.index + std::mem::size_of::<T>()];
|
||||
self.index += std::mem::size_of::<T>();
|
||||
Some(T::from_bytes(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl MemoryRef<'_> {
|
||||
pub fn read<T: bytemuck::AnyBitPattern>(&self, index: usize) -> T {
|
||||
pub fn read<T: MemoryValue>(&self, index: usize) -> T {
|
||||
let from = index * size_of::<T>();
|
||||
let to = from + size_of::<T>();
|
||||
*bytemuck::from_bytes(&self.inner[from..to])
|
||||
T::from_bytes(&self.inner[from..to])
|
||||
}
|
||||
|
||||
pub fn range<T: bytemuck::AnyBitPattern>(&self, start: usize, count: usize) -> &[T] {
|
||||
pub fn range<T: MemoryValue>(&self, start: usize, count: usize) -> MemoryIter<T> {
|
||||
let from = start * size_of::<T>();
|
||||
let to = from + (count * size_of::<T>());
|
||||
bytemuck::cast_slice(&self.inner[from..to])
|
||||
MemoryIter::new(&self.inner[from..to])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user